[xmonad] Window manager replacement (--replace flag)

Jan Vornberger Jan.Vornberger at Informatik.Uni-Oldenburg.DE
Sat May 2 19:39:02 EDT 2009


Hi there!

I have looked a little bit into enabling XMonad to replace an existing
window manager when starting. I think it's a useful feature to help a
new user to try out the window manager (e.g. from a running
Gnome-Session with Metacity).

I also found a corresponding 'issue' on the bug tracker
(http://code.google.com/p/xmonad/issues/detail?id=99), which however has
been closed as 'WontFix'.

I have a rough version of the feature ready, which is good enough for my
needs for now. It's not in a shape to go into the repository though, I'm
only posting this here in case someone wants to continue working on it
and for reference.

The current version of the patch is attached. It's also available at my
repository (http://tuvok.home.dyndns.org/xmonad-dev/xmonad/). I had a
look at http://tronche.com/gui/x/icccm/sec-2.html#s-2.8 for reference,
but mostly followed the code of other window managers. Namely XFWM4,
Compiz and Metacity. If someone wants to look into it, here are the
relevant parts:

  apt-get source xfwm4 -> edit screen.c -> search for myScreenSetWMAtom
  apt-get source compiz -> edit display.c -> search for replaceCurrentWm
  apt-get source metacity -> core/screen.c -> search for replace_current_wm

My code does not everything these window managers do for this feature.
The steps that I have skipped out of laziness and/or limited
understanding of X11 programming, are marked with 'SKIPPED' in the code.
Basically my code right now always replaces an existing window manager
and assumes that everything goes fine.

One other thing I noticed: While XMonad can now replace other window
managers, it doesn't allow itself to be replaced in this manner. I
haven't looked into it further, but we would need to play nice and
terminate when we see another WM trying to take over.

Things to do:

  - implement 'SKIPPED' parts
  - add '--replace' flag and only replace when the user specifies this flag
  - allow replacement of XMonad by another WM

As I said, I have paused working on this feature for now. If anyone
wants to have a shot at it, feel free to do so! :-)

Cheers!

Jan
-------------- next part --------------
Sat Apr 18 00:25:09 CEST 2009  Jan Vornberger <jan.vornberger at informatik.uni-oldenburg.de>
  * half-implemented support for replacing an existing window manager

New patches:

[half-implemented support for replacing an existing window manager
Jan Vornberger <jan.vornberger at informatik.uni-oldenburg.de>**20090417222509
 Ignore-this: 17d9f72ef7a5d84b5fa6ac319566602b
] {
hunk ./XMonad/Main.hsc 42
 import XMonad.Operations
 
 import System.IO
+--import System.Exit
 
 ------------------------------------------------------------------------
 -- Locale support
hunk ./XMonad/Main.hsc 70
 
     rootw  <- rootWindow dpy dflt
 
+    -- check for other WM
+    wmSnAtom <- internAtom dpy ("WM_S" ++ (show dflt)) False
+    currentWmSnOwner <- xGetSelectionOwner dpy wmSnAtom
+    when (currentWmSnOwner /= 0) $ do
+        putStrLn $ "Screen " ++ (show dflt) ++ " on display \""
+                    ++ (displayString dpy) ++ "\" already has a window manager."
+        -- exitFailure
+
+        -- prepare to receive destroyNotify for old WM
+        selectInput dpy currentWmSnOwner structureNotifyMask
+
+        -- create off-screen window
+        netWmSnOwner <- allocaSetWindowAttributes $ \attributes -> do
+            set_override_redirect attributes True
+            set_event_mask attributes propertyChangeMask
+            let screen = defaultScreenOfDisplay dpy
+            let visual = defaultVisualOfScreen screen
+            let attrmask = cWOverrideRedirect .|. cWEventMask
+            createWindow dpy rootw (-100) (-100) 1 1 0 copyFromParent copyFromParent visual attrmask attributes
+
+        -- try to acquire wmSnAtom, this should signal the old WM to terminate
+        putStrLn $ "Replacing existing window manager..."
+        xSetSelectionOwner dpy wmSnAtom netWmSnOwner currentTime
+
+        -- SKIPPED: check if we acquired the selection
+        -- SKIPPED: send client message indicating that we are now the WM
+
+        -- wait for old WM to go away
+        putStr $ "Waiting for other window manager to terminate... "
+        fix $ \again -> do
+            evt <- allocaXEvent $ \event -> do
+                windowEvent dpy currentWmSnOwner structureNotifyMask event
+                get_EventType event
+
+            when (evt /= destroyNotify) again
+        putStrLn $ "done"
+
     -- If another WM is running, a BadAccess error will be returned.  The
     -- default error handler will write the exception to stderr and exit with
     -- an error.
}

Context:

[Avoid deadly cycle in man/xmonad.hs
Spencer Janssen <spencerjanssen at gmail.com>**20090319081918
 Ignore-this: adcba110caad465a2cbb4b9dca7cb612
] 
[X.Config.hs, ./man/xmonad.hs: update Event Hook doc
wirtwolff at gmail.com**20090209183837
 Ignore-this: 3792043278932e371e3e2858913a2b17
] 
[Use records to document Tall's arguments
Spencer Janssen <spencerjanssen at gmail.com>**20090221230628
 Ignore-this: 253c09de793715c18a029406795a42fd
] 
[Fix possible head []
Joachim Breitner <mail at joachim-breitner.de>**20090106192026
 This seems to be a rare case, but I just got hit by it.
] 
[ManageHook.doShift: use shiftWin instead of shift
Spencer Janssen <spencerjanssen at gmail.com>**20090219041458
 Ignore-this: 4d7f348d6d394c581ab2809bbc45a2c6
] 
[Express shift in terms of shiftWin
Spencer Janssen <spencerjanssen at gmail.com>**20090217235343
 Ignore-this: 8f213bca20065a39e7c16027f7b398cf
] 
[Use standard -fforce-recomp instead of undocumented -no-recomp
Don Stewart <dons at galois.com>**20090208165518] 
[Support for custom event hooks
Daniel Schoepe <asgaroth_ at gmx.de>**20090203155536
 Ignore-this: f22f1a7ae2d958ba1b3625aa923b7efd
] 
[Make X an instance of Typeable
Daniel Schoepe <asgaroth_ at gmx.de>**20090128215406
 Ignore-this: bb155e62ea4e451460e3b94508dc49d2
] 
[Add uninstallSignalHandlers, use in spawn
Spencer Janssen <spencerjanssen at gmail.com>**20090122002643
 Ignore-this: d91bde6f965341a2619fe2dde83cc099
] 
[Create a new session for forked processes
Spencer Janssen <spencerjanssen at gmail.com>**20090122000423
 Ignore-this: f5d9cf254a0b07ddbf204457b7783880
] 
[TAG 0.8.1
Spencer Janssen <spencerjanssen at gmail.com>**20090118083910] 
[Close stdin in spawned processes
Spencer Janssen <spencerjanssen at gmail.com>**20090117040024
 Ignore-this: 2e372ed6215160adae8da1c44cdede3d
] 
[Document spawnPID
Spencer Janssen <spencerjanssen at gmail.com>**20090117035907
 Ignore-this: 1641bdcf5055b2ec7b9455265f5b1d52
] 
[Asynchronously recompile/restart xmonad on mod-q
Spencer Janssen <spencerjanssen at gmail.com>**20090117035300
 Ignore-this: 753d8746034f818b81df79003ae5ee0d
] 
[Add --restart, a command line flag to cause a running xmonad process to restart
Spencer Janssen <spencerjanssen at gmail.com>**20090117034959
 Ignore-this: 45c8c8aba7cc7391b95c7e3fb01e5bf9
] 
[Bump version to 0.8.1
Spencer Janssen <spencerjanssen at gmail.com>**20090116223621
 Ignore-this: 2e8e9dc7b6ca725542f4afe04253dc57
] 
[Remove doubleFork, handle SIGCHLD
Spencer Janssen <spencerjanssen at gmail.com>**20090116204742
 Ignore-this: f9b1a65b4f0622922f80ad2ab6c5a52f
 This is a rather big change.  Rather than make spawned processes become
 children of init, we handle them in xmonad.  As a side effect of this change,
 we never need to use waitForProcess in any contrib module -- in fact, doing so
 will raise an exception.  The main benefit to handling SIGCHLD is that xmonad
 can now be started with 'exec', and will correctly clean up after inherited
 child processes.
] 
[Main.hs: escape / in Haddocks
gwern0 at gmail.com**20081207020915
 Ignore-this: 2c4525280fbe73c46f3abd8fc13628e9
 This lets haddocks for Main.hs, at least, to build with 2.3.0.
] 
[More flexible userCode function
Daniel Schoepe <asgaroth_ at gmx.de>**20090110221852] 
[Call logHook as the very last action in windows
Spencer Janssen <spencerjanssen at gmail.com>**20081209233700
 Ignore-this: 4396ad891b607780f8e4b3b6bbce87e
] 
[Accept inferior crossing events.  This patch enables fmouse-focus-follows-screen
Spencer Janssen <spencerjanssen at gmail.com>**20081205045130
 Ignore-this: 3ac329fb92839827aed0a4370784cabd
] 
[Tile all windows at once
Spencer Janssen <spencerjanssen at gmail.com>**20081118074447] 
[Factor rational rect scaling into a separate function
Spencer Janssen <spencerjanssen at gmail.com>**20081118072849] 
[Change screen focus by clicking on the root window.
Spencer Janssen <spencerjanssen at gmail.com>**20081106224031
 This is a modification of a patch from Joachim Breitner.
] 
[Fix #192.
Spencer Janssen <spencerjanssen at gmail.com>**20081021220059] 
[select base < 4 for building on ghc 6.10
Adam Vogt <vogt.adam at gmail.com>**20081013214509] 
[add killWindow function
Joachim Breitner <mail at joachim-breitner.de>**20081005001804
 This is required to kill anything that is not focused, without
 having to focus it first.
] 
[add'l documentation
Devin Mullins <me at twifkak.com>**20080927234639] 
[Regression: ungrab buttons on *non* root windows
Spencer Janssen <spencerjanssen at gmail.com>**20081007214351] 
[Partial fix for #40
Spencer Janssen <spencerjanssen at gmail.com>**20081007212053
 Improvements:
  - clicking on the root will change focus to that screen
  - moving the mouse from a window on a screen to an empty screen changes focus
    to that screen
 The only remaining issue is that moving the mouse between two empty screens
 does not change focus.  In order to solve this, we'd have to select motion events
 on the root window, which is potentially expensive.
] 
[Track mouse position via events received
Spencer Janssen <spencerjanssen at gmail.com>**20081007203953] 
[Fix haddock
Spencer Janssen <spencerjanssen at gmail.com>**20081007094641] 
[Move screen locating code into pointScreen
Spencer Janssen <spencerjanssen at gmail.com>**20081007094207] 
[Make pointWithin a top-level binding
Spencer Janssen <spencerjanssen at gmail.com>**20081007090229] 
[sp README, CONFIG, STYLE, TODO
gwern0 at gmail.com**20080913024457] 
[Use the same X11 dependency as xmonad-contrib
Spencer Janssen <spencerjanssen at gmail.com>**20080921061508] 
[Export focusUp' and focusDown' -- work entirely on stacks
Spencer Janssen <spencerjanssen at gmail.com>**20080911214803] 
[add W.shiftMaster, fix float/tile-reordering bug
Devin Mullins <me at twifkak.com>**20080911053909] 
[TAG 0.8
Spencer Janssen <spencerjanssen at gmail.com>**20080905195412] 
Patch bundle hash:
91fd805c1299465b19d8ae2c93f4b66709d68e46


More information about the xmonad mailing list