fix: restore bar if tray saving enabled

This commit is contained in:
Matthew Wong 2026-03-04 22:22:53 -08:00
parent 5a29688ca2
commit 8298832607
11 changed files with 144 additions and 48 deletions

View file

@ -13,7 +13,7 @@ bool isParentDead() {
void parseEvent() {
while(1) {
g_pWindowManager->recieveEvent();
g_pWindowManager->receiveEvent("bar");
}
}
@ -244,7 +244,7 @@ void CStatusBar::setupTray() {
free(SELREPLY);
free(TRAYREPLY);
Debug::log(LOG, "Tray setup done, sending message!");
Debug::log(LOG, "Tray setup done, sending message! Tray window id: " + std::to_string(trayWindowID));
uint8_t buf[32] = {NULL};
xcb_client_message_event_t* event = (xcb_client_message_event_t*)buf;
@ -268,6 +268,7 @@ void CStatusBar::fixTrayOnCreate() {
if (m_bHasTray && ConfigManager::getInt("bar:no_tray_saving") == 0) {
for (auto& tray : g_pWindowManager->trayclients) {
Debug::log(LOG, "Fixing tray client on create " + std::to_string(tray.window) + " by reparenting to tray " + std::to_string(g_pWindowManager->statusBar->trayWindowID));
xcb_reparent_window(g_pWindowManager->DisplayConnection, tray.window, g_pWindowManager->statusBar->trayWindowID, 0, 0);
xcb_map_window(g_pWindowManager->DisplayConnection, tray.window);
tray.hidden = false;
@ -300,6 +301,7 @@ void CStatusBar::saveTrayOnDestroy() {
return;
for (auto& tray : g_pWindowManager->trayclients) {
Debug::log(LOG, "Saving tray client on destroy " + std::to_string(tray.window) + " by reparenting to root " + std::to_string(g_pWindowManager->Screen->root));
xcb_reparent_window(g_pWindowManager->DisplayConnection, tray.window, g_pWindowManager->Screen->root, 30000, 30000);
}
}
@ -383,13 +385,13 @@ void CStatusBar::setup(int MonitorID) {
// fix tray
fixTrayOnCreate();
Debug::log(LOG, "Bar setup done!");
Debug::log(LOG, "Bar setup done! Bar window id " + std::to_string(m_iWindowID));
m_bIsDestroyed = false;
}
void CStatusBar::destroy() {
Debug::log(LOG, "Destroying the bar!");
Debug::log(LOG, "Destroying bar! Bar window id " + std::to_string(m_iWindowID));
if (m_bIsDestroyed)
return;
@ -411,6 +413,7 @@ void CStatusBar::destroy() {
m_pCairo = nullptr;
m_bIsDestroyed = true;
Debug::log(LOG, "Destroyed bar! Bar window id " + std::to_string(m_iWindowID));
}
int CStatusBar::getTextWidth(std::string text, std::string font, double size) {
@ -694,4 +697,4 @@ void CStatusBar::ensureTrayClientHidden(xcb_window_t window, bool hide) {
if (trayitem.window == window)
trayitem.hidden = hide;
}
}
}

View file

@ -113,4 +113,4 @@ private:
};
// Main thread for the bar. Is only initted once in main.cpp so we can do this.
int64_t barMainThread();
int64_t barMainThread();

View file

@ -416,6 +416,7 @@ void ConfigManager::loadConfigLoadVars() {
// Reload the bar as well, don't load it before the default is loaded.
if (loadBar && g_pWindowManager->statusBar && (configValues["bar:enabled"].intValue == 1 || parseError != "")) {
Debug::log(WARN, "Destroying bar because reloading! Bar window id " + std::to_string(g_pWindowManager->statusBar->getWindowID()));
g_pWindowManager->statusBar->destroy();
// make the bar height visible

View file

@ -125,14 +125,14 @@ void Events::eventLeave(xcb_generic_event_t* event) {
void Events::eventDestroy(xcb_generic_event_t* event) {
const auto E = reinterpret_cast<xcb_destroy_notify_event_t*>(event);
Debug::log(LOG, "Destroy called on event " + std::to_string(E->event) + " window " + std::to_string(E->window));
// let bar check if it wasnt a tray item
if (g_pWindowManager->statusBar)
g_pWindowManager->statusBar->ensureTrayClientDead(E->window);
RETURNIFBAR;
Debug::log(LOG, "Destroy called on " + std::to_string(E->window));
g_pWindowManager->closeWindowAllChecks(E->window);
// refocus on new window
@ -145,6 +145,8 @@ void Events::eventDestroy(xcb_generic_event_t* event) {
void Events::eventUnmapWindow(xcb_generic_event_t* event) {
const auto E = reinterpret_cast<xcb_unmap_notify_event_t*>(event);
Debug::log(LOG, "Unmap called on event " + std::to_string(E->event) + " window " + std::to_string(E->window));
// let bar check if it wasnt a tray item
if (g_pWindowManager->statusBar)
g_pWindowManager->statusBar->ensureTrayClientHidden(E->window, true);
@ -154,11 +156,11 @@ void Events::eventUnmapWindow(xcb_generic_event_t* event) {
const auto PCLOSEDWINDOW = g_pWindowManager->getWindowFromDrawable(E->window);
if (!PCLOSEDWINDOW) {
Debug::log(LOG, "Unmap called on an invalid window: " + std::to_string(E->window));
Debug::log(LOG, "Unmap called on an invalid window: event " + std::to_string(E->event) + " window " + std::to_string(E->window));
return; // bullshit window?
}
Debug::log(LOG, "Unmap called on " + std::to_string(E->window) + " -> " + PCLOSEDWINDOW->getName());
Debug::log(LOG, "Unmap called on event " + std::to_string(E->event) + " window " + std::to_string(E->window) + " -> " + PCLOSEDWINDOW->getName());
if (!PCLOSEDWINDOW->getDock())
g_pWindowManager->closeWindowAllChecks(E->window);
@ -635,9 +637,6 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
void Events::eventMapWindow(xcb_generic_event_t* event) {
const auto E = reinterpret_cast<xcb_map_request_event_t*>(event);
// Ignore sequence
ignoredEvents.push_back(E->sequence);
// let bar check if it wasnt a tray item
if (g_pWindowManager->statusBar)
g_pWindowManager->statusBar->ensureTrayClientHidden(E->window, false);
@ -645,7 +644,12 @@ void Events::eventMapWindow(xcb_generic_event_t* event) {
RETURNIFBAR;
// Map the window
xcb_map_window(g_pWindowManager->DisplayConnection, E->window);
const auto COOKIE = xcb_map_window(g_pWindowManager->DisplayConnection, E->window);
// Ignore sequence
Debug::log(LOG, "Will ignore map request event sequence " + std::to_string(E->sequence) + " on window " + std::to_string(E->window));
auto ignoreEvent = std::make_tuple(COOKIE.sequence, XCB_MAP_REQUEST);
Events::ignoredEvents.push_back(ignoreEvent);
// We check if the window is not on our tile-blacklist and if it is, we have a special treatment procedure for it.
// this func also sets some stuff
@ -941,6 +945,7 @@ void Events::eventClientMessage(xcb_generic_event_t* event) {
g_pWindowManager->trayclients.push_back(newTrayClient);
xcb_map_window(g_pWindowManager->DisplayConnection, CLIENT);
Debug::log(LOG, "Docked window " + std::to_string(CLIENT) + " to the bar " + std::to_string(g_pWindowManager->statusBar->getWindowID()));
}
}
}
@ -1029,4 +1034,4 @@ void Events::eventRandRScreenChange(xcb_generic_event_t* event) {
// Make all windows dirty and recalc all workspaces
g_pWindowManager->recalcAllWorkspaces();
}
}

View file

@ -1,3 +1,4 @@
#include <cstdint>
#include <inttypes.h>
#include <thread>
@ -17,6 +18,7 @@ namespace Events {
EVENT(MotionNotify);
EVENT(ClientMessage);
EVENT(Configure);
EVENT(Property);
EVENT(RandRScreenChange);
@ -32,9 +34,9 @@ namespace Events {
inline bool nextWindowCentered = false;
// Fix focus on open
inline std::deque<uint64_t> ignoredEvents;
inline std::deque<std::tuple<uint64_t, int32_t>> ignoredEvents;
// Fix spammed RandR events
inline std::chrono::high_resolution_clock::time_point lastRandREvent = std::chrono::high_resolution_clock::now();
inline int susRandREventNo = 0;
};
};

View file

@ -127,4 +127,4 @@ void AnimationUtil::move() {
if (updateRequired)
emptyEvent(); // send a fake request to update dirty windows
}
}

View file

@ -106,4 +106,4 @@ std::vector<std::string> splitString(std::string in, char c) {
}
return returns;
}
}

View file

@ -125,4 +125,79 @@ uint8_t getWindowState(const int& win) {
free(REPLY);
}
return returns;
}
}
std::string eventCodeToString(const uint8_t& code) {
switch (code) {
case XCB_KEY_PRESS:
return "XCB_KEY_PRESS";
case XCB_KEY_RELEASE:
return "XCB_KEY_RELEASE";
case XCB_BUTTON_PRESS:
return "XCB_BUTTON_PRESS";
case XCB_BUTTON_RELEASE:
return "XCB_BUTTON_RELEASE";
case XCB_MOTION_NOTIFY:
return "XCB_MOTION_NOTIFY";
case XCB_ENTER_NOTIFY:
return "XCB_ENTER_NOTIFY";
case XCB_LEAVE_NOTIFY:
return "XCB_LEAVE_NOTIFY";
case XCB_FOCUS_IN:
return "XCB_FOCUS_IN";
case XCB_FOCUS_OUT:
return "XCB_FOCUS_OUT";
case XCB_KEYMAP_NOTIFY:
return "XCB_KEYMAP_NOTIFY";
case XCB_EXPOSE:
return "XCB_EXPOSE";
case XCB_GRAPHICS_EXPOSURE:
return "XCB_GRAPHICS_EXPOSURE";
case XCB_NO_EXPOSURE:
return "XCB_NO_EXPOSURE";
case XCB_VISIBILITY_NOTIFY:
return "XCB_VISIBILITY_NOTIFY";
case XCB_CREATE_NOTIFY:
return "XCB_CREATE_NOTIFY";
case XCB_DESTROY_NOTIFY:
return "XCB_DESTROY_NOTIFY";
case XCB_UNMAP_NOTIFY:
return "XCB_UNMAP_NOTIFY";
case XCB_MAP_NOTIFY:
return "XCB_MAP_NOTIFY";
case XCB_MAP_REQUEST:
return "XCB_MAP_REQUEST";
case XCB_REPARENT_NOTIFY:
return "XCB_REPARENT_NOTIFY";
case XCB_CONFIGURE_NOTIFY:
return "XCB_CONFIGURE_NOTIFY";
case XCB_CONFIGURE_REQUEST:
return "XCB_CONFIGURE_REQUEST";
case XCB_GRAVITY_NOTIFY:
return "XCB_GRAVITY_NOTIFY";
case XCB_RESIZE_REQUEST:
return "XCB_RESIZE_REQUEST";
case XCB_CIRCULATE_NOTIFY:
return "XCB_CIRCULATE_NOTIFY";
case XCB_CIRCULATE_REQUEST:
return "XCB_CIRCULATE_REQUEST";
case XCB_PROPERTY_NOTIFY:
return "XCB_PROPERTY_NOTIFY";
case XCB_SELECTION_CLEAR:
return "XCB_SELECTION_CLEAR";
case XCB_SELECTION_REQUEST:
return "XCB_SELECTION_REQUEST";
case XCB_SELECTION_NOTIFY:
return "XCB_SELECTION_NOTIFY";
case XCB_COLORMAP_NOTIFY:
return "XCB_COLORMAP_NOTIFY";
case XCB_CLIENT_MESSAGE:
return "XCB_CLIENT_MESSAGE";
case XCB_MAPPING_NOTIFY:
return "XCB_MAPPING_NOTIFY";
case XCB_GE_GENERIC:
return "XCB_GE_GENERIC";
default:
return "UNKNOWN_EVENT";
}
}

View file

@ -9,4 +9,6 @@ std::string getRoleName(int64_t window);
std::string getWindowName(uint64_t window);
uint8_t getWindowState(const int& win);
void removeAtom(const int& window, xcb_atom_t prop, xcb_atom_t atom);
void removeAtom(const int& window, xcb_atom_t prop, xcb_atom_t atom);
std::string eventCodeToString(const uint8_t& code);

View file

@ -214,8 +214,8 @@ bool CWindowManager::handleEvent() {
xcb_flush(DisplayConnection);
// recieve the event. Blocks.
recieveEvent();
// receive the event. Blocks.
receiveEvent("main");
// refresh and apply the parameters of all dirty windows.
refreshDirtyWindows();
@ -251,7 +251,7 @@ bool CWindowManager::handleEvent() {
return true;
}
void CWindowManager::recieveEvent() {
void CWindowManager::receiveEvent(const std::string& id) {
const auto ev = xcb_wait_for_event(DisplayConnection);
if (ev != NULL) {
while (animationUtilBusy) {
@ -259,13 +259,15 @@ void CWindowManager::recieveEvent() {
}
for (auto& e : Events::ignoredEvents) {
if (e == ev->sequence) {
Debug::log(LOG, "Ignoring event type " + std::to_string(ev->response_type & ~0x80) + ".");
auto [sequence, responseType] = e;
if (sequence == ev->sequence &&
(responseType == 0 || responseType == ev->response_type)) {
Debug::log(LOG, id + ": Ignoring event type " + eventCodeToString(ev->response_type) + " sequence " + std::to_string(ev->sequence));
free(ev);
return;
}
}
if (Events::ignoredEvents.size() > 20)
Events::ignoredEvents.pop_front();
@ -282,31 +284,31 @@ void CWindowManager::recieveEvent() {
switch (EVENTCODE) {
case XCB_ENTER_NOTIFY:
Events::eventEnter(ev);
Debug::log(LOG, "Event dispatched ENTER");
Debug::log(LOG, id + ": Event dispatched ENTER");
break;
case XCB_LEAVE_NOTIFY:
Events::eventLeave(ev);
Debug::log(LOG, "Event dispatched LEAVE");
Debug::log(LOG, id + ": Event dispatched LEAVE");
break;
case XCB_DESTROY_NOTIFY:
Events::eventDestroy(ev);
Debug::log(LOG, "Event dispatched DESTROY");
Debug::log(LOG, id + ": Event dispatched DESTROY");
break;
case XCB_UNMAP_NOTIFY:
Events::eventUnmapWindow(ev);
Debug::log(LOG, "Event dispatched UNMAP");
Debug::log(LOG, id + ": Event dispatched UNMAP");
break;
case XCB_MAP_REQUEST:
Events::eventMapWindow(ev);
Debug::log(LOG, "Event dispatched MAP");
Debug::log(LOG, id + ": Event dispatched MAP");
break;
case XCB_BUTTON_PRESS:
Events::eventButtonPress(ev);
Debug::log(LOG, "Event dispatched BUTTON_PRESS");
Debug::log(LOG, id + ": Event dispatched BUTTON_PRESS");
break;
case XCB_BUTTON_RELEASE:
Events::eventButtonRelease(ev);
Debug::log(LOG, "Event dispatched BUTTON_RELEASE");
Debug::log(LOG, id + ": Event dispatched BUTTON_RELEASE");
break;
case XCB_MOTION_NOTIFY:
Events::eventMotionNotify(ev);
@ -314,31 +316,31 @@ void CWindowManager::recieveEvent() {
break;
case XCB_EXPOSE:
Events::eventExpose(ev);
Debug::log(LOG, "Event dispatched EXPOSE");
Debug::log(LOG, id + ": Event dispatched EXPOSE");
break;
case XCB_KEY_PRESS:
Events::eventKeyPress(ev);
Debug::log(LOG, "Event dispatched KEY_PRESS");
Debug::log(LOG, id + ": Event dispatched KEY_PRESS");
break;
case XCB_CLIENT_MESSAGE:
Events::eventClientMessage(ev);
Debug::log(LOG, "Event dispatched CLIENT_MESSAGE");
Debug::log(LOG, id + ": Event dispatched CLIENT_MESSAGE");
break;
case XCB_CONFIGURE_REQUEST:
Events::eventConfigure(ev);
Debug::log(LOG, "Event dispatched CONFIGURE");
Debug::log(LOG, id + ": Event dispatched CONFIGURE");
break;
default:
if ((EVENTCODE != 14) && (EVENTCODE != 13) && (EVENTCODE != 0) && (EVENTCODE != 22) && (TYPE - RandREventBase != XCB_RANDR_SCREEN_CHANGE_NOTIFY))
Debug::log(WARN, "Unknown event: " + std::to_string(ev->response_type & ~0x80));
Debug::log(WARN, id + ": Unknown event: " + eventCodeToString(ev->response_type));
break;
}
if ((int)TYPE - RandREventBase == XCB_RANDR_SCREEN_CHANGE_NOTIFY && RandREventBase > 0) {
Events::eventRandRScreenChange(ev);
Debug::log(LOG, "Event dispatched RANDR_SCREEN_CHANGE");
Debug::log(LOG, id + ": Event dispatched RANDR_SCREEN_CHANGE");
}
free(ev);
@ -361,7 +363,8 @@ void CWindowManager::processBarHiding() {
if (WORK->getHasFullscreenWindow() && !w.getDockHidden()) {
const auto COOKIE = xcb_unmap_window(DisplayConnection, w.getDrawable());
Events::ignoredEvents.push_back(COOKIE.sequence);
auto event = std::make_tuple(COOKIE.sequence, 0);
Events::ignoredEvents.push_back(event);
w.setDockHidden(true);
}
@ -480,7 +483,8 @@ void CWindowManager::refreshDirtyWindows() {
const auto COOKIE = xcb_configure_window(DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, Values);
window.setLastUpdatePosition(Vector2D(Values[0], Values[1]));
Events::ignoredEvents.push_back(COOKIE.sequence);
auto event = std::make_tuple(COOKIE.sequence, 0);
Events::ignoredEvents.push_back(event);
}
} else {
// Update the position because the border makes the window jump
@ -491,7 +495,8 @@ void CWindowManager::refreshDirtyWindows() {
const auto COOKIE = xcb_configure_window(DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, Values);
window.setLastUpdatePosition(Vector2D(Values[0], Values[1]));
Events::ignoredEvents.push_back(COOKIE.sequence);
auto event = std::make_tuple(COOKIE.sequence, 0);
Events::ignoredEvents.push_back(event);
}
Values[0] = (int)ConfigManager::getInt("border_size");
@ -509,7 +514,8 @@ void CWindowManager::refreshDirtyWindows() {
const auto COOKIE = xcb_configure_window(DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, Values);
window.setLastUpdateSize(Vector2D(Values[0], Values[1]));
Events::ignoredEvents.push_back(COOKIE.sequence);
auto event = std::make_tuple(COOKIE.sequence, 0);
Events::ignoredEvents.push_back(event);
}
window.setFirstAnimFrame(true);
}
@ -524,7 +530,8 @@ void CWindowManager::refreshDirtyWindows() {
const auto COOKIE = xcb_configure_window(DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, Values);
window.setLastUpdateSize(Vector2D(Values[0], Values[1]));
Events::ignoredEvents.push_back(COOKIE.sequence);
auto event = std::make_tuple(COOKIE.sequence, 0);
Events::ignoredEvents.push_back(event);
}
}
}
@ -2086,7 +2093,8 @@ void CWindowManager::setAllFloatingWindowsTop() {
void CWindowManager::setAWindowTop(xcb_window_t window) {
Values[0] = XCB_STACK_MODE_ABOVE;
const auto COOKIE = xcb_configure_window(g_pWindowManager->DisplayConnection, window, XCB_CONFIG_WINDOW_STACK_MODE, Values);
Events::ignoredEvents.push_back(COOKIE.sequence);
auto event = std::make_tuple(COOKIE.sequence, 0);
Events::ignoredEvents.push_back(event);
// set the bar topper jic
Values[0] = XCB_STACK_MODE_ABOVE;
@ -2677,4 +2685,4 @@ void CWindowManager::processCursorDeltaOnWindowResizeTiled(CWindow* pWindow, con
TOPCONTAINER->setSplitRatio(std::clamp(TOPCONTAINER->getSplitRatio() + allowedMovement.y, (double)0.05f, (double)1.95f));
SIDECONTAINER->recalcSizePosRecursive();
TOPCONTAINER->recalcSizePosRecursive();
}
}

View file

@ -80,7 +80,7 @@ public:
void setupManager();
bool handleEvent();
void recieveEvent();
void receiveEvent(const std::string& id);
void refreshDirtyWindows();
void setFocusedWindow(xcb_drawable_t);