packages feed

buster-0.99.2: App/Widgets/GtkMouseKeyboard.hs

-- | Gtk mouse keyboard widget.
--
--   For a mouse button press or release, add events named SingleClick or ClickRelease respectively to the bus.
--   For this widget, all events have source ''KeyboardMouseWidget'', and group ''Mouse''
--   Additionally, the data attached to the event follows the form [EString SingleClick|ClickRelease, EDouble x, EDouble y, EStringL [Gtk modifier names]]
--
--   For a keyboard press or release, add events named KeyDown or KeyUp respectively to the bus.
--   All keyboard events have group ''Keyboard'' and source ''WidgetName.KeyboardMouseWidget''
--   Additionally, the data attached to a keyboard event follows the form [EString keyName | EChar keyChar, EStringL [Gtk modifier names]]
module App.Widgets.GtkMouseKeyboard where

import Control.Applicative
import Control.Concurrent
import Data.Maybe
import qualified Graphics.UI.Gtk as Gtk
import qualified Graphics.UI.Gtk.Gdk.Events as Gtk
import App.EventBus

-- Gtk's button click event system is annoying, so we're ignoring it and only bothering with the single clicks.
-- when we receive a click, fire off a thread (once) that waits for 100ms to see how many clicks we get total in that time.  Then fire off that number.
buttonHandler _ _ (Gtk.Button _ Gtk.DoubleClick _ _ _ _ _ _ _) = return True
buttonHandler _ _ (Gtk.Button _ Gtk.TripleClick _ _ _ _ _ _ _) = return True
buttonHandler wname b (Gtk.Button sent click time x y modifiers button _ _) = do
    produce' "Mouse" (wname ++ ".KeyboardMouseWidget") (show click) once [EString . show $ button, EDouble x, EDouble y, EStringL . map show $ modifiers] b
    return True

scrollWheelHandler wname b (Gtk.Scroll _ _ x y direction _ _) = do
    produce' "Mouse" (wname ++ ".KeyboardMouseWidget") (show direction) once [EDouble x, EDouble y] b
    return True

keyboardHandler wname b (Gtk.Key released sent time modifiers withCapsLock withNumLock withScrollLock keyVal keyName keyChar) = do
    produce' "Keyboard" (wname ++ "KeyboardMouseWidget") (if released then "KeyUp" else "KeyDown") once
            [ fromMaybe (EString . show $ keyName) (EChar <$> keyChar)
            , EStringL . map show $ modifiers ] b
    return False

motionHandler wname w b evt = do
    produce' "Mouse" (wname ++ ".KeyboardMouseWidget") "Position" once [EDouble . Gtk.eventX $ evt, EDouble . Gtk.eventY $ evt] b
    dwin <- Gtk.widgetGetDrawWindow w
    Gtk.drawWindowGetPointer dwin
    return False

-- | Bind a keyboard mouse widget to the given Gtk widget. Se module documentation for description of events.
bindMouseKeyboardWidget :: Gtk.Widget -> Widget [EData a]
bindMouseKeyboardWidget w b = do
    ref <- newEmptyMVar
    wname <- Gtk.widgetGetName w
    Gtk.onButtonPress w (buttonHandler wname b)
    Gtk.onButtonRelease w (buttonHandler wname b)
    Gtk.onScroll w (scrollWheelHandler wname b)
    Gtk.onKeyPress w (keyboardHandler wname b)
    Gtk.onKeyRelease w (keyboardHandler wname b)
    Gtk.onMotionNotify w True (motionHandler wname w b)
    return ()