From 9aab7c087c8f64967050073251ae87e2f6ce2672 Mon Sep 17 00:00:00 2001 From: Paul Breugnot Date: Sun, 29 Dec 2024 13:51:11 +0100 Subject: [PATCH] :sparkles: Very basic native htiles --- CMakeLists.txt | 6 +- src/aswm/aswm.c | 15 +-- src/aswm/aswm.h | 2 - src/aswm/event_handlers/map.c | 3 +- src/aswm/event_handlers/reparent.c | 2 +- src/aswm/event_handlers/unmap.c | 5 +- src/aswm/log/log.c | 17 +++ src/aswm/log/log.h | 8 ++ src/aswm/mapper/mapper.c | 159 +++++++++++++++++------------ src/aswm/mapper/mapper.h | 20 +--- 10 files changed, 137 insertions(+), 100 deletions(-) create mode 100644 src/aswm/log/log.c create mode 100644 src/aswm/log/log.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6558b84..404a449 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 23) find_package(X11 REQUIRED) -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -pg") add_executable(aswm src/aswm/aswm.c @@ -16,6 +16,8 @@ add_executable(aswm 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/unmap.c + src/aswm/log/log.c +) target_include_directories(aswm PUBLIC ${X11_INCLUDE_DIR} src) target_link_libraries(aswm ${X11_LIBRARIES}) diff --git a/src/aswm/aswm.c b/src/aswm/aswm.c index acf2eb1..0f44bcd 100644 --- a/src/aswm/aswm.c +++ b/src/aswm/aswm.c @@ -7,21 +7,19 @@ #include "event_handlers/unmap.h" #include "event_handlers/reparent.h" #include "event_handlers/destroy.h" +#include "log/log.h" Aswm _aswm; void aswm_open() { _aswm.display = XOpenDisplay(NULL); - _aswm.root_window = DefaultRootWindow(_aswm.display); - - - _aswm.root_tile = aswm_alloc_root_tile(_aswm.display, _aswm.root_window); + Window root_window = DefaultRootWindow(_aswm.display); printf("PointerRoot %lu\n", PointerRoot); printf("None %lu\n", None); - printf("Root window %lu\n", _aswm.root_window); + printf("Root window %lu\n", root_window); - XSelectInput(_aswm.display, _aswm.root_window, SubstructureRedirectMask | SubstructureNotifyMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask); + XSelectInput(_aswm.display, root_window, SubstructureRedirectMask | SubstructureNotifyMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask); XSync(_aswm.display, 0); atexit(aswm_close); @@ -41,9 +39,13 @@ void aswm_event_loop() { break; case MapRequest: OnMapRequest(&_aswm, &e.xmaprequest); + printf("Map tree:\n"); + log_tree(_aswm.display, DefaultRootWindow(_aswm.display), 1); break; case UnmapNotify: OnUnmapNotify(&_aswm, &e.xunmap); + printf("Unmap tree:\n"); + log_tree(_aswm.display, DefaultRootWindow(_aswm.display), 1); break; case DestroyNotify: OnDestroyNotify(&e.xdestroywindow); @@ -81,7 +83,6 @@ void aswm_event_loop() { } void aswm_close() { - aswm_free_tile(_aswm.root_tile); XCloseDisplay(_aswm.display); } diff --git a/src/aswm/aswm.h b/src/aswm/aswm.h index c0944c5..bd4c9da 100644 --- a/src/aswm/aswm.h +++ b/src/aswm/aswm.h @@ -5,8 +5,6 @@ typedef struct { Display *display; - Window root_window; - AswmTile* root_tile; Window es_de_window; } Aswm; diff --git a/src/aswm/event_handlers/map.c b/src/aswm/event_handlers/map.c index 6e96a9a..357c063 100644 --- a/src/aswm/event_handlers/map.c +++ b/src/aswm/event_handlers/map.c @@ -23,8 +23,7 @@ void OnMapRequest(Aswm* aswm, const XMapRequestEvent* e) { int full_width = XDisplayWidth(e->display, screen_number); int full_height = XDisplayWidth(e->display, screen_number); - aswm_map_new_window(e->display, e->window, aswm->root_tile); + aswm_map_new_window(e->display, DefaultRootWindow(e->display), e->window); /* XSelectInput(e->display, e->window, FocusChangeMask | EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask); */ - XMapWindow(e->display, e->window); } diff --git a/src/aswm/event_handlers/reparent.c b/src/aswm/event_handlers/reparent.c index f2f3842..e3b5675 100644 --- a/src/aswm/event_handlers/reparent.c +++ b/src/aswm/event_handlers/reparent.c @@ -2,5 +2,5 @@ #include void OnReparentNotify(const XReparentEvent* e) { - printf("XReparentEvent %lu\n", e->window); + printf("XReparentEvent from %lu: %lu to %lu\n", e->event, e->window, e->parent); } diff --git a/src/aswm/event_handlers/unmap.c b/src/aswm/event_handlers/unmap.c index c4431f6..a439967 100644 --- a/src/aswm/event_handlers/unmap.c +++ b/src/aswm/event_handlers/unmap.c @@ -2,8 +2,11 @@ #include void OnUnmapNotify(Aswm* aswm, const XUnmapEvent* e) { - printf("XUnmapWindow %lu\n", e->window); + 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); + // Since SubstructureNotify is selected on each frame, e->event corresponds + // to the parent of the unmapped window (e->window) + aswm_unmap_window(e->display, e->event); } diff --git a/src/aswm/log/log.c b/src/aswm/log/log.c new file mode 100644 index 0000000..f08ef2b --- /dev/null +++ b/src/aswm/log/log.c @@ -0,0 +1,17 @@ +#include "log.h" +#include + +void log_tree(Display* display, Window window, int indent) { + for(int i = 0; i < indent; i++) + printf(" "); + printf("%lu\n", window); + + Window root_window; + Window parent_tile; + Window* children; + unsigned int children_count; + XQueryTree(display, window, &root_window, &parent_tile, &children, &children_count); + for(auto i = 0; i < children_count; i++) + log_tree(display, children[i], indent+1); + XFree(children); +} diff --git a/src/aswm/log/log.h b/src/aswm/log/log.h new file mode 100644 index 0000000..e58014a --- /dev/null +++ b/src/aswm/log/log.h @@ -0,0 +1,8 @@ +#ifndef ASWM_LOG +#define ASWM_LOG + +#include + +void log_tree(Display* display, Window root, int indent); + +#endif diff --git a/src/aswm/mapper/mapper.c b/src/aswm/mapper/mapper.c index 566cd9f..1d30688 100644 --- a/src/aswm/mapper/mapper.c +++ b/src/aswm/mapper/mapper.c @@ -1,80 +1,103 @@ #include #include #include "aswm/mapper/mapper.h" - -AswmTile* aswm_alloc_tile() { - AswmTile* tile = malloc(sizeof(AswmTile)); - for(int i = 0; i < 2; i++) - tile->children[i] = nullptr; - return tile; -} - -AswmTile* aswm_alloc_root_tile(Display* display, Window window) { - int screen_number = XDefaultScreen(display); - AswmTile* tile = aswm_alloc_tile(); - - tile->has_children = false; - tile->x = 0; - tile->y = 0; - tile->free = true; - tile->width = XDisplayWidth(display, screen_number); - tile->height = XDisplayHeight(display, screen_number); - - return tile; -} - -void aswm_free_tile(AswmTile* tile) { - for(int i = 0; i < 2; i++) - aswm_free_tile(tile->children[i]); - if(tile != nullptr) - free(tile); -} +#include "aswm/log/log.h" /** * Returns the free tile built in the split process. */ -AswmTile* h_split(AswmTile* tile); +void h_split(Display* display, Window current_node, Window window_to_map); -AswmTile* aswm_map_new_window(Display* display, Window window, AswmTile* tile) { - if(tile->has_children) { - // The tile is necessarily considered occupied - return aswm_map_new_window(display, window, tile->children[1]); - } - if(tile->free) { - // Leef of the tile tree, the window can be inserted there - tile->free = false; - tile->display = display; - tile->window = window; - - // Automatically reconfigure position and size of the window - XWindowChanges changes; - changes.x = tile->x; - changes.y = tile->y; - changes.width = tile->width; - changes.height = tile->height; - - XConfigureWindow(display, window, CWX | CWY | CWWidth | CWHeight, &changes); - return tile; - } - // Leef of tile tree, but occupied. Split the tile and map the window to the - // new tile. - return aswm_map_new_window(display, window, h_split(tile)); +void aswm_map_new_window(Display* display, Window current_node, Window window_to_map) { + h_split(display, current_node, window_to_map); } -AswmTile* h_split(AswmTile* tile) { - tile->has_children = true; - for(int i = 0; i < 2; i++) { - tile->children[i] = aswm_alloc_tile(); - tile->children[i]->has_children = false; - tile->children[i]->free = true; - tile->children[i]->x = tile->x; - tile->children[i]->width = tile->width; - tile->children[i]->height = tile->height / 2; +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); } - tile->children[0]->y = tile->y; - tile->children[1]->y = tile->y + tile->children[0]->height; - - aswm_map_new_window(tile->display, tile->window, tile->children[0]); - - return tile->children[1]; + XFree(children); + XMapWindow(display, window_to_map); +} + +void resize_children_to_tile(Display* display, Window tile) { + Window _root_window; // unused + Window _grand_parent; // unused + Window* children; + unsigned int children_count; + XQueryTree( + display, tile, + &_root_window, &_grand_parent, + &children, &children_count); + printf("Current siblings of %lu:\n", tile); + 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, tile, &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_unmap_window(Display* display, Window tile) { + // +-------------------------------+ + // | root | + // |+-------------+ +-------------+| + // || tile | | || + // || +--------+ | | || + // || | win 1 | | | || + // || +--------+ | | || + // || +--------+ | | || + // || | del win| | | win 3 || + // || +--------+ | | || + // || +--------+ | | || + // || | win 2 | | | || + // || +--------+ | | || + // |+-------------+ +-------------+| + // +-------------------------------+ + + resize_children_to_tile(display, tile); } diff --git a/src/aswm/mapper/mapper.h b/src/aswm/mapper/mapper.h index dce378d..e14b576 100644 --- a/src/aswm/mapper/mapper.h +++ b/src/aswm/mapper/mapper.h @@ -3,23 +3,9 @@ #include -struct AswmTile; +Window create_aswm_root_tile(Display* display, Window root_window); -typedef struct AswmTile { - int x, y; - int width, height; - bool free; - Display* display; - Window window; - bool has_children; - struct AswmTile* children[2]; -} AswmTile; - -AswmTile* aswm_alloc_tile(); -AswmTile* aswm_alloc_root_tile(Display* display, Window window); -void aswm_free_tile(AswmTile* tile); - -AswmTile* aswm_map_new_window(Display* display, Window window, AswmTile* tile); -AswmTile* aswm_unmap_window(Display* display, Window window, AswmTile* tile); +void aswm_map_new_window(Display* display, Window current_node, Window window_to_map); +void aswm_unmap_window(Display* display, Window window); #endif