Xmonad切换全屏模式 / xmobar

19

考虑到我对Haskell的知识非常有限(事实上是零),修改xmonad.hs可能会很具有挑战性。

我正在寻找如何修改我的配置文件以允许“真正”的全屏,例如在观看视频时使用VLC。

我的当前xmonad.hs:

    import XMonad
    import XMonad.Hooks.DynamicLog
    import XMonad.Hooks.ManageDocks
    import XMonad.Util.Run(spawnPipe)
    import XMonad.Util.EZConfig(additionalKeys)
    import Graphics.X11.ExtraTypes.XF86
    import System.IO

main = do
    xmproc <- spawnPipe "xmobar /home/user/.xmobarrc"
    xmonad $ defaultConfig
        { terminal = "urxvt",
          manageHook = manageDocks <+> manageHook defaultConfig
        , layoutHook = avoidStruts  $  layoutHook defaultConfig
        , logHook = dynamicLogWithPP xmobarPP
                        { ppOutput = hPutStrLn xmproc
                        , ppTitle = xmobarColor "green" "" . shorten 50
                        }
        } `additionalKeys`
                [ ((0 , xF86XK_AudioLowerVolume), spawn "amixer set Master on && amixer set Headphone on && amixer set Master 2-"),
                  ((0 , xF86XK_AudioRaiseVolume), spawn "amixer set Master on && amixer set Headphone on && amixer set Master 2+"),
                  ((0 , xF86XK_AudioMute), spawn "amixer set Master toggle && amixer set Headphone toggle")
                ]

目前我的xmobar在看视频时也是可见的,而且我观看视频时窗口上有一个红色边框。

我该如何修改配置以实现例如使用Mod-b在全屏模式和正常模式之间切换?


你是在xmonad中以单窗口模式显示VLC,还是使用全屏模式?因为当我在我的媒体播放器中全屏时,它们都覆盖了xmobar并没有边框。 - kqr
@kqr 我指的是双击视频框时出现的全屏类型。如果你所说的单窗口模式是指 Xmonad 的“full”模式,那么我正在运行该模式。 - toeplitz
如果您将VLC窗口设置为浮动状态(通常是通过按住modkey并单击它来实现),然后在视频框中双击全屏,那么它是否会覆盖整个屏幕?这可能是平铺窗口的行为不同。 - kqr
5个回答

30

虽然我不完全确定,但我认为您的问题是在尝试全屏平铺窗口时出现的。您配置文件中的那一行是:

While I'm not at all sure about this, I think that your problem arises when you try to fullscreen a tiled window. The line in your config that says


manageHook = manageDocks <+> ...

这告诉xmonad,你不想让平铺窗口重叠xmobar。因此,即使是平铺的全屏窗口,xmonad也会尝试遵守此规则。解决方案有三个部分:

  1. 你可以在全屏之前将窗口浮动。通常可以通过按住mod键并单击窗口一次来完成。当你将窗口浮动后,它可以覆盖所有其他窗口,包括xmobar。因此,如果你尝试全屏窗口,则应该覆盖整个屏幕。

  2. 你可以告诉xmonad默认浮动VLC。这是mplayer的内置行为,但显然不适用于VLC。你可以通过更改配置来实现这一点:

  3. manageHook = manageDocks <+> (className =? "Vlc" --> doFloat) <+> manageHook defaultConfig
    

    “管理钩子”是决定窗口应该如何显示的东西。 <+> 这个东西结合了管理钩子的选项。其中一部分说:

    (className =? "Vlc" --> doFloat)
    

    这意味着“如果窗口是VLC窗口,则默认浮动。”

  4. 第三种非常可行的选择是下载xmonad-contrib包,其中包含XMonad.Hooks.ManageHelpers模块。该模块包含许多聪明的帮助函数,用于自定义xmonad如何处理您的窗口。例如,您可以添加一个规则,如下所示:

    (isFullscreen --> doFullFloat)
    

    这意味着“如果窗口正在尝试全屏,自动将其浮动并使其覆盖整个屏幕”-这正是您想要的效果。您可以像添加类名一样将此内容添加到您的管理钩子中:

    manageHook = manageDocks <+> (isFullscreen --> doFullFloat) <+> manageHook defaultConfig
    

    接着,无论你是否将VLC浮动,它在全屏时应该都会正常工作!


小提示:当您的管理挂钩选项变得很多并且厌倦了使用<+>组合它们时,您可以选择将其写为:

manageHook = composeAll [
    manageDocks,
    isFullscreen --> doFullFloat,
    className =? "Vlc" --> doFloat,
    manageHook defaultConfig
  ]

这个 composeAll 函数会自动使用 <+> 操作符将列表中的每个项组合起来。

如果您对某些配置不确定其含义,请询问。我相信很多人愿意将Haskell代码翻译成人类语言。我知道没有真正了解它如何工作就只能随意复制和粘贴配置是多么令人沮丧。(最近我开始学习xmonad配置,这非常美妙。)


编辑:关于全屏窗口的窗口边框。有一个名为XMonad.Layout.NoBorders的模块提供了一个很棒的函数smartBorders,它修改了您的布局挂钩,使其在看起来为全屏的窗口上不绘制边框。您可以通过更改配置中的行以使用此函数来更改您的布局挂钩:

layoutHook = smartBorders . avoidStruts $ layoutHook defaultConfig

