Skip to content

Replace support #380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 8, 2018
Merged

Replace support #380

merged 13 commits into from
Mar 8, 2018

Conversation

medranocalvo
Copy link
Collaborator

Support for replacing other window managers and being replaced by them. Tested with FVWM2.

As a side-effect (and probably the greatest value of these changes) EXWM now cleans up after itself.

Needs chages to XELB: ch11ng/xelb#19.

Please, review carefully.

@ch11ng
Copy link
Owner

ch11ng commented Mar 1, 2018

@medranocalvo Thanks! You've made a lot of PRs! I'll try to finish the first round review by the end of this week.

@medranocalvo
Copy link
Collaborator Author

No hurry :-). Have a nice day.

@tumashu
Copy link
Contributor

tumashu commented Mar 1, 2018

do you have signed gnu paper?

exwm-input.el Outdated
@@ -967,14 +986,42 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."

(defun exwm-input--exit ()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's generally no need to ungrab keys, unselect events, destroy X windows etc, as they are automatically done after this X connection is closed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove the cleanup code.

@medranocalvo
Copy link
Collaborator Author

@tumashu Yes I did.

@medranocalvo
Copy link
Collaborator Author

Dropped cleanup code. Please, review again.

These are the changes from v1 (note I fixed a bug regarding exwm-exit):

diff --git c/exwm-input.el w/exwm-input.el
index 090e86b..5d0ca6c 100644
--- c/exwm-input.el
+++ w/exwm-input.el
@@ -429,13 +429,6 @@ ARGS are additional arguments to CALLBACK."
     (with-slots (window) evt
       (exwm-input--grab-global-prefix-keys window))))
 
