Hi Axel, Axel Simon <axel.si...@in.tum.de> writes:
> H Andy, > > a few comment: > > - you make your SerializedEvent an instance of Storable. That could work, but > you really have to > ensure that the size of the C structure you allocated is big enough. At the > moment, you have > > instance Storable SerializedEvent where > sizeOf _ = #{const sizeof (GdkEventKey)} > This should be > sizeOf _ = maximum [#{const sizeof (GdkEventKey)}, #{const sizeof > (GdkEventButton)}] > i.e. the maximum of any event you event want to marshal. I create Storable instance when i just have GdkEventKey. And i think i need drop Storable instance, it's less help with SerializedEvent. > > The next problem I see is with pointers in the event structure. Data > structures that the event > structure reference must be serialized as well (which is not too hard and > which you've > done). However, when you deserialize these you need to re-create > these structures. > At the moment > you have: > > pokeSerializedEventKey ptr (SerializedEvent > (SerializedEventKeyValue > { > [..] > ,sEventString = string_ > }) window_) = do > str <- newCString string_ > [..] > #{poke GdkEventKey, string} ptr str > Here, you leak the space of str. To fix this, you need to revamp the > whole code. Yes, it's a bug. I should ignore "string" field since it's has deprecated and should never be used. > Instead of using > with event $ \eventPtr -> runReaderT fun (castPtr eventPtr) > you need to write your own function that allocates space not only for the > event structure but also > for the referenced structures, e.g. the string. All of these structures must > be freed > afterwards. Thus, instead of 'with' you need to write your own function > using 'alloca'. > > So I wonder if making you SerializedEvent an instance of Storable is really > helpful as the 'sizeOf' > and the 'with' function that uses the 'poke' method need to be spacial. Yes, you're right! instance Storable is less help, i should use allocaBytes. How about this? ------------------------------> new version start <------------------------------ deserializeEvent :: SerializedEventValue -> DrawWindow -> (EventM t a) -> IO a deserializeEvent value drawWindow fun = do -- We need use *client* value replace field of event. let event = SerializedEvent value currentTime (Just drawWindow) allocaBytes (sizeOfSerializedEvent event) $ \eventPtr -> do pokeSerializedEvent eventPtr event runReaderT fun eventPtr sizeOfSerializedEvent event = do let eType = fromIntegral $ sEventType $ sEventValue event (case eType of #{const GDK_KEY_PRESS} -> #{const sizeof (GdkEventKey)} #{const GDK_KEY_RELEASE} -> #{const sizeof (GdkEventKey)} #{const GDK_BUTTON_PRESS} -> #{const sizeof (GdkEventButton)} #{const GDK_2BUTTON_PRESS} -> #{const sizeof (GdkEventButton)} #{const GDK_3BUTTON_PRESS} -> #{const sizeof (GdkEventButton)} #{const GDK_BUTTON_RELEASE} -> #{const sizeof (GdkEventButton)} ty -> error ("sizeOfSerializedEvent: haven't support event type " ++ show ty)) ------------------------------> new version end <------------------------------ allocaBytes will allocated enough space for different event type. > > Also, since you're not using the time field, why have it in SerializedEvent? Yes, it's wrong. Now i use below code fix this problem. ------------------------------> new version start <------------------------------ data SerializedEvent = SerializedEvent {sEventValue :: SerializedEventValue ,sEventTime :: Word32 ,sEventWindow :: Maybe DrawWindow} data SerializedEventValue = SerializedEventKeyValue {sEventType :: Int ,sEventSent :: Bool ,sEventState :: Int ,sEventKeyval :: KeyVal ,sEventLength :: Int ,sEventKeycode :: Word16 ,sEventGroup :: Word8} | SerializedEventButtonValue {sEventType :: Int ,sEventSent :: Bool ,sEventX :: Double ,sEventY :: Double ,sEventState :: Int ,sEventButton :: Int ,sEventXRoot :: Double ,sEventYRoot :: Double} deriving (Show, Read, Eq, Ord) ------------------------------> new version end <------------------------------ Thank you for correcting my mistake! You can find new version at https://patch-tag.com/r/AndyStewart/gtk-serialized-event/snapshot/current/content/pretty/Graphics/UI/Gtk/Gdk/SerializedEvent.hsc Please let me know if you find any problem in my new code. BTW, do you want merge SerializedEvent.hsc into gtk2hs repo? Or i release it as individual package? Cheers, -- Andy > > Cheers, > Axel > > On Jul 3, 2010, at 20:06, Andy Stewart wrote: > >> Hi Axel, >> >> Axel Simon <axel.si...@in.tum.de> writes: >> >>> On 30.06.2010, at 17:34, Andy Stewart wrote: >>>>>> >>>>>> So my question is how to binding gtk_main_do_event ? >>>>>> Looks I should use Graphics.UI.Gtk.Gdk.Events.Event and not EventM. >>>>>> >>>>> >>>>> Event is deprecated and will be removed soon. The problem with the C >>>>> Event structure is that it can contains pointers and varying fields. >>>>> Event did not mangage to translate all of them, also because new >>>>> event >>>>> are being added to Gtk+ occasionally. If you want to convert a C >>>>> Event >>>>> structure completely to Haskell, send it over the network and then >>>>> reemit the event inside a different application, I suggest that you >>>>> start with the Event module and create an opaque but serializable >>>>> data >>>>> type. This data type should contain some events of interest (keys, >>>>> mouse) but not all events. You would probably need to re-insert the >>>>> time stamp of the event when you reemit it in the other application. >>>>> >>>>> If you implement this, then the extraction of an event should be a >>>>> function >>>>> >>>>> serializeEvent :: EventM t SerializedEvent >>>>> >>>>> that runs in the EventM monad. It should throw an exception if it is >>>>> applied to an event that it can't handle. >>>>> >>>>> Then at the client side, we can implement gtk_main_do_event as >>>>> >>>>> mainDoEvent :: EventM t () >>>>> >>>>> and have >>>>> >>>>> deserializeEvent :: SerializedEvent -> (EventM t a) -> IO a >>>>> >>>>> which executes any EventM function with the serialized event. >>>>> >>>>> Let me know if you need further help. The functions in Event.hs may >>>>> help you to get started with marshalling the events, but you should >>>>> use the EventM interface as described above. >>>> For make problem simpler, let us just think GdkEventKey. >>>> >>>> I have below SerializedEventKey for serialized the value of >>>> GdkEventKey >>>> on *Server* side. >>>> >>>> data SerializedEventKey = >>>> -- sEventType :: Int -- >>>> get EventType when deserialize >>> >>> No, you need to get the event type from the event itself. You don't >>> know what the event type is at the deserialisation point. >>> >>>> -- ,sEventWindow :: DrawWindow -- >>>> get DrawWindow when deserialize >>>> -- ,sEventTime :: TimeStamp -- >>>> get TimeStamp when deserialize >>>> >>>> SerializedEventKey {sEventSent :: Bool >>>> ,sEventState :: [Modifier] >>>> ,sEventKeyval :: KeyVal >>>> ,sEventLength :: Int >>>> ,sEventString :: String >>>> ,sEventKeycode :: Word16 >>>> ,sEventGroup :: Word8 >>>> ,sEventIsModifier :: Bool} >>>> >>>> I use below function to pick-up SerializeEventKey value from EventM >>>> monad at *Server* side: >>>> >>>> serializedEventKey :: EventM EKey SerializedEventKey >>>> serializedEventKey = do >>>> sent <- eventSent >>>> state <- eventModifier >>>> keyval <- eventKeyVal >>>> string <- eventKeyName >>>> keycode <- eventHardwareKeycode >>>> group <- eventKeyboardGroup >>>> liftIO $ return $ >>>> SerializedEventKey sent >>>> state >>>> keyval >>>> (length string) >>>> string >>>> keycode >>>> group >>>> False >>>> >>> >>> Ok. I was suggesting a function that can deal with several, different >>> events. You could copy and paste code from the deprecated Event module. >>> >>>> Now we can send SerializedEventKey value to *client* side through >>>> DBus-system. >>>> >>>> When *client* receive the value of SerializedEventKey, >>>> We can use >>>> >>>> "deserializeEvent :: SerializedEventKey -> IO EventKey" >>>> >>>> add three new values: >>>> >>>> sEventType : GDK_KEY_RELEASE or GDK_KEY_PRESS >>>> sEventWindow : The DrawWindow of *client* that event focus >>>> sEventTime : The TimeStamp when *client* process re-emit >>>> key event >>>> >>>> to re-build EventKey. >>>> >>>> Because gtk_main_do_event need GdkEvent, so we transfer EventKey to >>>> is okay. >>>> >>> >>> What is EventKey? >>> >>> What EventM is doing is to wrap a pointer to a C event struct. So your >>> EventKey could be a ForeignPtr to a C event struct and mainDoEvent >>> could take this ForeignPtr and call the main_do_event function with it. >>> >>> Or you could provide a function >>> >>>>> deserializeEvent :: SerializedEvent -> (EventM t a) -> IO a >>> >>> that executes the action with a pointer to a C event struct (and >>> destroys the memory associated with this pointer after the action has >>> finished). The mainDoEvent can send this event by reading this pointer. >>> >>> The advantages: >>> >>> - you can use mainDoEvent not only on deserialized events, but also on >>> local events in any event callback >>> - you can use other functions to query a deserialized event, e.g., you >>> could check if the deserialized event is a left-mouse-button click and >>> only call mainDoEvent on those >>> >>> It's more consistent with the rest of the interface. >> I success! >> >> Code at >> > https://patch-tag.com/r/AndyStewart/gtk-serialized-event/snapshot/current/content/pretty/Graphics/UI/Gtk/Gdk/SerializedEvent.hsc >> >> Can you help me review it? >> >> In EventM, >> >> sEvent <- serializedEvent >> >> will got SerializedEventValue, you can pass SerializedEventValue over the >> network. >> >> When client receive SerializedEventValue from network, client can use >> below code propagate same event at child process: >> >> drawWindow <- widgetGetDrawWindow targetWidget >> postGUIAsync $ deserializeEvent event drawWindow (widgetEvent >> targetWidget) >> return () >> >> Demo at >> > https://patch-tag.com/r/AndyStewart/gtk-serialized-event/snapshot/current/content/pretty/demo/Main.hs >> >> To test demo program, you need install below packages: >> >> dbus-core, dbus-client, webkit >> >> and apply the patch i send. >> >> Here is demo screenshot : >> http://farm5.static.flickr.com/4080/4758242386_5230d3d54d_b.jpg >> >> Since Events.hsc has deprecated, i guess you don't like SerializedEvent >> style. >> I need merge SerializedEvent.hsc into gtk2hs or release it as individual >> package? >> >> Cheers, >> >> -- Andy >> >> >> >> >> >> ------------------------------------------------------------------------------ >> This SF.net email is sponsored by Sprint >> What will you do first with EVO, the first 4G phone? >> Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first >> _______________________________________________ >> Gtk2hs-devel mailing list >> Gtk2hs-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel ------------------------------------------------------------------------------ This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first _______________________________________________ Gtk2hs-devel mailing list Gtk2hs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel