diff --git a/event.c b/event.c index c3d1d3ad..617f2032 100644 --- a/event.c +++ b/event.c @@ -311,29 +311,37 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev) if((c = client_getbywin(ev->window))) { area_t geometry = c->geometry; + uint16_t bw = c->border_width; + uint16_t tb_left = c->titlebar[CLIENT_TITLEBAR_LEFT].size; + uint16_t tb_right = c->titlebar[CLIENT_TITLEBAR_RIGHT].size; + uint16_t tb_top = c->titlebar[CLIENT_TITLEBAR_TOP].size; + uint16_t tb_bottom = c->titlebar[CLIENT_TITLEBAR_BOTTOM].size; + uint16_t deco_left = bw + tb_left; + uint16_t deco_right = bw + tb_right; + uint16_t deco_top = bw + tb_top; + uint16_t deco_bottom = bw + tb_bottom; int16_t diff_w = 0, diff_h = 0, diff_border = 0; if(ev->value_mask & XCB_CONFIG_WINDOW_X) { + int16_t diff = 0; geometry.x = ev->x; - /* The ConfigureRequest specifies the position of the outer corner of the client window, we want the frame */ - geometry.x -= c->titlebar[CLIENT_TITLEBAR_LEFT].size; - geometry.x -= c->border_width; + xwindow_translate_for_gravity(c->size_hints.win_gravity, deco_left, 0, deco_right, 0, &diff, NULL); + geometry.x += diff; } if(ev->value_mask & XCB_CONFIG_WINDOW_Y) { + int16_t diff = 0; geometry.y = ev->y; - /* The ConfigureRequest specifies the position of the outer corner of the client window, we want the frame */ - geometry.y -= c->titlebar[CLIENT_TITLEBAR_TOP].size; - geometry.y -= c->border_width; + xwindow_translate_for_gravity(c->size_hints.win_gravity, 0, deco_top, 0, deco_bottom, NULL, &diff); + geometry.y += diff; } 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; + geometry.width += tb_left + tb_right; diff_w = geometry.width - old_w; } if(ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT) @@ -341,15 +349,14 @@ event_handle_configurerequest(xcb_configure_request_event_t *ev) 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; + geometry.height += tb_top + tb_bottom; diff_h = geometry.height - old_h; } if(ev->value_mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { lua_State *L = globalconf_get_lua_State(); - diff_border = ev->border_width - c->border_width; + diff_border = ev->border_width - bw; diff_h += diff_border; diff_w += diff_border; diff --git a/objects/client.c b/objects/client.c index ba979def..c88d7203 100644 --- a/objects/client.c +++ b/objects/client.c @@ -128,6 +128,7 @@ static area_t titlebar_get_area(client_t *c, client_titlebar_t bar); static drawable_t *titlebar_get_drawable(lua_State *L, client_t *c, int cl_idx, client_titlebar_t bar); +static void client_resize_do(client_t *c, area_t geometry, bool force_notice); /** Collect a client. * \param L The Lua VM state. @@ -466,6 +467,24 @@ client_focus_refresh(void) win, globalconf.timestamp); } +static void +border_width_callback(client_t *c, uint16_t old_width, uint16_t new_width) +{ + if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY) + { + area_t geometry = c->geometry; + int16_t diff = new_width - old_width; + int16_t diff_x = 0, diff_y = 0; + xwindow_translate_for_gravity(c->size_hints.win_gravity, + diff, diff, diff, diff, + &diff_x, &diff_y); + geometry.x += diff_x; + geometry.y += diff_y; + /* force_notice = true -> inform client about changes */ + client_resize_do(c, geometry, true); + } +} + static void client_update_properties(lua_State *L, int cidx, client_t *c) { @@ -537,6 +556,7 @@ client_manage(xcb_window_t w, xcb_get_geometry_reply_t *wgeom, xcb_get_window_at client_t *c = client_new(L); xcb_screen_t *s = globalconf.screen; + c->border_width_callback = (void (*) (void *, uint16_t, uint16_t)) border_width_callback; /* consider the window banned */ c->isbanned = true; @@ -1847,27 +1867,43 @@ titlebar_resize(lua_State *L, int cidx, client_t *c, client_titlebar_t bar, int * titlebars should keep its current size!) */ area_t geometry = c->geometry; int change = size - c->titlebar[bar].size; + int16_t diff_top = 0, diff_bottom = 0, diff_right = 0, diff_left = 0; switch (bar) { case CLIENT_TITLEBAR_TOP: geometry.height += change; + diff_top = change; property_name = "property::titlebar_top"; break; case CLIENT_TITLEBAR_BOTTOM: geometry.height += change; + diff_bottom = change; property_name = "property::titlebar_bottom"; break; case CLIENT_TITLEBAR_RIGHT: geometry.width += change; + diff_right = change; property_name = "property::titlebar_right"; break; case CLIENT_TITLEBAR_LEFT: geometry.width += change; + diff_left = change; property_name = "property::titlebar_left"; break; default: fatal("Unknown titlebar kind %d\n", (int) bar); } + 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_left, diff_top, + diff_right, diff_bottom, + &diff_x, &diff_y); + geometry.x += diff_x; + geometry.y += diff_y; + } + c->titlebar[bar].size = size; client_resize_do(c, geometry, true); diff --git a/objects/window.c b/objects/window.c index 45077bbf..94254bef 100644 --- a/objects/window.c +++ b/objects/window.c @@ -178,6 +178,7 @@ void window_set_border_width(lua_State *L, int idx, int width) { window_t *window = luaA_checkudata(L, idx, &window_class); + uint16_t old_width = window->border_width; if(width == window->border_width || width < 0) return; @@ -189,6 +190,9 @@ window_set_border_width(lua_State *L, int idx, int width) window->border_width = width; + if(window->border_width_callback) + (*window->border_width_callback)(window, old_width, width); + luaA_object_emit_signal(L, idx, "property::border_width", 0); } diff --git a/objects/window.h b/objects/window.h index 30e492c3..7c20eee7 100644 --- a/objects/window.h +++ b/objects/window.h @@ -67,7 +67,9 @@ typedef enum /** Border width */ \ uint16_t border_width; \ /** The window type */ \ - window_type_t type; + window_type_t type; \ + /** The border width callback */ \ + void (*border_width_callback)(void *, uint16_t old, uint16_t new); /** Window structure */ typedef struct diff --git a/xwindow.c b/xwindow.c index 55b27f62..f1ec2881 100644 --- a/xwindow.c +++ b/xwindow.c @@ -417,7 +417,7 @@ void xwindow_translate_for_gravity(xcb_gravity_t gravity, int16_t change_width_b break; case XCB_GRAVITY_STATIC: x = -change_width_before; - x = -change_height_before; + y = -change_height_before; break; }