emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/exwm 04e4269 29/64: Improve input focus switch mechanis


From: Chris Feng
Subject: [elpa] externals/exwm 04e4269 29/64: Improve input focus switch mechanism
Date: Thu, 17 Sep 2015 23:18:00 +0000

branch: externals/exwm
commit 04e426961736c67046fa3809fc14f1ac027dae77
Author: Chris Feng <address@hidden>
Commit: Chris Feng <address@hidden>

    Improve input focus switch mechanism
    
    This commit should fix most input focus bugs (especially those related to
    floating windows). The actual settings of input focus are delayed to exclude
    redundant event. Dead code since this commit is removed.
    
    This commit also fixes a bug for non-floating windows converted form 
floating
    state. The workaround for `ido-mode` is also improved to properly handle
    `exwm-mode` buffers.
---
 exwm-floating.el  |   16 +++-----
 exwm-input.el     |   95 +++++++++++++++++++++++++++--------------------------
 exwm-manage.el    |   11 +-----
 exwm-workspace.el |    3 --
 exwm.el           |   18 +++-------
 5 files changed, 62 insertions(+), 81 deletions(-)

diff --git a/exwm-floating.el b/exwm-floating.el
index 7888fd2..e1d8738 100644
--- a/exwm-floating.el
+++ b/exwm-floating.el
@@ -179,12 +179,7 @@
             exwm--floating-frame frame)
       (set-window-buffer window (current-buffer)) ;this changes current buffer
       (set-window-dedicated-p window t))
-    (with-current-buffer (exwm--id->buffer id)
-      ;; Some window should not get input focus on creation
-      ;; FIXME: other conditions?
-      (unless (memq xcb:Atom:_NET_WM_WINDOW_TYPE_UTILITY exwm-window-type)
-        (x-focus-frame exwm--floating-frame)
-        (exwm-input--set-focus id)))))
+    (select-window window)))
 
 (defun exwm-floating--unset-floating (id)
   "Make window ID non-floating."
@@ -212,11 +207,12 @@
         (set-window-dedicated-p (frame-first-window exwm--floating-frame) nil)
         (delete-frame exwm--floating-frame))) ;remove the floating frame
     (with-current-buffer buffer
-      (setq exwm--floating-frame nil
+      (setq window-size-fixed nil
+            exwm--floating-frame nil
             exwm--frame exwm-workspace--current))
-    (select-frame exwm-workspace--current t)
-    (set-window-buffer nil buffer)
-    (exwm-input--set-focus id)))
+    (let ((window (frame-selected-window exwm-workspace--current)))
+      (set-window-buffer window buffer)
+      (select-window window))))
 
 (defun exwm-floating-toggle-floating ()
   "Toggle the current window between floating and non-floating states."
diff --git a/exwm-input.el b/exwm-input.el
index 4acacdf..454521f 100644
--- a/exwm-input.el
+++ b/exwm-input.el
@@ -57,8 +57,6 @@ It's updated in several occasions, and only used by 
`exwm-input--set-focus'.")
 (defun exwm-input--set-focus (id)
   "Set input focus to window ID in a proper way."
   (with-current-buffer (exwm--id->buffer id)
-    (exwm--log "Set focus ID to #x%x" id)
-    (setq exwm-input--focus-id id)
     (if (and (not exwm--hints-input)
              (memq xcb:Atom:WM_TAKE_FOCUS exwm--protocols))
         (progn
@@ -79,45 +77,53 @@ It's updated in several occasions, and only used by 
`exwm-input--set-focus'.")
                          :time xcb:Time:CurrentTime)))
     (xcb:flush exwm--connection)))
 
