{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-} module Hbro.Core where -- {{{ Imports import Hbro.Gui import Hbro.Socket import Hbro.Util import qualified Config.Dyre as Dyre import Control.Concurrent import Control.Monad.Trans(liftIO) import qualified Data.Map as Map import qualified Data.Set as Set import Graphics.UI.Gtk.Abstract.Container --import Graphics.UI.Gtk.Abstract.IMContext import Graphics.UI.Gtk.Abstract.Widget import Graphics.UI.Gtk.General.General import Graphics.UI.Gtk.Gdk.EventM --import Graphics.UI.Gtk.WebKit.Download --import Graphics.UI.Gtk.WebKit.NetworkRequest import Graphics.UI.Gtk.WebKit.WebView import Graphics.UI.Gtk.WebKit.WebFrame import Graphics.UI.Gtk.WebKit.WebInspector import Graphics.UI.Gtk.WebKit.WebSettings import Network.URL import Prelude import System.Console.CmdArgs --import System.Glib.Attributes import System.Glib.Signals import System.Posix.Process -- }}} -- {{{ Type definitions data Browser = Browser { mOptions :: CliOptions, -- ^ Commandline options mGUI :: GUI -- ^ Graphical widgets } data Configuration = Configuration { mHomePage :: String, -- ^ Startup page mSocketDir :: String, -- ^ Path to socket directory ("/tmp" for example) mUIFile :: String, -- ^ Path to XML file describing UI (used by GtkBuilder) mKeyBindings :: KeyBindingsList, -- ^ List of keybindings mWebSettings :: IO WebSettings, -- ^ Web settings mAtStartUp :: GUI -> IO (), -- ^ Custom startup instructions mError :: Maybe String -- ^ Error } type KeyBindingsList = [(([Modifier], String), (GUI -> IO ()))] -- }}} -- {{{ Commandline options data CliOptions = CliOptions { mURI :: Maybe String } deriving (Data, Typeable, Show, Eq) cliOptions :: CliOptions cliOptions = CliOptions{ mURI = def &= help "URI to open at startup" &= explicit &= name "u" &= name "uri" &= typ "URI" } getOptions :: IO CliOptions getOptions = cmdArgs $ cliOptions     &= verbosityArgs [explicit, name "Verbose", name "v"] []     &= versionArg [ignore]     &= help "A suckless minimal KISSy browser."     &= helpArg [explicit, name "help", name "h"]     &= program "hbro" -- }}} -- {{{ Entry point -- | Entry point of the application. -- | Parse arguments and step down in favour of initBrowser. realMain :: Configuration -> IO () realMain configuration = do options <- getOptions initBrowser configuration options -- }}} -- {{{ Main function -- | Application's main function. -- Create browser and load homepage. initBrowser :: Configuration -> CliOptions -> IO () initBrowser configuration options = do -- Print configuration error, if any case (mError configuration) of Just e -> putStrLn e _ -> return () -- Initialize browser _ <- initGUI gui <- loadGUI (mUIFile configuration) --let browser = Browser options gui -- Initialize IPC socket pid <- getProcessID _ <- forkIO $ createReplySocket ("ipc://" ++ (mSocketDir configuration) ++ "/hbro." ++ show pid) gui -- Load configuration settings <- mWebSettings configuration webViewSetWebSettings (mWebView gui) settings -- Launch custom startup (mAtStartUp configuration) gui -- Load url let url = case (mURI options) of Just x -> x _ -> mHomePage configuration loadURL url gui -- Load key bindings let keyBindings = importKeyBindings (mKeyBindings configuration) -- On new window request --newWindowWebView <- webViewNew _ <- on (mWebView gui) createWebView $ \frame -> do newUri <- webFrameGetUri frame case newUri of Just uri -> webViewLoadUri (mWebView gui) uri --Just uri -> runExternalCommand $ "hbro " ++ uri Nothing -> return () return (mWebView gui) -- return newWindowWebView -- _ <- on newWindowWebView loadCommitted $ \frame -> do -- getUri <- (webViewGetUri newWindowWebView) -- case getUri of -- Just uri -> runExternalCommand $ "hbro \"" ++ uri ++ "\"" -- _ -> return () -- Web inspector inspector <- webViewGetInspector (mWebView gui) _ <- on inspector inspectWebView $ \_ -> do webView <- webViewNew containerAdd (mInspectorWindow gui) webView return webView _ <- on inspector showWindow $ do widgetShowAll (mInspectorWindow gui) return True -- TODO: when does this signal happen ?! --_ <- on inspector finished $ return () -- _ <- on inspector attachWindow $ do -- getWebView <- webInspectorGetWebView inspector -- case getWebView of -- Just webView -> do widgetHide (mInspectorWindow gui) -- containerRemove (mInspectorWindow gui) webView -- widgetSetSizeRequest webView (-1) 250 -- boxPackEnd (mWindowBox gui) webView PackNatural 0 -- widgetShow webView -- return True -- _ -> return False -- _ <- on inspector detachWindow $ do -- getWebView <- webInspectorGetWebView inspector -- _ <- case getWebView of -- Just webView -> do containerRemove (mWindowBox gui) webView -- containerAdd (mInspectorWindow gui) webView -- widgetShowAll (mInspectorWindow gui) -- return True -- _ -> return False widgetShowAll (mInspectorWindow gui) return True -- Key bindings -- imContext <- get (mWebView gui) webViewImContext -- _ <- on (mWebView gui) keyPressEvent $ do -- value <- eventKeyVal -- modifiers <- eventModifier -- let keyString = keyToString value -- -- case keyString of -- Just "" -> do -- liftIO $ imContextFocusIn imContext -- return True -- _ -> return False _ <- after (mWebView gui) keyPressEvent $ do value <- eventKeyVal modifiers <- eventModifier let keyString = keyToString value case keyString of Just string -> do case Map.lookup (Set.fromList modifiers, string) keyBindings of Just callback -> liftIO $ callback gui _ -> liftIO $ putStrLn string _ -> return () return False -- imContextFilterKeypress imContext $ do -- value <- eventKeyVal -- modifiers <- eventModifier -- let keyString = keyToString value -- putStrLn keyString -- -- case keyString of -- -- Just string -> do -- -- case Map.lookup (Set.fromList modifiers, string) keyBindings of -- -- Just callback -> liftIO $ callback gui -- -- _ -> liftIO $ putStrLn string -- -- _ -> return () -- return False -- Connect and show. _ <- onDestroy (mWindow gui) mainQuit widgetShowAll (mWindow gui) widgetHide (mPromptLabel gui) widgetHide (mPrompt gui) mainGUI -- }}} -- | Show web inspector for current webpage. showWebInspector :: GUI -> IO () showWebInspector gui = do inspector <- webViewGetInspector (mWebView gui) webInspectorInspectCoordinates inspector 0 0 -- | Load given URL in the browser. loadURL :: String -> GUI -> IO () loadURL url gui = case importURL url of Just url' -> loadURL' url' gui _ -> return () -- | Backend function for loadURL. loadURL' :: URL -> GUI -> IO () loadURL' url@URL {url_type = Absolute _} gui = webViewLoadUri (mWebView gui) (exportURL url) loadURL' url@URL {url_type = HostRelative} gui = webViewLoadUri (mWebView gui) ("file://" ++ exportURL url) >> putStrLn (show url) loadURL' url@URL {url_type = _} gui = webViewLoadUri (mWebView gui) ("http://" ++ exportURL url) >> print url -- {{{ Dyre showError :: Configuration -> String -> Configuration showError configuration message = configuration { mError = Just message } hbro :: Configuration -> IO () hbro = Dyre.wrapMain Dyre.defaultParams { Dyre.projectName = "hbro", Dyre.showError = showError, Dyre.realMain = realMain, Dyre.ghcOpts = ["-threaded"] } -- }}}