From 9f876c8714b84d3bb7ae1a65f470e5eaa83fc54d Mon Sep 17 00:00:00 2001 From: Paul Breugnot Date: Wed, 1 Jan 2025 18:20:38 +0100 Subject: [PATCH] :bug: Fixes unmap + analysis of various properties --- CMakeLists.txt | 1 + src/aswm/aswm.c | 9 ++-- src/aswm/event_handlers/create.c | 6 +++ src/aswm/event_handlers/map.c | 3 +- src/aswm/event_handlers/property.c | 68 ++++++++++++++++++++++++++++++ src/aswm/event_handlers/property.h | 7 +++ src/aswm/event_handlers/unmap.c | 20 ++++++--- src/aswm/log/log.c | 18 ++++++-- src/aswm/log/log.h | 3 +- 9 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 src/aswm/event_handlers/property.c create mode 100644 src/aswm/event_handlers/property.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 404a449..e5764da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ add_executable(aswm src/aswm/event_handlers/destroy.c src/aswm/event_handlers/map.c src/aswm/event_handlers/unmap.c + src/aswm/event_handlers/property.c src/aswm/log/log.c ) target_include_directories(aswm PUBLIC ${X11_INCLUDE_DIR} src) diff --git a/src/aswm/aswm.c b/src/aswm/aswm.c index 3144d3b..129d50d 100644 --- a/src/aswm/aswm.c +++ b/src/aswm/aswm.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include "aswm.h" #include "event_handlers/create.h" #include "event_handlers/configure.h" @@ -7,6 +9,7 @@ #include "event_handlers/unmap.h" #include "event_handlers/reparent.h" #include "event_handlers/destroy.h" +#include "event_handlers/property.h" #include "log/error.h" Aswm _aswm; @@ -125,11 +128,9 @@ void aswm_event_loop() { XFree(atom_name); break; case PropertyNotify: + OnPropertyNotify(&_aswm, &e.xproperty); // TODO: handle this - printf("Unhandled property change for window %lu:\n", e.xclient.window); - char* property_name = XGetAtomName(e.xclient.display, e.xclient.message_type); - printf("\t%s\n", property_name); - XFree(property_name); + default: break; /* LOG(WARNING) << "Ignored event"; */ diff --git a/src/aswm/event_handlers/create.c b/src/aswm/event_handlers/create.c index 5dec25d..a3e16df 100644 --- a/src/aswm/event_handlers/create.c +++ b/src/aswm/event_handlers/create.c @@ -11,6 +11,12 @@ void OnCreateNotify(Aswm* aswm, const XCreateWindowEvent* e) { printf("\th = %i\n", e->height); printf("\toverride_redirect = %i\n", e->override_redirect); + XWMHints* hints = XGetWMHints(aswm->display, e->window); + if(hints != NULL) { + printf("\tWM_HINTS\n"); + printf("\t\tinitial_state: %i\n", hints->initial_state); + } + // The WM must subscribe to property changes, notably to implement the // Extended Window Manager Hints (EWMH) propocol XSelectInput(aswm->display, e->window, PropertyChangeMask); diff --git a/src/aswm/event_handlers/map.c b/src/aswm/event_handlers/map.c index 954cf2c..ba74771 100644 --- a/src/aswm/event_handlers/map.c +++ b/src/aswm/event_handlers/map.c @@ -17,11 +17,12 @@ void OnMapRequest(Aswm* aswm, const XMapRequestEvent* e) { /* printf("\t\tBase w:%i\n", size->base_width); */ /* printf("\t\tBase h:%i\n", size->base_height); */ /* } */ + /* XFree(size); */ // Assumes map requests are always received on root and adressed to the // current workspace aswm_map_new_window(e->display, aswm->current_workspace, e->window); printf("Map tree:\n"); - log_tree(aswm->display, DefaultRootWindow(aswm->display), 1); + log_tree(aswm, DefaultRootWindow(aswm->display), 1); } diff --git a/src/aswm/event_handlers/property.c b/src/aswm/event_handlers/property.c new file mode 100644 index 0000000..fc628b2 --- /dev/null +++ b/src/aswm/event_handlers/property.c @@ -0,0 +1,68 @@ +#include "property.h" +#include +#include +#include +#include + +void OnPropertyNotify(Aswm* aswm, XPropertyEvent* e) { + printf("Unhandled property change for window %lu:\n", e->window); + char* property_name = XGetAtomName(e->display, e->atom); + printf("\t%s\n", property_name); + if(strcmp(property_name, "_NET_WM_NAME") == 0) { + XTextProperty wm_name_property; + char** wm_name; + int wm_name_count; + XGetTextProperty(e->display, e->window, &wm_name_property, e->atom); + Xutf8TextPropertyToTextList(e->display, &wm_name_property, &wm_name, &wm_name_count); + for(auto i = 0; i < wm_name_count; i++) + printf("\t_NET_WM_NAME: %s\n", wm_name[i]); + XFreeStringList(wm_name); + } else if(strcmp(property_name, "WM_NAME") == 0) { + XTextProperty text_property; + if(XGetWMName(e->display, e->window, &text_property)) { + printf("\tWM_NAME: %s\n", text_property.value); + } + } else if(strcmp(property_name, "WM_NORMAL_HINTS") == 0) { + XSizeHints* size = XAllocSizeHints(); + long supplied; + if(XGetWMNormalHints(e->display, e->window, size, &supplied)) { + printf("\tWMNormalHints:\n"); + printf("\t\tMin w:%i\n", size->min_width); + printf("\t\tMin h:%i\n", size->min_height); + printf("\t\tMax w:%i\n", size->max_width); + printf("\t\tMax h:%i\n", size->max_height); + printf("\t\tBase w:%i\n", size->base_width); + printf("\t\tBase h:%i\n", size->base_height); + } + XFree(size); + } else if(strcmp(property_name, "WM_HINTS") == 0) { + XWMHints* hints = XGetWMHints(aswm->display, e->window); + printf("\t\tflags Input: %li\n", hints->flags & InputHint); + printf("\t\tflags Input: %li\n", hints->flags & StateHint); + printf("\t\tflags IconPixmap: %li\n", hints->flags & IconPixmapHint); + printf("\t\tflags WindowHint: %li\n", hints->flags & IconWindowHint); + printf("\t\tflags IconPosition: %li\n", hints->flags & IconPositionHint); + printf("\t\tflags IconMask: %li\n", hints->flags & IconMaskHint); + printf("\t\tflags WindowGroup: %li\n", hints->flags & WindowGroupHint); + printf("\t\tflags XUrgency: %li\n", hints->flags & XUrgencyHint); + printf("\t\tflags AllHints: %li\n", hints->flags & AllHints); + printf("\t\tinitial_state: %i\n", hints->initial_state); + XFree(hints); + } else if(strcmp(property_name, "WM_PROTOCOLS") == 0) { + Atom* protocols; + int count; + XGetWMProtocols(aswm->display, e->window, &protocols, &count); + if(count > 0) + printf("\t\t"); + for(auto i = 0; i < count; i++) { + char* name = XGetAtomName(aswm->display, protocols[i]); + printf("%s ", name); + XFree(name); + } + if(count > 0) + printf("\n"); + XFree(protocols); + + } + XFree(property_name); +} diff --git a/src/aswm/event_handlers/property.h b/src/aswm/event_handlers/property.h new file mode 100644 index 0000000..8915cfa --- /dev/null +++ b/src/aswm/event_handlers/property.h @@ -0,0 +1,7 @@ +#ifndef ASWM_PROPERTY +#define ASWM_PROPERTY + +#include "aswm/aswm.h" + +void OnPropertyNotify(Aswm* aswm, XPropertyEvent* e); +#endif diff --git a/src/aswm/event_handlers/unmap.c b/src/aswm/event_handlers/unmap.c index 6faa3b3..6af785b 100644 --- a/src/aswm/event_handlers/unmap.c +++ b/src/aswm/event_handlers/unmap.c @@ -1,17 +1,23 @@ #include "unmap.h" #include #include "aswm/log/log.h" +#include void OnUnmapNotify(Aswm* aswm, const XUnmapEvent* e) { printf("XUnmapWindow %lu tiled in %lu\n", e->window, e->event); - /* printf("ES-DE window %lu\n", aswm->es_de_window); */ - /* if(aswm->es_de_window != None) */ - /* XSetInputFocus(e->display, aswm->es_de_window, RevertToPointerRoot, CurrentTime); */ + XWMHints* hints = XGetWMHints(aswm->display, e->window); + if(hints != NULL) { + printf("\tWM_HINTS\n"); + printf("\t\tinitial_state: %i\n", hints->initial_state); + } // Since SubstructureNotify is selected on each frame, e->event corresponds // to the parent of the unmapped window (e->window) - // Only handles request that refer to the ASWM window hierarchy - aswm_unmap_window(e->display, e->event, e->window); - printf("Unmap tree:\n"); - log_tree(aswm->display, DefaultRootWindow(aswm->display), 1); + // Unmap should have no effect on not map windows. Currently, all mapped + // windows are children of aswm->root_window. + if(e->event != XDefaultRootWindow(e->display)) { + aswm_unmap_window(e->display, e->event, e->window); + printf("Unmap tree:\n"); + log_tree(aswm, DefaultRootWindow(aswm->display), 1); + } } diff --git a/src/aswm/log/log.c b/src/aswm/log/log.c index f08ef2b..e267eca 100644 --- a/src/aswm/log/log.c +++ b/src/aswm/log/log.c @@ -1,17 +1,27 @@ #include "log.h" #include -void log_tree(Display* display, Window window, int indent) { +void log_tree(Aswm* aswm, Window window, int indent) { + XWindowAttributes window_attributes; + XGetWindowAttributes(aswm->display, window, &window_attributes); for(int i = 0; i < indent; i++) printf(" "); - printf("%lu\n", window); + printf("%lu ", window); + if(window == XDefaultRootWindow(aswm->display)) { + printf("(X root) "); + } else if (window == aswm->root_window) { + printf("(ASWM root) "); + } else if (window == aswm->current_workspace) { + printf("(current workspace) "); + } + printf("at (%i, %i): %ix%i\n", window_attributes.x, window_attributes.y, window_attributes.width, window_attributes.height); Window root_window; Window parent_tile; Window* children; unsigned int children_count; - XQueryTree(display, window, &root_window, &parent_tile, &children, &children_count); + XQueryTree(aswm->display, window, &root_window, &parent_tile, &children, &children_count); for(auto i = 0; i < children_count; i++) - log_tree(display, children[i], indent+1); + log_tree(aswm, children[i], indent+1); XFree(children); } diff --git a/src/aswm/log/log.h b/src/aswm/log/log.h index e58014a..1253e34 100644 --- a/src/aswm/log/log.h +++ b/src/aswm/log/log.h @@ -2,7 +2,8 @@ #define ASWM_LOG #include +#include "aswm/aswm.h" -void log_tree(Display* display, Window root, int indent); +void log_tree(Aswm* aswm, Window window, int indent); #endif