'GTK: How do I grab keyboard input for a dialog/splash window, so that keyinput works out of window region?
I noticed that when my mouse is out of the dialog area, the keyboard input stops working.
This is detrimental since I want this small app to grab keyboard, so that I could handle it through keyboard without having to move my mouse.
I tried:
windowSetKeepAbove, windowSetSkipPagerHint, windowSetSkipTaskbarHint,
and windowPresentWithTime. I still could not focus in the window. None of these seem to work.
Also tried Seat.grab function, it gave me GDK_GRAB_NOT_VIEWABLE. But I am running this after calling showAll on the main window. Why is it not viewable?
I am so confused now. Any help would be appreciated.
EDIT: It is written in gi-gtk binding of haskell, but I don't think the language would be relevant - it is pretty much 1-1 binding to the gtk library itself. (E.g. windowSetTypeHint corresponds toGtk.Window.set_type_hint)
Here is the close-to-minimal reproducible example. (I guess things like windowSetPosition could have culled out, but it should not affect much. onWidgetKeyPressEvent is to hook into key press event)
{-# 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 ()
I know, horrible hack, but I don't know other ways to get Gdk.Window. Searched through the gtk library, could not find the way to take Gdk.Window out of Gtk.Window.
Still, it turns out that this hack have found the gdk window.
Running with e.g. cabal run prints:
Finding window
Window found
GrabStatusNotViewable
So I got: GDK_GRAB_NOT_VIEWABLE somehow.
It turns out that later on when e.g. focus event is fired, grab works normally. But I want to grab the mouse/keyboard earlier.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
