about summary refs log tree commit diff
path: root/exwm-input.el
diff options
context:
space:
mode:
authorChris Feng <chris.w.feng@gmail.com>2018-02-17T17·04+0800
committerChris Feng <chris.w.feng@gmail.com>2018-02-17T17·04+0800
commit7823eb988c22f5dc804ef862d91a0fcf474ca718 (patch)
treec7a5428f6e195f5205750c9ad922b5f05bc6c407 /exwm-input.el
parent83c0a2db3448091e44cded075104a0b7df636431 (diff)
Make X windows container-less
; This is an attempt to make (managed) X windows container-less, i.e. direct children of the root window.  This is mainly to make EXWM compatible with third-party compositors.  Other issues like wrong absolute position should also get resolved by the way.  The workspace containers ("virtual roots") are also removed.  However Emacs frames are still wrapped in containers to avoid unexpected stack reordering.

* exwm-cm.el: Make this module obsolete as EXWM supports third-party compositors now.

* exwm-core.el (exwm--container):
* exwm-floating.el (exwm-floating--set-floating)
(exwm-floating--unset-floating, exwm-floating-hide)
(exwm-floating--start-moveresize, exwm-floating--stop-moveresize)
(exwm-floating--do-moveresize, exwm-floating-move):
* exwm-input.el (exwm-input--update-focus):
* exwm-layout.el (exwm-layout--show, exwm-layout--hide)
(exwm-layout-set-fullscreen, exwm-layout-unset-fullscreen):
* exwm-manage.el (exwm-manage--manage-window, exwm-manage--unmanage-window)
(exwm-manage--kill-buffer-query-function, exwm-manage--kill-client):
* exwm-workspace.el (exwm-workspace--set-fullscreen, exwm-workspace-switch)
(exwm-workspace-move-window, exwm-workspace--add-frame-as-workspace)
(exwm-workspace--remove-frame-as-workspace): Make adaptions for container-less X windows.

* exwm-workspace.el (exwm-workspace--update-ewmh-props):
* exwm.el (exwm--init-icccm-ewmh, exwm--exit-icccm-ewmh): No longer use virtual roots.

* exwm-input.el (exwm-input--on-workspace-list-change)
(exwm-input--update-global-prefix-keys, exwm-input--init, exwm-input--exit): From now on global key bindings are grabbed on the root window so it's no long required to re-grab them each time the workspace list changes.  As a result `exwm-input--on-workspace-list-change' and its corresponding references are discarded.  It remains to be seen if this change will raise input focus issues.

* exwm-manage.el (exwm-manage--manage-window): Explicitly set the workspace for newly managed X windows.
* exwm-floating.el (exwm-floating--set-floating): Avoid implicit reference to the current workspace.

