2015-05-04 20 views
5

Ich versuche, über eine Zeigerbewegung benachrichtigt zu werden. Da ich nicht als Fenster-Manager ausführen möchte, muss ich für alle Fenster festlegen, die ich sowohl beim Start als auch beim Erstellen eines Benachrichtigungsereignisses erstelle.XCB - Ich erhalte keine Benachrichtigung über Bewegungsereignisse in allen Fenstern

Dies scheint im Allgemeinen gut zu funktionieren, und ich erhalte Bewegung benachrichtigen Ereignisse in allen Fenstern. Dies gilt jedoch nicht für Google Chrome-Fenster. Ich habe die Ereignismaske überprüft, indem ich sie explizit danach abgefragt habe und sie korrekt gesetzt wurde. Ich sehe in der Ausbreitungsmaske auch nichts Ungewöhnliches.

Was könnte dazu führen, dass Google Chrome keine Benachrichtigungsereignisse meldet? AFAIK, das X-Protokoll erlaubt das nicht, außer für aktive Pointergreifer, die Chrome sicher nicht hat.

So registriere ich mich in allen vorhandenen Fenstern. Ich nenne register_events auf den Root-Fenstern und wenn ich auch eine erstellen benachrichtigt Veranstaltung erhalten:

static void register_events(xcb_window_t window) { 
    xcb_void_cookie_t cookie = xcb_change_window_attributes_checked(connection,           
     window, XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_LEAVE_WINDOW }); 
    xcb_generic_error_t *error = xcb_request_check(connection, cookie); 
    if (error != NULL) { 
     xcb_disconnect(connection); 
     errx(EXIT_FAILURE, "could not subscribe to events on a window, bailing out"); 
    } 
} 

static void register_existing_windows(void) { 
    xcb_query_tree_reply_t *reply; 
    if ((reply = xcb_query_tree_reply(connection, xcb_query_tree(connection, root), 0)) == NULL) { 
     return; 
    } 

    int len = xcb_query_tree_children_length(reply); 
    xcb_window_t *children = xcb_query_tree_children(reply); 
    for (int i = 0; i < len; i++) { 
     register_events(children[i]); 
    } 

    xcb_flush(connection); 
    free(reply); 
} 
+1

Was bekommen Sie von 'xev', wenn Sie es an ein Chome-Fenster anhängen? –

+0

@AndrewHenle Wenn ich es anschließe und meine Maus dorthin bewege, es umherbewege, es ruhen lasse und das Fenster wieder verlasse, bekomme ich nur Enter/LeaveNotify, KeymapNotify und FocusIn/Out (http://pastebin.com/XQ3ZkVhW) –

+0

sollte ich auch weisen darauf hin, dass die gleiche Beobachtung mit Chrom auf einer anderen Maschine gemacht werden kann. –

Antwort

2

Während @Jay Kominek Antwort war hilfreich und gültig Ich habe jetzt erkannt, dass die Verwendung der Xinput-Erweiterung einen viel besseren Ansatz bietet, da sie keinerlei Auswirkungen auf Anwendungen hat.

Wenn Sie einfach auf den gesamten Baum klicken, treten alle möglichen Probleme auf, z. B. der Mauszeiger funktioniert in Chrome nicht mehr.

5

Die Chrome-Fenster erscheinen, die aus ganz dem Baum von verschachtelten untergeordneten Fenstern werden. Es scheint, dass Sie den Baum der Fenster laufen und sie alle überwachen müssen. Dieser Code nimmt Zeigerbewegungsereignisse über die Gesamtheit meiner Chrome-Fenster:

#include <stdio.h> 
#include <stdlib.h> 
#include <xcb/xcb.h> 
#include <X11/Xlib.h> 

static void register_events(xcb_connection_t *conn, 
          xcb_window_t window) { 
    xcb_void_cookie_t cookie = 
    xcb_change_window_attributes_checked(conn, 
             window, XCB_CW_EVENT_MASK, 
             (uint32_t[]) { 
              XCB_EVENT_MASK_POINTER_MOTION }); 
    xcb_generic_error_t *error = xcb_request_check(conn, cookie); 
    if (error != NULL) { 
    xcb_disconnect(conn); 
    exit(-1); 
    } 
} 

static void register_existing_windows(xcb_connection_t *conn, 
             xcb_window_t root) { 
    int i, len; 
    xcb_window_t *children; 
    xcb_query_tree_reply_t *reply; 
    if ((reply = xcb_query_tree_reply(conn, 
            xcb_query_tree(conn, root), 0)) 
     == NULL) 
    { 
     return; 
    } 

    len = xcb_query_tree_children_length(reply); 
    children = xcb_query_tree_children(reply); 
    for (i = 0; i < len; i++) { 
    register_events(conn, children[i]); 
    register_existing_windows(conn, children[i]); 
    } 

    xcb_flush(conn); 
} 

void main(void) { 
    int i=0; 

    /* Open the connection to the X server */ 
    xcb_connection_t *conn = xcb_connect (NULL, NULL); 

    /* Get the first screen */ 
    xcb_screen_t *screen = xcb_setup_roots_iterator (xcb_get_setup (conn)).data; 

    register_existing_windows(conn, screen->root); 

    while(1) { 
    xcb_generic_event_t *evt; 
    evt = xcb_wait_for_event(conn); 
    printf("%i\n", i++); 
    } 
} 

(das ist nur als Proof of Concept gedacht und nicht sehr schön.)

+0

Ich hatte eine Ahnung, dass es eine Verschachtelung Art von Problem sein könnte, aber sah nur "eine Ebene tief". Ich hätte nicht gedacht, dass ich * rekursiv sein müsste. Ich gebe dir eine Chance und komme zu dir zurück. Danke für die Antwort! –

+0

Ja, es scheint, das war das Problem. Ich dachte über Vermehrungsmasken zu kompliziert nach. Ich habe überprüft, bevor ich es jetzt repariere, dass, wenn ich ein * neues * Chrome-Fenster öffne, ich alle Ereignisse bekomme, da ich Erzeuge-Benachrichtigungs-Ereignisse sogar für alle Unterfenster erhalte. Nur dieser erste Teil war fehlerhaft. Danke, das hat mich verrückt gemacht! –

+1

Ahh, ich sehe es wurde gelöst. Willkommen in der verrückten Welt von XWindows. –