Search code examples
haskellxlibxmonad

XMonad, spawn floating window right above focused window


I am trying to spawn a floating window whose screen position would match currently focused, tiled or itself floating, window.

I am assuming the spawn command itself should reside inside keys list (like all other commands) while layout should reside in manageHook. I can distinguish the window precisely by setting unique WM_NAME (urxvt makes that easy), and I can access currently focused window inside keys list; however, I don't know if there's a proper, built-in/non-dirty way of passing this information downwards into the manageHook.

In addition, I am assuming (perhaps wrongly?) that during layout, focused window is going to be the newly spawned window - so I can't access it there inside layout code.

Three ideas I have (descending order of hacky):

  • store layout data into WM_NAME and parse it out down the line
  • store dimensions as an X attribute and read it down in the manage hook
  • store focused window as an MVar, then access it during layout to obtain dimensions

All these seem a bit hacky; is there a better way?


Solution

  • Don't make this part of the spawning command, making it part of your ManageHook. Basic usage is like

    className "my-unique-class" --> doRectFloat blah
    

    where figuring out what to put in blah is probably the most annoying part. You can fetch the window's ID with ask, and the current layout with liftX (gets (layout . workspace . current . windowset)). I can't think of a good way to work out the rectangle of the currently focused window other than to then manually run that layout with doLayout, then search its output for the currently-focused window's ID. The values you need as the other arguments are also lurking in the windowset in various places, as well as the window ID of the currently focused window. So a sketch would look like:

    className "my-unique-class" --> do
        ws <- liftX (gets (current . windowset))
        case stack (workspace ws) of
            Nothing -> -- what do you want to do when there's no windows?
            Just st -> do
                (rects, _) <- liftX $ doLayout (layout $ workspace ws) (screenRect (screenDetail ws)) (stack (workspace ws))
                case lookup (focus st) rects of
                    Nothing -> -- what do you want to do when the layout doesn't display the currently focused window?
                    Just rect -> -- use rect and screenRect (screenDetail ws)