Hi Axel, Axel Simon <axel.si...@in.tum.de> writes:
> Hi Andy, > > On Jul 4, 2010, at 16:20, Andy Stewart wrote: >>> >>> 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. >> > > No, you cannot omit any field of the event structure. You have to store > everything, every field, > with every pointer (to a string or other structure) that exists. Even though > a field might be > deprecated, it could still be used in a widget, esp in earlier versions of > Gtk. Please make sure > you store every field of the event structure. I see. I suppose i can omit field if this field is deprecated. > >>> 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 > > Well, you can't use pokeSerializedEvent since you need a function that also > allocates bytes for the > string (and other structures that the event points to). Something like: > > deserializeEvent value drawWindow fun = do > let execFun = case sEventType value of > #{const GDK_KEY_PRESS} -> withKeyEvent > #{const GDK_KEY_RELEASE} -> withKeyEvent > #{const GDK_BUTTON_PRESS} -> withButtonEvent > #{const GDK_2BUTTON_PRESS} -> withButtonEvent > #{const GDK_3BUTTON_PRESS} -> withButtonEvent > #{const GDK_BUTTON_RELEASE} -> withButtonEvent > execFun drawWindow value $ runReaderT fun > > withKeyEvent :: DrawWindow -> SerializedEvent -> (Ptr Event -> IO a) - >> IO a > withKeyEvent win SerializedEventKeyValue > {sEventType = typ_ > ,sEventSent = sent_ > ,sEventTime = time_ > ,sEventState = state_ > ,sEventKeyval = keyval_ > ,sEventLength = length_ > ,sEventString = string_ > ,sEventKeycode = keycode_ > ,sEventGroup = group_ > } act = do > withCString string_ $ \str -> do > allocaBytes #{size GtkKeyEvent} $ \ptr -> do > #{poke GdkEventKey, type} ptr ((fromIntegral typ_) ::#gtk2hs_type > GdkEventType) > case (fromMaybe (DrawWindow nullForeignPtr) window_) of > win_ -> withForeignPtr (unDrawWindow win_) $ \winPtr -> > #{poke GdkEventKey, window} ptr winPtr > #{poke GdkEventKey, send_event} ptr ((fromBool sent_) > ::#gtk2hs_type gint8) > #{poke GdkEventKey, time} ptr ((fromIntegral time_) > ::#gtk2hs_type guint32) > #{poke GdkEventKey, state} ptr ((fromIntegral state_) > ::#gtk2hs_type guint) > #{poke GdkEventKey, keyval} ptr (keyval_ > ::#gtk2hs_type guint) > #{poke GdkEventKey, length} ptr ((fromIntegral length_) > ::#gtk2hs_type gint) > #{poke GdkEventKey, string} ptr str > #{poke GdkEventKey, hardware_keycode} ptr (keycode_ > ::#gtk2hs_type guint16) > #{poke GdkEventKey, group} ptr (group_ > ::#gtk2hs_type guint8) > act ptr Thanks, has fix in darcs repo. > >> >> ------------------------------> new version start >> <------------------------------ >> data SerializedEvent = >> SerializedEvent >> {sEventValue :: SerializedEventValue >> ,sEventTime :: Word32 >> ,sEventWindow :: Maybe DrawWindow} >> > > This data type is superfluous! Indeed, i have remove it. >> >> BTW, do you want merge SerializedEvent.hsc into gtk2hs repo? >> Or i release it as individual package? >> > > I'm happy to have it in Gtk2Hs. > > I'm concerned that you're not transmitting all the data that there is in an > event: > > See: > > http://library.gnome.org/devel/gdk/stable/gdk-Event-Structures.html#GdkEventKey > > typedef struct { GdkEventType type; GdkWindow *window; gint8 send_event; > guint32 time; guint state; > guint keyval; gint length; gchar *string; guint16 hardware_keycode; guint8 > group; guint > is_modifier : 1; } GdkEventKey; > > So there is the is_modifier field for which you need to write a C function to > access it (neither > hsc2hs nor c2hs can handle bit fields). Of course you can ignore it, but it > could lead to > unexpected bugs. At least you need to ensure that you know how to set a > certain field. You cannot > leave it randomly set! Infact, i don't know how to write C function to access this bitfield, then i omit this field. Axel, can you help me write this C function? Or have similar gtk2hs code that i can study? > Also: > typedef struct { GdkEventType type; GdkWindow *window; gint8 send_event; > guint32 time; gdouble x; > gdouble y; gdouble *axes; guint state; guint button; GdkDevice *device; > gdouble x_root, y_root; } > GdkEventButton; > > This structure contains a pointer to a GdkDevice. You could compare that if > it's the mouse (say) and > then only send it if it is the mouse. Then you need to re-insert the > GdkDevice pointer to the > standard mouse at the client side. Hmm, looks field "axes" and "device" is correlative. I need research those two fields deeply. Cheers, -- Andy > The accessor functions in EventM only give provide the most useful fields in > the event > structure. This is exactly because it is impossible to marshall all the > fields to Haskell and then > marshall them all back in case you want to re-use the whole event structure. > (Well, it also has to > do with memory management.) > > Cheers, > Axel > > >> 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