diff options
Diffstat (limited to 'mcwm.c')
-rw-r--r-- | mcwm.c | 337 |
1 files changed, 224 insertions, 113 deletions
@@ -168,7 +168,19 @@ struct client struct item *wsitem[WORKSPACES]; /* Pointer to our place in every * workspace window list. */ }; - + +/* Window configuration data. */ +struct winconf +{ + int16_t x; + int16_t y; + uint16_t width; + uint16_t height; + uint8_t stackmode; + xcb_window_t sibling; + uint16_t borderwidth; +}; + /* Globals */ @@ -316,6 +328,8 @@ static void setunfocus(xcb_drawable_t win); static void setfocus(struct client *client); static int start_terminal(void); static void resizelim(struct client *client); +static void moveresize(xcb_drawable_t win, uint16_t x, uint16_t y, + uint16_t width, uint16_t height); static void resize(xcb_drawable_t win, uint16_t width, uint16_t height); static void resizestep(struct client *client, char direction); static void mousemove(struct client *client, int rel_x, int rel_y); @@ -336,6 +350,7 @@ static void deletewin(void); static void prevscreen(void); static void nextscreen(void); static void handle_keypress(xcb_key_press_event_t *ev); +static void configwin(xcb_window_t win, uint16_t mask, struct winconf wc); static void configurerequest(xcb_configure_request_event_t *e); static void events(void); static void printhelp(void); @@ -2187,6 +2202,32 @@ void resizelim(struct client *client) resize(client->id, client->width, client->height); } +void moveresize(xcb_drawable_t win, uint16_t x, uint16_t y, + uint16_t width, uint16_t height) +{ + uint32_t values[4]; + + if (screen->root == win || 0 == win) + { + /* Can't move or resize root. */ + return; + } + + PDEBUG("Moving to %d, %d, resizing to %d x %d.\n", x, y, width, height); + + values[0] = x; + values[1] = y; + values[2] = width; + values[3] = height; + + xcb_configure_window(conn, win, + XCB_CONFIG_WINDOW_X + | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH + | XCB_CONFIG_WINDOW_HEIGHT, values); + xcb_flush(conn); +} + /* Resize window win to width,height. */ void resize(xcb_drawable_t win, uint16_t width, uint16_t height) { @@ -3083,163 +3124,233 @@ void handle_keypress(xcb_key_press_event_t *ev) } } /* handle_keypress() */ -void configurerequest(xcb_configure_request_event_t *e) +/* Helper function to configure a window. */ +void configwin(xcb_window_t win, uint16_t mask, struct winconf wc) { - uint32_t mask = 0; uint32_t values[7]; int i = -1; - struct client *client; - int16_t mon_x; - int16_t mon_y; - uint16_t mon_width; - uint16_t mon_height; - - PDEBUG("event: Configure request. mask = %d\n", e->value_mask); + + if (mask & XCB_CONFIG_WINDOW_X) + { + mask |= XCB_CONFIG_WINDOW_X; + i ++; + values[i] = wc.x; + } - /* Find the client. */ - client = findclient(e->window); - if (NULL == client) + if (mask & XCB_CONFIG_WINDOW_Y) { - PDEBUG("We don't know about this window yet.\n"); + mask |= XCB_CONFIG_WINDOW_Y; + i ++; + values[i] = wc.y; } - - if (NULL == client || NULL == client->monitor) + + if (mask & XCB_CONFIG_WINDOW_WIDTH) { - mon_x = 0; - mon_y = 0; - mon_width = screen->width_in_pixels; - mon_height = screen->height_in_pixels; + mask |= XCB_CONFIG_WINDOW_WIDTH; + i ++; + values[i] = wc.width; } - else + + if (mask & XCB_CONFIG_WINDOW_HEIGHT) { - mon_x = client->monitor->x; - mon_y = client->monitor->y; - mon_width = client->monitor->width; - mon_height = client->monitor->height; + mask |= XCB_CONFIG_WINDOW_HEIGHT; + i ++; + values[i] = wc.height; } - /* - * We ignore border width configurations, but handle all - * others. - */ + if (mask & XCB_CONFIG_WINDOW_SIBLING) + { + mask |= XCB_CONFIG_WINDOW_SIBLING; + i ++; + values[i] = wc.sibling; + } - if (e->value_mask & XCB_CONFIG_WINDOW_X) + if (mask & XCB_CONFIG_WINDOW_STACK_MODE) { - PDEBUG("Changing X coordinate to %d\n", e->x); - mask |= XCB_CONFIG_WINDOW_X; - i ++; + mask |= XCB_CONFIG_WINDOW_STACK_MODE; + i ++; + values[i] = wc.stackmode; + } + + if (-1 != i) + { + xcb_configure_window(conn, win, mask, values); + xcb_flush(conn); + } +} + +void configurerequest(xcb_configure_request_event_t *e) +{ + struct client *client; + struct winconf wc; + int16_t mon_x; + int16_t mon_y; + uint16_t mon_width; + uint16_t mon_height; - if (client) + PDEBUG("event: Configure request. mask = %d\n", e->value_mask); + + /* Find the client. */ + if ((client = findclient(e->window))) + { + /* Find monitor position and size. */ + if (NULL == client || NULL == client->monitor) { - client->x = e->x; - if (client->x < mon_x) - { - client->x = mon_x; - } - else if (client->x + client->width > mon_x + mon_width) - { - client->x = (mon_x + mon_width) - client->width; - } - - values[i] = client->x; + mon_x = 0; + mon_y = 0; + mon_width = screen->width_in_pixels; + mon_height = screen->height_in_pixels; } else { - values[i] = e->x; + mon_x = client->monitor->x; + mon_y = client->monitor->y; + mon_width = client->monitor->width; + mon_height = client->monitor->height; } - } - if (e->value_mask & XCB_CONFIG_WINDOW_Y) - { - PDEBUG("Changing Y coordinate to %d.\n", e->y); - mask |= XCB_CONFIG_WINDOW_Y; - i ++; - - if (client) +#if 0 + /* + * We ignore moves the user haven't initiated, that is do + * nothing on XCB_CONFIG_WINDOW_X and XCB_CONFIG_WINDOW_Y + * ConfigureRequests. + * + * Code here if we ever change our minds or if you, dear user, + * wants this functionality. + */ + + if (e->value_mask & XCB_CONFIG_WINDOW_X) { - client->y = e->y; - if (client->y < mon_y) + /* Don't move window if maximized. Don't move off the screen. */ + if (!client->maxed && e->x > 0) { - client->y = mon_y; + client->x = e->x; } - else if (client->y + client->height > mon_y + mon_height) + } + + if (e->value_mask & XCB_CONFIG_WINDOW_Y) + { + /* + * Don't move window if maximized. Don't move off the + * screen. + */ + if (!client->maxed && !client->vertmaxed && e->y > 0) { - client->y = (mon_y + mon_height) - client->height; + client->y = e->y; } - - values[i] = client->y; } - else +#endif + + if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { - values[i] = e->y; - } - } - - if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) - { - PDEBUG("Changing width to %d.\n", e->width); - mask |= XCB_CONFIG_WINDOW_WIDTH; - i ++; + /* Don't resize if maximized. */ + if (!client->maxed) + { + client->width = e->width; + } + } - if (client) + if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { - client->width = e->width; - - if (client->width + conf.borderwidth * 2 > mon_width) + /* Don't resize if maximized. */ + if (!client->maxed && !client->vertmaxed) { - client->width = mon_width - conf.borderwidth * 2; + client->height = e->height; } - - values[i] = client->width; } - else + + /* + * XXX Do we really need to pass on sibling and stack mode + * configuration? Do we want to? + */ + if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { - values[i] = e->width; + uint32_t values[1]; + + values[0] = e->sibling; + xcb_configure_window(conn, e->window, + XCB_CONFIG_WINDOW_SIBLING, + values); + xcb_flush(conn); + } - } + + if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) + { + uint32_t values[1]; - if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) - { - PDEBUG("Changing height to %d.\n", e->height); - mask |= XCB_CONFIG_WINDOW_HEIGHT; - i ++; + values[0] = e->stack_mode; + xcb_configure_window(conn, e->window, + XCB_CONFIG_WINDOW_STACK_MODE, + values); + xcb_flush(conn); + } - if (client) + /* Check if window fits on screen after resizing. */ + + if (client->x + client->width + 2 * conf.borderwidth + > mon_x + mon_width) { - client->height = e->height; - if (client->height + conf.borderwidth * 2 > mon_height) + /* + * See if it fits if we move away the window from the + * right edge of the screen. + */ + client->x = mon_x + mon_width + - (client->width + 2 * conf.borderwidth); + + /* + * If we moved over the left screen edge, move back and + * fit exactly on screen. + */ + if (client->x < mon_x) { - client->height = mon_height - conf.borderwidth * 2; - } - - values[i] = client->height; + client->x = mon_x; + client->width = mon_width - 2 * conf.borderwidth; + } } - else + + if (client->y + client->height + 2 * conf.borderwidth + > mon_y + mon_height) { - values[i] = e->height; + /* + * See if it fits if we move away the window from the + * bottom edge. + */ + client->y = mon_y + mon_height + - (client->height + 2 * conf.borderwidth); + + /* + * If we moved over the top screen edge, move back and fit + * on screen. + */ + if (client->y < mon_y) + { + PDEBUG("over the edge: y < %d\n", mon_y); + client->y = mon_y; + client->height = mon_height - 2 * conf.borderwidth; + } } + + moveresize(client->id, client->x, client->y, client->width, + client->height); } - - if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) + else { - mask |= XCB_CONFIG_WINDOW_SIBLING; - i ++; - values[i] = e->sibling; - } + PDEBUG("We don't know about this window yet.\n"); - if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) - { - PDEBUG("Changing stack order.\n"); - mask |= XCB_CONFIG_WINDOW_STACK_MODE; - i ++; - values[i] = e->stack_mode; - } + /* + * Unmapped window. Just pass all options except border + * width. + */ + wc.x = e->x; + wc.y = e->y; + wc.width = e->width; + wc.height = e->height; + wc.sibling = e->sibling; + wc.stackmode = e->stack_mode; - if (-1 != i) - { - xcb_configure_window(conn, e->window, mask, values); - xcb_flush(conn); - } + configwin(e->window, e->value_mask, wc); + } } void events(void) |