From 131e0e19837b56ef7887ef3c447e64789b480afb Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 10 Jan 2014 02:26:06 -0500 Subject: [PATCH] ecore-x now supports XPRESENT see http://cgit.freedesktop.org/xorg/proto/presentproto/plain/presentproto.txt --- configure.ac | 24 ++- src/Makefile_Ecore_X.am | 2 + src/lib/ecore_x/Ecore_X.h | 78 +++++++++ src/lib/ecore_x/xcb/ecore_xcb_events.c | 16 ++ src/lib/ecore_x/xcb/ecore_xcb_extensions.c | 3 + src/lib/ecore_x/xcb/ecore_xcb_present.c | 194 +++++++++++++++++++++ src/lib/ecore_x/xcb/ecore_xcb_private.h | 5 + src/lib/ecore_x/xlib/ecore_x.c | 5 + src/lib/ecore_x/xlib/ecore_x_events.c | 22 ++- src/lib/ecore_x/xlib/ecore_x_present.c | 169 ++++++++++++++++++ src/lib/ecore_x/xlib/ecore_x_private.h | 9 + 11 files changed, 514 insertions(+), 13 deletions(-) create mode 100644 src/lib/ecore_x/xcb/ecore_xcb_present.c create mode 100644 src/lib/ecore_x/xlib/ecore_x_present.c diff --git a/configure.ac b/configure.ac index 8f991867f3..62ed2c5682 100644 --- a/configure.ac +++ b/configure.ac @@ -2697,6 +2697,17 @@ AC_ARG_ENABLE([gesture], ], [want_gesture="no"]) +AC_ARG_ENABLE([xpresent], + [AC_HELP_STRING([--enable-xpresent], [enable X11 XPresent extension support])], + [ + if test "x${enableval}" = "xyes" ; then + want_xpresent="yes" + else + want_xpresent="no" + fi + ], + [want_xpresent="no"]) + AC_ARG_ENABLE([xinput2], [AC_HELP_STRING([--disable-xinput2], [disable X11 XInput v2.x support])], [ @@ -2861,6 +2872,11 @@ if test "x${want_x11_xlib}" = "xyes" ; then ECORE_CHECK_X_EXTENSION([Xtest], [XTest.h], [Xtst], [XTestFakeKeyEvent]) ECORE_CHECK_X_EXTENSION([Xss], [scrnsaver.h], [Xss], [XScreenSaverSelectInput]) + if test "${want_xpresent}" = "yes"; then + ECORE_CHECK_X_EXTENSION([Xpresent], [Xpresent.h], [Xpresent], [XPresentQueryExtension]) + fi + EFL_ADD_FEATURE([ECORE_X], [xpresent]) + if test "${want_gesture}" = "yes"; then ECORE_CHECK_X_EXTENSION([Xgesture], [gesture.h], [Xgesture], [XGestureQueryExtension]) fi @@ -2888,7 +2904,7 @@ fi if test "${want_x11_xcb}" = "yes"; then dnl note: added pixman-1 as ecore_xcb_region uses that EFL_DEPEND_PKG([ECORE_X], [ECORE_X_XCB], - [x11-xcb xcb xcb-shm xcb-event xcb-icccm >= 0.3.8 xcb-util >= 0.3.8 xcb-image xcb-keysyms >= 0.3.8 xcb-composite xcb-damage xcb-dpms xcb-randr xcb-render xcb-screensaver xcb-shape xcb-sync xcb-xfixes xcb-xinerama xcb-xprint xcb-xtest xcb-renderutil pixman-1]) + [x11-xcb xcb xcb-shm xcb-event xcb-icccm >= 0.3.8 xcb-util >= 0.3.8 xcb-image xcb-keysyms >= 0.3.8 xcb-composite xcb-present xcb-damage xcb-dpms xcb-randr xcb-render xcb-screensaver xcb-shape xcb-sync xcb-xfixes xcb-xinerama xcb-xprint xcb-xtest xcb-renderutil pixman-1]) dnl TODO: remove these ifdefs from code! AC_DEFINE([ECORE_XCB_COMPOSITE], [1], [Build support for XCB composite]) @@ -2905,6 +2921,12 @@ dnl TODO: remove these ifdefs from code! AC_DEFINE([ECORE_XCB_XTEST], [1], [Build support for XCB xtest]) AC_DEFINE([ECORE_XCB_CURSOR], [1], [Build support for XCB cursor]) + EFL_OPTIONAL_DEPEND_PKG([ECORE_X], [${want_xpresent}], [ECORE_XCB_XPRESENT], + [xcb-present]) + AC_DEFINE_IF([ECORE_XCB_XPRESENT], [test "${want_xpresent}" = "yes"], + [1], [Build support for XCB Present]) + EFL_ADD_FEATURE([ECORE_X], [xpresent]) + EFL_OPTIONAL_DEPEND_PKG([ECORE_X], [${want_gesture}], [ECORE_XCB_GESTURE], [xcb-gesture]) AC_DEFINE_IF([ECORE_XCB_XGESTURE], [test "${want_gesture}" = "yes"], diff --git a/src/Makefile_Ecore_X.am b/src/Makefile_Ecore_X.am index d0c6e85b14..0b6d390e17 100644 --- a/src/Makefile_Ecore_X.am +++ b/src/Makefile_Ecore_X.am @@ -38,6 +38,7 @@ lib/ecore_x/xcb/ecore_xcb_input.c \ lib/ecore_x/xcb/ecore_xcb_gesture.c \ lib/ecore_x/xcb/ecore_xcb_mwm.c \ lib/ecore_x/xcb/ecore_xcb_pixmap.c \ +lib/ecore_x/xcb/ecore_xcb_present.c \ lib/ecore_x/xcb/ecore_xcb_region.c \ lib/ecore_x/xcb/ecore_xcb_selection.c \ lib/ecore_x/xcb/ecore_xcb_textlist.c \ @@ -75,6 +76,7 @@ lib/ecore_x/xlib/ecore_x_window.c \ lib/ecore_x/xlib/ecore_x_window_prop.c \ lib/ecore_x/xlib/ecore_x_window_shape.c \ lib/ecore_x/xlib/ecore_x_pixmap.c \ +lib/ecore_x/xlib/ecore_x_present.c \ lib/ecore_x/xlib/ecore_x_gc.c \ lib/ecore_x/xlib/ecore_x_xinerama.c \ lib/ecore_x/xlib/ecore_x_screensaver.c \ diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h index f7c0e7708b..6dbed60c76 100644 --- a/src/lib/ecore_x/Ecore_X.h +++ b/src/lib/ecore_x/Ecore_X.h @@ -94,6 +94,7 @@ typedef void Ecore_X_Connection; typedef void Ecore_X_Screen; typedef Ecore_X_ID Ecore_X_Sync_Counter; typedef Ecore_X_ID Ecore_X_Sync_Alarm; +typedef Ecore_X_ID Ecore_X_Sync_Fence; /**< @since 1.9 */ typedef void Ecore_X_XRegion; typedef Ecore_X_ID Ecore_X_Randr_Output; @@ -489,12 +490,18 @@ typedef struct _Ecore_X_Event_Startup_Sequence Ecore_X_Event_Startup typedef struct _Ecore_X_Event_Generic Ecore_X_Event_Generic; + +typedef struct Ecore_X_Event_Present_Configure Ecore_X_Event_Present_Configure; /**< @since 1.9 */ +typedef struct Ecore_X_Event_Present_Complete Ecore_X_Event_Present_Complete; /**< @since 1.9 */ +typedef struct Ecore_X_Event_Present_Idle Ecore_X_Event_Present_Idle; /**< @since 1.9 */ + typedef struct _Ecore_X_Randr_Screen_Size Ecore_X_Randr_Screen_Size; typedef struct _Ecore_X_Randr_Screen_Size_MM Ecore_X_Randr_Screen_Size_MM; typedef struct _Ecore_X_Randr_Crtc_Info Ecore_X_Randr_Crtc_Info; /**< @since 1.8 */ typedef struct _Ecore_X_Xdnd_Position Ecore_X_Xdnd_Position; + struct _Ecore_X_Event_Mouse_In { int modifiers; @@ -1053,6 +1060,59 @@ struct _Ecore_X_Event_Generic void *data; }; +typedef enum Ecore_X_Present_Event_Mask +{ + ECORE_X_PRESENT_EVENT_MASK_NO_EVENT = 0, + ECORE_X_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY = 1, + ECORE_X_PRESENT_EVENT_MASK_COMPLETE_NOTIFY = 2, + ECORE_X_PRESENT_EVENT_MASK_IDLE_NOTIFY = 4, +} Ecore_X_Present_Event_Mask; /**< @since 1.9 */ + +typedef struct Ecore_X_Present +{ + Ecore_X_Window win; + unsigned int serial; +} Ecore_X_Present; /**< @since 1.9 */ + +struct Ecore_X_Event_Present_Configure +{ + Ecore_X_Window win; + + int x, y; + unsigned int width, height; + int off_x, off_y; + int pixmap_width, pixmap_height; + long pixmap_flags; +}; /**< @since 1.9 */ + +typedef enum +{ + ECORE_X_PRESENT_COMPLETE_MODE_COPY, + ECORE_X_PRESENT_COMPLETE_MODE_FLIP, + ECORE_X_PRESENT_COMPLETE_MODE_SKIP, +} Ecore_X_Present_Complete_Mode; + +struct Ecore_X_Event_Present_Complete +{ + Ecore_X_Window win; + + unsigned int serial; // value provided when generating request + unsigned long long ust; // system time of presentation + unsigned long long msc; // frame count at time of presentation + Eina_Bool kind : 1; /* 0 for PresentCompleteKindPixmap (PresentPixmap completion), + 1 for PresentCompleteKindNotifyMsc (PresentNotifyMSC completion) */ + Ecore_X_Present_Complete_Mode mode; +}; /**< @since 1.9 */ + +struct Ecore_X_Event_Present_Idle +{ + Ecore_X_Window win; + + unsigned int serial; + Ecore_X_Pixmap pixmap; + Ecore_X_Sync_Fence idle_fence; +}; /**< @since 1.9 */ + EAPI extern int ECORE_X_EVENT_ANY; /**< low level event dependent on backend in use, if Xlib will be XEvent, if XCB will be xcb_generic_event_t. @warning avoid using it. @@ -1118,6 +1178,10 @@ EAPI extern int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY; /** @since 1.7 */ EAPI extern int ECORE_X_EVENT_GENERIC; +EAPI extern int ECORE_X_EVENT_PRESENT_CONFIGURE; /**< @since 1.9 */ +EAPI extern int ECORE_X_EVENT_PRESENT_COMPLETE; /**< @since 1.9 */ +EAPI extern int ECORE_X_EVENT_PRESENT_IDLE; /**< @since 1.9 */ + EAPI extern int ECORE_X_EVENT_XDND_ENTER; EAPI extern int ECORE_X_EVENT_XDND_POSITION; EAPI extern int ECORE_X_EVENT_XDND_STATUS; @@ -2356,6 +2420,20 @@ EAPI void ecore_x_composite_window_events_enable(Ecore_X_Window wi EAPI Ecore_X_Window ecore_x_composite_render_window_enable(Ecore_X_Window root); EAPI void ecore_x_composite_render_window_disable(Ecore_X_Window root); +/* XPresent Extension Support */ +/** @since 1.9 */ +EAPI void ecore_x_present_select_events(Ecore_X_Window win, unsigned int events); +/** @since 1.9 */ +EAPI void ecore_x_present_notify_msc(Ecore_X_Window win, unsigned int serial, unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder); +/** @since 1.9 */ +EAPI void ecore_x_present_pixmap(Ecore_X_Window win, Ecore_X_Pixmap pixmap, unsigned int serial, Ecore_X_Region valid, + Ecore_X_Region update, int x_off, int y_off, Ecore_X_Randr_Crtc target_crtc, + Ecore_X_Sync_Fence wait_fence, Ecore_X_Sync_Fence idle_fence, unsigned int options, + unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder, + Ecore_X_Present *notifies, int num_notifies); +/** @since 1.9 */ +EAPI Eina_Bool ecore_x_present_exists(void); + /* XDamage Extension Support */ typedef Ecore_X_ID Ecore_X_Damage; diff --git a/src/lib/ecore_x/xcb/ecore_xcb_events.c b/src/lib/ecore_x/xcb/ecore_xcb_events.c index 7f76d7a741..adee7ce0ba 100644 --- a/src/lib/ecore_x/xcb/ecore_xcb_events.c +++ b/src/lib/ecore_x/xcb/ecore_xcb_events.c @@ -18,6 +18,9 @@ # ifdef ECORE_XCB_XFIXES # include # endif +# ifdef ECORE_XCB_XPRESENT +# include +# endif # ifdef ECORE_XCB_XGESTURE # include # endif @@ -184,6 +187,10 @@ EAPI int ECORE_X_EVENT_XKB_STATE_NOTIFY = 0; EAPI int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = 0; EAPI int ECORE_X_EVENT_GENERIC = 0; +EAPI int ECORE_X_EVENT_PRESENT_CONFIGURE = 0; +EAPI int ECORE_X_EVENT_PRESENT_COMPLETE = 0; +EAPI int ECORE_X_EVENT_PRESENT_IDLE = 0; + EAPI int ECORE_X_RAW_BUTTON_PRESS = 0; EAPI int ECORE_X_RAW_BUTTON_RELEASE = 0; EAPI int ECORE_X_RAW_MOTION = 0; @@ -253,6 +260,10 @@ _ecore_xcb_events_init(void) ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = ecore_event_type_new(); ECORE_X_EVENT_GENERIC = ecore_event_type_new(); + ECORE_X_EVENT_PRESENT_CONFIGURE = ecore_event_type_new(); + ECORE_X_EVENT_PRESENT_COMPLETE = ecore_event_type_new(); + ECORE_X_EVENT_PRESENT_IDLE = ecore_event_type_new(); + ECORE_X_RAW_BUTTON_PRESS = ecore_event_type_new(); ECORE_X_RAW_BUTTON_RELEASE = ecore_event_type_new(); ECORE_X_RAW_MOTION = ecore_event_type_new(); @@ -2303,6 +2314,11 @@ _ecore_xcb_event_handle_generic_event(xcb_generic_event_t *event) // FIXME: should we generate generic events as WELL as input events? // return; } + else if (ev->pad0 == _ecore_xcb_event_xpresent) + { + _ecore_xcb_event_handle_present_event((xcb_ge_event_t*)event); + return; + } if (!(e = calloc(1, sizeof(Ecore_X_Event_Generic)))) return; diff --git a/src/lib/ecore_x/xcb/ecore_xcb_extensions.c b/src/lib/ecore_x/xcb/ecore_xcb_extensions.c index 40c10ac05b..2e3577bf1c 100644 --- a/src/lib/ecore_x/xcb/ecore_xcb_extensions.c +++ b/src/lib/ecore_x/xcb/ecore_xcb_extensions.c @@ -64,6 +64,8 @@ _ecore_xcb_extensions_init(void) _ecore_xcb_gesture_init(); #endif + _ecore_xcb_present_init(); + /* #ifdef ECORE_XCB_DRI */ /* _ecore_xcb_dri_init(); */ /* #endif */ @@ -135,6 +137,7 @@ _ecore_xcb_extensions_finalize(void) _ecore_xcb_gesture_finalize(); #endif + _ecore_xcb_present_finalize(); /* #ifdef ECORE_XCB_DRI */ /* _ecore_xcb_dri_finalize(); */ /* #endif */ diff --git a/src/lib/ecore_x/xcb/ecore_xcb_present.c b/src/lib/ecore_x/xcb/ecore_xcb_present.c new file mode 100644 index 0000000000..b5b426ba28 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_present.c @@ -0,0 +1,194 @@ +#include "ecore_xcb_private.h" +# ifdef ECORE_XCB_XPRESENT +# include +# endif + +/* local variables */ +static Eina_Bool _xpresent_avail = EINA_FALSE; + +/* external variables */ +int _ecore_xcb_event_xpresent = -1; + +void +_ecore_xcb_xpresent_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XPRESENT + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_present_id); +#endif +} + +void +_ecore_xcb_xpresent_finalize(void) +{ +#ifdef ECORE_XCB_XPRESENT + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XPRESENT + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_present_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_present_query_version_cookie_t cookie; + xcb_present_query_version_reply_t *reply; + + cookie = + xcb_present_query_version_unchecked(_ecore_xcb_conn, + XCB_PRESENT_MAJOR_VERSION, + XCB_PRESENT_MINOR_VERSION); + reply = xcb_present_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + _xpresent_avail = EINA_TRUE; + free(reply); + } + + if (_xpresent_avail) + _ecore_xcb_event_xpresent = ext_reply->first_event; + } +#endif +} + +#ifdef ECORE_XCB_XPRESENT +#define SET(X) e->X = ev->X + +static void +_present_configure(xcb_present_configure_notify_event_t *ev) +{ + Ecore_X_Event_Present_Configure *e; + + e = calloc(1, sizeof(Ecore_X_Event_Present_Configure)); + if (!e) return; + + e->win = ev->window; + SET(x), SET(y); + SET(width), SET(height); + SET(off_x), SET(off_y); + SET(pixmap_width), SET(pixmap_height); + SET(pixmap_flags); + + ecore_event_add(ECORE_X_EVENT_PRESENT_CONFIGURE, e, NULL, NULL); +} + +static void +_present_complete(xcb_present_complete_notify_event_t *ev) +{ + unsigned int mode[] = + { + [XCB_PRESENT_COMPLETE_MODE_COPY] = ECORE_X_PRESENT_COMPLETE_MODE_COPY, + [XCB_PRESENT_COMPLETE_MODE_FLIP] = ECORE_X_PRESENT_COMPLETE_MODE_FLIP, + [XCB_PRESENT_COMPLETE_MODE_SKIP] = ECORE_X_PRESENT_COMPLETE_MODE_SKIP, + }; + Ecore_X_Event_Present_Complete *e; + + e = calloc(1, sizeof(Ecore_X_Event_Present_Complete)); + if (!e) return; + + e->win = ev->window; + SET(serial); + SET(ust), SET(msc); + e->kind = (ev->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC); + e->mode = mode[ev->mode]; + ecore_event_add(ECORE_X_EVENT_PRESENT_COMPLETE, e, NULL, NULL); +} + +static void +_present_idle(xcb_present_idle_notify_event_t *ev) +{ + Ecore_X_Event_Present_Idle *e; + + e = calloc(1, sizeof(Ecore_X_Event_Present_Idle)); + if (!e) return; + + e->win = ev->window; + SET(serial); + SET(pixmap); + SET(idle_fence); + ecore_event_add(ECORE_X_EVENT_PRESENT_IDLE, e, NULL, NULL); +} +#undef SET + +void +_ecore_xcb_event_handle_present_event(xcb_ge_event_t *ev) +{ + switch (ev->event_type) + { + case XCB_PRESENT_EVENT_CONFIGURE_NOTIFY: + _present_configure((xcb_present_configure_notify_event_t*)(long)ev->pad1); + break; + case XCB_PRESENT_EVENT_COMPLETE_NOTIFY: + _present_complete((xcb_present_complete_notify_event_t*)(long)ev->pad1); + break; + case XCB_PRESENT_EVENT_IDLE_NOTIFY: + _present_idle((xcb_present_idle_notify_event_t*)(long)ev->pad1); + break; + default: break; + } +} +#endif + + +EAPI void +ecore_x_present_select_events(Ecore_X_Window win, unsigned int events) +{ +#ifdef ECORE_XCB_XPRESENT + xcb_present_select_input(_ecore_xcb_conn, _ecore_xcb_event_xpresent, win, events); +#else + (void)win; + (void)events; +#endif +} + +EAPI void +ecore_x_present_notify_msc(Ecore_X_Window win, unsigned int serial, unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder) +{ +#ifdef ECORE_XCB_XPRESENT + xcb_present_notify_msc(_ecore_xcb_conn, win, serial, target_msc, divisor, remainder); +#else + (void)win; + (void)serial; + (void)target_msc; + (void)divisor; + (void)remainder; +#endif +} + +EAPI void +ecore_x_present_pixmap(Ecore_X_Window win, Ecore_X_Pixmap pixmap, unsigned int serial, Ecore_X_Region valid, + Ecore_X_Region update, int x_off, int y_off, Ecore_X_Randr_Crtc target_crtc, + Ecore_X_Sync_Fence wait_fence, Ecore_X_Sync_Fence idle_fence, unsigned int options, + unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder, + Ecore_X_Present *notifies, int num_notifies) +{ +#ifdef ECORE_XCB_XPRESENT + xcb_present_pixmap(_ecore_xcb_conn, win, pixmap, serial, valid, update, + x_off, y_off, target_crtc, wait_fence, idle_fence, options, target_msc, + divisor, remainder, num_notifies, (xcb_present_notify_t*)notifies); +#else + (void)win; + (void)pixmap; + (void)serial; + (void)valid; + (void)update; + (void)x_off; + (void)y_off; + (void)target_crtc; + (void)wait_fence; + (void)idle_fence; + (void)options; + (void)target_msc; + (void)divisor; + (void)remainder; + (void)notifies; + (void)num_notifies; +#endif +} + +EAPI Eina_Bool +ecore_x_present_exists(void) +{ + return _xpresent_avail; +} diff --git a/src/lib/ecore_x/xcb/ecore_xcb_private.h b/src/lib/ecore_x/xcb/ecore_xcb_private.h index d578a975ca..61452f2385 100644 --- a/src/lib/ecore_x/xcb/ecore_xcb_private.h +++ b/src/lib/ecore_x/xcb/ecore_xcb_private.h @@ -278,6 +278,11 @@ void _ecore_xcb_damage_finalize(void); void _ecore_xcb_composite_init(void); void _ecore_xcb_composite_finalize(void); +void _ecore_xcb_present_init(void); +void _ecore_xcb_present_finalize(void); +void _ecore_xcb_event_handle_present_event(xcb_ge_event_t *ev); +extern int _ecore_xcb_event_xpresent; + void _ecore_xcb_dpms_init(void); void _ecore_xcb_dpms_finalize(void); diff --git a/src/lib/ecore_x/xlib/ecore_x.c b/src/lib/ecore_x/xlib/ecore_x.c index 501bc7ae92..a9be6b6fc7 100644 --- a/src/lib/ecore_x/xlib/ecore_x.c +++ b/src/lib/ecore_x/xlib/ecore_x.c @@ -148,6 +148,10 @@ EAPI int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = 0; EAPI int ECORE_X_EVENT_GENERIC = 0; +EAPI int ECORE_X_EVENT_PRESENT_CONFIGURE = 0; +EAPI int ECORE_X_EVENT_PRESENT_COMPLETE = 0; +EAPI int ECORE_X_EVENT_PRESENT_IDLE = 0; + EAPI int ECORE_X_MODIFIER_SHIFT = 0; EAPI int ECORE_X_MODIFIER_CTRL = 0; EAPI int ECORE_X_MODIFIER_ALT = 0; @@ -665,6 +669,7 @@ ecore_x_init(const char *name) _ecore_x_fixes_init(); _ecore_x_damage_init(); _ecore_x_composite_init(); + _ecore_x_present_init(); _ecore_x_dpms_init(); _ecore_x_randr_init(); _ecore_x_gesture_init(); diff --git a/src/lib/ecore_x/xlib/ecore_x_events.c b/src/lib/ecore_x/xlib/ecore_x_events.c index ac1e475f2d..467cbcd1a7 100644 --- a/src/lib/ecore_x/xlib/ecore_x_events.c +++ b/src/lib/ecore_x/xlib/ecore_x_events.c @@ -2270,7 +2270,6 @@ static void _ecore_x_event_free_generic_event(void *data, void *ev) { -#ifdef ECORE_XI2 Ecore_X_Event_Generic *e = (Ecore_X_Event_Generic *)ev; if (data) @@ -2280,16 +2279,11 @@ _ecore_x_event_free_generic_event(void *data, free(data); } free(e); -#else - return; - data = NULL; ev = NULL; -#endif /* ifdef ECORE_XI2 */ } void _ecore_x_event_handle_generic_event(XEvent *event) { -#ifdef ECORE_XI2 XGenericEvent *generic_event; Ecore_X_Event_Generic *e; XGenericEventCookie *data; @@ -2297,6 +2291,14 @@ _ecore_x_event_handle_generic_event(XEvent *event) LOGFN(__FILE__, __LINE__, __FUNCTION__); generic_event = (XGenericEvent *)event; +#ifdef ECORE_XPRESENT + if (generic_event->extension == _ecore_x_present_major) + { + _ecore_x_present_handler(generic_event); + return; + } +#endif + e = calloc(1, sizeof(Ecore_X_Event_Generic)); if (!e) return; @@ -2314,20 +2316,16 @@ _ecore_x_event_handle_generic_event(XEvent *event) e->extension = generic_event->extension; e->evtype = generic_event->evtype; - +#ifdef ECORE_XI2 if (e->extension == _ecore_x_xi2_opcode) _ecore_x_input_handler(event); - +#endif /* ifdef ECORE_XI2 */ data = malloc(sizeof(XGenericEventCookie)); if (data) memcpy(data, &(event->xcookie), sizeof(XGenericEventCookie)); ecore_event_add(ECORE_X_EVENT_GENERIC, e, _ecore_x_event_free_generic_event, data); -#else - return; - event = NULL; -#endif /* ifdef ECORE_XI2 */ } #ifdef ECORE_XGESTURE diff --git a/src/lib/ecore_x/xlib/ecore_x_present.c b/src/lib/ecore_x/xlib/ecore_x_present.c new file mode 100644 index 0000000000..9e6a398e4b --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_present.c @@ -0,0 +1,169 @@ +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + +#include + +#include "ecore_x_private.h" +#include "Ecore_X.h" + +int _ecore_x_present_major = 0; +static Eina_Bool _ecore_x_present_exists = EINA_FALSE; + +void +_ecore_x_present_init(void) +{ + ECORE_X_EVENT_PRESENT_CONFIGURE = ecore_event_type_new(); + ECORE_X_EVENT_PRESENT_COMPLETE = ecore_event_type_new(); + ECORE_X_EVENT_PRESENT_IDLE = ecore_event_type_new(); +#ifdef ECORE_XPRESENT + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_present_exists = XPresentQueryExtension(_ecore_x_disp, &_ecore_x_present_major, NULL, NULL); +#endif +} + +#ifdef ECORE_XPRESENT +#define SET(X) e->X = ev->X + +static void +_present_configure(XPresentConfigureNotifyEvent *ev) +{ + Ecore_X_Event_Present_Configure *e; + + e = calloc(1, sizeof(Ecore_X_Event_Present_Configure)); + if (!e) return; + + e->win = ev->window; + SET(x), SET(y); + SET(width), SET(height); + SET(off_x), SET(off_y); + SET(pixmap_width), SET(pixmap_height); + SET(pixmap_flags); + + ecore_event_add(ECORE_X_EVENT_PRESENT_CONFIGURE, e, NULL, NULL); +} + +static void +_present_complete(XPresentCompleteNotifyEvent *ev) +{ + unsigned int mode[] = + { + [PresentCompleteModeCopy] = ECORE_X_PRESENT_COMPLETE_MODE_COPY, + [PresentCompleteModeFlip] = ECORE_X_PRESENT_COMPLETE_MODE_FLIP, + [PresentCompleteModeSkip] = ECORE_X_PRESENT_COMPLETE_MODE_SKIP, + }; + Ecore_X_Event_Present_Complete *e; + + e = calloc(1, sizeof(Ecore_X_Event_Present_Complete)); + if (!e) return; + + e->win = ev->window; + e->serial = ev->serial_number; + SET(ust), SET(msc); + e->kind = (ev->kind == 1); //libXpresent doesn't expose this... + e->mode = mode[ev->mode]; + ecore_event_add(ECORE_X_EVENT_PRESENT_COMPLETE, e, NULL, NULL); +} + +static void +_present_idle(XPresentIdleNotifyEvent *ev) +{ + Ecore_X_Event_Present_Idle *e; + + e = calloc(1, sizeof(Ecore_X_Event_Present_Idle)); + if (!e) return; + + e->win = ev->window; + e->serial = ev->serial_number; + SET(pixmap); + SET(idle_fence); + ecore_event_add(ECORE_X_EVENT_PRESENT_IDLE, e, NULL, NULL); +} +#undef SET + +void +_ecore_x_present_handler(XGenericEvent *ge) +{ + XGenericEventCookie *gec = (XGenericEventCookie*)ge; + + if (XGetEventData(_ecore_x_disp, gec)) + { + switch (gec->evtype) + { + case PresentConfigureNotify: + _present_configure(gec->data); + break; + case PresentCompleteNotify: + _present_complete(gec->data); + break; + case PresentIdleNotify: + _present_idle(gec->data); + break; + default: break; + } + } + XFreeEventData(_ecore_x_disp, gec); +} +#endif + +EAPI void +ecore_x_present_select_events(Ecore_X_Window win, unsigned int events) +{ +#ifdef ECORE_XPRESENT + XPresentSelectInput(_ecore_x_disp, win, events); +#else + (void)win; + (void)events; +#endif +} + +EAPI void +ecore_x_present_notify_msc(Ecore_X_Window win, unsigned int serial, unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder) +{ +#ifdef ECORE_XPRESENT + XPresentNotifyMSC(_ecore_x_disp, win, serial, target_msc, divisor, remainder); +#else + (void)win; + (void)serial; + (void)target_msc; + (void)divisor; + (void)remainder; +#endif +} + +EAPI void +ecore_x_present_pixmap(Ecore_X_Window win, Ecore_X_Pixmap pixmap, unsigned int serial, Ecore_X_Region valid, + Ecore_X_Region update, int x_off, int y_off, Ecore_X_Randr_Crtc target_crtc, + Ecore_X_Sync_Fence wait_fence, Ecore_X_Sync_Fence idle_fence, unsigned int options, + unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder, + Ecore_X_Present *notifies, int num_notifies) +{ +#ifdef ECORE_XPRESENT + XPresentPixmap(_ecore_x_disp, win, pixmap, serial, valid, update, + x_off, y_off, target_crtc, wait_fence, idle_fence, options, target_msc, + divisor, remainder, (XPresentNotify*)notifies, num_notifies); +#else + (void)win; + (void)pixmap; + (void)serial; + (void)valid; + (void)update, + (void)x_off; + (void)y_off; + (void)target_crtc; + (void)wait_fence; + (void)idle_fence; + (void)options; + (void)target_msc, + (void)divisor; + (void)remainder; + (void)notifies; + (void)num_notifies; +#endif +} + +EAPI Eina_Bool +ecore_x_present_exists(void) +{ + return _ecore_x_present_exists; +} diff --git a/src/lib/ecore_x/xlib/ecore_x_private.h b/src/lib/ecore_x/xlib/ecore_x_private.h index 815e081238..94a3db88bf 100644 --- a/src/lib/ecore_x/xlib/ecore_x_private.h +++ b/src/lib/ecore_x/xlib/ecore_x_private.h @@ -40,6 +40,9 @@ #ifdef ECORE_XCOMPOSITE #include #endif /* ifdef ECORE_XCOMPOSITE */ +#ifdef ECORE_XPRESENT +#include +#endif /* ifdef ECORE_XPRESENT */ #ifdef ECORE_XDAMAGE #include #endif /* ifdef ECORE_XDAMAGE */ @@ -264,6 +267,10 @@ void _ecore_x_event_handle_xkb(XEvent *xevent); #endif /* ifdef ECORE_XKB */ void _ecore_x_event_handle_generic_event(XEvent *xevent); +#ifdef ECORE_XPRESENT +void _ecore_x_present_handler(XGenericEvent *ge); +#endif + void _ecore_x_selection_data_init(void); void _ecore_x_selection_shutdown(void); Ecore_X_Atom _ecore_x_selection_target_atom_get(const char *target); @@ -308,12 +315,14 @@ int _ecore_x_netwm_startup_info(Ecore_X_Window win, void _ecore_x_fixes_init(void); void _ecore_x_damage_init(void); void _ecore_x_composite_init(void); +void _ecore_x_present_init(void); void _ecore_x_dpms_init(void); void _ecore_x_randr_init(void); void _ecore_x_gesture_init(void); void _ecore_x_atoms_init(void); +extern int _ecore_x_present_major; extern int _ecore_x_xi2_opcode; void _ecore_x_events_init(void);