Implement window gravity in ConfigureRequests (FS#1137)

Previously, awesome didn't move windows when they sent a ConfigureRequest (and
it also shrunk them by the size of titlebars, before it forgot to add these).
This commit adds proper gravity support to ConfigureRequest handling.

This was tested with test-gravity from metacity (in src/wm-tester).

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2013-04-07 11:57:40 +02:00
parent ddfd9c0e79
commit 2d3103345e
3 changed files with 91 additions and 1 deletions

31
event.c
View file

@ -285,23 +285,52 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev)
if((c = client_getbywin(ev->window)))
{
area_t geometry = c->geometry;
int16_t diff_w = 0, diff_h = 0, diff_border = 0;
if(ev->value_mask & XCB_CONFIG_WINDOW_X)
geometry.x = ev->x;
if(ev->value_mask & XCB_CONFIG_WINDOW_Y)
geometry.y = ev->y;
if(ev->value_mask & XCB_CONFIG_WINDOW_WIDTH)
{
uint16_t old_w = geometry.width;
geometry.width = ev->width;
/* The ConfigureRequest specifies the size of the client window, we want the frame */
geometry.width += c->titlebar[CLIENT_TITLEBAR_LEFT].size;
geometry.width += c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
diff_w = geometry.width - old_w;
}
if(ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
{
uint16_t old_h = geometry.height;
geometry.height = ev->height;
/* The ConfigureRequest specifies the size of the client window, we want the frame */
geometry.height += c->titlebar[CLIENT_TITLEBAR_TOP].size;
geometry.height += c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
diff_h = geometry.height - old_h;
}
if(ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH)
{
diff_border = ev->border_width - c->border_width;
diff_h += diff_border;
diff_w += diff_border;
luaA_object_push(globalconf.L, c);
window_set_border_width(globalconf.L, -1, ev->border_width);
lua_pop(globalconf.L, 1);
}
/* If the client resizes without moving itself, apply window gravity */
if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)
{
int16_t diff_x = 0, diff_y = 0;
xwindow_translate_for_gravity(c->size_hints.win_gravity, diff_border, diff_border, diff_w, diff_h, &diff_x, &diff_y);
if(!(ev->value_mask & XCB_CONFIG_WINDOW_X))
geometry.x += diff_x;
if(!(ev->value_mask & XCB_CONFIG_WINDOW_Y))
geometry.y += diff_y;
}
if(!client_resize(c, geometry, false))
/* ICCCM 4.1.5 / 4.2.3, if nothing was changed, send an event saying so */
client_send_configure(c);

View file

@ -296,4 +296,64 @@ xwindow_set_shape(xcb_window_t win, int width, int height, enum xcb_shape_sk_t k
xcb_free_pixmap(globalconf.connection, pixmap);
}
/** Calculate the position change that a window needs applied.
* \param gravity The window gravity that should be used.
* \param change_width_before The window width difference that will be applied.
* \param change_height_before The window height difference that will be applied.
* \param change_width_after The window width difference that will be applied.
* \param change_height_after The window height difference that will be applied.
* \param dx On return, this will be set to the amount the pixel has to be moved.
* \param dy On return, this will be set to the amount the pixel has to be moved.
*/
void xwindow_translate_for_gravity(xcb_gravity_t gravity, int16_t change_width_before, int16_t change_height_before,
int16_t change_width_after, int16_t change_height_after, int16_t *dx, int16_t *dy)
{
int16_t x = 0, y = 0;
int16_t change_height = change_height_before + change_height_after;
int16_t change_width = change_width_before + change_width_after;
switch (gravity) {
case XCB_GRAVITY_WIN_UNMAP:
case XCB_GRAVITY_NORTH_WEST:
break;
case XCB_GRAVITY_NORTH:
x = -change_width / 2;
break;
case XCB_GRAVITY_NORTH_EAST:
x = -change_width;
break;
case XCB_GRAVITY_WEST:
y = -change_height / 2;
break;
case XCB_GRAVITY_CENTER:
x = -change_width / 2;
y = -change_height / 2;
break;
case XCB_GRAVITY_EAST:
x = -change_width;
y = -change_height / 2;
break;
case XCB_GRAVITY_SOUTH_WEST:
y = -change_height;
break;
case XCB_GRAVITY_SOUTH:
x = -change_width / 2;
y = -change_height;
break;
case XCB_GRAVITY_SOUTH_EAST:
x = -change_width;
y = -change_height;
break;
case XCB_GRAVITY_STATIC:
x = -change_width_before;
x = -change_height_before;
break;
}
if (dx)
*dx = x;
if (dy)
*dy = y;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View file

@ -41,6 +41,7 @@ void xwindow_takefocus(xcb_window_t);
void xwindow_set_cursor(xcb_window_t, xcb_cursor_t);
void xwindow_set_border_color(xcb_window_t, color_t *);
void xwindow_set_shape(xcb_window_t, int, int, enum xcb_shape_sk_t, cairo_surface_t *, int);
void xwindow_translate_for_gravity(xcb_gravity_t, int16_t, int16_t, int16_t, int16_t, int16_t *, int16_t *);
#endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80