From 3bd724f08db431aebeff3d889ee6eb8b214fb099 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 6 Aug 2009 00:59:48 +0200 Subject: [PATCH] =?utf8?q?Bugfix:=20Track=20the=20user=E2=80=99s=20pointer?= =?utf8?q?=20over=20the=20root=20window=20and=20update=20current=20workspa?= =?utf8?q?ce=20(Thanks=20xeen)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When not having any windows on the first workspace, switching to the second workspace using your mouse was not registered by i3. --- include/handlers.h | 9 +++++++++ src/handlers.c | 49 +++++++++++++++++++++++++++++++++++----------- src/mainx.c | 5 +++++ 3 files changed, 52 insertions(+), 11 deletions(-) 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); -- 2.39.5