-(defun exwm-input--global-prefix-key-window-list ()
-  "List of windows keys should be grabbed."
-  (slot-value (xcb:+request-unchecked+reply exwm--connection
-                  (make-instance 'xcb:QueryTree
-                                 :window exwm--root))
-              'children))
-
 (defun exwm-input--update-global-prefix-keys ()
   "Update `exwm-input--global-prefix-keys'."
   (when exwm--connection
@@ -445,7 +438,10 @@ ARGS are additional arguments to CALLBACK."
         (cl-pushnew (elt i 0) exwm-input--global-prefix-keys))
       (unless (equal original exwm-input--global-prefix-keys)
         (apply #'exwm-input--grab-global-prefix-keys
-               (exwm-input--global-prefix-key-window-list))))))
+               (slot-value (xcb:+request-unchecked+reply exwm--connection
+                               (make-instance 'xcb:QueryTree
+                                              :window exwm--root))
+                           'children))))))
 
 (defun exwm-input--grab-global-prefix-keys (&rest xwins)
   (let ((req (make-instance 'xcb:GrabKey
@@ -472,17 +468,6 @@ ARGS are additional arguments to CALLBACK."
           (xcb:+request exwm--connection req))))
     (xcb:flush exwm--connection)))
 
-(defun exwm-input--ungrab-global-prefix-keys (&rest xwins)
-  "Ungrab global prefix keys on windows XWINS."
-  (let ((ungrab-keys (make-instance 'xcb:UngrabKey
-                                    :key xcb:Grab:Any
-                                    :grab-window nil
-                                    :modifiers xcb:ModMask:Any)))
-    (dolist (xwin xwins)
-      (setf (slot-value ungrab-keys 'grab-window) xwin)
-        (if (xcb:+request-checked+request-check exwm--connection ungrab-keys)
-            (exwm--log "Failed to ungrab keys")))))
-
 (defun exwm-input--set-key (key command)
   (global-set-key key command)
   (cl-pushnew key exwm-input--global-keys))
@@ -986,42 +971,15 @@ where both ORIGINAL-KEY and SIMULATED-KEY are key sequences."
 
 (defun exwm-input--exit ()
   "Exit the input module."
-  ;; Ungrab keys
   (exwm-input--unset-simulation-keys)
-  (apply #'exwm-input--ungrab-global-prefix-keys
-         (exwm-input--global-prefix-key-window-list))
-  ;; Detach hooks.
   (remove-hook 'minibuffer-setup-hook #'exwm-input--on-minibuffer-setup)
   (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)
-  ;; Detach event listeners.
-  (xcb:+remove-event exwm--connection 'xcb:PropertyNotify
-                     #'exwm-input--on-PropertyNotify)
-  (xcb:+remove-event exwm--connection 'xcb:CreateNotify
-                     #'exwm-input--on-CreateNotify)
-  (xcb:+remove-event exwm--connection 'xcb:KeyPress
-                     #'exwm-input--on-KeyPress)
-  (xcb:+remove-event exwm--connection 'xcb:ButtonPress
-                     #'exwm-input--on-ButtonPress)
-  (xcb:+remove-event exwm--connection 'xcb:ButtonRelease
-                     #'exwm-floating--stop-moveresize)
-  (xcb:+remove-event exwm--connection 'xcb:MotionNotify
-                     #'exwm-floating--do-moveresize)
-  (when mouse-autoselect-window
-    (xcb:+remove-event exwm--connection 'xcb:EnterNotify
-                       #'exwm-input--on-EnterNotify))
-  ;; Cancel timers.
   (when exwm-input--update-focus-defer-timer
     (cancel-timer exwm-input--update-focus-defer-timer))
   (when exwm-input--update-focus-timer
-    (cancel-timer exwm-input--update-focus-timer))
-  ;; Destroy windows
-  (when exwm-input--timestamp-window
-    (xcb:+request exwm--connection
-        (make-instance 'xcb:DestroyWindow
-                       :window exwm-input--timestamp-window)))
-  (setq exwm-input--timestamp-window nil))
+    (cancel-timer exwm-input--update-focus-timer)))
 
 
 
diff --git c/exwm-manage.el w/exwm-manage.el
index 9fa1cc7..b647819 100644
--- c/exwm-manage.el
+++ w/exwm-manage.el
@@ -622,14 +622,6 @@ border-width: %d; sibling: #x%x; stack-mode: %d"
   "Exit the manage module."
   (dolist (pair exwm--id-buffer-alist)
     (exwm-manage--unmanage-window (car pair) 'quit))
-  (xcb:+remove-event exwm--connection 'xcb:DestroyNotify
-                     #'exwm-manage--on-DestroyNotify)
-  (xcb:+remove-event exwm--connection 'xcb:UnmapNotify
-                     #'exwm-manage--on-UnmapNotify)
-  (xcb:+remove-event exwm--connection 'xcb:MapRequest
-                     #'exwm-manage--on-MapRequest)
-  (xcb:+remove-event exwm--connection 'xcb:ConfigureRequest
-                     #'exwm-manage--on-ConfigureRequest)
   (remove-hook 'after-make-frame-functions #'exwm-manage--add-frame)
   (remove-hook 'delete-frame-functions #'exwm-manage--remove-frame)
   (setq exwm-manage--_MOTIF_WM_HINTS nil))
diff --git c/exwm-randr.el w/exwm-randr.el
index 9a55d0b..c2860d4 100644
--- c/exwm-randr.el
+++ w/exwm-randr.el
@@ -217,16 +217,7 @@ the first one in result being the primary output."
 
 (defun exwm-randr--exit ()
   "Exit the RandR module."
-  (unless (or (not (xcb:got-extension-data-p exwm--connection 'xcb:randr))
-              (= 0 (slot-value (xcb:get-extension-data exwm--connection 'xcb:randr) 'present)))
-    (remove-hook 'exwm-workspace-list-change-hook #'exwm-randr--refresh)
-    (xcb:+remove-event exwm--connection 'xcb:randr:ScreenChangeNotify
-                       #'exwm-randr--on-ScreenChangeNotify)
-    (xcb:+request exwm--connection
-        (make-instance 'xcb:randr:SelectInput
-                       :window exwm--root
-                       :enable 0))
-    (xcb:flush exwm--connection)))
+  (remove-hook 'exwm-workspace-list-change-hook #'exwm-randr--refresh))
 
 (defun exwm-randr-enable ()
   "Enable RandR support for EXWM."
diff --git c/exwm-workspace.el w/exwm-workspace.el
index d17fb03..1d0d6b3 100644
--- c/exwm-workspace.el
+++ w/exwm-workspace.el
@@ -126,7 +126,6 @@ Please manually run the hook `exwm-workspace-list-change-hook' afterwards.")
 (defvar exwm-input--during-command)
 (defvar exwm-layout-show-all-buffers)
 (defvar exwm-manage--desktop)
-(declare-function exwm--exit "exwm.el")
 (declare-function exwm-input--on-buffer-list-update "exwm-input.el" ())
 (declare-function exwm-layout--hide "exwm-layout.el" (id))
 (declare-function exwm-layout--other-buffer-predicate "exwm-layout.el"
@@ -1547,7 +1546,7 @@ applied to all subsequently created X frames."
                                  ;; (client . nil)
                                  (fullscreen . nil)
                                  (buffer-predicate . nil))))
-  ;; Restore the 'client' frame parameter (before `exwm--exit').
+  ;; Restore the 'client' frame parameter (before `exwm-exit').
   (when exwm-workspace--client
     (dolist (f exwm-workspace--list)
       (set-frame-parameter f 'client exwm-workspace--client))
diff --git c/exwm.el w/exwm.el
index b8fff06..eaa68f4 100644
--- c/exwm.el
+++ w/exwm.el
@@ -685,21 +685,6 @@
                      :data [0 0]))
   (xcb:flush exwm--connection))
 
-(defun exwm--exit-icccm-ewmh ()
-  "Remove ICCCM/EWMH properties."
-  ;; Stop handling relevant client messages
-  (xcb:+remove-event exwm--connection 'xcb:ClientMessage #'exwm--on-ClientMessage)
-  ;; Stop handling PropertyNotify event
-  (xcb:+remove-event exwm--connection 'xcb:PropertyNotify #'exwm--on-PropertyNotify)
-  ;; Stop handling SelectionClear event
-  (xcb:+remove-event exwm--connection 'xcb:SelectionClear #'exwm--on-SelectionClear)
-  ;; Delete _NET_SUPPORTING_WM_CHECK's window
-  (when exwm--guide-window
-    (xcb:+request exwm--connection
-        (make-instance 'xcb:DestroyWindow :window exwm--guide-window))
-    (setq exwm--guide-window nil))
-  (xcb:flush exwm--connection))
-
 (defun exwm--wmsn-acquire (replace)
   "Acquire the WM_Sn selection.
 
@@ -775,14 +760,6 @@ manager.  If t, replace it, if nil, abort and if `ask'."
         (xcb:+request exwm--connection se))
       (setq exwm--wmsn-window new-owner))))
 
-(defun exwm--wmsn-release ()
-  "Release the window manager selection."
-  (when exwm--wmsn-window
-    (xcb:+request exwm--connection
-        (make-instance 'xcb:DestroyWindow
-                       :window exwm--wmsn-window))
-    (setq exwm--wmsn-window nil)))
-
 ;;;###autoload
 (defun exwm-init (&optional frame)
   "Initialize EXWM."
@@ -849,12 +826,10 @@ manager.  If t, replace it, if nil, abort and if `ask'."
   (exwm-workspace--exit)
   (exwm-floating--exit)
   (exwm-layout--exit)
-  (exwm--exit-icccm-ewmh)
   (xcb:+request-checked+request-check exwm--connection
       (make-instance 'xcb:ChangeWindowAttributes
                      :window exwm--root :value-mask xcb:CW:EventMask
                      :event-mask xcb:EventMask:NoEvent))
-  (exwm--wmsn-release)
   (when exwm--connection
     (xcb:flush exwm--connection)
     (xcb:disconnect exwm--connection))
@@ -961,7 +936,7 @@ manager.  If t, replace it, if nil, abort and if `ask'."
       (run-hooks 'kill-emacs-hook)
       (setq kill-emacs-hook nil))
     ;; Exit each module, destroying all resources created by this connection.
-    (exwm--exit)
+    (exwm-exit)
     ;; Set the return value.
     t))

* exwm-workspace.el (exwm-workspace--init):
* exwm-randr.el (exwm-randr--init): Prevent duplicate keys in
frameset-filter-alist
* exwm-input.el (exwm-input--exit): Remove missing hook reset window
variable.
* exwm-layout.el (exwm-layout--exit): Remove
`window-pixel-width-before-size-change' hook.
* exwm-manage.el (exwm-manage--unmanage-window): Map windows when
quitting.
(exwm-manage--exit): Remap all windows.

* exwm.el (exwm--exit): Reorder deinitialization sequence so that
windows are reparented before the workspaces are removed.
* exwm-randr.el (exwm-randr--on-ScreenChangeNotify)
(exwm-randr--init): Factor ScreenChangeNotify event callback into
a function.
…guration of frames as workspaces

* exwm-workspace.el (exwm-workspace--add-frame-as-workspace)
(exwm-workspace--remove-frame-as-workspace): Limit functionality
to the configuration of frames as workspaces.
(exwm-workspace--on-after-make-frame)
(exwm-workspace--on-delete-frame): Callbacks run on frame creation
and deletion that may use or stop them from being used as
workspaces.
* exwm-workspace.el (exwm-workspace--confirm-kill-emacs): Move
deinitialization to `exwm-workspace--exit'.
(exwm-workspace--exit): Reparent minibuffer frame to the root
window, turn workspace frames into regular frames, restore frame
parameters.
(exwm-workspace--init): Reset the fullscreen counter.
(exwm-workspace--remove-frame-as-workspace): Reset fullscreen
state.
(exwm-workspace--init-minibuffer-frame)
(exwm-workspace--exit-minibuffer-frame): New functions configuring
the minibuffer frame.
(exwm-workspace--init, exwm-workspace--exit): Use the above
functions to configure the minibuffer frame.
* exwm.el (exwm-exit): Disconnect `exwm-connection'.
* exwm.el (exwm-init, exwm-exit, exwm--confirm-kill-emacs)
* exwm-workspace.el (exwm-workspace--set-desktop-geometry)
(exwm-workspace--init, exwm-workspace--exit): Move
`confirm-kill-emacs' to this exwm.el`.  Delegate disconnection of
`exwm--connection' to `exwm-exit'.
* exwm.el (exwm-reset): Remove autoload cookie.
(exwm-init, exwm-exit): Add autoload cookie and interactive
declaration.
* exwm-workspace.el (exwm-workspace--add-frame-as-workspace)
(exwm-workspace--init):
* exwm-input.el (exwm-input--init):
* exwm-floating.el (exwm-floating--set-floating): Name created
helper windows with prefix "EXWM".
* exwm.el (exwm-init, exwm-exit): Clean up when failing to start.
(exwm--exit-icccm-ewmh): Stop deleting root window properties on
exit: delete function.
* exwm.el (exwm--on-SelectionClear, exwm--init-icccm-ewmh)
(exwm--exit-icccm-ewmh, exwm--wmsn-acquire, exwm--wmsn-release):
Get the window manager selection; die when it is cleared.
@medranocalvo medranocalvo force-pushed the replace-support branch 2 times, most recently from cb03266 to 7aae6ef Compare March 6, 2018 16:30
@medranocalvo
Copy link
Collaborator Author

Fixed leftover, rebased.

diff --git c/exwm.el w/exwm.el
index dfb0362..90b1fe4 100644
--- c/exwm.el
+++ w/exwm.el
@@ -119,7 +119,7 @@
 (defun exwm-restart ()
   "Restart EXWM."
   (interactive)
-  (when (exwm-workspace--confirm-kill-emacs "[EXWM] Restart? " 'no-check)
+  (when (exwm--confirm-kill-emacs "[EXWM] Restart? " 'no-check)
     (let* ((attr (process-attributes (emacs-pid)))
            (args (cdr (assq 'args attr)))
            (ppid (cdr (assq 'ppid attr)))

@ch11ng
Copy link
Owner

ch11ng commented Mar 7, 2018

Replacing EXWM with Openbox would fail due to Openbox receives SIGFPE. I suspect there are some properties set to 0 by EXWM. I'll fix that when merging this PR.

@medranocalvo
Copy link
Collaborator Author

The issue is caused by these properties that EXWM leaves upon exit:

$ xprop -root | grep '^_NET_'
[...]
_NET_CURRENT_DESKTOP(CARDINAL) = 4294967295
_NET_NUMBER_OF_DESKTOPS(CARDINAL) = 0
[...]

These are set by exwm-workspace--remove-frame-as-workspace when exiting. Although I think openbox should make sure the values are sane before relying on them, we should also try not to set insane values. Would it make sense for the mentioned function to ensure _NET_NUMBER_OF_DESKTOPS is never set to a value smaller than 1, and that _NET_CURRENT_DESKTOP is always set to a value between 0 and _NET_NUMBER_OF_DESKTOPS?

@ch11ng ch11ng merged commit 7aae6ef into ch11ng:master Mar 8, 2018
@ch11ng
Copy link
Owner

ch11ng commented Mar 8, 2018

@medranocalvo Thanks! It was _NET_NUMBER_OF_DESKTOPS.

@medranocalvo
Copy link
Collaborator Author

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants