summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Fadel <samuel@nihil.ws>2022-12-08 15:57:36 +0100
committerSamuel Fadel <samuel@nihil.ws>2022-12-08 15:57:36 +0100
commit6bdaee03c0fd3caac390dffdaaf52d54653b1430 (patch)
treed6e6d725f0c46aa4acf89ceb2bc1cf3f714d9760
parenta6051a3146da4d99788905c0805890d78ab004da (diff)
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
-rw-r--r--.manifest.scm1
-rw-r--r--Makefile4
-rw-r--r--main.scm31
-rw-r--r--schewm.c151
-rw-r--r--wm.scm8
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
diff --git a/Makefile b/Makefile
index 2d8ba0f..66db823 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/main.scm b/main.scm
index e0647ab..6487a30 100644
--- a/main.scm
+++ b/main.scm
@@ -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!
diff --git a/schewm.c b/schewm.c
index 350ed80..126ab2f 100644
--- a/schewm.c
+++ b/schewm.c
@@ -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;
}
diff --git a/wm.scm b/wm.scm
index 85a23f4..3241d94 100644
--- a/wm.scm
+++ b/wm.scm
@@ -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" '()))