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

Reply via email to