mirror of
https://github.com/hyprwm/Hypr.git
synced 2024-11-22 13:35:57 +01:00
Added a tray module
This commit is contained in:
parent
b897a1b64e
commit
2ca2ddfd2e
9 changed files with 442 additions and 49 deletions
|
@ -30,6 +30,8 @@ Bar {
|
||||||
col.high=0xffff3333
|
col.high=0xffff3333
|
||||||
|
|
||||||
module=left,X,0xff8000ff,0xffffffff,1,workspaces
|
module=left,X,0xff8000ff,0xffffffff,1,workspaces
|
||||||
|
module=pad,left,10
|
||||||
|
module=left,,0xff7000dd,0xff7000dd,1,tray
|
||||||
module=right,X,0xffffffff,0xff00ff33,1000,$date +%a,\ %b\ %Y\ \ %I:%M\ %p$
|
module=right,X,0xffffffff,0xff00ff33,1000,$date +%a,\ %b\ %Y\ \ %I:%M\ %p$
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
251
src/bar/Bar.cpp
251
src/bar/Bar.cpp
|
@ -11,6 +11,12 @@ bool isParentDead() {
|
||||||
return PPID == 1;
|
return PPID == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parseEvent() {
|
||||||
|
while(1) {
|
||||||
|
g_pWindowManager->recieveEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int64_t barMainThread() {
|
int64_t barMainThread() {
|
||||||
// Main already created all the pipes
|
// Main already created all the pipes
|
||||||
|
|
||||||
|
@ -18,14 +24,14 @@ int64_t barMainThread() {
|
||||||
|
|
||||||
// Well now this is the init
|
// Well now this is the init
|
||||||
// it's pretty tricky because we only need to init the stuff we need
|
// it's pretty tricky because we only need to init the stuff we need
|
||||||
g_pWindowManager->DisplayConnection = xcb_connect(NULL, NULL);
|
g_pWindowManager->DisplayConnection = xcb_connect(NULL, &barScreen);
|
||||||
if (const auto RET = xcb_connection_has_error(g_pWindowManager->DisplayConnection); RET != 0) {
|
if (const auto RET = xcb_connection_has_error(g_pWindowManager->DisplayConnection); RET != 0) {
|
||||||
Debug::log(CRIT, "Connection Failed! Return: " + std::to_string(RET));
|
Debug::log(CRIT, "Connection Failed! Return: " + std::to_string(RET));
|
||||||
return RET;
|
return RET;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Screen
|
// Screen
|
||||||
g_pWindowManager->Screen = xcb_setup_roots_iterator(xcb_get_setup(g_pWindowManager->DisplayConnection)).data;
|
g_pWindowManager->Screen = xcb_aux_get_screen(g_pWindowManager->DisplayConnection, barScreen);
|
||||||
|
|
||||||
if (!g_pWindowManager->Screen) {
|
if (!g_pWindowManager->Screen) {
|
||||||
Debug::log(CRIT, "Screen was null!");
|
Debug::log(CRIT, "Screen was null!");
|
||||||
|
@ -69,6 +75,11 @@ int64_t barMainThread() {
|
||||||
|
|
||||||
Debug::log(LOG, "Bar init Phase 2 done.");
|
Debug::log(LOG, "Bar init Phase 2 done.");
|
||||||
|
|
||||||
|
// Start the parse event thread
|
||||||
|
std::thread([=]() {
|
||||||
|
parseEvent();
|
||||||
|
}).detach();
|
||||||
|
|
||||||
// Init config manager
|
// Init config manager
|
||||||
ConfigManager::init();
|
ConfigManager::init();
|
||||||
|
|
||||||
|
@ -78,6 +89,9 @@ int64_t barMainThread() {
|
||||||
|
|
||||||
int lazyUpdateCounter = 0;
|
int lazyUpdateCounter = 0;
|
||||||
|
|
||||||
|
// setup the tray so apps send to us
|
||||||
|
STATUSBAR.setupTray();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
// Don't spam these
|
// Don't spam these
|
||||||
|
@ -130,6 +144,142 @@ void CStatusBar::destroyModule(SBarModule* module) {
|
||||||
xcb_free_gc(g_pWindowManager->DisplayConnection, module->bgcontext);
|
xcb_free_gc(g_pWindowManager->DisplayConnection, module->bgcontext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CStatusBar::setupTray() {
|
||||||
|
Debug::log(LOG, "Setting up tray!");
|
||||||
|
|
||||||
|
char atomName[strlen("_NET_SYSTEM_TRAY_S") + 11];
|
||||||
|
|
||||||
|
snprintf(atomName, strlen("_NET_SYSTEM_TRAY_S") + 11, "_NET_SYSTEM_TRAY_S%d", barScreen);
|
||||||
|
|
||||||
|
// init the atom
|
||||||
|
const auto TRAYCOOKIE = xcb_intern_atom(g_pWindowManager->DisplayConnection, 0, strlen(atomName), atomName);
|
||||||
|
|
||||||
|
trayWindowID = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
||||||
|
|
||||||
|
uint32_t values[] = {g_pWindowManager->Screen->black_pixel, g_pWindowManager->Screen->black_pixel, 1, g_pWindowManager->Colormap};
|
||||||
|
|
||||||
|
xcb_create_window(g_pWindowManager->DisplayConnection, g_pWindowManager->Depth, trayWindowID,
|
||||||
|
g_pWindowManager->Screen->root, -1, -1, 1, 1, 0,
|
||||||
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, g_pWindowManager->VisualType->visual_id,
|
||||||
|
XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_COLORMAP,
|
||||||
|
values);
|
||||||
|
|
||||||
|
const uint32_t ORIENTATION = 0; // Horizontal
|
||||||
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, trayWindowID,
|
||||||
|
HYPRATOMS["_NET_SYSTEM_TRAY_ORIENTATION"], XCB_ATOM_CARDINAL,
|
||||||
|
32, 1, &ORIENTATION);
|
||||||
|
|
||||||
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, trayWindowID,
|
||||||
|
HYPRATOMS["_NET_SYSTEM_TRAY_VISUAL"], XCB_ATOM_VISUALID,
|
||||||
|
32, 1, &g_pWindowManager->VisualType->visual_id);
|
||||||
|
|
||||||
|
// COLORS
|
||||||
|
|
||||||
|
// Check if the tray module is active
|
||||||
|
SBarModule* pBarModule = nullptr;
|
||||||
|
for (auto& mod : modules) {
|
||||||
|
if (mod.value == "tray") {
|
||||||
|
pBarModule = &mod;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pBarModule) {
|
||||||
|
// init colors
|
||||||
|
const auto R = (uint16_t)(RED(pBarModule->bgcolor) * 255.f);
|
||||||
|
const auto G = (uint16_t)(GREEN(pBarModule->bgcolor) * 255.f);
|
||||||
|
const auto B = (uint16_t)(BLUE(pBarModule->bgcolor) * 255.f);
|
||||||
|
|
||||||
|
const unsigned short TRAYCOLORS[] = {
|
||||||
|
R, G, B, R, G, B, R, G, B, R, G, B // Foreground, Error, Warning, Success
|
||||||
|
};
|
||||||
|
|
||||||
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, trayWindowID,
|
||||||
|
HYPRATOMS["_NET_SYSTEM_TRAY_COLORS"], XCB_ATOM_CARDINAL, 32, 12, TRAYCOLORS);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
const auto TRAYREPLY = xcb_intern_atom_reply(g_pWindowManager->DisplayConnection, TRAYCOOKIE, NULL);
|
||||||
|
|
||||||
|
if (!TRAYREPLY) {
|
||||||
|
Debug::log(ERR, "Tray reply NULL! Aborting tray...");
|
||||||
|
free(TRAYREPLY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the owner and check
|
||||||
|
xcb_set_selection_owner(g_pWindowManager->DisplayConnection, trayWindowID, TRAYREPLY->atom, XCB_CURRENT_TIME);
|
||||||
|
|
||||||
|
const auto SELCOOKIE = xcb_get_selection_owner(g_pWindowManager->DisplayConnection, TRAYREPLY->atom);
|
||||||
|
const auto SELREPLY = xcb_get_selection_owner_reply(g_pWindowManager->DisplayConnection, SELCOOKIE, NULL);
|
||||||
|
|
||||||
|
if (!SELREPLY) {
|
||||||
|
Debug::log(ERR, "Selection owner reply NULL! Aborting tray...");
|
||||||
|
free(SELREPLY);
|
||||||
|
free(TRAYREPLY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SELREPLY->owner != trayWindowID) {
|
||||||
|
Debug::log(ERR, "Couldn't set the Tray owner, maybe a different tray is running??");
|
||||||
|
free(SELREPLY);
|
||||||
|
free(TRAYREPLY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(SELREPLY);
|
||||||
|
free(TRAYREPLY);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Tray setup done, sending message!");
|
||||||
|
|
||||||
|
uint8_t buf[32] = {NULL};
|
||||||
|
xcb_client_message_event_t* event = (xcb_client_message_event_t*)buf;
|
||||||
|
|
||||||
|
event->response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
event->window = g_pWindowManager->Screen->root;
|
||||||
|
event->type = HYPRATOMS["MANAGER"];
|
||||||
|
event->format = 32;
|
||||||
|
event->data.data32[0] = 0L;
|
||||||
|
event->data.data32[1] = TRAYREPLY->atom;
|
||||||
|
event->data.data32[2] = trayWindowID;
|
||||||
|
|
||||||
|
xcb_send_event(g_pWindowManager->DisplayConnection, 0, g_pWindowManager->Screen->root, 0xFFFFFF, (char*)buf);
|
||||||
|
|
||||||
|
Debug::log(LOG, "Tray message sent!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStatusBar::fixTrayOnCreate() {
|
||||||
|
if (m_bHasTray) {
|
||||||
|
for (auto& tray : g_pWindowManager->trayclients) {
|
||||||
|
xcb_reparent_window(g_pWindowManager->DisplayConnection, tray.window, g_pWindowManager->statusBar->getWindowID(), 0, 0);
|
||||||
|
xcb_map_window(g_pWindowManager->DisplayConnection, tray.window);
|
||||||
|
tray.hidden = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint32_t values[2];
|
||||||
|
|
||||||
|
values[0] = 0;
|
||||||
|
values[1] = 0;
|
||||||
|
|
||||||
|
for (auto& tray : g_pWindowManager->trayclients) {
|
||||||
|
tray.hidden = true;
|
||||||
|
values[0] = 0;
|
||||||
|
values[1] = 0;
|
||||||
|
xcb_configure_window(g_pWindowManager->DisplayConnection, tray.window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
|
||||||
|
values[0] = 30000;
|
||||||
|
values[1] = 30000;
|
||||||
|
xcb_configure_window(g_pWindowManager->DisplayConnection, tray.window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStatusBar::saveTrayOnDestroy() {
|
||||||
|
for (auto& tray : g_pWindowManager->trayclients) {
|
||||||
|
xcb_reparent_window(g_pWindowManager->DisplayConnection, tray.window, g_pWindowManager->Screen->root, -999, -999);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CStatusBar::setup(int MonitorID) {
|
void CStatusBar::setup(int MonitorID) {
|
||||||
Debug::log(LOG, "Creating the bar!");
|
Debug::log(LOG, "Creating the bar!");
|
||||||
|
|
||||||
|
@ -137,7 +287,15 @@ void CStatusBar::setup(int MonitorID) {
|
||||||
MonitorID = 0;
|
MonitorID = 0;
|
||||||
Debug::log(ERR, "Incorrect value in MonitorID for the bar. Setting to 0.");
|
Debug::log(ERR, "Incorrect value in MonitorID for the bar. Setting to 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_bHasTray = false;
|
||||||
|
for (auto& mod : g_pWindowManager->statusBar->modules) {
|
||||||
|
if (mod.value == "tray") {
|
||||||
|
m_bHasTray = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const auto MONITOR = g_pWindowManager->monitors[MonitorID];
|
const auto MONITOR = g_pWindowManager->monitors[MonitorID];
|
||||||
|
|
||||||
m_iMonitorID = MonitorID;
|
m_iMonitorID = MonitorID;
|
||||||
|
@ -191,11 +349,16 @@ void CStatusBar::setup(int MonitorID) {
|
||||||
m_vecSize.x, m_vecSize.y);
|
m_vecSize.x, m_vecSize.y);
|
||||||
m_pCairo = cairo_create(m_pCairoSurface);
|
m_pCairo = cairo_create(m_pCairoSurface);
|
||||||
cairo_surface_destroy(m_pCairoSurface);
|
cairo_surface_destroy(m_pCairoSurface);
|
||||||
|
|
||||||
|
// fix tray
|
||||||
|
fixTrayOnCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStatusBar::destroy() {
|
void CStatusBar::destroy() {
|
||||||
Debug::log(LOG, "Destroying the bar!");
|
Debug::log(LOG, "Destroying the bar!");
|
||||||
|
|
||||||
|
saveTrayOnDestroy();
|
||||||
|
|
||||||
xcb_close_font(g_pWindowManager->DisplayConnection, m_mContexts["HITEXT"].Font);
|
xcb_close_font(g_pWindowManager->DisplayConnection, m_mContexts["HITEXT"].Font);
|
||||||
xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iWindowID);
|
xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iWindowID);
|
||||||
xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iPixmap);
|
xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iPixmap);
|
||||||
|
@ -285,7 +448,19 @@ void CStatusBar::draw() {
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// fix the fucking tray
|
||||||
|
if (!m_bHasTray) {
|
||||||
|
uint32_t values[2];
|
||||||
|
for (auto& tray : g_pWindowManager->trayclients) {
|
||||||
|
tray.hidden = true;
|
||||||
|
values[0] = 30000;
|
||||||
|
values[1] = 30000;
|
||||||
|
xcb_configure_window(g_pWindowManager->DisplayConnection, tray.window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cairo_surface_flush(m_pCairoSurface);
|
cairo_surface_flush(m_pCairoSurface);
|
||||||
|
|
||||||
xcb_copy_area(g_pWindowManager->DisplayConnection, m_iPixmap, m_iWindowID, m_mContexts["BG"].GContext,
|
xcb_copy_area(g_pWindowManager->DisplayConnection, m_iPixmap, m_iWindowID, m_mContexts["BG"].GContext,
|
||||||
|
@ -320,11 +495,59 @@ int CStatusBar::drawWorkspacesModule(SBarModule* mod, int off) {
|
||||||
return drawnWorkspaces * m_vecSize.y;
|
return drawnWorkspaces * m_vecSize.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CStatusBar::drawTrayModule(SBarModule* mod, int off) {
|
||||||
|
|
||||||
|
const auto PAD = 2;
|
||||||
|
|
||||||
|
const auto ELEMENTWIDTH = (m_vecSize.y - 2 < 1 ? 1 : m_vecSize.y - 2);
|
||||||
|
|
||||||
|
const auto MODULEWIDTH = g_pWindowManager->trayclients.size() * (ELEMENTWIDTH + PAD);
|
||||||
|
|
||||||
|
Vector2D position;
|
||||||
|
switch (mod->alignment) {
|
||||||
|
case LEFT:
|
||||||
|
position = Vector2D(off, 0);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
position = Vector2D(m_vecSize.x - off - MODULEWIDTH, 0);
|
||||||
|
break;
|
||||||
|
case CENTER:
|
||||||
|
position = Vector2D(m_vecSize.x / 2.f - (MODULEWIDTH) / 2.f, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw tray
|
||||||
|
|
||||||
|
if (MODULEWIDTH < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
drawCairoRectangle(position, Vector2D(MODULEWIDTH, m_vecSize.y), mod->bgcolor);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (auto& tray : g_pWindowManager->trayclients) {
|
||||||
|
|
||||||
|
if (tray.hidden)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t values[] = {(int)(position.x + (i * (ELEMENTWIDTH + PAD)) + PAD / 2.f), (int)position.y + 1, (int)XCB_STACK_MODE_ABOVE};
|
||||||
|
|
||||||
|
xcb_configure_window(g_pWindowManager->DisplayConnection, g_pWindowManager->trayclients[i].window,
|
||||||
|
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MODULEWIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
int CStatusBar::drawModule(SBarModule* mod, int off) {
|
int CStatusBar::drawModule(SBarModule* mod, int off) {
|
||||||
|
|
||||||
if (mod->isPad)
|
if (mod->isPad)
|
||||||
return mod->pad;
|
return mod->pad;
|
||||||
|
|
||||||
|
if (mod->value == "tray")
|
||||||
|
return drawTrayModule(mod, off);
|
||||||
|
|
||||||
const int PAD = ConfigManager::getInt("bar:mod_pad_in");
|
const int PAD = ConfigManager::getInt("bar:mod_pad_in");
|
||||||
|
|
||||||
// check if we need to update
|
// check if we need to update
|
||||||
|
@ -362,4 +585,24 @@ int CStatusBar::drawModule(SBarModule* mod, int off) {
|
||||||
drawText(position + Vector2D(PAD / 2 + ICONWIDTH, getTextHalfY()), mod->valueCalculated, mod->color, ConfigManager::getString("bar:font.main"));
|
drawText(position + Vector2D(PAD / 2 + ICONWIDTH, getTextHalfY()), mod->valueCalculated, mod->color, ConfigManager::getString("bar:font.main"));
|
||||||
|
|
||||||
return MODULEWIDTH + ICONWIDTH;
|
return MODULEWIDTH + ICONWIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStatusBar::ensureTrayClientDead(xcb_window_t window) {
|
||||||
|
auto temp = g_pWindowManager->trayclients;
|
||||||
|
|
||||||
|
g_pWindowManager->trayclients.clear();
|
||||||
|
|
||||||
|
for (auto& trayitem : temp) {
|
||||||
|
if (trayitem.window != window)
|
||||||
|
g_pWindowManager->trayclients.push_back(trayitem);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug::log(LOG, "Ensured client dead (Bar, Tray)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStatusBar::ensureTrayClientHidden(xcb_window_t window, bool hide) {
|
||||||
|
for (auto& trayitem : g_pWindowManager->trayclients) {
|
||||||
|
if (trayitem.window == window)
|
||||||
|
trayitem.hidden = hide;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,8 @@
|
||||||
#include "BarCommands.hpp"
|
#include "BarCommands.hpp"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
inline int barScreen = 0;
|
||||||
|
|
||||||
struct SDrawingContext {
|
struct SDrawingContext {
|
||||||
xcb_gcontext_t GContext;
|
xcb_gcontext_t GContext;
|
||||||
xcb_font_t Font;
|
xcb_font_t Font;
|
||||||
|
@ -45,12 +47,16 @@ public:
|
||||||
EXPOSED_MEMBER(LastWindowName, std::string, sz);
|
EXPOSED_MEMBER(LastWindowName, std::string, sz);
|
||||||
EXPOSED_MEMBER(LastWindowClass, std::string, sz);
|
EXPOSED_MEMBER(LastWindowClass, std::string, sz);
|
||||||
EXPOSED_MEMBER(IsCovered, bool, b);
|
EXPOSED_MEMBER(IsCovered, bool, b);
|
||||||
|
EXPOSED_MEMBER(HasTray, bool, b);
|
||||||
|
|
||||||
void draw();
|
void draw();
|
||||||
void setup(int MonitorID);
|
void setup(int MonitorID);
|
||||||
void destroy();
|
void destroy();
|
||||||
void setupModule(SBarModule*);
|
void setupModule(SBarModule*);
|
||||||
void destroyModule(SBarModule*);
|
void destroyModule(SBarModule*);
|
||||||
|
void ensureTrayClientDead(xcb_window_t);
|
||||||
|
void ensureTrayClientHidden(xcb_window_t, bool);
|
||||||
|
void setupTray();
|
||||||
|
|
||||||
std::vector<int> openWorkspaces;
|
std::vector<int> openWorkspaces;
|
||||||
EXPOSED_MEMBER(CurrentWorkspace, int, i);
|
EXPOSED_MEMBER(CurrentWorkspace, int, i);
|
||||||
|
@ -77,6 +83,12 @@ private:
|
||||||
int getTextHalfY();
|
int getTextHalfY();
|
||||||
|
|
||||||
std::unordered_map<std::string, SDrawingContext> m_mContexts;
|
std::unordered_map<std::string, SDrawingContext> m_mContexts;
|
||||||
|
|
||||||
|
|
||||||
|
void fixTrayOnCreate();
|
||||||
|
void saveTrayOnDestroy();
|
||||||
|
int drawTrayModule(SBarModule*, int);
|
||||||
|
xcb_window_t trayWindowID = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Main thread for the bar. Is only initted once in main.cpp so we can do this.
|
// Main thread for the bar. Is only initted once in main.cpp so we can do this.
|
||||||
|
|
|
@ -79,4 +79,7 @@
|
||||||
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
|
#define GREEN(c) ((double)(((c) >> 8) & 0xff) / 255.0)
|
||||||
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
|
#define BLUE(c) ((double)(((c)) & 0xff) / 255.0)
|
||||||
|
|
||||||
#define CONTAINS(s, f) s.find(f) != std::string::npos
|
#define CONTAINS(s, f) s.find(f) != std::string::npos
|
||||||
|
|
||||||
|
#define RETURNIFBAR if (g_pWindowManager->statusBar) return;
|
||||||
|
#define RETURNIFMAIN if (!g_pWindowManager->statusBar) return;
|
|
@ -49,18 +49,13 @@ void Events::setThread() {
|
||||||
Debug::log(ERR, "Gthread failed!");
|
Debug::log(ERR, "Gthread failed!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*g_pWindowManager->barThread = new std::thread([&]() {
|
|
||||||
for (;;) {
|
|
||||||
handle();
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / ConfigManager::getInt("max_fps")));
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::eventEnter(xcb_generic_event_t* event) {
|
void Events::eventEnter(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_enter_notify_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_enter_notify_event_t*>(event);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
|
|
||||||
const auto PENTERWINDOW = g_pWindowManager->getWindowFromDrawable(E->event);
|
const auto PENTERWINDOW = g_pWindowManager->getWindowFromDrawable(E->event);
|
||||||
|
|
||||||
|
@ -79,12 +74,20 @@ void Events::eventEnter(xcb_generic_event_t* event) {
|
||||||
void Events::eventLeave(xcb_generic_event_t* event) {
|
void Events::eventLeave(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_leave_notify_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_leave_notify_event_t*>(event);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void Events::eventDestroy(xcb_generic_event_t* event) {
|
void Events::eventDestroy(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_destroy_notify_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_destroy_notify_event_t*>(event);
|
||||||
|
|
||||||
|
// let bar check if it wasnt a tray item
|
||||||
|
if (g_pWindowManager->statusBar)
|
||||||
|
g_pWindowManager->statusBar->ensureTrayClientDead(E->window);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
g_pWindowManager->closeWindowAllChecks(E->window);
|
g_pWindowManager->closeWindowAllChecks(E->window);
|
||||||
|
|
||||||
// refocus on new window
|
// refocus on new window
|
||||||
|
@ -94,6 +97,12 @@ void Events::eventDestroy(xcb_generic_event_t* event) {
|
||||||
void Events::eventUnmapWindow(xcb_generic_event_t* event) {
|
void Events::eventUnmapWindow(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_unmap_notify_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_unmap_notify_event_t*>(event);
|
||||||
|
|
||||||
|
// let bar check if it wasnt a tray item
|
||||||
|
if (g_pWindowManager->statusBar)
|
||||||
|
g_pWindowManager->statusBar->ensureTrayClientHidden(E->window, true);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
g_pWindowManager->closeWindowAllChecks(E->window);
|
g_pWindowManager->closeWindowAllChecks(E->window);
|
||||||
|
|
||||||
// refocus on new window
|
// refocus on new window
|
||||||
|
@ -330,6 +339,12 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
|
||||||
void Events::eventMapWindow(xcb_generic_event_t* event) {
|
void Events::eventMapWindow(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_map_request_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_map_request_event_t*>(event);
|
||||||
|
|
||||||
|
// let bar check if it wasnt a tray item
|
||||||
|
if (g_pWindowManager->statusBar)
|
||||||
|
g_pWindowManager->statusBar->ensureTrayClientHidden(E->window, false);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
// Map the window
|
// Map the window
|
||||||
xcb_map_window(g_pWindowManager->DisplayConnection, E->window);
|
xcb_map_window(g_pWindowManager->DisplayConnection, E->window);
|
||||||
|
|
||||||
|
@ -362,6 +377,8 @@ void Events::eventMapWindow(xcb_generic_event_t* event) {
|
||||||
void Events::eventButtonPress(xcb_generic_event_t* event) {
|
void Events::eventButtonPress(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_button_press_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_button_press_event_t*>(event);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
// mouse down!
|
// mouse down!
|
||||||
g_pWindowManager->mouseKeyDown = E->detail;
|
g_pWindowManager->mouseKeyDown = E->detail;
|
||||||
xcb_grab_pointer(g_pWindowManager->DisplayConnection, 0, g_pWindowManager->Screen->root, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT,
|
xcb_grab_pointer(g_pWindowManager->DisplayConnection, 0, g_pWindowManager->Screen->root, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT,
|
||||||
|
@ -379,6 +396,8 @@ void Events::eventButtonPress(xcb_generic_event_t* event) {
|
||||||
void Events::eventButtonRelease(xcb_generic_event_t* event) {
|
void Events::eventButtonRelease(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_button_release_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_button_release_event_t*>(event);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
// ungrab the mouse ptr
|
// ungrab the mouse ptr
|
||||||
xcb_ungrab_pointer(g_pWindowManager->DisplayConnection, XCB_CURRENT_TIME);
|
xcb_ungrab_pointer(g_pWindowManager->DisplayConnection, XCB_CURRENT_TIME);
|
||||||
const auto PACTINGWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->actingOnWindowFloating);
|
const auto PACTINGWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->actingOnWindowFloating);
|
||||||
|
@ -391,6 +410,8 @@ void Events::eventButtonRelease(xcb_generic_event_t* event) {
|
||||||
void Events::eventKeyPress(xcb_generic_event_t* event) {
|
void Events::eventKeyPress(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_key_press_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_key_press_event_t*>(event);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
const auto KEYSYM = KeybindManager::getKeysymFromKeycode(E->detail);
|
const auto KEYSYM = KeybindManager::getKeysymFromKeycode(E->detail);
|
||||||
|
|
||||||
for (auto& keybind : KeybindManager::keybinds) {
|
for (auto& keybind : KeybindManager::keybinds) {
|
||||||
|
@ -405,6 +426,8 @@ void Events::eventKeyPress(xcb_generic_event_t* event) {
|
||||||
void Events::eventMotionNotify(xcb_generic_event_t* event) {
|
void Events::eventMotionNotify(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_motion_notify_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_motion_notify_event_t*>(event);
|
||||||
|
|
||||||
|
RETURNIFBAR;
|
||||||
|
|
||||||
if (!g_pWindowManager->mouseKeyDown)
|
if (!g_pWindowManager->mouseKeyDown)
|
||||||
return; // mouse up.
|
return; // mouse up.
|
||||||
|
|
||||||
|
@ -463,4 +486,89 @@ void Events::eventExpose(xcb_generic_event_t* event) {
|
||||||
const auto E = reinterpret_cast<xcb_expose_event_t*>(event);
|
const auto E = reinterpret_cast<xcb_expose_event_t*>(event);
|
||||||
|
|
||||||
// nothing
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void Events::eventClientMessage(xcb_generic_event_t* event) {
|
||||||
|
const auto E = reinterpret_cast<xcb_client_message_event_t*>(event);
|
||||||
|
|
||||||
|
RETURNIFMAIN; // Only for the bar
|
||||||
|
|
||||||
|
// Tray clients
|
||||||
|
|
||||||
|
if (E->type == HYPRATOMS["_NET_SYSTEM_TRAY_OPCODE"] && E->format == 32) {
|
||||||
|
// Tray request!
|
||||||
|
|
||||||
|
Debug::log(LOG, "Docking a window to the tray!");
|
||||||
|
|
||||||
|
if (E->data.data32[1] == 0) { // Request dock
|
||||||
|
const xcb_window_t CLIENT = E->data.data32[2];
|
||||||
|
|
||||||
|
uint32_t values[3] = {0,0,0};
|
||||||
|
|
||||||
|
values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_RESIZE_REDIRECT;
|
||||||
|
|
||||||
|
xcb_change_window_attributes(g_pWindowManager->DisplayConnection, CLIENT,
|
||||||
|
XCB_CW_EVENT_MASK, values);
|
||||||
|
|
||||||
|
// get XEMBED
|
||||||
|
|
||||||
|
const auto XEMBEDCOOKIE = xcb_get_property(g_pWindowManager->DisplayConnection, 0, CLIENT, HYPRATOMS["_XEMBED_INFO"],
|
||||||
|
XCB_GET_PROPERTY_TYPE_ANY, 0, 64);
|
||||||
|
|
||||||
|
xcb_generic_error_t* err;
|
||||||
|
const auto XEMBEDREPLY = xcb_get_property_reply(g_pWindowManager->DisplayConnection, XEMBEDCOOKIE, &err);
|
||||||
|
|
||||||
|
if (!XEMBEDREPLY || err || XEMBEDREPLY->length == 0) {
|
||||||
|
Debug::log(ERR, "Tray dock opcode recieved with no XEmbed?");
|
||||||
|
if (err)
|
||||||
|
Debug::log(ERR, "Error code: " + std::to_string(err->error_code));
|
||||||
|
free(XEMBEDREPLY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t* XEMBEDPROP = (uint32_t*)xcb_get_property_value(XEMBEDREPLY);
|
||||||
|
Debug::log(LOG, "XEmbed recieved with format " + std::to_string(XEMBEDREPLY->format) + ", length " + std::to_string(XEMBEDREPLY->length)
|
||||||
|
+ ", version " + std::to_string(XEMBEDPROP[0]) + ", flags " + std::to_string(XEMBEDPROP[1]));
|
||||||
|
|
||||||
|
const auto XEMBEDVERSION = XEMBEDPROP[0] > 1 ? 1 : XEMBEDPROP[0];
|
||||||
|
|
||||||
|
free(XEMBEDREPLY);
|
||||||
|
|
||||||
|
xcb_reparent_window(g_pWindowManager->DisplayConnection, CLIENT, g_pWindowManager->statusBar->getWindowID(), 0, 0);
|
||||||
|
|
||||||
|
// icon sizes are barY - 2 - pad: 1
|
||||||
|
values[0] = ConfigManager::getInt("bar:height") - 2 < 1 ? 1 : ConfigManager::getInt("bar:height") - 2;
|
||||||
|
values[1] = values[0];
|
||||||
|
|
||||||
|
xcb_configure_window(g_pWindowManager->DisplayConnection, CLIENT, XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_WIDTH, values);
|
||||||
|
|
||||||
|
|
||||||
|
// Notify the thing we did it
|
||||||
|
uint8_t buf[32] = {NULL};
|
||||||
|
xcb_client_message_event_t* event = (xcb_client_message_event_t*)buf;
|
||||||
|
event->response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
event->window = CLIENT;
|
||||||
|
event->type = HYPRATOMS["_XEMBED"];
|
||||||
|
event->format = 32;
|
||||||
|
event->data.data32[0] = XCB_CURRENT_TIME;
|
||||||
|
event->data.data32[1] = 0;
|
||||||
|
event->data.data32[2] = g_pWindowManager->statusBar->getWindowID();
|
||||||
|
event->data.data32[3] = XEMBEDVERSION;
|
||||||
|
xcb_send_event(g_pWindowManager->DisplayConnection, 0, CLIENT, XCB_EVENT_MASK_NO_EVENT, (char*)event);
|
||||||
|
|
||||||
|
// put it into the save set
|
||||||
|
xcb_change_save_set(g_pWindowManager->DisplayConnection, XCB_SET_MODE_INSERT, CLIENT);
|
||||||
|
|
||||||
|
// make a tray client
|
||||||
|
CTrayClient newTrayClient;
|
||||||
|
newTrayClient.window = CLIENT;
|
||||||
|
newTrayClient.XEVer = XEMBEDVERSION;
|
||||||
|
|
||||||
|
g_pWindowManager->trayclients.push_back(newTrayClient);
|
||||||
|
|
||||||
|
xcb_map_window(g_pWindowManager->DisplayConnection, CLIENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,6 +15,7 @@ namespace Events {
|
||||||
EVENT(Expose);
|
EVENT(Expose);
|
||||||
EVENT(KeyPress);
|
EVENT(KeyPress);
|
||||||
EVENT(MotionNotify);
|
EVENT(MotionNotify);
|
||||||
|
EVENT(ClientMessage);
|
||||||
|
|
||||||
// Bypass some events for floating windows
|
// Bypass some events for floating windows
|
||||||
CWindow* remapWindow(int, bool floating = false, int forcemonitor = -1);
|
CWindow* remapWindow(int, bool floating = false, int forcemonitor = -1);
|
||||||
|
|
8
src/utilities/Tray.hpp
Normal file
8
src/utilities/Tray.hpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class CTrayClient {
|
||||||
|
public:
|
||||||
|
uint32_t window = 0;
|
||||||
|
int XEVer = -1;
|
||||||
|
bool hidden = false;
|
||||||
|
};
|
|
@ -198,19 +198,52 @@ bool CWindowManager::handleEvent() {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
xcb_flush(DisplayConnection);
|
xcb_flush(DisplayConnection);
|
||||||
|
|
||||||
|
// recieve the event. Blocks.
|
||||||
|
recieveEvent();
|
||||||
|
|
||||||
|
// refresh and apply the parameters of all dirty windows.
|
||||||
|
refreshDirtyWindows();
|
||||||
|
|
||||||
|
// Sanity checks
|
||||||
|
for (const auto active : activeWorkspaces) {
|
||||||
|
sanityCheckOnWorkspace(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove unused workspaces
|
||||||
|
cleanupUnusedWorkspaces();
|
||||||
|
|
||||||
|
// Update last window name
|
||||||
|
updateActiveWindowName();
|
||||||
|
|
||||||
|
// Update the bar with the freshest stuff
|
||||||
|
updateBarInfo();
|
||||||
|
|
||||||
|
xcb_flush(DisplayConnection);
|
||||||
|
|
||||||
|
// Restore thread state
|
||||||
|
mainThreadBusy = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindowManager::recieveEvent() {
|
||||||
const auto ev = xcb_wait_for_event(DisplayConnection);
|
const auto ev = xcb_wait_for_event(DisplayConnection);
|
||||||
if (ev != NULL) {
|
if (ev != NULL) {
|
||||||
while (animationUtilBusy) {
|
while (animationUtilBusy) {
|
||||||
; // wait for it to finish
|
; // wait for it to finish
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set thread state, halt animations until done.
|
// Set thread state, halt animations until done.
|
||||||
mainThreadBusy = true;
|
mainThreadBusy = true;
|
||||||
|
|
||||||
// Read from the bar
|
// Read from the bar
|
||||||
IPCRecieveMessageM(m_sIPCBarPipeOut.szPipeName);
|
if (!g_pWindowManager->statusBar)
|
||||||
|
IPCRecieveMessageM(m_sIPCBarPipeOut.szPipeName);
|
||||||
|
|
||||||
switch (ev->response_type & ~0x80) {
|
const auto EVENTCODE = ev->response_type & ~0x80;
|
||||||
|
|
||||||
|
switch (EVENTCODE) {
|
||||||
case XCB_ENTER_NOTIFY:
|
case XCB_ENTER_NOTIFY:
|
||||||
Events::eventEnter(ev);
|
Events::eventEnter(ev);
|
||||||
Debug::log(LOG, "Event dispatched ENTER");
|
Debug::log(LOG, "Event dispatched ENTER");
|
||||||
|
@ -241,7 +274,7 @@ bool CWindowManager::handleEvent() {
|
||||||
break;
|
break;
|
||||||
case XCB_MOTION_NOTIFY:
|
case XCB_MOTION_NOTIFY:
|
||||||
Events::eventMotionNotify(ev);
|
Events::eventMotionNotify(ev);
|
||||||
//Debug::log(LOG, "Event dispatched MOTION_NOTIFY"); // Spam!!
|
// Debug::log(LOG, "Event dispatched MOTION_NOTIFY"); // Spam!!
|
||||||
break;
|
break;
|
||||||
case XCB_EXPOSE:
|
case XCB_EXPOSE:
|
||||||
Events::eventExpose(ev);
|
Events::eventExpose(ev);
|
||||||
|
@ -251,39 +284,20 @@ bool CWindowManager::handleEvent() {
|
||||||
Events::eventKeyPress(ev);
|
Events::eventKeyPress(ev);
|
||||||
Debug::log(LOG, "Event dispatched KEY_PRESS");
|
Debug::log(LOG, "Event dispatched KEY_PRESS");
|
||||||
break;
|
break;
|
||||||
|
case XCB_CLIENT_MESSAGE:
|
||||||
|
Events::eventClientMessage(ev);
|
||||||
|
Debug::log(LOG, "Event dispatched CLIENT_MESSAGE");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (ev->response_type & ~0x80 != 14)
|
|
||||||
|
if ((EVENTCODE != 14) && (EVENTCODE != 13) && (EVENTCODE != 0) && (EVENTCODE != 22))
|
||||||
Debug::log(WARN, "Unknown event: " + std::to_string(ev->response_type & ~0x80));
|
Debug::log(WARN, "Unknown event: " + std::to_string(ev->response_type & ~0x80));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ev);
|
free(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh and apply the parameters of all dirty windows.
|
|
||||||
refreshDirtyWindows();
|
|
||||||
|
|
||||||
// Sanity checks
|
|
||||||
for (const auto active : activeWorkspaces) {
|
|
||||||
sanityCheckOnWorkspace(active);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove unused workspaces
|
|
||||||
cleanupUnusedWorkspaces();
|
|
||||||
|
|
||||||
// Update last window name
|
|
||||||
updateActiveWindowName();
|
|
||||||
|
|
||||||
// Update the bar with the freshest stuff
|
|
||||||
updateBarInfo();
|
|
||||||
|
|
||||||
xcb_flush(DisplayConnection);
|
|
||||||
|
|
||||||
// Restore thread state
|
|
||||||
mainThreadBusy = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindowManager::cleanupUnusedWorkspaces() {
|
void CWindowManager::cleanupUnusedWorkspaces() {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "utilities/XCBProps.hpp"
|
#include "utilities/XCBProps.hpp"
|
||||||
#include "ewmh/ewmh.hpp"
|
#include "ewmh/ewmh.hpp"
|
||||||
#include "bar/Bar.hpp"
|
#include "bar/Bar.hpp"
|
||||||
|
#include "utilities/Tray.hpp"
|
||||||
|
|
||||||
#include "ipc/ipc.hpp"
|
#include "ipc/ipc.hpp"
|
||||||
|
|
||||||
|
@ -51,6 +52,8 @@ public:
|
||||||
Vector2D lastKnownBarPosition = {-1,-1};
|
Vector2D lastKnownBarPosition = {-1,-1};
|
||||||
uint64_t barWindowID = 0;
|
uint64_t barWindowID = 0;
|
||||||
GThread* barThread; /* Well right now anything but the bar but lol */
|
GThread* barThread; /* Well right now anything but the bar but lol */
|
||||||
|
|
||||||
|
std::vector<CTrayClient> trayclients;
|
||||||
|
|
||||||
std::atomic<bool> mainThreadBusy = false;
|
std::atomic<bool> mainThreadBusy = false;
|
||||||
std::atomic<bool> animationUtilBusy = false;
|
std::atomic<bool> animationUtilBusy = false;
|
||||||
|
@ -64,6 +67,7 @@ public:
|
||||||
|
|
||||||
void setupManager();
|
void setupManager();
|
||||||
bool handleEvent();
|
bool handleEvent();
|
||||||
|
void recieveEvent();
|
||||||
void refreshDirtyWindows();
|
void refreshDirtyWindows();
|
||||||
|
|
||||||
void setFocusedWindow(xcb_drawable_t);
|
void setFocusedWindow(xcb_drawable_t);
|
||||||
|
@ -111,7 +115,7 @@ public:
|
||||||
|
|
||||||
void recalcAllWorkspaces();
|
void recalcAllWorkspaces();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Internal WM functions that don't have to be exposed
|
// Internal WM functions that don't have to be exposed
|
||||||
|
|
||||||
|
@ -181,15 +185,13 @@ inline std::map<std::string, xcb_atom_t> HYPRATOMS = {
|
||||||
HYPRATOM("WM_CLIENT_LEADER"),
|
HYPRATOM("WM_CLIENT_LEADER"),
|
||||||
HYPRATOM("WM_TAKE_FOCUS"),
|
HYPRATOM("WM_TAKE_FOCUS"),
|
||||||
HYPRATOM("WM_WINDOW_ROLE"),
|
HYPRATOM("WM_WINDOW_ROLE"),
|
||||||
HYPRATOM("I3_SOCKET_PATH"),
|
|
||||||
HYPRATOM("I3_CONFIG_PATH"),
|
|
||||||
HYPRATOM("I3_SYNC"),
|
|
||||||
HYPRATOM("I3_SHMLOG_PATH"),
|
|
||||||
HYPRATOM("I3_PID"),
|
|
||||||
HYPRATOM("I3_LOG_STREAM_SOCKET_PATH"),
|
|
||||||
HYPRATOM("I3_FLOATING_WINDOW"),
|
|
||||||
HYPRATOM("_NET_REQUEST_FRAME_EXTENTS"),
|
HYPRATOM("_NET_REQUEST_FRAME_EXTENTS"),
|
||||||
HYPRATOM("_NET_FRAME_EXTENTS"),
|
HYPRATOM("_NET_FRAME_EXTENTS"),
|
||||||
HYPRATOM("_MOTIF_WM_HINTS"),
|
HYPRATOM("_MOTIF_WM_HINTS"),
|
||||||
HYPRATOM("WM_CHANGE_STATE"),
|
HYPRATOM("WM_CHANGE_STATE"),
|
||||||
|
HYPRATOM("_NET_SYSTEM_TRAY_OPCODE"),
|
||||||
|
HYPRATOM("_NET_SYSTEM_TRAY_COLORS"),
|
||||||
|
HYPRATOM("_NET_SYSTEM_TRAY_VISUAL"),
|
||||||
|
HYPRATOM("_NET_SYSTEM_TRAY_ORIENTATION"),
|
||||||
|
HYPRATOM("_XEMBED_INFO"),
|
||||||
HYPRATOM("MANAGER")};
|
HYPRATOM("MANAGER")};
|
||||||
|
|
Loading…
Reference in a new issue