deech / fltkhs

Haskell bindings to FLTK GUI toolkit.
MIT License
190 stars 24 forks source link

Crash in FL.eventKey on special key #148

Closed ericu closed 5 years ago

ericu commented 5 years ago

I have a handler that deals with keyboard events; it calls FL.eventKey. If I press my laptop's Fn button [in this case to adjust the brightness], it crashes my app. I don't see what in cToKeyType calls down to Prelude.chr, but it looks like it's probably in toEnum somewhere. Ideally we'd find this key in allSpecialKeys, I believe, but it seems way out of range. That table has all 16-bit values.

This is on a Lenovo ThinkPad P1 running Ubuntu 18.04.

*** Exception (reporting due to +RTS -xc): (THUNK_1_0), stack trace: Graphics.UI.FLTK.LowLevel.Utils.cToKeyType, called from Graphics.UI.FLTK.LowLevel.FL.eventKey..res', called from Graphics.UI.FLTK.LowLevel.FL.eventKey.\, called from Graphics.UI.FLTK.LowLevel.FL.eventKey, called from BcdWindows.handleKeyDown, called from BcdWindows.onWindowEvent, called from BcdWindows.createWindow.onWindowEvent', called from Graphics.UI.FLTK.LowLevel.Base.Widget.toEventHandlerPrim.\, called from Graphics.UI.FLTK.LowLevel.Base.Widget.toEventHandlerPrim, called from Graphics.UI.FLTK.LowLevel.Utils.orNullFunPtr, called from Graphics.UI.FLTK.LowLevel.Base.Widget.fillCustomWidgetFunctionStruct, called from Graphics.UI.FLTK.LowLevel.Base.Window.windowMaker, called from Graphics.UI.FLTK.LowLevel.Base.DoubleWindow.doubleWindowCustom, called from BcdWindows.createWindow, called from BcdWindows.startGui.\, called from BcdWindows.startGui, called from BcdGraphicsTest.ui, called from BcdGraphicsTest.runLeanMain, called from Main.main server: Prelude.chr: bad argument: 269025067

Here's what I see for allSpecialKeys:

(Button,65256), (Kb_Backspace,65288), (Kb_Clear,65291), (Kb_Tab,65289), (Kb_IsoKey,65292), (Kb_Enter,65293), (Kb_Pause,65299), (Kb_Escape,65307), (Kb_Kana,65326), (Kb_Eisu,65327), (Kb_Yen,65328), (Kb_JisUnderscore,65329), (Kb_Home,65360), (Kb_Left,65361), (Kb_Up,65362), (Kb_Right,65363), (Kb_Down,65364), (Kb_PageUp,65365), (Kb_PageDown,65366), (Kb_End,65367), (Kb_Print,65377), (Kb_Insert,65379), (Kb_Menu,65383), (Kb_Help,65384), (Kb_Kp,65408), (Kb_KpEnter,65421), (Kb_F,65469), (Kb_Flast,65504), (Kb_ShiftL,65505), (Kb_ShiftR,65506), (Kb_ControlL,65507), (Kb_ControlR,65508), (Kb_CapsLock,65509), (Kb_MetaL,65511), (Kb_MetaR,65512), (Kb_AltL,65513), (Kb_AltR,65514), (Kb_Delete,65535), (Kb_VolumeDown,61201), (Kb_VolumeMute,61202), (Kb_VolumeUp,61203), (Kb_MediaPlay,61204), (Kb_MediaStop,61205), (Kb_MediaPrev,61206), (Kb_MediaNext,61207), (Kb_HomePage,61208), (Kb_Mail,61209), (Kb_Search,61211), (Kb_Back,61222), (Kb_Forward,61223), (Kb_Stop,61224), (Kb_Refresh,61225), (Kb_Sleep,61231), (Kb_Favorites,61232)])

deech commented 5 years ago

Does any Fn + any key crash your app or is it just the brightness? For instance if you try to control your volume does that map to Kb_VolumeUp?

ericu commented 5 years ago

It crashes as I push Fn; I don't actually need to combine it with anything.

deech commented 5 years ago

Sorry, it's been a while but life and all that. In any case I can't seem to replicate the crash, I do see that it doesn't understand Fn+{Brightness,Volume}{Up,Down} but a minimal app stays up:

windowHandler :: Ref Window -> FL.Event -> IO (Either UnknownEvent ())
windowHandler w e =
  case e of
    _ -> do
      print "printing event key"
      k <- FL.eventKey
      print k
      handleWindowBase (safeCast w) e

ui :: IO ()
ui = do
 window <- windowCustom
            (Size (Width 115) (Height 100))
            Nothing
            Nothing
            Nothing
            (defaultCustomWidgetFuncs { handleCustom = Just windowHandler })
            defaultCustomWindowFuncs
...
ericu commented 5 years ago

I'll bet my laptop keyboard just produces a different weird keycode than yours, or mine produces an event for that key whereas yours waits for composition. It still crashes instantly on Fn, but handles any other key just fine.

Looking at the source for chr, it won't accept a value that high, so ideally we wouldn't call it for such values. How about if cToKeyType checked before calling toEnum for an out-of-range value? Then we could map it to a new Kb_Unrecognized or something. I see that FLTK uses a flag FL_F and then adds the number to support F1, F2, etc. We could map this key to just F [essentially F1] and that would make some sense. But putting in a general way to handle "that's a key I don't know about and you don't need to handle" would probably be better for the next one that comes along. I'd be happy to make you a patch.

ericu commented 5 years ago

It looks like some other systems have run into similar problems with that key on Lenovo keyboards, e.g. https://discourse.libsdl.org/t/key-not-recognised-by-sdl/24181

Apparently the keysym is XF86WakeUp.

https://superuser.com/questions/859862/tmux-and-xf86-keys-the-fn-key-xf86wakeup

They confirm that most computers' BIOSes just don't send anything for that key, but Lenovo behaves differently. Still seems like we should just ignore out-of-range keys for now, or remap them to a special catchall value.

deech commented 5 years ago

Interesting ... in that case a catch-all called Kb_Unrecognized is definitely the right way to go. Mind submitting a patch? Thanks for chasing this down.

ericu commented 5 years ago

https://github.com/deech/fltkhs/pull/153

deech commented 5 years ago

Merged, thanks!