【发布时间】:2022-06-11 11:14:44
【问题描述】:
我注意到当我的鼠标离开对话框区域时,键盘输入停止工作。
这是有害的,因为我希望这个小应用程序能够抓取键盘,这样我就可以通过键盘处理它而无需移动鼠标。
我试过了:
windowSetKeepAbove, windowSetSkipPagerHint, windowSetSkipTaskbarHint,
和windowPresentWithTime。我仍然无法专注于窗口。这些似乎都不起作用。
还尝试了Seat.grab 函数,它给了我GDK_GRAB_NOT_VIEWABLE。但是我在主窗口上调用showAll 后运行它。为什么看不到?
我现在很困惑。任何帮助将不胜感激。
编辑:它是用haskell 的gi-gtk 绑定编写的,但我认为该语言不相关——它几乎是与gtk 库本身的1-1 绑定。 (例如windowSetTypeHint对应Gtk.Window.set_type_hint)
这是一个接近最小的可重现示例。 (我猜windowSetPosition 之类的东西可能会被剔除,但应该不会影响太大。onWidgetKeyPressEvent 是挂钩按键事件)
{-# LANGUAGE GHC2021 #-}
{-# LANGUAGE LambdaCase #-}
module Main where
import Control.Monad
import Data.Foldable
import Data.Text qualified as T
import GI.Gdk qualified as Gdk
import GI.Gio.Objects qualified as Gio
import GI.Gtk qualified as Gtk
import System.Exit
main :: IO ()
main = do
-- Does not care crashing here
Just app <- Gtk.applicationNew (Just $ T.pack "test.program") []
Gio.onApplicationActivate app (activating app)
status <- Gio.applicationRun app Nothing
when (status /= 0) $ exitWith (ExitFailure $ fromIntegral status)
where
activating :: Gtk.Application -> IO ()
activating app = do
window <- Gtk.applicationWindowNew app >>= Gtk.toWindow
Gtk.windowSetTitle window (T.pack "Test Program")
Gtk.windowSetDefaultSize window 560 140
Gtk.windowSetTypeHint window Gdk.WindowTypeHintDialog
Gtk.windowSetPosition window Gtk.WindowPositionCenterAlways
Gtk.windowSetKeepAbove window True
Gtk.windowSetSkipPagerHint window True
Gtk.windowSetSkipTaskbarHint window True
Gtk.onWidgetKeyPressEvent window $
Gdk.getEventKeyKeyval >=> \case
Gdk.KEY_Escape -> True <$ Gtk.windowClose window
_ -> pure False
Gtk.widgetShowAll window
screen <- Gtk.windowGetScreen window
gdkWins <- Gdk.screenGetToplevelWindows screen
seat <- Gdk.screenGetDisplay screen >>= Gdk.displayGetDefaultSeat
event <- Gtk.getCurrentEvent
putStrLn "Finding window"
filterM (fmap (Gdk.WindowStateAbove `elem`) . Gdk.windowGetState) gdkWins
>>= traverse_
( \win -> do
putStrLn "Window found"
Gdk.windowShow win
stat <- Gdk.seatGrab seat win [Gdk.SeatCapabilitiesAll] True (Nothing @Gdk.Cursor) event Nothing
print stat
)
pure ()
我知道,可怕的 hack,但我不知道其他获取 Gdk.Window 的方法。搜遍了gtk library,找不到将Gdk.Window从Gtk.Window中取出的方法。
但事实证明,这个 hack 已经找到了 gdk 窗口。
与例如运行cabal run 打印:
Finding window
Window found
GrabStatusNotViewable
所以我得到了:GDK_GRAB_NOT_VIEWABLE。
事实证明,后来当例如触发焦点事件,抓取正常工作。但我想早点抓住鼠标/键盘。
【问题讨论】:
-
您能给我们提供一个minimal reproducible example吗?
-
@SylvesterKruin 是的,完成。抱歉,我不知道如何用 C++ 构建 gtk,所以语言与我遇到问题的项目相同。语言应该无关紧要。我想要可靠的方法来抓取指针/键盘,但我不知道哪种方法是要走的路。