-(defvar exwm-input--focus-id xcb:Window:None
-  "The window that is theoretically focused.")
+(defvar exwm-input--focus-buffer nil "The buffer to be focused.")
+(defvar exwm-input--redirected nil
+  "Indicate next update on buffer list is actually a result of redirection.")
+(defvar exwm-input--timer nil "Currently running timer.")
+
+(defun exwm-input--on-buffer-list-update ()
+  "Run in buffer-list-update-hook to track input focus."
+  (let ((frame (selected-frame))
+        (buffer (current-buffer)))
+    (when (and (not (minibufferp buffer))
+               (frame-parameter frame 'exwm-window-id) ;e.g. emacsclient frame
+               (eq buffer (window-buffer))) ;e.g. `with-temp-buffer'
+      (unless (and exwm-input--redirected
+                   exwm-input--focus-buffer
+                   (with-current-buffer exwm-input--focus-buffer
+                     exwm--floating-frame))
+        (setq exwm-input--focus-buffer buffer)
+        (when exwm-input--timer (cancel-timer exwm-input--timer))
+        (setq exwm-input--timer
+              (run-with-timer 0.01 nil 'exwm-input--update-focus)))
+      (setq exwm-input--redirected nil))))
+
+(defun exwm-input--on-focus-in ()
+  "Run in focus-in-hook to remove redirected focus on frame."
+  (let ((frame (selected-frame)))
+    (when (and (frame-parameter frame 'exwm-window-id)
+               (not (memq frame exwm-workspace--list)))
+      (setq exwm-input--redirected t))))
 
 (defun exwm-input--update-focus ()
   "Update input focus."
-  (when (and (frame-parameter nil 'exwm-window-id) ;e.g. emacsclient frame
-             (eq (current-buffer) (window-buffer))) ;e.g. `with-temp-buffer'
-    (if (eq major-mode 'exwm-mode)
-        (progn (exwm--log "Set focus ID to #x%x" exwm--id)
-               (setq exwm-input--focus-id exwm--id)
-               (when exwm--floating-frame
-                 (if (eq (selected-frame) exwm--floating-frame)
-                     ;; Cancel the possible input focus redirection
-                     (progn
-                       (exwm--log "Cancel input focus redirection on %s"
-                                  exwm--floating-frame)
-                       (redirect-frame-focus exwm--floating-frame nil))
-                   ;; Focus the floating frame
-                   (exwm--log "Focus on floating frame %s"
-                              exwm--floating-frame)
-                   (x-focus-frame exwm--floating-frame)))
-               ;; Finally focus the window
-               (when (exwm--id->buffer exwm-input--focus-id)
-                 (exwm-input--set-focus exwm-input--focus-id)))
-      (let ((buffer (exwm--id->buffer exwm-input--focus-id)))
-        (when (and buffer (eq (selected-frame) exwm-workspace--current))
-          (with-current-buffer buffer
-            (exwm--log "Set focus ID to #x%x" xcb:Window:None)
-            (setq exwm-input--focus-id xcb:Window:None)
-            (if exwm--floating-frame
-                (unless (active-minibuffer-window)
-                  ;; Redirect input focus to the workspace frame
-                  (exwm--log "Redirect input focus (%s => %s)"
-                             exwm--floating-frame exwm-workspace--current)
-                  (redirect-frame-focus exwm--floating-frame
-                                        exwm-workspace--current))
-              ;; Focus the workspace frame
-              (exwm--log "Focus on workspace %s" exwm-workspace--current)
-              (x-focus-frame exwm-workspace--current))))))))
+  (when exwm-input--focus-buffer
+    (with-current-buffer exwm-input--focus-buffer
+      (exwm--log "Set focus on %s" exwm-input--focus-buffer)
+      (setq exwm-input--focus-buffer nil)
+      (if (eq major-mode 'exwm-mode)
+          (progn
+            (when exwm--floating-frame
+              (redirect-frame-focus exwm--floating-frame nil)
+              (select-frame-set-input-focus exwm--floating-frame t))
+            (exwm-input--set-focus exwm--id))
+        (select-frame-set-input-focus exwm-workspace--current t)
+        (dolist (pair exwm--id-buffer-alist)
+          (with-current-buffer (cdr pair)
+            (when (and exwm--floating-frame
+                       (eq exwm--frame exwm-workspace--current))
+              (redirect-frame-focus exwm--floating-frame exwm--frame))))))))
 
 (defun exwm-input--finish-key-sequence ()
   "Mark the end of a key sequence (with the aid of `pre-command-hook')."
@@ -169,12 +175,8 @@ It's updated in several occasions, and only used by 
`exwm-input--set-focus'.")
              ;; Resize
              (exwm-floating--start-moveresize event))
             (t
-             ;; Click to focus
-             (unless (and (boundp 'exwm--id) (= event exwm--id))
-               (with-current-buffer (exwm--id->buffer event)
-                 (select-frame-set-input-focus (or exwm--floating-frame
-                                                   exwm--frame))
-                 (select-window (get-buffer-window nil 'visible))))
+             (select-window (get-buffer-window (exwm--id->buffer event)
+                                               'visible))
              ;; The event should be replayed
              (setq mode xcb:Allow:ReplayPointer))))
     (xcb:+request exwm--connection
@@ -246,7 +248,6 @@ It's updated in several occasions, and only used by 
`exwm-input--set-focus'.")
 ;;       (when (and keysym
 ;;                  (setq event (xcb:keysyms:keysym->event keysym state))
 ;;                  (or exwm-input--during-key-sequence
-;;                      (= exwm-input--focus-id xcb:Window:None)
 ;;                      (setq window (active-minibuffer-window))
 ;;                      (eq event ?\C-c)   ;mode-specific key
 ;;                      (memq event exwm-input--global-prefix-keys)
@@ -273,7 +274,6 @@ It's updated in several occasions, and only used by 
`exwm-input--set-focus'.")
       (if (and keysym
                (setq event (xcb:keysyms:keysym->event keysym state))
                (or exwm-input--during-key-sequence
-                   (= exwm-input--focus-id xcb:Window:None)
                    (setq minibuffer-window (active-minibuffer-window))
                    (eq event ?\C-c)   ;mode-specific key
                    (memq event exwm-input--global-prefix-keys)
@@ -466,7 +466,8 @@ SIMULATION-KEYS is a list of alist (key-sequence1 . 
key-sequence2)."
   ;; `pre-command-hook' marks the end of a key sequence (existing or not)
   (add-hook 'pre-command-hook 'exwm-input--finish-key-sequence)
   ;; Update focus when buffer list updates
-  (add-hook 'buffer-list-update-hook 'exwm-input--update-focus)
+  (add-hook 'buffer-list-update-hook 'exwm-input--on-buffer-list-update)
+  (add-hook 'focus-in-hook 'exwm-input--on-focus-in)
   ;; Update prefix keys for global keys
   (exwm-input--update-global-prefix-keys))
 
diff --git a/exwm-manage.el b/exwm-manage.el
index fc61e50..d1736ff 100644
--- a/exwm-manage.el
+++ b/exwm-manage.el
@@ -183,15 +183,8 @@ corresponding buffer.")
         (let ((floating exwm--floating-frame))
           (kill-buffer)
           (when floating
-            (if (eq 'exwm-mode
-                    (with-current-buffer
-                        (window-buffer
-                         (frame-first-window exwm-workspace--current))
-                      major-mode))
-                ;; Input focus is to be set on a window
-                (x-focus-frame exwm-workspace--current)
-              ;; Set input focus on a frame
-              (select-frame-set-input-focus exwm-workspace--current))))))))
+            (select-window
+             (frame-selected-window exwm-workspace--current))))))))
 
 (defun exwm-manage--scan ()
   "Search for existing windows and try to manage them."
diff --git a/exwm-workspace.el b/exwm-workspace.el
index bcac917..09112d2 100644
--- a/exwm-workspace.el
+++ b/exwm-workspace.el
@@ -188,9 +188,6 @@ The optional FORCE option is for internal use only."
           ;; Move the window itself
           (bury-buffer)
           (exwm-layout--hide id)
-          ;; Force update input focus
-          (setq exwm-input--focus-id xcb:Window:None)
-          (exwm-input--update-focus)
           (xcb:+request exwm--connection
               (make-instance 'xcb:ReparentWindow
                              :window id
diff --git a/exwm.el b/exwm.el
index 7e909cd..989bf88 100644
--- a/exwm.el
+++ b/exwm.el
@@ -195,15 +195,9 @@
 (defun exwm-reset ()
   "Reset window to standard state: non-fullscreen, line-mode."
   (interactive)
-  (unless (frame-parameter nil 'exwm-window-id)
-    ;; Move focus away form a non-EXWM frame
-    (x-focus-frame exwm-workspace--current))
   (with-current-buffer (window-buffer)
     (when (eq major-mode 'exwm-mode)
       (when exwm--fullscreen (exwm-layout-unset-fullscreen))
-      ;; Force update input focus
-      (setq exwm-input--focus-id xcb:Window:None)
-      (exwm-input--update-focus)
       ;; Force refresh
       (exwm-layout--refresh)
       (exwm-input-grab-keyboard))))
@@ -709,12 +703,12 @@
 
 (defun exwm--ido-buffer-window-other-frame (orig-fun buffer)
   "Wrapper for `ido-buffer-window-other-frame' to exclude invisible windows."
-  (let* ((window (funcall orig-fun buffer))
-         (frame (window-frame window)))
-    ;; Exclude windows on other workspaces
-    (unless (and (memq frame exwm-workspace--list)
-                 (not (eq frame exwm-workspace--current)))
-      window)))
+  (with-current-buffer buffer
+    (if (eq major-mode 'exwm-mode)
+        ;; `ido-mode' works well with `exwm-mode' buffers
+        (funcall orig-fun buffer)
+      ;; Other buffers should be selected within the same workspace
+      (get-buffer-window buffer exwm-workspace--current))))
 
 (defun exwm--fix-ido-buffer-window-other-frame ()
   "Fix `ido-buffer-window-other-frame'."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]