[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/exwm e7ff9a9 1/2: Fix restarting issues
From: |
Chris Feng |
Subject: |
[elpa] externals/exwm e7ff9a9 1/2: Fix restarting issues |
Date: |
Mon, 1 Aug 2016 11:59:26 +0000 (UTC) |
branch: externals/exwm
commit e7ff9a9f90f0356a9ab8a9ca3857df03deeb1696
Author: Chris Feng <address@hidden>
Commit: Chris Feng <address@hidden>
Fix restarting issues
* exwm-workspace.el (exwm-workspace--confirm-kill-emacs): Prompt for
unsaved files before restarting; avoid running `server-force-stop'
early; restore the 'client' frame parameter before calling `exwm--exit';
correctly handle emacsclient.
* exwm.el (exwm-restart): Always kill subordinate Emacs instances.
---
exwm-workspace.el | 55 +++++++++++++++++++++++++++++++++++------------------
exwm.el | 27 ++++++++++++++++++++++----
2 files changed, 59 insertions(+), 23 deletions(-)
diff --git a/exwm-workspace.el b/exwm-workspace.el
index 7c2601a..097a950 100644
--- a/exwm-workspace.el
+++ b/exwm-workspace.el
@@ -25,6 +25,8 @@
;;; Code:
+(require 'server)
+
(require 'exwm-core)
(defvar exwm-workspace-number 1 "Initial number of workspaces.")
@@ -1046,15 +1048,32 @@ Please check `exwm-workspace--minibuffer-own-frame-p'
first."
(defun exwm-workspace--confirm-kill-emacs (prompt &optional force)
"Confirm before exiting Emacs."
- (when (or (and force (not (eq force 'no-check)))
- (and (or (eq force 'no-check) (not exwm--id-buffer-alist))
- (y-or-n-p prompt))
- (yes-or-no-p (format "[EXWM] %d window(s) will be destroyed. %s"
- (length exwm--id-buffer-alist) prompt)))
- ;; Run `kill-emacs-hook' before Emacs frames are unmapped so that
- ;; errors can be visible.
- (run-hooks 'kill-emacs-hook)
- (setq kill-emacs-hook nil)
+ (when (cond
+ ((and force (not (eq force 'no-check)))
+ ;; Force killing Emacs.
+ t)
+ ((or (eq force 'no-check) (not exwm--id-buffer-alist))
+ ;; Check if there's any unsaved file.
+ (pcase (catch 'break
+ (let ((kill-emacs-query-functions
+ (append kill-emacs-query-functions
+ (list (lambda ()
+ (throw 'break 'break))))))
+ (save-buffers-kill-emacs)))
+ (`break (y-or-n-p prompt))
+ (x x)))
+ (t
+ (yes-or-no-p (format "[EXWM] %d window(s) will be destroyed. %s"
+ (length exwm--id-buffer-alist) prompt))))
+ ;; Run `kill-emacs-hook' (`server-force-stop' excluded) before Emacs
+ ;; frames are unmapped so that errors (if any) can be visible.
+ (if (memq #'server-force-stop kill-emacs-hook)
+ (progn
+ (setq kill-emacs-hook (delq #'server-force-stop kill-emacs-hook))
+ (run-hooks 'kill-emacs-hook)
+ (setq kill-emacs-hook (list #'server-force-stop)))
+ (run-hooks 'kill-emacs-hook)
+ (setq kill-emacs-hook nil))
;; Hide & reparent out all frames (save-set can't be used here since
;; X windows will be re-mapped).
(when (exwm-workspace--minibuffer-own-frame-p)
@@ -1079,22 +1098,20 @@ Please check `exwm-workspace--minibuffer-own-frame-p'
first."
:parent exwm--root
:x 0
:y 0))))
- ;; Exit each module.
- (exwm--exit)
- ;; Destroy all resources created by this connection.
- (xcb:disconnect exwm--connection)
- (setq exwm--connection nil)
- ;; Extra cleanups for emacsclient.
+ ;; 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))
(when (exwm-workspace--minibuffer-own-frame-p)
(set-frame-parameter exwm-workspace--minibuffer 'client
- exwm-workspace--client))
- ;; Kill the client.
- (server-save-buffers-kill-terminal nil))
+ exwm-workspace--client)))
+ ;; Exit each module.
+ (exwm--exit)
+ ;; Destroy all resources created by this connection.
+ (xcb:disconnect exwm--connection)
+ (setq exwm--connection nil)
;; Set the return value.
- (not exwm-workspace--client)))
+ t))
(defun exwm-workspace--set-desktop-geometry ()
"Set _NET_DESKTOP_GEOMETRY."
diff --git a/exwm.el b/exwm.el
index 861d51a..dd279bb 100644
--- a/exwm.el
+++ b/exwm.el
@@ -88,10 +88,29 @@
"Restart EXWM."
(interactive)
(when (exwm-workspace--confirm-kill-emacs "[EXWM] Restart? " 'no-check)
- (apply #'call-process (car command-line-args) nil nil nil
- (cdr command-line-args))
- ;; Kill this instance at last.
- (kill-emacs)))
+ (let* ((attr (process-attributes (emacs-pid)))
+ (args (cdr (assq 'args attr)))
+ (ppid (cdr (assq 'ppid attr)))
+ (pargs (cdr (assq 'args (process-attributes ppid)))))
+ (cond
+ ((= ppid 1)
+ ;; The parent is the init process. This probably means this
+ ;; instance is an emacsclient. Anyway, start a control instance
+ ;; to manage the subsequent ones.
+ (call-process (car command-line-args))
+ (kill-emacs))
+ ((string= args pargs)
+ ;; This is a subordinate instance. Return a magic number to
+ ;; inform the parent (control instance) to start another one.
+ (kill-emacs ?R))
+ (t
+ ;; This is the control instance. Keep starting subordinate
+ ;; instances until told to exit.
+ ;; Run `server-force-stop' if it exists.
+ (run-hooks 'kill-emacs-hook)
+ (with-temp-buffer
+ (while (= ?R (shell-command-on-region (point) (point) args))))
+ (kill-emacs))))))
(defun exwm--update-window-type (id &optional force)
"Update _NET_WM_WINDOW_TYPE."