From 6bdaee03c0fd3caac390dffdaaf52d54653b1430 Mon Sep 17 00:00:00 2001 From: Samuel Fadel Date: Thu, 8 Dec 2022 15:57:36 +0100 Subject: More features implemented. * .manifest.scm: Added libx11 * Makefile: Add x11 to pkg-config calls * main.scm: Add more config, including some keybinding stuff * wm.scm: Add key-from-str function * schewm.c: keysym_from_str() and others implemented/refactored --- schewm.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 117 insertions(+), 34 deletions(-) (limited to 'schewm.c') diff --git a/schewm.c b/schewm.c index 350ed80..126ab2f 100644 --- a/schewm.c +++ b/schewm.c @@ -9,6 +9,7 @@ #include #include #include +#include #include // 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; } -- cgit v1.2.3