Module: wine Branch: master Commit: 0118e0d0f10fb61abcfeb5100b206b94594d4493 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0118e0d0f10fb61abcfeb5100b...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Mar 11 12:11:35 2008 +0100
winex11: Add support for merging redundant events, and use it for ConfigureNotify and MotionNotify.
---
dlls/winex11.drv/event.c | 100 ++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 83 insertions(+), 17 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index cdd0853..c531410 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -241,39 +241,105 @@ static Bool filter_event( Display *display, XEvent *event, char *arg ) }
+enum event_merge_action +{ + MERGE_DISCARD, /* discard the old event */ + MERGE_HANDLE, /* handle the old event */ + MERGE_KEEP /* keep the old event for future merging */ +}; + +/*********************************************************************** + * merge_events + * + * Try to merge 2 consecutive events. + */ +static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) +{ + if (prev->xany.window != next->xany.window) return MERGE_HANDLE; + switch (prev->type) + { + case ConfigureNotify: + if (prev->xany.window != next->xany.window) break; + switch (next->type) + { + case ConfigureNotify: + TRACE( "discarding duplicate ConfigureNotify for window %lx\n", prev->xany.window ); + return MERGE_DISCARD; + case Expose: + case PropertyNotify: + return MERGE_KEEP; + } + break; + case MotionNotify: + if (next->type == MotionNotify) + { + TRACE( "discarding duplicate MotionNotify for window %lx\n", prev->xany.window ); + return MERGE_DISCARD; + } + break; + } + return MERGE_HANDLE; +} + + +/*********************************************************************** + * call_event_handler + */ +static inline void call_event_handler( Display *display, XEvent *event ) +{ + HWND hwnd; + x11drv_event_handler handler; + + if (!(handler = find_handler( event->type ))) + { + TRACE( "%s for win %lx, ignoring\n", dbgstr_event( event->type ), event->xany.window ); + return; /* no handler, ignore it */ + } + + if (XFindContext( display, event->xany.window, winContext, (char **)&hwnd ) != 0) + hwnd = 0; /* not for a registered window */ + if (!hwnd && event->xany.window == root_window) hwnd = GetDesktopWindow(); + + TRACE( "%s for hwnd/window %p/%lx\n", + dbgstr_event( event->type ), hwnd, event->xany.window ); + wine_tsx11_unlock(); + handler( hwnd, event ); + wine_tsx11_lock(); +} + + /*********************************************************************** * process_events */ static int process_events( Display *display, Bool (*filter)(), ULONG_PTR arg ) { - XEvent event; - HWND hwnd; + XEvent event, prev_event; int count = 0; - x11drv_event_handler handler; + enum event_merge_action action = MERGE_DISCARD;
+ prev_event.type = 0; wine_tsx11_lock(); while (XCheckIfEvent( display, &event, filter, (char *)arg )) { count++; if (XFilterEvent( &event, None )) continue; /* filtered, ignore it */ - - if (!(handler = find_handler( event.type ))) + if (prev_event.type) action = merge_events( &prev_event, &event ); + switch( action ) { - TRACE( "%s for win %lx, ignoring\n", dbgstr_event( event.type ), event.xany.window ); - continue; /* no handler, ignore it */ + case MERGE_DISCARD: /* discard prev, keep new */ + prev_event = event; + break; + case MERGE_HANDLE: /* handle prev, keep new */ + call_event_handler( display, &prev_event ); + prev_event = event; + break; + case MERGE_KEEP: /* handle new, keep prev for future merging */ + call_event_handler( display, &event ); + break; } - - if (XFindContext( display, event.xany.window, winContext, (char **)&hwnd ) != 0) - hwnd = 0; /* not for a registered window */ - if (!hwnd && event.xany.window == root_window) hwnd = GetDesktopWindow(); - - wine_tsx11_unlock(); - TRACE( "%s for hwnd/window %p/%lx\n", - dbgstr_event( event.type ), hwnd, event.xany.window ); - handler( hwnd, &event ); - wine_tsx11_lock(); } XFlush( gdi_display ); + if (prev_event.type) call_event_handler( display, &prev_event ); wine_tsx11_unlock(); if (count) TRACE( "processed %d events\n", count ); return count;