emacs-config/config-exwm.org

25 KiB

e2wm

  (use-package e2wm
    :bind (("M-+" . e2wm:start-management)))

desktop-environment

  (use-package desktop-environment
    :init
    (desktop-environment-mode))

Meta

(use-package exwm)
(require 'exwm-config)
(exwm-config-default)

Naming Windows

  (defvar my/window-name nil)

  (defun exwmx-name-buffer ()
    (interactive)
    (let* ((xprograms (mapcar (lambda (a) (plist-get a :instance)) (exwmx-appconfig--get-all-appconfigs)))
           (name (completing-read "Name: " xprograms)))
      (if (and (get-buffer name)
               (not (equal (get-buffer name) (current-buffer)))
               (y-or-n-p (format "Already a buffer named \"%s\". Would you like to swap?" name)))
          (let ((oname (completing-read "Name of other buffer: " xprograms)))
            (exwm-workspace-rename-buffer "This is a stupid name that no one would ever choose for a buffer, hopefully")
            (save-window-excursion
              (switch-to-buffer (get-buffer name))
              (exwm-workspace-rename-buffer oname)
              (setq-local exwm-instance-name oname))
            (exwm-workspace-rename-buffer name)
            (setq-local exwm-instance-name name))
        (exwm-workspace-rename-buffer name)
        (setq-local exwm-instance-name name))))

  (defun exwm-rename-buffer ()
    (interactive)
    (when my/window-name
      (exwm-workspace-rename-buffer my/window-name)
      (setq-local exwm-instance-name my/window-name)
      (setq my/window-name nil)))

  ;; Add these hooks in a suitable place (e.g., as done in exwm-config-default)
  (add-hook 'exwm-manage-finish-hook 'exwm-rename-buffer)

  (defun launch-program-with-name (cmd name)
    (interactive)
    (when name (setq my/window-name name))
    (start-process-shell-command cmd nil cmd))

exwm-x stuff and naming windows

  (use-package exwm-x)
  (require 'exwmx-quickrun) 

  (defun exwmx-quickrun (command &optional search-alias ruler)
    (exwmx--switch-window)
    (let* ((ruler-plist-p (and ruler (exwmx--plist-p ruler)))
           (keys
            ;; Deal with ruler which is like (:class :instance :title)
            (if (and ruler (listp ruler) (not ruler-plist-p))
                (exwmx--clean-keylist ruler)
              '(:class :instance)))
           (appconfigs (exwmx-appconfig--get-all-appconfigs))
           (cmd (if search-alias
                    (or (plist-get (exwmx-appconfig--search
                                    `((:alias ,command)))
                                   :command)
                        (when appconfigs
                          (let ((appconfig (exwmx-appconfig--select-appconfig)))
                            (plist-put appconfig :alias command)
                            (exwmx-appconfig--add-appconfig appconfig)
                            (plist-get appconfig :command))))
                  command))
           (buffer (or (if search-alias
                           (exwmx-quickrun--find-buffer
                            (if ruler-plist-p
                                ruler
                              (exwmx-appconfig--get-subset
                               (exwmx-appconfig--search
                                `((:alias ,command)))
                               keys)))
                         (exwmx-quickrun--find-buffer
                          (if ruler-plist-p
                              ruler
                            (exwmx-appconfig--get-subset
                             (exwmx-appconfig--search
                              `((:command ,command)))
                             keys)))))))
      (if (and search-alias (not cmd))
          (message "EXWM-X: please run `exwmx-appconfig' to add appconfig.")
        (message "EXWM-X Quick Run: %s" cmd))
      ;; If current application window is a floating-window, minumize it.
      (when (and (eq major-mode 'exwm-mode)
                 exwm--floating-frame)
        (exwm-floating-hide))
      (if buffer
          (exwm-workspace-switch-to-buffer buffer)
        (when cmd
          (launch-program-with-name cmd (plist-get ruler :instance))))))

  (defun exwmx-quickrun--find-buffer (ruler)
    "Find a exwm buffer which match `ruler', ruler is
          a plist with three keys: :class, :instance and :title."
    (let ((current (current-buffer))
          (buffers (buffer-list))
          (result '()))
      (while buffers
        (let ((buffer (pop buffers))
              (class (plist-get ruler :class))
              (instance (plist-get ruler :instance))
              (title (plist-get ruler :title)))
          (with-current-buffer buffer
            (when (and (or class instance title)
                       (exwmx--string-match-p (or class ".*") exwm-class-name)
                       (exwmx--string-match-p (or (concat "^" instance "$") ".*") exwm-instance-name)
                       (exwmx--string-match-p (or title ".*") exwm-title))
              (push buffer result)))))
      (setq result (reverse result))
      ;; If two more buffers are found, switch between these buffer.
      (if (and (cadr result)
               (eq (car result) current))
          (cadr result)
        (car result))))

  (defmacro quickrun-lambda (cmd instance)
    (if (null instance)
        `(lambda ()
           (interactive)
           (exwmx-quickrun ,cmd))
      `(lambda ()
         (interactive)
         (exwmx-quickrun ,cmd nil '(:class ".*" :instance ,instance)))))

  (use-package dmenu)            

  (make-thread 
   #'dmenu--cache-executable-files)


  (defun read-program ()
    (funcall #'ido-completing-read "$ "
             (append dmenu--history-list
                     (cl-remove-if (lambda (x)
                                     (member x dmenu--history-list))
                                   dmenu--cache-executable-files))))

  (defun launch-program (command &optional process-name)
    (interactive (list (read-program)))
    (setq dmenu--history-list (cons command (remove command dmenu--history-list)))
    (when (> (length dmenu--history-list)
             dmenu-history-size)
      (setcdr (nthcdr (- dmenu-history-size 1)
                      dmenu--history-list)
              nil))
    (let ((name (or process-name command)))
      (start-process-shell-command name nil command)))

  (defun exwmx-launch-program (command &optional process-name)
    (interactive (list (read-program)))
    (setq dmenu--history-list (cons command (remove command dmenu--history-list)))
    (when (> (length dmenu--history-list)
             dmenu-history-size)
      (setcdr (nthcdr (- dmenu-history-size 1)
                      dmenu--history-list)
              nil))
    (exwmx-quickrun command))

  ;; (exwmx-quickrun "firefox" nil '(:class ".*" :instance "School"))

  ;; (exwmx-quickrun--find-buffer '(:class ".*" :instance "Hello"))

Youtube split

  (defun youtube-split (arg)
    (interactive "P")
    (let ((buf (get-buffer "youtube"))
          (back (current-buffer)))
      (delete-other-windows)
      (if buf 
          (switch-to-buffer buf)
        (when arg
          (launch-program-with-name "firefox" "youtube")))
      (side-window-op 'left 472 buf)
      (switch-to-buffer back)))

  (defun big-youtube-split (arg)
    (interactive "P")
    (delete-other-windows)
    (let ((buf (get-buffer "youtube")))
      (if buf
          (switch-to-buffer buf)
        (when arg
          (launch-program-with-name "firefox" "youtube")))
      (side-window-op 'left 630 buf)))

  (defun side-window-op (side &optional size buffer)
    (let ((prev-win (selected-window))
          (win (display-buffer-in-side-window
                (or buffer (current-buffer))
                `((side . ,side)))))
      (select-window win)
      (set-window-dedicated-p win t)
      (set-window-parameter win 'no-delete-other-windows t)
      (when size
        (window-resize win (- size (window-pixel-width)) t nil t))
      (select-window prev-win)))

  (defun side-left-window ()
    (interactive)
    (side-window-op 'left))

  (defun side-right-window ()
    (interactive)
    (side-window-op 'right))

  (defun side-bottom-window ()
    (interactive)
    (side-window-op 'bottom))

  (setq window-sides-vertical t)

Disable simulation keys on an emacs window

  (add-hook 'exwm-manage-finish-hook
            (lambda ()
              (when (and exwm-class-name (string= exwm-class-name "Emacs"))
                (exwm-input-set-local-simulation-keys nil))))

Custom keymap

  (use-package vterm)

  (defmacro exec (body)
    `(lambda ()
       (interactive)
       ,body))

  (defun toggle-notifications ()
    (interactive)
    (shell-command "kill -s USR1 $(pidof deadd-notification-center)"))

  (add-to-list 'exwm-input-prefix-keys ?\C-t)
  (defun simulate-C-t (arg)
    (interactive "P")
    (if (eq major-mode 'exwm-mode)
        (exwm-input--fake-key ?\C-t)
      (transpose-chars arg)))
  (use-package zeal-at-point)
  (define-key *root-map* (kbd "C-d") (quickrun-lambda "zeal" "zeal"))
  (define-key *root-map* (kbd "d") #'zeal-at-point)
  (define-key *root-map* (kbd "C-t") 'simulate-C-t)
  (define-key *root-map* (kbd "C-p") 'exwmx-launch-program)
  (define-key *root-map* (kbd "e") (quickrun-lambda "emacs" "emacs"))
  (define-key *root-map* (kbd "s") (quickrun-lambda "steam" nil))
  (define-key *root-map* (kbd "V") (quickrun-lambda "VBoxManage startvm \"Windows 7\"" "VirtualBox Machine"))
  (define-key *root-map* (kbd "r") 'exwmx-name-buffer)
  (define-key *root-map* (kbd ")") (lambda () (interactive) (leaving-computer) (shell-command "sleep 2s ; xset dpms force off")))

  (define-prefix-command '*window-map*)
  (define-key *root-map* (kbd "w") '*window-map*)
  (define-key *window-map* (kbd "y") 'youtube-split)
  (define-key *window-map* (kbd "Y") 'big-youtube-split)
  (define-key *window-map* (kbd "j") 'side-bottom-window)
  (define-key *window-map* (kbd "h") 'side-left-window)
  (define-key *window-map* (kbd "l") 'side-right-window)
  (define-key *window-map* (kbd "d") 'window-toggle-side-windows)

  (define-prefix-command '*firefox-map*)
  (define-key *firefox-map* (kbd "c") (quickrun-lambda "google-chrome-stable" "chrome"))
  (define-key *firefox-map* (kbd "f") (quickrun-lambda "firefox" "firefox"))
  (define-key *firefox-map* (kbd "1") (quickrun-lambda "firefox" "firefox1"))
  (define-key *firefox-map* (kbd "2") (quickrun-lambda "firefox" "firefox2"))
  (define-key *firefox-map* (kbd "3") (quickrun-lambda "firefox" "firefox3"))
  (define-key *firefox-map* (kbd "4") (quickrun-lambda "firefox" "firefox4"))
  (define-key *firefox-map* (kbd "d") (quickrun-lambda "firefox" "development"))
  (define-key *firefox-map* (kbd "s") (quickrun-lambda "firefox" "school"))
  (define-key *firefox-map* (kbd "w") (quickrun-lambda "firefox" "work"))
  (define-key *firefox-map* (kbd "y") (quickrun-lambda "firefox" "youtube"))

  (define-key *root-map* (kbd "f") '*firefox-map*)

  (define-prefix-command '*music-map*)
  (define-key *music-map* (kbd "SPC") (exec (shell-command "clementine -t")))
  (define-key *music-map* (kbd "n") (exec (shell-command "clementine --next")))
  (define-key *music-map* (kbd "p") (exec (shell-command "clementine --previous")))
  (define-key *music-map* (kbd "r") (exec (shell-command "clementine --restart-or-previous")))
  (defhydra clementine-volume-hydra (*music-map* "v")
    "Clementine volume up and down"
    ("j" (lambda () (interactive) (shell-command "clementine --volume-down")))
    ("J" (lambda () (interactive) (shell-command "clementine --volume-decrease-by 25")))
    ("k" (lambda () (interactive) (shell-command "clementine --volume-up")))
    ("K" (lambda () (interactive) (shell-command "clementine --volume-increase-by 25")))
    ("q" nil))

  (define-key *root-map* (kbd "m") '*music-map*)

exwm-background

  (add-to-list 'load-path "~/.emacs.d/submodule/exwm-background/")
  (require 'exwm-background)
  (define-key *window-map* (kbd "t") 'exwm-background/window-transparency-hydra/body)
  (setq window-system-default-frame-alist `((x . ((alpha . (,exwm-background/current-transparency . 50))))))
  (exwm-global-set-key (kbd "s-v") #'exwm-background/toggle-viewing-background)
  (exwm-global-set-key (kbd "s-b") #'exwm-background/exwm-background-window) ;; TODO: Fix keybinding
  (define-key desktop-environment-mode-map (kbd "<S-XF86MonBrightnessDown>") #'exwm-background/decrease-transparency)
  (define-key desktop-environment-mode-map (kbd "<S-XF86MonBrightnessUp>") #'exwm-background/increase-transparency)
  (define-key *window-map* (kbd "b") #'exwm-background/exwm-background-window)
  (define-key *root-map* (kbd "k") #'exwm-background/exwm-send-key-to-background)
  (define-key *root-map* (kbd "C-k") #'exwm-background/exwm-send-key-to-background-loop)

toggle dedicated

  (defun my/toggle-dedicated-window ()
    (interactive)
    (let ((win (selected-window)))
      (set-window-dedicated-p win (not (window-dedicated-p win)))))

This is so that I can send fullscreen windows to the back

  (cl-defun my/exwm-layout-set-fullscreen (&optional id)
    "Make window ID fullscreen."
    (interactive)
    (exwm--log "id=#x%x" (or id 0))
    (unless (and (or id (derived-mode-p 'exwm-mode))
                 (not (exwm-layout--fullscreen-p)))
      (cl-return-from exwm-layout-set-fullscreen))
    (with-current-buffer (if id (exwm--id->buffer id) (window-buffer))
      ;; Expand the X window to fill the whole screen.
      (with-slots (x y width height) (exwm-workspace--get-geometry exwm--frame)
        (exwm--set-geometry exwm--id x y width height))
      ;; Raise the X window.
      (xcb:+request exwm--connection
          (make-instance 'xcb:ConfigureWindow
                         :window exwm--id
                         :value-mask (logior xcb:ConfigWindow:BorderWidth
                                             xcb:ConfigWindow:StackMode)
                         :border-width 0
                         :stack-mode xcb:StackMode:Above))
      (xcb:+request exwm--connection
          (make-instance 'xcb:ewmh:set-_NET_WM_STATE
                         :window exwm--id
                         :data (vector xcb:Atom:_NET_WM_STATE_FULLSCREEN)))
      (xcb:flush exwm--connection)
      ;;(set-window-dedicated-p (get-buffer-window) t)
      (cl-pushnew xcb:Atom:_NET_WM_STATE_FULLSCREEN exwm--ewmh-state)
      (exwm-input--release-keyboard exwm--id)))


  (advice-add #'exwm-layout-set-fullscreen :override #'my/exwm-layout-set-fullscreen)

Switch window

  (setq switch-window-input-style 'minibuffer)

Multimonitor support

  (require 'exwm-randr)
  (exwm-randr-enable)

Keybindings

  (use-package transpose-frame)

  (exwm-global-set-key (kbd "s-r") #'exwm-reset)
  (exwm-global-set-key (kbd "s-l") #'lock-screen)
  (exwm-global-set-key (kbd "s-c") #'org-capture)
  (exwm-global-set-key (kbd "s-n") #'switch-window)
  (exwm-global-set-key (kbd "s-k") #'kill-this-buffer)
  (exwm-global-set-key (kbd "s-z") #'resize-window)
  (exwm-global-set-key (kbd "s-s") #'youtube-split)
  (exwm-global-set-key (kbd "s-n") #'switch-to-next-buffer)
  (exwm-global-set-key (kbd "s-p") #'switch-to-prev-buffer)
  (exwm-global-set-key (kbd "s-a") #'my/toggle-keyboard)
  (exwm-global-set-key my/keymap-key '*root-map*)

  (exwm-global-set-key (kbd "s-h") 'windmove-left)
  (exwm-global-set-key (kbd "s-l") 'windmove-right)
  (define-key desktop-environment-mode-map (kbd "s-l") nil)

  (defun dvorak? ()
    (string-match-p "de(neo_dvorak)" 
                    (shell-command-to-string "setxkbmap -v | grep symbols")))

  (defun set-keyboard (layout)
    (shell-command (format "setxkbmap %s" layout)))

  (defun my/toggle-keyboard ()
    (interactive)
    (if (dvorak?)
        (set-keyboard "us")
      (set-keyboard "de neo_dvorak")))

  ;; Don't do this one, causes blinking
  (global-set-key (kbd "C-x p") 'launch-program)
  ;; These have issues, presumably utf8 or something
  (global-set-key (kbd "M-…") 'multi-term)
  (global-set-key (kbd "C-ü") 'undo-tree-undo)

  (defun prompt-workspace (&optional prompt)
    "Prompt for a workspace, returning the workspace frame."
    (exwm-workspace--update-switch-history)
    (let* ((current-idx (exwm-workspace--position exwm-workspace--current))
           (history-add-new-input nil)  ;prevent modifying history
           (history-idx (read-from-minibuffer
                         (or prompt "Workspace: ")
                         (elt exwm-workspace--switch-history current-idx)
                         exwm-workspace--switch-map nil
                         `(exwm-workspace--switch-history . ,current-idx)))
           (workspace-idx (mod (1- (cl-position history-idx exwm-workspace--switch-history
                                                :test #'equal)) 
                               10)))
      (elt exwm-workspace--list workspace-idx)))

  (advice-add 'exwm-workspace--prompt-for-workspace
              :override
              #'prompt-workspace)

Helper functions

  (setq i3-string "Xephyr -br -ac -noreset -resizeable -screen 1920x1080 :8 & sleep 1s; DISPLAY=:8 i3")
  (setq xfce4-string "Xephyr -br -ac -noreset -resizeable -screen 1920x1080 :8 & sleep 1s; DISPLAY=:8 xfce4-session")
  (setq kde-string "Xephyr -br -ac -noreset -resizeable -screen 1920x1080 :8 & sleep 1s; DISPLAY=:8 startkde")
  (setq kde+exwm-string "Xephyr -br -ac -noreset -resizeable -screen 1920x1080 :8 & sleep 1s; DISPLAY=:8 KDEWM=/usr/bin/emacs startkde")
  (defvar exwm-startup-programs
    '("megasync"
      "deadd-notification-center"
      "/usr/lib/kdeconnectd"
      ("compton -f -i .7 -b")
      ;; ("compton -f -i .7 -b --backend glx --blur-background --blur-method kawase --blur-strength 2")
      ("/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1")
      ("/usr/lib/notification-daemon-1.0/notification-daemon")
      ("nm-applet")
      ))
  (defvar hard-drive-space "")

  (defun launch-i3 ()
    (interactive)
    (launch-program i3-string))

  (defun launch-xfce ()
    (interactive)
    (launch-program xfce4-string))

  (defun launch-kde ()
    (interactive)
    (launch-program kde-string))

  (defun launch-kde+emacs ()
    (interactive)
    (launch-program kde-string))

  (defun lock-screen ()
    (interactive)
    (shell-command "~/Github/my-projects/i3lock-fancy/i3lock-fancy & disown"))

  (setq enable-recursive-minibuffers t)
  (defun counsel-shell-command ()
    "Forward to `shell-command'."
    (interactive)
    (ivy-read "Shell Command: "
              shell-command-history
              :caller 'counsel-shell-command))

  (defun dmenu-run ()
    (interactive)
    (shell-command "dmenu" nil "dmenu_run -b"))

  (defun call-startup-programs ()
    (dolist (program exwm-startup-programs)
      (if (listp program)
        (launch-program (car program) (cadr program))
        (launch-program program))))

  (defun get-hard-drive-space ()
    (shell-command-to-string "df -h -P -l / | tail -n 1 | tr -s ' ' | cut -d ' ' -f 4"))

  (defun update-hard-drive-space-string ()
    (setq hard-drive-space
          (let ((space-left (get-hard-drive-space)))
            (propertize (concat " "
                                (substring space-left
                                           0
                                           (1- (length space-left))))
                        'face 'sml/time))))

  (defun display-hard-drive-space-mode ()
    (if (not (member 'hard-drive-space
                     global-mode-string))
        (add-to-list 'global-mode-string
                     'hard-drive-space
                     t)))

Simulation keys

  (setq exwm-input-simulation-keys
   '(
      ;; movement
      ([?\C-b] . left)
      ([?\M-b] . C-left)
      ([?\C-f] . right)
      ([?\M-f] . C-right)
      ([?\C-p] . up)
      ([?\C-n] . down)
      ([?\C-a] . home)
      ([?\C-e] . end)
      ([?\M-v] . prior)
      ([?\C-v] . next)
      ([?\C-d] . delete)
      ([?\M-d] . backspace)
      ([?\C-k] . (S-end delete))
      ;; cut/paste.
      ([?\C-w] . ?\C-x)
      ([?\M-w] . ?\C-c)
      ([?\C-y] . ?\C-v)
      ;; search
      ([?\C-s] . ?\C-f)
      ([?\C-.] . ?\C-w)
      ([?\C-/] . ?\C-z)
      ([?\M-s] . ?\C-s)
  ))

Startup

Emacs server, startup programs, wallpaper

  (add-hook 'exwm-init-hook 'server-start)

  ; Reminder: Hooks execute in order. Make sure megasync launches after systemtray is enabled
  (add-hook 'exwm-init-hook 'call-startup-programs)

  (require 'exwm-screens)
  (add-hook 'exwm-init-hook 'my/setup-screens)

  (define-minor-mode exwm-presentation-mode
    "Make both screen outputs display the same thing"
    nil nil nil
    (cond (exwm-presentation-mode
           (cl-destructuring-bind (primary . secondary) (my/get-screens)
             (shell-command
              (format "xrandr --output %s --mode 1920x1080 --same-as %s"
               (car secondary)
               primary))
             (setq exwm-randr-workspace-monitor-plist nil)
             (exwm-randr-refresh)))
          (t
           (my/setup-screens))))

System tray, display time, display battery, display hard-drive-space

  (require 'exwm-systemtray)
  (exwm-systemtray-enable)
  (setq display-time-day-and-date t)

  (defvar my/exclude-buffer-modes '(helm-major-mode messages-buffer-mode special-mode))

  (defun my-buffer-predicate (buf)
    (with-current-buffer buf
      (if (memq major-mode my/exclude-buffer-modes)
          nil
        (exwm-layout--other-buffer-predicate buf))))

  (add-hook 'exwm-init-hook
            (lambda ()
              (interactive) 
              (modify-all-frames-parameters
       '((buffer-predicate . my-buffer-predicate)))))

  ;; Display hard drive space
  (add-hook 'display-time-hook 'update-hard-drive-space-string)

  (display-time-mode)
  (display-battery-mode)
  (display-hard-drive-space-mode)

Shutdown

  (add-hook 'exwm-exit-hook 'org-save-all-org-buffers)
  ;;(add-hook 'exwm-exit-hook 'save-org-agenda-files)
  (eval-after-load "term"
    '(progn 
       (define-key term-raw-map (kbd "C-c C-y") 'term-paste)
       (define-key term-raw-map (kbd "M-x") 'helm-M-x)))

Xephyr launches in tiling-mode

  (setq exwm-manage-configurations `(((equal exwm-class-name "Xephyr")
                                      floating nil 
                                      char-mode t
                                      fullscreen t)
                                     ((equal exwm-class-name "plasmashell")
                                      floating t)))

Wallpaper

  (setq wallpaper-path "/home/benson/.emacs.d/res/digital_space_universe_4k_8k-wide.jpg")

Volume

  (use-package volume)
  (define-key *root-map* (kbd "v") 'volume)

exwm-edit

  (use-package exwm-edit)

Floating windows don't need that many faces ^_^

  (defun my/frame-dont-copy-faces (frame &optional parameters)
    "Initialize the frame-local faces of FRAME.
  Calculate the face definitions using the face specs, custom theme
  settings, X resources, and `face-new-frame-defaults'.
  Finally, apply any relevant face attributes found amongst the
  frame parameters in PARAMETERS."
    ;; The `reverse' is so that `default' goes first.
    (dolist (face (remove-if-not (lambda (x)
                                   (let ((name (symbol-name x)))
                                     (string-match-p "^doom-.*"
                                                     name)))
                                 (nreverse (face-list))))
      (condition-case ()
          (progn
            ;; Initialize faces from face spec and custom theme.
            (face-spec-recalc face frame)
            ;; Apply attributes specified by face-new-frame-defaults
            (internal-merge-in-global-face face frame))
        ;; Don't let invalid specs prevent frame creation.
        (error nil)))

    ;; Apply attributes specified by frame parameters.
    (let ((face-params '((foreground-color default :foreground)
                         (background-color default :background)
                         (font default :font)
                         (border-color border :background)
                         (cursor-color cursor :background)
                         (scroll-bar-foreground scroll-bar :foreground)
                         (scroll-bar-background scroll-bar :background)
                         (mouse-color mouse :background))))
      (dolist (param face-params)
        (let* ((param-name (nth 0 param))
               (value (cdr (assq param-name parameters))))
          (if value
              (set-face-attribute (nth 1 param) frame
                                  (nth 2 param) value))))))

  (defun my/exwm-floating--advise-make-frame (orig id)
    (advice-add 'face-set-after-frame-default
                :override
                'my/frame-dont-copy-faces)
    (funcall orig id)
    (advice-remove 'face-set-after-frame-default
                   'my/frame-dont-copy-faces))

  (advice-add #'exwm-floating--set-floating
              :around
              #'my/exwm-floating--advise-make-frame)

  (exwm-global-set-key (kbd "s-b") #'wg-undo-wconfig-change)