2021-11-24 21:23:14 +01:00
|
|
|
#include "ewmh.hpp"
|
|
|
|
#include "../windowManager.hpp"
|
|
|
|
|
|
|
|
void EWMH::setupInitEWMH() {
|
|
|
|
Debug::log(LOG, "EWMH init!");
|
|
|
|
|
|
|
|
EWMHwindow = xcb_generate_id(g_pWindowManager->DisplayConnection);
|
|
|
|
|
|
|
|
Debug::log(LOG, "Allocated ID " + std::to_string(EWMHwindow) + " for the EWMH window.");
|
|
|
|
|
|
|
|
uint32_t values[1] = {1};
|
|
|
|
xcb_create_window(g_pWindowManager->DisplayConnection, XCB_COPY_FROM_PARENT, EWMHwindow, g_pWindowManager->Screen->root,
|
|
|
|
-1, -1, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, 0, values);
|
|
|
|
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, EWMHwindow, HYPRATOMS["_NET_SUPPORTING_WM_CHECK"], XCB_ATOM_WINDOW, 32, 1, &EWMHwindow);
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, EWMHwindow, HYPRATOMS["_NET_WM_NAME"], HYPRATOMS["UTF8_STRING"], 8, strlen("Hypr"), "Hypr");
|
|
|
|
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_WM_NAME"], HYPRATOMS["UTF8_STRING"], 8, strlen("Hypr"), "Hypr");
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_SUPPORTING_WM_CHECK"], XCB_ATOM_WINDOW, 32, 1, &EWMHwindow);
|
|
|
|
|
|
|
|
// Atoms EWMH
|
|
|
|
|
|
|
|
xcb_atom_t supportedAtoms[HYPRATOMS.size()];
|
|
|
|
int i = 0;
|
|
|
|
for (auto& a : HYPRATOMS) {
|
|
|
|
supportedAtoms[i] = a.second;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_SUPPORTED"], XCB_ATOM_ATOM, 32, sizeof(supportedAtoms) / sizeof(xcb_atom_t), supportedAtoms);
|
|
|
|
|
2021-12-13 20:21:54 +01:00
|
|
|
// delete workarea
|
|
|
|
xcb_delete_property(g_pWindowManager->DisplayConnection, g_pWindowManager->Screen->root, HYPRATOMS["_NET_WORKAREA"]);
|
|
|
|
|
2021-11-24 21:23:14 +01:00
|
|
|
Debug::log(LOG, "EWMH init done.");
|
2021-12-13 20:21:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void EWMH::updateCurrentWindow(xcb_window_t w) {
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_ACTIVE_WINDOW"], XCB_ATOM_WINDOW, 32, 1, &w);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EWMH::updateClientList() {
|
2021-12-23 22:53:20 +01:00
|
|
|
std::vector<xcb_window_t> windowsList;
|
2021-12-21 09:48:41 +01:00
|
|
|
|
2021-12-13 20:21:54 +01:00
|
|
|
for (auto& w : g_pWindowManager->windows)
|
2021-12-21 09:48:41 +01:00
|
|
|
if (w.getDrawable() > 0 && !w.getIsFloating())
|
2021-12-23 22:53:20 +01:00
|
|
|
windowsList.push_back(w.getDrawable());
|
2021-12-13 20:21:54 +01:00
|
|
|
|
|
|
|
// hack
|
2021-12-23 22:53:20 +01:00
|
|
|
xcb_window_t* ArrWindowList = &windowsList[0];
|
2021-12-13 20:21:54 +01:00
|
|
|
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_CLIENT_LIST"], XCB_ATOM_WINDOW,
|
2021-12-23 22:53:20 +01:00
|
|
|
32, windowsList.size(), ArrWindowList);
|
2021-12-21 09:48:41 +01:00
|
|
|
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_CLIENT_LIST_STACKING"], XCB_ATOM_WINDOW,
|
2021-12-23 22:53:20 +01:00
|
|
|
32, windowsList.size(), ArrWindowList);
|
2021-12-19 02:39:54 +01:00
|
|
|
}
|
|
|
|
|
2021-12-19 08:23:51 +01:00
|
|
|
void EWMH::refreshAllExtents() {
|
|
|
|
for (auto& w : g_pWindowManager->windows)
|
|
|
|
if (w.getDrawable() > 0)
|
|
|
|
setFrameExtents(w.getDrawable());
|
|
|
|
}
|
|
|
|
|
2021-12-19 02:39:54 +01:00
|
|
|
void EWMH::setFrameExtents(xcb_window_t w) {
|
2021-12-19 08:23:51 +01:00
|
|
|
const auto BORDERSIZE = ConfigManager::getInt("border_size");
|
|
|
|
uint32_t extents[4] = {BORDERSIZE,BORDERSIZE,BORDERSIZE,BORDERSIZE};
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, w, HYPRATOMS["_NET_FRAME_EXTENTS"], XCB_ATOM_CARDINAL, 32, 4, &extents);
|
2021-12-19 02:39:54 +01:00
|
|
|
}
|
2021-12-21 09:41:55 +01:00
|
|
|
|
|
|
|
void EWMH::updateDesktops() {
|
2021-12-22 14:53:53 +01:00
|
|
|
|
|
|
|
int ACTIVEWORKSPACE = -1;
|
2021-12-21 09:41:55 +01:00
|
|
|
|
|
|
|
if (!g_pWindowManager->getMonitorFromCursor()) {
|
2021-12-22 14:53:53 +01:00
|
|
|
Debug::log(ERR, "Monitor was null! (updateDesktops EWMH) Using LastWindow");
|
|
|
|
if (const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); PWINDOW)
|
2022-03-08 20:14:01 +01:00
|
|
|
ACTIVEWORKSPACE = g_pWindowManager->activeWorkspaces[PWINDOW->getWorkspaceID()] - 1; // because xorg counts from zero
|
2021-12-22 14:53:53 +01:00
|
|
|
else
|
|
|
|
ACTIVEWORKSPACE = 0;
|
|
|
|
} else {
|
2022-03-08 20:14:01 +01:00
|
|
|
ACTIVEWORKSPACE = g_pWindowManager->activeWorkspaces[g_pWindowManager->getMonitorFromCursor()->ID] - 1;
|
2021-12-21 09:41:55 +01:00
|
|
|
}
|
2021-12-22 14:53:53 +01:00
|
|
|
|
2021-12-21 09:41:55 +01:00
|
|
|
if (DesktopInfo::lastid != ACTIVEWORKSPACE) {
|
|
|
|
// Update the current workspace
|
|
|
|
DesktopInfo::lastid = ACTIVEWORKSPACE;
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_CURRENT_DESKTOP"], XCB_ATOM_CARDINAL, 32, 1, &ACTIVEWORKSPACE);
|
|
|
|
|
|
|
|
|
|
|
|
// Update all desktops
|
|
|
|
const auto ALLDESKTOPS = g_pWindowManager->workspaces.size();
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_NUMBER_OF_DESKTOPS"], XCB_ATOM_CARDINAL, 32, 1, &ALLDESKTOPS);
|
|
|
|
|
|
|
|
// Update desktop names, create a sorted workspaces vec
|
|
|
|
auto workspacesVec = g_pWindowManager->workspaces;
|
|
|
|
std::sort(workspacesVec.begin(), workspacesVec.end(), [](CWorkspace& a, CWorkspace& b) { return a.getID() < b.getID(); });
|
|
|
|
|
|
|
|
int msglen = 0;
|
|
|
|
for (auto& work : workspacesVec) {
|
2022-04-03 22:02:25 +02:00
|
|
|
if (work.getID() == SCRATCHPAD_ID)
|
|
|
|
continue;
|
2021-12-21 09:41:55 +01:00
|
|
|
msglen += strlen(std::to_string(work.getID()).c_str()) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char names[msglen];
|
|
|
|
int curpos = 0;
|
|
|
|
for (auto& work : workspacesVec) {
|
|
|
|
for (int i = 0; i < strlen(std::to_string(work.getID()).c_str()) + 1; ++i) {
|
2022-04-03 22:02:25 +02:00
|
|
|
if (work.getID() == SCRATCHPAD_ID)
|
|
|
|
break;
|
|
|
|
|
2021-12-21 09:41:55 +01:00
|
|
|
names[curpos] = std::to_string(work.getID())[i];
|
|
|
|
++curpos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_DESKTOP_NAMES"], HYPRATOMS["UTF8_STRING"], 8, msglen, names);
|
2022-03-08 20:26:53 +01:00
|
|
|
|
|
|
|
// Also update where the workspaces are so that bars and shit can read which monitor they belong to.
|
|
|
|
uint32_t workspaceCoords[ALLDESKTOPS * 2];
|
|
|
|
|
|
|
|
int pos = 0;
|
|
|
|
for (int i = 0; i < ALLDESKTOPS; ++i) {
|
|
|
|
workspaceCoords[pos++] = g_pWindowManager->monitors[g_pWindowManager->workspaces[i].getMonitor()].vecPosition.x;
|
|
|
|
workspaceCoords[pos++] = g_pWindowManager->monitors[g_pWindowManager->workspaces[i].getMonitor()].vecPosition.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, g_pWindowManager->Screen->root, HYPRATOMS["_NET_DESKTOP_VIEWPORT"], XCB_ATOM_CARDINAL, 32, pos, &workspaceCoords);
|
2021-12-21 09:41:55 +01:00
|
|
|
}
|
2021-12-21 10:46:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void EWMH::updateWindow(xcb_window_t win) {
|
|
|
|
const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(win);
|
|
|
|
|
|
|
|
if (!PWINDOW || win < 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto WORKSPACE = PWINDOW->getWorkspaceID();
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, win, HYPRATOMS["_NET_WM_DESKTOP"], XCB_ATOM_CARDINAL, 32, 1, &WORKSPACE);
|
2021-12-21 11:02:17 +01:00
|
|
|
|
|
|
|
// ICCCM State Normal
|
2021-12-21 11:46:31 +01:00
|
|
|
if (!PWINDOW->getDock()) {
|
2021-12-21 11:02:17 +01:00
|
|
|
long data[] = {XCB_ICCCM_WM_STATE_NORMAL, XCB_NONE};
|
2021-12-21 11:05:32 +01:00
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_REPLACE, win, HYPRATOMS["WM_STATE"], HYPRATOMS["WM_STATE"], 32, 2, data);
|
2022-04-20 17:36:53 +02:00
|
|
|
|
|
|
|
if (PWINDOW->getDrawable() == g_pWindowManager->LastWindow) {
|
|
|
|
uint32_t dataa[] = {HYPRATOMS["_NET_WM_STATE_FOCUSED"]};
|
|
|
|
xcb_change_property(g_pWindowManager->DisplayConnection, XCB_PROP_MODE_APPEND, PWINDOW->getDrawable(), HYPRATOMS["_NET_WM_STATE"], XCB_ATOM_ATOM, 32, 1, dataa);
|
|
|
|
} else {
|
|
|
|
removeAtom(PWINDOW->getDrawable(), HYPRATOMS["_NET_WM_STATE"], HYPRATOMS["_NET_WM_STATE_FOCUSED"]);
|
|
|
|
}
|
2021-12-21 11:02:17 +01:00
|
|
|
}
|
2021-12-21 12:22:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void EWMH::checkTransient(xcb_window_t window) {
|
|
|
|
|
|
|
|
const auto PWINDOW = g_pWindowManager->getWindowFromDrawable(window);
|
|
|
|
|
|
|
|
if (!PWINDOW)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Check if it's a transient
|
|
|
|
const auto TRANSIENTCOOKIE = xcb_get_property(g_pWindowManager->DisplayConnection, false, window, 68 /* TRANSIENT_FOR */, XCB_GET_PROPERTY_TYPE_ANY, 0, UINT32_MAX);
|
|
|
|
const auto TRANSIENTREPLY = xcb_get_property_reply(g_pWindowManager->DisplayConnection, TRANSIENTCOOKIE, NULL);
|
|
|
|
|
|
|
|
if (!TRANSIENTREPLY || xcb_get_property_value_length(TRANSIENTREPLY) == 0) {
|
|
|
|
Debug::log(WARN, "Transient check failed.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcb_window_t transientWindow;
|
|
|
|
if (!xcb_icccm_get_wm_transient_for_from_reply(&transientWindow, TRANSIENTREPLY)) {
|
|
|
|
Debug::log(WARN, "Transient reply failed.");
|
|
|
|
free(TRANSIENTREPLY);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set the flags
|
|
|
|
const auto PPARENTWINDOW = g_pWindowManager->getWindowFromDrawable(transientWindow);
|
|
|
|
|
|
|
|
if (!PPARENTWINDOW) {
|
|
|
|
free(TRANSIENTREPLY);
|
|
|
|
Debug::log(LOG, "Transient set for a nonexistent window, ignoring.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PPARENTWINDOW->addTransientChild(window);
|
|
|
|
|
|
|
|
Debug::log(LOG, "Added a transient child to " + std::to_string(transientWindow) + ".");
|
|
|
|
|
|
|
|
free(TRANSIENTREPLY);
|
2021-12-21 09:41:55 +01:00
|
|
|
}
|