13

I'm using a few key mappings in my xmonad.hs configuration file:

...
    , modMask = mod4Mask     -- Rebind Mod to the Windows key
...
 [ ((controlMask, xK_Print), spawn "sleep 0.2; scrot -s")
 , ((0, xK_Print), spawn "scrot")
 , ((controlMask, xK_f), spawn "firefox")
 ]

The third mapping runs firefox when pressing ctrl+f. I'd like to do something more complex:

if (firefox is running):
  focus and maximize firefox window:
else:
  run firefox

And I'd like to change ctrl+f to win+f. How can I do that?

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
xralf
  • 16,149
  • 29
  • 101
  • 149

1 Answers1

8

Looking at XMonad's contrib packages, you'll find XMonad.Actions.WindowGo, which exports the following function:

runOrRaiseMaster :: String -> Query Bool -> X ()

which takes a string argument of the program to run, e.g. "firefox"; and a boolean query that is used to find out if it is already running, via X11 properties, e.g. (className =? "Firefox") (see top of the XMonad.Actions.WindowGo page for variants).

So, all you need is to bind runOrRaiseMaster "firefox" (className =? "Firefox") to the key you want, as explained in XMonad.Doc.Extending, via

((modMask, xK_f ), runOrRaiseMaster "firefox" (className =? "Firefox"))

as part of the key bindings Data.Map of your configuration (details differ with your way of settings this up, i.e, the whole of your xmonad.hs, see Adding Keybindings).

Note that there is no real sense in maximizing a window in XMonad. When you set things up as explained, you'll have Mod4+f act as follows:

  • if there's a window with a classname matching "Firefox", it will be focused and set to master, i.e., depending on your recent layout, will be the big window
  • if no window matches, Firefox will be spawned and set to master.

Maximizing can be emulated by choosing the Full layout after calling runOrRaiseMaster, as is described here:

("M-<F1>", sendMessage $ JumpToLayout "Full")

(note that this example also demonstrates XMonad.Util.EZConfig allowing easier keybinding definitions)

Combining these two things is possible, too. Both are of type X (), i.e., they are in the X Monad. Using >>, which is of type (check with :t (>>) in ghci)

(>>) :: Monad m => m a -> m b -> m b

we have (runOrRaiseMaster "firefox" (className =? "Firefox")) >> (sendMessage $ JumpToLayout "Full") as a combination of two X () types of type X (), too, and it can thus be bound to a key.

EDIT Missing ) in the code line with >>

Edit2 modm -> modMask.

Edit3 This xmonad.hs hopefully works.

(Why not learn you a Haskell for great good?)

sr_
  • 15,224
  • 49
  • 55
  • Thank you for working answer and other information and Haskell tutorial. I like Haskell syntax and functional paradigm. The only thing that doesn't work is the part `>> (sendMessage $ JumptoLayout "Full")` there is some error with constructor. Maybe it's something easy, that I will solve after learning Haskell. – xralf Nov 24 '11 at 13:08
  • I forgot : Yet the `modm` doesn't work, I'm still using `controlMask`. – xralf Nov 24 '11 at 13:10
  • @xralf, (1) there was a missing bracket - does it work now? (2) I'd need your whole `xmonad.hs` to fix this; better just [have a look around here, the config archive](http://haskell.org/haskellwiki/Xmonad/Config_archive) and see how others do it or use the mentioned `EZConfig`. – sr_ Nov 24 '11 at 14:17
  • The bracket did not helped. [Here](http://pastebin.com/xqfkh8bk) is the xmonad.hs file I'm using. – xralf Nov 24 '11 at 16:13
  • (1) The brackets are still wrong, the action of type `X ()` to bind to the key should be `(runOrRaiseMaster ...) >> (sendMessage ...)`, resulting in `,((...,...), (runOrR...) >> (send...) )` (a `(` before `run...`) – sr_ Nov 24 '11 at 16:44
  • (2) Either try `modMask` instead of `controlMask` (as it is set to `mod4Mask` in your config) or use [`XMonad.Util.EZConfig`s `additionalKeysP` with prettier keyspecs](http://hackage.haskell.org/packages/archive/xmonad-contrib/0.10/doc/html/XMonad-Util-EZConfig.html#v%3AmkKeymap) like `M+f` instead of `(modMask, xK_f)`. (Don't forget to import this function instead, then.) – sr_ Nov 24 '11 at 18:59
  • Could you please edit my paste and click "create new version of this paste" and post a link? I tried a few version of bracketing but none of them works. The `modMask` doesn't work (it was the key I tried before controlMask, that's quite strange), I will try `EZConfig` – xralf Nov 24 '11 at 19:48