]> git.sur5r.net Git - i3/i3/commitdiff
tests: implement xtest_sync_with_i3
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 30 Sep 2017 09:27:53 +0000 (11:27 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sat, 30 Sep 2017 09:28:20 +0000 (11:28 +0200)
The regular sync_with_i3 is not sufficient because i3test::XTEST uses a separate
X11 connection.

testcases/lib/i3test/XTEST.pm
testcases/t/257-keypress-group1-fallback.t
testcases/t/258-keypress-release.t
testcases/t/286-root-window-mouse-binding.t
testcases/t/290-keypress-numlock.t

index 1ca964b154813d6897f7c43c3b40ab58c187cbb0..40759cfdb1098942358c2e61d6bc7bdcc5ef7c13 100644 (file)
@@ -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>
index f9166fadbcbfeddff82ead75870a17773d0ff81c..e3874c92b2ad27ffeedb9e5bed4ce05ae2d96dff 100644 (file)
@@ -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',
index 72bfc86281e2831355ebca4609713d3b8a4690ac..bf446003b38ab6d1d27e67600eb989e6bdb7c96d 100644 (file)
@@ -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',
index 6c1b5d6ace7b5f561df1c66672ee8c5e55f0ac3f..0da373b74e3168129d95b6971dcf60200d5011b7 100644 (file)
@@ -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');
 
index 5137c35fc8e55d0e3ed1fb1f45e8c282b1d4176f..b896e4320f1b2d46b6611c373c2b36f4767581ba 100644 (file)
@@ -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',
@@ -376,8 +397,9 @@ is(listen_for_binding(
 
 is(listen_for_binding(
     sub {
-       xtest_button_press(4, 50, 50);
-       xtest_button_release(4, 50, 50);
+        xtest_button_press(4, 50, 50);
+        xtest_button_release(4, 50, 50);
+        xtest_sync_with_i3;
     },
     ),
    'button4',