;;; early-init.el --- frames conf. -*- lexical-binding:t;no-byte-compile:t -*- ;; Copyright (C) 2020-2023 Sean Whitton ;; ;; This file 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. ;; ;; This file 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 this file. If not, see . (let ((in-tree ;; `installation-directory' is normally nil when running an installed ;; Emacs. If I've installed Emacs somewhere under HOME, then I can ;; ensure that it is indeed nil when running that build. ;; Thus, if `installation-directory' is non-nil and under HOME, we can ;; be sure that we are running an uninstalled executable. (and installation-directory (file-in-directory-p installation-directory (expand-file-name "~/"))))) (when in-tree ;; Make packages compiled against my emacs-snapshot Debian packages ;; available to in-tree builds. (Previously we patched the code computing ;; the default value of `package-directory-list' in those builds.) (when (file-directory-p "/usr/share/emacs-snapshot/site-lisp/elpa") (add-to-list 'package-directory-list "/usr/share/emacs-snapshot/site-lisp/elpa" t)) ;; Run Debian's site-start library site-run-file for in-tree builds too. ;; (Used to do this by patching `command-line' in those builds.) (when (file-readable-p "/etc/emacs/site-start.d/00debian.el") (load "/etc/emacs/site-start.d/00debian.el"))) (setq frame-title-format (format "%%b — %s%c%s@%s" (if (stringp (daemonp)) (daemonp) "Emacs") (if in-tree ?: ?-) emacs-version system-name) icon-title-format t)) ;;; Per docstring for `after-make-frame-functions', these additions to that ;;; list of functions are made in this file in order that they can affect the ;;; initial frame. (defun spw/set-fontset-fonts (frame) "Set some fonts for specific charsets. This has to happen after there's at least one graphical frame, or the fonts won't be found." (when (display-graphic-p frame) (setq after-make-frame-functions (delq #'spw/set-fontset-fonts after-make-frame-functions)) (let ((spec (font-spec :name "Noto Serif CJK JP"))) (dolist (charset '(kana han symbol cjk-misc bopomofo)) (set-fontset-font t charset spec))) (set-fontset-font t 'hangul (font-spec :name "Noto Serif CJK KR")))) (add-to-list 'after-make-frame-functions #'spw/set-fontset-fonts) (defvar spw/tiling-wm-p nil "Have we had at least one frame managed by a tiling window manager?") (defun spw/disable-mouse-autoselect-window (orig-fun &rest args) (let (mouse-autoselect-window) (apply orig-fun args))) ;; 'emacsclient --spw/update-environment' supplies us with I3SOCK, so if we ;; see that variable we know there is at least one frame under i3 or swaywm, ;; and so we want to set `focus-follows-mouse' to t. As we can't do that ;; frame-locally, once it's set it's set. (I used to set ;; `mouse-autoselect-window' to t too, but it often caused unwanted focus ;; changes, and it makes the tool and menu bars much fiddlier to use.) ;; ;; On the other hand, ideally functions like `spw/save-buffer-for-later' ;; decide whether to open a new frame or a new tab frame-locally, so we used ;; to temporarily set DISPLAY to (frame-parameter (selected-frame) 'display) ;; and then call wmctrl(1) to get the name of the window manager for that ;; frame, and stored it in a frame parameter. But that works only for X11, ;; not Wayland. So for now we just set a boolean `spw/tiling-wm-p' to which ;; functions like `spw/save-buffer-for-later' can respond. (defun spw/detect-tiling-wm (frame) (unless (or spw/tiling-wm-p (not (setq spw/tiling-wm-p (or (getenv "I3SOCK") (getenv "SWAYSOCK"))))) (setq focus-follows-mouse t ;; mouse-autoselect-window t desktop-restore-forces-onscreen nil) ;; Disable `mouse-autoselect-window' during `display-buffer', to avoid ;; surprise focus changes -- some code that calls `display-buffer' does ;; not expect `mouse-autoselect-window' to be on. E.g. `magit-status' can ;; leave focus in the wrong window without this. ;; (advice-add 'display-buffer ;; :around #'spw/disable-mouse-autoselect-window) ) ;; If X or Sway, we know we have a usable primary selection, so we used to ;; turn off additionally copying to the clipboard. However, we do want to ;; be able to yank from the clipboard. See also NEWS.24. ;; (setq select-enable-clipboard ;; (not (or spw/tiling-wm-p (eq (framep frame) 'x)))) ) (add-to-list 'after-make-frame-functions #'spw/detect-tiling-wm)