Запуск процесса из dmenu блокирует XMonad

У меня проблема с функцией, которую я взял из XMonad.Util.Dmenu, а именно dmenuXinerama (см. ниже). Кажется, это происходит:

Эти функции блокируют цикл событий xmonad до выхода из dmenu; это означает, что программы не смогут открывать новые окна, и вы не сможете изменить рабочие пространства или фокус ввода, пока вы так или иначе не отреагируете на подсказку.

Что происходит, так это то, что я создаю экземпляр меню, и оно появляется, но как только я запускаю что-то оттуда, все блокируется, и я ничего не могу сделать.

Это функция:

dmenuXinerama :: [String] -> X String
dmenuXinerama opts = do
    curscreen <- (fromIntegral . W.screen . W.current) `fmap` gets windowset :: X Int
    io $ runProcessWithInput "dmenu_run" ["-m", show curscreen] (unlines opts)

... и привязка:

-- Spawn dmenu
, ((modMask, xK_p), void $ dmenuXinerama [])

Я также пробовал это:

dmenuXinerama :: [String] -> X String
dmenuXinerama opts = do
    curscreen <-
      (fromIntegral . W.screen . W.current) `fmap` gets windowset :: X Int
    _ <-
      runProcessWithInput "dmenu_run" ["-m", show curscreen] (unlines opts)
    menuArgs "dmenu_run" ["-m", show curscreen] opts

-- | Like 'menu' but also takes a list of command line arguments.
menuArgs :: MonadIO m => String -> [String] -> [String] -> m String
menuArgs menuCmd args opts = liftM (filter (/='\n')) $
  runProcessWithInput menuCmd args (unlines opts)

Я был бы признателен, если бы кто-нибудь объяснил, что происходит и как я могу преодолеть проблему.


person adder    schedule 14.12.2020    source источник


Ответы (1)


Я думаю, что dmenu_run не завершается (до тех пор, пока программа, с которой вы запускаете его), не подходит для использования с runProcessWithInput. Вместо этого используйте dmenu_path и dmenu, затем spawn результат.

pickExe :: X ()
pickExe = do
    exes <- runProcessWithInput "dmenu_path" [] ""
    exe <- dmenuXinerama (lines exes)
    spawn exe

dmenuXinerama в приведенном выше фрагменте — это тот, который вы можете импортировать из XMonad.Util.Dmenu, а не модифицированный из вопроса. (И spawn от XMonad.Core.)

Если вам нравится интерфейс Monad, вы можете написать его без временных имен, например:

pickExe = spawn =<< dmenuXinerama . lines =<< runProcessWithInput "dmenu_path" [] ""
person Daniel Wagner    schedule 14.12.2020
comment
Спасибо за помощь, однако я вижу, что модуль XMonad.Util.Dmenu использует -xs, а в моем dmenu нет параметров -x и -s, поэтому я определил свою собственную функцию в первую очередь. Вторая причина заключалась в том, что dmenu появлялся не на том экране из-за +1 в коде. Если я уберу это, он появится на правом экране. Когда дело доходит до ваших фрагментов, я пробовал их, и первый фрагмент не работал, мне пришлось обернуть exes в список ([exes]), и после его компиляции dmenu вообще не появлялся. - person adder; 14.12.2020
comment
Что касается вашего второго фрагмента, я тоже получаю сообщение об ошибке: Couldn't match type ‘Char’ with ‘[Char]’ Expected type: String -> X String Actual type: [String] -> X String, это красная волнистая линия под dmenuXinerama в моем редакторе. Я был бы признателен за предложения о том, как заставить функцию, которую я определил, работать правильно, потому что в моем dmenu нет этих опций, и оно появляется не на том экране. версия dmenu dmenu-4.8. - person adder; 14.12.2020
comment
Кажется, я заставил его работать с комбинацией моей функции и вашей вещи. - person adder; 14.12.2020
comment
@adder Как обсуждалось в документации, -xs, используемый dmenuXinerama, требует, чтобы вы применили патч jcreigh для нескольких мониторов к dmenu. (Вы читали документацию, верно?) Извиняюсь за бит String/[String]. Я был немного неряшлив. Правильный способ - dmenuXinerama (lines exes) (или dmenu (lines exes), если вы не хотите использовать dmenuXinerama). Аналогичное исправление для второй версии - spawn =<< dmenuXinerama . lines =<< runProcessWithInput "dmenu_path" [] "". - person Daniel Wagner; 14.12.2020