Last active
January 29, 2019 16:38
-
-
Save woodensquares/9b5c7d3e186c5d49540f29c81d688e1e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/include/xcb.h b/include/xcb.h | |
index b7eed2c..c51adf4 100644 | |
--- a/include/xcb.h | |
+++ b/include/xcb.h | |
@@ -51,6 +51,7 @@ | |
ConfigureNotify */ \ | |
XCB_EVENT_MASK_POINTER_MOTION | \ | |
XCB_EVENT_MASK_PROPERTY_CHANGE | \ | |
+ XCB_EVENT_MASK_LEAVE_WINDOW | \ | |
XCB_EVENT_MASK_ENTER_WINDOW) | |
#define xmacro(atom) xcb_atom_t A_##atom; | |
diff --git a/src/handlers.c b/src/handlers.c | |
index 2991d7c..07e2a7a 100644 | |
--- a/src/handlers.c | |
+++ b/src/handlers.c | |
@@ -22,6 +22,7 @@ | |
int randr_base = -1; | |
int xkb_base = -1; | |
int xkb_current_group; | |
+extern uint8_t previous_screen; | |
/* After mapping/unmapping windows, a notify event is generated. However, we don’t want it, | |
since it’d trigger an infinite loop of switching between the different windows when | |
@@ -122,13 +123,28 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) { | |
* When the user moves the mouse pointer onto a window, this callback gets called. | |
* | |
*/ | |
+static void handle_leave_notify(xcb_enter_notify_event_t *event) { | |
+ DLOG("leave_notify for %08x, mode = %d, detail %d, serial %d, focus %d\n", | |
+ event->event, event->mode, event->detail, event->sequence, | |
+ event->same_screen_focus); | |
+ | |
+ if (event->mode != XCB_NOTIFY_MODE_NORMAL) { | |
+ DLOG("This was not a normal notify, ignoring\n"); | |
+ return; | |
+ } | |
+ | |
+ /* When leaving we don't care about the previous value */ | |
+ previous_screen = event->same_screen_focus; | |
+ return; | |
+} | |
+ | |
static void handle_enter_notify(xcb_enter_notify_event_t *event) { | |
Con *con; | |
- | |
last_timestamp = event->time; | |
- DLOG("enter_notify for %08x, mode = %d, detail %d, serial %d\n", | |
- event->event, event->mode, event->detail, event->sequence); | |
+ DLOG("enter_notify for %08x, mode = %d, detail %d, serial %d, focus %d\n", | |
+ event->event, event->mode, event->detail, event->sequence, | |
+ event->same_screen_focus); | |
DLOG("coordinates %d, %d\n", event->event_x, event->event_y); | |
if (event->mode != XCB_NOTIFY_MODE_NORMAL) { | |
DLOG("This was not a normal notify, ignoring\n"); | |
@@ -141,6 +157,18 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) { | |
return; | |
} | |
+ bool refresh = false; | |
+ if (event->same_screen_focus != previous_screen) { | |
+ /* Note we should not skip on previous_screen being | |
+ * UINT8_MAX because we don't want the first display | |
+ * switch to be missed (say we have i3 on :0.0 and :0.1, | |
+ * the :0.1 i3 will not get an event in general until | |
+ * the first time the user tries to use it, since the | |
+ * mouse pointer is likely on :0.0 to start with */ | |
+ DLOG("The user changed screens\n"); | |
+ refresh = true; | |
+ } | |
+ | |
bool enter_child = false; | |
/* Get container by frame or by child window */ | |
if ((con = con_by_frame_id(event->event)) == NULL) { | |
@@ -152,6 +180,15 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) { | |
if (con == NULL) { | |
DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y); | |
check_crossing_screen_boundary(event->root_x, event->root_y); | |
+ | |
+ if (refresh && ! config.disable_focus_follows_mouse) { | |
+ /* The user entered the root window coming from another X | |
+ * screen, this means that the above will not have called | |
+ * tree_render (leaving the keyboard focus on the other | |
+ * screen) let's focus a rerender. | |
+ */ | |
+ tree_render(); | |
+ } | |
return; | |
} | |
@@ -185,20 +222,24 @@ static void handle_enter_notify(xcb_enter_notify_event_t *event) { | |
if (config.disable_focus_follows_mouse) | |
return; | |
- /* if this container is already focused, there is nothing to do. */ | |
- if (con == focused) | |
+ /* if this container is already focused, there is nothing to do | |
+ * unless we have switched screens. | |
+ */ | |
+ if (con == focused && !refresh) | |
return; | |
- /* Get the currently focused workspace to check if the focus change also | |
- * involves changing workspaces. If so, we need to call workspace_show() to | |
- * correctly update state and send the IPC event. */ | |
+ /* Get the currently focused workspace to check if the focus change | |
+ * also involves changing workspaces. If so, or if we switched | |
+ * screens, we need to call workspace_show() to correctly update | |
+ * state and send the IPC event. */ | |
Con *ws = con_get_workspace(con); | |
- if (ws != con_get_workspace(focused)) | |
+ if (ws != con_get_workspace(focused) || refresh) | |
workspace_show(ws); | |
focused_id = XCB_NONE; | |
con_focus(con_descend_focused(con)); | |
tree_render(); | |
+ previous_screen = event->same_screen_focus; | |
return; | |
} | |
@@ -1454,6 +1495,10 @@ void handle_event(int type, xcb_generic_event_t *event) { | |
handle_enter_notify((xcb_enter_notify_event_t *)event); | |
break; | |
+ case XCB_LEAVE_NOTIFY: | |
+ handle_leave_notify((xcb_enter_notify_event_t *)event); | |
+ break; | |
+ | |
/* 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 and _NET_WM_STATE_DEMANDS_ATTENTION */ | |
diff --git a/src/main.c b/src/main.c | |
index b2ce17d..d14567d 100644 | |
--- a/src/main.c | |
+++ b/src/main.c | |
@@ -37,6 +37,7 @@ int listen_fds; | |
static struct ev_check *xcb_check; | |
extern Con *focused; | |
+extern uint8_t previous_screen; | |
char **start_argv; | |
@@ -474,6 +475,7 @@ int main(int argc, char *argv[]) { | |
root_screen = xcb_aux_get_screen(conn, conn_screen); | |
root = root_screen->root; | |
+ previous_screen = UINT8_MAX; | |
/* Place requests for the atoms we need as soon as possible */ | |
#define xmacro(atom) \ | |
diff --git a/src/tree.c b/src/tree.c | |
index e848a6a..9220493 100644 | |
--- a/src/tree.c | |
+++ b/src/tree.c | |
@@ -13,6 +13,7 @@ | |
struct Con *croot; | |
struct Con *focused; | |
+uint8_t previous_screen; | |
struct all_cons_head all_cons = TAILQ_HEAD_INITIALIZER(all_cons); | |
Having the same problem. Are you having to recompile i3? Using more than one X screen seems to cause i3 to not work properly.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you don't mind me asking how do you implement this into i3? I have the same problem of using multiple XScreens and multiple i3 sessions. Thanks.