diff --git a/i3bar/include/xcb_atoms.def b/i3bar/include/xcb_atoms.def index 65a147c47..453dd0ceb 100644 --- a/i3bar/include/xcb_atoms.def +++ b/i3bar/include/xcb_atoms.def @@ -9,4 +9,5 @@ ATOM_DO(_NET_SYSTEM_TRAY_OPCODE) ATOM_DO(_NET_SYSTEM_TRAY_COLORS) ATOM_DO(_XEMBED_INFO) ATOM_DO(_XEMBED) +ATOM_DO(I3_SYNC) #undef ATOM_DO diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index fed969df7..dfa66ee2d 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -678,8 +678,26 @@ static void configure_trayclients(void) { * */ static void handle_client_message(xcb_client_message_event_t *event) { - if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] && - event->format == 32) { + if (event->type == atoms[I3_SYNC]) { + xcb_window_t window = event->data.data32[0]; + uint32_t rnd = event->data.data32[1]; + DLOG("[i3 sync protocol] Forwarding random value %d, X11 window 0x%08x to i3\n", rnd, window); + + void *reply = scalloc(32, 1); + xcb_client_message_event_t *ev = reply; + + ev->response_type = XCB_CLIENT_MESSAGE; + ev->window = window; + ev->type = atoms[I3_SYNC]; + ev->format = 32; + ev->data.data32[0] = window; + ev->data.data32[1] = rnd; + + xcb_send_event(conn, false, xcb_root, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char *)ev); + xcb_flush(conn); + free(reply); + } else if (event->type == atoms[_NET_SYSTEM_TRAY_OPCODE] && + event->format == 32) { DLOG("_NET_SYSTEM_TRAY_OPCODE received\n"); /* event->data.data32[0] is the timestamp */ uint32_t op = event->data.data32[1]; diff --git a/testcases/lib/i3test/XTEST.pm b/testcases/lib/i3test/XTEST.pm index 5c1dfe13a..4c464c5e3 100644 --- a/testcases/lib/i3test/XTEST.pm +++ b/testcases/lib/i3test/XTEST.pm @@ -14,6 +14,7 @@ use ExtUtils::PkgConfig; use Exporter (); our @EXPORT = qw( inlinec_connect + xtest_sync_with xtest_sync_with_i3 set_xkb_group xtest_key_press @@ -118,7 +119,7 @@ bool inlinec_connect() { return true; } -void xtest_sync_with_i3() { +void xtest_sync_with(int window) { xcb_client_message_event_t ev; memset(&ev, '\0', sizeof(xcb_client_message_event_t)); @@ -131,7 +132,7 @@ void xtest_sync_with_i3() { ev.data.data32[0] = sync_window; ev.data.data32[1] = nonce; - xcb_send_event(conn, false, root_window, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char *)&ev); + xcb_send_event(conn, false, (xcb_window_t)window, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char *)&ev); xcb_flush(conn); xcb_generic_event_t *event = NULL; @@ -176,6 +177,10 @@ void xtest_sync_with_i3() { free(event); } +void xtest_sync_with_i3() { + xtest_sync_with((int)root_window); +} + // NOTE: while |group| should be a uint8_t, Inline::C will not define the // function unless we use an int. bool set_xkb_group(int group) { @@ -287,6 +292,11 @@ Sends a ButtonRelease event via XTEST, with the specified C<$button>. Returns false when there was an X11 error, true otherwise. +=head2 xtest_sync_with($window) + +Ensures the specified window has processed all X11 events which were triggered +by this module, provided the window response to the i3 sync protocol. + =head2 xtest_sync_with_i3() Ensures i3 has processed all X11 events which were triggered by this module. diff --git a/testcases/t/525-i3bar-mouse-bindings.t b/testcases/t/525-i3bar-mouse-bindings.t index 1dfa6aa71..d3216d974 100644 --- a/testcases/t/525-i3bar-mouse-bindings.t +++ b/testcases/t/525-i3bar-mouse-bindings.t @@ -61,7 +61,7 @@ sub i3bar_present { for my $node (@{$nodes}) { my $props = $node->{window_properties}; if (defined($props) && $props->{class} eq 'i3bar') { - return 1; + return $node->{window}; } } @@ -73,13 +73,17 @@ sub i3bar_present { return i3bar_present(\@children); } -if (i3bar_present($i3->get_tree->recv->{nodes})) { +my $i3bar_window = i3bar_present($i3->get_tree->recv->{nodes}); +if ($i3bar_window) { ok(1, 'i3bar present'); } else { my $con = $cv->recv; ok($con, 'i3bar appeared'); + $i3bar_window = $con->{window}; } +diag('i3bar window = ' . $i3bar_window); + my $left = open_window; my $right = open_window; sync_with_i3; @@ -99,7 +103,7 @@ subtest 'button 1 moves focus left', \&focus_subtest, sub { xtest_button_press(1, 3, 3); xtest_button_release(1, 3, 3); - xtest_sync_with_i3; + xtest_sync_with($i3bar_window); }, [ $left->{id} ], 'button 1 moves focus left'; @@ -108,7 +112,7 @@ subtest 'button 2 moves focus right', \&focus_subtest, sub { xtest_button_press(2, 3, 3); xtest_button_release(2, 3, 3); - xtest_sync_with_i3; + xtest_sync_with($i3bar_window); }, [ $right->{id} ], 'button 2 moves focus right'; @@ -117,7 +121,7 @@ subtest 'button 3 moves focus left', \&focus_subtest, sub { xtest_button_press(3, 3, 3); xtest_button_release(3, 3, 3); - xtest_sync_with_i3; + xtest_sync_with($i3bar_window); }, [ $left->{id} ], 'button 3 moves focus left'; @@ -126,7 +130,7 @@ subtest 'button 4 moves focus right', \&focus_subtest, sub { xtest_button_press(4, 3, 3); xtest_button_release(4, 3, 3); - xtest_sync_with_i3; + xtest_sync_with($i3bar_window); }, [ $right->{id} ], 'button 4 moves focus right'; @@ -135,7 +139,7 @@ subtest 'button 5 moves focus left', \&focus_subtest, sub { xtest_button_press(5, 3, 3); xtest_button_release(5, 3, 3); - xtest_sync_with_i3; + xtest_sync_with($i3bar_window); }, [ $left->{id} ], 'button 5 moves focus left';