diff options
Diffstat (limited to 'schewm.c')
-rw-r--r-- | schewm.c | 140 |
1 files changed, 140 insertions, 0 deletions
@@ -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. */ |