diff --git a/CMakeLists.txt b/CMakeLists.txt index e5764da..c110d25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,24 +1,17 @@ -cmake_minimum_required(VERSION 3.21) +cmake_minimum_required(VERSION 3.20) project(aswm) -set(CMAKE_C_STANDARD 23) - find_package(X11 REQUIRED) -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -pg") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address") add_executable(aswm - src/aswm/aswm.c - src/aswm/mapper/mapper.c - src/aswm/event_handlers/create.c - src/aswm/event_handlers/configure.c - src/aswm/event_handlers/reparent.c - 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) + src/main.c + src/create.c + src/configure.c + src/reparent.c + src/destroy.c + src/map.c) +target_include_directories(aswm PUBLIC ${X11_INCLUDE_DIR} include) target_link_libraries(aswm ${X11_LIBRARIES}) diff --git a/src/aswm/event_handlers/configure.h b/include/configure.h similarity index 100% rename from src/aswm/event_handlers/configure.h rename to include/configure.h diff --git a/include/create.h b/include/create.h new file mode 100644 index 0000000..3fc8812 --- /dev/null +++ b/include/create.h @@ -0,0 +1,3 @@ +#include + +void OnCreateNotify(const XCreateWindowEvent*); diff --git a/src/aswm/event_handlers/destroy.h b/include/destroy.h similarity index 100% rename from src/aswm/event_handlers/destroy.h rename to include/destroy.h diff --git a/include/map.h b/include/map.h new file mode 100644 index 0000000..e8638ca --- /dev/null +++ b/include/map.h @@ -0,0 +1,3 @@ +#include + +void OnMapRequest(Window root, const XMapRequestEvent* e); diff --git a/src/aswm/event_handlers/reparent.h b/include/reparent.h similarity index 100% rename from src/aswm/event_handlers/reparent.h rename to include/reparent.h diff --git a/include/unmap.h b/include/unmap.h new file mode 100644 index 0000000..f82fe1c --- /dev/null +++ b/include/unmap.h @@ -0,0 +1,3 @@ +#include + +void OnUnmapRequest(Window root, const XMapRequestEvent* e); diff --git a/src/aswm/aswm.c b/src/aswm/aswm.c deleted file mode 100644 index 5a27318..0000000 --- a/src/aswm/aswm.c +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include -#include -#include "aswm.h" -#include "event_handlers/create.h" -#include "event_handlers/configure.h" -#include "event_handlers/map.h" -#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; - - -void aswm_open() { - _aswm.display = XOpenDisplay(NULL); - _aswm.desktops = malloc(0); - _aswm.desktops_count = 0; - - XSetErrorHandler(aswm_error_handler); - - Window x_root_window = DefaultRootWindow(_aswm.display); - XWindowAttributes x_root_attributes; - XGetWindowAttributes(_aswm.display, x_root_window, &x_root_attributes); - - _aswm.root_window = XCreateSimpleWindow( - _aswm.display, x_root_window, - 0, 0, - x_root_attributes.width, - x_root_attributes.height, - 0, 0, 0); - - // User windows are created from the X root window, while ASWM specific - // windows are created on the ASWM root window - XSelectInput(_aswm.display, _aswm.root_window, FocusChangeMask | EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask); - - XSelectInput(_aswm.display, x_root_window, SubstructureRedirectMask | SubstructureNotifyMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask); - - XMapWindow(_aswm.display, _aswm.root_window); - XSync(_aswm.display, 0); - - printf("PointerRoot %lu\n", PointerRoot); - printf("Useful constants:\n"); - printf("\tNone: %lu\n", None); - printf("\tTrue / False: %i / %i\n", True, False); - printf("X Root window %lu\n", x_root_window); - printf("ASWM Root window %lu\n", _aswm.root_window); - - atexit(aswm_close); -} - -void aswm_create_workspace() { - _aswm.desktops = realloc(_aswm.desktops, (_aswm.desktops_count+1) * sizeof(Desktop)); - - XWindowAttributes root_attributes; - XGetWindowAttributes(_aswm.display, _aswm.root_window, &root_attributes); - - _aswm.desktops[_aswm.desktops_count].root_window = XCreateSimpleWindow( - _aswm.display, _aswm.root_window, - 0, 0, - root_attributes.width, root_attributes.height, - 0, 0, 0); - _aswm.desktops[_aswm.desktops_count].tile_root = XCreateSimpleWindow( - _aswm.display, _aswm.desktops[_aswm.desktops_count].root_window, - 0, 0, - root_attributes.width, root_attributes.height, - 0, 0, 0); - _aswm.desktops[_aswm.desktops_count].stack_root = XCreateSimpleWindow( - _aswm.display, _aswm.desktops[_aswm.desktops_count].root_window, - 0, 0, - root_attributes.width, root_attributes.height, - 0, 0, 0); - - _aswm.current_desktop = _aswm.desktops[_aswm.desktops_count]; - _aswm.desktops_count++; - XSelectInput(_aswm.display, _aswm.current_desktop.tile_root, SubstructureNotifyMask); - XSelectInput(_aswm.display, _aswm.current_desktop.stack_root, SubstructureNotifyMask); - XMapWindow(_aswm.display, _aswm.current_desktop.root_window); - XMapWindow(_aswm.display, _aswm.current_desktop.tile_root); - printf("Create workspace %lu\n", _aswm.current_desktop.root_window); -} - -void aswm_event_loop() { - for (;;) { - XEvent e; - XNextEvent(_aswm.display, &e); - - switch(e.type) { - case CreateNotify: - // Windows with override_redirect set to True can be safely - // ignored, according to the X server specification. - if(e.xcreatewindow.override_redirect == False) - OnCreateNotify(&_aswm, &e.xcreatewindow); - break; - case ConfigureRequest: - OnConfigureRequest(&e.xconfigurerequest); - break; - case MapRequest: - OnMapRequest(&_aswm, &e.xmaprequest); - break; - case UnmapNotify: - OnUnmapNotify(&_aswm, &e.xunmap); - break; - case DestroyNotify: - OnDestroyNotify(&e.xdestroywindow); - break; - case ReparentNotify: - OnReparentNotify(&e.xreparent); - break; - case FocusIn: - printf("FocusIn %lu\n", (&e.xfocus)->window); - break; - case FocusOut: - printf("FocusOut %lu\n", e.xfocus.window); - break; - case EnterNotify: - int revert_to; - Window window; - XGetInputFocus(e.xcrossing.display, &window, &revert_to); - printf("Enter %lu\n", e.xcrossing.window); - printf("Input focus %lu\n", window); - break; - case LeaveNotify: - printf("Leave %lu\n", e.xcrossing.window); - break; - case ButtonPress: - printf("Press %lu\n", e.xbutton.window); - break; - case ButtonRelease: - printf("Release %lu\n", e.xbutton.window); - break; - case ClientMessage: - // TODO: handle this - printf("Unhandled client message from window %lu:\n", e.xclient.window); - char* atom_name = XGetAtomName(e.xclient.display, e.xclient.message_type); - printf("\t%s\n", atom_name); - XFree(atom_name); - break; - case PropertyNotify: - OnPropertyNotify(&_aswm, &e.xproperty); - // TODO: handle this - - default: - break; - /* LOG(WARNING) << "Ignored event"; */ - } - } -} - -void aswm_close() { - free(_aswm.desktops); - XCloseDisplay(_aswm.display); -} - -int main(int argc, char** argv) { - aswm_open(); - aswm_event_loop(); - aswm_close(); -} diff --git a/src/aswm/aswm.h b/src/aswm/aswm.h deleted file mode 100644 index ce54b78..0000000 --- a/src/aswm/aswm.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef ASWM -#define ASWM - -#include "mapper/mapper.h" - -typedef struct { - Window root_window; - Window tile_root; - Window stack_root; -} Desktop; - -typedef struct { - Display *display; - Window root_window; - Desktop* desktops; - unsigned int desktops_count; - Desktop current_desktop; -} Aswm; - -void aswm_open(); -void aswm_create_workspace(); -void aswm_event_loop(); -void aswm_close(); - -int main(int argc, char** argv); - -#endif diff --git a/src/aswm/event_handlers/configure.c b/src/aswm/event_handlers/configure.c deleted file mode 100644 index 937211b..0000000 --- a/src/aswm/event_handlers/configure.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "configure.h" -#include - -void OnConfigureRequest(const XConfigureRequestEvent* e) { - printf("XConfigureRequestEvent %lu (ignored)\n", e->window); - printf("\tx = %i\n", e->x); - printf("\ty = %i\n", e->y); - printf("\tw = %i\n", e->width); - printf("\th = %i\n", e->height); -} diff --git a/src/aswm/event_handlers/create.c b/src/aswm/event_handlers/create.c deleted file mode 100644 index ee0d56c..0000000 --- a/src/aswm/event_handlers/create.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "create.h" -#include -#include -#include - -void OnCreateNotify(Aswm* aswm, const XCreateWindowEvent* e) { - printf("XCreateWindowEvent %lu on parent %lu\n", e->window, e->parent); - printf("\tx = %i\n", e->x); - printf("\ty = %i\n", e->y); - printf("\tw = %i\n", e->width); - 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); - - { - XTextProperty text_property; - if(XGetWMName(e->display, e->window, &text_property)) { - printf("\tname: %s\n", text_property.value); - } - } - { - XClassHint class; - if(XGetClassHint(e->display, e->window, &class)) { - printf("\tclass: %s, %s\n", class.res_class, class.res_name); - XFree(class.res_class); - XFree(class.res_name); - } - } - if(aswm->desktops_count == 0) - aswm_create_workspace(); -} diff --git a/src/aswm/event_handlers/create.h b/src/aswm/event_handlers/create.h deleted file mode 100644 index bc60d72..0000000 --- a/src/aswm/event_handlers/create.h +++ /dev/null @@ -1,4 +0,0 @@ -#include -#include "aswm/aswm.h" - -void OnCreateNotify(Aswm* aswm, const XCreateWindowEvent*); diff --git a/src/aswm/event_handlers/map.c b/src/aswm/event_handlers/map.c deleted file mode 100644 index 60d940a..0000000 --- a/src/aswm/event_handlers/map.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "map.h" -#include -#include "aswm/log/log.h" -#include "aswm/mapper/mapper.h" -#include "X11/Xutil.h" - -void OnMapRequest(Aswm* aswm, const XMapRequestEvent* e) { - printf("XMapRequestEvent %lu\n", e->window); - - XSizeHints* size = XAllocSizeHints(); - long supplied; - bool stacked = false; - if(XGetWMNormalHints(aswm->display, e->window, size, &supplied)) { - if((supplied & (PMinSize | PMaxSize)) && !aswm_is_resizeable(size)) { - 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); - aswm_stack_window(e->display, aswm->current_desktop.stack_root, e->window, size->max_width, size->max_height); - stacked = true; - } - } - XFree(size); - - if(!stacked) - aswm_tile_window(e->display, aswm->current_desktop.tile_root, e->window); - - printf("Map tree:\n"); - log_tree(aswm, DefaultRootWindow(aswm->display), 1); -} diff --git a/src/aswm/event_handlers/map.h b/src/aswm/event_handlers/map.h deleted file mode 100644 index 6270df5..0000000 --- a/src/aswm/event_handlers/map.h +++ /dev/null @@ -1,4 +0,0 @@ -#include -#include "aswm/aswm.h" - -void OnMapRequest(Aswm* aswm, const XMapRequestEvent* e); diff --git a/src/aswm/event_handlers/property.c b/src/aswm/event_handlers/property.c deleted file mode 100644 index be4c4db..0000000 --- a/src/aswm/event_handlers/property.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "property.h" -#include -#include -#include -#include -#include "aswm/mapper/mapper.h" - -void OnPropertyNotify(Aswm* aswm, XPropertyEvent* e) { - printf("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) { - printf("\t-> Unhandled\n"); - 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) { - printf("\t-> Unhandled\n"); - 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); - aswm_handle_normal_hints( - aswm->display, aswm->current_desktop.stack_root, - e->window, size, supplied); - } - XFree(size); - } else if(strcmp(property_name, "WM_HINTS") == 0) { - printf("\t-> Unhandled\n"); - 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) { - printf("\t-> Unhandled\n"); - 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); - - } else { - printf("\t-> Unhandled\n"); - } - XFree(property_name); -} diff --git a/src/aswm/event_handlers/property.h b/src/aswm/event_handlers/property.h deleted file mode 100644 index 8915cfa..0000000 --- a/src/aswm/event_handlers/property.h +++ /dev/null @@ -1,7 +0,0 @@ -#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 deleted file mode 100644 index c70bad2..0000000 --- a/src/aswm/event_handlers/unmap.c +++ /dev/null @@ -1,29 +0,0 @@ -#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); - 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) - - // 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)) { - if(e->event == aswm->current_desktop.tile_root) { - printf("aswm untile\n"); - aswm_untile_window(e->display, e->event, e->window); - } else if(e->event == aswm->current_desktop.stack_root) { - printf("aswm unstack\n"); - aswm_unstack_window(e->display, e->event); - } - printf("Unmap tree:\n"); - log_tree(aswm, DefaultRootWindow(aswm->display), 1); - } -} diff --git a/src/aswm/event_handlers/unmap.h b/src/aswm/event_handlers/unmap.h deleted file mode 100644 index 5f0aec4..0000000 --- a/src/aswm/event_handlers/unmap.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -#include "aswm/aswm.h" - -void OnUnmapNotify(Aswm* aswm, const XUnmapEvent* e); diff --git a/src/aswm/log/error.h b/src/aswm/log/error.h deleted file mode 100644 index fd00c24..0000000 --- a/src/aswm/log/error.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef ASWM_ERROR_H -#define ASWM_ERROR_H - -#include -#include - -char message_buffer[1024]; - -int aswm_error_handler( Display *disp, XErrorEvent *xe ) { - XGetErrorText(xe->display, xe->error_code, message_buffer, 1024); - printf("%s\n", message_buffer); - return 0; -} - -#endif diff --git a/src/aswm/log/log.c b/src/aswm/log/log.c deleted file mode 100644 index 0cdebac..0000000 --- a/src/aswm/log/log.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "log.h" -#include - -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 ", window); - if(window == XDefaultRootWindow(aswm->display)) { - printf("(X root) "); - } else if (window == aswm->root_window) { - printf("(ASWM root) "); - } else if (window == aswm->current_desktop.root_window) { - printf("(current workspace) "); - } else if (window == aswm->current_desktop.tile_root) { - printf("(tile root) "); - } else if (window == aswm->current_desktop.stack_root) { - printf("(stack root) "); - } - 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(aswm->display, window, &root_window, &parent_tile, &children, &children_count); - for(auto i = 0; i < children_count; i++) - log_tree(aswm, children[i], indent+1); - XFree(children); -} diff --git a/src/aswm/log/log.h b/src/aswm/log/log.h deleted file mode 100644 index 1253e34..0000000 --- a/src/aswm/log/log.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef ASWM_LOG -#define ASWM_LOG - -#include -#include "aswm/aswm.h" - -void log_tree(Aswm* aswm, Window window, int indent); - -#endif diff --git a/src/aswm/mapper/mapper.c b/src/aswm/mapper/mapper.c deleted file mode 100644 index 70f5049..0000000 --- a/src/aswm/mapper/mapper.c +++ /dev/null @@ -1,267 +0,0 @@ -#include -#include -#include "aswm/mapper/mapper.h" -#include "aswm/log/log.h" -#include - -bool aswm_is_resizeable(XSizeHints* size) { - return size->min_width != size->max_width - || size->min_height != size->max_height; -} - -/** - * Returns the free tile built in the split process. - */ -void h_split(Display* display, Window current_node, Window window_to_map); - -void aswm_tile_window(Display* display, Window current_node, Window window_to_map) { - h_split(display, current_node, window_to_map); -} - -void h_split(Display* display, Window current_tile, Window window_to_map) { - // Current: - // +--------------+ - // | current tile | - // | +--------+ | - // | | child | | - // | +--------+ | - // +--------------+ - // Target: - // +---------------+ - // | current tile | - // | +-----------+ | - // | | child | | - // | +-----------+ | - // | +-----------+ | - // | | free tile | | - // | +-----------+ | - // +---------------+ - - XWindowAttributes current_tile_attributes; - XGetWindowAttributes(display, current_tile, ¤t_tile_attributes); - - XReparentWindow(display, window_to_map, current_tile, 0, 0); - - Window _root_window; // unused - Window _parent_window; // unused - Window* children; - unsigned int children_count; - - XQueryTree(display, current_tile, &_root_window, &_parent_window, &children, &children_count); - - for(auto i = 0; i < children_count; i++) { - XMoveResizeWindow(display, children[i], - 0, i * current_tile_attributes.height / children_count, - current_tile_attributes.width, - current_tile_attributes.height / children_count); - } - XFree(children); - XMapWindow(display, window_to_map); -} - -void resize_children_to_parent(Display* display, Window parent) { - Window _root_window; // unused - Window _grand_parent; // unused - Window* children; - unsigned int children_count; - XQueryTree( - display, parent, - &_root_window, &_grand_parent, - &children, &children_count); - printf(" Resize children of %lu:\n", parent); - for(auto i = 0; i < children_count; i++) - printf("%lu ", children[i]); - printf("\n"); - - // Resize new children of the parent tile - XWindowAttributes parent_attributes; - XGetWindowAttributes(display, parent, &parent_attributes); - - for(auto i = 0; i < children_count; i++) { - // TODO: currently only hsplit supported - XMoveResizeWindow(display, children[i], - 0, - i * parent_attributes.height / children_count, - parent_attributes.width, - parent_attributes.height / children_count); - } - XFree(children); -} - -void aswm_untile_window(Display* display, Window parent, Window window) { - // +-------------------------------+ - // | root | - // |+-------------+ +-------------+| - // || parent | | || - // || +--------+ | | || - // || | win 1 | | | || - // || +--------+ | | || - // || +--------+ | | || - // || | del win| | | win 3 || - // || +--------+ | | || - // || +--------+ | | || - // || | win 2 | | | || - // || +--------+ | | || - // |+-------------+ +-------------+| - // +-------------------------------+ - - Window _root_window; // unused - Window _grand_parent; // unused - Window* children; - unsigned int children_count; - XQueryTree( - display, parent, - &_root_window, &_grand_parent, - &children, &children_count); - printf(" Current children of %lu:\n", parent); - for(auto i = 0; i < children_count; i++) - printf("%lu ", children[i]); - printf("\n"); - for(auto i = 0; i < children_count; i++) { - if(children[i] == window) - // If the unmap request does not come from a destroy window, we - // still want to remove the window from the ASWM hierarchy. It is - // the responsability of the client to decide to remap it latter or - // not. - XReparentWindow(display, window, XDefaultRootWindow(display), 0, 0); - } - - resize_children_to_parent(display, parent); -} - -/** - * Currently, resize to the max width and max height of any children, but should - * be reconsidered as it can create black square artifacts if the max width and - * height are not for the same window. - */ -void resize_stack(Display* display, Window stack) { - Window root; // unused - Window parent; - Window* children; - unsigned int children_count; - XQueryTree(display, stack, &root, &parent, &children, &children_count); - - unsigned int width = 0; - unsigned int height = 0; - for(auto i = 0; i < children_count; i++) { - XWindowAttributes child_attributes; - XGetWindowAttributes(display, children[i], &child_attributes); - if(child_attributes.map_state != IsUnmapped) { - if(child_attributes.width > width) - width = child_attributes.width; - if(child_attributes.height > height) - height = child_attributes.height; - } - } - - // The current method is always called when there is at least a child, so - // children is never NULL - XFree(children); - - XWindowAttributes parent_attributes; - XGetWindowAttributes(display, parent, &parent_attributes); - XMoveResizeWindow(display, stack, - (parent_attributes.width - width) / 2, - (parent_attributes.height - height) / 2, - width, height); -} - -void aswm_stack_window(Display* display, Window stack, Window window_to_map, int width, int height) { - XWindowAttributes stack_attributes; - XGetWindowAttributes(display, stack, &stack_attributes); - - XSetWindowAttributes stacked_attributes; - stack_attributes.width = width; - stack_attributes.height = height; - stack_attributes.win_gravity = CenterGravity; - XChangeWindowAttributes(display, window_to_map, - CWWidth | CWHeight | CWWinGravity, - &stacked_attributes); - XReparentWindow(display, window_to_map, stack, - (stack_attributes.width - width) / 2, - (stack_attributes.height - height) / 2 - ); - // Map before resize so window_to_map can be taken into account in resizing - // of stack - XMapWindow(display, window_to_map); - - resize_stack(display, stack); - - if(stack_attributes.map_state == IsUnmapped) { - XMapWindow(display, stack); - } -} - -void aswm_unstack_window(Display* display, Window stack) { - Window root; // unused - Window parent; - Window* children; - unsigned int children_count; - XQueryTree(display, stack, &root, &parent, &children, &children_count); - - bool visible_child = false; - int i = 0; - while(!visible_child && i < children_count) { - XWindowAttributes child_attributes; - XGetWindowAttributes(display, children[i], &child_attributes); - visible_child = (child_attributes.map_state == IsViewable); - i++; - } - XFree(children); - - if(visible_child) { - printf("Resize stack %lu\n", stack); - resize_stack(display, stack); - } else { - printf("Nothing in stack, unmap %lu\n", stack); - XWindowAttributes parent_size; - XGetWindowAttributes(display, parent, &parent_size); - - XMoveResizeWindow(display, stack, 0, 0, parent_size.width, parent_size.height); - XUnmapWindow(display, stack); - } -} - -bool is_in_stack(Display* display, Window stack_root, Window window) { - Window _root; // unused - Window parent; - Window* _children; // unused - unsigned int _children_count; // unused - - XQueryTree(display, window, &_root, &parent, &_children, &_children_count); - return parent == stack_root; -} - -void aswm_handle_normal_hints(Display* display, Window stack_root, Window window, XSizeHints* size, long supplied) { - printf("Handle normal hints for %lu\n", window); - XWindowAttributes win_attributes; - XGetWindowAttributes(display, window, &win_attributes); - - if(win_attributes.map_state != IsUnmapped) { - // TODO: handle multiple desktops - if((supplied & (PMinSize | PMaxSize))) { - if(is_in_stack(display, stack_root, window)) { - if(aswm_is_resizeable(size)) { - // Remap to tile root - XUnmapWindow(display, window); - XMapWindow(display, window); - } else { - XResizeWindow(display, window, size->max_width, size->max_height); - resize_stack(display, stack_root); - } - } else { - if(!aswm_is_resizeable(size)) { - // Resize window to its fixed size before stacking it - XResizeWindow(display, window, size->max_width, size->max_height); - - // XMapWindow does not trigger a MapRequest for the current - // client, so we need to call aswm_stack_window directly. - // aswm_stack_window automatically triggers the appropriate - // unmap from tile when reparenting from tile to stack - aswm_stack_window(display, stack_root, window, size->max_width, size->max_height); - } - } - } - } -} - diff --git a/src/aswm/mapper/mapper.h b/src/aswm/mapper/mapper.h deleted file mode 100644 index 2e6af65..0000000 --- a/src/aswm/mapper/mapper.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ASWM_MAPPER -#define ASWM_MAPPER - -#include -#include - -Window create_aswm_root_tile(Display* display, Window root_window); - -void aswm_tile_window(Display* display, Window current_node, Window window_to_map); -void aswm_untile_window(Display* display, Window parent, Window window); - -void aswm_stack_window(Display* display, Window stack, Window window_to_map, int width, int height); -void aswm_unstack_window(Display* display, Window stack); -void aswm_handle_normal_hints(Display* display, Window stack_root, Window window, XSizeHints* size, long supplied); - -bool aswm_is_resizeable(XSizeHints* size); - -#endif diff --git a/src/configure.c b/src/configure.c new file mode 100644 index 0000000..b4e7c49 --- /dev/null +++ b/src/configure.c @@ -0,0 +1,39 @@ +#include "configure.h" +#include +#include + +void OnConfigureRequest(const XConfigureRequestEvent* e) { + XWindowChanges changes; + printf("XConfigureRequestEvent %lu\n", e->window); + printf("\tx = %i\n", e->x); + printf("\ty = %i\n", e->y); + printf("\tw = %i\n", e->width); + printf("\th = %i\n", e->height); + + + { + XTextProperty text_property; + XGetWMName(e->display, e->window, &text_property); + printf("\tname: %s\n", text_property.value); + } + { + XClassHint class; + XGetClassHint(e->display, e->window, &class); + printf("\tclass: %s, %s\n", class.res_class, class.res_name); + } + + int screen_number = XDefaultScreen(e->display); + int full_width = XDisplayWidth(e->display, screen_number); + int full_height = XDisplayWidth(e->display, screen_number); + + // Copy fields from e to changes. + changes.x = 0; + changes.y = 0; + changes.width = full_width; + changes.height = full_height; + changes.border_width = e->border_width; + changes.sibling = e->above; + changes.stack_mode = e->detail; + // Grant request by calling XConfigureWindow(). + XConfigureWindow(e->display, e->window, e->value_mask, &changes); +} diff --git a/src/create.c b/src/create.c new file mode 100644 index 0000000..95c3052 --- /dev/null +++ b/src/create.c @@ -0,0 +1,6 @@ +#include "create.h" +#include + +void OnCreateNotify(const XCreateWindowEvent* e) { + printf("XCreateWindowEvent %lu\n", e->window); +} diff --git a/src/aswm/event_handlers/destroy.c b/src/destroy.c similarity index 100% rename from src/aswm/event_handlers/destroy.c rename to src/destroy.c diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..766493e --- /dev/null +++ b/src/main.c @@ -0,0 +1,46 @@ +#include +#include "create.h" +#include "configure.h" +#include "map.h" +#include "reparent.h" +#include "destroy.h" + +Display *display; +Window root; + +int main(int argc, char** argv) { + display = XOpenDisplay(NULL); + + root = DefaultRootWindow(display); + + XSelectInput(display, root, SubstructureRedirectMask | SubstructureNotifyMask); + XSync(display, 0); + + for (;;) { + XEvent e; + XNextEvent(display, &e); + + switch(e.type) { + case CreateNotify: + OnCreateNotify(&e.xcreatewindow); + break; + case ConfigureRequest: + OnConfigureRequest(&e.xconfigurerequest); + break; + case MapRequest: + OnMapRequest(root, &e.xmaprequest); + break; + case DestroyNotify: + OnDestroyNotify(&e.xdestroywindow); + break; + case ReparentNotify: + OnReparentNotify(&e.xreparent); + break; + default: + break; + /* LOG(WARNING) << "Ignored event"; */ + } + } + + XCloseDisplay(display); +} diff --git a/src/map.c b/src/map.c new file mode 100644 index 0000000..c9a590c --- /dev/null +++ b/src/map.c @@ -0,0 +1,7 @@ +#include "map.h" +#include + +void OnMapRequest(Window root, const XMapRequestEvent* e) { + printf("XMapRequestEvent %lu\n", e->window); + XMapWindow(e->display, e->window); +} diff --git a/src/aswm/event_handlers/reparent.c b/src/reparent.c similarity index 53% rename from src/aswm/event_handlers/reparent.c rename to src/reparent.c index e3b5675..f2f3842 100644 --- a/src/aswm/event_handlers/reparent.c +++ b/src/reparent.c @@ -2,5 +2,5 @@ #include void OnReparentNotify(const XReparentEvent* e) { - printf("XReparentEvent from %lu: %lu to %lu\n", e->event, e->window, e->parent); + printf("XReparentEvent %lu\n", e->window); } diff --git a/src/unmap.c b/src/unmap.c new file mode 100644 index 0000000..6f3ae67 --- /dev/null +++ b/src/unmap.c @@ -0,0 +1,6 @@ +#include "unmap.h" +#include + +void OnUnmapRequest(Window root, const XMapRequestEvent* e) { + printf("XUnmapWindow %lu", e->window); +}