2021-11-18 18:04:09 +01:00
|
|
|
#include "events.hpp"
|
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
gpointer handle(gpointer data) {
|
2021-11-27 19:07:33 +01:00
|
|
|
int lazyUpdateCounter = 0;
|
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
while (1) {
|
|
|
|
// wait for the main thread to be idle
|
|
|
|
while (g_pWindowManager->mainThreadBusy) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set state to let the main thread know to wait.
|
|
|
|
g_pWindowManager->animationUtilBusy = true;
|
|
|
|
|
|
|
|
// update animations.
|
|
|
|
AnimationUtil::move();
|
|
|
|
//
|
2021-11-21 12:40:03 +01:00
|
|
|
|
2021-11-27 19:07:33 +01:00
|
|
|
// Don't spam these
|
|
|
|
if (lazyUpdateCounter > 10){
|
|
|
|
// Update the active window name
|
|
|
|
g_pWindowManager->updateActiveWindowName();
|
|
|
|
|
|
|
|
// Update the bar
|
|
|
|
g_pWindowManager->updateBarInfo();
|
|
|
|
|
|
|
|
// check config
|
|
|
|
ConfigManager::tick();
|
|
|
|
|
|
|
|
lazyUpdateCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
++lazyUpdateCounter;
|
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
// restore anim state
|
|
|
|
g_pWindowManager->animationUtilBusy = false;
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / ConfigManager::getInt("max_fps")));
|
|
|
|
}
|
2021-11-21 11:25:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Events::setThread() {
|
|
|
|
|
2021-11-26 20:20:11 +01:00
|
|
|
// Start a GTK thread so that Cairo does not complain.
|
|
|
|
|
|
|
|
g_pWindowManager->barThread = g_thread_new("Bar", handle, nullptr);
|
|
|
|
|
|
|
|
if (!g_pWindowManager->barThread) {
|
|
|
|
Debug::log(ERR, "Gthread failed!");
|
|
|
|
return;
|
|
|
|
}
|
2021-11-21 11:25:26 +01:00
|
|
|
}
|
|
|
|
|
2021-11-18 18:04:09 +01:00
|
|
|
void Events::eventEnter(xcb_generic_event_t* event) {
|
|
|
|
const auto E = reinterpret_cast<xcb_enter_notify_event_t*>(event);
|
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-18 18:04:09 +01:00
|
|
|
|
2021-12-05 12:05:44 +01:00
|
|
|
const auto PENTERWINDOW = g_pWindowManager->getWindowFromDrawable(E->event);
|
|
|
|
|
|
|
|
if (!PENTERWINDOW)
|
|
|
|
return; // wut
|
|
|
|
|
|
|
|
// Only when focus_when_hover OR floating OR last window floating
|
|
|
|
if (ConfigManager::getInt("focus_when_hover") == 1
|
|
|
|
|| PENTERWINDOW->getIsFloating()
|
|
|
|
|| (g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow) && g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow)->getIsFloating()))
|
|
|
|
g_pWindowManager->setFocusedWindow(E->event);
|
|
|
|
|
|
|
|
PENTERWINDOW->setDirty(true);
|
2021-11-18 18:04:09 +01:00
|
|
|
}
|
|
|
|
|
2021-11-18 22:08:28 +01:00
|
|
|
void Events::eventLeave(xcb_generic_event_t* event) {
|
|
|
|
const auto E = reinterpret_cast<xcb_leave_notify_event_t*>(event);
|
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-18 22:08:28 +01:00
|
|
|
//
|
|
|
|
}
|
|
|
|
|
2021-11-18 18:04:09 +01:00
|
|
|
void Events::eventDestroy(xcb_generic_event_t* event) {
|
2021-11-18 22:21:52 +01:00
|
|
|
const auto E = reinterpret_cast<xcb_destroy_notify_event_t*>(event);
|
2021-11-18 18:04:09 +01:00
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
// let bar check if it wasnt a tray item
|
|
|
|
if (g_pWindowManager->statusBar)
|
|
|
|
g_pWindowManager->statusBar->ensureTrayClientDead(E->window);
|
|
|
|
|
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-24 21:50:44 +01:00
|
|
|
g_pWindowManager->closeWindowAllChecks(E->window);
|
2021-12-02 15:08:19 +01:00
|
|
|
|
|
|
|
// refocus on new window
|
|
|
|
g_pWindowManager->refocusWindowOnClosed();
|
2021-11-30 17:08:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Events::eventUnmapWindow(xcb_generic_event_t* event) {
|
|
|
|
const auto E = reinterpret_cast<xcb_unmap_notify_event_t*>(event);
|
2021-11-28 16:14:12 +01:00
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
// let bar check if it wasnt a tray item
|
|
|
|
if (g_pWindowManager->statusBar)
|
|
|
|
g_pWindowManager->statusBar->ensureTrayClientHidden(E->window, true);
|
|
|
|
|
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-30 17:08:52 +01:00
|
|
|
g_pWindowManager->closeWindowAllChecks(E->window);
|
2021-12-02 15:08:19 +01:00
|
|
|
|
|
|
|
// refocus on new window
|
|
|
|
g_pWindowManager->refocusWindowOnClosed();
|
2021-11-18 18:04:09 +01:00
|
|
|
}
|
|
|
|
|
2021-11-25 17:44:46 +01:00
|
|
|
CWindow* Events::remapFloatingWindow(int windowID, int forcemonitor) {
|
2021-11-23 22:15:36 +01:00
|
|
|
CWindow window;
|
|
|
|
window.setDrawable(windowID);
|
|
|
|
window.setIsFloating(true);
|
|
|
|
window.setDirty(true);
|
|
|
|
if (!g_pWindowManager->getMonitorFromCursor()) {
|
|
|
|
Debug::log(ERR, "Monitor was null! (remapWindow)");
|
|
|
|
// rip! we cannot continue.
|
|
|
|
}
|
2021-11-25 17:44:46 +01:00
|
|
|
const auto CURRENTSCREEN = forcemonitor != -1 ? forcemonitor : g_pWindowManager->getMonitorFromCursor()->ID;
|
2021-11-23 22:15:36 +01:00
|
|
|
window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]);
|
|
|
|
window.setMonitor(CURRENTSCREEN);
|
|
|
|
|
2021-11-27 19:07:33 +01:00
|
|
|
// Window name
|
|
|
|
const auto WINNAME = getWindowName(windowID);
|
|
|
|
Debug::log(LOG, "New window got name: " + WINNAME);
|
|
|
|
window.setName(WINNAME);
|
|
|
|
|
2021-12-01 22:23:16 +01:00
|
|
|
const auto WINCLASSNAME = getClassName(windowID);
|
|
|
|
Debug::log(LOG, "New window got class: " + WINCLASSNAME.second);
|
|
|
|
window.setClassName(WINCLASSNAME.second);
|
|
|
|
|
2021-11-24 18:37:45 +01:00
|
|
|
// For all floating windows, get their default size
|
|
|
|
const auto GEOMETRYCOOKIE = xcb_get_geometry(g_pWindowManager->DisplayConnection, windowID);
|
|
|
|
const auto GEOMETRY = xcb_get_geometry_reply(g_pWindowManager->DisplayConnection, GEOMETRYCOOKIE, 0);
|
|
|
|
|
|
|
|
if (GEOMETRY) {
|
2021-11-25 17:44:46 +01:00
|
|
|
window.setDefaultPosition(g_pWindowManager->monitors[CURRENTSCREEN].vecPosition);
|
2021-11-24 18:37:45 +01:00
|
|
|
window.setDefaultSize(Vector2D(GEOMETRY->width, GEOMETRY->height));
|
|
|
|
} else {
|
|
|
|
Debug::log(ERR, "Geometry failed in remap.");
|
|
|
|
|
2021-11-25 17:44:46 +01:00
|
|
|
window.setDefaultPosition(g_pWindowManager->monitors[CURRENTSCREEN].vecPosition);
|
2021-11-24 18:37:45 +01:00
|
|
|
window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels / 2.f, g_pWindowManager->Screen->height_in_pixels / 2.f));
|
|
|
|
}
|
2021-11-23 22:15:36 +01:00
|
|
|
|
2021-12-04 23:38:31 +01:00
|
|
|
if (window.getDefaultSize().x < 40 || window.getDefaultSize().y < 40) {
|
2021-12-01 16:24:49 +01:00
|
|
|
// min size
|
2021-12-04 23:38:31 +01:00
|
|
|
window.setDefaultSize(Vector2D(std::clamp(window.getDefaultSize().x, (double)40, (double)99999),
|
|
|
|
std::clamp(window.getDefaultSize().y, (double)40, (double)99999)));
|
2021-12-01 16:24:49 +01:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:14:12 +01:00
|
|
|
if (nextWindowCentered) {
|
|
|
|
nextWindowCentered = false;
|
|
|
|
|
2021-12-01 22:28:53 +01:00
|
|
|
window.setDefaultPosition(g_pWindowManager->monitors[CURRENTSCREEN].vecPosition + g_pWindowManager->monitors[CURRENTSCREEN].vecSize / 2.f - window.getDefaultSize() / 2.f);
|
2021-11-28 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
2021-11-28 11:52:40 +01:00
|
|
|
//
|
|
|
|
// Dock Checks
|
|
|
|
//
|
|
|
|
const auto wm_type_cookie = xcb_get_property(g_pWindowManager->DisplayConnection, false, windowID, HYPRATOMS["_NET_WM_WINDOW_TYPE"], XCB_GET_PROPERTY_TYPE_ANY, 0, (4294967295U));
|
|
|
|
const auto wm_type_cookiereply = xcb_get_property_reply(g_pWindowManager->DisplayConnection, wm_type_cookie, NULL);
|
|
|
|
xcb_atom_t TYPEATOM = NULL;
|
|
|
|
if (wm_type_cookiereply == NULL || xcb_get_property_value_length(wm_type_cookiereply) < 1) {
|
|
|
|
Debug::log(LOG, "No preferred type found.");
|
|
|
|
} else {
|
|
|
|
const auto ATOMS = (xcb_atom_t*)xcb_get_property_value(wm_type_cookiereply);
|
|
|
|
if (!ATOMS) {
|
|
|
|
Debug::log(ERR, "Atoms not found in preferred type!");
|
|
|
|
} else {
|
|
|
|
if (xcbContainsAtom(wm_type_cookiereply, HYPRATOMS["_NET_WM_WINDOW_TYPE_DOCK"])) {
|
|
|
|
// set to floating and set the immovable and nointerventions flag
|
|
|
|
window.setImmovable(true);
|
|
|
|
window.setNoInterventions(true);
|
|
|
|
|
|
|
|
window.setDefaultPosition(Vector2D(GEOMETRY->x, GEOMETRY->y));
|
|
|
|
window.setDefaultSize(Vector2D(GEOMETRY->width, GEOMETRY->height));
|
|
|
|
|
|
|
|
Debug::log(LOG, "New dock created, setting default XYWH to: " + std::to_string(GEOMETRY->x) + ", " + std::to_string(GEOMETRY->y)
|
|
|
|
+ ", " + std::to_string(GEOMETRY->width) + ", " + std::to_string(GEOMETRY->height));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(wm_type_cookiereply);
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
2021-12-04 23:38:31 +01:00
|
|
|
window.setSize(window.getDefaultSize());
|
|
|
|
window.setPosition(window.getDefaultPosition());
|
2021-12-04 23:45:22 +01:00
|
|
|
window.setEffectiveSize(window.getDefaultSize());
|
|
|
|
window.setEffectivePosition(window.getDefaultPosition());
|
2021-12-04 23:38:31 +01:00
|
|
|
|
2021-11-23 22:15:36 +01:00
|
|
|
// Also sets the old one
|
|
|
|
g_pWindowManager->calculateNewWindowParams(&window);
|
|
|
|
|
|
|
|
// Set real size. No animations in the beginning. Maybe later. TODO?
|
|
|
|
window.setRealPosition(window.getEffectivePosition());
|
|
|
|
window.setRealSize(window.getEffectiveSize());
|
|
|
|
|
|
|
|
// Add to arr
|
|
|
|
g_pWindowManager->addWindowToVectorSafe(window);
|
|
|
|
|
2021-11-24 19:33:32 +01:00
|
|
|
Debug::log(LOG, "Created a new floating window! X: " + std::to_string(window.getPosition().x) + ", Y: " + std::to_string(window.getPosition().y) + ", W: " + std::to_string(window.getSize().x) + ", H:" + std::to_string(window.getSize().y) + " ID: " + std::to_string(windowID));
|
2021-11-23 22:15:36 +01:00
|
|
|
|
|
|
|
// Set map values
|
|
|
|
g_pWindowManager->Values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE;
|
|
|
|
xcb_change_window_attributes_checked(g_pWindowManager->DisplayConnection, windowID, XCB_CW_EVENT_MASK, g_pWindowManager->Values);
|
|
|
|
|
|
|
|
g_pWindowManager->setFocusedWindow(windowID);
|
|
|
|
|
|
|
|
// Make all floating windows above
|
|
|
|
g_pWindowManager->setAllFloatingWindowsTop();
|
|
|
|
|
|
|
|
return g_pWindowManager->getWindowFromDrawable(windowID);
|
|
|
|
}
|
|
|
|
|
2021-11-25 17:44:46 +01:00
|
|
|
CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
|
2021-11-18 18:04:09 +01:00
|
|
|
// Do the setup of the window's params and stuf
|
|
|
|
CWindow window;
|
2021-11-22 21:20:32 +01:00
|
|
|
window.setDrawable(windowID);
|
2021-11-18 18:04:09 +01:00
|
|
|
window.setIsFloating(false);
|
|
|
|
window.setDirty(true);
|
2021-11-22 22:37:01 +01:00
|
|
|
if (!g_pWindowManager->getMonitorFromCursor()) {
|
|
|
|
Debug::log(ERR, "Monitor was null! (remapWindow)");
|
|
|
|
// rip! we cannot continue.
|
|
|
|
}
|
2021-11-25 17:44:46 +01:00
|
|
|
const auto CURRENTSCREEN = forcemonitor != -1 ? forcemonitor : g_pWindowManager->getMonitorFromCursor()->ID;
|
2021-11-21 19:59:59 +01:00
|
|
|
window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]);
|
2021-11-21 17:40:02 +01:00
|
|
|
window.setMonitor(CURRENTSCREEN);
|
2021-11-18 18:04:09 +01:00
|
|
|
|
2021-11-27 19:07:33 +01:00
|
|
|
// Window name
|
|
|
|
const auto WINNAME = getWindowName(windowID);
|
|
|
|
Debug::log(LOG, "New window got name: " + WINNAME);
|
|
|
|
window.setName(WINNAME);
|
|
|
|
|
2021-12-01 22:23:16 +01:00
|
|
|
const auto WINCLASSNAME = getClassName(windowID);
|
|
|
|
Debug::log(LOG, "New window got class: " + WINCLASSNAME.second);
|
|
|
|
window.setClassName(WINCLASSNAME.second);
|
|
|
|
|
2021-11-24 19:24:56 +01:00
|
|
|
// For all floating windows, get their default size
|
|
|
|
const auto GEOMETRYCOOKIE = xcb_get_geometry(g_pWindowManager->DisplayConnection, windowID);
|
|
|
|
const auto GEOMETRY = xcb_get_geometry_reply(g_pWindowManager->DisplayConnection, GEOMETRYCOOKIE, 0);
|
|
|
|
|
2021-11-24 18:37:45 +01:00
|
|
|
if (GEOMETRY) {
|
|
|
|
window.setDefaultPosition(Vector2D(GEOMETRY->x, GEOMETRY->y));
|
|
|
|
window.setDefaultSize(Vector2D(GEOMETRY->width, GEOMETRY->height));
|
|
|
|
} else {
|
|
|
|
Debug::log(ERR, "Geometry failed in remap.");
|
|
|
|
|
|
|
|
window.setDefaultPosition(Vector2D(0, 0));
|
|
|
|
window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels / 2.f, g_pWindowManager->Screen->height_in_pixels / 2.f));
|
|
|
|
}
|
2021-11-21 15:15:33 +01:00
|
|
|
|
2021-11-22 18:43:55 +01:00
|
|
|
// Set the parent
|
|
|
|
// check if lastwindow is on our workspace
|
2021-11-22 21:20:32 +01:00
|
|
|
if (auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); (PLASTWINDOW && PLASTWINDOW->getWorkspaceID() == g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) || wasfloating) {
|
|
|
|
// LastWindow is on our workspace, let's make a new split node
|
2021-11-22 18:43:55 +01:00
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
if (wasfloating || PLASTWINDOW->getIsFloating()) {
|
|
|
|
// find a window manually
|
|
|
|
PLASTWINDOW = g_pWindowManager->findWindowAtCursor();
|
|
|
|
}
|
2021-11-22 18:43:55 +01:00
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
if (PLASTWINDOW) {
|
2021-11-22 18:43:55 +01:00
|
|
|
CWindow newWindowSplitNode;
|
|
|
|
newWindowSplitNode.setPosition(PLASTWINDOW->getPosition());
|
|
|
|
newWindowSplitNode.setSize(PLASTWINDOW->getSize());
|
|
|
|
|
|
|
|
newWindowSplitNode.setChildNodeAID(PLASTWINDOW->getDrawable());
|
2021-11-22 21:20:32 +01:00
|
|
|
newWindowSplitNode.setChildNodeBID(windowID);
|
2021-11-22 18:43:55 +01:00
|
|
|
|
|
|
|
newWindowSplitNode.setParentNodeID(PLASTWINDOW->getParentNodeID());
|
|
|
|
|
|
|
|
newWindowSplitNode.setWorkspaceID(window.getWorkspaceID());
|
|
|
|
newWindowSplitNode.setMonitor(window.getMonitor());
|
|
|
|
|
|
|
|
// generates a negative node ID
|
|
|
|
newWindowSplitNode.generateNodeID();
|
|
|
|
|
|
|
|
// update the parent if exists
|
|
|
|
if (const auto PREVPARENT = g_pWindowManager->getWindowFromDrawable(PLASTWINDOW->getParentNodeID()); PREVPARENT) {
|
|
|
|
if (PREVPARENT->getChildNodeAID() == PLASTWINDOW->getDrawable()) {
|
|
|
|
PREVPARENT->setChildNodeAID(newWindowSplitNode.getDrawable());
|
|
|
|
} else {
|
|
|
|
PREVPARENT->setChildNodeBID(newWindowSplitNode.getDrawable());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
window.setParentNodeID(newWindowSplitNode.getDrawable());
|
|
|
|
PLASTWINDOW->setParentNodeID(newWindowSplitNode.getDrawable());
|
|
|
|
|
|
|
|
g_pWindowManager->addWindowToVectorSafe(newWindowSplitNode);
|
2021-11-22 21:20:32 +01:00
|
|
|
} else {
|
|
|
|
window.setParentNodeID(0);
|
|
|
|
}
|
2021-11-22 18:43:55 +01:00
|
|
|
} else {
|
|
|
|
// LastWindow is not on our workspace, so set the parent to 0.
|
|
|
|
window.setParentNodeID(0);
|
|
|
|
}
|
|
|
|
|
2021-12-04 23:16:24 +01:00
|
|
|
// For master layout, add the index
|
|
|
|
window.setMasterChildIndex(g_pWindowManager->getWindowsOnWorkspace(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) - 1);
|
|
|
|
// and set master if needed
|
|
|
|
if (g_pWindowManager->getWindowsOnWorkspace(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) == 0)
|
|
|
|
window.setMaster(true);
|
2021-11-18 18:04:09 +01:00
|
|
|
|
|
|
|
|
|
|
|
// Add to arr
|
2021-11-20 09:25:21 +01:00
|
|
|
g_pWindowManager->addWindowToVectorSafe(window);
|
2021-11-18 18:04:09 +01:00
|
|
|
|
2021-12-04 23:16:24 +01:00
|
|
|
// Now we need to modify the copy in the array.
|
|
|
|
const auto PWINDOWINARR = g_pWindowManager->getWindowFromDrawable(windowID);
|
|
|
|
|
|
|
|
|
|
|
|
// Also sets the old one
|
|
|
|
g_pWindowManager->calculateNewWindowParams(PWINDOWINARR);
|
|
|
|
|
|
|
|
// Set real size. No animations in the beginning. Maybe later. TODO?
|
|
|
|
PWINDOWINARR->setRealPosition(PWINDOWINARR->getEffectivePosition());
|
|
|
|
PWINDOWINARR->setRealSize(PWINDOWINARR->getEffectiveSize());
|
|
|
|
|
|
|
|
Debug::log(LOG, "Created a new tiled window! X: " + std::to_string(PWINDOWINARR->getPosition().x) + ", Y: " + std::to_string(PWINDOWINARR->getPosition().y) + ", W: " + std::to_string(PWINDOWINARR->getSize().x) + ", H:" + std::to_string(PWINDOWINARR->getSize().y) + " ID: " + std::to_string(windowID));
|
2021-11-18 18:04:09 +01:00
|
|
|
|
|
|
|
// Set map values
|
2021-11-20 09:25:21 +01:00
|
|
|
g_pWindowManager->Values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE;
|
2021-11-22 21:20:32 +01:00
|
|
|
xcb_change_window_attributes_checked(g_pWindowManager->DisplayConnection, windowID, XCB_CW_EVENT_MASK, g_pWindowManager->Values);
|
|
|
|
|
2021-12-06 19:43:01 +01:00
|
|
|
// make the last window top (animations look better)
|
|
|
|
g_pWindowManager->setAWindowTop(g_pWindowManager->LastWindow);
|
|
|
|
|
|
|
|
// Focus
|
2021-11-22 21:20:32 +01:00
|
|
|
g_pWindowManager->setFocusedWindow(windowID);
|
|
|
|
|
2021-11-23 17:43:27 +01:00
|
|
|
// Make all floating windows above
|
|
|
|
g_pWindowManager->setAllFloatingWindowsTop();
|
2021-11-22 21:20:32 +01:00
|
|
|
|
2021-12-04 23:16:24 +01:00
|
|
|
return PWINDOWINARR;
|
2021-11-22 21:20:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Events::eventMapWindow(xcb_generic_event_t* event) {
|
|
|
|
const auto E = reinterpret_cast<xcb_map_request_event_t*>(event);
|
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
// let bar check if it wasnt a tray item
|
|
|
|
if (g_pWindowManager->statusBar)
|
|
|
|
g_pWindowManager->statusBar->ensureTrayClientHidden(E->window, false);
|
|
|
|
|
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
// Map the window
|
|
|
|
xcb_map_window(g_pWindowManager->DisplayConnection, E->window);
|
|
|
|
|
2021-11-27 13:28:30 +01:00
|
|
|
// make sure it's not the bar!
|
|
|
|
if (E->window == g_pWindowManager->barWindowID)
|
|
|
|
return;
|
|
|
|
|
2021-11-23 22:15:36 +01:00
|
|
|
// 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
|
2021-11-28 11:52:40 +01:00
|
|
|
|
|
|
|
CWindow* pNewWindow = nullptr;
|
2021-11-23 22:15:36 +01:00
|
|
|
if (g_pWindowManager->shouldBeFloatedOnInit(E->window)) {
|
2021-11-24 18:37:45 +01:00
|
|
|
Debug::log(LOG, "Window SHOULD be floating on start.");
|
2021-11-28 11:52:40 +01:00
|
|
|
pNewWindow = remapFloatingWindow(E->window);
|
2021-11-23 22:15:36 +01:00
|
|
|
} else {
|
2021-11-24 18:37:45 +01:00
|
|
|
Debug::log(LOG, "Window should NOT be floating on start.");
|
2021-11-28 11:52:40 +01:00
|
|
|
pNewWindow = remapWindow(E->window);
|
2021-11-23 22:15:36 +01:00
|
|
|
}
|
2021-11-28 11:52:40 +01:00
|
|
|
|
|
|
|
if (!pNewWindow)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Do post-creation checks.
|
|
|
|
g_pWindowManager->doPostCreationChecks(pNewWindow);
|
2021-11-30 16:43:28 +01:00
|
|
|
|
|
|
|
// Do ICCCM
|
|
|
|
g_pWindowManager->getICCCMWMProtocols(pNewWindow);
|
2021-11-19 20:20:05 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 15:25:57 +01:00
|
|
|
void Events::eventButtonPress(xcb_generic_event_t* event) {
|
2021-11-22 21:20:32 +01:00
|
|
|
const auto E = reinterpret_cast<xcb_button_press_event_t*>(event);
|
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
// mouse down!
|
|
|
|
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_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
|
|
|
|
g_pWindowManager->Screen->root, XCB_NONE, XCB_CURRENT_TIME);
|
|
|
|
|
|
|
|
if (const auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); PLASTWINDOW) {
|
|
|
|
if (PLASTWINDOW->getIsFloating()) {
|
|
|
|
g_pWindowManager->actingOnWindowFloating = PLASTWINDOW->getDrawable();
|
|
|
|
g_pWindowManager->mouseLastPos = g_pWindowManager->getCursorPos();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Events::eventButtonRelease(xcb_generic_event_t* event) {
|
|
|
|
const auto E = reinterpret_cast<xcb_button_release_event_t*>(event);
|
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
// ungrab the mouse ptr
|
|
|
|
xcb_ungrab_pointer(g_pWindowManager->DisplayConnection, XCB_CURRENT_TIME);
|
|
|
|
const auto PACTINGWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->actingOnWindowFloating);
|
|
|
|
if (PACTINGWINDOW)
|
|
|
|
PACTINGWINDOW->setDirty(true);
|
|
|
|
g_pWindowManager->actingOnWindowFloating = 0;
|
|
|
|
g_pWindowManager->mouseKeyDown = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Events::eventKeyPress(xcb_generic_event_t* event) {
|
2021-11-19 20:20:05 +01:00
|
|
|
const auto E = reinterpret_cast<xcb_key_press_event_t*>(event);
|
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-19 20:20:05 +01:00
|
|
|
const auto KEYSYM = KeybindManager::getKeysymFromKeycode(E->detail);
|
|
|
|
|
|
|
|
for (auto& keybind : KeybindManager::keybinds) {
|
2021-12-06 15:04:47 +01:00
|
|
|
if (keybind.getKeysym() != 0 && keybind.getKeysym() == KEYSYM && keybind.getMod() == E->state) {
|
2021-11-19 20:20:05 +01:00
|
|
|
keybind.getDispatcher()(keybind.getCommand());
|
2021-11-21 19:59:59 +01:00
|
|
|
return;
|
|
|
|
// TODO: fix duplicating keybinds
|
2021-11-19 20:20:05 +01:00
|
|
|
}
|
|
|
|
}
|
2021-11-21 11:25:26 +01:00
|
|
|
}
|
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
void Events::eventMotionNotify(xcb_generic_event_t* event) {
|
|
|
|
const auto E = reinterpret_cast<xcb_motion_notify_event_t*>(event);
|
|
|
|
|
2021-12-06 18:56:24 +01:00
|
|
|
RETURNIFBAR;
|
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
if (!g_pWindowManager->mouseKeyDown)
|
|
|
|
return; // mouse up.
|
|
|
|
|
|
|
|
if (!g_pWindowManager->actingOnWindowFloating)
|
|
|
|
return; // not acting, return.
|
|
|
|
|
|
|
|
// means we are holding super
|
|
|
|
const auto POINTERPOS = g_pWindowManager->getCursorPos();
|
|
|
|
const auto POINTERDELTA = Vector2D(POINTERPOS) - g_pWindowManager->mouseLastPos;
|
|
|
|
|
|
|
|
const auto PACTINGWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->actingOnWindowFloating);
|
|
|
|
|
|
|
|
if (!PACTINGWINDOW) {
|
|
|
|
Debug::log(ERR, "ActingWindow not null but doesn't exist?? (Died?)");
|
|
|
|
g_pWindowManager->actingOnWindowFloating = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (abs(POINTERDELTA.x) < 1 && abs(POINTERDELTA.y) < 1)
|
|
|
|
return; // micromovements
|
|
|
|
|
|
|
|
if (g_pWindowManager->mouseKeyDown == 1) {
|
|
|
|
// moving
|
|
|
|
PACTINGWINDOW->setPosition(PACTINGWINDOW->getPosition() + POINTERDELTA);
|
|
|
|
PACTINGWINDOW->setEffectivePosition(PACTINGWINDOW->getPosition());
|
|
|
|
PACTINGWINDOW->setDefaultPosition(PACTINGWINDOW->getPosition());
|
2021-11-23 18:48:03 +01:00
|
|
|
PACTINGWINDOW->setRealPosition(PACTINGWINDOW->getPosition());
|
2021-11-22 21:20:32 +01:00
|
|
|
|
|
|
|
// update workspace if needed
|
|
|
|
if (g_pWindowManager->getMonitorFromCursor()) {
|
|
|
|
const auto WORKSPACE = g_pWindowManager->activeWorkspaces[g_pWindowManager->getMonitorFromCursor()->ID];
|
|
|
|
PACTINGWINDOW->setWorkspaceID(WORKSPACE);
|
|
|
|
} else {
|
|
|
|
PACTINGWINDOW->setWorkspaceID(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
PACTINGWINDOW->setDirty(true);
|
|
|
|
} else if (g_pWindowManager->mouseKeyDown == 3) {
|
|
|
|
// resizing
|
|
|
|
PACTINGWINDOW->setSize(PACTINGWINDOW->getSize() + POINTERDELTA);
|
|
|
|
// clamp
|
|
|
|
PACTINGWINDOW->setSize(Vector2D(std::clamp(PACTINGWINDOW->getSize().x, (double)30, (double)999999), std::clamp(PACTINGWINDOW->getSize().y, (double)30, (double)999999)));
|
|
|
|
|
|
|
|
// apply to other
|
|
|
|
PACTINGWINDOW->setDefaultSize(PACTINGWINDOW->getSize());
|
|
|
|
PACTINGWINDOW->setEffectiveSize(PACTINGWINDOW->getSize());
|
2021-11-23 18:48:03 +01:00
|
|
|
PACTINGWINDOW->setRealSize(PACTINGWINDOW->getSize());
|
2021-11-22 21:20:32 +01:00
|
|
|
|
|
|
|
PACTINGWINDOW->setDirty(true);
|
|
|
|
}
|
2021-11-21 15:25:57 +01:00
|
|
|
|
2021-11-22 21:20:32 +01:00
|
|
|
g_pWindowManager->mouseLastPos = POINTERPOS;
|
2021-11-21 15:25:57 +01:00
|
|
|
}
|
|
|
|
|
2021-11-21 11:25:26 +01:00
|
|
|
void Events::eventExpose(xcb_generic_event_t* event) {
|
|
|
|
const auto E = reinterpret_cast<xcb_expose_event_t*>(event);
|
|
|
|
|
2021-11-27 13:28:30 +01:00
|
|
|
// nothing
|
2021-12-06 18:56:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-18 18:04:09 +01:00
|
|
|
}
|