From: Michael Stapelberg Date: Wed, 5 Aug 2009 22:59:48 +0000 (+0200) Subject: Bugfix: Track the user’s pointer over the root window and update current workspace... X-Git-Tag: 3.c~22 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=3bd724f08db431aebeff3d889ee6eb8b214fb099;p=i3%2Fi3 Bugfix: Track the user’s pointer over the root window and update current workspace (Thanks xeen) When not having any windows on the first workspace, switching to the second workspace using your mouse was not registered by i3. --- diff --git a/include/handlers.h b/include/handlers.h index 83b70894..5b776de7 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -35,6 +35,15 @@ int handle_key_press(void *ignored, xcb_connection_t *conn, int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_event_t *event); +/** + * When the user moves the mouse but does not change the active window + * (e.g. when having no windows opened but moving mouse on the root screen + * and crossing virtual screen boundaries), this callback gets called. + * + */ +int handle_motion_notify(void *ignored, xcb_connection_t *conn, + xcb_motion_notify_event_t *event); + /** * Checks if the button press was on a stack window, handles focus setting and * returns true if so, or false otherwise. diff --git a/src/handlers.c b/src/handlers.c index 9a402629..ffbde9fa 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -140,6 +140,29 @@ int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_ return 1; } +/* + * Called with coordinates of an enter_notify event or motion_notify event + * to check if the user crossed virtual screen boundaries and adjust the + * current workspace, if so. + * + */ +static void check_crossing_screen_boundary(uint32_t x, uint32_t y) { + i3Screen *screen; + + if ((screen = get_screen_containing(x, y)) == NULL) { + LOG("ERROR: No such screen\n"); + return; + } + if (screen == c_ws->screen) + return; + + c_ws->current_row = current_row; + c_ws->current_col = current_col; + c_ws = &workspaces[screen->current_workspace]; + current_row = c_ws->current_row; + current_col = c_ws->current_col; + LOG("We're now on virtual screen number %d\n", screen->num); +} /* * When the user moves the mouse pointer onto a window, this callback gets called. @@ -176,17 +199,7 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_ /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */ if (client == NULL) { LOG("Getting screen at %d x %d\n", event->root_x, event->root_y); - i3Screen *screen = get_screen_containing(event->root_x, event->root_y); - if (screen == NULL) { - LOG("ERROR: No such screen\n"); - return 0; - } - c_ws->current_row = current_row; - c_ws->current_col = current_col; - c_ws = &workspaces[screen->current_workspace]; - current_row = c_ws->current_row; - current_col = c_ws->current_col; - LOG("We're now on virtual screen number %d\n", screen->num); + check_crossing_screen_boundary(event->root_x, event->root_y); return 1; } @@ -212,6 +225,20 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_ return 1; } +/* + * When the user moves the mouse but does not change the active window + * (e.g. when having no windows opened but moving mouse on the root screen + * and crossing virtual screen boundaries), this callback gets called. + * + */ +int handle_motion_notify(void *ignored, xcb_connection_t *conn, xcb_motion_notify_event_t *event) { + LOG("pointer motion notify, getting screen at %d x %d\n", event->root_x, event->root_y); + + check_crossing_screen_boundary(event->root_x, event->root_y); + + return 1; +} + /* * Checks if the button press was on a stack window, handles focus setting and returns true * if so, or false otherwise. diff --git a/src/mainx.c b/src/mainx.c index 27e026b5..a26a957f 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -257,6 +257,10 @@ int main(int argc, char *argv[], char *env[]) { /* Configure request = window tried to change size on its own */ xcb_event_set_configure_request_handler(&evenths, handle_configure_request, NULL); + /* Motion notify = user moved his cursor (over the root window and may + * cross virtual screen boundaries doing that) */ + xcb_event_set_motion_notify_handler(&evenths, handle_motion_notify, NULL); + /* Client message are sent to the root window. The only interesting client message for us is _NET_WM_STATE, we honour _NET_WM_STATE_FULLSCREEN */ xcb_event_set_client_message_handler(&evenths, handle_client_message, NULL); @@ -277,6 +281,7 @@ int main(int argc, char *argv[], char *env[]) { XCB_EVENT_MASK_STRUCTURE_NOTIFY | /* when the user adds a screen (e.g. video projector), the root window gets a ConfigureNotify */ + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_ENTER_WINDOW }; xcb_change_window_attributes(conn, root, mask, values);