diff options
-rw-r--r-- | third_party/exwm/.elpaignore | 1 | ||||
-rw-r--r-- | third_party/exwm/exwm-background.el | 12 | ||||
-rw-r--r-- | third_party/exwm/exwm-cm.el | 50 | ||||
-rw-r--r-- | third_party/exwm/exwm-config.el | 2 | ||||
-rw-r--r-- | third_party/exwm/exwm-core.el | 9 | ||||
-rw-r--r-- | third_party/exwm/exwm-floating.el | 11 | ||||
-rw-r--r-- | third_party/exwm/exwm-input.el | 92 | ||||
-rw-r--r-- | third_party/exwm/exwm-layout.el | 15 | ||||
-rw-r--r-- | third_party/exwm/exwm-manage.el | 45 | ||||
-rw-r--r-- | third_party/exwm/exwm-randr.el | 10 | ||||
-rw-r--r-- | third_party/exwm/exwm-systemtray.el | 3 | ||||
-rw-r--r-- | third_party/exwm/exwm-workspace.el | 3 | ||||
-rw-r--r-- | third_party/exwm/exwm-xim.el | 2 | ||||
-rw-r--r-- | third_party/exwm/exwm-xsettings.el | 336 | ||||
-rw-r--r-- | third_party/exwm/exwm.el | 44 | ||||
-rw-r--r-- | third_party/overlays/tvl.nix | 13 |
16 files changed, 484 insertions, 164 deletions
diff --git a/third_party/exwm/.elpaignore b/third_party/exwm/.elpaignore index b43bf86b50fd..f0f644ee08ad 100644 --- a/third_party/exwm/.elpaignore +++ b/third_party/exwm/.elpaignore @@ -1 +1,2 @@ +LICENSE README.md diff --git a/third_party/exwm/exwm-background.el b/third_party/exwm/exwm-background.el index 9c9bc5e35204..fa663d8fe637 100644 --- a/third_party/exwm/exwm-background.el +++ b/third_party/exwm/exwm-background.el @@ -1,6 +1,6 @@ ;;; exwm-background.el --- X Background Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2022-2023 Free Software Foundation, Inc. +;; Copyright (C) 2022-2024 Free Software Foundation, Inc. ;; Author: Steven Allen <steven@stebalien.com> @@ -27,7 +27,7 @@ ;; (require 'exwm-background) ;; (exwm-background-enable) ;; -;; By default, this will apply the theme's background color. However, that +;; By default, this will apply the theme's background color. However, that ;; color can be customized via the `exwm-background-color' setting. ;;; Code: @@ -47,13 +47,13 @@ (defconst exwm-background--properties '("_XROOTPMAP_ID" "_XSETROOT_ID" "ESETROOT_PMAP_ID") "The background properties to set. -We can't need to set these so that compositing window managers can correctly display the background -color.") +We can't need to set these so that compositing window managers +can correctly display the background color.") (defvar exwm-background--connection nil "The X connection used for setting the background. -We use a separate connection as other background-setting tools may kill this connection when they -replace it.") +We use a separate connection as other background-setting tools +may kill this connection when they replace it.") (defvar exwm-background--pixmap nil "Cached background pixmap.") diff --git a/third_party/exwm/exwm-cm.el b/third_party/exwm/exwm-cm.el deleted file mode 100644 index d2d04cbf9290..000000000000 --- a/third_party/exwm/exwm-cm.el +++ /dev/null @@ -1,50 +0,0 @@ -;;; exwm-cm.el --- Compositing Manager for EXWM -*- lexical-binding: t -*- - -;; Copyright (C) 2016-2023 Free Software Foundation, Inc. - -;; Author: Chris Feng <chris.w.feng@gmail.com> - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: - -;; This module is obsolete since EXWM now supports third-party compositors. - -;;; Code: - -(make-obsolete-variable 'exwm-cm-opacity - "This variable should no longer be used." "26") - -(defun exwm-cm-set-opacity (&rest _args) - (declare (obsolete nil "26"))) - -(defun exwm-cm-enable () - (declare (obsolete nil "26"))) - -(defun exwm-cm-start () - (declare (obsolete nil "26"))) - -(defun exwm-cm-stop () - (declare (obsolete nil "26"))) - -(defun exwm-cm-toggle () - (declare (obsolete nil "26"))) - - - -(provide 'exwm-cm) - -;;; exwm-cm.el ends here diff --git a/third_party/exwm/exwm-config.el b/third_party/exwm/exwm-config.el index f3357807b57a..a9f21e9c8c84 100644 --- a/third_party/exwm/exwm-config.el +++ b/third_party/exwm/exwm-config.el @@ -1,6 +1,6 @@ ;;; exwm-config.el --- Predefined configurations -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> diff --git a/third_party/exwm/exwm-core.el b/third_party/exwm/exwm-core.el index 4df57e738123..e0d644d941ed 100644 --- a/third_party/exwm/exwm-core.el +++ b/third_party/exwm/exwm-core.el @@ -1,6 +1,6 @@ ;;; exwm-core.el --- Core definitions -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -33,6 +33,10 @@ (require 'xcb-ewmh) (require 'xcb-debug) +(defgroup exwm-debug nil + "Debugging." + :group 'exwm) + (defcustom exwm-debug-log-time-function #'exwm-debug-log-uptime "Function used for generating timestamps in `exwm-debug' logs. @@ -40,7 +44,6 @@ Here are some predefined candidates: `exwm-debug-log-uptime': Display the uptime of this Emacs instance. `exwm-debug-log-time': Display time of day. `nil': Disable timestamp." - :group 'exwm-debug :type `(choice (const :tag "Emacs uptime" ,#'exwm-debug-log-uptime) (const :tag "Time of day" ,#'exwm-debug-log-time) (const :tag "Off" nil) @@ -203,7 +206,7 @@ If FRAME is null, use selected frame." "Convert COLOR to PIXEL (index in TrueColor colormap)." (when (and color (eq (x-display-visual-class) 'true-color)) - (let ((rgb (x-color-values color))) + (let ((rgb (color-values color))) (logior (ash (ash (pop rgb) -8) 16) (ash (ash (pop rgb) -8) 8) (ash (pop rgb) -8))))) diff --git a/third_party/exwm/exwm-floating.el b/third_party/exwm/exwm-floating.el index def7f43e535a..34d06a30db09 100644 --- a/third_party/exwm/exwm-floating.el +++ b/third_party/exwm/exwm-floating.el @@ -1,6 +1,6 @@ ;;; exwm-floating.el --- Floating Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -31,17 +31,16 @@ (defgroup exwm-floating nil "Floating." - :version "25.3" :group 'exwm) (defcustom exwm-floating-setup-hook nil - "Normal hook run when an X window has been made floating, in the -context of the corresponding buffer." + "Normal hook run when an X window has been made floating. +This hook runs in the context of the corresponding buffer." :type 'hook) (defcustom exwm-floating-exit-hook nil - "Normal hook run when an X window has exited floating state, in the -context of the corresponding buffer." + "Normal hook run when an X window has exited floating state. +This hook runs in the context of the corresponding buffer." :type 'hook) (defcustom exwm-floating-border-color "navy" diff --git a/third_party/exwm/exwm-input.el b/third_party/exwm/exwm-input.el index 4c762c40fe19..f1f035c91ad9 100644 --- a/third_party/exwm/exwm-input.el +++ b/third_party/exwm/exwm-input.el @@ -1,6 +1,6 @@ ;;; exwm-input.el --- Input Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -40,7 +40,6 @@ (defgroup exwm-input nil "Input." - :version "25.3" :group 'exwm) (defcustom exwm-input-prefix-keys @@ -102,6 +101,13 @@ defined in `exwm-mode-map' here." (defconst exwm-input--update-focus-interval 0.01 "Time interval (in seconds) for accumulating input focus update requests.") +(defconst exwm-input--passthrough-functions '(read-char + read-char-exclusive + read-key-sequence-vector + read-key-sequence + read-event) + "Low-level read functions that must be exempted from EXWM input handling.") + (defvar exwm-input--during-command nil "Indicate whether between `pre-command-hook' and `post-command-hook'.") @@ -129,11 +135,14 @@ defined in `exwm-mode-map' here." (defvar exwm-input--timestamp-window nil) +(defvar exwm-input--update-focus-timer nil + "Timer for deferring the update of input focus.") + (defvar exwm-input--update-focus-lock nil "Lock for solving input focus update contention.") -(defvar exwm-input--update-focus-timer nil - "Timer for deferring the update of input focus.") +(defvar exwm-input--update-focus-window nil "The (Emacs) window to be focused. +This value should always be overwritten.") (defvar exwm-input--echo-area-timer nil "Timer for detecting echo area dirty.") @@ -291,38 +300,38 @@ ARGS are additional arguments to CALLBACK." "Run in `buffer-list-update-hook' to track input focus." (when (and ; this hook is called incesantly; place cheap tests on top (not exwm-input--skip-buffer-list-update) - (exwm--terminal-p)) ; skip other terminals, e.g. TTY client frames + (exwm--terminal-p) ; skip other terminals, e.g. TTY client frames + (not (frame-parameter nil 'no-accept-focus))) (exwm--log "current-buffer=%S selected-window=%S" (current-buffer) (selected-window)) + (redirect-frame-focus (selected-frame) nil) + (setq exwm-input--update-focus-window (selected-window)) (exwm-input--update-focus-defer))) (defun exwm-input--update-focus-defer () - "Defer updating input focus." - (redirect-frame-focus (selected-frame) nil) + "Schedule a deferred update to input focus. +Instead of immediately focusing the current window, it defers the focus change +until the selected window stops changing (debouncing input focus updates)." (when exwm-input--update-focus-timer (cancel-timer exwm-input--update-focus-timer)) (setq exwm-input--update-focus-timer ;; Attempt to accumulate successive events close enough. (run-with-timer exwm-input--update-focus-interval nil - #'exwm-input--update-focus-commit - (selected-window)))) - -(defun exwm-input--update-focus-commit (window) - "Commit updating input focus." - (let ((cwin (selected-window))) - (if exwm-input--update-focus-lock - (unless (eq exwm-input--update-focus-lock cwin) - (exwm-input--update-focus-defer)) - (if (and cwin window (eq cwin window)) - (let ((exwm-input--update-focus-lock cwin)) - (exwm-input--update-focus window)) - (exwm-input--update-focus-defer))))) + #'exwm-input--update-focus-commit))) + +(defun exwm-input--update-focus-commit () + "Attempt to update the window focus. +If we're currently updating the window focus, re-schedule a focus update +attempt later." + (if exwm-input--update-focus-lock + (exwm-input--update-focus-defer) + (let ((exwm-input--update-focus-lock t)) + (exwm-input--update-focus exwm-input--update-focus-window)))) (defun exwm-input--update-focus (window) - "Update input focus." - (when (and (window-live-p window) - (not (frame-parameter (window-frame window) 'no-accept-focus))) + "Update input focus to WINDOW." + (when (window-live-p window) (exwm--log "focus-window=%s focus-buffer=%s" window (window-buffer window)) (with-current-buffer (window-buffer window) (if (derived-mode-p 'exwm-mode) @@ -573,20 +582,10 @@ instead." (when (called-interactively-p 'any) (exwm-input--update-global-prefix-keys))) -;; Putting (t . EVENT) into `unread-command-events' does not really work -;; as documented for Emacs < 26.2. -(eval-and-compile - (if (or (< emacs-major-version 26) - (and (= emacs-major-version 26) - (< emacs-minor-version 2))) - (defsubst exwm-input--unread-event (event) - (declare (indent defun)) - (setq unread-command-events - (append unread-command-events (list event)))) - (defsubst exwm-input--unread-event (event) - (declare (indent defun)) - (setq unread-command-events - (append unread-command-events `((t . ,event))))))) +(defsubst exwm-input--unread-event (event) + (declare (indent defun)) + (setq unread-command-events + (append unread-command-events `((t . ,event))))) (defun exwm-input--mimic-read-event (event) "Process EVENT as if it were returned by `read-event'." @@ -747,7 +746,7 @@ Current buffer must be an `exwm-mode' buffer." (defun exwm-input--on-ButtonPress-line-mode (buffer button-event) "Handle button events in line mode. BUFFER is the `exwm-mode' buffer the event was generated -on. BUTTON-EVENT is the X event converted into an Emacs event. +on. BUTTON-EVENT is the X event converted into an Emacs event. The return value is used as event_mode to release the original button event." @@ -970,11 +969,6 @@ multiple keys. If END-KEY is non-nil, stop sending keys if it's pressed." #'exwm-input-send-simulation-key)))) exwm-input--simulation-keys)) -(defun exwm-input-set-simulation-keys (simulation-keys) - "Please customize or set `exwm-input-simulation-keys' instead." - (declare (obsolete nil "26")) - (exwm-input--set-simulation-keys simulation-keys)) - (defcustom exwm-input-simulation-keys nil "Simulation keys. @@ -1151,6 +1145,11 @@ One use is to access the keymap bound to KEYS (as prefix keys) in `char-mode'." (exwm--log) (exwm-input--on-minibuffer-exit))) +(defun exwm-input--call-with-passthrough (function &rest args) + "Bind `exwm-input-line-mode-passthrough' and call FUNCTION with ARGS." + (let ((exwm-input-line-mode-passthrough t)) + (apply function args))) + (defun exwm-input--init () "Initialize the keyboard module." (exwm--log) @@ -1206,7 +1205,10 @@ One use is to access the keymap bound to KEYS (as prefix keys) in `char-mode'." (run-with-idle-timer 0 t #'exwm-input--on-echo-area-dirty)) (add-hook 'echo-area-clear-hook #'exwm-input--on-echo-area-clear) ;; Update focus when buffer list updates - (add-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update)) + (add-hook 'buffer-list-update-hook #'exwm-input--on-buffer-list-update) + + (dolist (fun exwm-input--passthrough-functions) + (advice-add fun :around #'exwm-input--call-with-passthrough))) (defun exwm-input--post-init () "The second stage in the initialization of the input module." @@ -1216,6 +1218,8 @@ One use is to access the keymap bound to KEYS (as prefix keys) in `char-mode'." (defun exwm-input--exit () "Exit the input module." (exwm--log) + (dolist (fun exwm-input--passthrough-functions) + (advice-remove fun #'exwm-input--call-with-passthrough)) (exwm-input--unset-simulation-keys) (remove-hook 'pre-command-hook #'exwm-input--on-pre-command) (remove-hook 'post-command-hook #'exwm-input--on-post-command) diff --git a/third_party/exwm/exwm-layout.el b/third_party/exwm/exwm-layout.el index 0cfc47f8a31c..8649c11ffd42 100644 --- a/third_party/exwm/exwm-layout.el +++ b/third_party/exwm/exwm-layout.el @@ -1,6 +1,6 @@ ;;; exwm-layout.el --- Layout Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -29,7 +29,6 @@ (defgroup exwm-layout nil "Layout." - :version "25.3" :group 'exwm) (defcustom exwm-layout-auto-iconify t @@ -146,8 +145,8 @@ See variable `exwm-layout-auto-iconify'." (exwm--set-geometry id x y width height) (xcb:+request exwm--connection (make-instance 'xcb:MapWindow :window id)) (exwm-layout--set-state id xcb:icccm:WM_STATE:NormalState) - ;; (setq exwm--ewmh-state - ;; (delq xcb:Atom:_NET_WM_STATE_HIDDEN exwm--ewmh-state)) + (setq exwm--ewmh-state + (delq xcb:Atom:_NET_WM_STATE_HIDDEN exwm--ewmh-state)) (exwm-layout--set-ewmh-state id) (exwm-layout--auto-iconify))) (xcb:flush exwm--connection)) @@ -157,7 +156,8 @@ See variable `exwm-layout-auto-iconify'." (with-current-buffer (exwm--id->buffer id) (unless (or (exwm-layout--iconic-state-p) (and exwm--floating-frame - (eq 4294967295. exwm--desktop))) + exwm--desktop + (= 4294967295. exwm--desktop))) (exwm--log "Hide #x%x" id) (when exwm--floating-frame (let* ((container (frame-parameter exwm--floating-frame @@ -182,7 +182,7 @@ See variable `exwm-layout-auto-iconify'." :window id :value-mask xcb:CW:EventMask :event-mask (exwm--get-client-event-mask))) (exwm-layout--set-state id xcb:icccm:WM_STATE:IconicState) - ;; (cl-pushnew xcb:Atom:_NET_WM_STATE_HIDDEN exwm--ewmh-state) + (cl-pushnew xcb:Atom:_NET_WM_STATE_HIDDEN exwm--ewmh-state) (exwm-layout--set-ewmh-state id) (exwm-layout--auto-iconify) (xcb:flush exwm--connection)))) @@ -207,8 +207,7 @@ See variable `exwm-layout-auto-iconify'." xcb:ConfigWindow:StackMode) :border-width 0 :stack-mode xcb:StackMode:Above)) - ;; commented out to work around https://github.com/ch11ng/exwm/issues/759 - ;; (cl-pushnew xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state) + (cl-pushnew xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state) (exwm-layout--set-ewmh-state exwm--id) (xcb:flush exwm--connection) (set-window-dedicated-p (get-buffer-window) t) diff --git a/third_party/exwm/exwm-manage.el b/third_party/exwm/exwm-manage.el index 4771c3c088db..ab66e298ac8e 100644 --- a/third_party/exwm/exwm-manage.el +++ b/third_party/exwm/exwm-manage.el @@ -1,7 +1,7 @@ ;;; exwm-manage.el --- Window Management Module for -*- lexical-binding: t -*- ;;; EXWM -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -30,7 +30,6 @@ (defgroup exwm-manage nil "Manage." - :version "25.3" :group 'exwm) (defcustom exwm-manage-finish-hook nil @@ -235,6 +234,23 @@ Override current hinds if FORCE is non-nil." (elt value 2))) ;MotifWmHints.decorations (setq exwm--mwm-hints-decorations nil)))))))) +(defun exwm-manage--update-default-directory (id) + "Update the `default-directory' of X window ID. +Sets the `default-directory' of the EXWM buffer associated with X window to +match its current working directory. + +This only works when procfs is mounted, which may not be the case on some BSDs." + (with-current-buffer (exwm--id->buffer id) + (if-let* ((response (xcb:+request-unchecked+reply exwm--connection + (make-instance 'xcb:ewmh:get-_NET_WM_PID + :window id))) + (pid (slot-value response 'value)) + (cwd (file-symlink-p (format "/proc/%d/cwd" pid))) + ((file-accessible-directory-p cwd))) + (setq default-directory (file-name-as-directory cwd)) + (setq default-directory (expand-file-name "~/"))))) + + (defun exwm-manage--set-client-list () "Set _NET_CLIENT_LIST." (exwm--log) @@ -394,23 +410,20 @@ Override current hinds if FORCE is non-nil." (if (plist-get exwm--configurations 'char-mode) (exwm-input-release-keyboard id) (exwm-input-grab-keyboard id)) - (let ((simulation-keys (plist-get exwm--configurations 'simulation-keys)) - (prefix-keys (plist-get exwm--configurations 'prefix-keys))) - (with-current-buffer (exwm--id->buffer id) - (when simulation-keys - (exwm-input-set-local-simulation-keys simulation-keys)) - (when prefix-keys - (setq-local exwm-input-prefix-keys prefix-keys)))) + (when-let ((simulation-keys (plist-get exwm--configurations 'simulation-keys))) + (exwm-input-set-local-simulation-keys simulation-keys)) + (when-let ((prefix-keys (plist-get exwm--configurations 'prefix-keys))) + (setq-local exwm-input-prefix-keys prefix-keys)) (setq exwm-workspace--switch-history-outdated t) (exwm--update-desktop id) (exwm-manage--update-ewmh-state id) - (with-current-buffer (exwm--id->buffer id) - (when (or (plist-get exwm--configurations 'fullscreen) - (exwm-layout--fullscreen-p)) - (setq exwm--ewmh-state (delq xcb:Atom:_NET_WM_STATE_FULLSCREEN - exwm--ewmh-state)) - (exwm-layout-set-fullscreen id)) - (run-hooks 'exwm-manage-finish-hook))))) + (exwm-manage--update-default-directory id) + (when (or (plist-get exwm--configurations 'fullscreen) + (exwm-layout--fullscreen-p)) + (setq exwm--ewmh-state (delq xcb:Atom:_NET_WM_STATE_FULLSCREEN + exwm--ewmh-state)) + (exwm-layout-set-fullscreen id)) + (run-hooks 'exwm-manage-finish-hook)))) (defun exwm-manage--unmanage-window (id &optional withdraw-only) "Unmanage window ID. diff --git a/third_party/exwm/exwm-randr.el b/third_party/exwm/exwm-randr.el index 8d1824babb83..7f0e50559bfa 100644 --- a/third_party/exwm/exwm-randr.el +++ b/third_party/exwm/exwm-randr.el @@ -1,6 +1,6 @@ ;;; exwm-randr.el --- RandR Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -56,7 +56,6 @@ (defgroup exwm-randr nil "RandR." - :version "25.3" :group 'exwm) (defcustom exwm-randr-refresh-hook nil @@ -91,10 +90,6 @@ corresponding monitors whenever the monitors are active. \\='(1 \"HDMI-1\" 3 \"DP-1\")" :type '(plist :key-type integer :value-type string)) -(with-no-warnings - (define-obsolete-variable-alias 'exwm-randr-workspace-output-plist - 'exwm-randr-workspace-monitor-plist "27.1")) - (defvar exwm-randr--last-timestamp 0 "Used for debouncing events.") (defvar exwm-randr--prev-screen-change-seqnum nil @@ -269,9 +264,6 @@ In a mirroring setup some monitors overlap and should be treated as one." (xcb:flush exwm--connection) (run-hooks 'exwm-randr-refresh-hook)))) -(define-obsolete-function-alias 'exwm-randr--refresh #'exwm-randr-refresh - "27.1") - (defun exwm-randr--on-ScreenChangeNotify (data _synthetic) "Handle `ScreenChangeNotify' event. diff --git a/third_party/exwm/exwm-systemtray.el b/third_party/exwm/exwm-systemtray.el index 7f2b268df932..9e57dae4ebb8 100644 --- a/third_party/exwm/exwm-systemtray.el +++ b/third_party/exwm/exwm-systemtray.el @@ -1,7 +1,7 @@ ;;; exwm-systemtray.el --- System Tray Module for -*- lexical-binding: t -*- ;;; EXWM -;; Copyright (C) 2016-2023 Free Software Foundation, Inc. +;; Copyright (C) 2016-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -57,7 +57,6 @@ (defgroup exwm-systemtray nil "System tray." - :version "25.3" :group 'exwm) (defcustom exwm-systemtray-height nil diff --git a/third_party/exwm/exwm-workspace.el b/third_party/exwm/exwm-workspace.el index 61e2f69d285c..89be6971598c 100644 --- a/third_party/exwm/exwm-workspace.el +++ b/third_party/exwm/exwm-workspace.el @@ -1,6 +1,6 @@ ;;; exwm-workspace.el --- Workspace Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 1015-2023 Free Software Foundation, Inc. +;; Copyright (C) 1015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> @@ -31,7 +31,6 @@ (defgroup exwm-workspace nil "Workspace." - :version "25.3" :group 'exwm) (defcustom exwm-workspace-switch-hook nil diff --git a/third_party/exwm/exwm-xim.el b/third_party/exwm/exwm-xim.el index aea0eb53fbda..1f0c9c460ba5 100644 --- a/third_party/exwm/exwm-xim.el +++ b/third_party/exwm/exwm-xim.el @@ -1,6 +1,6 @@ ;;; exwm-xim.el --- XIM Module for EXWM -*- lexical-binding: t -*- -;; Copyright (C) 2019-2023 Free Software Foundation, Inc. +;; Copyright (C) 2019-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> diff --git a/third_party/exwm/exwm-xsettings.el b/third_party/exwm/exwm-xsettings.el new file mode 100644 index 000000000000..99d6b9c4ac87 --- /dev/null +++ b/third_party/exwm/exwm-xsettings.el @@ -0,0 +1,336 @@ +;;; exwm-xsettings.el --- XSETTINGS Module for EXWM -*- lexical-binding: t -*- + +;; Copyright (C) 2022-2024 Free Software Foundation, Inc. + +;; Author: Steven Allen <steven@stebalien.com> + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Implements the XSETTINGS protocol, allowing Emacs to manage the system theme, +;; fonts, icons, etc. +;; +;; This package can be configured as follows: +;; +;; (require 'exwm-xsettings) +;; (setq exwm-xsettings-theme '("Adwaita" . "Adwaita-dark") ;; light/dark +;; exwm-xsettings `(("Xft/HintStyle" . "hintslight") +;; ("Xft/RGBA" . "rgb") +;; ("Xft/lcdfilter" . "lcddefault") +;; ("Xft/Antialias" . 1) +;; ;; DPI is in 1024ths of an inch, so this is a DPI of +;; ;; 144, equivalent to ;; a scaling factor of 1.5 +;; ;; (144 = 1.5 * 96). +;; ("Xft/DPI" . ,(* 144 1024)) +;; ("Xft/Hinting" . 1))) +;; (exwm-xsettings-enable) +;; +;; To modify these settings at runtime, customize them with +;; `custom-set-variables' or `setopt' (Emacs 29+). E.g., the following will +;; immediately change the icon theme to "Papirus" at runtime, even in running +;; applications: +;; +;; (setopt exwm-xsettings-icon-theme "Papirus") + +;;; Code: + +(require 'xcb-ewmh) +(require 'xcb-xsettings) +(require 'exwm-core) + +(defvar exwm-xsettings--connection nil) +(defvar exwm-xsettings--XSETTINGS_SETTINGS-atom nil) +(defvar exwm-xsettings--XSETTINGS_S0-atom nil) +(defvar exwm-xsettings--selection-owner-window nil) +(defvar exwm-xsettings--serial 0) + +(defun exwm-xsettings--rgba-match (_widget value) + "Return t if VALUE is a valid RGBA color." + (and (numberp value) (<= 0 value 1))) + +(defun exwm-xsettings--custom-set (symbol value) + "Setter used by `exwm-xsettings' customization options. + +SYMBOL is the setting being updated and VALUE is the new value." + (set-default-toplevel-value symbol value) + (exwm-xsettings--update-settings)) + +(defgroup exwm-xsettings nil + "XSETTINGS." + :group 'exwm) + +(defcustom exwm-xsettings nil + "Alist of custom XSETTINGS. +These settings take precedence over `exwm-xsettings-theme' and +`exwm-xsettings-icon-theme'." + :type '(alist :key-type (string :tag "Name") + :value-type (choice :tag "Value" + (string :tag "String") + (integer :tag "Integer") + (list :tag "Color" + (number :tag "Red" + :type-error + "This field should contain a number between 0 and 1." + :match exwm-xsettings--rgba-match) + (number :tag "Green" + :type-error + "This field should contain a number between 0 and 1." + :match exwm-xsettings--rgba-match) + (number :tag "Blue" + :type-error + "This field should contain a number between 0 and 1." + :match exwm-xsettings--rgba-match) + (number :tag "Alpha" + :type-error + "This field should contain a number between 0 and 1." + :match exwm-xsettings--rgba-match + :value 1.0)))) + :initialize #'custom-initialize-default + :set #'exwm-xsettings--custom-set) + +(defcustom exwm-xsettings-theme nil + "The system-wide theme." + :type '(choice (string :tag "Theme") + (cons (string :tag "Light Theme") + (string :tag "Dark Theme"))) + :initialize #'custom-initialize-default + :set #'exwm-xsettings--custom-set) + +(defcustom exwm-xsettings-icon-theme nil + "The system-wide icon theme." + :type '(choice (string :tag "Icon Theme") + (cons (string :tag "Light Icon Theme") + (string :tag "Dark Icon Theme"))) + :initialize #'custom-initialize-default + :set #'exwm-xsettings--custom-set) + +(defalias 'exwm-xsettings--color-dark-p + (if (eval-when-compile (< emacs-major-version 29)) + ;; Borrowed from Emacs 29. + (lambda (rgb) + "Whether RGB is more readable against white than black." + (unless (<= 0 (apply #'min rgb) (apply #'max rgb) 1) + (error "RGB components %S not in [0,1]" rgb)) + (let* ((r (expt (nth 0 rgb) 2.2)) + (g (expt (nth 1 rgb) 2.2)) + (b (expt (nth 2 rgb) 2.2)) + (y (+ (* r 0.2126) (* g 0.7152) (* b 0.0722)))) + (< y 0.325))) + 'color-dark-p)) + +(defun exwm-xsettings--pick-theme (theme) + "Pick a light or dark theme from the given THEME. +If THEME is a string, it's returned directly. +If THEME is a cons of (LIGHT . DARK), the appropriate theme is picked based on +the default face's background color." + (pcase theme + ((cl-type string) theme) + (`(,(cl-type string) . ,(cl-type string)) + (if (exwm-xsettings--color-dark-p (color-name-to-rgb (face-background 'default))) + (cdr theme) (car theme))) + (_ (error "Expected theme to be a string or a pair of strings")))) + +(defun exwm-xsettings--get-settings () + "Get the current settings. +Combines `exwm-xsettings', `exwm-xsettings-theme' (if set), and +`exwm-xsettings-icon-theme' (if set)." + (cl-remove-duplicates + (append + exwm-xsettings + (when exwm-xsettings-theme + (list (cons "Net/ThemeName" (exwm-xsettings--pick-theme exwm-xsettings-theme)))) + (when exwm-xsettings-icon-theme + (list (cons "Net/IconThemeName" (exwm-xsettings--pick-theme exwm-xsettings-icon-theme))))) + :key 'car + :test 'string=)) + +(defun exwm-xsettings--make-settings (settings serial) + "Construct a new settings object. +SETTINGS is an alist of key/value pairs. +SERIAL is a sequence number." + (make-instance 'xcb:xsettings:-Settings + :byte-order (if xcb:lsb 0 1) + :serial serial + :settings-len (length settings) + :settings + (mapcar + (lambda (prop) + (let* ((name (car prop)) + (value (cdr prop)) + (common (list :name name + :name-len (length name) + :last-change-serial serial))) + (pcase value + ((cl-type string) + (apply #'make-instance 'xcb:xsettings:-SETTING_STRING + :value-len (length value) + :value value + common)) + ((cl-type integer) + (apply #'make-instance 'xcb:xsettings:-SETTING_INTEGER + :value value common)) + ((and (cl-type list) (app length (or 3 4))) + ;; Convert from RGB(A) to 16bit integers. + (setq value (mapcar (lambda (x) (round (* x #xffff))) value)) + (apply #'make-instance 'xcb:xsettings:-SETTING_COLOR + :red (pop value) + :green (pop value) + :blue (pop value) + :alpha (or (pop value) #xffff))) + (_ (error "Setting value must be a string, integer, or length 3-4 list"))))) + settings))) + +(defun exwm-xsettings--update-settings () + "Update the xsettings." + (when exwm-xsettings--connection + (setq exwm-xsettings--serial (1+ exwm-xsettings--serial)) + (let* ((settings (exwm-xsettings--get-settings)) + (bytes (xcb:marshal (exwm-xsettings--make-settings settings exwm-xsettings--serial)))) + (xcb:+request exwm-xsettings--connection + (make-instance 'xcb:ChangeProperty + :mode xcb:PropMode:Replace + :window exwm-xsettings--selection-owner-window + :property exwm-xsettings--XSETTINGS_SETTINGS-atom + :type exwm-xsettings--XSETTINGS_SETTINGS-atom + :format 8 + :data-len (length bytes) + :data bytes))) + (xcb:flush exwm-xsettings--connection))) + +(defun exwm-xsettings--on-theme-change (&rest _) + "Called when the Emacs theme is changed." + ;; We only bother updating the xsettings if changing the theme could effect + ;; the settings. + (when (or (consp exwm-xsettings-theme) (consp exwm-xsettings-icon-theme)) + (exwm-xsettings--update-settings))) + +(defun exwm-xsettings--on-SelectionClear (_data _synthetic) + "Called when another xsettings daemon takes over." + (exwm--log "XSETTINGS manager has been replaced.") + (exwm-xsettings--exit)) + +(cl-defun exwm-xsettings--init () + "Initialize the XSETTINGS module." + (exwm--log) + + (cl-assert (not exwm-xsettings--connection)) + + ;; Connect + (setq exwm-xsettings--connection (xcb:connect)) + (set-process-query-on-exit-flag (slot-value exwm-xsettings--connection + 'process) + nil) + + ;; Intern the atoms. + (setq exwm-xsettings--XSETTINGS_SETTINGS-atom + (exwm--intern-atom "_XSETTINGS_SETTINGS" exwm-xsettings--connection) + + exwm-xsettings--XSETTINGS_S0-atom + (exwm--intern-atom "_XSETTINGS_S0" exwm-xsettings--connection)) + + ;; Detect running XSETTINGS managers. + (with-slots (owner) + (xcb:+request-unchecked+reply exwm-xsettings--connection + (make-instance 'xcb:GetSelectionOwner + :selection exwm-xsettings--XSETTINGS_S0-atom)) + (when (/= owner xcb:Window:None) + (xcb:disconnect exwm-xsettings--connection) + (setq exwm-xsettings--connection nil) + (warn "[EXWM] Other XSETTINGS manager detected") + (cl-return-from exwm-xsettings--init))) + + (let ((id(xcb:generate-id exwm-xsettings--connection))) + (setq exwm-xsettings--selection-owner-window id) + + ;; Create a settings window. + (xcb:+request exwm-xsettings--connection + (make-instance 'xcb:CreateWindow + :wid id + :parent exwm--root + :class xcb:WindowClass:InputOnly + :x 0 + :y 0 + :width 1 + :height 1 + :border-width 0 + :depth 0 + :visual 0 + :value-mask xcb:CW:OverrideRedirect + :override-redirect 1)) + + ;; Set _NET_WM_NAME. + (xcb:+request exwm-xsettings--connection + (make-instance 'xcb:ewmh:set-_NET_WM_NAME + :window id + :data "EXWM: exwm-xsettings--selection-owner-window")) + + ;; Apply the XSETTINGS properties. + (exwm-xsettings--update-settings) + + ;; Take ownership and notify. + (xcb:+request exwm-xsettings--connection + (make-instance 'xcb:SetSelectionOwner + :owner id + :selection exwm-xsettings--XSETTINGS_S0-atom + :time xcb:Time:CurrentTime)) + (xcb:+request exwm-xsettings--connection + (make-instance 'xcb:SendEvent + :propagate 0 + :destination exwm--root + :event-mask xcb:EventMask:StructureNotify + :event (xcb:marshal + (make-instance 'xcb:xsettings:-ClientMessage + :window exwm--root + :time xcb:Time:CurrentTime + :selection exwm-xsettings--XSETTINGS_S0-atom + :owner id) + exwm-xsettings--connection))) + + ;; Detect loss of XSETTINGS ownership. + (xcb:+event exwm-xsettings--connection 'xcb:SelectionClear + #'exwm-xsettings--on-SelectionClear) + + (xcb:flush exwm-xsettings--connection)) + + ;; Update the xsettings if/when the theme changes. + (add-hook 'enable-theme-functions #'exwm-xsettings--on-theme-change) + (add-hook 'disable-theme-functions #'exwm-xsettings--on-theme-change)) + +(defun exwm-xsettings--exit () + "Exit the XSETTINGS module." + (exwm--log) + + (when exwm-xsettings--connection + (remove-hook 'enable-theme-functions #'exwm-xsettings--on-theme-change) + (remove-hook 'disable-theme-functions #'exwm-xsettings--on-theme-change) + + (xcb:disconnect exwm-xsettings--connection) + + (setq exwm-xsettings--connection nil + exwm-xsettings--XSETTINGS_SETTINGS-atom nil + exwm-xsettings--XSETTINGS_S0-atom nil + exwm-xsettings--selection-owner-window nil))) + +(defun exwm-xsettings-enable () + "Enable xsettings support for EXWM." + (exwm--log) + (add-hook 'exwm-init-hook #'exwm-xsettings--init) + (add-hook 'exwm-exit-hook #'exwm-xsettings--exit)) + +(provide 'exwm-xsettings) + +;;; exwm-xsettings.el ends here diff --git a/third_party/exwm/exwm.el b/third_party/exwm/exwm.el index 4870d4bc4287..c4900eab48ca 100644 --- a/third_party/exwm/exwm.el +++ b/third_party/exwm/exwm.el @@ -1,13 +1,13 @@ ;;; exwm.el --- Emacs X Window Manager -*- lexical-binding: t -*- -;; Copyright (C) 2015-2023 Free Software Foundation, Inc. +;; Copyright (C) 2015-2024 Free Software Foundation, Inc. ;; Author: Chris Feng <chris.w.feng@gmail.com> -;; Maintainer: Adrián Medraño Calvo <adrian@medranocalvo.com> +;; Maintainer: Adrián Medraño Calvo <adrian@medranocalvo.com>, Steven Allen <steven@stebalien.com>, Daniel Mendler <mail@daniel-mendler.de> ;; Version: 0.28 -;; Package-Requires: ((xelb "0.18")) +;; Package-Requires: ((emacs "27.1") (xelb "0.18")) ;; Keywords: unix -;; URL: https://github.com/ch11ng/exwm +;; URL: https://github.com/emacs-exwm/exwm ;; This file is part of GNU Emacs. @@ -29,14 +29,18 @@ ;; Overview ;; -------- ;; EXWM (Emacs X Window Manager) is a full-featured tiling X window manager -;; for Emacs built on top of [XELB](https://github.com/ch11ng/xelb). +;; for Emacs built on top of [XELB](https://github.com/emacs-exwm/xelb). ;; It features: ;; + Fully keyboard-driven operations ;; + Hybrid layout modes (tiling & stacking) ;; + Dynamic workspace support ;; + ICCCM/EWMH compliance -;; + (Optional) RandR (multi-monitor) support -;; + (Optional) Built-in system tray +;; Optional features: +;; + RandR (multi-monitor) support +;; + System tray +;; + Input method +;; + Background setting support +;; + XSETTINGS server ;; Installation & configuration ;; ---------------------------- @@ -54,7 +58,7 @@ ;; xinit -- vt01 ;; ;; You should additionally hide the menu-bar, tool-bar, etc to increase the -;; usable space. Please check the wiki (https://github.com/ch11ng/exwm/wiki) +;; usable space. Please check the wiki (https://github.com/emacs-exwm/exwm/wiki) ;; for more detailed instructions on installation, configuration, usage, etc. ;; References: @@ -77,7 +81,6 @@ (defgroup exwm nil "Emacs X Window Manager." :tag "EXWM" - :version "25.3" :group 'applications :prefix "exwm-") @@ -97,7 +100,10 @@ "Normal hook run when window title is updated." :type 'hook) -(defcustom exwm-blocking-subrs '(x-file-dialog x-popup-dialog x-select-font) +(defcustom exwm-blocking-subrs + ;; `x-file-dialog' and `x-select-font' are missing on some Emacs builds, for + ;; example on the X11 Lucid build. + '(x-file-dialog x-popup-dialog x-select-font message-box message-or-box) "Subrs (primitives) that would normally block EXWM." :type '(repeat function)) @@ -110,6 +116,10 @@ (defconst exwm--server-name "server-exwm" "Name of the subordinate Emacs server.") +(defvar exwm--server-timeout 1 + "Number of seconds to wait for the subordinate Emacs server to exit. +After this time, the server will be killed.") + (defvar exwm--server-process nil "Process of the subordinate Emacs server.") (defun exwm-reset () @@ -166,7 +176,7 @@ Argument XWIN contains the X window of the `exwm-mode' buffer." (when reply (setq desktop (slot-value reply 'value)) (cond - ((eq desktop 4294967295.) + ((and desktop (= desktop 4294967295.)) (unless (or (not exwm--floating-frame) (eq exwm--frame exwm-workspace--current) (and exwm--desktop @@ -482,9 +492,6 @@ RAW-DATA contains unmarshalled ClientMessage event data." (exwm-workspace-switch (elt data 0))) ;; _NET_ACTIVE_WINDOW. ((= type xcb:Atom:_NET_ACTIVE_WINDOW) - (dolist (f exwm-workspace--list) - (when (eq id (frame-parameter f 'exwm-outer-id)) - (x-focus-frame f t))) (let ((buffer (exwm--id->buffer id)) iconic window) (if (buffer-live-p buffer) @@ -1002,8 +1009,13 @@ FRAME, if given, indicates the X display EXWM should manage." (defun exwm--server-stop () "Stop the subordinate Emacs server." (exwm--log) - (server-force-delete exwm--server-name) (when exwm--server-process + (when (process-live-p exwm--server-process) + (cl-loop + initially (signal-process exwm--server-process 'TERM) + while (process-live-p exwm--server-process) + repeat (* 10 exwm--server-timeout) + do (sit-for 0.1))) (delete-process exwm--server-process) (setq exwm--server-process nil))) @@ -1020,7 +1032,7 @@ FUNCTION is the function to be evaluated, ARGS are the arguments." (car command-line-args) ;The executable file "-d" (frame-parameter nil 'display) "-Q" - (concat "--daemon=" exwm--server-name) + (concat "--fg-daemon=" exwm--server-name) "--eval" ;; Create an invisible frame "(make-frame '((window-system . x) (visibility)))")) diff --git a/third_party/overlays/tvl.nix b/third_party/overlays/tvl.nix index 661470914351..861c66694a85 100644 --- a/third_party/overlays/tvl.nix +++ b/third_party/overlays/tvl.nix @@ -49,6 +49,19 @@ depot.nix.readTree.drvTargets { self.git ]; }); + + # Pin xelb to a newer one until the new maintainers do a release. + xelb = eself.trivialBuild { + pname = "xelb"; + version = "0.19-dev"; # invented version, last actual release was 0.18 + + src = self.fetchFromGitHub { + owner = "emacs-exwm"; + repo = "xelb"; + rev = "86089eba2de6c818bfa2fac075cb7ad876262798"; + sha256 = "1mmlrd2zpcwiv8gh10y7lrpflnbmsycdascrxjr3bfcwa8yx7901"; + }; + }; }) ); |