Communication with the Sway window manager



Sway Emacs

https://melpa.org/packages/sway-badge.svg http://stable.melpa.org/packages/sway-badge.svg

This package provides a partial interface for integrating Sway with Emacs. It is meant for those Emacs users who prefer to let their window manager deal with window management, and is designed to play well with Shackle.

Its only directly usable feature right now is the sway-shackle-display-buffer-frame, which either creates a new frame with a given buffer or focus that buffer in the frame it’s already displayed on. A reasonable default config with Shackle could look like:

(setq shackle-default-rule '(:frame t)
      shackle-display-buffer-frame-function 'sway-shackle-display-buffer-frame)

(sway-undertaker-mode) ;; If you want to use :dedicate, read below.
(sway-x-focus-through-sway-mode) ;; Temporary workaround for Sway bug 6216

Extension to Shackle

sway.el introduces a new Shackle rule, :dedicate t, managed by sway-undertaker-mode. With :dedicate, when a new frame is created for a buffer, it is sway-dedicated to this buffer. If this buffer gets buried, the frame gets closed immediately. For convenience, using this frame in any other way than acting on that buffer (switching buffers, splitting windows) will permanently deactivate the undertaker and make it behave like a normal frame.

This package requires an Emacs with (preferably native) JSON support. Your Emacs is built with native JSON iff C-h f reports that the function json-parse-buffer is implemented in C.

The socket problem

Emacs has an issue keeping track of environment variables of client frames. To maintain access to the Sway socket, we need some tricks, that are automagically managed by `sway-socket-tracker-mode`.

What about i3?

I don’t use i3, but it would be trivial to implement i3-msg along sway-msg, and the rest should work immediately. Feel free :) (Notice that with i3 you won’t need sway-socket-tracker-mode, frames have a display parameter).

Exemple Shackle configuration

(setq shackle-rules
      `(("*Help*" :align t :select t)
        ;; ** Magit **
        (magit-status-mode :same t)
          ,(lambda (buffer)
             (with-current-buffer buffer
                (eq major-mode 'magit-diff-mode)
         :select nil :frame t :dedicate t)
          ,(lambda (buffer)
             (with-current-buffer buffer
               (bound-and-true-p magit-display-buffer-noselect))))
         :select nil :frame nil :dedicate t)
        (magit-log-mode :same t)
        (magit-submodule-list-mode :same t)
        (magit-revision-mode :same t)
        (magit-process-mode :frame nil)
        ("COMMIT_EDITMSG" :popup t :select t)
        ("^magit.*$'" :regexp t :frame nil)
        (" *transient*" :frame nil :popup t :select nil) ; Magit helper popups
        ;; ** Sunrise commander **
        (sunrise-mode :custom (lambda (&rest _)))
        ;; ** Proced **
        ("*Proced*" :same t)
        (" *Marked Processes*" :frame nil :popup t :select t)
        ;; ** Byte-compiler
        ("*Compile-Log*" :frame nil :popup t :select t)
        ;; ** Local variables warning **
        ("*Local Variables*" :same t :frame nil :popup t :select t)
        ;; ** Misc **
        ("*Org PDF LaTeX Output*" :select nil)
        ("*Org Preview LaTeX Output*" :select nil)
        (" *undo-tree*" :frame nil)
        ("*Register Preview*" :frame nil :noselect t)
        (flycheck-error-list-mode :select t)
        ((compilation-mode) :noselect t)
        ((inferior-scheme-mode "*shell*" "*eshell*") :popup t))

      shackle-default-rule '(:frame t)
      shackle-default-size 0.4
      shackle-inhibit-window-quit-on-same-windows t
      shackle-display-buffer-frame-function 'sway-shackle-display-buffer-frame)