tests: implement xtest_sync_with_i3
The regular sync_with_i3 is not sufficient because i3test::XTEST uses a separate X11 connection.
This commit is contained in:
parent
c08ef36199
commit
14c8cf8622
|
@ -14,6 +14,7 @@ use ExtUtils::PkgConfig;
|
|||
use Exporter ();
|
||||
our @EXPORT = qw(
|
||||
inlinec_connect
|
||||
xtest_sync_with_i3
|
||||
set_xkb_group
|
||||
xtest_key_press
|
||||
xtest_key_release
|
||||
|
@ -38,7 +39,7 @@ i3test::XTEST - Inline::C wrappers for xcb-xtest and xcb-xkb
|
|||
# ineffective.
|
||||
my %sn_config;
|
||||
BEGIN {
|
||||
%sn_config = ExtUtils::PkgConfig->find('xcb-xkb xcb-xtest');
|
||||
%sn_config = ExtUtils::PkgConfig->find('xcb-xkb xcb-xtest xcb-util');
|
||||
}
|
||||
|
||||
use Inline C => Config => LIBS => $sn_config{libs}, CCFLAGS => $sn_config{cflags};
|
||||
|
@ -53,8 +54,12 @@ use Inline C => <<'END_OF_C_CODE';
|
|||
#include <xcb/xcb.h>
|
||||
#include <xcb/xkb.h>
|
||||
#include <xcb/xtest.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
|
||||
static xcb_connection_t *conn = NULL;
|
||||
static xcb_window_t sync_window;
|
||||
static xcb_window_t root_window;
|
||||
static xcb_atom_t i3_sync_atom;
|
||||
|
||||
bool inlinec_connect() {
|
||||
int screen;
|
||||
|
@ -89,9 +94,90 @@ bool inlinec_connect() {
|
|||
}
|
||||
free(usereply);
|
||||
|
||||
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, xcb_intern_atom(conn, 0, strlen("I3_SYNC"), "I3_SYNC"), NULL);
|
||||
i3_sync_atom = reply->atom;
|
||||
free(reply);
|
||||
|
||||
xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screen);
|
||||
root_window = root_screen->root;
|
||||
sync_window = xcb_generate_id(conn);
|
||||
xcb_create_window(conn,
|
||||
XCB_COPY_FROM_PARENT, // depth
|
||||
sync_window, // window
|
||||
root_window, // parent
|
||||
-15, // x
|
||||
-15, // y
|
||||
1, // width
|
||||
1, // height
|
||||
0, // border_width
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
|
||||
XCB_COPY_FROM_PARENT, // visual
|
||||
XCB_CW_OVERRIDE_REDIRECT, // value_mask
|
||||
(uint32_t[]){
|
||||
1, // override_redirect
|
||||
}); // value_list
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void xtest_sync_with_i3() {
|
||||
xcb_client_message_event_t ev;
|
||||
memset(&ev, '\0', sizeof(xcb_client_message_event_t));
|
||||
|
||||
const int nonce = rand() % 255;
|
||||
|
||||
ev.response_type = XCB_CLIENT_MESSAGE;
|
||||
ev.window = sync_window;
|
||||
ev.type = i3_sync_atom;
|
||||
ev.format = 32;
|
||||
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_flush(conn);
|
||||
|
||||
xcb_generic_event_t *event = NULL;
|
||||
while (1) {
|
||||
free(event);
|
||||
if ((event = xcb_wait_for_event(conn)) == NULL) {
|
||||
break;
|
||||
}
|
||||
if (event->response_type == 0) {
|
||||
fprintf(stderr, "X11 Error received! sequence %x\n", event->sequence);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Strip off the highest bit (set if the event is generated) */
|
||||
const int type = (event->response_type & 0x7F);
|
||||
switch (type) {
|
||||
case XCB_CLIENT_MESSAGE: {
|
||||
xcb_client_message_event_t *ev = (xcb_client_message_event_t *)event;
|
||||
{
|
||||
const uint32_t got = ev->data.data32[0];
|
||||
const uint32_t want = sync_window;
|
||||
if (got != want) {
|
||||
fprintf(stderr, "Ignoring ClientMessage: unknown window: got %d, want %d\n", got, want);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
{
|
||||
const uint32_t got = ev->data.data32[1];
|
||||
const uint32_t want = nonce;
|
||||
if (got != want) {
|
||||
fprintf(stderr, "Ignoring ClientMessage: unknown nonce: got %d, want %d\n", got, want);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Unexpected X11 event of type %d received (XCB_CLIENT_MESSAGE = %d)\n", type, XCB_CLIENT_MESSAGE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(event);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
@ -283,6 +369,10 @@ 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_i3()
|
||||
|
||||
Ensures i3 has processed all X11 events which were triggered by this module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael Stapelberg <michael@i3wm.org>
|
||||
|
|
|
@ -44,6 +44,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(107);
|
||||
xtest_key_release(107);
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Print',
|
||||
|
@ -55,6 +56,7 @@ is(listen_for_binding(
|
|||
xtest_key_press(36); # Return
|
||||
xtest_key_release(36); # Return
|
||||
xtest_key_release(133); # Super_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Mod4+Return',
|
||||
|
@ -67,6 +69,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(107);
|
||||
xtest_key_release(107);
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Print',
|
||||
|
@ -78,6 +81,7 @@ is(listen_for_binding(
|
|||
xtest_key_press(36); # Return
|
||||
xtest_key_release(36); # Return
|
||||
xtest_key_release(133); # Super_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Mod4+Return',
|
||||
|
|
|
@ -43,6 +43,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(107); # Print
|
||||
xtest_key_release(107); # Print
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Print',
|
||||
|
@ -54,6 +55,7 @@ is(listen_for_binding(
|
|||
xtest_key_press(107); # Print
|
||||
xtest_key_release(107); # Print
|
||||
xtest_key_release(37); # Control_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Control+Print',
|
||||
|
@ -65,6 +67,7 @@ is(listen_for_binding(
|
|||
xtest_key_press(56); # b
|
||||
xtest_key_release(56); # b
|
||||
xtest_key_release(64); # Alt_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Mod1+b',
|
||||
|
@ -78,6 +81,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(56); # b
|
||||
xtest_key_release(50); # Shift_L
|
||||
xtest_key_release(64); # Alt_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Mod1+Shift+b release',
|
||||
|
|
|
@ -30,7 +30,7 @@ fresh_workspace;
|
|||
|
||||
xtest_button_press(4, 50, 50);
|
||||
xtest_button_release(4, 50, 50);
|
||||
sync_with_i3;
|
||||
xtest_sync_with_i3;
|
||||
|
||||
is(focused_ws(), 'special', 'the binding was triggered');
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(87); # KP_End
|
||||
xtest_key_release(87); # KP_End
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'KP_End',
|
||||
|
@ -70,6 +71,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(87); # KP_1
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'KP_1',
|
||||
|
@ -81,6 +83,7 @@ is(listen_for_binding(
|
|||
xtest_key_press(38); # a
|
||||
xtest_key_release(38); # a
|
||||
xtest_key_release(133); # Super_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'a',
|
||||
|
@ -96,6 +99,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(133); # Super_L
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'a',
|
||||
|
@ -105,6 +109,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(9); # Escape
|
||||
xtest_key_release(9); # Escape
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Escape',
|
||||
|
@ -118,6 +123,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(9); # Escape
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Escape',
|
||||
|
@ -129,6 +135,7 @@ is(listen_for_binding(
|
|||
xtest_key_press(9); # Escape
|
||||
xtest_key_release(9); # Escape
|
||||
xtest_key_release(50); # Shift_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Shift+Escape',
|
||||
|
@ -144,6 +151,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(50); # Shift_L
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Shift+Escape',
|
||||
|
@ -157,6 +165,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(24); # q
|
||||
xtest_key_release(64); # Alt_L
|
||||
xtest_key_release(50); # Shift_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Mod1+Shift+q',
|
||||
|
@ -174,6 +183,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(50); # Shift_L
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Mod1+Shift+q',
|
||||
|
@ -183,6 +193,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(39); # s
|
||||
xtest_key_release(39); # s
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
's',
|
||||
|
@ -196,6 +207,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(39); # s
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
's',
|
||||
|
@ -228,6 +240,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(133); # Super_L
|
||||
xtest_key_release(133); # Super_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Super_L',
|
||||
|
@ -241,6 +254,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(133); # Super_L
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Super_L',
|
||||
|
@ -252,6 +266,7 @@ is(listen_for_binding(
|
|||
xtest_key_press(36); # Return
|
||||
xtest_key_release(36); # Return
|
||||
xtest_key_release(133); # Super_L
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Return',
|
||||
|
@ -267,6 +282,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(133); # Super_L
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'Return',
|
||||
|
@ -297,6 +313,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(87); # KP_End
|
||||
xtest_key_release(87); # KP_End
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'KP_End',
|
||||
|
@ -306,6 +323,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_key_press(88); # KP_Down
|
||||
xtest_key_release(88); # KP_Down
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'KP_Down',
|
||||
|
@ -319,6 +337,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(87); # KP_1
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'timeout',
|
||||
|
@ -332,6 +351,7 @@ is(listen_for_binding(
|
|||
xtest_key_release(88); # KP_2
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'timeout',
|
||||
|
@ -369,6 +389,7 @@ is(listen_for_binding(
|
|||
xtest_button_release(4, 50, 50);
|
||||
xtest_key_press(77); # disable Num_Lock
|
||||
xtest_key_release(77); # disable Num_Lock
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'button4',
|
||||
|
@ -378,6 +399,7 @@ is(listen_for_binding(
|
|||
sub {
|
||||
xtest_button_press(4, 50, 50);
|
||||
xtest_button_release(4, 50, 50);
|
||||
xtest_sync_with_i3;
|
||||
},
|
||||
),
|
||||
'button4',
|
||||
|
|
Loading…
Reference in New Issue