From 053020f2db7d6e175d68ac4b0bf1fc3d6de56f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20B=C3=BCrk?= Date: Sat, 5 Sep 2015 12:35:28 +0200 Subject: [PATCH] Support moving dock clients to another output. This fixes #1883 where a race condition between i3 and i3bar caused two i3bar clients to be put onto the same output. --- src/handlers.c | 26 ++++++++++++-- testcases/t/526-reconfigure-dock.t | 57 ++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 testcases/t/526-reconfigure-dock.t diff --git a/src/handlers.c b/src/handlers.c index 1e7eef1e..f3c2350e 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -386,15 +386,35 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { return; } - /* Dock windows can be reconfigured in their height */ + /* Dock windows can be reconfigured in their height and moved to another output. */ if (con->parent && con->parent->type == CT_DOCKAREA) { - DLOG("Dock window, only height reconfiguration allowed\n"); + DLOG("Reconfiguring dock window (con = %p).\n", con); if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { - DLOG("Height given, changing\n"); + DLOG("Dock client wants to change height to %d, we can do that.\n", event->height); con->geometry.height = event->height; tree_render(); } + + if (event->value_mask & XCB_CONFIG_WINDOW_X || event->value_mask & XCB_CONFIG_WINDOW_Y) { + int16_t x = event->value_mask & XCB_CONFIG_WINDOW_X ? event->x : (int16_t)con->geometry.x; + int16_t y = event->value_mask & XCB_CONFIG_WINDOW_Y ? event->y : (int16_t)con->geometry.y; + + Con *current_output = con_get_output(con); + Output *target = get_output_containing(x, y); + if (target != NULL && current_output != target->con) { + DLOG("Dock client is requested to be moved to output %s, moving it there.\n", target->name); + Match *match; + Con *nc = con_for_window(target->con, con->window, &match); + DLOG("Dock client will be moved to container %p.\n", nc); + con_detach(con); + con_attach(con, nc, false); + + tree_render(); + } else { + DLOG("Dock client will not be moved, we only support moving it to another output.\n"); + } + } } fake_absolute_configure_notify(con); diff --git a/testcases/t/526-reconfigure-dock.t b/testcases/t/526-reconfigure-dock.t new file mode 100644 index 00000000..9e3ed3f2 --- /dev/null +++ b/testcases/t/526-reconfigure-dock.t @@ -0,0 +1,57 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Test reconfiguration of dock clients. +# Ticket: #1883 +use i3test i3_autostart => 0; + +my ($config, $pid, $window, $rect); +my (@docks); + +############################################################################### +# 1: Given two screens A and B and a dock client on screen A, when the dock +# client is reconfigured to be positioned on screen B, then the client is +# moved to the correct position. +############################################################################### + +$config = < $x->atom(name => '_NET_WM_WINDOW_TYPE_DOCK') + }); + +$rect = $window->rect; +is($rect->x, 0, 'sanity check: dock client is on the left screen'); + +$window->rect(X11::XCB::Rect->new(x => 1024, y => 0, width => 1024, height => 30)); +sync_with_i3; + +@docks = get_dock_clients; +is(@docks, 1, 'there is still exactly one dock'); + +is($docks[0]->{rect}->{x}, 1024, 'dock client has moved to the other screen'); + +exit_gracefully($pid); + +############################################################################### + +done_testing;