{-# LANGUAGE TemplateHaskell, TypeFamilies #-} module Hbro.K ( KData, K, init, getHooks, resetKeyBindings, ) where -- {{{ import Hbro.Clipboard as Clipboard import Hbro.Config as Config import Hbro.Core import Hbro.Error import Hbro.Gdk.KeyVal import Hbro.Gui as Gui import Hbro.Gui.NotificationBar import Hbro.Gui.PromptBar as Prompt -- import Hbro.IPC as IPC (Command(..)) import Hbro.IPC.Hooks as IPC import Hbro.IPC.Signals as IPC import Hbro.Keys as Keys import Hbro.Keys.Model ((.|)) import Hbro.Keys.Monadic as Keys import Hbro.Hooks as Hooks import Hbro.Signals as Signals import Hbro.Gui.PromptBar.Hooks import Hbro.Prelude import Hbro.WebView.Hooks as WebView import Hbro.WebView.Signals as WebView -- import Control.Lens.Getter import Control.Lens.Lens import Control.Lens.Setter import Control.Lens.TH import Control.Monad.Reader import Data.Map as M hiding(foldl, map) import Graphics.UI.Gtk.Gdk.EventM as Gdk import Graphics.UI.Gtk.Windows.Window import Graphics.UI.Gtk.WebKit.WebView import Network.URI.Monadic import qualified System.Glib.Attributes as G -- }}} data KData = KData { _config :: TVar Config , _gui :: GUI , _hooks :: Hooks.Hooks KE , _signals :: Signals.Signals } type K = ReaderT KData IO type KE = ExceptT Text K makeLensesWith ?? ''KData $ lensRules & lensField .~ (\name -> Just (tailSafe name ++ "L")) instance HasConfig KData where _config = configL instance HasGUI KData where _gui = guiL instance Keys.HasHooks KE KData where _hooks = hooksL.keyHooksL instance HasPromptHooks KE KData where _promptHooks = hooksL.promptHooksL instance WebView.HasHooks KE KData where _hooks = hooksL.webViewHooksL instance HasNotificationBar KData where _notificationbar = guiL.notificationBarL instance HasPromptBar KData where _promptbar = guiL.promptBarL init :: (BaseIO m) => GUI -> Hooks.Hooks KE -> Signals.Signals -> m KData init ui hooks signals = io (KData <$> newTVarIO def <*> pure ui <*> pure hooks <*> pure signals) getHooks :: (MonadReader KData m) => m (Hooks.Hooks KE) getHooks = askL hooksL -- {{{ Default configuration -- instance Default (Signals.DownloadHook KE) where -- def = Signals.DownloadHook . const . const . const $ return () instance Default (Hooks.LinkClickedHook KE) where def = Hooks.LinkClickedHook f where f (LinkClicked uri Gdk.MiddleButton) = spawn "hbro" ["-u", show uri] f (LinkClicked uri _ ) = load uri instance Default (Hooks.LoadRequestedHook KE) where def = Hooks.LoadRequestedHook $ \(LoadRequested uri) -> load uri instance Default (Hooks.NewWindowHook KE) where def = Hooks.NewWindowHook $ \(NewWindow uri) -> spawn "hbro" ["-u", show uri] -- /!\ NetworkRequest's Haskell binding is missing the function "webkit_network_request_get_message", which makes it rather useless... -- | Display content if webview can show the given MIME type, otherwise download it. instance Default (Hooks.ResourceOpenedHook KE) where def = Hooks.ResourceOpenedHook $ \(ResourceOpened _uri mimetype) -> do return Hooks.Load <<| canRender mimetype |>> return Hooks.Download' instance Default (Hooks.TitleChangedHook KE) where def = Hooks.TitleChangedHook (\(TitleChanged title) -> gAsync . (`G.set` [ windowTitle G.:= ("hbro | " ++ title)]) =<< Gui.get mainWindowL) -- | List of default supported requests. instance Default (IPC.Hooks KE) where def = IPC.Hooks . M.fromList . map (first IPC.Command) $ [ -- Get information ("GET_URI", \_arguments -> Right . tshow <$> getCurrentURI), ("GET_TITLE", \_arguments -> Right <$> getPageTitle), ("GET_FAVICON_URI", \_arguments -> Right . tshow <$> getFaviconURI), ("GET_LOAD_PROGRESS", \_arguments -> Right . tshow <$> getLoadProgress), -- Trigger actions ("LOAD_URI", \arguments -> case arguments of uri:_ -> parseURIReference uri >>= load >> (return $ Right "OK") _ -> return . Left $ "Argument needed."), ("STOP_LOADING", \_arguments -> stopLoading >> (return $ Right "OK")), ("RELOAD", \_arguments -> reload >> (return $ Right "OK")), ("RELOAD_BYPASS_CACHE", \_arguments -> reloadBypassCache >> (return $ Right "OK")), ("GO_BACK", \_arguments -> goBack >> (return $ Right "OK")), ("GO_FORWARD", \_arguments -> goForward >> (return $ Right "OK")), ("ZOOM_IN", \_arguments -> zoomIn >> (return $ Right "OK")), ("ZOOM_OUT", \_arguments -> zoomOut >> (return $ Right "OK"))] resetKeyBindings :: (BaseIO m, MonadReader t m, Keys.HasHooks (ExceptT Text K) t) => m () resetKeyBindings = do -- Browse Keys.bind (_Alt .| _Left) $ goBack Keys.bind (_Alt .| _Right) $ goForward Keys.bind (_Control .| _Escape) $ stopLoading Keys.bind _F5 $ reload Keys.bind (_Control .| _r) $ reload Keys.bind (_Control .| _F5) $ reloadBypassCache Keys.bind (_Alt .| _r) $ reloadBypassCache Keys.bind (_Control .| _dead_circumflex) $ scrollH (Absolute 0) Keys.bind (_Control .| _dollar) $ scrollH (Absolute 100) Keys.bind (_Control .| _Home) $ scrollV (Absolute 0) Keys.bind (_Control .| _End) $ scrollV (Absolute 100) Keys.bind (_Alt .| _Home) $ goHome -- Copy/paste Keys.bind (_Control .| _c) $ getCurrentURI >>= Clipboard.write . tshow Keys.bind (_Alt .| _c) $ getPageTitle >>= Clipboard.write Keys.bind (_Control .| _v) $ Clipboard.read >>= parseURIReference >>= load Keys.bind (_Alt .| _v) $ Clipboard.read >>= spawn "hbro" . ("-u":) . (:[]) . unpack -- Display Keys.bind (_Control .| _plus) $ zoomIn Keys.bind (_Control .| _minus) $ zoomOut Keys.bind (_Control .| _b) $ Gui.toggle =<< Gui.get statusBarL Keys.bind (_Alt .| _b) $ Gui.toggle =<< Gui.get notificationBarL Keys.bind (_Control .| _u) $ toggleSourceMode >> reload -- Prompt Keys.bind (_Control .| _o) $ promptURI "Open URI" "" >>= load Keys.bind (_Alt .| _o) $ getCurrentURI >>= \uri -> promptURI "Open URI " (tshow uri) >>= load -- Search Keys.bind _slash $ void $ prompt' "Search " "" $ searchText_ CaseInsensitive Forward Wrap Keys.bind (_Control .| _f) $ prompt "Search " "" >>= searchText_ CaseInsensitive Forward Wrap Keys.bind _question $ void $ prompt' "Search " "" $ searchText_ CaseInsensitive Backward Wrap Keys.bind (_Control .| _n) $ searchText_ CaseInsensitive Forward Wrap =<< Prompt.getEntryValue Keys.bind (_Control .| _p) $ searchText_ CaseInsensitive Backward Wrap =<< Prompt.getEntryValue Keys.bind (_Control .| _h) $ gAsync . webViewUnMarkTextMatches =<< Gui.get webViewL -- Misc -- Keys.bind (_Control .| _i) $ openInspector Keys.bind (_Alt .| _Print) printPage Keys.bind (_Control .| _t) $ spawn "hbro" [] Keys.bind (_Control .| _w) quit -- }}}