* exwm-core.el (exwm--set-geometry): New function for setting the geometry of an X window.
* exwm-layout.el (exwm-layout--resize-container): Replaced by `exwm-layout--resize-container'.

* exwm-core.el (exwm--guide-window): New global variable recording the guide X window.
* exwm.el (exwm--init-icccm-ewmh): Set it.

* exwm-input.el (exwm-input--post-init): New function containing staffs for initialization but should better get called after the event loop starts.
* exwm.el (exwm-init): Use it.
Diffstat (limited to 'exwm-input.el')
-rw-r--r--exwm-input.el112
1 files changed, 44 insertions, 68 deletions
diff --git a/exwm-input.el b/exwm-input.el
index 54d0540e46..eaddf6b252 100644
--- a/exwm-input.el
+++ b/exwm-input.el
@@ -63,6 +63,8 @@
 (defvar exwm-input--simulation-prefix-keys nil
   "List of prefix keys of simulation keys in line-mode.")
 
+(declare-function exwm-layout--show "exwm-layout.el" (id &optional window))
+
 (defun exwm-input--set-focus (id)
   "Set input focus to window ID in a proper way."
   (when (exwm--id->buffer id)
@@ -183,20 +185,6 @@ ARGS are additional arguments to CALLBACK."
   (let ((exwm-input--global-prefix-keys nil))
     (exwm-input--update-global-prefix-keys)))
 
-(defun exwm-input--on-workspace-list-change ()
-  "Run in `exwm-input--update-global-prefix-keys'."
-  (dolist (f exwm-workspace--list)
-    ;; Reuse the 'exwm-grabbed' frame parameter set in
-    ;; `exwm-input--update-global-prefix-keys'.
-    (unless (frame-parameter f 'exwm-grabbed)
-      (xcb:+request exwm--connection
-          (make-instance 'xcb:ChangeWindowAttributes
-                         :window (frame-parameter f 'exwm-workspace)
-                         :value-mask xcb:CW:EventMask
-                         :event-mask xcb:EventMask:FocusChange))))
-  (exwm-input--update-global-prefix-keys)
-  (xcb:flush exwm--connection))
-
 (declare-function exwm-workspace--client-p "exwm-workspace.el"
                   (&optional frame))
 
@@ -253,7 +241,6 @@ This value should always be overwritten.")
                           exwm-input--update-focus-window))))
 
 (declare-function exwm-layout--iconic-state-p "exwm-layout.el" (&optional id))
-(declare-function exwm-layout--set-state "exwm-layout.el" (id state))
 (declare-function exwm-workspace--minibuffer-own-frame-p "exwm-workspace.el")
 (declare-function exwm-workspace-switch "exwm-workspace.el"
                   (frame-or-index &optional force))
@@ -276,19 +263,27 @@ This value should always be overwritten.")
                 (set-frame-parameter exwm--frame 'exwm-selected-window window)
                 (exwm--defer 0 #'exwm-workspace-switch exwm--frame))
             (exwm--log "Set focus on #x%x" exwm--id)
-            (exwm-input--set-focus exwm--id)
             (when exwm--floating-frame
-              ;; Adjust stacking orders of the floating container.
+              ;; Adjust stacking orders of the floating X window.
               (xcb:+request exwm--connection
                   (make-instance 'xcb:ConfigureWindow
-                                 :window exwm--container
+                                 :window exwm--id
                                  :value-mask xcb:ConfigWindow:StackMode
-                                 :stack-mode xcb:StackMode:Above))
+                                 :stack-mode xcb:StackMode:TopIf))
+              (xcb:+request exwm--connection
+                  (make-instance 'xcb:ConfigureWindow
+                                 :window (frame-parameter exwm--floating-frame
+                                                          'exwm-container)
+                                 :value-mask (logior
+                                              xcb:ConfigWindow:Sibling
+                                              xcb:ConfigWindow:StackMode)
+                                 :sibling exwm--id
+                                 :stack-mode xcb:StackMode:Below))
               ;; This floating X window might be hide by `exwm-floating-hide'.
               (when (exwm-layout--iconic-state-p)
-                (exwm-layout--set-state exwm--id
-                                        xcb:icccm:WM_STATE:NormalState))
-              (xcb:flush exwm--connection)))
+                (exwm-layout--show exwm--id window))
+              (xcb:flush exwm--connection))
+            (exwm-input--set-focus exwm--id))
         (when (eq (selected-window) window)
           (exwm--log "Focus on %s" window)
           (if (and (exwm-workspace--workspace-p (selected-frame))
@@ -389,51 +384,38 @@ This value should always be overwritten.")
   "Update `exwm-input--global-prefix-keys'."
   (when exwm--connection
     (let ((original exwm-input--global-prefix-keys)
-          keysym keycode ungrab-key grab-key workspace)
+          keysym keycode grab-key)
       (setq exwm-input--global-prefix-keys nil)
       (dolist (i exwm-input--global-keys)
         (cl-pushnew (elt i 0) exwm-input--global-prefix-keys))
       ;; Stop here if the global prefix keys are update-to-date and
       ;; there's no new workspace.
-      (unless (and (equal original exwm-input--global-prefix-keys)
-                   (cl-every (lambda (w) (frame-parameter w 'exwm-grabbed))
-                             exwm-workspace--list))
-        (setq ungrab-key (make-instance 'xcb:UngrabKey
-                                        :key xcb:Grab:Any :grab-window nil
-                                        :modifiers xcb:ModMask:Any)
-              grab-key (make-instance 'xcb:GrabKey
+      (unless (equal original exwm-input--global-prefix-keys)
+        (setq grab-key (make-instance 'xcb:GrabKey
                                       :owner-events 0
-                                      :grab-window nil
+                                      :grab-window exwm--root
                                       :modifiers nil
                                       :key nil
                                       :pointer-mode xcb:GrabMode:Async
                                       :keyboard-mode xcb:GrabMode:Async))
-        (dolist (w exwm-workspace--list)
-          (setq workspace (frame-parameter w 'exwm-workspace))
-          (setf (slot-value ungrab-key 'grab-window) workspace)
-          (if (xcb:+request-checked+request-check exwm--connection ungrab-key)
-              (exwm--log "Failed to ungrab keys")
-            ;; Label this frame.
-            (set-frame-parameter w 'exwm-grabbed t)
-            (dolist (k exwm-input--global-prefix-keys)
-              (setq keysym (xcb:keysyms:event->keysym exwm--connection k)
-                    keycode (xcb:keysyms:keysym->keycode exwm--connection
-                                                         (car keysym)))
-              (setf (slot-value grab-key 'grab-window) workspace
-                    (slot-value grab-key 'modifiers) (cdr keysym)
-                    (slot-value grab-key 'key) keycode)
-              (when (or (= 0 keycode)
-                        (xcb:+request-checked+request-check exwm--connection
-                            grab-key)
-                        ;; Also grab this key with num-lock mask set.
-                        (when (/= 0 xcb:keysyms:num-lock-mask)
-                          (setf (slot-value grab-key 'modifiers)
-                                (logior (cdr keysym)
-                                        xcb:keysyms:num-lock-mask))
-                          (xcb:+request-checked+request-check exwm--connection
-                              grab-key)))
-                (user-error "[EXWM] Failed to grab key: %s"
-                            (single-key-description k))))))))))
+        (dolist (k exwm-input--global-prefix-keys)
+          (setq keysym (xcb:keysyms:event->keysym exwm--connection k)
+                keycode (xcb:keysyms:keysym->keycode exwm--connection
+                                                     (car keysym)))
+          (setf (slot-value grab-key 'modifiers) (cdr keysym)
+                (slot-value grab-key 'key) keycode)
+          (when (or (= 0 keycode)
+                    (xcb:+request-checked+request-check exwm--connection
+                        grab-key)
+                    ;; Also grab this key with num-lock mask set.
+                    (when (/= 0 xcb:keysyms:num-lock-mask)
+                      (setf (slot-value grab-key 'modifiers)
+                            (logior (cdr keysym)
+                                    xcb:keysyms:num-lock-mask))
+                      (xcb:+request-checked+request-check exwm--connection
+                          grab-key)))
+            (user-error "[EXWM] Failed to grab key: %s"
+                        (single-key-description k))))))))
 
 ;;;###autoload
 (defun exwm-input-set-key (key command)
@@ -808,23 +790,17 @@ Its usage is the same with `exwm-input-set-simulation-keys'."
   (add-hook 'pre-command-hook #'exwm-input--on-pre-command)
   (add-hook 'post-command-hook #'exwm-input--on-post-command)
   ;; Update focus when buffer list updates
-  (add-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update)
-  ;; Re-grab global keys.
-  (add-hook 'exwm-workspace-list-change-hook
-            #'exwm-input--on-workspace-list-change)
-  (exwm-input--on-workspace-list-change)
-  ;; Prevent frame parameters introduced by this module from being
-  ;; saved/restored.
-  (dolist (i '(exwm-grabbed))
-    (push (cons i :never) frameset-filter-alist)))
+  (add-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update))
+
+(defun exwm-input--post-init ()
+  "The second stage in the initialization of the input module."
+  (exwm-input--update-global-prefix-keys))
 
 (defun exwm-input--exit ()
   "Exit the input module."
   (remove-hook 'pre-command-hook #'exwm-input--on-pre-command)
   (remove-hook 'post-command-hook #'exwm-input--on-post-command)
   (remove-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update)
-  (remove-hook 'exwm-workspace-list-change-hook
-               #'exwm-input--on-workspace-list-change)
   (when exwm-input--update-focus-defer-timer
     (cancel-timer exwm-input--update-focus-defer-timer))
   (when exwm-input--update-focus-timer