summaryrefslogtreecommitdiff
path: root/schewm.c
diff options
context:
space:
mode:
authorSamuel Fadel <samuel@nihil.ws>2022-12-07 13:14:27 +0100
committerSamuel Fadel <samuel@nihil.ws>2022-12-07 13:14:27 +0100
commit8902bfca018b8bd573454ba7fffb7cde5d3983b0 (patch)
treebff16904f851d6fe99b4a47552ad052fc55b93d3 /schewm.c
parent26f2b1aaa4eded77cc2a2ec9529b4216fc8f94da (diff)
Ported some more code.
* schewm.c: Mostly added utility functions not yet wired to wm.
Diffstat (limited to 'schewm.c')
-rw-r--r--schewm.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/schewm.c b/schewm.c
index 5f7bc8a..8d19b60 100644
--- a/schewm.c
+++ b/schewm.c
@@ -23,6 +23,45 @@ const uint16_t RESIZE_GLYPH = 120;
const uint16_t MOD_META = XCB_MOD_MASK_4;
const uint16_t MOD_SHIFT = XCB_MOD_MASK_SHIFT;
+// General utility functions
+uint32_t
+parse_color(const char *s) {
+ unsigned int r, g, b;
+ if (s == NULL
+ || strlen(s) != 7
+ || sscanf(s, "#%2x%2x%2x", &r, &g, &b) != 3) {
+ // Parse error
+ return 0;
+ }
+ return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
+}
+
+uint64_t
+make_key_chord(uint16_t mod, xcb_keysym_t keysym) {
+ uint64_t chord = mod;
+ chord = (chord << 32) | keysym;
+ return chord;
+}
+
+uint32_t
+make_button_chord(uint16_t mod, xcb_button_t button) {
+ uint32_t chord = mod;
+ chord = (chord << 16) | button;
+ return chord;
+}
+
+void
+parse_key_chord(uint64_t chord, uint16_t *mod, xcb_keysym_t *keysym) {
+ *mod = chord >> 32;
+ *keysym = chord & 0xffff;
+}
+
+void
+parse_button_chord(uint32_t chord, uint16_t *mod, xcb_button_t *button) {
+ *mod = chord >> 16;
+ *button = chord & 0xf;
+}
+
struct Point {
int16_t x, y;
};
@@ -1231,6 +1270,13 @@ dpy_window_under_cursor() {
}
void
+dpy_center_cursor_client(const struct Client *client) {
+ int16_t x = client->width / 2;
+ int16_t y = client->height / 2;
+ xcb_warp_pointer(dpy.conn, XCB_NONE, client->id, 0, 0, 0, 0, x, y);
+}
+
+void
dpy_grab_buttons(struct Client *client) {
}
@@ -1536,6 +1582,100 @@ void
wm_set_client_workspace(struct Client *client, uint32_t workspace) {
}
+void
+wm_client_monitor_size(const struct Client *client,
+ bool with_offsets,
+ struct Rect *rect) {
+ if (client->monitor == NULL) {
+ // No monitor means that the default screen is our monitor
+ rect->x = rect->y = 0;
+ rect->width = dpy.screen->width_in_pixels;
+ rect->height = dpy.screen->height_in_pixels;
+ } else {
+ rect->x = client->monitor->x;
+ rect->y = client->monitor->y;
+ rect->width = client->monitor->width;
+ rect->height = client->monitor->height;
+ }
+
+ if (with_offsets) {
+ rect->x += cfg.offset_x;
+ rect->y += cfg.offset_y;
+ rect->width -= cfg.offset_width;
+ rect->height -= cfg.offset_height;
+ }
+}
+
+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);
+
+ // 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) {
+ 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;
+ 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;
+ should_move = true;
+ }
+ if (client->x < mon_size.x) {
+ client->x = mon_size.x;
+ should_move = true;
+ }
+ if (client->y < mon_size.y) {
+ client->y = mon_size.y;
+ should_move = true;
+ }
+
+ // Check if client is larger than monitor, if so move to upper corner and
+ // 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;
+ 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);
+ 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;
+ 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);
+ should_move = true;
+ }
+
+ if (should_move && should_resize) {
+ dpy_update_window_geometry(client);
+ } else if (should_move) {
+ dpy_update_window_position(client);
+ } else if (should_resize) {
+ dpy_update_window_size(client);
+ }
+
+ return should_move || should_resize;
+}
+
/*
* event handlers which take a generic event and know what to cast it into.
*/