[Question] How to handle external events "globally"
Closed this issue · 5 comments
My usecase: I want to be able to hit Esc
or Ctrl + Q
and quit the app, closing its window.
What is the best way to go about this?
I saw that when creating custom widgets one can use handleEvent
, but what about handling events globally, on the app level?
I checked few tutorial samples and all handleEvent
functions which are passed to startApp
have a fixed user defined data type.
I can see that startApp
has WidgetEvent e
constraint which is actually a Typeable e
, but Typeable
is something I haven't studied yet, so maybe I don't see something obvious here.
To handle a global keyboard event you can use the keystroke widget, and have it be your top level widget. This widget provides a way of handling events at the Application/Composite level. The To-Do example uses this widget. Since this widget has a single widget as its child, you can just put it before the content you currently have:
buildUI wenv model = widgetTree where
bindings = [ ... ]
widgetTree = keystroke bindings $
-- Your current widgets
One important thing is that keystroke
will only receive events if any of its children can receive focus (textField, checkbox, etc). If you will not have any of those widgets in your UI (maybe you are testing and printing messages to the console), you will want to mark this widget as focusable
.
keystroke bindings childNode
`nodeFocusable` True
Great! Thank you!
I have almost managed to make this work, need a little help if possible.
- I have added an
AppQuit
event toAppEvent
type - I have added
appExitEvent AppQuit
toAppConfig
passed tostartApp
- I have added a
keystroke
widget as you've described above - Now to avoid "partial"
case
inhandleEvent
I need to handleAppQuit
there too, so I've addedAppQuit -> []
branch there
But the thing is that this way it consumes AppQuit
event (I guess) and it does not reach "internal" event handler which would quit the app.
If I remove AppQuit -> []
case branch, then everything works as expected, but compiler nags at me for having a partial case
, so I'd like to make it happier by not having it.
I would appreciate any hints on how to properly fix this.
Maybe I shouldn't use appExitEvent
and instead somehow post the command to quit the app from handleEvent
?
Sorry, I missed this. The appExitEvent configuration gives you the chance to cancel exiting the application when the user closes the window (you can return [Request (ExitApplication False)]
from the handler).
I'm not sure I understand the use case. Handling Esc
and requesting to close the Application should work without issues. I don't think you can handle Ctrl-Q
with keystroke
, since the OS will most likely capture this combination earlier. If you have some sort of action you want to run on exit, you can use appExitEvent
as you mentioned, but it will be a different event than the one you use with keystroke
.
handleEvent wenv node model evt = case evt of
CloseButton -> [ exitApplication ] -- Same as: [ Request (ExitApplication True) ]
OnExit -> [ ... ] -- Maybe call cancelExitApplication
Oh! The thing I have missed was that there's a special exitApplication
request which can be used in an event handler!
I'm so excited to try things that I start asking questions before I read the whole tutorial :) This event is described in Composite
tutorial chapter which is the next in my to-read list.
Thanks!