diff options
author | Chris Feng <chris.w.feng@gmail.com> | 2015-09-27T11·31+0800 |
---|---|---|
committer | Chris Feng <chris.w.feng@gmail.com> | 2015-09-27T11·43+0800 |
commit | 5184f0d7c1b540a6241904528d068dce288a911e (patch) | |
tree | 1f7cecd5399eb739293104f8e5dc9c6cab50b5d6 /exwm.el | |
parent | f685de12d464b334ba7efdfe67e989dd63a96fa0 (diff) |
Work around subrs that block EXWM; other minor fixes
Some subrs (e.g. x-file-dialog) create X windows and block the execution of EXWM, so they won't work normally. This commit partly fixes this issue by invoking them in a subordinate Emacs instance and trying to fetch the result back. * exwm.el (exwm-blocking-subrs): New variable for specify such subrs. * exwm.el (exwm-enable, exwm--server-name, exwm--server-stop) (exwm--server-eval-at): The implementation. * exwm-core.el: * exwm-floating.el: * exwm-layout.el: * exwm-manage.el: * exwm-randr.el: Evaluate constants at compile-time. * README.md: Renamed from README.org to make the 'Commentary:' section used by GNU ELPA instead. * exwm.el: Depends on XELB version 0.3.
Diffstat (limited to 'exwm.el')
-rw-r--r-- | exwm.el | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/exwm.el b/exwm.el index d2a0ecf14460..b5d246ed40b8 100644 --- a/exwm.el +++ b/exwm.el @@ -5,7 +5,7 @@ ;; Author: Chris Feng <chris.w.feng@gmail.com> ;; Maintainer: Chris Feng <chris.w.feng@gmail.com> ;; Version: 0 -;; Package-Requires: ((xelb "0.1")) +;; Package-Requires: ((xelb "0.3")) ;; Keywords: unix ;; URL: https://github.com/ch11ng/exwm @@ -74,6 +74,7 @@ ;;; Code: +(require 'server) (require 'exwm-core) (require 'exwm-workspace) (require 'exwm-layout) @@ -526,14 +527,78 @@ (exwm-manage--scan) (run-hooks 'exwm-init-hook))))) +(defvar exwm-blocking-subrs '(x-file-dialog x-popup-dialog x-select-font) + "Subrs (primitives) that would normally block EXWM.") + (defun exwm-enable (&optional undo) "Enable/Disable EXWM." - (if (eq undo 'undo) - (progn (remove-hook 'window-setup-hook #'exwm-init) - (remove-hook 'after-make-frame-functions #'exwm-init)) - (setq frame-resize-pixelwise t) ;mandatory; before init - (add-hook 'window-setup-hook #'exwm-init t) ;for Emacs - (add-hook 'after-make-frame-functions #'exwm-init t))) ;for Emacs Client + (pcase undo + (`undo ;prevent reinitialization + (remove-hook 'window-setup-hook #'exwm-init) + (remove-hook 'after-make-frame-functions #'exwm-init)) + (`undo-all ;attempt to revert everything + (remove-hook 'window-setup-hook #'exwm-init) + (remove-hook 'after-make-frame-functions #'exwm-init) + (remove-hook 'kill-emacs-hook #'exwm--server-stop) + (dolist (i exwm-blocking-subrs) + (advice-remove i #'exwm--server-eval-at))) + (_ ;enable EXWM + (setq frame-resize-pixelwise t) ;mandatory; before init + (add-hook 'window-setup-hook #'exwm-init t) ;for Emacs + (add-hook 'after-make-frame-functions #'exwm-init t) ;for Emacs Client + (add-hook 'kill-emacs-hook #'exwm--server-stop) + (dolist (i exwm-blocking-subrs) + (advice-add i :around #'exwm--server-eval-at))))) + +(defconst exwm--server-name "server-exwm" + "Name of the subordinate Emacs server.") +(defvar exwm--server-process nil "Process of the subordinate Emacs server.") + +(defun exwm--server-stop () + "Stop the subordinate Emacs server." + (server-force-delete exwm--server-name) + (when exwm--server-process + (delete-process exwm--server-process) + (setq exwm--server-process nil))) + +(defun exwm--server-eval-at (&rest args) + "Wrapper of `server-eval-at' used to advice subrs." + ;; Start the subordinate Emacs server if it's not alive + (unless (server-running-p exwm--server-name) + (when exwm--server-process (delete-process exwm--server-process)) + (setq exwm--server-process + (start-process exwm--server-name + nil + (car command-line-args) ;The executable file + "-d" x-display-name + "-Q" + (concat "--daemon=" exwm--server-name) + "--eval" + ;; Create an invisible frame + "(make-frame '((window-system . x) (visibility)))")) + (while (not (server-running-p exwm--server-name)) + (sit-for 0.001))) + (server-eval-at + exwm--server-name + `(progn (select-frame (car (frame-list))) + (let ((result ,(nconc (list (make-symbol (subr-name (car args)))) + (cdr args)))) + (pcase (type-of result) + ;; Return the name of a buffer + (`buffer (buffer-name result)) + ;; We blindly convert all font objects to their XLFD names. This + ;; might cause problems of course, but it still has a chance to + ;; work (whereas directly passing font objects would merely + ;; raise errors). + ((or `font-entity `font-object `font-spec) + (font-xlfd-name result)) + ;; Passing following types makes little sense + ((or `compiled-function `finalizer `frame `hash-table `marker + `overlay `process `window `window-configuration)) + ;; Passing the name of a subr + (`subr (make-symbol (subr-name result))) + ;; For other types, return the value as-is. + (t result)))))) (defun exwm--ido-buffer-window-other-frame (orig-fun buffer) "Wrapper for `ido-buffer-window-other-frame' to exclude invisible windows." |