]> git.sur5r.net Git - i3/i3/commitdiff
Added 'focus_on_window_activation' directive
authorIngo Bürk <ingo.buerk@tngtech.com>
Mon, 30 Mar 2015 20:07:48 +0000 (22:07 +0200)
committerIngo Bürk <ingo.buerk@tngtech.com>
Mon, 30 Mar 2015 20:09:36 +0000 (22:09 +0200)
When a window receives a _NET_ACTIVE_WINDOW message, it can steal the focus. This may not be preferable to all users.
With this directive, the user can choose from one of the following:
1) 'smart' - focus the container if its workspace is visible, otherwise set the urgency flag (default)
2) 'urgent' - always set the urgency flag, do not steal focus
3) 'focus' - always switch focus, never set the urgency hint
4) 'none' - ignore the request entirely (do not switch focus, nor set the urgency hint)

fixes #1426

include/config.h
include/config_directives.h
parser-specs/config.spec
src/config_directives.c
src/handlers.c
testcases/t/201-config-parser.t

index 9a0af0e6cd6b8119e1a5ae4a4bd5fcef915cb66e..5b534fb7379a4aef5f485f7e3b80b9cd513ae6f7 100644 (file)
@@ -167,6 +167,18 @@ struct Config {
      * flag can be delayed using an urgency timer. */
     float workspace_urgency_timer;
 
+    /** Behavior when a window sends a NET_ACTIVE_WINDOW message. */
+    enum {
+        /* Focus if the target workspace is visible, set urgency hint otherwise. */
+        FOWA_SMART,
+        /* Always set the urgency hint. */
+        FOWA_URGENT,
+        /* Always focus the window. */
+        FOWA_FOCUS,
+        /* Ignore the request (no focus, no urgency hint). */
+        FOWA_NONE
+    } focus_on_window_activation;
+
     /** The default border style for new windows. */
     border_style_t default_border;
 
index 6c960b1f8c765771c2fd6d340872a76d7ea4fae6..8f99e64861dc48b3bf20f5f93c1ba38fa3863823 100644 (file)
@@ -51,6 +51,7 @@ CFGFUN(force_focus_wrapping, const char *value);
 CFGFUN(force_xinerama, const char *value);
 CFGFUN(fake_outputs, const char *outputs);
 CFGFUN(force_display_urgency_hint, const long duration_ms);
+CFGFUN(focus_on_window_activation, const char *mode);
 CFGFUN(hide_edge_borders, const char *borders);
 CFGFUN(assign, const char *workspace);
 CFGFUN(ipc_socket, const char *path);
index 25be5cf107e2bef2eebdba243980ee04085c9efa..e23c37c884364e50f28d32425cd10ed4d1fd8853 100644 (file)
@@ -38,6 +38,7 @@ state INITIAL:
   'workspace_auto_back_and_forth'          -> WORKSPACE_BACK_AND_FORTH
   'fake_outputs', 'fake-outputs'           -> FAKE_OUTPUTS
   'force_display_urgency_hint'             -> FORCE_DISPLAY_URGENCY_HINT
+  'focus_on_window_activation'             -> FOCUS_ON_WINDOW_ACTIVATION
   'workspace'                              -> WORKSPACE
   'ipc_socket', 'ipc-socket'               -> IPC_SOCKET
   'restart_state'                          -> RESTART_STATE
@@ -210,6 +211,11 @@ state FORCE_DISPLAY_URGENCY_HINT_MS:
   end
       -> call cfg_force_display_urgency_hint(&duration_ms)
 
+# focus_on_window_activation <smart|urgent|focus|none>
+state FOCUS_ON_WINDOW_ACTIVATION:
+  mode = word
+      -> call cfg_focus_on_window_activation($mode)
+
 # workspace <workspace> output <output>
 state WORKSPACE:
   workspace = word
index c8b25c7645f6cfc7e8c2d8ab210101138719957d..039cb29e65a4769b96e10b5690e595e69aa7b810 100644 (file)
@@ -329,6 +329,23 @@ CFGFUN(force_display_urgency_hint, const long duration_ms) {
     config.workspace_urgency_timer = duration_ms / 1000.0;
 }
 
+CFGFUN(focus_on_window_activation, const char *mode) {
+    if (strcmp(mode, "smart") == 0)
+        config.focus_on_window_activation = FOWA_SMART;
+    else if (strcmp(mode, "urgent") == 0)
+        config.focus_on_window_activation = FOWA_URGENT;
+    else if (strcmp(mode, "focus") == 0)
+        config.focus_on_window_activation = FOWA_FOCUS;
+    else if (strcmp(mode, "none") == 0)
+        config.focus_on_window_activation = FOWA_NONE;
+    else {
+        ELOG("Unknown focus_on_window_activation mode \"%s\", ignoring it.\n", mode);
+        return;
+    }
+
+    DLOG("Set new focus_on_window_activation mode = %i", config.focus_on_window_activation);
+}
+
 CFGFUN(workspace, const char *workspace, const char *output) {
     DLOG("Assigning workspace \"%s\" to output \"%s\"\n", workspace, output);
     /* Check for earlier assignments of the same workspace so that we
index 041f7e366f76a96da1620c1ab950ffacc084edc5..c80c279efe43857b83e9a4e4246e72f3681dc5cb 100644 (file)
@@ -743,16 +743,17 @@ static void handle_client_message(xcb_client_message_event_t *event) {
             workspace_show(ws);
             con_focus(con);
         } else {
-            /* If the request is from an application, only focus if the
-             * workspace is visible. Otherwise set the urgency hint. */
-            if (workspace_is_visible(ws)) {
-                DLOG("Request to focus con on a visible workspace. Focusing con = %p\n", con);
+            /* Request is from an application. */
+
+            if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(ws))) {
+                DLOG("Focusing con = %p\n", con);
                 workspace_show(ws);
                 con_focus(con);
-            } else {
-                DLOG("Request to focus con on a hidden workspace. Setting urgent con = %p\n", con);
+            } else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(ws))) {
+                DLOG("Marking con = %p urgent\n", con);
                 con_set_urgency(con, true);
-            }
+            } else
+                DLOG("Ignoring request for con = %p", con);
         }
 
         tree_render();
index 1e91d47f9cf5cdcb71f9ccf350aefd1f61f2e364..a6b1fe0c2cfacd4bdbb23ef5722c0db24af9f45b 100644 (file)
@@ -433,7 +433,7 @@ client.focused          #4c7899 #285577 #ffffff #2e9ef4
 EOT
 
 my $expected_all_tokens = <<'EOT';
-ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
+ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'bindsym', 'bindcode', 'bind', 'bar', 'font', 'mode', 'floating_minimum_size', 'floating_maximum_size', 'floating_modifier', 'default_orientation', 'workspace_layout', 'new_window', 'new_float', 'hide_edge_borders', 'for_window', 'assign', 'focus_follows_mouse', 'mouse_warping', 'force_focus_wrapping', 'force_xinerama', 'force-xinerama', 'workspace_auto_back_and_forth', 'fake_outputs', 'fake-outputs', 'force_display_urgency_hint', 'focus_on_window_activation', 'workspace', 'ipc_socket', 'ipc-socket', 'restart_state', 'popup_during_fullscreen', 'exec_always', 'exec', 'client.background', 'client.focused_inactive', 'client.focused', 'client.unfocused', 'client.urgent', 'client.placeholder'
 EOT
 
 my $expected_end = <<'EOT';