1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
-- Use GtkSocket and GtkPlug for cross-process embedded.
-- Just startup program, press 'm' to create tab with new button.
-- Click button for hang to simulate plug hanging process,
-- but socket process still running, can switch to other tab.
module Main where
import System.Process
import System.Environment
import System.Directory
import System.FilePath ((</>))
import Control.Monad
import Control.Monad.Trans
import Control.Concurrent
import Data.Text (unpack)
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Gdk.DrawWindow
import Graphics.UI.Gtk.Gdk.EventM
-- | Main.
main :: IO ()
main = do
-- Get program arguments.
args <- getArgs
case args of
-- Entry plug main when have two arguments.
[id] -> plugMain (toNativeWindowId $ read id :: NativeWindowId) -- get GtkSocket id
-- Othersise entry socket main when no arguments.
_ -> socketMain
-- | GtkSocekt main.
socketMain :: IO ()
socketMain = do
initGUI
-- Create top-level window.
window <- windowNew
windowSetPosition window WinPosCenter
windowSetDefaultSize window 600 400
set window [windowTitle := "Press `m` to new tab, press `q` exit."]
on window objectDestroy mainQuit
-- Create notebook to contain GtkSocekt.
notebook <- notebookNew
window `containerAdd` notebook
-- Handle key press.
window `on` keyPressEvent $ tryEvent $ do
keyName <- eventKeyName
liftIO $
case unpack keyName of
"m" -> do
-- Create new GtkSocket.
socket <- socketNew
widgetShow socket -- must show before add GtkSocekt to container
notebookAppendPage notebook socket "Tab" -- add to GtkSocekt notebook
id <- socketGetId socket -- get GtkSocket id
-- Fork process to add GtkPlug into GtkSocekt.
path <- liftM2 (</>) getCurrentDirectory getProgName -- get program full path
runCommand $ path ++ " " ++ (show $ fromNativeWindowId id) -- don't use `forkProcess`
return ()
"q" -> mainQuit -- quit
widgetShowAll window
mainGUI
-- | GtkPlug main.
plugMain :: NativeWindowId -> IO ()
plugMain id = do
initGUI
plug <- plugNew $ Just id
on plug objectDestroy $ mainQuit
button <- buttonNewWithLabel "Click me to hang."
plug `containerAdd` button
-- Simulate a plugin hanging to see if it blocks the outer process.
on button buttonActivated $ threadDelay 5000000
widgetShowAll plug
mainGUI
|