. 这个东西将几个功能合并成一个,这种情况下它将 smartBordersavoidStruts 结合起来,让你同时获得两者的好处。然后它会将默认的布局挂钩传递给它们两个,以创建修改后的更好的布局挂钩。

不幸的是,由于我没有使用边框运行 XMonad,所以无法测试其效果。


谢谢。我正在使用选项3。当我进入全屏模式时,它可以遮盖xmobar。但是,在全屏模式下,我仍然可以看到红色的“活动窗口”边框。而且,当我切换回来时,我无法再看到xmobar了。是否还需要更多操作才能去除“红边框”? - toeplitz
@toeplitz 我已经编辑了我的答案,包括关于那方面的信息。 - kqr

2
尝试在您的.xmobarrc中设置lowerOnStart = True,已经有了avoidStruts,并且有一个键盘快捷键来切换struts,例如:
((mod4Mask .|. shiftMask, xK_f), sendMessage ToggleStruts)

对我来说,这似乎是最简单的解决方案。注意:在第一次重新加载配置后,它不会立即生效。只有在工作区创建新窗口后才能生效。 - Anton Harald
是的,这并不会让 xmobar 消失,而是使其他窗口显示在它的上方。没有其他窗口 -> xmobar 没有可以隐藏的东西。 - Gauthier

1
你不需要将窗口浮动起来才能实现全屏功能。
使用全屏布局修饰符,你可以拥有良好的全屏能力,例如允许切换到其他窗口(但仍显示xmobar)。
我在Layout.Fullscreen之上编写了一个小型布局修饰符,它使用SetStruts(来自Hooks.ManageDocks)在窗口全屏时隐藏/显示栏:
{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses, FlexibleInstances, TypeSynonymInstances #-}
import XMonad
import qualified XMonad.Layout.Fullscreen as FS
import XMonad.Hooks.ManageDocks (SetStruts(..))
import XMonad.Layout.LayoutModifier (LayoutModifier(..), ModifiedLayout(..))
import Data.List (delete, nub)

fullscreenToggleStruts = ModifiedLayout $ FullscreenToggleStruts []
data FullscreenToggleStruts a = FullscreenToggleStruts [a]
     deriving (Read, Show)
instance LayoutModifier FullscreenToggleStruts Window where
    handleMess ff@(FullscreenToggleStruts fulls) m = case fromMessage m of
        Just (FS.AddFullscreen win) -> setStruts $ nub $ win:fulls
        Just (FS.RemoveFullscreen win) -> setStruts $ delete win fulls
        Just FS.FullscreenChanged -> return $ Just ff
        _ -> return Nothing
        where setStruts f = do
                let m = if null f
                        then SetStruts [minBound .. maxBound] []
                        else SetStruts [] [minBound .. maxBound]
                sendMessage m
                return $ Just $ FullscreenToggleStruts f

例如,可以像这样使用它:

layoutHook = fullscreenToggleStruts $ FS.fullscreenFocus $ avoidStruts $ layoutHook'

它甚至可以很好地与多个显示器一起使用!

参见 我的Github 获取我的xmonad+xmobar配置。


1
这是我的配置文件内容(稍微重新格式化以更像你的):
main = do
    config <- statusBar "xmobar" myPP toggleXMobarKey myConfig
    xmonad config

myPP = xmobarPP { -- your PP customizations...
                  ppOutput = hPutStrLn xmproc
                , ppTitle = xmobarColor "green" "" . shorten 50
                }

toggleXMobarKey XConfig { XMonad.modMask = modMask } = (modMask, xK_b)

myConfig = defaultConfig { -- put your config here...
                           -- not including your logHook
                         }

啊,当然,我没有考虑就从你的配置文件中复制了它。只需删除那一行 :) - Tarmil
我不明白这里发生了什么。myPPtoggleXMobarKey是传递给statusBar的参数吗?xmobar如何知道在mod+b上要做什么?-> 答案在这里 - Gauthier
这似乎也可以使 xmobar 保持可见,但在后台运行。如果您有非不透明的窗口或间隙,则状态栏仍然会有些可见。 - Gauthier

0

我想我是从某个默认配置中找到的。 我的程序会监视全屏窗口,然后使用管理钩子将其设置为全屏。

myManageHook = composeAll
    [ className =? "Firefox"        --> doShift (head myWorkspaces)
    , className =? "banshee"        --> doShift (last myWorkspaces)
    , resource  =? "desktop_window" --> doIgnore
    , isFullscreen                  --> doFullFloat ] -- this one

然后它只是将其添加到钩子列表中。

allHooks = [manageDocks, myManageHook, manageHook defaultConfig, manageSpawn]

最后,将所有的钩子组合在一起。
defaults xmproc = defaultConfig
   { -- Simple Stuff
     terminal           = myTerminal
   , focusFollowsMouse  = myFocusFollowsMouse
   , borderWidth        = myBorderWidth
   , modMask            = myModMask
     -- numlockMask        = myNumlockMask,
   , workspaces         = myWorkspaces
   , normalBorderColor  = myNormalBorderColor
   , focusedBorderColor = myFocusedBorderColor

     -- key bindings
   , keys               = myKeys
   , mouseBindings      = myMouseBindings
     -- hooks, layouts
   , layoutHook         = myLayout
   , manageHook         = foldr1 (<+>) allHooks -- Right here
   , logHook            = myLogHook xmproc
   , startupHook        = myStartupHook
   }

这不是最简单的实现方式,但我只是从我的配置文件中复制和粘贴了它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接