Hi Axel,
Axel Simon <[email protected]> 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 <[email protected]> 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
>> [email protected]
>> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtk2hs-devel