From ac58e5e6db60a2a629c966259786b94f1a53a7bb Mon Sep 17 00:00:00 2001 From: Paul Breugnot Date: Wed, 25 Dec 2024 11:58:58 +0100 Subject: [PATCH] :construction: Basic tiling window creation Only supports creation of windows with horizontal splitting, and not removal of windows. --- CMakeLists.txt | 5 +- include/aswm/aswm.h | 17 ++++--- include/aswm/event_handlers/map.h | 3 +- include/aswm/mapper/mapper.h | 24 +++++++++ src/aswm/aswm.c | 21 +++++--- src/aswm/event_handlers/map.c | 17 +------ src/aswm/main.c | 6 +-- src/aswm/mapper/mapper.c | 85 +++++++++++++++++++++++++++++++ 8 files changed, 145 insertions(+), 33 deletions(-) create mode 100644 include/aswm/mapper/mapper.h create mode 100644 src/aswm/mapper/mapper.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e30d5fb..5b8e223 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,9 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.21) project(aswm) +set(CMAKE_C_STANDARD 23) + find_package(X11 REQUIRED) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address") @@ -9,6 +11,7 @@ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address") add_executable(aswm src/aswm/main.c 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 diff --git a/include/aswm/aswm.h b/include/aswm/aswm.h index 46800a2..1d538b3 100644 --- a/include/aswm/aswm.h +++ b/include/aswm/aswm.h @@ -1,11 +1,16 @@ -#include +#ifndef ASWM +#define ASWM + +#include "aswm/mapper/mapper.h" typedef struct { Display *display; - Window root; -} aswm; + Window root_window; + AswmTile* root_tile; +} Aswm; -void AswmOpen(); -void AswmEventLoop(); -void AswmClose(); +void aswm_open(); +void aswm_event_loop(); +void aswm_close(); +#endif diff --git a/include/aswm/event_handlers/map.h b/include/aswm/event_handlers/map.h index e8638ca..6270df5 100644 --- a/include/aswm/event_handlers/map.h +++ b/include/aswm/event_handlers/map.h @@ -1,3 +1,4 @@ #include +#include "aswm/aswm.h" -void OnMapRequest(Window root, const XMapRequestEvent* e); +void OnMapRequest(Aswm* aswm, const XMapRequestEvent* e); diff --git a/include/aswm/mapper/mapper.h b/include/aswm/mapper/mapper.h new file mode 100644 index 0000000..3e7a757 --- /dev/null +++ b/include/aswm/mapper/mapper.h @@ -0,0 +1,24 @@ +#ifndef ASWM_MAPPER +#define ASWM_MAPPER + +#include + +struct AswmTile; + +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); + +#endif diff --git a/src/aswm/aswm.c b/src/aswm/aswm.c index 5a3f5b6..ce9d359 100644 --- a/src/aswm/aswm.c +++ b/src/aswm/aswm.c @@ -1,3 +1,4 @@ +#include #include "aswm/aswm.h" #include "aswm/event_handlers/create.h" #include "aswm/event_handlers/configure.h" @@ -5,17 +6,22 @@ #include "aswm/event_handlers/reparent.h" #include "aswm/event_handlers/destroy.h" -aswm _aswm; +Aswm _aswm; -void AswmOpen() { +void aswm_open() { _aswm.display = XOpenDisplay(NULL); - _aswm.root = DefaultRootWindow(_aswm.display); + _aswm.root_window = DefaultRootWindow(_aswm.display); - XSelectInput(_aswm.display, _aswm.root, SubstructureRedirectMask | SubstructureNotifyMask); + + _aswm.root_tile = aswm_alloc_root_tile(_aswm.display, _aswm.root_window); + + XSelectInput(_aswm.display, _aswm.root_window, SubstructureRedirectMask | SubstructureNotifyMask); XSync(_aswm.display, 0); + + atexit(aswm_close); } -void AswmEventLoop() { +void aswm_event_loop() { for (;;) { XEvent e; XNextEvent(_aswm.display, &e); @@ -28,7 +34,7 @@ void AswmEventLoop() { OnConfigureRequest(&e.xconfigurerequest); break; case MapRequest: - OnMapRequest(_aswm.root, &e.xmaprequest); + OnMapRequest(&_aswm, &e.xmaprequest); break; case DestroyNotify: OnDestroyNotify(&e.xdestroywindow); @@ -43,6 +49,7 @@ void AswmEventLoop() { } } -void AswmClose() { +void aswm_close() { + aswm_free_tile(_aswm.root_tile); XCloseDisplay(_aswm.display); } diff --git a/src/aswm/event_handlers/map.c b/src/aswm/event_handlers/map.c index 7d22a65..a15fb92 100644 --- a/src/aswm/event_handlers/map.c +++ b/src/aswm/event_handlers/map.c @@ -2,7 +2,7 @@ #include #include -void OnMapRequest(Window root, const XMapRequestEvent* e) { +void OnMapRequest(Aswm* aswm, const XMapRequestEvent* e) { printf("XMapRequestEvent %lu\n", e->window); { @@ -20,19 +20,6 @@ void OnMapRequest(Window root, const XMapRequestEvent* e) { int full_width = XDisplayWidth(e->display, screen_number); int full_height = XDisplayWidth(e->display, screen_number); - // Automatically reconfigure position and size of the window - XWindowChanges changes; - changes.x = 0; - changes.y = 0; - changes.width = full_width; - changes.height = full_height; - - printf("\tx = %i\n", changes.x); - printf("\ty = %i\n", changes.y); - printf("\tw = %i\n", changes.width); - printf("\th = %i\n", changes.height); - - XConfigureWindow(e->display, e->window, CWX | CWY | CWWidth | CWHeight, &changes); - + aswm_map_new_window(e->display, e->window, aswm->root_tile); XMapWindow(e->display, e->window); } diff --git a/src/aswm/main.c b/src/aswm/main.c index 46f5d3e..ce0202f 100644 --- a/src/aswm/main.c +++ b/src/aswm/main.c @@ -1,7 +1,7 @@ #include "aswm/aswm.h" int main(int argc, char** argv) { - AswmOpen(); - AswmEventLoop(); - AswmClose(); + aswm_open(); + aswm_event_loop(); + aswm_close(); } diff --git a/src/aswm/mapper/mapper.c b/src/aswm/mapper/mapper.c new file mode 100644 index 0000000..f56a100 --- /dev/null +++ b/src/aswm/mapper/mapper.c @@ -0,0 +1,85 @@ +#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); +} + +/** + * Returns the free tile built in the split process. + */ +AswmTile* h_split(AswmTile* tile); + +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; + + printf("\tx = %i\n", changes.x); + printf("\ty = %i\n", changes.y); + printf("\tw = %i\n", changes.width); + printf("\th = %i\n", changes.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)); +} + +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; + } + 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]; +}