diff options
-rw-r--r-- | .manifest.scm | 1 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | main.scm | 31 | ||||
-rw-r--r-- | schewm.c | 151 | ||||
-rw-r--r-- | wm.scm | 8 |
5 files changed, 155 insertions, 40 deletions
diff --git a/.manifest.scm b/.manifest.scm index ef6bbf7..56b34f4 100644 --- a/.manifest.scm +++ b/.manifest.scm @@ -15,6 +15,7 @@ gnu-make gcc-toolchain pkg-config + libx11 libxcb xcb-util-keysyms xcb-util-wm @@ -1,5 +1,5 @@ -CFLAGS=`pkg-config --cflags xcb xcb-ewmh xcb-icccm xcb-keysyms xcb-randr` -LDFLAGS=`pkg-config --libs xcb xcb-ewmh xcb-icccm xcb-keysyms xcb-randr` +CFLAGS=`pkg-config --cflags x11 xcb xcb-ewmh xcb-icccm xcb-keysyms xcb-randr` +LDFLAGS=`pkg-config --libs x11 xcb xcb-ewmh xcb-icccm xcb-keysyms xcb-randr` all: libschewm.so @@ -2,13 +2,36 @@ (wm)) (define-record-type <wm-config> - (make-config border-width outer-border-width) + (make-config + inner-border-width + outer-border-width + manger-border-width + offset-x + offset-y + offset-width + offset-height) wm-config? - (border-width config-border-width set-config-border-width!) - (outer-border-width config-outer-border-width set-config-outer-border-width!)) + (inner-border-width config-inner-border-width set-config-inner-border-width!) + (outer-border-width config-outer-border-width set-config-outer-border-width!) + (magnet-border-width config-magnet-border-width set-config-magnet-border-width!) + (offset-x config-offset-x set-config-offset-x!) + (offset-y config-offset-y set-config-offset-y!) + (offset-width config-offset-width set-config-offset-width!) + (offset-height config-offset-height set-config-offset-height!)) (define config - (make-config 2 0)) + (make-config + 2 ; inner-border-width + 0 ; outer-border-width + 16 ; magnet-border-width + 0 ; offset-x + 0 ; offset-y + 0 ; offset-width + 0 ; offset-height + )) + +(define keys + '(((make-key-chord (key-from-str "q")) . wm-quit))) (when (wm-init) (wm-set-key-press-handler! @@ -9,6 +9,7 @@ #include <xcb/xcb_ewmh.h> #include <xcb/xcb_icccm.h> #include <xcb/xcb_keysyms.h> +#include <X11/Xlib.h> #include <X11/keysym.h> // Workspace values which are special for us @@ -23,6 +24,11 @@ const uint16_t RESIZE_GLYPH = 120; const uint16_t MOD_META = XCB_MOD_MASK_4; const uint16_t MOD_SHIFT = XCB_MOD_MASK_SHIFT; +uint32_t +keysym_from_str(const char *s) { + return (uint32_t) XStringToKeysym(s); +} + // General utility functions uint32_t parse_color(const char *s) { @@ -1033,6 +1039,16 @@ dpy_grab_key(uint16_t mod, xcb_keysym_t keysym) { } } +static uint16_t +dpy_clean_mod(uint16_t mod) { + return mod & ~(dpy.num_lock | dpy.caps_lock | dpy.scroll_lock); +} + +static xcb_keysym_t +dpy_keysym_from_keycode(xcb_keycode_t keycode) { + return xcb_key_symbols_get_keysym(dpy.keysyms, keycode, 0); +} + static void dpy_set_workspace(uint32_t workspace) { xcb_ewmh_set_current_desktop(dpy.ewmh, dpy.screen_num, workspace); @@ -1353,21 +1369,24 @@ dpy_should_ignore_window(xcb_window_t window) { cookie, &window_type, NULL); + if (!reply) { + return false; + } + + // Figure out from window type if we should ignore it bool should_ignore = false; - if (reply) { - // Figure out from window type if we should ignore it - for (uint32_t i = 0; i < window_type.atoms_len; i++) { - xcb_atom_t atom = window_type.atoms[i]; - if (atom == dpy.ewmh->_NET_WM_WINDOW_TYPE_TOOLBAR - || atom == dpy.ewmh->_NET_WM_WINDOW_TYPE_DESKTOP - || atom == dpy.ewmh->_NET_WM_WINDOW_TYPE_DOCK) { - // Ignore those windows - should_ignore = true; - break; - } + for (uint32_t i = 0; i < window_type.atoms_len; i++) { + xcb_atom_t atom = window_type.atoms[i]; + if (atom == dpy.ewmh->_NET_WM_WINDOW_TYPE_TOOLBAR + || atom == dpy.ewmh->_NET_WM_WINDOW_TYPE_DESKTOP + || atom == dpy.ewmh->_NET_WM_WINDOW_TYPE_DOCK) { + // Ignore those windows + should_ignore = true; + break; } - xcb_ewmh_get_atoms_reply_wipe(&window_type); } + // TODO: test/check if this is necessary only if reply is valid + xcb_ewmh_get_atoms_reply_wipe(&window_type); return should_ignore; } @@ -1530,6 +1549,32 @@ wm_erase_client(xcb_window_t id) { } } +bool +wm_apply_size_hints(struct Client *client) { + if (client->state != WS_NORMAL) { + return false; + } + + bool any_change = false; + if (client->min_width > 0 && client->width < client->min_width) { + client->width = client->min_width; + any_change = true; + } + if (client->max_width > 0 && client->width > client->max_width) { + client->width = client->max_width; + any_change = true; + } + if (client->min_height > 0 && client->height < client->min_height) { + client->height = client->min_height; + any_change = true; + } + if (client->max_height > 0 && client->height > client->max_height) { + client->height = client->max_height; + any_change = true; + } + return any_change; +} + void wm_set_focus(struct Client *client) { if (wm.focus != NULL) { @@ -1625,39 +1670,77 @@ wm_client_monitor_size(const struct Client *client, } } +void +wm_set_client_state(struct Client *client, enum WindowState state) { + if (state == client->state) { + return; + } + + switch (state) { + case WS_NORMAL: + if (client->state == WS_ICONIFIED) { + dpy_map_window(client->id); + // TODO: check size restoration + } + client_restore_size(client); + dpy_update_window_geometry(client); + break; + case WS_ICONIFIED: + dpy_unmap_window(client->id); + break; + case WS_MAXIMIZED: + client_store_size(client); + { + struct Rect mon_rect; + wm_client_monitor_size(client, true, &mon_rect); + client->x = mon_rect.x; + client->y = mon_rect.y; + client->width = mon_rect.width; + client->height = mon_rect.height; + } + dpy_update_window_geometry(client); + break; + case WS_FULLSCREEN: + break; + } + client->prev_state = client->state; + client->state = state; + dpy_set_window_state(client->id, client->state); +} + bool wm_fit_client(struct Client *client) { if (client->state == WS_ICONIFIED) { return false; } - struct Rect mon_size; - wm_client_monitor_size(client, true, &mon_size); + struct Rect mon_rect; + wm_client_monitor_size(client, true, &mon_rect); // Check if client *looks* maximized, event though it is not if (client->state == WS_NORMAL - && client->width >= mon_size.width - && client->height >= mon_size.height) { + && client->width >= mon_rect.width + && client->height >= mon_rect.height) { wm_set_client_state(client, WS_MAXIMIZED); return true; } bool should_move = false; // Check if client is located outside monitor coords - if (client->x > mon_size.x + mon_size.width) { - client->x = mon_size.x + mon_size.width - client->width - cfg.inner_border_width * 2; + if (client->x > mon_rect.x + mon_rect.width) { + client->x = mon_rect.x + mon_rect.width - client->width - cfg.inner_border_width * 2; should_move = true; } - if (client->y > mon_size.y + mon_size.height) { - client->y = mon_size.y + mon_size.height - client->height - cfg.inner_border_width * 2; + if (client->y > mon_rect.y + mon_rect.height) { + client->y = mon_rect.y + mon_rect.height - client->height - cfg.inner_border_width * 2; should_move = true; } - if (client->x < mon_size.x) { - client->x = mon_size.x; + if (client->x < mon_rect.x) { + client->x = mon_rect.x; should_move = true; } - if (client->y < mon_size.y) { - client->y = mon_size.y; + if (client->y < mon_rect.y) { + client->y = mon_rect.y; should_move = true; } @@ -1665,22 +1748,22 @@ wm_fit_client(struct Client *client) { // resize to fill bool should_resize = wm_apply_size_hints(client); uint16_t border_width = client->should_ignore_borders ? 0 : cfg.inner_border_width; - if (client->width + border_width * 2 > mon_size.width) { - client->x = mon_size.x; - client->width = mon_size.width - border_width * 2; + if (client->width + border_width * 2 > mon_rect.width) { + client->x = mon_rect.x; + client->width = mon_rect.width - border_width * 2; should_move = true; should_resize = true; - } else if (client->x + client->width + border_width * 2 > mon_size.x + mon_size.width) { - client->x = mon_size.x + mon_size.width - (client->width + border_width * 2); + } else if (client->x + client->width + border_width * 2 > mon_rect.x + mon_rect.width) { + client->x = mon_rect.x + mon_rect.width - (client->width + border_width * 2); should_move = true; } - if (client->height + border_width * 2 > mon_size.height) { - client->y = mon_size.y; - client->height = mon_size.height - border_width * 2; + if (client->height + border_width * 2 > mon_rect.height) { + client->y = mon_rect.y; + client->height = mon_rect.height - border_width * 2; should_move = true; should_resize = true; - } else if (client->y + client->height + border_width * 2 > mon_size.y + mon_size.height) { - client->y = mon_size.y + mon_size.height - (client->height + border_width * 2); + } else if (client->y + client->height + border_width * 2 > mon_rect.y + mon_rect.height) { + client->y = mon_rect.y + mon_rect.height - (client->height + border_width * 2); should_move = true; } @@ -16,6 +16,14 @@ (dynamic-func name libschewm) args)) +(define c/key-from-str + (schewm-func uint32 + "keysym_from_str" + (list '*))) + +(define (key-from-str s) + (c/key-from-str (string->pointer s))) + (define c/wm-init (schewm-func int "wm_init" '())) |