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.
This commit is contained in:
Michael Stapelberg 2009-08-06 00:59:48 +02:00
parent 20875494ee
commit 3bd724f08d
3 changed files with 52 additions and 11 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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);