From 8f172a4e55506548012aa6785191bc34d9f3fca0 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 24 Nov 2021 18:37:45 +0100 Subject: [PATCH] Added some simple checks for windows that shouldnt be tiled --- src/defines.hpp | 7 +++- src/events/events.cpp | 32 ++++++++++++++++--- src/main.cpp | 13 ++++++++ src/utilities/Util.cpp | 15 +++++++++ src/utilities/Util.hpp | 1 + src/utilities/XCBProps.cpp | 46 +++++++++++++++++++++++++++ src/utilities/XCBProps.hpp | 8 +++++ src/windowManager.cpp | 65 +++++++++++++++++++++++--------------- src/windowManager.hpp | 62 ++++++++++++++++++++++++++++++++++++ 9 files changed, 218 insertions(+), 31 deletions(-) create mode 100644 src/utilities/XCBProps.cpp create mode 100644 src/utilities/XCBProps.hpp diff --git a/src/defines.hpp b/src/defines.hpp index a5635c6..de0e02c 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "./helpers/Vector.hpp" #include "./utilities/Debug.hpp" @@ -50,4 +51,8 @@ #define VECTORDELTANONZERO(veca, vecb) ((int)abs(veca.x - vecb.x) > 0 || (int)abs(veca.y - vecb.y) > 0) #define PROP(cookie, name, len) const auto cookie = xcb_get_property(DisplayConnection, false, window, name, XCB_GET_PROPERTY_TYPE_ANY, 0, len); \ - const auto cookie##reply = xcb_get_property_reply(DisplayConnection, cookie, NULL) \ No newline at end of file + const auto cookie##reply = xcb_get_property_reply(DisplayConnection, cookie, NULL) + + + +#define HYPRATOM(name) {name, 0} \ No newline at end of file diff --git a/src/events/events.cpp b/src/events/events.cpp index a5b1820..14059e7 100644 --- a/src/events/events.cpp +++ b/src/events/events.cpp @@ -60,8 +60,19 @@ CWindow* Events::remapFloatingWindow(int windowID) { window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]); window.setMonitor(CURRENTSCREEN); - window.setDefaultPosition(Vector2D(0, 0)); - window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels / 2.f, g_pWindowManager->Screen->height_in_pixels / 2.f)); + // 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) { + 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)); + } // Also sets the old one g_pWindowManager->calculateNewWindowParams(&window); @@ -101,8 +112,19 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating) { window.setWorkspaceID(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]); window.setMonitor(CURRENTSCREEN); - window.setDefaultPosition(Vector2D(0, 0)); - window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels / 2.f, g_pWindowManager->Screen->height_in_pixels / 2.f)); + // 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) { + 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)); + } // Set the parent // check if lastwindow is on our workspace @@ -188,8 +210,10 @@ void Events::eventMapWindow(xcb_generic_event_t* event) { // 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 if (g_pWindowManager->shouldBeFloatedOnInit(E->window)) { + Debug::log(LOG, "Window SHOULD be floating on start."); remapFloatingWindow(E->window); } else { + Debug::log(LOG, "Window should NOT be floating on start."); remapWindow(E->window); } } diff --git a/src/main.cpp b/src/main.cpp index f435ab8..72485f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,19 @@ int main(int argc, char** argv) { return 1; } + // get atoms + for (auto& ATOM : HYPRATOMS) { + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(g_pWindowManager->DisplayConnection, 0, ATOM.first.length(), ATOM.first.c_str()); + xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(g_pWindowManager->DisplayConnection, cookie, NULL); + + if (!reply) { + Debug::log(ERR, "Atom failed: " + ATOM.first); + continue; + } + + ATOM.second = reply->atom; + } + g_pWindowManager->setupManager(); Debug::log(LOG, "Hypr Started!"); diff --git a/src/utilities/Util.cpp b/src/utilities/Util.cpp index f999b77..8e6ffc7 100644 --- a/src/utilities/Util.cpp +++ b/src/utilities/Util.cpp @@ -39,4 +39,19 @@ void emptyEvent() { exposeEvent.height = g_pWindowManager->Screen->height_in_pixels; xcb_send_event(g_pWindowManager->DisplayConnection, false, g_pWindowManager->Screen->root, XCB_EVENT_MASK_EXPOSURE, (char*)&exposeEvent); xcb_flush(g_pWindowManager->DisplayConnection); +} + +bool xcbContainsAtom(xcb_get_property_reply_t* PROP, xcb_atom_t ATOM) { + if (PROP == NULL || xcb_get_property_value_length(PROP) == 0) + return false; + + const auto ATOMS = (xcb_atom_t*)xcb_get_property_value(PROP); + if (!ATOMS) + return false; + + for (int i = 0; i < xcb_get_property_value_length(PROP) / (PROP->format / 8); ++i) + if (ATOMS[i] == ATOM) + return true; + + return false; } \ No newline at end of file diff --git a/src/utilities/Util.hpp b/src/utilities/Util.hpp index f8373f0..4791022 100644 --- a/src/utilities/Util.hpp +++ b/src/utilities/Util.hpp @@ -6,5 +6,6 @@ std::string exec(const char* cmd); void clearLogs(); void emptyEvent(); +bool xcbContainsAtom(xcb_get_property_reply_t* PROP, xcb_atom_t ATOM); double parabolic(double from, double to, double incline); \ No newline at end of file diff --git a/src/utilities/XCBProps.cpp b/src/utilities/XCBProps.cpp new file mode 100644 index 0000000..9239f06 --- /dev/null +++ b/src/utilities/XCBProps.cpp @@ -0,0 +1,46 @@ +#include "XCBProps.hpp" + +#include "../windowManager.hpp" + +#define DisplayConnection g_pWindowManager->DisplayConnection + +std::pair getClassName(int64_t window) { + PROP(class_cookie, XCB_ATOM_WM_CLASS, 128); + + const size_t PROPLEN = xcb_get_property_value_length(class_cookiereply); + char* NEWCLASS = (char*)xcb_get_property_value(class_cookiereply); + const size_t CLASSNAMEINDEX = strnlen(NEWCLASS, PROPLEN) + 1; + + const char* CLASSINSTANCE = strndup(NEWCLASS, PROPLEN); + const char* CLASSNAME; + if (CLASSNAMEINDEX < PROPLEN) { + CLASSNAME = strndup(NEWCLASS + CLASSNAMEINDEX, PROPLEN - CLASSNAMEINDEX); + } else { + CLASSNAME = ""; + } + + free(class_cookiereply); + + return std::make_pair<>(std::string(CLASSINSTANCE), std::string(CLASSNAME)); +} + +std::string getRoleName(int64_t window) { + PROP(role_cookie, HYPRATOMS["WM_WINDOW_ROLE"], 128); + + std::string returns = ""; + + if (role_cookiereply == NULL || xcb_get_property_value_length(role_cookiereply)) { + Debug::log(ERR, "Role reply was invalid!"); + } else { + // get the role + + char* role; + asprintf(&role, "%.*s", xcb_get_property_value_length(role_cookiereply), (char*)xcb_get_property_value(role_cookiereply)); + + returns = role; + } + + free(role_cookiereply); + + return returns; +} \ No newline at end of file diff --git a/src/utilities/XCBProps.hpp b/src/utilities/XCBProps.hpp new file mode 100644 index 0000000..67d6c99 --- /dev/null +++ b/src/utilities/XCBProps.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + + +std::pair getClassName(int64_t window); +std::string getRoleName(int64_t window); \ No newline at end of file diff --git a/src/windowManager.cpp b/src/windowManager.cpp index d6dd235..b290372 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -935,44 +935,57 @@ void CWindowManager::setAllFloatingWindowsTop() { bool CWindowManager::shouldBeFloatedOnInit(int64_t window) { // Should be floated also sets some properties - const auto GEOMETRY = xcb_get_geometry(DisplayConnection, window); - xcb_get_geometry_reply_t* geom; - const auto WINDOWATTRCOOKIE = xcb_get_window_attributes(DisplayConnection, window); - const auto ATTRIBUTES = xcb_get_window_attributes_reply(DisplayConnection, WINDOWATTRCOOKIE, 0); - - - PROP(transient_cookie, XCB_ATOM_WM_TRANSIENT_FOR, UINT32_MAX); - PROP(title_cookie, XCB_ATOM_WM_NAME, 128); - PROP(class_cookie, XCB_ATOM_WM_CLASS, 128); - PROP(wm_machine_cookie, XCB_ATOM_WM_CLIENT_MACHINE, UINT32_MAX); - + // get stuffza // floating for krunner // TODO: config this - const size_t PROPLEN = xcb_get_property_value_length(class_cookiereply); - char* NEWCLASS = (char*)xcb_get_property_value(class_cookiereply); - const size_t CLASSNAMEINDEX = strnlen(NEWCLASS, PROPLEN) + 1; - - const char* CLASSINSTANCE = strndup(NEWCLASS, PROPLEN); - const char* CLASSNAME; - if (CLASSNAMEINDEX < PROPLEN) { - CLASSNAME = strndup(NEWCLASS + CLASSNAMEINDEX, PROPLEN - CLASSNAMEINDEX); - } else { - CLASSNAME = ""; - } + + const auto WINCLASS = getClassName(window); + const auto CLASSNAME = WINCLASS.second; + const auto CLASSINSTANCE = WINCLASS.first; Debug::log(LOG, "New window got class " + (std::string)CLASSINSTANCE + " -> " + CLASSNAME); - free(class_cookiereply); - xcb_change_property(DisplayConnection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen("hypr"), "hypr"); - // TODO: add a role cookie, somehow. - if (((std::string)CLASSNAME).find("krunner") != std::string::npos) { return true; } + + // Role stuff + const auto WINROLE = getRoleName(window); + + Debug::log(LOG, "Window opened with a role of " + WINROLE); + + if (WINROLE.find("pop-up") != std::string::npos || WINROLE.find("task_dialog") != std::string::npos) { + return true; + } + + // + // Type stuff + // + PROP(wm_type_cookie, HYPRATOMS["_NET_WM_WINDOW_TYPE"], UINT32_MAX); + 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_NOTIFICATION"])) { + free(wm_type_cookiereply); + return true; + } + } + } + free(wm_type_cookiereply); + // + // + // + return false; } \ No newline at end of file diff --git a/src/windowManager.hpp b/src/windowManager.hpp index 08cbf9c..4cc91fa 100644 --- a/src/windowManager.hpp +++ b/src/windowManager.hpp @@ -14,6 +14,7 @@ #include "utilities/Monitor.hpp" #include "utilities/Util.hpp" #include "utilities/AnimationUtil.hpp" +#include "utilities/XCBProps.hpp" class CWindowManager { public: @@ -99,3 +100,64 @@ public: }; inline std::unique_ptr g_pWindowManager = std::make_unique(); + +inline std::map HYPRATOMS = { + HYPRATOM("_NET_SUPPORTED"), + HYPRATOM("_NET_SUPPORTING_WM_CHECK"), + HYPRATOM("_NET_WM_NAME"), + HYPRATOM("_NET_WM_VISIBLE_NAME"), + HYPRATOM("_NET_WM_MOVERESIZE"), + HYPRATOM("_NET_WM_STATE_STICKY"), + HYPRATOM("_NET_WM_STATE_FULLSCREEN"), + HYPRATOM("_NET_WM_STATE_DEMANDS_ATTENTION"), + HYPRATOM("_NET_WM_STATE_MODAL"), + HYPRATOM("_NET_WM_STATE_HIDDEN"), + HYPRATOM("_NET_WM_STATE_FOCUSED"), + HYPRATOM("_NET_WM_STATE"), + HYPRATOM("_NET_WM_WINDOW_TYPE"), + HYPRATOM("_NET_WM_WINDOW_TYPE_NORMAL"), + HYPRATOM("_NET_WM_WINDOW_TYPE_DOCK"), + HYPRATOM("_NET_WM_WINDOW_TYPE_DIALOG"), + HYPRATOM("_NET_WM_WINDOW_TYPE_UTILITY"), + HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLBAR"), + HYPRATOM("_NET_WM_WINDOW_TYPE_SPLASH"), + HYPRATOM("_NET_WM_WINDOW_TYPE_MENU"), + HYPRATOM("_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"), + HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"), + HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"), + HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION"), + HYPRATOM("_NET_WM_DESKTOP"), + HYPRATOM("_NET_WM_STRUT_PARTIAL"), + HYPRATOM("_NET_CLIENT_LIST"), + HYPRATOM("_NET_CLIENT_LIST_STACKING"), + HYPRATOM("_NET_CURRENT_DESKTOP"), + HYPRATOM("_NET_NUMBER_OF_DESKTOPS"), + HYPRATOM("_NET_DESKTOP_NAMES"), + HYPRATOM("_NET_DESKTOP_VIEWPORT"), + HYPRATOM("_NET_ACTIVE_WINDOW"), + HYPRATOM("_NET_CLOSE_WINDOW"), + HYPRATOM("_NET_MOVERESIZE_WINDOW"), + HYPRATOM("_NET_WM_USER_TIME"), + HYPRATOM("_NET_STARTUP_ID"), + HYPRATOM("_NET_WORKAREA"), + HYPRATOM("_NET_WM_ICON"), + HYPRATOM("WM_PROTOCOLS"), + HYPRATOM("WM_DELETE_WINDOW"), + HYPRATOM("UTF8_STRING"), + HYPRATOM("WM_STATE"), + HYPRATOM("WM_CLIENT_LEADER"), + HYPRATOM("WM_TAKE_FOCUS"), + 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_FRAME_EXTENTS"), + HYPRATOM("_MOTIF_WM_HINTS"), + HYPRATOM("WM_CHANGE_STATE"), + HYPRATOM("MANAGER") +};