Hi all,

In file `demo/embedded/Embedded.hs` 
(or 
-- Use GtkSocket and GtkPlug for cross-process embedded.
-- Just startup program, press 'Alt-m' to new editor, press `Alt-n` to new terminal.
-- And those plug widget (editor, terminal) running in child-process, 
-- so program won't crash when child-process throw un-catch exception.

module Main where

import System.Posix.Process
import System.Environment
import System.Directory
import System.FilePath ((</>))
import Control.Monad
import Control.Monad.Trans

import Graphics.UI.Gtk
import Graphics.UI.Gtk.General.Structs
import Graphics.UI.Gtk.Vte.Vte
import Graphics.UI.Gtk.Gdk.EventM

data PlugType = PlugEditor
              | PlugTerminal
              deriving (Eq, Ord, Show, Read)

-- | Main.
main :: IO ()
main = do
  -- Init main.
  initGUI

  -- Get program arguments.
  args <- getArgs

  case length args of
    -- Entry socket main when no arguments.
    0 -> socketMain 

    -- Entry plug main when have two arguments.
    2 -> do
      let pType = read (head args) :: PlugType -- get Plug type
          id    = toNativeWindowId $ read (last args) :: NativeWindowId -- get GtkSocket id

      plugMain id pType
    -- Otherwise just output error and exit.
    _ -> putStrLn "Wrong program arguments."
  
-- | GtkSocekt main.
socketMain :: IO ()  
socketMain = do
  -- Output message.
  pid <- getProcessID
  putStrLn $ "Running in socket process : " ++ show pid

  -- Create top-level window.
  window <- windowNew
  windowFullscreen window
  window `onDestroy` mainQuit

  -- Create notebook to contain GtkSocekt.
  notebook <- notebookNew
  window `containerAdd` notebook

  -- Handle key press.
  window `on` keyPressEvent $ tryEvent $ do
    keyModifier <- eventModifier
    keyName     <- eventKeyName
    liftIO $ when (keyModifier == [Alt]) $ 
      case keyName of
        "m" -> forkPlugProcess notebook PlugEditor "Editor"     -- create editor GtkPlug
        "n" -> forkPlugProcess notebook PlugTerminal "Terminal" -- create terminal GtkPlug
  -- forkPlugProcess notebook PlugEditor "Editor"     -- create editor GtkPlug
  -- forkPlugProcess notebook PlugTerminal "Terminal" -- create terminal GtkPlug

  widgetShowAll window

  mainGUI

-- | GtkPlug main.
plugMain :: NativeWindowId -> PlugType -> IO ()
plugMain id PlugEditor   = plugWrap id =<< createEditor
plugMain id PlugTerminal = plugWrap id =<< createTerminal

-- | Fork plug process.
forkPlugProcess :: Notebook -> PlugType -> String -> IO ()
forkPlugProcess notebook plugType tabName = do
  -- Create new GtkSocket.
  socket <- socketNew
  widgetShow socket                          -- must show before add GtkSocekt to container
  notebookAppendPage notebook socket tabName -- add to GtkSocekt notebook
  id <- socketGetId socket                    -- get GtkSocket id
  putStrLn "this"

  -- Fork process to add GtkPlug into GtkSocekt. 
  path <- liftM2 (</>) getCurrentDirectory getProgName -- get program full path
  forkProcess (executeFile path False [show plugType, show $ fromNativeWindowId id] Nothing)
  return ()

-- | Plug wrap function.
plugWrap :: WidgetClass widget => NativeWindowId -> widget -> IO ()
plugWrap id widget = do
  -- Output message.
  pid <- getProcessID
  putStrLn $ "Running in plug process : " ++ show pid

  -- Create GtkPlug with GtkSocekt id.
  plug <- plugNew $ Just id
  plug `onDestroy` mainQuit
  
  -- Add widget to GtkPlug.
  scrolledWindow <- scrolledWindowNew Nothing Nothing
  scrolledWindow `containerAdd` widget
  plug `containerAdd` scrolledWindow

  widgetShowAll plug  

  mainGUI

-- Create editor widget.
createEditor :: IO TextView
createEditor = textViewNew
  
-- Create terminal widget.
createTerminal :: IO Terminal  
createTerminal = do
  terminal <- terminalNew
  terminalForkCommand terminal Nothing Nothing Nothing Nothing False False False
  return terminal
 )
have below code snippets in function `socketMain`:

------------------------------> code start <------------------------------
  -- Handle key press.
  window `on` keyPressEvent $ tryEvent $ do
    keyModifier <- eventModifier
    keyName     <- eventKeyName
    liftIO $ when (keyModifier == [Alt]) $ 
      case keyName of
        "m" -> forkPlugProcess notebook PlugEditor "Editor"     -- create 
editor GtkPlug
        "n" -> forkPlugProcess notebook PlugTerminal "Terminal" -- create 
terminal GtkPlug
------------------------------> code end   <------------------------------

That's mean, when you press key `Alt-m` or `Alt-n` will fork child
process to build GtkPlug widget.

But when i running program and press `Alt-m` will crash Socket process
with below error:

------------------------------> error start <------------------------------
Running in socket process : 2047
The program 'Embedded' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadValue (integer parameter out of range for operation)'.
(Details: serial 423 error_code 2 request_code 53 minor_code 0)
(Note to programmers: normally, X errors are reported asynchronously;
      that is, you will receive the error a while after causing it.
      To debug your program, run it with the --sync command line
      option to change this behavior. You can then get a meaningful
      backtrace from your debugger if you break on the gdk_x_error() function.)
a...@ubuntu:~/Projects/Haskell/embbeded$ Running in plug process : 2049
------------------------------> error end   <------------------------------

And strange is above error is not occur always, most times works fine.

If i just instead above code snippets with:

------------------------------> new code start <------------------------------
 forkPlugProcess notebook PlugEditor "Editor"     -- create editor GtkPlug
 forkPlugProcess notebook PlugTerminal "Terminal" -- create terminal GtkPlug
------------------------------> new code end   <------------------------------

Then program works fine.

So i guess Socekt process and Plug process still share *same* resource when
user press key, then make Socket crash.

Any idea?

Thanks,

  -- Andy

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Gtk2hs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel

Reply via email to