[xmonad] emacs making itself sticky and copyToAllToggle

Antoine Beaupre anarcat at orangeseeds.org
Fri Apr 14 01:26:11 UTC 2017


Hi,

I've been working on improving the integration between the great
[writeroom-mode][] and Xmonad here, in what is probably the worst case
of procrastination, yak-shaving level. Writeroom is a "distraction-free
writing" mode for emacs. It turns out the "sticky" signal it sends is
not recognized by Xmonad, a known limitation which I will not expand on
here - other people more familiar with Xmonad may fix or talk about this
better than me.

 [writeroom-mode]: https://github.com/joostkremers/writeroom-mode/

But, needing to scratch that particular itch, and with the help of
clever people from the IRC channel, I was able to basically accomplish
what I needed. This involved creating a new function which I think could
be useful in the CopyWindow library:

-- | Toggle between "copyToAll" or "killAllOtherCopies". Copies to all
-- workspaces, or remove from all other workspaces, depending on
-- previous state (checked with "wsContainingCopies").
copyToAllToggle :: X ()
copyToAllToggle = do
    -- check which workspaces have copies
    copies <- wsContainingCopies
    if null copies
      then windows copyToAll -- no workspaces, make sticky
      else killAllOtherCopies -- already other workspaces, unstick

There are probably better ways of implementing this directly in the
CopyWindow code - wsContainingCopies, in particular, is probably
overkill. But it's all I can use directly from my xmonad.hs, so that's
what I did.

The other bit I needed was something to trigger that function from the
outside. I rejected the ServerMode hook because it looked a bit too
complicated and there is a built-in facility within X that works without
this, which, from Emacs' point of view, is the `x-send-client-message`
function. So I made up a new message identifier and wrote a event hook
handler to process it:

-- | handle X client messages that tell Xmonad to make a window appear
-- on all workspaces
--
-- this should really be using _NET_WM_STATE and
-- _NET_WM_STATE_STICKY. but that's more complicated: then we'd need
-- to inspect a window and figure out the current state and act
-- accordingly. I am not good enough with Xmonad to figure out that
-- part yet.
--
-- Instead, just check for the relevant message and check if the
-- focused window is already on all workspaces and toggle based on
-- that.
--
-- this is designed to interoperate with Emacs's writeroom-mode module
-- and called be called from elisp with:
--
-- (x-send-client-message nil 0 nil "XMONAD_COPY_ALL_SELF" 8 '(0))
myClientMessageEventHook :: Event -> X All
myClientMessageEventHook (ClientMessageEvent {ev_message_type = mt, ev_data = dt}) = do
  dpy <- asks display
  -- the client message we're expecting
  copyAllMsg <- io $ internAtom dpy "XMONAD_COPY_ALL_SELF" False
  -- if the event matches the message we expect, toggle sticky state
  when (mt == copyAllMsg && dt /= []) $ do
    copyToAllToggle
  -- we processed the event completely
  return $ All True

All that was left was to hook that into emacs, and I was done! Whoohoo!
Full screen total domination, distraction free work! :)

Attached is the patch to my configuration files that accomplished the
whole thing.

I would love to hear from others what they think of that approach, if
they have improvements or if the above copyToAllToggle function could be
merged in. Ideally, Xmonad would just parse the STICKY client messages
and do the right thing - maybe even directly in CopyWindow - but I have
found this enough Haskell for one day.. :)

Thanks for your attention,

A.

-- 
Instead of worrying about what somebody else is going to do, which is
not under your control, the important thing is, what are you going to
decide about what is under your control?
                         - Richard Stallman
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-hook-writeroom-mode-into-sticky-xmonad-desktops.patch
Type: text/x-diff
Size: 6667 bytes
Desc: not available
URL: <http://mail.haskell.org/pipermail/xmonad/attachments/20170413/ce46d0b8/attachment.patch>


More information about the xmonad mailing list