From 8e5a831e276453ea4cc61d35a9654ff8b8f18c2f Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 13 Apr 2010 18:43:37 +0200 Subject: [PATCH] re-add focus follows mouse handling --- include/handlers.h | 2 +- include/util.h | 1 + src/cfgparse.y | 8 +++ src/config.c | 2 + src/handlers.c | 153 ++++++++++++++++++++++++--------------------- src/nc.c | 7 +++ src/util.c | 7 +++ 7 files changed, 108 insertions(+), 72 deletions(-) diff --git a/include/handlers.h b/include/handlers.h index f4aaf582..a691b35a 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -21,7 +21,6 @@ int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_t *event); -#if 0 /** * When the user moves the mouse pointer onto a window, this callback gets * called. @@ -30,6 +29,7 @@ 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); +#if 0 /** * 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 diff --git a/include/util.h b/include/util.h index 5d954d39..cca6985d 100644 --- a/include/util.h +++ b/include/util.h @@ -36,6 +36,7 @@ while (0) int min(int a, int b); int max(int a, int b); +bool rect_contains(Rect rect, uint32_t x, uint32_t y); /** * Updates *destination with new_value and returns true if it was changed or false diff --git a/src/cfgparse.y b/src/cfgparse.y index 19bfaec1..99367adb 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -486,6 +486,7 @@ workspace_name: assign: TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow assign_target { +#if 0 printf("assignment of %s\n", $3); struct Assignment *new = $6; @@ -493,29 +494,36 @@ assign: printf(" floating = %d\n", new->floating); new->windowclass_title = $3; TAILQ_INSERT_TAIL(&assignments, new, assignments); +#endif } ; assign_target: NUMBER { +#if 0 struct Assignment *new = scalloc(sizeof(struct Assignment)); new->workspace = $1; new->floating = ASSIGN_FLOATING_NO; $$ = new; +#endif } | '~' { +#if 0 struct Assignment *new = scalloc(sizeof(struct Assignment)); new->floating = ASSIGN_FLOATING_ONLY; $$ = new; +#endif } | '~' NUMBER { +#if 0 struct Assignment *new = scalloc(sizeof(struct Assignment)); new->workspace = $2; new->floating = ASSIGN_FLOATING; $$ = new; +#endif } ; diff --git a/src/config.c b/src/config.c index 60c11fe7..2e611e95 100644 --- a/src/config.c +++ b/src/config.c @@ -305,6 +305,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, SLIST_REMOVE(&modes, mode, Mode, modes); } +#if 0 struct Assignment *assign; while (!TAILQ_EMPTY(&assignments)) { assign = TAILQ_FIRST(&assignments); @@ -312,6 +313,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, TAILQ_REMOVE(&assignments, assign, assignments); FREE(assign); } +#endif /* Clear workspace names */ #if 0 diff --git a/src/handlers.c b/src/handlers.c index b5609540..80f1e669 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -20,12 +20,12 @@ static SLIST_HEAD(ignore_head, Ignore_Event) ignore_events; static void add_ignore_event(const int sequence) { - struct Ignore_Event *event = smalloc(sizeof(struct Ignore_Event)); + struct Ignore_Event *event = smalloc(sizeof(struct Ignore_Event)); - event->sequence = sequence; - event->added = time(NULL); + event->sequence = sequence; + event->added = time(NULL); - SLIST_INSERT_HEAD(&ignore_events, event, ignore_events); + SLIST_INSERT_HEAD(&ignore_events, event, ignore_events); } /* @@ -33,26 +33,27 @@ static void add_ignore_event(const int sequence) { * */ static bool event_is_ignored(const int sequence) { - struct Ignore_Event *event; - time_t now = time(NULL); - for (event = SLIST_FIRST(&ignore_events); event != SLIST_END(&ignore_events);) { - if ((now - event->added) > 5) { - struct Ignore_Event *save = event; - event = SLIST_NEXT(event, ignore_events); - SLIST_REMOVE(&ignore_events, save, Ignore_Event, ignore_events); - free(save); - } else event = SLIST_NEXT(event, ignore_events); - } - - SLIST_FOREACH(event, &ignore_events, ignore_events) { - if (event->sequence == sequence) { - SLIST_REMOVE(&ignore_events, event, Ignore_Event, ignore_events); - free(event); - return true; - } - } + struct Ignore_Event *event; + time_t now = time(NULL); + for (event = SLIST_FIRST(&ignore_events); event != SLIST_END(&ignore_events);) { + if ((now - event->added) > 5) { + struct Ignore_Event *save = event; + event = SLIST_NEXT(event, ignore_events); + SLIST_REMOVE(&ignore_events, save, Ignore_Event, ignore_events); + free(save); + } else event = SLIST_NEXT(event, ignore_events); + } + + SLIST_FOREACH(event, &ignore_events, ignore_events) { + if (event->sequence != sequence) + continue; + + SLIST_REMOVE(&ignore_events, event, Ignore_Event, ignore_events); + free(event); + return true; + } - return false; + return false; } /* @@ -140,68 +141,78 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) { if (first_client != NULL) set_focus(global_conn, first_client, true); } +#endif /* * When the user moves the mouse pointer onto a window, this callback gets called. * */ -int handle_enter_notify(void *ignored, xcb_connection_t *conn, xcb_enter_notify_event_t *event) { - DLOG("enter_notify for %08x, mode = %d, detail %d, serial %d\n", event->event, event->mode, event->detail, event->sequence); - if (event->mode != XCB_NOTIFY_MODE_NORMAL) { - DLOG("This was not a normal notify, ignoring\n"); - return 1; - } - /* Some events are not interesting, because they were not generated actively by the - user, but by reconfiguration of windows */ - if (event_is_ignored(event->sequence)) - return 1; +int handle_enter_notify(void *ignored, xcb_connection_t *conn, + xcb_enter_notify_event_t *event) { + Con *con; - /* This was either a focus for a client’s parent (= titlebar)… */ - Client *client = table_get(&by_parent, event->event); - /* …or the client itself */ - if (client == NULL) - client = table_get(&by_child, event->event); + DLOG("enter_notify for %08x, mode = %d, detail %d, serial %d\n", + event->event, event->mode, event->detail, event->sequence); + DLOG("coordinates %x, %x\n", event->event_x, event->event_y); + if (event->mode != XCB_NOTIFY_MODE_NORMAL) { + DLOG("This was not a normal notify, ignoring\n"); + return 1; + } + /* Some events are not interesting, because they were not generated + * actively by the user, but by reconfiguration of windows */ + if (event_is_ignored(event->sequence)) + return 1; - /* Check for stack windows */ - if (client == NULL) { - struct Stack_Window *stack_win; - SLIST_FOREACH(stack_win, &stack_wins, stack_windows) - if (stack_win->window == event->event) { - client = stack_win->container->currently_focused; - break; - } - } + /* Get container by frame or by child window */ + if ((con = con_by_frame_id(event->event)) == NULL) + con = con_by_window_id(event->event); + /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */ + 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); + return 1; + } - /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */ - if (client == 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); - return 1; - } + /* see if the user entered the window on a certain window decoration */ + int layout = con->layout; + Con *child; + TAILQ_FOREACH(child, &(con->nodes_head), nodes) + if (rect_contains(child->deco_rect, event->event_x, event->event_y)) { + LOG("using child %p / %s instead!\n", child, child->name); + con = child; + break; + } + + /* for stacked/tabbed layout we do not want to change focus when the user + * enters the window at the decoration of any child window. */ + if (layout == L_STACKED || layout == L_TABBED) { + con = TAILQ_FIRST(&(con->parent->focus_head)); + LOG("using focused %p / %s instead\n", con, con->name); + } - /* Do plausibility checks: This event may be useless for us if it occurs on a window - which is in a stacked container but not the focused one */ - if (client->container != NULL && - client->container->mode == MODE_STACK && - client->container->currently_focused != client) { - DLOG("Plausibility check says: no\n"); - return 1; - } +#if 0 + if (client->workspace != c_ws && client->workspace->output == c_ws->output) { + /* This can happen when a client gets assigned to a different workspace than + * the current one (see src/mainx.c:reparent_window). Shortly after it was created, + * an enter_notify will follow. */ + DLOG("enter_notify for a client on a different workspace but the same screen, ignoring\n"); + return 1; + } +#endif - if (client->workspace != c_ws && client->workspace->output == c_ws->output) { - /* This can happen when a client gets assigned to a different workspace than - * the current one (see src/mainx.c:reparent_window). Shortly after it was created, - * an enter_notify will follow. */ - DLOG("enter_notify for a client on a different workspace but the same screen, ignoring\n"); - return 1; - } + if (config.disable_focus_follows_mouse) + return 1; + Con *next = con; + while (!TAILQ_EMPTY(&(next->focus_head))) + next = TAILQ_FIRST(&(next->focus_head)); - if (!config.disable_focus_follows_mouse) - set_focus(conn, client, false); + con_focus(next); + x_push_changes(croot); - return 1; + return 1; } +#if 0 /* * When the user moves the mouse but does not change the active window diff --git a/src/nc.c b/src/nc.c index e1b8a409..68646c87 100644 --- a/src/nc.c +++ b/src/nc.c @@ -139,7 +139,11 @@ void parse_command(const char *command) { tree_next('n', VERT); else if (strncasecmp(command, "workspace ", strlen("workspace ")) == 0) workspace_show(command + strlen("workspace ")); + else if (strcasecmp(command, "stack") == 0) { + focused->layout = L_STACKED; + x_push_changes(croot); + } else if (strcasecmp(command, "move before h") == 0) tree_move('p', HORIZ); else if (strcasecmp(command, "move before v") == 0) @@ -312,6 +316,9 @@ int main(int argc, char *argv[]) { xcb_event_set_expose_handler(&evenths, handle_expose_event, NULL); + /* Enter window = user moved his mouse over the window */ + xcb_event_set_enter_notify_handler(&evenths, handle_enter_notify, NULL); + /* Setup NetWM atoms */ #define GET_ATOM(name) \ diff --git a/src/util.c b/src/util.c index cf8f8df6..c8f4ee38 100644 --- a/src/util.c +++ b/src/util.c @@ -31,6 +31,13 @@ int max(int a, int b) { return (a > b ? a : b); } +bool rect_contains(Rect rect, uint32_t x, uint32_t y) { + return (x >= rect.x && + x <= (rect.x + rect.width) && + y >= rect.y && + y <= (rect.y + rect.height)); +} + /* * Updates *destination with new_value and returns true if it was changed or false * if it was the same -- 2.39.5