diff --git a/.gitignore b/.gitignore index 7681f948c..2fa63fb11 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ util.o *-protocol.h *-protocol.c *-protocol.o +compile_commands.json +.clangd diff --git a/docs/configuration/miscellaneous.md b/docs/configuration/miscellaneous.md index 32dc5b425..5933eaca8 100644 --- a/docs/configuration/miscellaneous.md +++ b/docs/configuration/miscellaneous.md @@ -32,6 +32,7 @@ description: Advanced settings for XWayland, focus behavior, and system integrat | Setting | Default | Description | | :--- | :--- | :--- | | `focus_cross_monitor` | `0` | Allow directional focus to cross monitor boundaries. | +| `focus_cross_monitor_mru` | `0` | When moving focus to another monitor, focus its most recently used window rather than the geometrically closest one. | | `exchange_cross_monitor` | `0` | Allow exchanging clients across monitor boundaries. | | `focus_cross_tag` | `0` | Allow directional focus to cross into other tags. | | `view_current_to_back` | `0` | Toggling the current tag switches back to the previously viewed tag. | diff --git a/src/config/parse_config.h b/src/config/parse_config.h index d8f322359..c03e22970 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -233,6 +233,7 @@ typedef struct { int32_t edge_scroller_pointer_focus; double edge_scroller_focus_allow_speed; int32_t focus_cross_monitor; + int32_t focus_cross_monitor_mru; int32_t exchange_cross_monitor; int32_t scratchpad_cross_monitor; int32_t focus_cross_tag; @@ -1515,6 +1516,8 @@ bool parse_option(Config *config, char *key, char *value, int line_number) { config->edge_scroller_focus_allow_speed = atof(value); } else if (strcmp(key, "focus_cross_monitor") == 0) { config->focus_cross_monitor = atoi(value); + } else if (strcmp(key, "focus_cross_monitor_mru") == 0) { + config->focus_cross_monitor_mru = atoi(value); } else if (strcmp(key, "exchange_cross_monitor") == 0) { config->exchange_cross_monitor = atoi(value); } else if (strcmp(key, "scratchpad_cross_monitor") == 0) { @@ -3704,6 +3707,8 @@ void override_config(void) { config.drag_corner = CLAMP_INT(config.drag_corner, 0, 4); config.drag_warp_cursor = CLAMP_INT(config.drag_warp_cursor, 0, 1); config.focus_cross_monitor = CLAMP_INT(config.focus_cross_monitor, 0, 1); + config.focus_cross_monitor_mru = + CLAMP_INT(config.focus_cross_monitor_mru, 0, 1); config.exchange_cross_monitor = CLAMP_INT(config.exchange_cross_monitor, 0, 1); config.scratchpad_cross_monitor = @@ -3871,6 +3876,7 @@ void set_value_default() { config.edge_scroller_pointer_focus = 1; config.edge_scroller_focus_allow_speed = 0.0f; config.focus_cross_monitor = 0; + config.focus_cross_monitor_mru = 0; config.exchange_cross_monitor = 0; config.scratchpad_cross_monitor = 0; config.focus_cross_tag = 0; diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 4d4e066ee..70a51fdf7 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -137,6 +137,11 @@ void focusdir(const Arg *arg) { Client *c = NULL; c = direction_select(arg); + if (config.focus_cross_monitor_mru && c && c->mon != selmon) { + focusmon(arg); + return; + } + if (!selmon->isoverview) c = get_focused_stack_client(c, arg->tc); if (c) { @@ -343,18 +348,26 @@ void focusmon(const Arg *arg) { return; selmon = tm; - if (config.warpcursor) { - warp_cursor_to_selmon(selmon); + + c = arg->tc; + if (config.focus_cross_monitor_mru || !c) { + c = focustop(selmon); } - c = arg->tc ? arg->tc : focustop(selmon); + if (!c) { selmon->sel = NULL; wlr_seat_pointer_notify_clear_focus(seat); wlr_seat_keyboard_notify_clear_focus(seat); focusclient(NULL, 0); - } else + if (config.warpcursor) { + warp_cursor_to_selmon(selmon); + } + } else { focusclient(c, 1); - + if (config.warpcursor) { + warp_cursor(c); + } + } return; }