diff --git a/legacy/ecore/configure.in b/legacy/ecore/configure.in index cb771a1620..15137603f2 100644 --- a/legacy/ecore/configure.in +++ b/legacy/ecore/configure.in @@ -142,11 +142,92 @@ AC_SUBST(iconv_libs) ECORE_CHECK_MODULE([Txt], [yes], [$have_iconv], [ecore_txt_libs="$ecore_txt_libs $iconv_libs"]) +dnl Check for XCB +have_ecore_x="no" +have_ecore_x_xcb="no" + +AC_ARG_ENABLE(ecore-x-xcb, + AC_HELP_STRING( + [--enable-ecore-x-xcb], + [enable the ecore_x module with XCB backend. [[default=disabled]]]), + [ want_ecore_x_xcb=$enableval ], + [ want_ecore_x_xcb="no" ]) + +AC_MSG_CHECKING(whether ecore_x with XCB backend is to be built) +AC_MSG_RESULT($want_ecore_x_xcb) + +if test "x$want_ecore_x_xcb" = "xyes" ; then + PKG_CHECK_MODULES(XCB, xcb xcb-icccm xcb-image xcb-keysyms, + [ have_ecore_x_xcb="yes" ], + [ have_ecore_x_xcb="no" ]) + + if test "x$have_ecore_x_xcb" = "xyes" ; then + PKG_CHECK_MODULES(XCB_DAMAGE, xcb-damage, + [ have_ecore_x_xcb_damage="yes" + AC_DEFINE(ECORE_XCB_DAMAGE, 1, [Build support for XCB damage]) ], + [ have_ecore_x_xcb_damage="no" ]) + + PKG_CHECK_MODULES(XCB_DPMS, xcb-dpms, + [ have_ecore_x_xcb_dpms="yes" + AC_DEFINE(ECORE_XCB_DPMS, 1, [Build support for XCB dpms]) ], + [ have_ecore_x_xcb_dpms="no" ]) + + PKG_CHECK_MODULES(XCB_RANDR, xcb-randr, + [ have_ecore_x_xcb_randr="yes" + AC_DEFINE(ECORE_XCB_RANDR, 1, [Build support for XCB randr]) ], + [ have_ecore_x_xcb_randr="no" ]) + + PKG_CHECK_MODULES(XCB_RENDER, xcb-render, + [ have_ecore_x_xcb_render="yes" + AC_DEFINE(ECORE_XCB_RENDER, 1, [Build support for XCB render]) ], + [ have_ecore_x_xcb_render="no" ]) + + PKG_CHECK_MODULES(XCB_SCREENSAVER, xcb-screensaver, + [ have_ecore_x_xcb_screensaver="yes" + AC_DEFINE(ECORE_XCB_SCREENSAVER, 1, [Build support for XCB screensaver]) ], + [ have_ecore_x_xcb_screensaver="no" ]) + + PKG_CHECK_MODULES(XCB_SHAPE, xcb-shape, + [ have_ecore_x_xcb_shape="yes" + AC_DEFINE(ECORE_XCB_SHAPE, 1, [Build support for XCB shape]) ], + [ have_ecore_x_xcb_shape="no" ]) + + PKG_CHECK_MODULES(XCB_SYNC, xcb-sync, + [ have_ecore_x_xcb_sync="yes" + AC_DEFINE(ECORE_XCB_SYNC, 1, [Build support for XCB sync]) ], + [ have_ecore_x_xcb_sync="no" ]) + + PKG_CHECK_MODULES(XCB_XFIXES, xcb-xfixes, + [ have_ecore_x_xcb_xfixes="yes" + AC_DEFINE(ECORE_XCB_FIXES, 1, [Build support for XCB xfixes]) ], + [ have_ecore_x_xcb_xfixes="no" ]) + + PKG_CHECK_MODULES(XCB_XINERAMA, xcb-xinerama, + [ have_ecore_x_xcb_xinerama="yes" + AC_DEFINE(ECORE_XCB_XINERAMA, 1, [Build support for XCB xinerama]) ], + [ have_ecore_x_xcb_xinerama="no" ]) + + PKG_CHECK_MODULES(XCB_XPRINT, xcb-xprint, + [ have_ecore_x_xcb_xprint="yes" + AC_DEFINE(ECORE_XCB_XPRINT, 1, [Build support for XCB xprint]) ], + [ have_ecore_x_xcb_xprint="no" ]) + + AC_DEFINE(BUILD_ECORE_X, 1, [Build Ecore_X Module (XCB backend)]) + AC_DEFINE(HAVE_ECORE_X_XCB, 1, [Defined to 1 if XCB backend is enabled.]) + + requirements_ecore_evas="$requirements_ecore_evas ecore-x" + have_ecore_x_xcb_define="-DHAVE_ECORE_X_XCB" + have_ecore_x="yes" + AC_SUBST(have_ecore_x_xcb_define) + fi +fi + have_x="no" x_dir=""; x_includes=""; x_cflags=""; x_libs=""; +if test "x$have_ecore_x_xcb" != "xyes" ; then AC_PATH_XTRA AC_CHECK_HEADER(X11/X.h, [ @@ -214,6 +295,8 @@ if test "x$have_ecore_x" = "xyes"; then requirements_ecore_evas="$requirements_ecore_evas ecore-x" fi +fi + ECORE_CHECK_MODULE([Job], [yes]) PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.16, @@ -630,6 +713,8 @@ AC_SUBST(requirements_ecore_txt) AC_SUBST(requirements_ecore_x) # set up conditionals +AM_CONDITIONAL(BUILD_ECORE_X, test "x$have_ecore_x" = "xyes") +AM_CONDITIONAL(BUILD_ECORE_X_XCB, test "x$have_ecore_x_xcb" = "xyes") AM_CONDITIONAL(BUILD_ECORE_EVAS_GL, test $have_ecore_evas_gl = yes) AM_CONDITIONAL(BUILD_ECORE_EVAS_XRENDER, test $have_ecore_evas_xrender = yes) AM_CONDITIONAL(BUILD_ECORE_EVAS_DIRECTFB, test $have_ecore_evas_dfb = yes) @@ -683,7 +768,11 @@ echo echo " Ecore_Job....................: $have_ecore_job" echo " Ecore_Con....................: $have_ecore_con (OpenSSL: $use_openssl)" echo " Ecore_Txt....................: $have_ecore_txt" -echo " Ecore_X......................: $have_ecore_x (Xcursor: $use_Xcursor) (Xprint: $use_xprint) (Xinerama: $use_xinerama) (Xrandr: $use_xrandr) (Xscreensaver: $use_xss) (Xrender: $use_xrender) (Xfixes: $use_xfixes) (Xdamage: $use_xdamage) (Xdpms: $use_xdpms)" +if test "x$have_ecore_x_xcb" = "xyes" ; then +echo " Ecore_X (XCB backend)........: $have_ecore_x_xcb (Xprint: $have_ecore_x_xcb_xprint) (Xinerama: $have_ecore_x_xcb_xinerama) (Xrandr: $have_ecore_x_xcb_randr) (Xscreensaver: $have_ecore_x_xcb_screensaver) (Xshape: $have_ecore_x_xcb_shape) (Xsync: $have_ecore_x_xcb_sync) (Xrender: $have_ecore_x_xcb_render) (Xfixes: $have_ecore_x_xcb_xfixes) (Xdamage: $have_ecore_x_xcb_damage) (Xdpms: $have_ecore_x_xcb_dpms)" +else + echo " Ecore_X (Xlib backend).......: $have_ecore_x (Xcursor: $use_Xcursor) (Xprint: $use_xprint) (Xinerama: $use_xinerama) (Xrandr: $use_xrandr) (Xscreensaver: $use_xss) (Xrender: $use_xrender) (Xfixes: $use_xfixes) (Xdamage: $use_xdamage) (Xdpms: $use_xdpms)" +fi echo " Ecore_FB.....................: $have_ecore_fb" echo " Ecore_DFB....................: $have_ecore_directfb" echo " Ecore_Evas...................: $have_ecore_evas" diff --git a/legacy/ecore/src/lib/ecore_evas/Makefile.am b/legacy/ecore/src/lib/ecore_evas/Makefile.am index 8b69aed38e..5160f0f03e 100644 --- a/legacy/ecore/src/lib/ecore_evas/Makefile.am +++ b/legacy/ecore/src/lib/ecore_evas/Makefile.am @@ -38,7 +38,8 @@ INCLUDES = \ $(ECORE_X_INC) \ $(ECORE_FB_INC) \ $(ECORE_DIRECTFB_INC) \ -@EVAS_CFLAGS@ +@EVAS_CFLAGS@ \ +@XCB_CFLAGS@ libecore_evas_la_LDFLAGS = -version-info 1:0:0 \ $(ECORE_X_LDF) \ @@ -65,7 +66,8 @@ $(ECORE_X_LIB) \ $(ECORE_FB_LIB) \ $(ECORE_DIRECTFB_LIB) \ $(top_builddir)/src/lib/ecore/libecore.la \ -@EVAS_LIBS@ +@EVAS_LIBS@ \ +@XCB_LIBS@ libecore_evas_la_DEPENDENCIES = \ $(ECORE_X_LIB) \ diff --git a/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h b/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h index 6f052ed60c..2ea2e724d0 100644 --- a/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h +++ b/legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h @@ -23,19 +23,30 @@ #endif #ifdef BUILD_ECORE_X -#include "Ecore_X.h" -#include -#include -#include -#ifdef ECORE_XRENDER -#include -#endif -#ifdef BUILD_ECORE_EVAS_GL -#include -#endif -#ifdef BUILD_ECORE_EVAS_XRENDER -#include -#endif +# include "Ecore_X.h" +# ifdef HAVE_ECORE_X_XCB +# include +# include +# ifdef ECORE_XCB_RENDER +# include +# endif +# ifdef BUILD_ECORE_EVAS_XRENDER +# include +# endif +# else +# include +# include +# include +# ifdef ECORE_XRENDER +# include +# endif +# ifdef BUILD_ECORE_EVAS_GL +# include +# endif +# ifdef BUILD_ECORE_EVAS_XRENDER +# include +# endif +# endif /* HAVE_ECORE_X_XCB */ #endif #ifdef BUILD_ECORE_EVAS_FB #include @@ -112,7 +123,11 @@ struct _Ecore_Evas_Engine Ecore_X_Pixmap pmap; Ecore_X_Pixmap mask; Ecore_X_GC gc; +#ifdef HAVE_ECORE_X_XCB +#warning [XCB] No Region code +#else Region damages; +#endif /* HAVE_ECORE_X_XCB */ int px, py, pw, ph; unsigned char direct_resize : 1; unsigned char using_bg_pixmap : 1; diff --git a/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c b/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c index f76c9c9669..3f7feec46e 100644 --- a/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c +++ b/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c @@ -21,13 +21,41 @@ static Evas_Hash *ecore_evases_hash = NULL; static Ecore_Event_Handler *ecore_evas_event_handlers[17]; static Ecore_Idle_Enterer *ecore_evas_idle_enterer = NULL; + +#ifdef HAVE_ECORE_X_XCB +static xcb_visualtype_t * +xcb_visualtype_get(xcb_screen_t *screen, xcb_visualid_t visual) +{ + xcb_depth_iterator_t iter_depth; + + if (!screen) return NULL; + + iter_depth = xcb_screen_allowed_depths_iterator(screen); + for (; iter_depth.rem; xcb_depth_next (&iter_depth)) + { + xcb_visualtype_iterator_t iter_vis; + + iter_vis = xcb_depth_visuals_iterator(iter_depth.data); + for (; iter_vis.rem; --screen, xcb_visualtype_next (&iter_vis)) + { + if (visual == iter_vis.data->visual_id) + return iter_vis.data; + } + } + + return NULL; +} +#endif /* HAVE_ECORE_X_XCB*/ + #ifdef BUILD_ECORE_EVAS_GL +# ifdef HAVE_ECORE_X_XCB +# else static Ecore_X_Window _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, int w, int h, int override) { Evas_Engine_Info_GL_X11 *einfo; Ecore_X_Window win; - + einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas); if (einfo) { @@ -40,13 +68,13 @@ _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, { Ecore_X_Window *roots; int num, i; - + num = 0; roots = ecore_x_window_root_list(&num); if (roots) { XWindowAttributes at; - + if (XGetWindowAttributes(ecore_x_display_get(), parent, &at)) { @@ -69,16 +97,16 @@ _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, attr.background_pixmap = None; attr.event_mask = KeyPressMask | KeyReleaseMask | - ExposureMask | ButtonPressMask | ButtonReleaseMask | + ExposureMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | StructureNotifyMask | VisibilityChangeMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask; attr.bit_gravity = ForgetGravity; - - win = - XCreateWindow(ecore_x_display_get(), + + win = + XCreateWindow(ecore_x_display_get(), parent, - x, y, + x, y, w, h, 0, einfo->func.best_depth_get(ecore_x_display_get(), screen), InputOutput, @@ -101,6 +129,7 @@ _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, } return win; } +#endif /* HAVE_ECORE_X_XCB*/ #endif static void @@ -109,34 +138,34 @@ _ecore_evas_x_render(Ecore_Evas *ee) #ifdef BUILD_ECORE_EVAS_BUFFER Evas_List *ll; #endif - + #ifdef BUILD_ECORE_EVAS_BUFFER for (ll = ee->sub_ecore_evas; ll; ll = ll->next) { Ecore_Evas *ee2; - + ee2 = ll->data; if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); _ecore_evas_buffer_render(ee2); if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); } -#endif +#endif if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); if (ee->prop.avoid_damage) { Evas_List *updates, *l; - + updates = evas_render_updates(ee->evas); #if 0 for (l = updates; l; l = l->next) { Evas_Rectangle *r; - + r = l->data; printf("DMG render [%p] %ix%i, [%i %i %ix%i]\n", ee, ee->w, ee->h, r->x, r->y, r->w, r->h); } -#endif +#endif if (ee->engine.x.using_bg_pixmap) { if (updates) @@ -144,7 +173,7 @@ _ecore_evas_x_render(Ecore_Evas *ee) for (l = updates; l; l = l->next) { Evas_Rectangle *r; - + r = l->data; ecore_x_window_area_clear(ee->engine.x.win, r->x, r->y, r->w, r->h); } @@ -155,12 +184,15 @@ _ecore_evas_x_render(Ecore_Evas *ee) } else { +#ifdef HAVE_ECORE_X_XCB +#warning [XCB] No Region code +#else for (l = updates; l; l = l->next) { Evas_Rectangle *r; XRectangle xr; Region tmpr; - + if (!ee->engine.x.damages) ee->engine.x.damages = XCreateRegion(); r = l->data; @@ -201,7 +233,7 @@ _ecore_evas_x_render(Ecore_Evas *ee) { /* if we have a damage pixmap - we can avoid exposures by * disabling them just for setting the mask */ - ecore_x_window_shape_events_select(ee->engine.x.win, + ecore_x_window_shape_events_select(ee->engine.x.win, ECORE_X_EVENT_MASK_KEY_DOWN | ECORE_X_EVENT_MASK_KEY_UP | ECORE_X_EVENT_MASK_MOUSE_DOWN | @@ -219,7 +251,7 @@ _ecore_evas_x_render(Ecore_Evas *ee) if ((ee->shaped) && (updates)) ecore_x_window_shape_mask_set(ee->engine.x.win, ee->engine.x.mask); /* and re-enable them again */ - ecore_x_window_shape_events_select(ee->engine.x.win, + ecore_x_window_shape_events_select(ee->engine.x.win, ECORE_X_EVENT_MASK_KEY_DOWN | ECORE_X_EVENT_MASK_KEY_UP | ECORE_X_EVENT_MASK_MOUSE_DOWN | @@ -236,7 +268,7 @@ _ecore_evas_x_render(Ecore_Evas *ee) ); XSetRegion(ecore_x_display_get(), ee->engine.x.gc, ee->engine.x.damages); /* debug rendering */ - /* + /* XSetForeground(ecore_x_display_get(), ee->engine.x.gc, rand()); XFillRectangle(ecore_x_display_get(), ee->engine.x.win, ee->engine.x.gc, 0, 0, ee->w, ee->h); @@ -249,17 +281,18 @@ _ecore_evas_x_render(Ecore_Evas *ee) XDestroyRegion(ee->engine.x.damages); ee->engine.x.damages = 0; } +#endif /* HAVE_ECORE_X_XCB */ if (updates) evas_render_updates_free(updates); } } - else if ((ee->visible) || + else if ((ee->visible) || ((ee->should_be_visible) && (ee->prop.fullscreen)) || ((ee->should_be_visible) && (ee->prop.override))) { if (ee->shaped) { Evas_List *updates; - + updates = evas_render_updates(ee->evas); if (updates) { @@ -270,24 +303,24 @@ _ecore_evas_x_render(Ecore_Evas *ee) else { Evas_List *updates; - + updates = evas_render_updates(ee->evas); if (updates) { #if 0 Evas_List *l; - + printf("RENDER [%p] [%i] %ix%i\n", ee, ee->visible, ee->w, ee->h); for (l = updates; l; l = l->next) { Evas_Rectangle *r; - + r = l->data; printf(" render [%i %i %ix%i]\n", r->x, r->y, r->w, r->h); } -#endif +#endif evas_render_updates_free(updates); } } @@ -306,19 +339,19 @@ _ecore_evas_x_mouse_move_process(Ecore_Evas *ee, int x, int y, unsigned int time { evas_object_show(ee->prop.cursor.object); if (ee->rotation == 0) - evas_object_move(ee->prop.cursor.object, + evas_object_move(ee->prop.cursor.object, x - ee->prop.cursor.hot.x, y - ee->prop.cursor.hot.y); else if (ee->rotation == 90) - evas_object_move(ee->prop.cursor.object, + evas_object_move(ee->prop.cursor.object, ee->h - y - 1 - ee->prop.cursor.hot.x, x - ee->prop.cursor.hot.y); else if (ee->rotation == 180) - evas_object_move(ee->prop.cursor.object, + evas_object_move(ee->prop.cursor.object, ee->w - x - 1 - ee->prop.cursor.hot.x, ee->h - y - 1 - ee->prop.cursor.hot.y); else if (ee->rotation == 270) - evas_object_move(ee->prop.cursor.object, + evas_object_move(ee->prop.cursor.object, y - ee->prop.cursor.hot.x, ee->w - x - 1 - ee->prop.cursor.hot.y); } @@ -338,7 +371,7 @@ _ecore_evas_x_winid_str_get(Ecore_X_Window win) const char *vals = "qWeRtYuIoP5-$&<~"; static char id[9]; unsigned int val; - + val = (unsigned int)win; id[0] = vals[(val >> 28) & 0xf]; id[1] = vals[(val >> 24) & 0xf]; @@ -356,7 +389,7 @@ static Ecore_Evas * _ecore_evas_x_match(Ecore_X_Window win) { Ecore_Evas *ee; - + ee = evas_hash_find(ecore_evases_hash, _ecore_evas_x_winid_str_get(win)); return ee; } @@ -365,18 +398,43 @@ static void _ecore_evas_x_resize_shape(Ecore_Evas *ee) { if (!strcmp(ee->driver, "software_x11")) - { + { #ifdef BUILD_ECORE_X +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_Software_Xcb *einfo; + + einfo = (Evas_Engine_Info_Software_Xcb *)evas_engine_info_get(ee->evas); +# else Evas_Engine_Info_Software_X11 *einfo; - + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); +# endif /* HAVE_ECORE_X_XCB */ if (einfo) { +# ifdef HAVE_ECORE_X_XCB + xcb_rectangle_t rectangle; + Ecore_X_GC gc; + uint32_t value_list; +# else GC gc; XGCValues gcv; - +# endif /* HAVE_ECORE_X_XCB */ + if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1); +# ifdef HAVE_ECORE_X_XCB + gc = xcb_generate_id(ecore_x_connection_get()); + value_list = 0; + xcb_create_gc(ecore_x_connection_get(), gc, ee->engine.x.mask, + XCB_GC_FOREGROUND, &value_list); + rectangle.x = 0; + rectangle.y = 0; + rectangle.width = ee->w; + rectangle.height = ee->h; + xcb_poly_fill_rectangle(ecore_x_connection_get(), ee->engine.x.mask, gc, + 1, &rectangle); + xcb_free_gc(ecore_x_connection_get(), gc); +# else gcv.foreground = 0; gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, GCForeground, @@ -384,26 +442,52 @@ _ecore_evas_x_resize_shape(Ecore_Evas *ee) XFillRectangle(ecore_x_display_get(), ee->engine.x.mask, gc, 0, 0, ee->w, ee->h); XFreeGC(ecore_x_display_get(), gc); +# endif /* HAVE_ECORE_X_XCB */ einfo->info.mask = ee->engine.x.mask; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); - + } -#endif +#endif /* BUILD_ECORE_X */ } else if (!strcmp(ee->driver, "xrender_x11")) - { + { #ifdef BUILD_ECORE_EVAS_XRENDER +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_XRender_Xcb *einfo; + + einfo = (Evas_Engine_Info_XRender_Xcb *)evas_engine_info_get(ee->evas); +# else Evas_Engine_Info_XRender_X11 *einfo; - + einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas); +# endif /* HAVE_ECORE_X_XCB */ if (einfo) { +# ifdef HAVE_ECORE_X_XCB + xcb_rectangle_t rectangle; + Ecore_X_GC gc; + uint32_t value_list; +# else GC gc; XGCValues gcv; - +# endif /* HAVE_ECORE_X_XCB */ + if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1); +# ifdef HAVE_ECORE_X_XCB + gc = xcb_generate_id(ecore_x_connection_get()); + value_list = 0; + xcb_create_gc(ecore_x_connection_get(), gc, ee->engine.x.mask, + XCB_GC_FOREGROUND, &value_list); + rectangle.x = 0; + rectangle.y = 0; + rectangle.width = ee->w; + rectangle.height = ee->h; + xcb_poly_fill_rectangle(ecore_x_connection_get(), ee->engine.x.mask, gc, + 1, &rectangle); + xcb_free_gc(ecore_x_connection_get(), gc); +# else gcv.foreground = 0; gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, GCForeground, @@ -411,12 +495,13 @@ _ecore_evas_x_resize_shape(Ecore_Evas *ee) XFillRectangle(ecore_x_display_get(), ee->engine.x.mask, gc, 0, 0, ee->w, ee->h); XFreeGC(ecore_x_display_get(), gc); +# endif /* HAVE_ECORE_X_XCB */ einfo->info.mask = ee->engine.x.mask; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); - + } -#endif +#endif /* BUILD_ECORE_EVAS_XRENDER */ } } @@ -456,7 +541,7 @@ _ecore_evas_x_modifier_locks_update(Ecore_Evas *ee, int modifiers) if (modifiers & ECORE_X_LOCK_CAPS) evas_key_lock_on(ee->evas, "Caps_Lock"); else - evas_key_lock_off(ee->evas, "Caps_Lock"); + evas_key_lock_off(ee->evas, "Caps_Lock"); } static int @@ -464,7 +549,7 @@ _ecore_evas_x_event_key_down(void *data __UNUSED__, int type __UNUSED__, void *e { Ecore_Evas *ee; Ecore_X_Event_Key_Down *e; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ @@ -478,7 +563,7 @@ _ecore_evas_x_event_key_up(void *data __UNUSED__, int type __UNUSED__, void *eve { Ecore_Evas *ee; Ecore_X_Event_Key_Up *e; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ @@ -493,7 +578,7 @@ _ecore_evas_x_event_mouse_button_down(void *data __UNUSED__, int type __UNUSED__ Ecore_Evas *ee; Ecore_X_Event_Mouse_Button_Down *e; Evas_Button_Flags flags = EVAS_BUTTON_NONE; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ @@ -511,12 +596,12 @@ _ecore_evas_x_event_mouse_button_up(void *data __UNUSED__, int type __UNUSED__, Ecore_Evas *ee; Ecore_X_Event_Mouse_Button_Up *e; Evas_Button_Flags flags = EVAS_BUTTON_NONE; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ if (e->win != ee->engine.x.win) return 1; - _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); if (e->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK; if (e->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK; evas_event_feed_mouse_up(ee->evas, e->button, flags, e->time, NULL); @@ -544,32 +629,40 @@ static int _ecore_evas_x_event_property_change(void *data __UNUSED__, int type __UNUSED__, void *event) { Ecore_Evas *ee; - Ecore_X_Event_Window_Property *e; + Ecore_X_Event_Window_Property *e; + printf ("_ecore_evas_x_event_property_change\n"); e = event; ee = _ecore_evas_x_match(e->win); - if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ + if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ if (e->win != ee->engine.x.win) return 1; if (e->atom == ECORE_X_ATOM_NET_WM_STATE) { unsigned int i, num; Ecore_X_Window_State *state; int sticky; - + + printf ("_ecore_evas_x_event_property_change2\n"); +#ifdef HAVE_ECORE_X_XCB + ecore_x_netwm_window_state_get_prefetch(e->win); +#endif /* HAVE_ECORE_X_XCB */ sticky = 0; - + /* TODO: we need to move those to the end, with if statements */ ee->engine.x.state.modal = 0; ee->engine.x.state.maximized_v = 0; ee->engine.x.state.maximized_h = 0; ee->engine.x.state.shaded = 0; ee->engine.x.state.skip_taskbar = 0; - ee->engine.x.state.skip_pager = 0; + ee->engine.x.state.skip_pager = 0; ee->prop.fullscreen = 0; ee->engine.x.state.fullscreen = 0; ee->engine.x.state.above = 0; - ee->engine.x.state.below = 0; - + ee->engine.x.state.below = 0; + +#ifdef HAVE_ECORE_X_XCB + ecore_x_netwm_window_state_get_fetch(); +#endif /* HAVE_ECORE_X_XCB */ ecore_x_netwm_window_state_get(e->win, &state, &num); if (state) { @@ -580,12 +673,12 @@ _ecore_evas_x_event_property_change(void *data __UNUSED__, int type __UNUSED__, case ECORE_X_WINDOW_STATE_MODAL: ee->engine.x.state.modal = 1; break; - case ECORE_X_WINDOW_STATE_STICKY: + case ECORE_X_WINDOW_STATE_STICKY: if (ee->prop.sticky && ee->engine.x.state.sticky) break; - + sticky = 1; - ee->prop.sticky = 1; + ee->prop.sticky = 1; ee->engine.x.state.sticky = 1; if (ee->func.fn_sticky) ee->func.fn_sticky(ee); break; @@ -594,7 +687,7 @@ _ecore_evas_x_event_property_change(void *data __UNUSED__, int type __UNUSED__, break; case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ: ee->engine.x.state.maximized_h = 1; - break; + break; case ECORE_X_WINDOW_STATE_SHADED: ee->engine.x.state.shaded = 1; break; @@ -604,7 +697,7 @@ _ecore_evas_x_event_property_change(void *data __UNUSED__, int type __UNUSED__, case ECORE_X_WINDOW_STATE_SKIP_PAGER: ee->engine.x.state.skip_pager = 1; break; - case ECORE_X_WINDOW_STATE_FULLSCREEN: + case ECORE_X_WINDOW_STATE_FULLSCREEN: ee->prop.fullscreen = 1; ee->engine.x.state.fullscreen = 1; break; @@ -620,14 +713,18 @@ _ecore_evas_x_event_property_change(void *data __UNUSED__, int type __UNUSED__, } free(state); } - +#ifdef HAVE_ECORE_X_XCB + ecore_xcb_reply_free(); +#endif /* HAVE_ECORE_X_XCB */ + if (ee->prop.sticky && !sticky) { ee->prop.sticky = 0; ee->engine.x.state.sticky = 0; if (ee->func.fn_unsticky) ee->func.fn_unsticky(ee); - } + } } + return 1; } @@ -636,7 +733,7 @@ _ecore_evas_x_event_mouse_move(void *data __UNUSED__, int type __UNUSED__, void { Ecore_Evas *ee; Ecore_X_Event_Mouse_Move *e; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ @@ -651,16 +748,16 @@ _ecore_evas_x_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *e { Ecore_Evas *ee; Ecore_X_Event_Mouse_In *e; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ if (e->win != ee->engine.x.win) return 1; -/* - { +/* + { time_t t; char *ct; - + const char *modes[] = { "MODE_NORMAL", "MODE_WHILE_GRABBED", @@ -687,8 +784,8 @@ _ecore_evas_x_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *e details[e->detail]); } */ -// disable. causes mroe problems than it fixes -// if ((e->mode == ECORE_X_EVENT_MODE_GRAB) || +// disable. causes mroe problems than it fixes +// if ((e->mode == ECORE_X_EVENT_MODE_GRAB) || // (e->mode == ECORE_X_EVENT_MODE_UNGRAB)) // return 0; /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */ @@ -704,16 +801,16 @@ _ecore_evas_x_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void * { Ecore_Evas *ee; Ecore_X_Event_Mouse_Out *e; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ if (e->win != ee->engine.x.win) return 1; -/* - { +/* + { time_t t; char *ct; - + const char *modes[] = { "MODE_NORMAL", "MODE_WHILE_GRABBED", @@ -739,13 +836,13 @@ _ecore_evas_x_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void * modes[e->mode], details[e->detail]); } - */ -// disable. causes more problems than it fixes -// if ((e->mode == ECORE_X_EVENT_MODE_GRAB) || + */ +// disable. causes more problems than it fixes +// if ((e->mode == ECORE_X_EVENT_MODE_GRAB) || // (e->mode == ECORE_X_EVENT_MODE_UNGRAB)) // return 0; /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */ - _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); _ecore_evas_x_mouse_move_process(ee, e->x, e->y, e->time); evas_event_feed_mouse_out(ee->evas, e->time, NULL); if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee); @@ -758,7 +855,7 @@ _ecore_evas_x_event_window_focus_in(void *data __UNUSED__, int type __UNUSED__, { Ecore_Evas *ee; Ecore_X_Event_Window_Focus_In *e; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ @@ -773,7 +870,7 @@ _ecore_evas_x_event_window_focus_out(void *data __UNUSED__, int type __UNUSED__, { Ecore_Evas *ee; Ecore_X_Event_Window_Focus_Out *e; - + e = event; ee = _ecore_evas_x_match(e->win); if ((!ee) || (ee->ignore_events)) return 1; /* pass on event */ @@ -798,40 +895,44 @@ _ecore_evas_x_event_window_damage(void *data __UNUSED__, int type __UNUSED__, vo if (ee->engine.x.using_bg_pixmap) return 1; if (ee->prop.avoid_damage) { - XRectangle xr; - Region tmpr; - +#ifdef HAVE_ECORE_X_XCB +#warning [XCB] No Region code +#else + Ecore_X_Rectangle rect; + Ecore_X_Region tmpr; + if (!ee->engine.x.damages) ee->engine.x.damages = XCreateRegion(); tmpr = XCreateRegion(); - xr.x = e->x; - xr.y = e->y; - xr.width = e->w; - xr.height = e->h; - XUnionRectWithRegion(&xr, ee->engine.x.damages, tmpr); + rect.x = e->x; + rect.y = e->y; + rect.width = e->w; + rect.height = e->h; + XUnionRectWithRegion(&rect, ee->engine.x.damages, tmpr); XDestroyRegion(ee->engine.x.damages); ee->engine.x.damages = tmpr; +#endif /* HAVE_ECORE_X_XCB */ } else { if (ee->rotation == 0) - evas_damage_rectangle_add(ee->evas, - e->x, - e->y, + evas_damage_rectangle_add(ee->evas, + e->x, + e->y, e->w, e->h); else if (ee->rotation == 90) - evas_damage_rectangle_add(ee->evas, - ee->h - e->y - e->h, - e->x, + evas_damage_rectangle_add(ee->evas, + ee->h - e->y - e->h, + e->x, e->h, e->w); else if (ee->rotation == 180) - evas_damage_rectangle_add(ee->evas, - ee->w - e->x - e->w, - ee->h - e->y - e->h, + evas_damage_rectangle_add(ee->evas, + ee->w - e->x - e->w, + ee->h - e->y - e->h, e->w, e->h); else if (ee->rotation == 270) - evas_damage_rectangle_add(ee->evas, - e->y, - ee->w - e->x - e->w, + evas_damage_rectangle_add(ee->evas, + e->y, + ee->w - e->x - e->w, e->h, e->w); } return 1; @@ -842,7 +943,7 @@ _ecore_evas_x_event_window_destroy(void *data __UNUSED__, int type __UNUSED__, v { Ecore_Evas *ee; Ecore_X_Event_Window_Destroy *e; - + e = event; ee = _ecore_evas_x_match(e->win); if (!ee) return 1; /* pass on event */ @@ -857,20 +958,20 @@ _ecore_evas_x_event_window_configure(void *data __UNUSED__, int type __UNUSED__, { Ecore_Evas *ee; Ecore_X_Event_Window_Configure *e; - + e = event; ee = _ecore_evas_x_match(e->win); if (!ee) return 1; /* pass on event */ if (e->win != ee->engine.x.win) return 1; if (ee->engine.x.direct_resize) return 1; - + if ((e->from_wm) || (ee->prop.override)) { if ((ee->x != e->x) || (ee->y != e->y)) { ee->x = e->x; ee->y = e->y; - if (ee->func.fn_move) ee->func.fn_move(ee); + if (ee->func.fn_move) ee->func.fn_move(ee); } } if ((ee->w != e->w) || (ee->h != e->h)) @@ -904,7 +1005,7 @@ _ecore_evas_x_event_window_configure(void *data __UNUSED__, int type __UNUSED__, ee->expecting_resize.w = 0; ee->expecting_resize.h = 0; } - if (ee->func.fn_resize) ee->func.fn_resize(ee); + if (ee->func.fn_resize) ee->func.fn_resize(ee); } return 1; } @@ -914,7 +1015,7 @@ _ecore_evas_x_event_window_delete_request(void *data __UNUSED__, int type __UNUS { Ecore_Evas *ee; Ecore_X_Event_Window_Delete_Request *e; - + e = event; ee = _ecore_evas_x_match(e->win); if (!ee) return 1; /* pass on event */ @@ -928,7 +1029,7 @@ _ecore_evas_x_event_window_show(void *data __UNUSED__, int type __UNUSED__, void { Ecore_Evas *ee; Ecore_X_Event_Window_Show *e; - + e = event; ee = _ecore_evas_x_match(e->win); if (!ee) return 1; /* pass on event */ @@ -944,7 +1045,7 @@ _ecore_evas_x_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void { Ecore_Evas *ee; Ecore_X_Event_Window_Hide *e; - + e = event; ee = _ecore_evas_x_match(e->win); if (!ee) return 1; /* pass on event */ @@ -956,9 +1057,14 @@ _ecore_evas_x_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void } /* FIXME, should be in idler */ +/* FIXME, round trip */ static void _ecore_evas_x_size_pos_hints_update(Ecore_Evas *ee) { +# ifdef HAVE_ECORE_X_XCB + ecore_x_icccm_size_pos_hints_get_prefetch(ee->engine.x.win); + ecore_x_icccm_size_pos_hints_get_fetch(); +# endif /* HAVE_ECORE_X_XCB */ ecore_x_icccm_size_pos_hints_set(ee->engine.x.win, ee->prop.request_pos /*request_pos */, ECORE_X_GRAVITY_NW /* gravity */, @@ -972,6 +1078,9 @@ _ecore_evas_x_size_pos_hints_update(Ecore_Evas *ee) ee->prop.step.h /* step_y */, 0 /* min_aspect */, 0 /* max_aspect */); +# ifdef HAVE_ECORE_X_XCB + ecore_xcb_reply_free(); +# endif /* HAVE_ECORE_X_XCB */ } /* FIXME, should be in idler */ @@ -1120,7 +1229,7 @@ _ecore_evas_x_idle_enter(void *data __UNUSED__) for (l = (Ecore_List2 *)ecore_evases; l; l = l->next) { Ecore_Evas *ee; - + ee = (Ecore_Evas *)l; _ecore_evas_x_render(ee); } @@ -1168,16 +1277,24 @@ _ecore_evas_x_free(Ecore_Evas *ee) if (ee->engine.x.pmap) ecore_x_pixmap_del(ee->engine.x.pmap); if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); if (ee->engine.x.gc) ecore_x_gc_del(ee->engine.x.gc); +#ifdef HAVE_ECORE_X_XCB +#warning [XCB] No Region code +#else if (ee->engine.x.damages) XDestroyRegion(ee->engine.x.damages); +#endif /* HAVE_ECORE_X_XCB */ ee->engine.x.pmap = 0; ee->engine.x.mask = 0; ee->engine.x.gc = 0; +#ifdef HAVE_ECORE_X_XCB +#warning [XCB] No Region code +#else ee->engine.x.damages = 0; +#endif /* HAVE_ECORE_X_XCB */ ecore_evases_hash = evas_hash_del(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win), ee); while (ee->engine.x.win_extra) { Ecore_X_Window *winp; - + winp = ee->engine.x.win_extra->data; ee->engine.x.win_extra = evas_list_remove_list(ee->engine.x.win_extra, ee->engine.x.win_extra); ecore_evases_hash = evas_hash_del(ecore_evases_hash, _ecore_evas_x_winid_str_get(*winp), ee); @@ -1188,14 +1305,22 @@ _ecore_evas_x_free(Ecore_Evas *ee) ecore_x_shutdown(); } +/* FIXME: round trip */ static void _ecore_evas_x_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) { +#ifdef HAVE_ECORE_X_XCB + ecore_x_icccm_protocol_get_prefetch(ee->engine.x.win); + ecore_x_icccm_protocol_get_fetch(); +#endif /* HAVE_ECORE_X_XCB */ if (func) ecore_x_icccm_protocol_set(ee->engine.x.win, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 1); else ecore_x_icccm_protocol_set(ee->engine.x.win, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 0); ee->func.fn_delete_request = func; +#ifdef HAVE_ECORE_X_XCB + ecore_xcb_reply_free(); +#endif /* HAVE_ECORE_X_XCB */ } static void @@ -1296,7 +1421,7 @@ _ecore_evas_x_move_resize(Ecore_Evas *ee, int x, int y, int w, int h) if ((ee->w != w) || (ee->h != h) || (x != ee->x) || (y != ee->y)) { int change_size = 0, change_pos = 0; - + if ((ee->w != w) || (ee->h != h)) change_size = 1; if (!ee->engine.x.managed) { @@ -1354,22 +1479,28 @@ static void _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation) { int rot_dif; - - if (ee->rotation == rotation) return; + + if (ee->rotation == rotation) return; if (!strcmp(ee->driver, "gl_x11")) return; rot_dif = ee->rotation - rotation; if (rot_dif < 0) rot_dif = -rot_dif; if (!strcmp(ee->driver, "software_x11")) - { + { #ifdef BUILD_ECORE_X +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_Software_Xcb *einfo; + + einfo = (Evas_Engine_Info_Software_Xcb *)evas_engine_info_get(ee->evas); +#else Evas_Engine_Info_Software_X11 *einfo; - + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); +#endif /* HAVE_ECORE_X_XCB */ if (!einfo) return; if (rot_dif != 180) { int minw, minh, maxw, maxh, basew, baseh, stepw, steph; - + einfo->info.rotation = rotation; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); if (!ee->prop.fullscreen) @@ -1381,7 +1512,7 @@ _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation) else { int w, h; - + ecore_x_window_size_get(ee->engine.x.win, &w, &h); ecore_x_window_resize(ee->engine.x.win, h, w); if ((rotation == 0) || (rotation == 180)) @@ -1394,7 +1525,7 @@ _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation) evas_output_size_set(ee->evas, ee->h, ee->w); evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); } - if (ee->func.fn_resize) ee->func.fn_resize(ee); + if (ee->func.fn_resize) ee->func.fn_resize(ee); } ecore_evas_size_min_get(ee, &minw, &minh); ecore_evas_size_max_get(ee, &maxw, &maxh); @@ -1415,13 +1546,13 @@ _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation) ee->rotation = rotation; _ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, ecore_x_current_time_get()); - if (ee->func.fn_resize) ee->func.fn_resize(ee); + if (ee->func.fn_resize) ee->func.fn_resize(ee); } if ((ee->rotation == 90) || (ee->rotation == 270)) evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w); else evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); -#endif +#endif /* BUILD_ECORE_X */ } } @@ -1433,25 +1564,55 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped) if (!strcmp(ee->driver, "software_x11")) { #ifdef BUILD_ECORE_X +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_Software_Xcb *einfo; + + einfo = (Evas_Engine_Info_Software_Xcb *)evas_engine_info_get(ee->evas); +#else Evas_Engine_Info_Software_X11 *einfo; - - ee->shaped = shaped; + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); +#endif /* HAVE_ECORE_X_XCB */ + + ee->shaped = shaped; if (einfo) { if (ee->shaped) { +# ifdef HAVE_ECORE_X_XCB + xcb_rectangle_t rectangle; + Ecore_X_GC gc; + uint32_t value_list; +#else GC gc; XGCValues gcv; - +#endif /* HAVE_ECORE_X_XCB */ + ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1); +# ifdef HAVE_ECORE_X_XCB + gc = xcb_generate_id(ecore_x_connection_get()); + value_list = 0; + xcb_create_gc(ecore_x_connection_get(), + gc, ee->engine.x.mask, + XCB_GC_FOREGROUND, + &value_list); + rectangle.x = 0; + rectangle.y = 0; + rectangle.width = ee->w; + rectangle.height = ee->h; + xcb_poly_fill_rectangle(ecore_x_connection_get(), + ee->engine.x.mask, gc, + 1, &rectangle); + xcb_free_gc(ecore_x_connection_get(), gc); +# else gcv.foreground = 0; - gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, + gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, GCForeground, &gcv); XFillRectangle(ecore_x_display_get(), ee->engine.x.mask, gc, 0, 0, ee->w, ee->h); XFreeGC(ecore_x_display_get(), gc); +# endif /* HAVE_ECORE_X_XCB */ einfo->info.mask = ee->engine.x.mask; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); @@ -1465,30 +1626,61 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped) ecore_x_window_shape_mask_set(ee->engine.x.win, 0); } } -#endif +#endif /* BUILD_ECORE_X */ } else if (!strcmp(ee->driver, "xrender_x11")) { #ifdef BUILD_ECORE_EVAS_XRENDER +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_XRender_Xcb *einfo; +# else Evas_Engine_Info_XRender_X11 *einfo; - +# endif /* HAVE_ECORE_X_XCB */ + ee->shaped = shaped; +# ifdef HAVE_ECORE_X_XCB + einfo = (Evas_Engine_Info_XRender_Xcb *)evas_engine_info_get(ee->evas); +# else einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas); +# endif /* HAVE_ECORE_X_XCB */ if (einfo) { if (ee->shaped) { +# ifdef HAVE_ECORE_X_XCB + xcb_rectangle_t rectangle; + Ecore_X_GC gc; + uint32_t value_list; +# else GC gc; XGCValues gcv; - +# endif /* HAVE_ECORE_X_XCB */ + ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1); +# ifdef HAVE_ECORE_X_XCB + gc = xcb_generate_id(ecore_x_connection_get()); + value_list = 0; + xcb_create_gc(ecore_x_connection_get(), + gc, ee->engine.x.mask, + XCB_GC_FOREGROUND, + &value_list); + rectangle.x = 0; + rectangle.y = 0; + rectangle.width = ee->w; + rectangle.height = ee->h; + xcb_poly_fill_rectangle(ecore_x_connection_get(), + ee->engine.x.mask, gc, + 1, &rectangle); + xcb_free_gc(ecore_x_connection_get(), gc); +# else gcv.foreground = 0; - gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, + gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, GCForeground, &gcv); XFillRectangle(ecore_x_display_get(), ee->engine.x.mask, gc, 0, 0, ee->w, ee->h); XFreeGC(ecore_x_display_get(), gc); +# endif /* HAVE_ECORE_X_XCB */ einfo->info.mask = ee->engine.x.mask; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); @@ -1502,10 +1694,11 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped) ecore_x_window_shape_mask_set(ee->engine.x.win, 0); } } -#endif +#endif } } +/* FIXME, round trip */ static void _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) { @@ -1514,13 +1707,26 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) if (!strcmp(ee->driver, "software_x11")) { #ifdef BUILD_ECORE_X +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_Software_Xcb *einfo; + + einfo = (Evas_Engine_Info_Software_Xcb *)evas_engine_info_get(ee->evas); +#else Evas_Engine_Info_Software_X11 *einfo; - + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); +#endif /* HAVE_ECORE_X_XCB */ if (einfo) { +# ifdef HAVE_ECORE_X_XCB + xcb_get_geometry_cookie_t cookie_geom; + xcb_get_window_attributes_cookie_t cookie_attr; + xcb_get_geometry_reply_t *reply_geom; + xcb_get_window_attributes_reply_t *reply_attr; +#else XWindowAttributes att; - +#endif /* HAVE_ECORE_X_XCB */ + ee->shaped = 0; ee->alpha = alpha; ecore_x_window_del(ee->engine.x.win); @@ -1541,10 +1747,20 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) ee->engine.x.win = ecore_x_window_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h); einfo->info.destination_alpha = 0; } +# ifdef HAVE_ECORE_X_XCB + reply_geom = xcb_get_geometry_reply(ecore_x_connection_get(), cookie_geom, NULL); + reply_attr = xcb_get_window_attributes_reply(ecore_x_connection_get(), cookie_attr, NULL); + einfo->info.visual = xcb_visualtype_get(ecore_x_default_screen_get(), reply_attr->visual); + einfo->info.colormap = reply_attr->colormap; + einfo->info.depth = reply_geom->depth; + free(reply_geom); + free(reply_attr); +# else XGetWindowAttributes(ecore_x_display_get(), ee->engine.x.win, &att); einfo->info.visual = att.visual; einfo->info.colormap = att.colormap; einfo->info.depth = att.depth; +# endif /* HAVE_ECORE_X_XCB */ if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); ee->engine.x.mask = 0; einfo->info.mask = 0; @@ -1558,18 +1774,31 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) if (ee->visible) ecore_x_window_show(ee->engine.x.win); if (ee->prop.focused) ecore_x_window_focus(ee->engine.x.win); } -#endif +#endif /* BUILD_ECORE_X */ } else if (!strcmp(ee->driver, "xrender_x11")) { #ifdef BUILD_ECORE_EVAS_XRENDER +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_XRender_Xcb *einfo; + + einfo = (Evas_Engine_Info_XRender_Xcb *)evas_engine_info_get(ee->evas); +# else Evas_Engine_Info_XRender_X11 *einfo; - + einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas); +# endif /* HAVE_ECORE_X_XCB */ if (einfo) { +# ifdef HAVE_ECORE_X_XCB + xcb_get_window_attributes_cookie_t cookie_attr; + xcb_get_window_attributes_reply_t *reply_attr; + + cookie_attr = xcb_get_window_attributes_unchecked(ecore_x_connection_get(), ee->engine.x.win); +# else XWindowAttributes att; - +# endif /* HAVE_ECORE_X_XCB */ + ee->shaped = 0; ee->alpha = alpha; ecore_x_window_del(ee->engine.x.win); @@ -1590,8 +1819,15 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) ee->engine.x.win = ecore_x_window_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h); einfo->info.destination_alpha = 0; } +# ifdef HAVE_ECORE_X_XCB + reply_attr = xcb_get_window_attributes_reply(ecore_x_connection_get(), cookie_attr, NULL); + + einfo->info.visual = reply_attr->visual; + free(reply_attr); +# else XGetWindowAttributes(ecore_x_display_get(), ee->engine.x.win, &att); einfo->info.visual = att.visual; +# endif /* HAVE_ECORE_X_XCB */ if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); ee->engine.x.mask = 0; einfo->info.mask = 0; @@ -1605,7 +1841,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) if (ee->visible) ecore_x_window_show(ee->engine.x.win); if (ee->prop.focused) ecore_x_window_focus(ee->engine.x.win); } -#endif +#endif } } @@ -1715,7 +1951,7 @@ static void _ecore_evas_x_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y) { int x, y; - + if (!file) { if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object); @@ -1734,11 +1970,11 @@ _ecore_evas_x_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, ee->prop.cursor.file = strdup(file); ee->prop.cursor.layer = layer; ee->prop.cursor.hot.x = hot_x; - ee->prop.cursor.hot.y = hot_y; + ee->prop.cursor.hot.y = hot_y; evas_pointer_output_xy_get(ee->evas, &x, &y); evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer); evas_object_color_set(ee->prop.cursor.object, 255, 255, 255, 255); - evas_object_move(ee->prop.cursor.object, + evas_object_move(ee->prop.cursor.object, x - ee->prop.cursor.hot.x, y - ee->prop.cursor.hot.y); evas_object_image_file_set(ee->prop.cursor.object, ee->prop.cursor.file, NULL); @@ -1799,7 +2035,7 @@ _ecore_evas_x_iconified_set(Ecore_Evas *ee, int on) } else { - ecore_x_icccm_hints_set(ee->engine.x.win, + ecore_x_icccm_hints_set(ee->engine.x.win, 1 /* accepts_focus */, ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */, 0 /* icon_pixmap */, @@ -1856,7 +2092,7 @@ _ecore_evas_x_sticky_set(Ecore_Evas *ee, int sticky) * the sticky callback not to get called. Its set on the * property change event. * ee->prop.sticky = sticky; - */ + */ ee->engine.x.state.sticky = sticky; if (ee->should_be_visible) ecore_x_netwm_state_request_send(ee->engine.x.win, ee->engine.x.win_root, @@ -1893,40 +2129,40 @@ _ecore_evas_x_reinit_win(Ecore_Evas *ee) { #ifdef BUILD_ECORE_X Evas_Engine_Info_Software_X11 *einfo; - + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); if (einfo) { einfo->info.drawable = ee->engine.x.win; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); } -#endif +#endif } else if (!strcmp(ee->driver, "xrender_x11")) { #ifdef BUILD_ECORE_EVAS_XRENDER Evas_Engine_Info_XRender_X11 *einfo; - + einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas); if (einfo) { einfo->info.drawable = ee->engine.x.win; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); } -#endif +#endif } else if (!strcmp(ee->driver, "gl_x11")) { #ifdef BUILD_ECORE_EVAS_GL Evas_Engine_Info_GL_X11 *einfo; - + einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas); if (einfo) { einfo->info.drawable = ee->engine.x.win; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); } -#endif +#endif } } */ @@ -1962,14 +2198,22 @@ _ecore_evas_x_fullscreen_set(Ecore_Evas *ee, int on) static void _ecore_evas_x_avoid_damage_set(Ecore_Evas *ee, int on) { +#ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_Software_Xcb *einfo; +#else Evas_Engine_Info_Software_X11 *einfo; +#endif /* HAVE_ECORE_X_XCB */ if (((ee->prop.avoid_damage) && (on)) || ((!ee->prop.avoid_damage) && (!on))) return; if (!strcmp(ee->driver, "gl_x11")) return; - ee->prop.avoid_damage = on; + ee->prop.avoid_damage = on; +#ifdef HAVE_ECORE_X_XCB + einfo = (Evas_Engine_Info_Software_Xcb *)evas_engine_info_get(ee->evas); +#else einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); +#endif /* HAVE_ECORE_X_XCB */ if (einfo) { if (ee->prop.avoid_damage) @@ -1984,7 +2228,7 @@ _ecore_evas_x_avoid_damage_set(Ecore_Evas *ee, int on) evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); if (ee->engine.x.direct_resize) { -/* Turn this off for now +/* Turn this off for now ee->engine.x.using_bg_pixmap = 1; ecore_x_window_pixmap_set(ee->engine.x.win, ee->engine.x.pmap); */ @@ -2014,7 +2258,7 @@ _ecore_evas_x_shutdown(void) if (_ecore_evas_init_count == 0) { int i; - + while (ecore_evases) _ecore_evas_free(ecore_evases); for (i = 0; i < 16; i++) ecore_event_handler_del(ecore_evas_event_handlers[i]); @@ -2075,35 +2319,52 @@ static const Ecore_Evas_Engine_Func _ecore_x_engine_func = }; #endif +/* + * FIXME: there are some round trips. Especially, we can split + * ecore_x_init in 2 functions and supress some round trips. + */ + /** * To be documented. * * FIXME: To be fixed. */ EAPI Ecore_Evas * -ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, +ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h) { #ifdef BUILD_ECORE_X +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_Software_Xcb *einfo; +# else Evas_Engine_Info_Software_X11 *einfo; +# endif /* HAVE_ECORE_X_XCB */ Ecore_Evas *ee; int argb = 0; int rmethod; static int redraw_debug = -1; +# ifdef HAVE_ECORE_X_XCB + rmethod = evas_render_method_lookup("software_xcb"); +# else rmethod = evas_render_method_lookup("software_x11"); +# endif /* HAVE_ECORE_X_XCB */ if (!rmethod) return NULL; if (!ecore_x_init(disp_name)) return NULL; ee = calloc(1, sizeof(Ecore_Evas)); if (!ee) return NULL; - + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); - + _ecore_evas_x_init(); - + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func; - + +# ifdef HAVE_ECORE_X_XCB + ee->driver = "software_xcb"; +# else ee->driver = "software_x11"; +# endif /* HAVE_ECORE_X_XCB */ if (disp_name) ee->name = strdup(disp_name); if (w < 1) w = 1; @@ -2112,14 +2373,14 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, ee->y = y; ee->w = w; ee->h = h; - + ee->prop.max.w = 32767; ee->prop.max.h = 32767; ee->prop.layer = 4; ee->prop.request_pos = 0; ee->prop.sticky = 0; ee->engine.x.state.sticky = 0; - + /* init evas here */ ee->evas = evas_new(); evas_data_attach_set(ee->evas, ee); @@ -2130,6 +2391,7 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, ee->engine.x.win_root = parent; if (parent != 0) { + /* FIXME: round trip in ecore_x_window_argb_get */ if (ecore_x_window_argb_get(parent)) { ee->engine.x.win = ecore_x_window_argb_new(parent, x, y, w, h); @@ -2145,28 +2407,76 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, ecore_x_netwm_startup_id_set(ee->engine.x.win, getenv("DESKTOP_STARTUP_ID")); /* NB: on linux this may simply empty the env as opposed to completely - * unset it to being empty - unsure as solartis libc crashes looking + * unset it to being empty - unsure as solartis libc crashes looking * for the '=' char */ putenv((char*)"DESKTOP_STARTUP_ID="); } +# ifdef HAVE_ECORE_X_XCB + einfo = (Evas_Engine_Info_Software_Xcb *)evas_engine_info_get(ee->evas); +# else einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); +# endif /* HAVE_ECORE_X_XCB */ if (einfo) { +# ifdef HAVE_ECORE_X_XCB + xcb_screen_iterator_t iter; + xcb_screen_t *screen; +# else int screen; +# endif /* HAVE_ECORE_X_XCB */ /* FIXME: this is inefficient as its a round trip */ +# ifdef HAVE_ECORE_X_XCB + screen = ecore_x_default_screen_get(); + iter = xcb_setup_roots_iterator (xcb_get_setup (ecore_x_connection_get())); + if (iter.rem > 1) + { + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + Ecore_X_Window *roots; + int num; + uint8_t i; + + num = 0; + cookie = xcb_get_geometry_unchecked(ecore_x_connection_get(), parent); + roots = ecore_x_window_root_list(&num); + if (roots) + { + reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL); + + if (reply) + { + for (i = 0; i < num; xcb_screen_next (&iter), i++) + { + if (reply->root == roots[i]) + { + screen = iter.data; + break; + } + } + free(reply); + } + free(roots); + } + else + { + reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL); + if (reply) free(reply); + } + } +# else screen = DefaultScreen(ecore_x_display_get()); if (ScreenCount(ecore_x_display_get()) > 1) { Ecore_X_Window *roots; int num, i; - + num = 0; roots = ecore_x_window_root_list(&num); if (roots) { XWindowAttributes at; - + if (XGetWindowAttributes(ecore_x_display_get(), parent, &at)) { @@ -2182,7 +2492,8 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, free(roots); } } - +# endif /* HAVE_ECORE_X_XCB */ + if (redraw_debug < 0) { if (getenv("REDRAW_DEBUG")) @@ -2190,12 +2501,39 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, else redraw_debug = 0; } +# ifdef HAVE_ECORE_X_XCB + einfo->info.conn = ecore_x_connection_get(); + einfo->info.screen = screen; +# else einfo->info.display = ecore_x_display_get(); +# endif /* HAVE_ECORE_X_XCB */ einfo->info.drawable = ee->engine.x.win; if (argb) { + /* FIXME: round trip */ +# ifdef HAVE_ECORE_X_XCB + xcb_get_geometry_cookie_t cookie_geom; + xcb_get_window_attributes_cookie_t cookie_attr; + xcb_get_geometry_reply_t *reply_geom; + xcb_get_window_attributes_reply_t *reply_attr; + + cookie_geom = xcb_get_geometry_unchecked(ecore_x_connection_get(), ee->engine.x.win); + cookie_attr = xcb_get_window_attributes_unchecked(ecore_x_connection_get(), ee->engine.x.win); + + reply_geom = xcb_get_geometry_reply(ecore_x_connection_get(), cookie_geom, NULL); + reply_attr = xcb_get_window_attributes_reply(ecore_x_connection_get(), cookie_attr, NULL); + if (reply_attr && reply_geom) + { + einfo->info.visual = xcb_visualtype_get(ecore_x_default_screen_get(), reply_attr->visual); + einfo->info.colormap = reply_attr->colormap; + einfo->info.depth = reply_geom->depth; + einfo->info.destination_alpha = 1; + free(reply_geom); + free(reply_attr); + } +# else XWindowAttributes at; - + if (XGetWindowAttributes(ecore_x_display_get(), ee->engine.x.win, &at)) { @@ -2204,12 +2542,22 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, einfo->info.depth = at.depth; einfo->info.destination_alpha = 1; } +# endif /* HAVE_ECORE_X_XCB */ } else { +# ifdef HAVE_ECORE_X_XCB + xcb_screen_t *screen; + + screen = ecore_x_default_screen_get(); + einfo->info.visual = xcb_visualtype_get(screen, screen->root_visual); + einfo->info.colormap = screen->default_colormap; + einfo->info.depth = screen->root_depth; +#else einfo->info.visual = DefaultVisual(ecore_x_display_get(), screen); einfo->info.colormap = DefaultColormap(ecore_x_display_get(), screen); einfo->info.depth = DefaultDepth(ecore_x_display_get(), screen); +# endif /* HAVE_ECORE_X_XCB */ einfo->info.destination_alpha = 0; } einfo->info.rotation = 0; @@ -2231,7 +2579,7 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, return ee; #else return NULL; -#endif +#endif /* BUILD_ECORE_X */ } /** @@ -2246,7 +2594,7 @@ ecore_evas_software_x11_window_get(Ecore_Evas *ee) return ee->engine.x.win; #else return 0; -#endif +#endif } /** @@ -2261,7 +2609,7 @@ ecore_evas_software_x11_subwindow_get(Ecore_Evas *ee) return ee->engine.x.win; #else return 0; -#endif +#endif } /** @@ -2278,7 +2626,7 @@ ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee, int on) { if (ee->engine.x.direct_resize) { -/* turn this off for now +/* turn this off for now ee->engine.x.using_bg_pixmap = 1; ecore_x_window_pixmap_set(ee->engine.x.win, ee->engine.x.pmap); */ @@ -2292,7 +2640,7 @@ ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee, int on) } #else return; -#endif +#endif } /** @@ -2307,7 +2655,7 @@ ecore_evas_software_x11_direct_resize_get(Ecore_Evas *ee) return ee->engine.x.direct_resize; #else return 0; -#endif +#endif } /** @@ -2320,7 +2668,7 @@ ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window wi { #ifdef BUILD_ECORE_X Ecore_X_Window *winp; - + winp = malloc(sizeof(Ecore_X_Window)); if (winp) { @@ -2329,7 +2677,7 @@ ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window wi ecore_evases_hash = evas_hash_add(ecore_evases_hash, _ecore_evas_x_winid_str_get(win), ee); } #else -#endif +#endif } /** @@ -2338,10 +2686,13 @@ ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window wi * FIXME: To be fixed. */ EAPI Ecore_Evas * -ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, +ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h) { -#ifdef BUILD_ECORE_EVAS_GL +#ifdef BUILD_ECORE_EVAS_GL +# ifdef HAVE_ECORE_X_XCB + Ecore_Evas *ee = NULL; +# else Evas_Engine_Info_GL_X11 *einfo; Ecore_Evas *ee; int rmethod; @@ -2351,13 +2702,13 @@ ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, if (!ecore_x_init(disp_name)) return NULL; ee = calloc(1, sizeof(Ecore_Evas)); if (!ee) return NULL; - + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); - + _ecore_evas_x_init(); - + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func; - + ee->driver = "gl_x11"; if (disp_name) ee->name = strdup(disp_name); @@ -2367,14 +2718,14 @@ ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, ee->y = y; ee->w = w; ee->h = h; - + ee->prop.max.w = 32767; ee->prop.max.h = 32767; ee->prop.layer = 4; ee->prop.request_pos = 0; ee->prop.sticky = 0; - ee->engine.x.state.sticky = 0; - + ee->engine.x.state.sticky = 0; + /* init evas here */ ee->evas = evas_new(); evas_data_attach_set(ee->evas, ee); @@ -2395,7 +2746,7 @@ ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, ecore_x_netwm_startup_id_set(ee->engine.x.win, getenv("DESKTOP_STARTUP_ID")); /* NB: on linux this may simply empty the env as opposed to completely - * unset it to being empty - unsure as solartis libc crashes looking + * unset it to being empty - unsure as solartis libc crashes looking * for the '=' char */ putenv((char*)"DESKTOP_STARTUP_ID="); } @@ -2411,6 +2762,8 @@ ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, ecore_evases = _ecore_list2_prepend(ecore_evases, ee); ecore_evases_hash = evas_hash_add(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win), ee); +# endif /* HAVE_ECORE_X_XCB */ + return ee; #else disp_name = NULL; @@ -2447,7 +2800,7 @@ ecore_evas_gl_x11_subwindow_get(Ecore_Evas *ee) return ee->engine.x.win; #else return 0; -#endif +#endif } /** @@ -2462,7 +2815,7 @@ ecore_evas_gl_x11_direct_resize_set(Ecore_Evas *ee, int on) ee->engine.x.direct_resize = on; #else return; -#endif +#endif } /** @@ -2477,7 +2830,7 @@ ecore_evas_gl_x11_direct_resize_get(Ecore_Evas *ee) return ee->engine.x.direct_resize; #else return 0; -#endif +#endif } /** @@ -2497,27 +2850,39 @@ ecore_evas_gl_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win) * FIXME: To be fixed. */ EAPI Ecore_Evas * -ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, +ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h) { #ifdef BUILD_ECORE_EVAS_XRENDER +# ifdef HAVE_ECORE_X_XCB + Evas_Engine_Info_XRender_Xcb *einfo; +# else Evas_Engine_Info_XRender_X11 *einfo; +# endif /* HAVE_ECORE_X_XCB */ Ecore_Evas *ee; int rmethod; +# ifdef HAVE_ECORE_X_XCB + rmethod = evas_render_method_lookup("xrender_xcb"); +# else rmethod = evas_render_method_lookup("xrender_x11"); +# endif /* HAVE_ECORE_X_XCB */ if (!rmethod) return NULL; if (!ecore_x_init(disp_name)) return NULL; ee = calloc(1, sizeof(Ecore_Evas)); if (!ee) return NULL; - + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); - + _ecore_evas_x_init(); - + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func; - + +# ifdef HAVE_ECORE_X_XCB + ee->driver = "xrender_xcb"; +# else ee->driver = "xrender_x11"; +# endif /* HAVE_ECORE_X_XCB */ if (disp_name) ee->name = strdup(disp_name); if (w < 1) w = 1; @@ -2526,21 +2891,21 @@ ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, ee->y = y; ee->w = w; ee->h = h; - + ee->prop.max.w = 32767; ee->prop.max.h = 32767; ee->prop.layer = 4; ee->prop.request_pos = 0; ee->prop.sticky = 0; - ee->engine.x.state.sticky = 0; - + ee->engine.x.state.sticky = 0; + /* init evas here */ ee->evas = evas_new(); evas_data_attach_set(ee->evas, ee); evas_output_method_set(ee->evas, rmethod); evas_output_size_set(ee->evas, w, h); evas_output_viewport_set(ee->evas, 0, 0, w, h); - + ee->engine.x.win_root = parent; ee->engine.x.win = ecore_x_window_new(parent, x, y, w, h); if (getenv("DESKTOP_STARTUP_ID")) @@ -2548,13 +2913,64 @@ ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, ecore_x_netwm_startup_id_set(ee->engine.x.win, getenv("DESKTOP_STARTUP_ID")); /* NB: on linux this may simply empty the env as opposed to completely - * unset it to being empty - unsure as solartis libc crashes looking + * unset it to being empty - unsure as solartis libc crashes looking * for the '=' char */ putenv((char*)"DESKTOP_STARTUP_ID="); } +# ifdef HAVE_ECORE_X_XCB + einfo = (Evas_Engine_Info_XRender_Xcb *)evas_engine_info_get(ee->evas); +# else einfo = (Evas_Engine_Info_XRender_X11 *)evas_engine_info_get(ee->evas); +# endif /* HAVE_ECORE_X_XCB */ if (einfo) { +# ifdef HAVE_ECORE_X_XCB + xcb_screen_iterator_t iter; + xcb_screen_t *screen; + + /* FIXME: this is inefficient as its a round trip */ + screen = ecore_x_default_screen_get(); + iter = xcb_setup_roots_iterator (xcb_get_setup (ecore_x_connection_get())); + if (iter.rem > 1) + { + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + Ecore_X_Window *roots; + int num; + uint8_t i; + + num = 0; + cookie = xcb_get_geometry_unchecked(ecore_x_connection_get(), parent); + roots = ecore_x_window_root_list(&num); + if (roots) + { + reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL); + + if (reply) + { + for (i = 0; i < num; xcb_screen_next (&iter), i++) + { + if (reply->root == roots[i]) + { + screen = iter.data; + break; + } + } + free(reply); + } + free(roots); + } + else + { + reply = xcb_get_geometry_reply(ecore_x_connection_get(), cookie, NULL); + if (reply) free(reply); + } + } + einfo->info.conn = ecore_x_connection_get(); + /* FIXME: uncomment that once the XCB render engine has that member */ +/* einfo->info.screen = screen; */ + einfo->info.visual = screen->root_visual; +# else int screen; /* FIXME: this is inefficient as its a round trip */ @@ -2563,13 +2979,13 @@ ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, { Ecore_X_Window *roots; int num, i; - + num = 0; roots = ecore_x_window_root_list(&num); if (roots) { XWindowAttributes at; - + if (XGetWindowAttributes(ecore_x_display_get(), parent, &at)) { @@ -2587,6 +3003,7 @@ ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, } einfo->info.display = ecore_x_display_get(); einfo->info.visual = DefaultVisual(ecore_x_display_get(), screen); +# endif /* HAVE_ECORE_X_XCB */ einfo->info.drawable = ee->engine.x.win; evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); } @@ -2616,7 +3033,7 @@ ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent, EAPI Ecore_X_Window ecore_evas_xrender_x11_window_get(Ecore_Evas *ee) { -#ifdef BUILD_ECORE_X +#ifdef BUILD_ECORE_X return ee->engine.x.win; #else return 0; @@ -2635,7 +3052,7 @@ ecore_evas_xrender_x11_subwindow_get(Ecore_Evas *ee) return ee->engine.x.win; #else return 0; -#endif +#endif } /** @@ -2650,7 +3067,7 @@ ecore_evas_xrender_x11_direct_resize_set(Ecore_Evas *ee, int on) ee->engine.x.direct_resize = on; #else return; -#endif +#endif } /** @@ -2665,7 +3082,7 @@ ecore_evas_xrender_x11_direct_resize_get(Ecore_Evas *ee) return ee->engine.x.direct_resize; #else return 0; -#endif +#endif } /** @@ -2678,4 +3095,3 @@ ecore_evas_xrender_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window win { ecore_evas_software_x11_extra_event_window_add(ee, win); } - diff --git a/legacy/ecore/src/lib/ecore_x/Ecore_X.h b/legacy/ecore/src/lib/ecore_x/Ecore_X.h index 070b40f1c8..16b8006892 100644 --- a/legacy/ecore/src/lib/ecore_x/Ecore_X.h +++ b/legacy/ecore/src/lib/ecore_x/Ecore_X.h @@ -40,19 +40,30 @@ * @li @ref Ecore_X_Flush_Group */ + typedef unsigned int Ecore_X_ID; -#ifndef _ECORE_X_WINDOW_PREDEF +# ifndef _ECORE_X_WINDOW_PREDEF typedef Ecore_X_ID Ecore_X_Window; -#endif +# endif +#ifdef HAVE_ECORE_X_XCB +typedef Ecore_X_ID Ecore_X_Visual; +#else typedef void * Ecore_X_Visual; +#endif /* HAVE_ECORE_X_XCB */ typedef Ecore_X_ID Ecore_X_Pixmap; typedef Ecore_X_ID Ecore_X_Drawable; +#ifdef HAVE_ECORE_X_XCB +typedef Ecore_X_ID Ecore_X_GC; +#else typedef void * Ecore_X_GC; +#endif /* HAVE_ECORE_X_XCB */ typedef Ecore_X_ID Ecore_X_Atom; typedef Ecore_X_ID Ecore_X_Colormap; typedef Ecore_X_ID Ecore_X_Time; typedef Ecore_X_ID Ecore_X_Cursor; typedef void Ecore_X_Display; +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; @@ -972,7 +983,9 @@ EAPI int ecore_x_init(const char *name); EAPI int ecore_x_shutdown(void); EAPI int ecore_x_disconnect(void); EAPI Ecore_X_Display *ecore_x_display_get(void); +EAPI Ecore_X_Connection *ecore_x_connection_get(void); EAPI int ecore_x_fd_get(void); +EAPI Ecore_X_Screen *ecore_x_default_screen_get(void); EAPI void ecore_x_double_click_time_set(double t); EAPI double ecore_x_double_click_time_get(void); EAPI void ecore_x_flush(void); @@ -991,12 +1004,20 @@ EAPI void ecore_x_event_mask_set(Ecore_X_Window w, Ecore_X_Event_Mas EAPI void ecore_x_event_mask_unset(Ecore_X_Window w, Ecore_X_Event_Mask mask); EAPI int ecore_x_selection_notify_send(Ecore_X_Window requestor, Ecore_X_Atom selection, Ecore_X_Atom target, Ecore_X_Atom property, Ecore_X_Time time); +EAPI void ecore_x_selection_primary_prefetch(void); +EAPI void ecore_x_selection_primary_fetch(void); EAPI int ecore_x_selection_primary_set(Ecore_X_Window w, const void *data, int size); EAPI int ecore_x_selection_primary_clear(void); +EAPI void ecore_x_selection_secondary_prefetch(void); +EAPI void ecore_x_selection_secondary_fetch(void); EAPI int ecore_x_selection_secondary_set(Ecore_X_Window w, const void *data, int size); EAPI int ecore_x_selection_secondary_clear(void); +EAPI void ecore_x_selection_xdnd_prefetch(void); +EAPI void ecore_x_selection_xdnd_fetch(void); EAPI int ecore_x_selection_xdnd_set(Ecore_X_Window w, const void *data, int size); EAPI int ecore_x_selection_xdnd_clear(void); +EAPI void ecore_x_selection_clipboard_prefetch(void); +EAPI void ecore_x_selection_clipboard_fetch(void); EAPI int ecore_x_selection_clipboard_set(Ecore_X_Window w, const void *data, int size); EAPI int ecore_x_selection_clipboard_clear(void); EAPI void ecore_x_selection_primary_request(Ecore_X_Window w, const char *target); @@ -1012,10 +1033,16 @@ EAPI void ecore_x_selection_parser_add(const char *target, void *(*f EAPI void ecore_x_selection_parser_del(const char *target); EAPI void ecore_x_dnd_aware_set(Ecore_X_Window win, int on); +EAPI void ecore_x_dnd_version_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_dnd_version_get_fetch(void); EAPI int ecore_x_dnd_version_get(Ecore_X_Window win); +EAPI void ecore_x_dnd_type_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_dnd_type_get_fetch(void); EAPI int ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type); EAPI void ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int on); EAPI void ecore_x_dnd_types_set(Ecore_X_Window win, char **types, unsigned int num_types); +EAPI void ecore_x_dnd_begin_prefetch(Ecore_X_Window source); +EAPI void ecore_x_dnd_begin_fetch(void); EAPI int ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size); EAPI int ecore_x_dnd_drop(void); EAPI void ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action); @@ -1047,6 +1074,8 @@ EAPI void ecore_x_window_resize(Ecore_X_Window win, int w, int h); EAPI void ecore_x_window_move_resize(Ecore_X_Window win, int x, int y, int w, int h); EAPI void ecore_x_window_focus(Ecore_X_Window win); EAPI void ecore_x_window_focus_at_time(Ecore_X_Window win, Ecore_X_Time t); +EAPI void ecore_x_get_input_focus_prefetch(void); +EAPI void ecore_x_get_input_focus_fetch(void); EAPI Ecore_X_Window ecore_x_window_focus_get(void); EAPI void ecore_x_window_raise(Ecore_X_Window win); EAPI void ecore_x_window_lower(Ecore_X_Window win); @@ -1062,6 +1091,8 @@ EAPI int ecore_x_window_visible_get(Ecore_X_Window win); EAPI Ecore_X_Window ecore_x_window_at_xy_get(int x, int y); EAPI Ecore_X_Window ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num); EAPI Ecore_X_Window ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y); +EAPI void ecore_x_query_tree_prefetch(Ecore_X_Window window); +EAPI void ecore_x_query_tree_fetch(void); EAPI Ecore_X_Window ecore_x_window_parent_get(Ecore_X_Window win); EAPI void ecore_x_window_background_color_set(Ecore_X_Window win, @@ -1082,6 +1113,9 @@ EAPI void ecore_x_window_override_set(Ecore_X_Window win, int overri EAPI void ecore_x_window_prop_card32_set(Ecore_X_Window win, Ecore_X_Atom atom, unsigned int *val, unsigned int num); +EAPI void ecore_x_window_prop_card32_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom); +EAPI void ecore_x_window_prop_card32_get_fetch(void); EAPI int ecore_x_window_prop_card32_get(Ecore_X_Window win, Ecore_X_Atom atom, unsigned int *val, unsigned int len); EAPI int ecore_x_window_prop_card32_list_get(Ecore_X_Window win, @@ -1093,6 +1127,10 @@ EAPI void ecore_x_window_prop_xid_set(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_ID * lst, unsigned int num); +EAPI void ecore_x_window_prop_xid_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom, + Ecore_X_Atom type); +EAPI void ecore_x_window_prop_xid_get_fetch(void); EAPI int ecore_x_window_prop_xid_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom type, @@ -1111,6 +1149,9 @@ EAPI void ecore_x_window_prop_atom_set(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom * val, unsigned int num); +EAPI void ecore_x_window_prop_atom_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom); +EAPI void ecore_x_window_prop_atom_get_fetch(void); EAPI int ecore_x_window_prop_atom_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom * val, @@ -1126,6 +1167,9 @@ EAPI void ecore_x_window_prop_window_set(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Window * val, unsigned int num); +EAPI void ecore_x_window_prop_window_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom); +EAPI void ecore_x_window_prop_window_get_fetch(void); EAPI int ecore_x_window_prop_window_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Window * val, @@ -1136,10 +1180,19 @@ EAPI int ecore_x_window_prop_window_list_get(Ecore_X_Window win, EAPI Ecore_X_Atom ecore_x_window_prop_any_type(void); EAPI void ecore_x_window_prop_property_set(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_Atom format, int size, void *data, int number); +EAPI void ecore_x_window_prop_property_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom property, + Ecore_X_Atom type); +EAPI void ecore_x_window_prop_property_get_fetch(void); EAPI int ecore_x_window_prop_property_get(Ecore_X_Window win, Ecore_X_Atom property, Ecore_X_Atom type, int size, unsigned char **data, int *num); EAPI void ecore_x_window_prop_property_del(Ecore_X_Window win, Ecore_X_Atom property); +EAPI void ecore_x_window_prop_list_prefetch(Ecore_X_Window window); +EAPI void ecore_x_window_prop_list_fetch(void); EAPI Ecore_X_Atom *ecore_x_window_prop_list(Ecore_X_Window win, int *num_ret); EAPI void ecore_x_window_prop_string_set(Ecore_X_Window win, Ecore_X_Atom type, const char *str); +EAPI void ecore_x_window_prop_string_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom type); +EAPI void ecore_x_window_prop_string_get_fetch(void); EAPI char *ecore_x_window_prop_string_get(Ecore_X_Window win, Ecore_X_Atom type); EAPI int ecore_x_window_prop_protocol_isset(Ecore_X_Window win, Ecore_X_WM_Protocol protocol); EAPI Ecore_X_WM_Protocol *ecore_x_window_prop_protocol_list_get(Ecore_X_Window win, int *num_ret); @@ -1154,6 +1207,8 @@ EAPI void ecore_x_window_shape_window_add_xy(Ecore_X_Window win, E EAPI void ecore_x_window_shape_rectangle_add(Ecore_X_Window win, int x, int y, int w, int h); EAPI void ecore_x_window_shape_rectangle_clip(Ecore_X_Window win, int x, int y, int w, int h); EAPI void ecore_x_window_shape_rectangles_add(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num); +EAPI void ecore_x_window_shape_rectangles_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_window_shape_rectangles_get_fetch(void); EAPI Ecore_X_Rectangle *ecore_x_window_shape_rectangles_get(Ecore_X_Window win, int *num_ret); EAPI void ecore_x_window_shape_events_select(Ecore_X_Window win, int on); @@ -1172,6 +1227,8 @@ EAPI int ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y); EAPI int ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b); EAPI int ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b); +EAPI void ecore_x_drawable_geometry_get_prefetch(Ecore_X_Drawable drawable); +EAPI void ecore_x_drawable_geometry_get_fetch(void); EAPI void ecore_x_drawable_geometry_get(Ecore_X_Drawable d, int *x, int *y, int *w, int *h); EAPI int ecore_x_drawable_border_width_get(Ecore_X_Drawable d); EAPI int ecore_x_drawable_depth_get(Ecore_X_Drawable d); @@ -1192,6 +1249,8 @@ EAPI void ecore_x_window_container_manage(Ecore_X_Window win); EAPI void ecore_x_window_client_manage(Ecore_X_Window win); EAPI void ecore_x_window_sniff(Ecore_X_Window win); EAPI void ecore_x_window_client_sniff(Ecore_X_Window win); +EAPI void ecore_x_atom_get_prefetch(const char *name); +EAPI void ecore_x_atom_get_fetch(void); EAPI Ecore_X_Atom ecore_x_atom_get(const char *name); @@ -1296,10 +1355,12 @@ typedef enum _Ecore_X_MWM_Hint_Input ECORE_X_MWM_HINT_INPUT_FULL_APPLICATION_MODAL = 3, } Ecore_X_MWM_Hint_Input; -EAPI int ecore_x_mwm_hints_get(Ecore_X_Window win, - Ecore_X_MWM_Hint_Func *fhint, - Ecore_X_MWM_Hint_Decor *dhint, - Ecore_X_MWM_Hint_Input *ihint); +EAPI void ecore_x_mwm_hints_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_mwm_hints_get_fetch(void); +EAPI int ecore_x_mwm_hints_get(Ecore_X_Window win, + Ecore_X_MWM_Hint_Func *fhint, + Ecore_X_MWM_Hint_Decor *dhint, + Ecore_X_MWM_Hint_Input *ihint); EAPI void ecore_x_mwm_borderless_set(Ecore_X_Window win, int borderless); /* netwm */ @@ -1307,6 +1368,8 @@ EAPI void ecore_x_netwm_init(void); EAPI void ecore_x_netwm_shutdown(void); EAPI void ecore_x_netwm_wm_identify(Ecore_X_Window root, Ecore_X_Window check, const char *wm_name); EAPI void ecore_x_netwm_supported_set(Ecore_X_Window root, Ecore_X_Atom *supported, int num); +EAPI void ecore_x_netwm_supported_get_prefetch(Ecore_X_Window root); +EAPI void ecore_x_netwm_supported_get_fetch(void); EAPI int ecore_x_netwm_supported_get(Ecore_X_Window root, Ecore_X_Atom **supported, int *num); EAPI void ecore_x_netwm_desk_count_set(Ecore_X_Window root, unsigned int n_desks); EAPI void ecore_x_netwm_desk_roots_set(Ecore_X_Window root, Ecore_X_Window *vroots, unsigned int n_desks); @@ -1321,41 +1384,79 @@ EAPI void ecore_x_netwm_client_list_set(Ecore_X_Window root, Ecor EAPI void ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root, Ecore_X_Window *p_clients, unsigned int n_clients); EAPI void ecore_x_netwm_client_active_set(Ecore_X_Window root, Ecore_X_Window win); EAPI void ecore_x_netwm_name_set(Ecore_X_Window win, const char *name); +EAPI void ecore_x_netwm_name_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_name_get_fetch(void); EAPI int ecore_x_netwm_name_get(Ecore_X_Window win, char **name); EAPI void ecore_x_netwm_startup_id_set(Ecore_X_Window win, const char *id); +EAPI void ecore_x_netwm_startup_id_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_startup_id_get_fetch(void); EAPI int ecore_x_netwm_startup_id_get(Ecore_X_Window win, char **id); EAPI void ecore_x_netwm_visible_name_set(Ecore_X_Window win, const char *name); +EAPI void ecore_x_netwm_visible_name_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_visible_name_get_fetch(void); EAPI int ecore_x_netwm_visible_name_get(Ecore_X_Window win, char **name); EAPI void ecore_x_netwm_icon_name_set(Ecore_X_Window win, const char *name); +EAPI void ecore_x_netwm_icon_name_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_icon_name_get_fetch(void); EAPI int ecore_x_netwm_icon_name_get(Ecore_X_Window win, char **name); EAPI void ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, const char *name); +EAPI void ecore_x_netwm_visible_icon_name_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_visible_icon_name_get_fetch(void); EAPI int ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, char **name); EAPI void ecore_x_netwm_desktop_set(Ecore_X_Window win, unsigned int desk); +EAPI void ecore_x_netwm_desktop_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_desktop_get_fetch(void); EAPI int ecore_x_netwm_desktop_get(Ecore_X_Window win, unsigned int *desk); EAPI void ecore_x_netwm_strut_set(Ecore_X_Window win, int left, int right, int top, int bottom); +EAPI void ecore_x_netwm_strut_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_strut_get_fetch(void); EAPI int ecore_x_netwm_strut_get(Ecore_X_Window win, int *left, int *right, int *top, int *bottom); EAPI void ecore_x_netwm_strut_partial_set(Ecore_X_Window win, int left, int right, int top, int bottom, int left_start_y, int left_end_y, int right_start_y, int right_end_y, int top_start_x, int top_end_x, int bottom_start_x, int bottom_end_x); +EAPI void ecore_x_netwm_strut_partial_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_strut_partial_get_fetch(void); EAPI int ecore_x_netwm_strut_partial_get(Ecore_X_Window win, int *left, int *right, int *top, int *bottom, int *left_start_y, int *left_end_y, int *right_start_y, int *right_end_y, int *top_start_x, int *top_end_x, int *bottom_start_x, int *bottom_end_x); +EAPI void ecore_x_netwm_icons_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_icons_get_fetch(void); EAPI int ecore_x_netwm_icons_get(Ecore_X_Window win, Ecore_X_Icon **icon, int *num); EAPI void ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, int x, int y, int width, int height); +EAPI void ecore_x_netwm_icon_geometry_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_icon_geometry_get_fetch(void); EAPI int ecore_x_netwm_icon_geometry_get(Ecore_X_Window win, int *x, int *y, int *width, int *height); EAPI void ecore_x_netwm_pid_set(Ecore_X_Window win, int pid); +EAPI void ecore_x_netwm_pid_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_pid_get_fetch(void); EAPI int ecore_x_netwm_pid_get(Ecore_X_Window win, int *pid); EAPI void ecore_x_netwm_handled_icons_set(Ecore_X_Window win); +EAPI void ecore_x_netwm_handled_icons_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_handled_icons_get_fetch(void); EAPI int ecore_x_netwm_handled_icons_get(Ecore_X_Window win); EAPI void ecore_x_netwm_user_time_set(Ecore_X_Window win, unsigned int time); +EAPI void ecore_x_netwm_user_time_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_user_time_get_fetch(void); EAPI int ecore_x_netwm_user_time_get(Ecore_X_Window win, unsigned int *time); EAPI void ecore_x_netwm_window_state_set(Ecore_X_Window win, Ecore_X_Window_State *state, unsigned int num); +EAPI void ecore_x_netwm_window_state_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_window_state_get_fetch(void); EAPI int ecore_x_netwm_window_state_get(Ecore_X_Window win, Ecore_X_Window_State **state, unsigned int *num); EAPI void ecore_x_netwm_window_type_set(Ecore_X_Window win, Ecore_X_Window_Type type); +EAPI void ecore_x_netwm_window_type_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_window_type_get_fetch(void); EAPI int ecore_x_netwm_window_type_get(Ecore_X_Window win, Ecore_X_Window_Type *type); EAPI int ecore_x_netwm_allowed_action_isset(Ecore_X_Window win, Ecore_X_Action action); EAPI void ecore_x_netwm_allowed_action_set(Ecore_X_Window win, Ecore_X_Action *action, unsigned int num); +EAPI void ecore_x_netwm_allowed_action_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_allowed_action_get_fetch(void); EAPI int ecore_x_netwm_allowed_action_get(Ecore_X_Window win, Ecore_X_Action **action, unsigned int *num); EAPI void ecore_x_netwm_opacity_set(Ecore_X_Window win, unsigned int opacity); +EAPI void ecore_x_netwm_opacity_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_opacity_get_fetch(void); EAPI int ecore_x_netwm_opacity_get(Ecore_X_Window win, unsigned int *opacity); EAPI void ecore_x_netwm_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb); +EAPI void ecore_x_netwm_frame_size_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_frame_size_get_fetch(void); EAPI int ecore_x_netwm_frame_size_get(Ecore_X_Window win, int *fl, int *fr, int *ft, int *fb); +EAPI void ecore_x_netwm_sync_counter_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_netwm_sync_counter_get_fetch(void); EAPI int ecore_x_netwm_sync_counter_get(Ecore_X_Window win, Ecore_X_Sync_Counter *counter); EAPI void ecore_x_netwm_ping_send(Ecore_X_Window win); EAPI void ecore_x_netwm_sync_request_send(Ecore_X_Window win, unsigned int serial); @@ -1369,11 +1470,17 @@ EAPI void ecore_x_e_init(void); EAPI void ecore_x_e_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb); +EAPI void ecore_x_xinerama_query_screens_prefetch(void); +EAPI void ecore_x_xinerama_query_screens_fetch(void); EAPI int ecore_x_xinerama_screen_count_get(void); EAPI int ecore_x_xinerama_screen_geometry_get(int screen, int *x, int *y, int *w, int *h); EAPI int ecore_x_screensaver_event_available_get(void); -EAPI int ecore_x_screensaver_idle_time_get(void); +EAPI void ecore_x_screensaver_idle_time_prefetch(void); +EAPI void ecore_x_screensaver_idle_time_fetch(void); +EAPI int ecore_x_screensaver_idle_time_get(void); +EAPI void ecore_x_get_screensaver_prefetch(void); +EAPI void ecore_x_get_screensaver_fetch(void); EAPI void ecore_x_screensaver_set(int timeout, int interval, int blank, int expose); EAPI void ecore_x_screensaver_timeout_set(double timeout); EAPI double ecore_x_screensaver_timeout_get(void); @@ -1413,12 +1520,16 @@ typedef struct _Ecore_X_Window_Attributes */ } Ecore_X_Window_Attributes; +EAPI void ecore_x_get_window_attributes_prefetch(Ecore_X_Window window); +EAPI void ecore_x_get_window_attributes_fetch(void); EAPI int ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret); EAPI void ecore_x_window_save_set_add(Ecore_X_Window win); EAPI void ecore_x_window_save_set_del(Ecore_X_Window win); EAPI Ecore_X_Window *ecore_x_window_children_get(Ecore_X_Window win, int *num); EAPI int ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold); +EAPI void ecore_x_pointer_control_get_prefetch(void); +EAPI void ecore_x_pointer_control_get_fetch(void); EAPI int ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold); EAPI int ecore_x_pointer_grab(Ecore_X_Window win); EAPI int ecore_x_pointer_confine_grab(Ecore_X_Window win); @@ -1442,6 +1553,8 @@ EAPI void ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key, EAPI void ecore_x_focus_reset(void); EAPI void ecore_x_events_allow_all(void); EAPI void ecore_x_pointer_last_xy_get(int *x, int *y); +EAPI void ecore_x_pointer_xy_get_prefetch(Ecore_X_Window window); +EAPI void ecore_x_pointer_xy_get_fetch(void); EAPI void ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y); /* ecore_x_sync.c */ @@ -1462,6 +1575,8 @@ struct _Ecore_X_Screen_Refresh_Rate }; EAPI int ecore_x_randr_events_select(Ecore_X_Window win, int on); +EAPI void ecore_x_randr_get_screen_info_prefetch(Ecore_X_Window window); +EAPI void ecore_x_randr_get_screen_info_fetch(void); EAPI Ecore_X_Randr_Rotation ecore_x_randr_screen_rotations_get(Ecore_X_Window root); EAPI Ecore_X_Randr_Rotation ecore_x_randr_screen_rotation_get(Ecore_X_Window root); EAPI void ecore_x_randr_screen_rotation_set(Ecore_X_Window root, Ecore_X_Randr_Rotation rot); @@ -1499,6 +1614,8 @@ EAPI void ecore_x_region_subtract(Ecore_X_Region dest, Ecore_X_Region EAPI void ecore_x_region_invert(Ecore_X_Region dest, Ecore_X_Rectangle *bounds, Ecore_X_Region source); EAPI void ecore_x_region_translate(Ecore_X_Region region, int dx, int dy); EAPI void ecore_x_region_extents(Ecore_X_Region dest, Ecore_X_Region source); +EAPI void ecore_x_region_fetch_prefetch(Ecore_X_Region region); +EAPI void ecore_x_region_fetch_fetch(void); EAPI Ecore_X_Rectangle * ecore_x_region_fetch(Ecore_X_Region region, int *num, Ecore_X_Rectangle *bounds); EAPI void ecore_x_region_expand(Ecore_X_Region dest, Ecore_X_Region source, unsigned int left, unsigned int right, unsigned int top, unsigned int bottom); EAPI void ecore_x_region_gc_clip_set(Ecore_X_Region region, Ecore_X_GC gc, int x_origin, int y_origin); @@ -1535,14 +1652,20 @@ EAPI void ecore_x_damage_subtract(Ecore_X_Damage damage, Ecore_X_Re EAPI int ecore_x_screen_is_composited(int screen); EAPI int ecore_x_dpms_query(void); +EAPI void ecore_x_dpms_capable_get_prefetch(void); +EAPI void ecore_x_dpms_capable_get_fetch(void); EAPI int ecore_x_dpms_capable_get(void); +EAPI void ecore_x_dpms_enable_get_prefetch(void); +EAPI void ecore_x_dpms_enable_get_fetch(void); EAPI int ecore_x_dpms_enabled_get(void); EAPI void ecore_x_dpms_enabled_set(int enabled); +EAPI void ecore_x_dpms_timeouts_get_prefetch(void); +EAPI void ecore_x_dpms_timeouts_get_fetch(void); EAPI void ecore_x_dpms_timeouts_get(unsigned int *standby, unsigned int *suspend, unsigned int *off); EAPI int ecore_x_dpms_timeouts_set(unsigned int standby, unsigned int suspend, unsigned int off); -EAPI unsigned int ecore_x_dpms_timeout_standby_get(); -EAPI unsigned int ecore_x_dpms_timeout_suspend_get(); -EAPI unsigned int ecore_x_dpms_timeout_off_get(); +EAPI unsigned int ecore_x_dpms_timeout_standby_get(void); +EAPI unsigned int ecore_x_dpms_timeout_suspend_get(void); +EAPI unsigned int ecore_x_dpms_timeout_off_get(void); EAPI void ecore_x_dpms_timeout_standby_set(unsigned int new_timeout); EAPI void ecore_x_dpms_timeout_suspend_set(unsigned int new_timeout); EAPI void ecore_x_dpms_timeout_off_set(unsigned int new_timeout); diff --git a/legacy/ecore/src/lib/ecore_x/Makefile.am b/legacy/ecore/src/lib/ecore_x/Makefile.am index 47de70a342..3b2a89ad69 100644 --- a/legacy/ecore/src/lib/ecore_x/Makefile.am +++ b/legacy/ecore/src/lib/ecore_x/Makefile.am @@ -1,5 +1,23 @@ MAINTAINERCLEANFILES = Makefile.in +if BUILD_ECORE_X_XCB +INCLUDES = \ +@XCB_DAMAGE_CFLAGS@ \ +@XCB_DPMS_CFLAGS@ \ +@XCB_RANDR_CFLAGS@ \ +@XCB_RENDER_CFLAGS@ \ +@XCB_SCREENSAVER_CFLAGS@ \ +@XCB_SHAPE_CFLAGS@ \ +@XCB_SYNC_CFLAGS@ \ +@XCB_XFIXES_CFLAGS@ \ +@XCB_XINERAMA_CFLAGS@ \ +@XCB_XPRINT_CFLAGS@ \ +@XCB_CFLAGS@ \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_txt \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_txt +else INCLUDES = \ @Xcursor_cflags@ \ @XDAMAGE_CFLAGS@ \ @@ -15,11 +33,68 @@ INCLUDES = \ -I$(top_srcdir)/src/lib/ecore_txt \ -I$(top_builddir)/src/lib/ecore \ -I$(top_builddir)/src/lib/ecore_txt +endif libecore_x_la_LDFLAGS = -version-info 1:0:0 \ -L$(top_builddir)/src/lib/ecore/.libs \ -L$(top_builddir)/src/lib/ecore_txt/.libs +if BUILD_ECORE_X_XCB + +lib_LTLIBRARIES = libecore_x.la +include_HEADERS = \ +Ecore_X.h \ +Ecore_X_Atoms.h \ +Ecore_X_Cursor.h + +libecore_x_la_SOURCES = \ +ecore_xcb_atom.c \ +ecore_xcb_cursor.c \ +ecore_xcb_damage.c \ +ecore_xcb_dnd.c \ +ecore_xcb_dpms.c \ +ecore_xcb_drawable.c \ +ecore_xcb_e.c \ +ecore_xcb_events.c \ +ecore_xcb_fixes.c \ +ecore_xcb_gc.c \ +ecore_xcb_icccm.c \ +ecore_xcb_mwm.c \ +ecore_xcb_netwm.c \ +ecore_xcb_pixmap.c \ +ecore_xcb_randr.c \ +ecore_xcb_reply.c \ +ecore_xcb_screensaver.c \ +ecore_xcb_selection.c \ +ecore_xcb_shape.c \ +ecore_xcb_sync.c \ +ecore_xcb_window.c \ +ecore_xcb_window_prop.c \ +ecore_xcb_xinerama.c \ +ecore_xcb.c \ +ecore_xcb_private.h + +libecore_x_la_LIBADD = \ +@XCB_DAMAGE_LIBS@ \ +@XCB_DPMS_LIBS@ \ +@XCB_RANDR_LIBS@ \ +@XCB_RENDER_LIBS@ \ +@XCB_SCREENSAVER_LIBS@ \ +@XCB_SHAPE_LIBS@ \ +@XCB_SYNC_LIBS@ \ +@XCB_XFIXES_LIBS@ \ +@XCB_XINERAMA_LIBS@ \ +@XCB_XPRINT_LIBS@ \ +@XCB_LIBS@ \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_txt/libecore_txt.la + +libecore_x_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_txt/libecore_txt.la + +endif + if BUILD_ECORE_X lib_LTLIBRARIES = libecore_x.la diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb.c new file mode 100644 index 0000000000..c1062ce236 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb.c @@ -0,0 +1,1824 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + +#include "Ecore.h" +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + +static int _ecore_xcb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_xcb_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_xcb_key_mask_get(xcb_keysym_t sym); +static void *_ecore_xcb_event_filter_start(void *data); +static int _ecore_xcb_event_filter_filter(void *data, void *loop_data,int type, void *event); +static void _ecore_xcb_event_filter_end(void *data, void *loop_data); + +static Ecore_Fd_Handler *_ecore_xcb_fd_handler_handle = NULL; +static Ecore_Event_Filter *_ecore_xcb_filter_handler = NULL; + +#ifdef ECORE_XCB_DAMAGE +static int _ecore_xcb_event_damage_id = 0; +#endif /* ECORE_XCB_DAMAGE */ +#ifdef ECORE_XCB_RANDR +static int _ecore_xcb_event_randr_id = 0; +#endif /* ECORE_XCB_RANDR */ +#ifdef ECORE_XCB_SCREENSAVER +static int _ecore_xcb_event_screensaver_id = 0; +#endif /* ECORE_XCB_SCREENSAVER */ +#ifdef ECORE_XCB_SHAPE +static int _ecore_xcb_event_shape_id = 0; +#endif /* ECORE_XCB_SHAPE */ +#ifdef ECORE_XCB_SYNC +static int _ecore_xcb_event_sync_id = 0; +#endif /* ECORE_XCB_SYNC */ +#ifdef ECORE_XCB_FIXES +static int _ecore_xcb_event_fixes_selection_id = 0; +#endif /* ECORE_XCB_FIXES */ + +static int _ecore_xcb_event_handlers_num = 0; +static void (**_ecore_xcb_event_handlers) (xcb_generic_event_t * event) = NULL; +static xcb_generic_event_t *_ecore_xcb_event_buffered = NULL; + +static int _ecore_xcb_init_count = 0; +static int _ecore_xcb_grab_count = 0; + +Ecore_X_Connection *_ecore_xcb_conn = NULL; +Ecore_X_Screen *_ecore_xcb_screen = NULL; +double _ecore_xcb_double_click_time = 0.25; +Ecore_X_Time _ecore_xcb_event_last_time = XCB_NONE; +Ecore_X_Window _ecore_xcb_event_last_window = XCB_NONE; +int16_t _ecore_xcb_event_last_root_x = 0; +int16_t _ecore_xcb_event_last_root_y = 0; +int _ecore_xcb_xcursor = 0; + +Ecore_X_Window _ecore_xcb_private_window = 0; + +/* FIXME - These are duplicates after making ecore atoms public */ + +Ecore_X_Atom _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM]; + + +EAPI int ECORE_X_EVENT_KEY_DOWN = 0; +EAPI int ECORE_X_EVENT_KEY_UP = 0; +EAPI int ECORE_X_EVENT_MOUSE_BUTTON_DOWN = 0; +EAPI int ECORE_X_EVENT_MOUSE_BUTTON_UP = 0; +EAPI int ECORE_X_EVENT_MOUSE_MOVE = 0; +EAPI int ECORE_X_EVENT_MOUSE_IN = 0; +EAPI int ECORE_X_EVENT_MOUSE_OUT = 0; +EAPI int ECORE_X_EVENT_MOUSE_WHEEL = 0; +EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0; +EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0; +EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0; +EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0; +EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0; +EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0; +EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0; +EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0; +EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_STACK = 0; +EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0; +EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0; +EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0; +EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0; +EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0; +EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0; +EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0; +EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0; +EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0; +EAPI int ECORE_X_EVENT_SYNC_ALARM = 0; +EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0; +EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0; + +EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0; +/* +EAPI int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = 0; +*/ + +EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0; +EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0; +EAPI int ECORE_X_EVENT_PING = 0; +EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0; + +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0; +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0; +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0; + +EAPI int ECORE_X_MODIFIER_SHIFT = 0; +EAPI int ECORE_X_MODIFIER_CTRL = 0; +EAPI int ECORE_X_MODIFIER_ALT = 0; +EAPI int ECORE_X_MODIFIER_WIN = 0; + +EAPI int ECORE_X_LOCK_SCROLL = 0; +EAPI int ECORE_X_LOCK_NUM = 0; +EAPI int ECORE_X_LOCK_CAPS = 0; + +/** + * @defgroup Ecore_Xcb_Init_Group X Library Init and Shutdown Functions + * + * Functions that start and shut down the Ecore X Library. + */ + +/** + * Initialize the X display connection to the given display. + * + * @param name Display target name. If @c NULL, the default display is + * assumed. + * @return The number of times the library has been initialized without + * being shut down. 0 is returned if an error occurs. + * @ingroup Ecore_Xcb_Init_Group + */ +EAPI int +ecore_x_init(const char *name) +{ + xcb_screen_iterator_t iter; + int screen; + uint32_t max_request_length; + const xcb_query_extension_reply_t *reply_big_requests; +#ifdef ECORE_XCB_DAMAGE + const xcb_query_extension_reply_t *reply_damage; +#endif /* ECORE_XCB_DAMAGE */ +#ifdef ECORE_XCB_DPMS + const xcb_query_extension_reply_t *reply_dpms; +#endif /* ECORE_XCB_DPMS */ +#ifdef ECORE_XCB_RANDR + const xcb_query_extension_reply_t *reply_randr; +#endif /* ECORE_XCB_RANDR */ +#ifdef ECORE_XCB_SCREENSAVER + const xcb_query_extension_reply_t *reply_screensaver; +#endif /* ECORE_XCB_SCREENSAVER */ +#ifdef ECORE_XCB_SHAPE + const xcb_query_extension_reply_t *reply_shape; +#endif /* ECORE_XCB_SHAPE */ +#ifdef ECORE_XCB_SYNC + xcb_sync_initialize_cookie_t cookie_sync_init; + xcb_sync_initialize_reply_t *reply_sync_init; + const xcb_query_extension_reply_t *reply_sync; +#endif /* ECORE_XCB_SYNC */ +#ifdef ECORE_XCB_FIXES + const xcb_query_extension_reply_t *reply_xfixes; +#endif /* ECORE_XCB_FIXES */ +#ifdef ECORE_XCB_XINERAMA + const xcb_query_extension_reply_t *reply_xinerama; +#endif /* ECORE_XCB_XINERAMA */ +#ifdef ECORE_XCB_XPRINT + const xcb_query_extension_reply_t *reply_xprint; +#endif /* ECORE_XCB_XPRINT */ + + if (_ecore_xcb_init_count > 0) + { + _ecore_xcb_init_count++; + return _ecore_xcb_init_count; + } + _ecore_xcb_conn = xcb_connect(name, &screen); + if (!_ecore_xcb_conn) return 0; + + /* FIXME: no error code right now */ + /* _ecore_xcb_error_handler_init(); */ + + /********************/ + /* First round trip */ + /********************/ + + /* + * Non blocking stuff: + * + * 1. We request the atoms + * 2. We Prefetch the extension data + * + */ + + /* We request the atoms (non blocking) */ + _ecore_x_atom_init(); + + /* We prefetch all the extension data (non blocking) */ + + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_big_requests_id); + +#ifdef ECORE_XCB_DAMAGE + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_damage_id); +#endif /* ECORE_XCB_DAMAGE */ + +#ifdef ECORE_XCB_DPMS + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_dpms_id); +#endif /* ECORE_XCB_DPMS */ + +#ifdef ECORE_XCB_RANDR + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_randr_id); +#endif /* ECORE_XCB_RANDR */ + +#ifdef ECORE_XCB_SCREENSAVER + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_screensaver_id); +#endif /* ECORE_XCB_SCREENSAVER */ + +#ifdef ECORE_XCB_SHAPE + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_shape_id); +#endif /* ECORE_XCB_SHAPE */ + +#ifdef ECORE_XCB_SYNC + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_sync_id); + cookie_sync_init = xcb_sync_initialize_unchecked(_ecore_xcb_conn); +#endif /* ECORE_XCB_SYNC */ + +#ifdef ECORE_XCB_FIXES + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xfixes_id); +#endif /* ECORE_XCB_FIXES */ + +#ifdef ECORE_XCB_XINERAMA + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xinerama_id); +#endif /* ECORE_XCB_XINERAMA */ + +#ifdef ECORE_XCB_XPRINT + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_x_print_id); +#endif /* ECORE_XCB_XPRINT */ + + /* We init some components (not related to XCB) */ + _ecore_x_reply_init(); + _ecore_x_dnd_init(); + ecore_x_netwm_init(); + _ecore_x_selection_init(); + + /* There is no LASTEvent constant in XCB */ + /* LASTevent is equal to 35 */ + _ecore_xcb_event_handlers_num = 35; + + /* We get the default screen */ + iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + for (; iter.rem; --screen, xcb_screen_next (&iter)) + if (screen == 0) + { + _ecore_xcb_screen = iter.data; + break; + } + + /* + * Blocking stuff: + * + * 1. We get the atoms + * 2. We ask for the extension data + * + */ + + /* We get the atoms (blocking) */ + _ecore_x_atom_init_finalize(); + + /* We then ask for the extension data (blocking) */ + reply_big_requests = xcb_get_extension_data(_ecore_xcb_conn, &xcb_big_requests_id); + +#ifdef ECORE_XCB_DAMAGE + reply_damage = xcb_get_extension_data(_ecore_xcb_conn, &xcb_damage_id); + if (reply_damage) + _ecore_xcb_event_damage_id = reply_damage->first_event + XCB_DAMAGE_NOTIFY; + if (_ecore_xcb_event_damage_id >= _ecore_xcb_event_handlers_num) + _ecore_xcb_event_handlers_num = _ecore_xcb_event_damage_id + 1; +#endif /* ECORE_XCB_DAMAGE */ + +#ifdef ECORE_XCB_DPMS + reply_dpms = xcb_get_extension_data(_ecore_xcb_conn, &xcb_dpms_id); +#endif /* ECORE_XCB_DAMAGE */ + +#ifdef ECORE_XCB_RANDR + reply_randr = xcb_get_extension_data(_ecore_xcb_conn, &xcb_randr_id); + if (reply_randr) + _ecore_xcb_event_randr_id = reply_randr->first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY; + if (_ecore_xcb_event_randr_id >= _ecore_xcb_event_handlers_num) + _ecore_xcb_event_handlers_num = _ecore_xcb_event_randr_id + 1; +#endif /* ECORE_XCB_RANDR */ + +#ifdef ECORE_XCB_SCREENSAVER + reply_screensaver = xcb_get_extension_data(_ecore_xcb_conn, &xcb_screensaver_id); + if (reply_screensaver) + _ecore_xcb_event_screensaver_id = reply_screensaver->first_event + XCB_SCREENSAVER_NOTIFY; + if (_ecore_xcb_event_screensaver_id >= _ecore_xcb_event_handlers_num) + _ecore_xcb_event_handlers_num = _ecore_xcb_event_screensaver_id + 1; +#endif /* ECORE_XCB_SCREENSAVER */ + +#ifdef ECORE_XCB_SHAPE + reply_shape = xcb_get_extension_data(_ecore_xcb_conn, &xcb_shape_id); + if (reply_shape) + _ecore_xcb_event_shape_id = reply_shape->first_event + XCB_SHAPE_NOTIFY; + if (_ecore_xcb_event_shape_id >= _ecore_xcb_event_handlers_num) + _ecore_xcb_event_handlers_num = _ecore_xcb_event_shape_id + 1; +#endif /* ECORE_XCB_SHAPE */ + +#ifdef ECORE_XCB_SYNC + reply_sync = xcb_get_extension_data(_ecore_xcb_conn, &xcb_sync_id); + if (reply_sync) + { + _ecore_xcb_event_sync_id = reply_sync->first_event; + reply_sync_init = xcb_sync_initialize_reply(_ecore_xcb_conn, + cookie_sync_init, NULL); + if (!reply_sync_init) + _ecore_xcb_event_sync_id = 0; + else + free(reply_sync_init); + } + if (_ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY >= _ecore_xcb_event_handlers_num) + _ecore_xcb_event_handlers_num = _ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY + 1; +#endif /* ECORE_XCB_SYNC */ + +#ifdef ECORE_XCB_FIXES + reply_xfixes = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xfixes_id); + if (reply_xfixes) + _ecore_xcb_event_fixes_selection_id = reply_xfixes->first_event + XCB_XFIXES_SELECTION_NOTIFY; + if (_ecore_xcb_event_fixes_selection_id >= _ecore_xcb_event_handlers_num) + _ecore_xcb_event_handlers_num = _ecore_xcb_event_fixes_selection_id + 1; +#endif /* ECORE_XCB_FIXES */ + +#ifdef ECORE_XCB_XINERAMA + reply_xinerama = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xinerama_id); +#endif /* ECORE_XCB_XINERAMA */ + +#ifdef ECORE_XCB_XPRINT + reply_xprint = xcb_get_extension_data(_ecore_xcb_conn, &xcb_x_print_id); +#endif /* ECORE_XCB_XPRINT */ + + /*********************/ + /* Second round trip */ + /*********************/ + + /* We ask for the QueryVersion request of the extensions */ + _ecore_x_damage_init(reply_damage); + _ecore_x_dpms_init(reply_dpms); + _ecore_x_randr_init(reply_randr); + _ecore_x_shape_init(reply_shape); + _ecore_x_sync_init(reply_sync); + _ecore_x_xfixes_init(reply_xfixes); + _ecore_x_xinerama_init(reply_xinerama); + + /* we enable the Big Request extension if present */ + max_request_length = xcb_get_maximum_request_length(_ecore_xcb_conn); + + _ecore_xcb_event_handlers = calloc(_ecore_xcb_event_handlers_num, sizeof(void *)); + if (!_ecore_xcb_event_handlers) + { + /* We get the replies of the QueryVersion request because we leave */ + _ecore_x_damage_init_finalize(); + _ecore_x_dpms_init_finalize(); + _ecore_x_randr_init_finalize(); + _ecore_x_shape_init_finalize(); + _ecore_x_sync_init_finalize(); + _ecore_x_xfixes_init_finalize(); + _ecore_x_xinerama_init_finalize(); + + xcb_disconnect(_ecore_xcb_conn); + _ecore_xcb_fd_handler_handle = NULL; + _ecore_xcb_conn = NULL; + return 0; + } + +#ifdef ECORE_XCB_CURSOR + _ecore_xcb_xcursor = XcursorSupportsARGB(_ecore_xcb_conn); +#endif /* ECORE_XCB_CURSOR */ + + _ecore_xcb_event_handlers[XCB_KEY_PRESS] = _ecore_x_event_handle_key_press; + _ecore_xcb_event_handlers[XCB_KEY_RELEASE] = _ecore_x_event_handle_key_release; + _ecore_xcb_event_handlers[XCB_BUTTON_PRESS] = _ecore_x_event_handle_button_press; + _ecore_xcb_event_handlers[XCB_BUTTON_RELEASE] = _ecore_x_event_handle_button_release; + _ecore_xcb_event_handlers[XCB_MOTION_NOTIFY] = _ecore_x_event_handle_motion_notify; + _ecore_xcb_event_handlers[XCB_ENTER_NOTIFY] = _ecore_x_event_handle_enter_notify; + _ecore_xcb_event_handlers[XCB_LEAVE_NOTIFY] = _ecore_x_event_handle_leave_notify; + _ecore_xcb_event_handlers[XCB_FOCUS_IN] = _ecore_x_event_handle_focus_in; + _ecore_xcb_event_handlers[XCB_FOCUS_OUT] = _ecore_x_event_handle_focus_out; + _ecore_xcb_event_handlers[XCB_KEYMAP_NOTIFY] = _ecore_x_event_handle_keymap_notify; + _ecore_xcb_event_handlers[XCB_EXPOSE] = _ecore_x_event_handle_expose; + _ecore_xcb_event_handlers[XCB_GRAPHICS_EXPOSURE] = _ecore_x_event_handle_graphics_expose; + _ecore_xcb_event_handlers[XCB_VISIBILITY_NOTIFY] = _ecore_x_event_handle_visibility_notify; + _ecore_xcb_event_handlers[XCB_CREATE_NOTIFY] = _ecore_x_event_handle_create_notify; + _ecore_xcb_event_handlers[XCB_DESTROY_NOTIFY] = _ecore_x_event_handle_destroy_notify; + _ecore_xcb_event_handlers[XCB_UNMAP_NOTIFY] = _ecore_x_event_handle_unmap_notify; + _ecore_xcb_event_handlers[XCB_MAP_NOTIFY] = _ecore_x_event_handle_map_notify; + _ecore_xcb_event_handlers[XCB_MAP_REQUEST] = _ecore_x_event_handle_map_request; + _ecore_xcb_event_handlers[XCB_REPARENT_NOTIFY] = _ecore_x_event_handle_reparent_notify; + _ecore_xcb_event_handlers[XCB_CONFIGURE_NOTIFY] = _ecore_x_event_handle_configure_notify; + _ecore_xcb_event_handlers[XCB_CONFIGURE_REQUEST] = _ecore_x_event_handle_configure_request; + _ecore_xcb_event_handlers[XCB_GRAVITY_NOTIFY] = _ecore_x_event_handle_gravity_notify; + _ecore_xcb_event_handlers[XCB_RESIZE_REQUEST] = _ecore_x_event_handle_resize_request; + _ecore_xcb_event_handlers[XCB_CIRCULATE_NOTIFY] = _ecore_x_event_handle_circulate_notify; + _ecore_xcb_event_handlers[XCB_CIRCULATE_REQUEST] = _ecore_x_event_handle_circulate_request; + _ecore_xcb_event_handlers[XCB_PROPERTY_NOTIFY] = _ecore_x_event_handle_property_notify; + _ecore_xcb_event_handlers[XCB_SELECTION_CLEAR] = _ecore_x_event_handle_selection_clear; + _ecore_xcb_event_handlers[XCB_SELECTION_REQUEST] = _ecore_x_event_handle_selection_request; + _ecore_xcb_event_handlers[XCB_SELECTION_NOTIFY] = _ecore_x_event_handle_selection_notify; + _ecore_xcb_event_handlers[XCB_COLORMAP_NOTIFY] = _ecore_x_event_handle_colormap_notify; + _ecore_xcb_event_handlers[XCB_CLIENT_MESSAGE] = _ecore_x_event_handle_client_message; + _ecore_xcb_event_handlers[XCB_MAPPING_NOTIFY] = _ecore_x_event_handle_mapping_notify; +#ifdef ECORE_XCB_DAMAGE + if (_ecore_xcb_event_damage_id) + _ecore_xcb_event_handlers[_ecore_xcb_event_damage_id] = _ecore_x_event_handle_damage_notify; +#endif /* ECORE_XCB_DAMAGE */ +#ifdef ECORE_XCB_RANDR + if (_ecore_xcb_event_randr_id) + _ecore_xcb_event_handlers[_ecore_xcb_event_randr_id] = _ecore_x_event_handle_randr_change; +#endif /* ECORE_XCB_RANDR */ +#ifdef ECORE_XCB_SCREENSAVER + if (_ecore_xcb_event_screensaver_id) + _ecore_xcb_event_handlers[_ecore_xcb_event_screensaver_id] = _ecore_x_event_handle_screensaver_notify; +#endif /* ECORE_XCB_SCREENSAVER */ +#ifdef ECORE_XCB_SHAPE + if (_ecore_xcb_event_shape_id) + _ecore_xcb_event_handlers[_ecore_xcb_event_shape_id] = _ecore_x_event_handle_shape_change; +#endif /* ECORE_XCB_SHAPE */ +#ifdef ECORE_XCB_SYNC + if (_ecore_xcb_event_sync_id) + { + _ecore_xcb_event_handlers[_ecore_xcb_event_sync_id + XCB_SYNC_COUNTER_NOTIFY] = + _ecore_x_event_handle_sync_counter; + _ecore_xcb_event_handlers[_ecore_xcb_event_sync_id + XCB_SYNC_ALARM_NOTIFY] = + _ecore_x_event_handle_sync_alarm; + } +#endif /* ECORE_XCB_SYNC */ +#ifdef ECORE_XCB_FIXES + if (_ecore_xcb_event_fixes_selection_id) + _ecore_xcb_event_handlers[_ecore_xcb_event_fixes_selection_id] = _ecore_x_event_handle_fixes_selection_notify; +#endif /* ECORE_XCB_FIXES */ + + if (!ECORE_X_EVENT_KEY_DOWN) + { + ECORE_X_EVENT_KEY_DOWN = ecore_event_type_new(); + ECORE_X_EVENT_KEY_UP = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_BUTTON_DOWN = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_BUTTON_UP = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_MOVE = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_IN = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_OUT = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_WHEEL = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_FOCUS_IN = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_FOCUS_OUT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_KEYMAP = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_DAMAGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CREATE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_DESTROY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_HIDE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHOW = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHOW_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_REPARENT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CONFIGURE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_GRAVITY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STACK = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STACK_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROPERTY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_COLORMAP = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_MAPPING = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_CLEAR = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_CLIENT_MESSAGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHAPE = ecore_event_type_new(); + ECORE_X_EVENT_SCREENSAVER_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_SYNC_COUNTER = ecore_event_type_new(); + ECORE_X_EVENT_SYNC_ALARM = ecore_event_type_new(); + ECORE_X_EVENT_SCREEN_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_DAMAGE_NOTIFY = ecore_event_type_new(); + + ECORE_X_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new(); + /* + ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = ecore_event_type_new(); + */ + + ECORE_X_EVENT_DESKTOP_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STATE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_PING = ecore_event_type_new(); + + ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = ecore_event_type_new(); + ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = ecore_event_type_new(); + } + + /* everything has these... unless its like a pda... :) */ + ECORE_X_MODIFIER_SHIFT = _ecore_xcb_key_mask_get(XK_Shift_L); + ECORE_X_MODIFIER_CTRL = _ecore_xcb_key_mask_get(XK_Control_L); + + /* apple's xdarwin has no alt!!!! */ + ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Alt_L); + if (!ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Meta_L); + if (!ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_ALT = _ecore_xcb_key_mask_get(XK_Super_L); + + /* the windows key... a valid modifier :) */ + ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Super_L); + if (!ECORE_X_MODIFIER_WIN) + ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Mode_switch); + if (!ECORE_X_MODIFIER_WIN) + ECORE_X_MODIFIER_WIN = _ecore_xcb_key_mask_get(XK_Meta_L); + + if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_WIN = 0; + if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL) + ECORE_X_MODIFIER_ALT = 0; + + ECORE_X_LOCK_SCROLL = _ecore_xcb_key_mask_get(XK_Scroll_Lock); + ECORE_X_LOCK_NUM = _ecore_xcb_key_mask_get(XK_Num_Lock); + ECORE_X_LOCK_CAPS = _ecore_xcb_key_mask_get(XK_Caps_Lock); + + _ecore_xcb_fd_handler_handle = + ecore_main_fd_handler_add(xcb_get_file_descriptor(_ecore_xcb_conn), + ECORE_FD_READ, + _ecore_xcb_fd_handler, _ecore_xcb_conn, + _ecore_xcb_fd_handler_buf, _ecore_xcb_conn); + if (!_ecore_xcb_fd_handler_handle) + { + /* We get the replies of the QueryVersion request because we leave */ + _ecore_x_damage_init_finalize(); + _ecore_x_dpms_init_finalize(); + _ecore_x_randr_init_finalize(); + _ecore_x_shape_init_finalize(); + _ecore_x_sync_init_finalize(); + _ecore_x_xfixes_init_finalize(); + _ecore_x_xinerama_init_finalize(); + + xcb_disconnect(_ecore_xcb_conn); + free(_ecore_xcb_event_handlers); + _ecore_xcb_fd_handler_handle = NULL; + _ecore_xcb_conn = NULL; + _ecore_xcb_event_handlers = NULL; + return 0; + } + _ecore_xcb_filter_handler = ecore_event_filter_add(_ecore_xcb_event_filter_start, _ecore_xcb_event_filter_filter, _ecore_xcb_event_filter_end, NULL); + + /* This is just to be anal about naming conventions */ + + _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = ECORE_X_ATOM_WM_DELETE_WINDOW; + _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = ECORE_X_ATOM_WM_TAKE_FOCUS; + _ecore_xcb_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] = ECORE_X_ATOM_NET_WM_PING; + _ecore_xcb_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST; + + _ecore_xcb_init_count++; + + _ecore_xcb_private_window = ecore_x_window_override_new(0, -77, -777, 123, 456); + + /* We finally get the replies of the QueryVersion request */ + _ecore_x_damage_init_finalize(); + _ecore_x_dpms_init_finalize(); + _ecore_x_randr_init_finalize(); + _ecore_x_shape_init_finalize(); + _ecore_x_sync_init_finalize(); + _ecore_x_xfixes_init_finalize(); + _ecore_x_xinerama_init_finalize(); + + return _ecore_xcb_init_count; +} + +static int +_ecore_x_shutdown(int close_display) +{ + _ecore_xcb_init_count--; + if (_ecore_xcb_init_count > 0) return _ecore_xcb_init_count; + if (!_ecore_xcb_conn) return _ecore_xcb_init_count; + if (close_display) + xcb_disconnect(_ecore_xcb_conn); + else + close(xcb_get_file_descriptor(_ecore_xcb_conn)); + free(_ecore_xcb_event_handlers); + ecore_main_fd_handler_del(_ecore_xcb_fd_handler_handle); + ecore_event_filter_del(_ecore_xcb_filter_handler); + _ecore_xcb_fd_handler_handle = NULL; + _ecore_xcb_filter_handler = NULL; + _ecore_xcb_conn = NULL; + _ecore_xcb_event_handlers = NULL; + _ecore_x_selection_shutdown(); + _ecore_x_dnd_shutdown(); + ecore_x_netwm_shutdown(); + _ecore_x_reply_shutdown(); + if (_ecore_xcb_init_count < 0) _ecore_xcb_init_count = 0; + return _ecore_xcb_init_count; +} + +/** + * Shuts down the Ecore X library. + * + * In shutting down the library, the X display connection is terminated + * and any event handlers for it are removed. + * + * @return The number of times the library has been initialized without + * being shut down. + * @ingroup Ecore_Xcb_Init_Group + */ +EAPI int +ecore_x_shutdown(void) +{ + return _ecore_x_shutdown(1); +} + +/** + * Shuts down the Ecore X library. + * + * As ecore_xcb_shutdown, except do not close Display, only connection. + * + * @ingroup Ecore_Xcb_Init_Group + */ +EAPI int +ecore_x_disconnect(void) +{ + return _ecore_x_shutdown(0); +} + +/** + * @defgroup Ecore_Xcb_Display_Attr_Group X Display Attributes + * + * Functions that set and retrieve X display attributes. + */ + +EAPI Ecore_X_Display * +ecore_x_display_get(void) +{ + return NULL; +} + +/** + * Retrieves the Ecore_X_Connection handle used for the current X connection. + * @return The current X connection. + * @ingroup Ecore_Xcb_Display_Attr_Group + */ +EAPI Ecore_X_Connection * +ecore_x_connection_get(void) +{ + return (Ecore_X_Connection *)_ecore_xcb_conn; +} + +/** + * Retrieves the X display file descriptor. + * @return The current X display file descriptor. + * @ingroup Ecore_Xcb_Display_Attr_Group + */ +EAPI int +ecore_x_fd_get(void) +{ + return xcb_get_file_descriptor(_ecore_xcb_conn); +} + +/** + * Retrieves the Ecore_X_Screen handle used for the current X connection. + * @return The current default screen. + * @ingroup Ecore_Xcb_Display_Attr_Group + */ +EAPI Ecore_X_Screen * +ecore_x_default_screen_get(void) +{ + return (Ecore_X_Screen *)_ecore_xcb_screen; +} + +/** + * Sets the timeout for a double and triple clicks to be flagged. + * + * This sets the time between clicks before the double_click flag is + * set in a button down event. If 3 clicks occur within double this + * time, the triple_click flag is also set. + * + * @param t The time in seconds + * @ingroup Ecore_Xcb_Display_Attr_Group + */ +EAPI void +ecore_x_double_click_time_set(double t) +{ + if (t < 0.0) t = 0.0; + _ecore_xcb_double_click_time = t; +} + +/** + * Retrieves the double and triple click flag timeout. + * + * See @ref ecore_xcb_double_click_time_set for more information. + * + * @return The timeout for double clicks in seconds. + * @ingroup Ecore_Xcb_Display_Attr_Group + */ +EAPI double +ecore_x_double_click_time_get(void) +{ + return _ecore_xcb_double_click_time; +} + +/** + * @defgroup Ecore_Xcb_Flush_Group X Synchronization Functions + * + * Functions that ensure that all commands that have been issued by the + * Ecore X library have been sent to the server. + */ + +/** + * Sends all X commands in the X Display buffer. + * @ingroup Ecore_Xcb_Flush_Group + */ +EAPI void +ecore_x_flush(void) +{ + xcb_flush(_ecore_xcb_conn); +} + +/** + * Flushes the command buffer and waits until all requests have been + * processed by the server. + * @ingroup Ecore_Xcb_Flush_Group + */ +EAPI void +ecore_x_sync(void) +{ + free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL)); +} + +/** + * Kill all clients with subwindows under a given window. + * + * You can kill all clients connected to the X server by using + * @ref ecore_x_window_root_list to get a list of root windows, and + * then passing each root window to this function. + * + * @param root The window whose children will be killed. + */ +EAPI void +ecore_x_killall(Ecore_X_Window root) +{ + int screens; + int i; + + xcb_grab_server(_ecore_xcb_conn); + screens = xcb_setup_roots_iterator (xcb_get_setup (_ecore_xcb_conn)).rem; + + /* Tranverse window tree starting from root, and drag each + * before the firing squad */ + for (i = 0; i < screens; ++i) + { + xcb_query_tree_cookie_t cookie; + xcb_query_tree_reply_t *reply; + + cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, root); + reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + xcb_window_iterator_t iter; + + iter = xcb_query_tree_children_iterator(reply); + for (; iter.rem; xcb_window_next(&iter)) + xcb_kill_client(_ecore_xcb_conn, *iter.data); + free(reply); + } + } + + xcb_ungrab_server(_ecore_xcb_conn); + free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL)); +} + +/** + * Kill a specific client + * + * You can kill a specific client woning window @p window + * + * @param window Window of the client to be killed + */ +EAPI void +ecore_x_kill(Ecore_X_Window window) +{ + xcb_kill_client(_ecore_xcb_conn, window); +} + +/** + * Return the last event time + */ +EAPI Ecore_X_Time +ecore_x_current_time_get(void) +{ + return _ecore_xcb_event_last_time; +} + +static int +_ecore_xcb_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + xcb_connection_t *c; + xcb_generic_event_t *ev; + uint8_t response_type; + + c = (xcb_connection_t *)data; + +/* printf ("nbr events: %d\n", _ecore_xcb_event_handlers_num); */ + /* We check if _ecore_xcb_event_buffered is NULL or not */ + if (_ecore_xcb_event_buffered) + { + response_type = _ecore_xcb_event_buffered->response_type & ~0x80; + if (response_type < _ecore_xcb_event_handlers_num) + { + printf ("event buffered: %d\n", response_type); + if (_ecore_xcb_event_handlers[response_type]) + _ecore_xcb_event_handlers[response_type] (_ecore_xcb_event_buffered); + } + } + while ((ev = xcb_poll_for_event(c))) + { + response_type = ev->response_type & ~0x80; + printf ("event non buffered: %d\n", response_type); + if (response_type < _ecore_xcb_event_handlers_num) + { + if (_ecore_xcb_event_handlers[response_type]) + _ecore_xcb_event_handlers[response_type] (ev); + } + } + + return 1; +} + +static int +_ecore_xcb_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + xcb_connection_t *c; + + c = (xcb_connection_t *)data; + + _ecore_xcb_event_buffered = xcb_poll_for_event(c); + if (!_ecore_xcb_event_buffered) + return 0; + + return 1; +} + +/* FIXME: possible roundtrip */ +/* FIXME: fix xcb_keysyms. It's ugly !! (reply in xcb_key_symbols_get_keysym) */ +static int +_ecore_xcb_key_mask_get(xcb_keysym_t sym) +{ + xcb_keycode_iterator_t iter; + xcb_get_modifier_mapping_cookie_t cookie; + xcb_get_modifier_mapping_reply_t *reply; + xcb_key_symbols_t *symbols; + xcb_keysym_t sym2; + int i, j; + const int masks[8] = + { + XCB_MOD_MASK_SHIFT, + XCB_MOD_MASK_LOCK, + XCB_MOD_MASK_CONTROL, + XCB_MOD_MASK_1, + XCB_MOD_MASK_2, + XCB_MOD_MASK_3, + XCB_MOD_MASK_4, + XCB_MOD_MASK_5 + }; + + cookie = xcb_get_modifier_mapping_unchecked(_ecore_xcb_conn); + symbols = xcb_key_symbols_alloc(_ecore_xcb_conn); + + reply = xcb_get_modifier_mapping_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + { + xcb_key_symbols_free(symbols); + + return 0; + } + + iter = xcb_get_modifier_mapping_keycodes_iterator(reply); + + for (i = 0; iter.rem; xcb_keycode_next(&iter), i++) + { + for (j = 0; j < 8; j++) + { + sym2 = xcb_key_symbols_get_keysym(symbols, *iter.data, j); + if (sym2 != 0) break; + } + if (sym2 == sym) + { + int mask; + + mask = masks[i]; + free(reply); + xcb_key_symbols_free(symbols); + return mask; + } + } + + free(reply); + xcb_key_symbols_free(symbols); + + return 0; +} + +typedef struct _Ecore_X_Filter_Data Ecore_X_Filter_Data; + +struct _Ecore_X_Filter_Data +{ + int last_event_type; +}; + +static void * +_ecore_xcb_event_filter_start(void *data __UNUSED__) +{ + Ecore_X_Filter_Data *filter_data; + + filter_data = calloc(1, sizeof(Ecore_X_Filter_Data)); + return filter_data; +} + +static int +_ecore_xcb_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__) +{ + Ecore_X_Filter_Data *filter_data; + + filter_data = loop_data; + if (!filter_data) return 1; + if (type == ECORE_X_EVENT_MOUSE_MOVE) + { + if ((filter_data->last_event_type) == ECORE_X_EVENT_MOUSE_MOVE) + { + filter_data->last_event_type = type; + return 0; + } + } + filter_data->last_event_type = type; + return 1; +} + +static void +_ecore_xcb_event_filter_end(void *data __UNUSED__, void *loop_data) +{ + Ecore_X_Filter_Data *filter_data; + + filter_data = loop_data; + if (filter_data) free(filter_data); +} + + + + + + + + + + + + + + + + + + + + + + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/* FIXME: these funcs need categorising */ +/*****************************************************************************/ + + + + +/** + * Get a list of all the root windows on the server. + * + * @note The returned array will need to be freed after use. + * @param num_ret Pointer to integer to put number of windows returned in. + * @return An array of all the root windows. @c NULL is returned if memory + * could not be allocated for the list, or if @p num_ret is @c NULL. + */ +EAPI Ecore_X_Window * +ecore_x_window_root_list(int *num_ret) +{ + xcb_screen_iterator_t iter; + const xcb_setup_t *setup; + uint8_t i; + uint8_t num; + Ecore_X_Window *roots; +/* #ifdef ECORE_XCBXPRINT */ +/* int xp_base, xp_err_base; */ +/* #endif /\* ECORE_XCBXPRINT *\/ */ + + if (!num_ret) return NULL; + *num_ret = 0; + + /* FIXME: todo... */ +/* #ifdef ECORE_XCBXPRINT */ +/* num = ScreenCount(_ecore_xcb_conn); */ +/* if (ecore_xcb_xprint_query()) */ +/* { */ +/* Screen **ps = NULL; */ +/* int psnum = 0; */ + +/* ps = XpQueryScreens(_ecore_xcb_conn, &psnum); */ +/* if (ps) */ +/* { */ +/* int overlap, j; */ + +/* overlap = 0; */ +/* for (i = 0; i < num; i++) */ +/* { */ +/* for (j = 0; j < psnum; j++) */ +/* { */ +/* if (ScreenOfDisplay(_ecore_xcb_conn, i) == ps[j]) */ +/* overlap++; */ +/* } */ +/* } */ +/* roots = malloc((num - overlap) * sizeof(Ecore_X_Window)); */ +/* if (roots) */ +/* { */ +/* int k; */ + +/* k = 0; */ +/* for (i = 0; i < num; i++) */ +/* { */ +/* int is_print; */ + +/* is_print = 0; */ +/* for (j = 0; j < psnum; j++) */ +/* { */ +/* if (ScreenOfDisplay(_ecore_xcb_conn, i) == ps[j]) */ +/* { */ +/* is_print = 1; */ +/* break; */ +/* } */ +/* } */ +/* if (!is_print) */ +/* { */ +/* roots[k] = RootWindow(_ecore_xcb_conn, i); */ +/* k++; */ +/* } */ +/* } */ +/* *num_ret = k; */ +/* } */ +/* XFree(ps); */ +/* } */ +/* else */ +/* { */ +/* roots = malloc(num * sizeof(Ecore_X_Window)); */ +/* if (!roots) return NULL; */ +/* *num_ret = num; */ +/* for (i = 0; i < num; i++) */ +/* roots[i] = RootWindow(_ecore_xcb_conn, i); */ +/* } */ +/* } */ +/* else */ +/* { */ +/* roots = malloc(num * sizeof(Ecore_X_Window)); */ +/* if (!roots) return NULL; */ +/* *num_ret = num; */ +/* for (i = 0; i < num; i++) */ +/* roots[i] = RootWindow(_ecore_xcb_conn, i); */ +/* } */ +/* #else */ + setup = xcb_get_setup (_ecore_xcb_conn); + iter = xcb_setup_roots_iterator (setup); + num = setup->roots_len; + roots = malloc(num * sizeof(Ecore_X_Window)); + if (!roots) return NULL; + + *num_ret = num; + for (i = 0; iter.rem; xcb_screen_next(&iter), i++) + roots[i] = iter.data->root; +/* #endif /\* ECORE_XCBXPRINT *\/ */ + + return roots; +} + +EAPI Ecore_X_Window +ecore_x_window_root_first_get(void) +{ + Ecore_X_Window *roots = NULL; + Ecore_X_Window root; + int num; + + roots = ecore_x_window_root_list(&num); + if(!(roots)) return 0; + + if (num > 0) + root = roots[0]; + else + root = 0; + + free(roots); + return root; +} + +/* FIXME: todo */ + +static void _ecore_x_window_manage_error(void *data); + +static int _ecore_xcb_window_manage_failed = 0; +static void +_ecore_x_window_manage_error(void *data __UNUSED__) +{ +/* if ((ecore_xcb_error_request_get() == X_ChangeWindowAttributes) && */ +/* (ecore_xcb_error_code_get() == BadAccess)) */ +/* _ecore_xcb_window_manage_failed = 1; */ +} + +/* FIXME: round trip */ +EAPI int +ecore_x_window_manage(Ecore_X_Window window) +{ + xcb_get_window_attributes_cookie_t cookie_attr; + xcb_get_input_focus_cookie_t cookie_sync; + xcb_get_window_attributes_reply_t *reply_attr; + xcb_get_input_focus_reply_t *reply_sync; + uint32_t value_list; + + cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); + cookie_sync = xcb_get_input_focus_unchecked(_ecore_xcb_conn); + + reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL); + if (!reply_attr) + { + reply_sync = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie_sync, NULL); + if (reply_sync) free(reply_sync); + return 0; + } + + reply_sync = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie_sync, NULL); + if (reply_sync) free(reply_sync); + + _ecore_xcb_window_manage_failed = 0; + /* FIXME: no error code yet */ + /* ecore_xcb_error_handler_set(_ecore_xcb_window_manage_error, NULL); */ + + value_list = + XCB_EVENT_MASK_KEY_PRESS | + XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | + XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_RESIZE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_PROPERTY_CHANGE | + reply_attr->your_event_mask; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_EVENT_MASK, + &value_list); + free(reply_attr); + + cookie_sync = xcb_get_input_focus_unchecked(_ecore_xcb_conn); + if (reply_sync) free(reply_sync); + + /* FIXME: no error code yet */ + /* ecore_xcb_error_handler_set(NULL, NULL); */ + if (_ecore_xcb_window_manage_failed) + { + _ecore_xcb_window_manage_failed = 0; + return 0; + } + + return 1; +} + + + + + + + + +EAPI int +ecore_x_pointer_control_set(int accel_num, + int accel_denom, + int threshold) +{ + xcb_change_pointer_control(_ecore_xcb_conn, + accel_num, accel_denom, threshold, + 1, 1); + return 1; +} + +EAPI void +ecore_x_pointer_control_get_prefetch(void) +{ + xcb_get_pointer_control_cookie_t cookie; + + cookie = xcb_get_pointer_control_unchecked(_ecore_xcb_conn); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +EAPI void +ecore_x_pointer_control_get_fetch(void) +{ + xcb_get_pointer_control_cookie_t cookie; + xcb_get_pointer_control_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_pointer_control_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +EAPI int +ecore_x_pointer_control_get(int *accel_num, + int *accel_denom, + int *threshold) +{ + xcb_get_pointer_control_reply_t *reply; + + if (accel_num) *accel_num = 0; + if (accel_denom) *accel_denom = 1; + if (threshold) *threshold = 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + if (accel_num) *accel_num = reply->acceleration_numerator; + if (accel_denom) *accel_denom = reply->acceleration_denominator; + if (threshold) *threshold = reply->threshold; + + return 1; +} + +EAPI int +ecore_x_pointer_grab(Ecore_X_Window window) +{ + xcb_grab_pointer_cookie_t cookie; + xcb_grab_pointer_reply_t *reply; + + cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, window, + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | + XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION, + XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC, + XCB_NONE, XCB_NONE, + XCB_CURRENT_TIME); + reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + return 0; + + free(reply); + + return 1; +} + +EAPI int +ecore_x_pointer_confine_grab(Ecore_X_Window window) +{ + xcb_grab_pointer_cookie_t cookie; + xcb_grab_pointer_reply_t *reply; + + cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, window, + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | + XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION, + XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC, + window, XCB_NONE, + XCB_CURRENT_TIME); + reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + return 0; + + free(reply); + + return 1; +} + +EAPI void +ecore_x_pointer_ungrab(void) +{ + xcb_ungrab_pointer(_ecore_xcb_conn, XCB_CURRENT_TIME); +} + +EAPI int +ecore_x_pointer_warp(Ecore_X_Window window, + int x, + int y) +{ + xcb_warp_pointer(_ecore_xcb_conn, XCB_NONE, window, 0, 0, 0, 0, x, y); + + return 1; +} + +EAPI int +ecore_x_keyboard_grab(Ecore_X_Window window) +{ + xcb_grab_keyboard_cookie_t cookie; + xcb_grab_keyboard_reply_t *reply; + + cookie = xcb_grab_keyboard_unchecked(_ecore_xcb_conn, 0, window, + XCB_CURRENT_TIME, + XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC); + reply = xcb_grab_keyboard_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + return 0; + + free(reply); + + return 1; +} + +EAPI void +ecore_x_keyboard_ungrab(void) +{ + xcb_ungrab_keyboard(_ecore_xcb_conn, XCB_CURRENT_TIME); +} + +EAPI void +ecore_x_grab(void) +{ + _ecore_xcb_grab_count++; + + if (_ecore_xcb_grab_count == 1) + xcb_grab_server(_ecore_xcb_conn); +} + +EAPI void +ecore_x_ungrab(void) +{ + _ecore_xcb_grab_count--; + if (_ecore_xcb_grab_count < 0) + _ecore_xcb_grab_count = 0; + + if (_ecore_xcb_grab_count == 0) + { + xcb_ungrab_server(_ecore_xcb_conn); + free(xcb_get_input_focus_reply(_ecore_xcb_conn, xcb_get_input_focus(_ecore_xcb_conn), NULL)); + } +} + +int _ecore_window_grabs_num = 0; +Ecore_X_Window *_ecore_window_grabs = NULL; +int (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event); +void *_ecore_window_grab_replay_data; + +EAPI void +ecore_x_passive_grab_replay_func_set(int (*func) (void *data, + int event_type, + void *event), + void *data) +{ + _ecore_window_grab_replay_func = func; + _ecore_window_grab_replay_data = data; +} + +EAPI void +ecore_x_window_button_grab(Ecore_X_Window window, + int button, + Ecore_X_Event_Mask event_mask, + int mod, + int any_mod) +{ + int i; + uint16_t m; + uint16_t locks[8]; + uint16_t ev; + + m = mod; + if (any_mod) m = XCB_BUTTON_MASK_ANY; + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + ev = event_mask; + for (i = 0; i < 8; i++) + xcb_grab_button(_ecore_xcb_conn, 0, window, ev, + XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, + XCB_NONE, XCB_NONE, button, m | locks[i]); + _ecore_window_grabs_num++; + _ecore_window_grabs = realloc(_ecore_window_grabs, + _ecore_window_grabs_num * sizeof(Ecore_X_Window)); + _ecore_window_grabs[_ecore_window_grabs_num - 1] = window; +} + +void +_ecore_x_sync_magic_send(int val, + Ecore_X_Window swindow) +{ + xcb_client_message_event_t ev; + + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 32; + ev.window = _ecore_xcb_private_window; + ev.type = 27777; + ev.data.data32[0] = 0x7162534; + ev.data.data32[1] = 0x10000000 + val; + ev.data.data32[2] = swindow; + + xcb_send_event(_ecore_xcb_conn, 0, _ecore_xcb_private_window, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +} + +void +_ecore_x_window_grab_remove(Ecore_X_Window window) +{ + int i, shuffle = 0; + + if (_ecore_window_grabs_num > 0) + { + for (i = 0; i < _ecore_window_grabs_num; i++) + { + if (shuffle) _ecore_window_grabs[i - 1] = _ecore_window_grabs[i]; + if ((!shuffle) && (_ecore_window_grabs[i] == window)) + shuffle = 1; + } + if (shuffle) + { + _ecore_window_grabs_num--; + _ecore_window_grabs = realloc(_ecore_window_grabs, + _ecore_window_grabs_num * sizeof(Ecore_X_Window)); + } + } +} + +EAPI void +ecore_x_window_button_ungrab(Ecore_X_Window window, + int button, + int mod, + int any_mod) +{ + int i; + uint16_t m; + uint16_t locks[8]; + + m = mod; + if (any_mod) m = XCB_BUTTON_MASK_ANY; + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + for (i = 0; i < 8; i++) + xcb_ungrab_button(_ecore_xcb_conn, button, window, m | locks[i]); + _ecore_x_sync_magic_send(1, window); +} + +int _ecore_key_grabs_num = 0; +Ecore_X_Window *_ecore_key_grabs = NULL; + +EAPI void +ecore_x_window_key_grab(Ecore_X_Window window, + const char *key, + int mod, + int any_mod) +{ + xcb_keycode_t keycode = 0; + uint16_t m; + uint16_t locks[8]; + int i; + + if (!strncmp(key, "Keycode-", 8)) + keycode = atoi(key + 8); + /* FIXME: TODO... */ + +/* else */ +/* { */ +/* KeySym keysym; */ + +/* keysym = XStringToKeysym(key); */ +/* if (keysym == NoSymbol) return; */ +/* keycode = XKeysymToKeycode(_ecore_xcb_conn, XStringToKeysym(key)); */ +/* } */ + if (keycode == 0) return; + + m = mod; + if (any_mod) m = XCB_BUTTON_MASK_ANY; + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + for (i = 0; i < 8; i++) + xcb_grab_key(_ecore_xcb_conn, 1, window, m | locks[i], keycode, + XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); + _ecore_key_grabs_num++; + _ecore_key_grabs = realloc(_ecore_key_grabs, + _ecore_key_grabs_num * sizeof(Ecore_X_Window)); + _ecore_key_grabs[_ecore_key_grabs_num - 1] = window; +} + +void +_ecore_x_key_grab_remove(Ecore_X_Window window) +{ + int i, shuffle = 0; + + if (_ecore_key_grabs_num > 0) + { + for (i = 0; i < _ecore_key_grabs_num; i++) + { + if (shuffle) _ecore_key_grabs[i - 1] = _ecore_key_grabs[i]; + if ((!shuffle) && (_ecore_key_grabs[i] == window)) + shuffle = 1; + } + if (shuffle) + { + _ecore_key_grabs_num--; + _ecore_key_grabs = realloc(_ecore_key_grabs, + _ecore_key_grabs_num * sizeof(Ecore_X_Window)); + } + } +} + +EAPI void +ecore_x_window_key_ungrab(Ecore_X_Window window, + const char *key, + int mod, + int any_mod) +{ + xcb_keycode_t keycode = 0; + uint16_t m; + uint16_t locks[8]; + int i; + + if (!strncmp(key, "Keycode-", 8)) + keycode = atoi(key + 8); + /* FIXME: todo... */ + +/* else */ +/* { */ +/* KeySym keysym; */ + +/* keysym = XStringToKeysym(key); */ +/* if (keysym == NoSymbol) return; */ +/* keycode = XKeysymToKeycode(_ecore_xcb_conn, XStringToKeysym(key)); */ +/* } */ + if (keycode == 0) return; + + m = mod; + if (any_mod) m = XCB_BUTTON_MASK_ANY; + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + for (i = 0; i < 8; i++) + xcb_ungrab_key(_ecore_xcb_conn, keycode, window, m | locks[i]); + _ecore_x_sync_magic_send(2, window); +} + +/** + * Send client message with given type and format 32. + * + * @param window The window the message is sent to. + * @param type The client message type. + * @param mask The client message mask. + * @param d0 The client message data item 1 + * @param d1 The client message data item 2 + * @param d2 The client message data item 3 + * @param d3 The client message data item 4 + * @param d4 The client message data item 5 + * + * @return !0 on success. + */ +EAPI int +ecore_x_client_message32_send(Ecore_X_Window window, + Ecore_X_Atom type, + Ecore_X_Event_Mask mask, + long d0, + long d1, + long d2, + long d3, + long d4) +{ + xcb_client_message_event_t ev; + + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 32; + ev.window = window; + ev.type = type; + ev.data.data32[0] = d0; + ev.data.data32[1] = d1; + ev.data.data32[2] = d2; + ev.data.data32[3] = d3; + ev.data.data32[4] = d4; + + xcb_send_event(_ecore_xcb_conn, 0, window, mask, (const char *)&ev); + + return 1; +} + +/** + * Send client message with given type and format 8. + * + * @param window The window the message is sent to. + * @param type The client message type. + * @param data Data to be sent. + * @param len Number of data bytes, max 20. + * + * @return !0 on success. + */ +EAPI int +ecore_x_client_message8_send(Ecore_X_Window window, + Ecore_X_Atom type, + const void *data, + int len) +{ + xcb_client_message_event_t ev; + + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 8; + ev.window = window; + ev.type = type; + if (len > 20) + len = 20; + memcpy(ev.data.data8, data, len); + memset(ev.data.data8 + len, 0, 20 - len); + + xcb_send_event(_ecore_xcb_conn, 0, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); + + return 1; +} + +/* FIXME: round trip */ +EAPI int +ecore_x_mouse_move_send(Ecore_X_Window window, + int x, + int y) +{ + xcb_motion_notify_event_t ev; + xcb_get_geometry_cookie_t cookie_geom; + xcb_translate_coordinates_cookie_t cookie_trans; + xcb_get_geometry_reply_t *reply_geom; + xcb_translate_coordinates_reply_t *reply_trans; + + cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window); + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (!reply_geom) return 0; + + cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y); + reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL); + if (!reply_trans) + { + free(reply_geom); + return 0; + } + + ev.response_type = XCB_MOTION_NOTIFY; + ev.detail = 0; + ev.time = _ecore_xcb_event_last_time; + ev.root = reply_geom->root; + ev.event = window; + ev.child = window; + ev.root_x = reply_trans->dst_x; + ev.root_y = reply_trans->dst_y; + ev.event_x = x; + ev.event_y = y; + ev.state = 0; + ev.same_screen = 1; + + xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_POINTER_MOTION, (const char *)&ev); + + free(reply_geom); + free(reply_trans); + + return 1; +} + +/* FIXME: round trip */ +EAPI int +ecore_x_mouse_down_send(Ecore_X_Window window, + int x, + int y, + int button) +{ + xcb_button_press_event_t ev; + xcb_get_geometry_cookie_t cookie_geom; + xcb_translate_coordinates_cookie_t cookie_trans; + xcb_get_geometry_reply_t *reply_geom; + xcb_translate_coordinates_reply_t *reply_trans; + + cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window); + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (!reply_geom) return 0; + + cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y); + reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL); + if (!reply_trans) + { + free(reply_geom); + return 0; + } + + ev.response_type = XCB_BUTTON_PRESS; + ev.detail = button; + ev.time = _ecore_xcb_event_last_time; + ev.root = reply_geom->root; + ev.event = window; + ev.child = window; + ev.root_x = reply_trans->dst_x; + ev.root_y = reply_trans->dst_y; + ev.event_x = x; + ev.event_y = y; + ev.state = 1 << button; + ev.same_screen = 1; + + xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_BUTTON_PRESS, (const char *)&ev); + + free(reply_geom); + free(reply_trans); + + return 1; +} + +/* FIXME: round trip */ +EAPI int +ecore_x_mouse_up_send(Ecore_X_Window window, + int x, + int y, + int button) +{ + xcb_button_release_event_t ev; + xcb_get_geometry_cookie_t cookie_geom; + xcb_translate_coordinates_cookie_t cookie_trans; + xcb_get_geometry_reply_t *reply_geom; + xcb_translate_coordinates_reply_t *reply_trans; + + cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window); + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (!reply_geom) return 0; + + cookie_trans = xcb_translate_coordinates_unchecked(_ecore_xcb_conn, window, reply_geom->root, x, y); + reply_trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie_trans, NULL); + if (!reply_trans) + { + free(reply_geom); + return 0; + } + + ev.response_type = XCB_BUTTON_RELEASE; + ev.detail = button; + ev.time = _ecore_xcb_event_last_time; + ev.root = reply_geom->root; + ev.event = window; + ev.child = window; + ev.root_x = reply_trans->dst_x; + ev.root_y = reply_trans->dst_y; + ev.event_x = x; + ev.event_y = y; + ev.state = 0; + ev.same_screen = 1; + + xcb_send_event(_ecore_xcb_conn, 1, window, XCB_EVENT_MASK_BUTTON_RELEASE, (const char *)&ev); + + free(reply_geom); + free(reply_trans); + + return 1; +} + +EAPI void +ecore_x_focus_reset(void) +{ + xcb_set_input_focus(_ecore_xcb_conn, + (uint8_t)XCB_INPUT_FOCUS_POINTER_ROOT, + XCB_INPUT_FOCUS_POINTER_ROOT, + XCB_CURRENT_TIME); +} + +EAPI void +ecore_x_events_allow_all(void) +{ + xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_BOTH, XCB_CURRENT_TIME); +} + +EAPI void +ecore_x_pointer_last_xy_get(int *x, + int *y) +{ + if (x) *x = _ecore_xcb_event_last_root_x; + if (y) *y = _ecore_xcb_event_last_root_y; +} + + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_atom.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_atom.c new file mode 100644 index 0000000000..00d09c7c59 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_atom.c @@ -0,0 +1,607 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_Atom_Group XCB Atom Functions + * + * Functions that operate on atoms. + */ + +#define ECORE_X_ATOMS_COUNT 115 +static xcb_intern_atom_cookie_t ecore_xcb_atom_init_cookies[ECORE_X_ATOMS_COUNT]; + + +/*********/ +/* Atoms */ +/*********/ + +/* generic atoms */ +EAPI Ecore_X_Atom ECORE_X_ATOM_ATOM = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_CARDINAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_FILE_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_STRING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEXT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_UTF8_STRING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WINDOW = 0; + +/* dnd atoms */ +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_XDND = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_XDND = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_AWARE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ENTER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_TYPE_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_POSITION = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_COPY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_MOVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_PRIVATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_ASK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LINK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_DESCRIPTION = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_PROXY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_STATUS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_LEAVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_DROP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_FINISHED = 0; + +/* dnd atoms that need to be exposed to the application interface */ +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_COPY = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_MOVE = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_LINK = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_ASK = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE = 0; + +/* old E atom */ +EAPI Ecore_X_Atom ECORE_X_ATOM_E_FRAME_SIZE = 0; + +/* old Gnome atom */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WIN_LAYER = 0; + +/* ICCCM atoms */ + +/* ICCCM: client properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_ICON_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_NORMAL_HINTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_SIZE_HINTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_HINTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CLASS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_TRANSIENT_FOR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_PROTOCOLS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_WINDOWS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_COMMAND = 0; /* obsolete */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_MACHINE = 0; /* obsolete */ + +/* ICCCM: window manager properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_ICON_SIZE = 0; + +/* ICCCM: WM_STATE property */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CHANGE_STATE = 0; + +/* ICCCM: WM_PROTOCOLS properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_TAKE_FOCUS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_SAVE_YOURSELF = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_DELETE_WINDOW = 0; + +/* ICCCM: WM_COLORMAP properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_NOTIFY = 0; + +/* ICCCM: session management properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_SM_CLIENT_ID = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_LEADER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_WINDOW_ROLE = 0; + +/* Motif WM atom */ +EAPI Ecore_X_Atom ECORE_X_ATOM_MOTIF_WM_HINTS = 0; + +/* NetWM 1.3 atoms (http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html) */ + +/* + * NetWM: Root Window Properties and related messages (complete) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST_STACKING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_VIEWPORT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CURRENT_DESKTOP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_NAMES = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_ACTIVE_WINDOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WORKAREA = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_VIRTUAL_ROOTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_LAYOUT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_SHOWING_DESKTOP = 0; + +/* + * NetWM: Other Root Window Messages (complete) + */ + +/* pager */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CLOSE_WINDOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_MOVERESIZE_WINDOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_MOVERESIZE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_RESTACK_WINDOW = 0; + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS = 0; + +/* + * NetWM: Application Window Properties (complete) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_DESKTOP = 0; + +/* window type */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL = 0; + +/* state */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MODAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_STICKY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SHADED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_HIDDEN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_ABOVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_BELOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION = 0; + +/* allowed actions */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MOVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_RESIZE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_SHADE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_STICK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CLOSE = 0; + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT_PARTIAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_PID = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_HANDLED_ICONS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_USER_TIME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_ID = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_FRAME_EXTENTS = 0; + +/* + * NetWM: Window Manager Protocols (complete) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_PING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER = 0; + +/* + * NetWM: Not in the spec + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_OPACITY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADE = 0; + +/* + * Startup Notification (http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO = 0; + +/* selection atoms */ +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_PRIMARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_SECONDARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD = 0; + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_atom_init and + _ecore_xcb_atom_init_finalize. The first one gets the cookies and + the second one gets the replies and set the atoms. */ + +void +_ecore_x_atom_init(void) +{ + const char *atom_names[ECORE_X_ATOMS_COUNT] = { + /* generic atoms */ + "COMPOUND_TEXT", + "FILE_NAME", + "TEXT", + "UTF8_STRING", + + /* dnd atoms */ + "JXSelectionWindowProperty", + "XdndSelection", + "XdndAware", + "XdndEnter", + "XdndTypeList", + "XdndPosition", + "XdndActionCopy", + "XdndActionMove", + "XdndActionPrivate", + "XdndActionAsk", + "XdndActionList", + "XdndActionLink", + "XdndActionDescription", + "XdndProxy", + "XdndStatus", + "XdndLeave", + "XdndDrop", + "XdndFinished", + + /* old E atom */ + "_E_FRAME_SIZE", + + /* old Gnome atom */ + "_WIN_LAYER", + + /* ICCCM */ + "WM_PROTOCOLS", + "WM_COLORMAP_WINDOWS", + + "WM_STATE", + + "WM_CHANGE_STATE", + + "WM_TAKE_FOCUS", + "WM_SAVE_YOURSELF", + "WM_DELETE_WINDOW", + + "WM_COLORMAP_NOTIFY", + + "SM_CLIENT_ID", + "WM_CLIENT_LEADER", + "WM_WINDOW_ROLE", + + /* Motif WM atom */ + "_MOTIF_WM_HINTS", + + /* NetWM atoms */ + "_NET_SUPPORTED", + "_NET_CLIENT_LIST", + "_NET_CLIENT_LIST_STACKING", + "_NET_NUMBER_OF_DESKTOPS", + "_NET_DESKTOP_GEOMETRY", + "_NET_DESKTOP_VIEWPORT", + "_NET_CURRENT_DESKTOP", + "_NET_DESKTOP_NAMES", + "_NET_ACTIVE_WINDOW", + "_NET_WORKAREA", + "_NET_SUPPORTING_WM_CHECK", + "_NET_VIRTUAL_ROOTS", + "_NET_DESKTOP_LAYOUT", + "_NET_SHOWING_DESKTOP", + + "_NET_CLOSE_WINDOW", + "_NET_MOVERESIZE_WINDOW", + "_NET_WM_MOVERESIZE", + "_NET_RESTACK_WINDOW", + "_NET_REQUEST_FRAME_EXTENTS", + + "_NET_WM_NAME", + "_NET_WM_VISIBLE_NAME", + "_NET_WM_ICON_NAME", + "_NET_WM_VISIBLE_ICON_NAME", + "_NET_WM_DESKTOP", + + "_NET_WM_WINDOW_TYPE", + "_NET_WM_WINDOW_TYPE_DESKTOP", + "_NET_WM_WINDOW_TYPE_DOCK", + "_NET_WM_WINDOW_TYPE_TOOLBAR", + "_NET_WM_WINDOW_TYPE_MENU", + "_NET_WM_WINDOW_TYPE_UTILITY", + "_NET_WM_WINDOW_TYPE_SPLASH", + "_NET_WM_WINDOW_TYPE_DIALOG", + "_NET_WM_WINDOW_TYPE_NORMAL", + + "_NET_WM_STATE", + "_NET_WM_STATE_MODAL", + "_NET_WM_STATE_STICKY", + "_NET_WM_STATE_MAXIMIZED_VERT", + "_NET_WM_STATE_MAXIMIZED_HORZ", + "_NET_WM_STATE_SHADED", + "_NET_WM_STATE_SKIP_TASKBAR", + "_NET_WM_STATE_SKIP_PAGER", + "_NET_WM_STATE_HIDDEN", + "_NET_WM_STATE_FULLSCREEN", + "_NET_WM_STATE_ABOVE", + "_NET_WM_STATE_BELOW", + "_NET_WM_STATE_DEMANDS_ATTENTION", + + "_NET_WM_ALLOWED_ACTIONS", + "_NET_WM_ACTION_MOVE", + "_NET_WM_ACTION_RESIZE", + "_NET_WM_ACTION_MINIMIZE", + "_NET_WM_ACTION_SHADE", + "_NET_WM_ACTION_STICK", + "_NET_WM_ACTION_MAXIMIZE_HORZ", + "_NET_WM_ACTION_MAXIMIZE_VERT", + "_NET_WM_ACTION_FULLSCREEN", + "_NET_WM_ACTION_CHANGE_DESKTOP", + "_NET_WM_ACTION_CLOSE", + + "_NET_WM_STRUT", + "_NET_WM_STRUT_PARTIAL", + "_NET_WM_ICON_GEOMETRY", + "_NET_WM_ICON", + "_NET_WM_PID", + "_NET_WM_HANDLED_ICONS", + "_NET_WM_USER_TIME", + "_NET_STARTUP_ID", + "_NET_FRAME_EXTENTS", + + "_NET_WM_PING", + "_NET_WM_SYNC_REQUEST", + "_NET_WM_SYNC_REQUEST_COUNTER", + + "_NET_WM_WINDOW_OPACITY", + "_NET_WM_WINDOW_SHADOW", + "_NET_WM_WINDOW_SHADE", + + "_NET_STARTUP_INFO_BEGIN", + "_NET_STARTUP_INFO", + + /* selection atoms */ + "TARGETS", + "CLIPBOARD", + "_ECORE_SELECTION_PRIMARY", + "_ECORE_SELECTION_SECONDARY", + "_ECORE_SELECTION_CLIPBOARD" + }; + int i; + + for (i = 0; i < ECORE_X_ATOMS_COUNT; i++) + ecore_xcb_atom_init_cookies[i] = xcb_intern_atom(_ecore_xcb_conn, 0, + strlen(atom_names[i]), + atom_names[i]); + + /* These atoms are already internally defined */ + ECORE_X_ATOM_SELECTION_PRIMARY = 1; + ECORE_X_ATOM_SELECTION_SECONDARY = 2; + ECORE_X_ATOM_ATOM = 4; + ECORE_X_ATOM_CARDINAL = 6; + ECORE_X_ATOM_STRING = 31; + ECORE_X_ATOM_WINDOW = 33; + ECORE_X_ATOM_WM_NAME = 39; + ECORE_X_ATOM_WM_ICON_NAME = 37; + ECORE_X_ATOM_WM_NORMAL_HINTS = 40; + ECORE_X_ATOM_WM_SIZE_HINTS = 41; + ECORE_X_ATOM_WM_HINTS = 35; + ECORE_X_ATOM_WM_CLASS = 67; + ECORE_X_ATOM_WM_TRANSIENT_FOR = 68; + ECORE_X_ATOM_WM_COMMAND = 34; + ECORE_X_ATOM_WM_CLIENT_MACHINE = 36; + ECORE_X_ATOM_WM_ICON_SIZE = 38; + + /* Initialize the globally defined xdnd atoms */ + ECORE_X_DND_ACTION_COPY = ECORE_X_ATOM_XDND_ACTION_COPY; + ECORE_X_DND_ACTION_MOVE = ECORE_X_ATOM_XDND_ACTION_MOVE; + ECORE_X_DND_ACTION_LINK = ECORE_X_ATOM_XDND_ACTION_LINK; + ECORE_X_DND_ACTION_ASK = ECORE_X_ATOM_XDND_ACTION_ASK; + ECORE_X_DND_ACTION_PRIVATE = ECORE_X_ATOM_XDND_ACTION_PRIVATE; +} + +void +_ecore_x_atom_init_finalize(void) +{ + xcb_intern_atom_reply_t *replies[ECORE_X_ATOMS_COUNT]; + int i; + + for (i = 0; i < ECORE_X_ATOMS_COUNT; i++) { + xcb_generic_error_t *error = NULL; + + replies[i] = xcb_intern_atom_reply(_ecore_xcb_conn, + ecore_xcb_atom_init_cookies[i], + &error); + if (!replies[i]) { + printf ("pas de reply %d\n", i); + if (error) + printf ("Error !\n"); + } + } + + ECORE_X_ATOM_COMPOUND_TEXT = replies[0]->atom; + ECORE_X_ATOM_FILE_NAME = replies[1]->atom; + ECORE_X_ATOM_TEXT = replies[2]->atom; + ECORE_X_ATOM_UTF8_STRING = replies[3]->atom; + ECORE_X_ATOM_SELECTION_PROP_XDND = replies[4]->atom; + ECORE_X_ATOM_SELECTION_XDND = replies[5]->atom; + ECORE_X_ATOM_XDND_AWARE = replies[6]->atom; + ECORE_X_ATOM_XDND_ENTER = replies[7]->atom; + ECORE_X_ATOM_XDND_TYPE_LIST = replies[8]->atom; + ECORE_X_ATOM_XDND_POSITION = replies[9]->atom; + ECORE_X_ATOM_XDND_ACTION_COPY = replies[10]->atom; + ECORE_X_ATOM_XDND_ACTION_MOVE = replies[11]->atom; + ECORE_X_ATOM_XDND_ACTION_PRIVATE = replies[12]->atom; + ECORE_X_ATOM_XDND_ACTION_ASK = replies[13]->atom; + ECORE_X_ATOM_XDND_ACTION_LIST = replies[14]->atom; + ECORE_X_ATOM_XDND_ACTION_LINK = replies[15]->atom; + ECORE_X_ATOM_XDND_ACTION_DESCRIPTION = replies[16]->atom; + ECORE_X_ATOM_XDND_PROXY = replies[17]->atom; + ECORE_X_ATOM_XDND_STATUS = replies[18]->atom; + ECORE_X_ATOM_XDND_LEAVE = replies[19]->atom; + ECORE_X_ATOM_XDND_DROP = replies[20]->atom; + ECORE_X_ATOM_XDND_FINISHED = replies[21]->atom; + ECORE_X_ATOM_E_FRAME_SIZE = replies[22]->atom; + ECORE_X_ATOM_WIN_LAYER = replies[23]->atom; + ECORE_X_ATOM_WM_PROTOCOLS = replies[24]->atom; + ECORE_X_ATOM_WM_COLORMAP_WINDOWS = replies[25]->atom; + ECORE_X_ATOM_WM_STATE = replies[26]->atom; + ECORE_X_ATOM_WM_CHANGE_STATE = replies[27]->atom; + ECORE_X_ATOM_WM_TAKE_FOCUS = replies[28]->atom; + ECORE_X_ATOM_WM_SAVE_YOURSELF = replies[29]->atom; + ECORE_X_ATOM_WM_DELETE_WINDOW = replies[30]->atom; + ECORE_X_ATOM_WM_COLORMAP_NOTIFY = replies[31]->atom; + ECORE_X_ATOM_SM_CLIENT_ID = replies[32]->atom; + ECORE_X_ATOM_WM_CLIENT_LEADER = replies[33]->atom; + ECORE_X_ATOM_WM_WINDOW_ROLE = replies[34]->atom; + ECORE_X_ATOM_MOTIF_WM_HINTS = replies[35]->atom; + ECORE_X_ATOM_NET_SUPPORTED = replies[36]->atom; + ECORE_X_ATOM_NET_CLIENT_LIST = replies[37]->atom; + ECORE_X_ATOM_NET_CLIENT_LIST_STACKING = replies[38]->atom; + ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS = replies[39]->atom; + ECORE_X_ATOM_NET_DESKTOP_GEOMETRY = replies[40]->atom; + ECORE_X_ATOM_NET_DESKTOP_VIEWPORT = replies[41]->atom; + ECORE_X_ATOM_NET_CURRENT_DESKTOP = replies[42]->atom; + ECORE_X_ATOM_NET_DESKTOP_NAMES = replies[43]->atom; + ECORE_X_ATOM_NET_ACTIVE_WINDOW = replies[44]->atom; + ECORE_X_ATOM_NET_WORKAREA = replies[45]->atom; + ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK = replies[46]->atom; + ECORE_X_ATOM_NET_VIRTUAL_ROOTS = replies[47]->atom; + ECORE_X_ATOM_NET_DESKTOP_LAYOUT = replies[48]->atom; + ECORE_X_ATOM_NET_SHOWING_DESKTOP = replies[49]->atom; + ECORE_X_ATOM_NET_CLOSE_WINDOW = replies[50]->atom; + ECORE_X_ATOM_NET_MOVERESIZE_WINDOW = replies[51]->atom; + ECORE_X_ATOM_NET_WM_MOVERESIZE = replies[52]->atom; + ECORE_X_ATOM_NET_RESTACK_WINDOW = replies[53]->atom; + ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS = replies[54]->atom; + ECORE_X_ATOM_NET_WM_NAME = replies[55]->atom; + ECORE_X_ATOM_NET_WM_VISIBLE_NAME = replies[56]->atom; + ECORE_X_ATOM_NET_WM_ICON_NAME = replies[57]->atom; + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME = replies[58]->atom; + ECORE_X_ATOM_NET_WM_DESKTOP = replies[59]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE = replies[60]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP = replies[61]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK = replies[62]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR = replies[63]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU = replies[64]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY = replies[65]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH = replies[66]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG = replies[67]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL = replies[68]->atom; + ECORE_X_ATOM_NET_WM_STATE = replies[69]->atom; + ECORE_X_ATOM_NET_WM_STATE_MODAL = replies[70]->atom; + ECORE_X_ATOM_NET_WM_STATE_STICKY = replies[71]->atom; + ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT = replies[72]->atom; + ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ = replies[73]->atom; + ECORE_X_ATOM_NET_WM_STATE_SHADED = replies[74]->atom; + ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR = replies[75]->atom; + ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER = replies[76]->atom; + ECORE_X_ATOM_NET_WM_STATE_HIDDEN = replies[77]->atom; + ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN = replies[78]->atom; + ECORE_X_ATOM_NET_WM_STATE_ABOVE = replies[79]->atom; + ECORE_X_ATOM_NET_WM_STATE_BELOW = replies[80]->atom; + ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION = replies[81]->atom; + ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS = replies[82]->atom; + ECORE_X_ATOM_NET_WM_ACTION_MOVE = replies[83]->atom; + ECORE_X_ATOM_NET_WM_ACTION_RESIZE = replies[84]->atom; + ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE = replies[85]->atom; + ECORE_X_ATOM_NET_WM_ACTION_SHADE = replies[86]->atom; + ECORE_X_ATOM_NET_WM_ACTION_STICK = replies[87]->atom; + ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ = replies[88]->atom; + ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT = replies[89]->atom; + ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN = replies[90]->atom; + ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP = replies[91]->atom; + ECORE_X_ATOM_NET_WM_ACTION_CLOSE = replies[92]->atom; + ECORE_X_ATOM_NET_WM_STRUT = replies[93]->atom; + ECORE_X_ATOM_NET_WM_STRUT_PARTIAL = replies[94]->atom; + ECORE_X_ATOM_NET_WM_ICON_GEOMETRY = replies[95]->atom; + ECORE_X_ATOM_NET_WM_ICON = replies[96]->atom; + ECORE_X_ATOM_NET_WM_PID = replies[97]->atom; + ECORE_X_ATOM_NET_WM_HANDLED_ICONS = replies[98]->atom; + ECORE_X_ATOM_NET_WM_USER_TIME = replies[99]->atom; + ECORE_X_ATOM_NET_STARTUP_ID = replies[100]->atom; + ECORE_X_ATOM_NET_FRAME_EXTENTS = replies[101]->atom; + ECORE_X_ATOM_NET_WM_PING = replies[102]->atom; + ECORE_X_ATOM_NET_WM_SYNC_REQUEST = replies[103]->atom; + ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER = replies[104]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_OPACITY = replies[105]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_SHADOW = replies[106]->atom; + ECORE_X_ATOM_NET_WM_WINDOW_SHADE = replies[107]->atom; + ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN = replies[108]->atom; + ECORE_X_ATOM_NET_STARTUP_INFO = replies[109]->atom; + ECORE_X_ATOM_SELECTION_TARGETS = replies[110]->atom; + ECORE_X_ATOM_SELECTION_CLIPBOARD = replies[111]->atom; + ECORE_X_ATOM_SELECTION_PROP_PRIMARY = replies[112]->atom; + ECORE_X_ATOM_SELECTION_PROP_SECONDARY = replies[113]->atom; + ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD = replies[114]->atom; + + for (i = 0; i < ECORE_X_ATOMS_COUNT; i++) + free(replies[i]); +} + + +/** + * Sends the InternAtom request. + * @param name Name of the requested atom. + * @ingroup Ecore_X_Atom_Group + */ +EAPI void +ecore_x_atom_get_prefetch(const char *name) +{ + xcb_intern_atom_cookie_t cookie; + + cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, strlen(name), name); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the InternAtom request sent by ecore_x_atom_get_prefetch(). + * @ingroup Ecore_X_Atom_Group + */ +EAPI void +ecore_x_atom_get_fetch(void) +{ + xcb_intern_atom_cookie_t cookie; + xcb_intern_atom_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Retrieves the atom value associated to a name. + * @param name Unused. + * @return Associated atom value. + * + * Retrieves the atom value associated to a name. The reply is the + * returned value of the function ecore_xcb_intern_atom_reply(). If + * @p reply is @c NULL, the NULL atom is returned. Otherwise, the atom + * associated to the name is returned. + * + * To use this function, you must call before, and in order, + * ecore_x_atom_get_prefetch(), which sends the InternAtom request, + * then ecore_x_atom_get_fetch(), which gets the reply. + * @ingroup Ecore_X_Atom_Group + */ +EAPI Ecore_X_Atom +ecore_x_atom_get(const char *name __UNUSED__) +{ + xcb_intern_atom_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return XCB_NONE; + + return reply->atom; +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_cursor.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_cursor.c new file mode 100644 index 0000000000..d0cf49324c --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_cursor.c @@ -0,0 +1,270 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" +#include +#include + + +extern int _ecore_xcb_xcursor; + + +EAPI int +ecore_x_cursor_color_supported_get(void) +{ + return _ecore_xcb_xcursor; +} + +EAPI Ecore_X_Cursor +ecore_x_cursor_new(Ecore_X_Window window, + int *pixels, + int w, + int h, + int hot_x, + int hot_y) +{ + Ecore_X_Cursor cursor = 0; + +#ifdef ECORE_XCB_CURSOR + if (_ecore_x_xcursor) + { + Cursor c; + XcursorImage *xci; + + xci = XcursorImageCreate(w, h); + if (xci) + { + int i; + + xci->xhot = hot_x; + xci->yhot = hot_y; + xci->delay = 0; + for (i = 0; i < (w * h); i++) + { +// int r, g, b, a; +// +// a = (pixels[i] >> 24) & 0xff; +// r = (((pixels[i] >> 16) & 0xff) * a) / 0xff; +// g = (((pixels[i] >> 8 ) & 0xff) * a) / 0xff; +// b = (((pixels[i] ) & 0xff) * a) / 0xff; + xci->pixels[i] = pixels[i]; +// (a << 24) | (r << 16) | (g << 8) | (b); + } + c = XcursorImageLoadCursor(_ecore_x_disp, xci); + XcursorImageDestroy(xci); + return c; + } + } + else +#endif /* ECORE_XCB_CURSOR */ + { + const uint32_t dither[2][2] = + { + {0, 2}, + {3, 1} + }; + Ecore_X_Drawable draw; + Ecore_X_Pixmap pixmap; + Ecore_X_Pixmap mask; + Ecore_X_GC gc; + xcb_image_t *image; + uint32_t *pix; + uint8_t fr; + uint8_t fg; + uint8_t fb; + uint8_t br; + uint8_t bg; + uint8_t bb; + uint32_t brightest = 0; + uint32_t darkest = 255 * 3; + uint16_t x; + uint16_t y; + + draw = window; + pixmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, + 1, pixmap, draw, + 1, 1); + mask = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, + 1, mask, draw, + 1, 1); + + image = xcb_image_create(_ecore_xcb_conn, 1, + XCB_IMAGE_FORMAT_Z_PIXMAP, 0, + NULL, w, h, 32, 0); + image->data = malloc(image->bytes_per_line * image->height); + + fr = 0x00; fg = 0x00; fb = 0x00; + br = 0xff; bg = 0xff; bb = 0xff; + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint8_t r, g, b, a; + + a = (pix[0] >> 24) & 0xff; + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8 ) & 0xff; + b = (pix[0] ) & 0xff; + if (a > 0) + { + if ((uint32_t)(r + g + b) > brightest) + { + brightest = r + g + b; + br = r; + bg = g; + bb = b; + } + if ((uint32_t)(r + g + b) < darkest) + { + darkest = r + g + b; + fr = r; + fg = g; + fb = b; + } + } + pix++; + } + } + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint32_t v; + uint8_t r, g, b; + int32_t d1, d2; + + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8 ) & 0xff; + b = (pix[0] ) & 0xff; + d1 = + ((r - fr) * (r - fr)) + + ((g - fg) * (g - fg)) + + ((b - fb) * (b - fb)); + d2 = + ((r - br) * (r - br)) + + ((g - bg) * (g - bg)) + + ((b - bb) * (b - bb)); + if (d1 + d2) + { + v = (((d2 * 255) / (d1 + d2)) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) v = 1; + else v = 0; + } + else + { + v = 0; + } + xcb_image_put_pixel(image, x, y, v); + pix++; + } + } + draw = pixmap; + gc = xcb_generate_id(_ecore_xcb_conn); + xcb_create_gc(_ecore_xcb_conn, gc, draw, 0, NULL); + xcb_image_put(_ecore_xcb_conn, draw, gc, image, 0, 0, 0, 0, w, h); + xcb_free_gc(_ecore_xcb_conn, gc); + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint32_t v; + + v = (((pix[0] >> 24) & 0xff) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) v = 1; + else v = 0; + xcb_image_put_pixel(image, x, y, v); + pix++; + } + } + draw = mask; + gc = xcb_generate_id(_ecore_xcb_conn); + xcb_create_gc (_ecore_xcb_conn, gc, draw, 0, NULL); + xcb_image_put(_ecore_xcb_conn, draw, gc, image, 0, 0, 0, 0, w, h); + xcb_free_gc(_ecore_xcb_conn, gc); + + free(image->data); + image->data = NULL; + xcb_image_destroy(image); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_create_cursor (_ecore_xcb_conn, cursor, + pixmap, mask, + fr << 8 | fr, + fg << 8 | fg, + fb << 8 | fb, + br << 8 | br, + bg << 8 | bg, + bb << 8 | bb, + hot_x, + hot_y); + xcb_free_pixmap(_ecore_xcb_conn, pixmap); + xcb_free_pixmap(_ecore_xcb_conn, mask); + + return cursor; + } + return 0; +} + +EAPI void +ecore_x_cursor_free(Ecore_X_Cursor cursor) +{ + xcb_free_cursor(_ecore_xcb_conn, cursor); +} + +/* + * Returns the cursor for the given shape. + * Note that the return value must not be freed with + * ecore_x_cursor_free()! + */ +EAPI Ecore_X_Cursor +ecore_x_cursor_shape_get(int shape) +{ + Ecore_X_Cursor cursor; + xcb_font_t font; + + /* Shapes are defined in Ecore_X_Cursor.h */ + font = xcb_generate_id(_ecore_xcb_conn); + xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor"); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_create_glyph_cursor (_ecore_xcb_conn, + cursor, + font, + font, + shape, + shape + 1, + 0, 0, 0, + 65535, 65535, 65535); + + xcb_close_font(_ecore_xcb_conn, font); + + return cursor; +} + +EAPI void +ecore_x_cursor_size_set(int size) +{ +#ifdef ECORE_XCB_CURSOR + XcursorSetDefaultSize(_ecore_x_disp, size); +#else + size = 0; +#endif /* ECORE_XCB_CURSOR */ +} + +EAPI int +ecore_x_cursor_size_get(void) +{ +#ifdef ECORE_XCB_CURSOR + return XcursorGetDefaultSize(_ecore_x_disp); +#else + return 0; +#endif /* ECORE_XCB_CURSOR */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_damage.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_damage.c new file mode 100644 index 0000000000..d5b0c6663a --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_damage.c @@ -0,0 +1,138 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_Damage_Group X Damage Extension Functions + * + * Functions related to the X Damage extension. + */ + + +#ifdef ECORE_XCB_DAMAGE +static uint8_t _damage_available = 0; +static xcb_damage_query_version_cookie_t _ecore_xcb_damage_init_cookie; +#endif /* ECORE_XCB_DAMAGE */ + + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_damage_init and + _ecore_xcb_damage_init_finalize. The first one gets the cookies and + the second one gets the replies. */ + +void +_ecore_x_damage_init(const xcb_query_extension_reply_t *reply) +{ +#ifdef ECORE_XCB_DAMAGE + if (reply && (reply->present)) + _ecore_xcb_damage_init_cookie = xcb_damage_query_version_unchecked(_ecore_xcb_conn, 1, 1); +#endif /* ECORE_XCB_DAMAGE */ +} + +void +_ecore_x_damage_init_finalize(void) +{ +#ifdef ECORE_XCB_DAMAGE + xcb_damage_query_version_reply_t *reply; + + reply = xcb_damage_query_version_reply(_ecore_xcb_conn, + _ecore_xcb_damage_init_cookie, + NULL); + if (reply) + { + if (reply->major_version >= 1) + _damage_available = 1; + free(reply); + } +#endif /* ECORE_XCB_DAMAGE */ +} + + +/** + * Return whether the Damage Extension is available. + * @return 1 if the Damage Extension is available, 0 if not. + * + * Return 1 if the X server supports the Damage Extension version 1.0, + * 0 otherwise. + * @ingroup Ecore_X_Damage_Group + */ +EAPI int +ecore_x_damage_query(void) +{ +#ifdef ECORE_XCB_DAMAGE + return _damage_available; +#else + return 0; +#endif /* ECORE_XCB_DAMAGE */ +} + + +/** + * Creates a damage object. + * @param drawable The drawable to monotor. + * @param level The level of the damage report. + * @return The damage object. + * + * Creates a damage object to monitor changes to @p drawable, with the + * level @p level. + * @ingroup Ecore_X_Damage_Group + */ +EAPI Ecore_X_Damage +ecore_x_damage_new(Ecore_X_Drawable drawable, + Ecore_X_Damage_Report_Level level) +{ + Ecore_X_Damage damage = 0; + +#ifdef ECORE_XCB_DAMAGE + damage = xcb_generate_id(_ecore_xcb_conn); + xcb_damage_create(_ecore_xcb_conn, damage, drawable, level); +#endif /* ECORE_XCB_DAMAGE */ + + return damage; +} + + +/** + * Destroys a damage object. + * @param damage The damage object to destroy. + * + * Destroys the damage object @p damage. + * @ingroup Ecore_X_Damage_Group + */ +EAPI void +ecore_x_damage_del(Ecore_X_Damage damage) +{ +#ifdef ECORE_XCB_DAMAGE + xcb_damage_destroy(_ecore_xcb_conn, damage); +#endif /* ECORE_XCB_DAMAGE */ +} + + +/** + * Synchronously modifies the region. + * @param damage The damage object to destroy. + * @param repair The repair region. + * @param parts The parts region. + * + * Synchronously modifies the regions in the following manner: + * If @p repair is @c XCB_NONE: + * 1) parts = damage + * 2) damage = + * Otherwise: + * 1) parts = damage INTERSECT repair + * 2) damage = damage - parts + * 3) Generate DamageNotify for remaining damage areas + * @ingroup Ecore_X_Damage_Group + */ +EAPI void +ecore_x_damage_subtract(Ecore_X_Damage damage, + Ecore_X_Region repair, + Ecore_X_Region parts) +{ +#ifdef ECORE_XCB_DAMAGE + xcb_damage_subtract(_ecore_xcb_conn, damage, repair, parts); +#endif /* ECORE_XCB_DAMAGE */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_dnd.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_dnd.c new file mode 100644 index 0000000000..c0324b8eff --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_dnd.c @@ -0,0 +1,749 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "Ecore.h" +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + + +EAPI int ECORE_X_EVENT_XDND_ENTER = 0; +EAPI int ECORE_X_EVENT_XDND_POSITION = 0; +EAPI int ECORE_X_EVENT_XDND_STATUS = 0; +EAPI int ECORE_X_EVENT_XDND_LEAVE = 0; +EAPI int ECORE_X_EVENT_XDND_DROP = 0; +EAPI int ECORE_X_EVENT_XDND_FINISHED = 0; + +static Ecore_X_DND_Source *_source = NULL; +static Ecore_X_DND_Target *_target = NULL; +static int _ecore_x_dnd_init_count = 0; + + +void +_ecore_x_dnd_init(void) +{ + if (!_ecore_x_dnd_init_count) + { + + _source = calloc(1, sizeof(Ecore_X_DND_Source)); + _source->version = ECORE_X_DND_VERSION; + _source->win = XCB_NONE; + _source->dest = XCB_NONE; + _source->state = ECORE_X_DND_SOURCE_IDLE; + + _target = calloc(1, sizeof(Ecore_X_DND_Target)); + _target->win = XCB_NONE; + _target->source = XCB_NONE; + _target->state = ECORE_X_DND_TARGET_IDLE; + + ECORE_X_EVENT_XDND_ENTER = ecore_event_type_new(); + ECORE_X_EVENT_XDND_POSITION = ecore_event_type_new(); + ECORE_X_EVENT_XDND_STATUS = ecore_event_type_new(); + ECORE_X_EVENT_XDND_LEAVE = ecore_event_type_new(); + ECORE_X_EVENT_XDND_DROP = ecore_event_type_new(); + ECORE_X_EVENT_XDND_FINISHED = ecore_event_type_new(); + } + + _ecore_x_dnd_init_count++; +} + +void +_ecore_x_dnd_shutdown(void) +{ + _ecore_x_dnd_init_count--; + if (_ecore_x_dnd_init_count > 0) + return; + + if (_source) + free(_source); + _source = NULL; + + if (_target) + free(_target); + _target = NULL; + + _ecore_x_dnd_init_count = 0; +} + +EAPI void +ecore_x_dnd_aware_set(Ecore_X_Window window, + int on) +{ + Ecore_X_Atom prop_data = ECORE_X_DND_VERSION; + + if (on) + ecore_x_window_prop_property_set(window, ECORE_X_ATOM_XDND_AWARE, + ECORE_X_ATOM_ATOM, 32, &prop_data, 1); + else + ecore_x_window_prop_property_del(window, ECORE_X_ATOM_XDND_AWARE); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + */ +EAPI void +ecore_x_dnd_version_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root, + ECORE_X_ATOM_XDND_AWARE, + ECORE_X_ATOM_ATOM, + 0, LONG_MAX); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_dnd_version_get_prefetch(). + */ +EAPI void +ecore_x_dnd_version_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the DnD version. + * @param window Unused. + * @return 0 on failure, the version otherwise. + * + * Get the DnD version. Returns 0 on failure, the version otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_dnd_version_get_prefetch(), which sends the GetProperty request, + * then ecore_x_dnd_version_get_fetch(), which gets the reply. + */ +EAPI int +ecore_x_dnd_version_get(Ecore_X_Window window) +{ + unsigned char *prop_data; + int num; + + if (ecore_x_window_prop_property_get(window, ECORE_X_ATOM_XDND_AWARE, + ECORE_X_ATOM_ATOM, 32, &prop_data, &num)) + { + int version = (int) *prop_data; + free(prop_data); + return version; + } + else + return 0; +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + */ +EAPI void +ecore_x_dnd_type_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, + 0, LONG_MAX); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_dnd_type_get_prefetch(). + */ +EAPI void +ecore_x_dnd_type_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* FIXME: round trip (InternAtomGet request) */ + +/** + * Check if the type is set. + * @param window Unused. + * @param type The type to check + * @return 0 on failure, 1 otherwise. + * + * Check if the type is set. 0 on failure, 1 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_dnd_type_get_prefetch(), which sends the GetProperty request, + * then ecore_x_dnd_type_get_fetch(), which gets the reply. + */ +EAPI int +ecore_x_dnd_type_isset(Ecore_X_Window window, + const char *type) +{ + xcb_intern_atom_cookie_t cookie; + xcb_intern_atom_reply_t *reply; + Ecore_X_Atom *atoms; + unsigned char *data; + int num; + int i; + uint8_t ret = 0; + + cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, + strlen(type), type); + + if (!ecore_x_window_prop_property_get(window, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, &data, &num)) + { + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) free(reply); + return ret; + } + + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + { + free(data); + return 0; + } + atoms = (Ecore_X_Atom *)data; + + for (i = 0; i < num; ++i) + { + if (reply->atom == atoms[i]) + { + ret = 1; + break; + } + } + + free(data); + free(reply); + + return ret; +} + +/* FIXME: round trip (InternAtomGet request) */ + +/** + * Set the type. + * @param window Unused. + * @param type The type to set + * @param on 0 or non 0... + * + * Set the type. + * + * To use this function, you must call before, and in order, + * ecore_x_dnd_type_get_prefetch(), which sends the GetProperty request, + * then ecore_x_dnd_type_get_fetch(), which gets the reply. + */ +EAPI void +ecore_x_dnd_type_set(Ecore_X_Window window, + const char *type, + int on) +{ + xcb_intern_atom_cookie_t cookie; + xcb_intern_atom_reply_t *reply; + Ecore_X_Atom *oldset = NULL; + Ecore_X_Atom *newset = NULL; + unsigned char *data = NULL; + unsigned char *old_data = NULL; + Ecore_X_Atom atom; + int i, j = 0, num = 0; + + cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, + strlen(type), type); + + atom = ecore_x_atom_get(type); + if (!ecore_x_window_prop_property_get(window, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, + 32, &old_data, &num)) + { + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) free(reply); + return; + } + oldset = (Ecore_X_Atom *)old_data; + + if (on) + { + if (ecore_x_dnd_type_isset(window, type)) + { + free(old_data); + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) free(reply); + return; + } + data = calloc(num + 1, sizeof(Ecore_X_Atom)); + if (!data) + { + free(old_data); + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) free(reply); + return; + } + newset = (Ecore_X_Atom *)data; + + for (i = 0; i < num; i++) + newset[i + 1] = oldset[i]; + /* prepend the new type */ + + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + { + free(old_data); + return; + } + newset[0] = reply->atom; + free(reply); + + ecore_x_window_prop_property_set(window, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, + 32, data, num + 1); + } + else + { + if (!ecore_x_dnd_type_isset(window, type)) + { + free(old_data); + return; + } + newset = calloc(num - 1, sizeof(Ecore_X_Atom)); + if (!newset) + { + free(old_data); + return; + } + data = (unsigned char *)newset; + for (i = 0; i < num; i++) + if (oldset[i] != atom) + newset[j++] = oldset[i]; + + ecore_x_window_prop_property_set(window, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, + 32, data, num - 1); + } + + free(oldset); + free(newset); +} + +/* FIXME: round trips, but I don't think we can do much, here */ + +/** + * Set the types. + * @param window Unused. + * @param types The types to set + * @param num_types The number of types + * + * Set the types. + * + * To use this function, you must call before, and in order, + * ecore_x_dnd_type_get_prefetch(), which sends the GetProperty request, + * then ecore_x_dnd_type_get_fetch(), which gets the reply. + */ +EAPI void +ecore_x_dnd_types_set(Ecore_X_Window window, + char **types, + unsigned int num_types) +{ + Ecore_X_Atom *newset = NULL; + void *data = NULL; + uint32_t i; + + if (!num_types) + { + ecore_x_window_prop_property_del(window, ECORE_X_ATOM_XDND_TYPE_LIST); + } + else + { + xcb_intern_atom_cookie_t *cookies; + xcb_intern_atom_reply_t *reply; + + cookies = (xcb_intern_atom_cookie_t *)malloc(sizeof(xcb_intern_atom_cookie_t)); + if (!cookies) return; + for (i = 0; i < num_types; i++) + cookies[i] = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, + strlen(types[i]), types[i]); + data = calloc(num_types, sizeof(Ecore_X_Atom)); + if (!data) + { + for (i = 0; i < num_types; i++) + { + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookies[i], NULL); + if (reply) free(reply); + } + free(cookies); + return; + } + newset = data; + for (i = 0; i < num_types; i++) + { + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookies[i], NULL); + if (reply) + { + newset[i] = reply->atom; + free(reply); + } + else + newset[i] = XCB_NONE; + } + free(cookies); + ecore_x_window_prop_property_set(window, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, data, num_types); + free(data); + } +} + +Ecore_X_DND_Source * +_ecore_x_dnd_source_get(void) +{ + return _source; +} + +Ecore_X_DND_Target * +_ecore_x_dnd_target_get(void) +{ + return _target; +} + +/** + * Sends the GetProperty request. + * @param source Window whose properties are requested. + */ +EAPI void +ecore_x_dnd_begin_prefetch(Ecore_X_Window source) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + source ? source : ((xcb_screen_t *)_ecore_xcb_screen)->root, + ECORE_X_ATOM_XDND_AWARE, + ECORE_X_ATOM_ATOM, + 0, LONG_MAX); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_dnd_begin_prefetch(). + */ +EAPI void +ecore_x_dnd_begin_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* FIXME: round trip */ + +/** + * Begins the DnD. + * @param source Unused. + * @param data The data. + * @param size The size of the data. + * @return 0 on failure, 1 otherwise. + * + * Begins the DnD. Returns 0 on failure, 1 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_dnd_begin_prefetch(), which sends the GetProperty request, + * then ecore_x_dnd_begin_fetch(), which gets the reply. + */ +EAPI int +ecore_x_dnd_begin(Ecore_X_Window source, + unsigned char *data, + int size) +{ + ecore_x_selection_xdnd_prefetch(); + if (!ecore_x_dnd_version_get(source)) + { + ecore_x_selection_xdnd_fetch(); + return 0; + } + + /* Take ownership of XdndSelection */ + ecore_x_selection_xdnd_prefetch(); + ecore_x_selection_xdnd_fetch(); + if (!ecore_x_selection_xdnd_set(source, data, size)) + return 0; + + _source->win = source; + ecore_x_window_ignore_set(_source->win, 1); + _source->state = ECORE_X_DND_SOURCE_DRAGGING; + _source->time = _ecore_xcb_event_last_time; + + /* Default Accepted Action: ask */ + _source->action = ECORE_X_ATOM_XDND_ACTION_COPY; + _source->accepted_action = XCB_NONE; + return 1; +} + +EAPI int +ecore_x_dnd_drop(void) +{ + uint8_t status = 0; + + if (_source->dest) + { + xcb_client_message_event_t ev; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = _source->dest; + + if (_source->will_accept) + { + ev.type = ECORE_X_ATOM_XDND_DROP; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + ev.data.data32[2] = _source->time; + xcb_send_event(_ecore_xcb_conn, 0, _source->dest, 0, (const char *)&ev); + _source->state = ECORE_X_DND_SOURCE_DROPPED; + status = 1; + } + else + { + ev.type = ECORE_X_ATOM_XDND_LEAVE; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + xcb_send_event(_ecore_xcb_conn, 0, _source->dest, 0, (const char *)&ev); + _source->state = ECORE_X_DND_SOURCE_IDLE; + } + } + else + { + /* Dropping on nothing */ + ecore_x_selection_xdnd_clear(); + _source->state = ECORE_X_DND_SOURCE_IDLE; + } + ecore_x_window_ignore_set(_source->win, 0); + + _source->dest = XCB_NONE; + + return status; +} + +EAPI void +ecore_x_dnd_send_status(int will_accept, + int suppress, + Ecore_X_Rectangle rectangle, + Ecore_X_Atom action) +{ + xcb_client_message_event_t ev; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) + return; + + _target->will_accept = will_accept; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = _target->source; + ev.type = ECORE_X_ATOM_XDND_STATUS; + + ev.data.data32[0] = _target->win; + ev.data.data32[1] = 0; + if (will_accept) + ev.data.data32[1] |= 0x1UL; + if (!suppress) + ev.data.data32[1] |= 0x2UL; + + /* Set rectangle information */ + ev.data.data32[2] = rectangle.x; + ev.data.data32[2] <<= 16; + ev.data.data32[2] |= rectangle.y; + ev.data.data32[3] = rectangle.width; + ev.data.data32[3] <<= 16; + ev.data.data32[3] |= rectangle.height; + + if (will_accept) + { + ev.data.data32[4] = action; + _target->accepted_action = action; + } + else + { + ev.data.data32[4] = XCB_NONE; + _target->accepted_action = action; + } + + xcb_send_event(_ecore_xcb_conn, 0, _target->source, 0, (const char *)&ev); +} + +EAPI void +ecore_x_dnd_send_finished(void) +{ + xcb_client_message_event_t ev; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) + return; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = _target->source; + ev.type = ECORE_X_ATOM_XDND_FINISHED; + + ev.data.data32[0] = _target->win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + if (_target->will_accept) + { + ev.data.data32[1] |= 0x1UL; + ev.data.data32[2] = _target->accepted_action; + } + xcb_send_event(_ecore_xcb_conn, 0, _target->source, 0, (const char *)&ev); + + _target->state = ECORE_X_DND_TARGET_IDLE; +} + +void +_ecore_x_dnd_drag(int x, + int y) +{ + xcb_client_message_event_t ev; + Ecore_X_Window win; + Ecore_X_Window *skip; + int num; + + if (_source->state != ECORE_X_DND_SOURCE_DRAGGING) + return; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + + /* Attempt to find a DND-capable window under the cursor */ + skip = ecore_x_window_ignore_list(&num); + win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num); + while (win) + { + xcb_query_tree_cookie_t cookie_tree; + xcb_query_tree_reply_t *reply_tree; + + ecore_x_dnd_version_get_prefetch(win); + cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, win); + + ecore_x_dnd_version_get_fetch(); + /* We found the correct window ? */ + if (ecore_x_dnd_version_get(win)) + { + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) free(reply_tree); + break; + } + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) + { + win = reply_tree->parent; + free(reply_tree); + } + } + + /* Send XdndLeave to current destination window if we have left it */ + if ((_source->dest) && (win != _source->dest)) + { + ev.window = _source->dest; + ev.type = ECORE_X_ATOM_XDND_LEAVE; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, _source->dest, 0, (const char *)&ev); + _source->suppress = 0; + } + + if (win) + { + int16_t x1; + int16_t x2; + int16_t y1; + int16_t y2; + + ecore_x_dnd_version_get_prefetch(win); + ecore_x_dnd_type_get_prefetch(_source->win); + + ecore_x_dnd_version_get_fetch(); + if (!ecore_x_dnd_version_get(win)) + { + ecore_x_dnd_type_get_fetch(); + return; + } + + _source->version = MIN(ECORE_X_DND_VERSION, + ecore_x_dnd_version_get(win)); + if (win != _source->dest) + { + unsigned char *data; + Ecore_X_Atom *types; + int num; + int i; + + ecore_x_dnd_type_get_fetch(); + if (!ecore_x_window_prop_property_get(_source->win, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, + 32, &data, &num)) + return; + + types = (Ecore_X_Atom *)data; + + /* Entered new window, send XdndEnter */ + ev.window = win; + ev.type = ECORE_X_ATOM_XDND_ENTER; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + if (num > 3) + ev.data.data32[1] |= 0x1UL; + else + ev.data.data32[1] &= 0xfffffffeUL; + ev.data.data32[1] |= ((unsigned long) _source->version) << 24; + + for (i = 2; i < 5; i++) + ev.data.data32[i] = 0; + for (i = 0; i < MIN(num, 3); ++i) + ev.data.data32[i + 2] = types[i]; + free(data); + xcb_send_event(_ecore_xcb_conn, 0, win, 0, (const char *)&ev); + _source->await_status = 0; + _source->will_accept = 0; + } + else + ecore_x_dnd_type_get_fetch(); + + /* Determine if we're still in the rectangle from the last status */ + x1 = _source->rectangle.x; + x2 = _source->rectangle.x + _source->rectangle.width; + y1 = _source->rectangle.y; + y2 = _source->rectangle.y + _source->rectangle.height; + + if ((!_source->await_status) || + (!_source->suppress) || + ((x < x1) || (x > x2) || (y < y1) || (y > y2))) + { + ev.window = win; + ev.type = ECORE_X_ATOM_XDND_POSITION; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; /* Reserved */ + ev.data.data32[2] = ((x << 16) & 0xffff0000) | (y & 0xffff); + ev.data.data32[3] = _source->time; /* Version 1 */ + ev.data.data32[4] = _source->action; /* Version 2, Needs to be pre-set */ + xcb_send_event(_ecore_xcb_conn, 0, win, 0, (const char *)&ev); + + _source->await_status = 1; + } + } + + _source->dest = win; +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_dpms.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_dpms.c new file mode 100644 index 0000000000..cb61d45e93 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_dpms.c @@ -0,0 +1,451 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_DPMS_Group X DPMS Extension Functions + * + * Functions related to the X DPMS extension. + */ + + +#ifdef ECORE_XCB_DPMS +static int _dpms_available = 0; +static xcb_dpms_get_version_cookie_t _ecore_xcb_dpms_init_cookie; +#endif /* ECORE_XCB_DPMS */ + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_dpms_init and + _ecore_xcb_dpms_init_finalize. The first one gets the cookies and + the second one gets the replies. */ + +void +_ecore_x_dpms_init(const xcb_query_extension_reply_t *reply) +{ +#ifdef ECORE_XCB_DPMS + if (reply && (reply->present)) + _ecore_xcb_dpms_init_cookie = xcb_dpms_get_version_unchecked(_ecore_xcb_conn, 0, 0); +#endif /* ECORE_XCB_DPMS */ +} + +void +_ecore_x_dpms_init_finalize(void) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_version_reply_t *reply; + + reply = xcb_dpms_get_version_reply(_ecore_xcb_conn, + _ecore_xcb_dpms_init_cookie, NULL); + + if (reply) + { + if (reply->server_major_version >= 1) + _dpms_available = 1; + free(reply); + } +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Checks if the DPMS extension is available or not. + * @return @c 1 if the DPMS extension is available, @c 0 otherwise. + * + * Return 1 if the X server supports the DPMS Extension version 1.0, + * 0 otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI int +ecore_x_dpms_query(void) +{ +#ifdef ECORE_XCB_DPMS + return _dpms_available; +#else + return 0; +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Sends the DPMSCapable request. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_capable_get_prefetch(void) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_capable_cookie_t cookie; + + cookie = xcb_dpms_capable_unchecked(_ecore_xcb_conn); + _ecore_xcb_cookie_cache(cookie.sequence); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Gets the reply of the DPMSCapable request sent by ecore_x_dpms_capable_get_prefetch(). + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_capable_get_fetch(void) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_capable_cookie_t cookie; + xcb_dpms_capable_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_dpms_capable_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Checks if the X server is capable of DPMS. + * @return @c 1 if the X server is capable of DPMS, @c 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_capable_get_prefetch(), which sends the DPMSCapable request, + * then ecore_x_dpms_capable_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI int +ecore_x_dpms_capable_get(void) +{ + int capable = 0; +#ifdef ECORE_XCB_DPMS + xcb_dpms_capable_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + capable = reply->capable; +#endif /* ECORE_XCB_DPMS */ + + return capable; +} + + +/** + * Sends the DPMSInfo request. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_enable_get_prefetch(void) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_info_cookie_t cookie; + + cookie = xcb_dpms_info_unchecked(_ecore_xcb_conn); + _ecore_xcb_cookie_cache(cookie.sequence); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Gets the reply of the DPMSInfo request sent by ecore_x_dpms_enable_get_prefetch(). + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_enable_get_fetch(void) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_info_cookie_t cookie; + xcb_dpms_info_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_dpms_info_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Checks the DPMS state of the display. + * @return @c 1 if DPMS is enabled, @c 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_enapable_get_prefetch(), which sends the DPMSInfo request, + * then ecore_x_dpms_enapable_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI int +ecore_x_dpms_enable_get(void) +{ + int enable = 0; +#ifdef ECORE_XCB_DPMS + xcb_dpms_info_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + enable = reply->state; +#endif /* ECORE_XCB_DPMS */ + + return enable; +} + + +/** + * Sets the DPMS state of the display. + * @param enabled @c 0 to disable DPMS characteristics of the server, enable it otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_enabled_set(int enabled) +{ +#ifdef ECORE_XCB_DPMS + if (enabled) + xcb_dpms_enable(_ecore_xcb_conn); + else + xcb_dpms_disable(_ecore_xcb_conn); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Sets the timeouts. The values are in unit of seconds. + * @param standby Amount of time of inactivity before standby mode will be invoked. + * @param suspend Amount of time of inactivity before the screen is placed into suspend mode. + * @param off Amount of time of inactivity before the monitor is shut off. + * @return Returns always 1. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI int +ecore_x_dpms_timeouts_set(unsigned int standby, + unsigned int suspend, + unsigned int off) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_set_timeouts(_ecore_xcb_conn, standby, suspend, off); +#endif /* ECORE_XCB_DPMS */ + + return 1; +} + + +/** + * Sends the DPMSGetTimeouts request. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeouts_get_prefetch(void) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_cookie_t cookie; + + cookie = xcb_dpms_get_timeouts_unchecked(_ecore_xcb_conn); + _ecore_xcb_cookie_cache(cookie.sequence); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Gets the reply of the DPMSGetTimeouts request sent by ecore_x_dpms_timeouts_get_prefetch(). + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeouts_get_fetch(void) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_cookie_t cookie; + xcb_dpms_get_timeouts_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_dpms_get_timeouts_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Gets the timeouts. The values are in unit of seconds. + * @param standby Amount of time of inactivity before standby mode will be invoked. + * @param suspend Amount of time of inactivity before the screen is placed into suspend mode. + * @param off Amount of time of inactivity before the monitor is shut off. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeouts_get(unsigned int *standby, + unsigned int *suspend, + unsigned int *off) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (reply) + { + if (standby) *standby = reply->standby_timeout; + if (suspend) *suspend = reply->suspend_timeout; + if (off) *off = 0; + } + else +#endif /* ECORE_XCB_DPMS */ + { + if (standby) *standby = 0; + if (suspend) *suspend = 0; + if (off) *off = 0; + } +} + + +/** + * Returns the amount of time of inactivity before standby mode is invoked. + * @return The standby timeout value. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request, + * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_standby_get(void) +{ + int standby = 0; +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + standby = reply->standby_timeout; +#endif /* ECORE_XCB_DPMS */ + + return standby; +} + + +/** + * Returns the amount of time of inactivity before the second level of + * power saving is invoked. + * @return The suspend timeout value. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request, + * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_suspend_get(void) +{ + int suspend = 0;; +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + suspend = reply->suspend_timeout; +#endif /* ECORE_XCB_DPMS */ + + return suspend; +} + + +/** + * Returns the amount of time of inactivity before the third and final + * level of power saving is invoked. + * @return The off timeout value. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request, + * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_off_get(void) +{ + int off = 0; +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + off = reply->off_timeout; +#endif /* ECORE_XCB_DPMS */ + + return off; +} + + +/** + * Sets the standby timeout (in unit of seconds). + * @param new_standby Amount of time of inactivity before standby mode will be invoked. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request, + * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_standby_set(unsigned int new_standby) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + xcb_dpms_set_timeouts(_ecore_xcb_conn, + new_standby, + reply->suspend_timeout, + reply->off_timeout); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Sets the suspend timeout (in unit of seconds). + * @param suspend Amount of time of inactivity before the screen is placed into suspend mode. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request, + * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_suspend_set(unsigned int new_suspend) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + xcb_dpms_set_timeouts(_ecore_xcb_conn, + reply->standby_timeout, + new_suspend, + reply->off_timeout); +#endif /* ECORE_XCB_DPMS */ +} + + +/** + * Sets the off timeout (in unit of seconds). + * @param off Amount of time of inactivity before the monitor is shut off. + * + * To use this function, you must call before, and in order, + * ecore_x_dpms_timeouts_get_prefetch(), which sends the DPMSGetTimeouts request, + * then ecore_x_dpms_timeouts_get_fetch(), which gets the reply. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_off_set(unsigned int new_off) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + xcb_dpms_set_timeouts(_ecore_xcb_conn, + reply->standby_timeout, + reply->suspend_timeout, + new_off); +#endif /* ECORE_XCB_DPMS */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_drawable.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_drawable.c new file mode 100644 index 0000000000..3a1bb5b789 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_drawable.c @@ -0,0 +1,129 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" +#include + + +/** + * @defgroup Ecore_X_Drawable_Group X Drawable Functions + * + * Functions that operate on drawables. + */ + + +/** + * Sends the GetGeometry request. + * @param drawable Drawable whose characteristics are sought. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI void +ecore_x_drawable_geometry_get_prefetch(Ecore_X_Drawable drawable) +{ + xcb_get_geometry_cookie_t cookie; + + cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, drawable); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetGeometry request sent by ecore_x_atom_get_prefetch(). + * @ingroup Ecore_X_Drawable_Group + */ +EAPI void +ecore_x_drawable_geometry_get_fetch(void) +{ + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + + +/** + * Retrieves the geometry of the given drawable. + * @param drawable Unused. + * @param x Pointer to an integer into which the X position is to be stored. + * @param y Pointer to an integer into which the Y position is to be stored. + * @param width Pointer to an integer into which the width is to be stored. + * @param height Pointer to an integer into which the height is to be stored. + * + * To use this function, you must call before, and in order, + * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request, + * then ecore_x_drawable_geometry_get_fetch(), which gets the reply. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI void +ecore_x_drawable_geometry_get(Ecore_X_Drawable drawable __UNUSED__, + int *x, + int *y, + int *width, + int *height) +{ + xcb_get_geometry_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + { + if (x) *x = 0; + if (y) *y = 0; + if (width) *width = 0; + if (height) *height = 0; + return; + } + + if (x) *x = reply->x; + if (y) *y = reply->y; + if (width) *width = reply->width; + if (height) *height = reply->height; +} + + +/** + * Retrieves the width of the border of the given drawable. + * @param drawable Unused. + * @return The border width of the given drawable. + * + * To use this function, you must call before, and in order, + * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request, + * then ecore_x_drawable_geometry_get_fetch(), which gets the reply. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI int +ecore_x_drawable_border_width_get(Ecore_X_Drawable drawable __UNUSED__) +{ + xcb_get_geometry_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + return reply->border_width; +} + + +/** + * Retrieves the depth of the given drawable. + * @param drawable Unused. + * @return The depth of the given drawable. + * + * To use this function, you must call before, and in order, + * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request, + * then ecore_x_drawable_geometry_get_fetch(), which gets the reply. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI int +ecore_x_drawable_depth_get(Ecore_X_Drawable drawable __UNUSED__) +{ + xcb_get_geometry_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + return reply->depth; +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_e.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_e.c new file mode 100644 index 0000000000..4c82617ee2 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_e.c @@ -0,0 +1,29 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* + * OLD E hints + */ + +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + + +EAPI void +ecore_x_e_frame_size_set(Ecore_X_Window window, + int fl, + int fr, + int ft, + int fb) +{ + uint32_t frames[4]; + + frames[0] = fl; + frames[1] = fr; + frames[2] = ft; + frames[3] = fb; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_E_FRAME_SIZE, ECORE_X_ATOM_CARDINAL, 32, + 4, (const void *)frames); +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_events.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_events.c new file mode 100644 index 0000000000..b38510b60a --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_events.c @@ -0,0 +1,2063 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "Ecore.h" +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + + +/** OpenBSD does not define CODESET + * FIXME ?? + */ + +#ifndef CODESET +#define CODESET "INVALID" +#endif + +#if 0 +static void _ecore_x_event_free_window_prop_name_class_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_title_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev); +#endif +static void _ecore_x_event_free_key_down(void *data, void *ev); +static void _ecore_x_event_free_key_up(void *data, void *ev); + +static Ecore_X_Window _ecore_xcb_mouse_down_last_window = 0; +static Ecore_X_Window _ecore_xcb_mouse_down_last_last_window = 0; +static Ecore_X_Window _ecore_xcb_mouse_down_last_event_window = 0; +static Ecore_X_Window _ecore_xcb_mouse_down_last_last_event_window = 0; +static Ecore_X_Time _ecore_xcb_mouse_down_last_time = 0; +static Ecore_X_Time _ecore_xcb_mouse_down_last_last_time = 0; +static int _ecore_xcb_mouse_up_count = 0; +static int _ecore_xcb_mouse_down_did_triple = 0; + + +/* FIXME: roundtrip */ +EAPI void +ecore_x_event_mask_set(Ecore_X_Window window, + Ecore_X_Event_Mask mask) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + uint32_t value_list; + + if (!window) + window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + + value_list = mask | reply->your_event_mask; + xcb_change_window_attributes(_ecore_xcb_conn, window, XCB_CW_EVENT_MASK, &value_list); + free(reply); +} + +/* FIXME: roundtrip */ +EAPI void +ecore_x_event_mask_unset(Ecore_X_Window window, + Ecore_X_Event_Mask mask) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + uint32_t value_list; + + if (!window) + window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + + value_list = reply->your_event_mask & ~mask; + xcb_change_window_attributes(_ecore_xcb_conn, window, XCB_CW_EVENT_MASK, &value_list); + free(reply); +} + +#if 0 +static void +_ecore_x_event_free_window_prop_name_class_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Name_Class_Change *e; + + e = ev; + if (e->name) free(e->name); + if (e->clas) free(e->clas); + free(e); +} + +static void +_ecore_x_event_free_window_prop_title_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Title_Change *e; + + e = ev; + if (e->title) free(e->title); + free(e); +} + +static void +_ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Visible_Title_Change *e; + + e = ev; + if (e->title) free(e->title); + free(e); +} + +static void +_ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Icon_Name_Change *e; + + e = ev; + if (e->name) free(e->name); + free(e); +} + +static void +_ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e; + + e = ev; + if (e->name) free(e->name); + free(e); +} + +static void +_ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Client_Machine_Change *e; + + e = ev; + if (e->name) free(e->name); + free(e); +} +#endif + +static void +_ecore_x_event_free_key_down(void *data __UNUSED__, void *ev) +{ + Ecore_X_Event_Key_Down *e; + + e = ev; + if (e->keyname) free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static void +_ecore_x_event_free_key_up(void *data __UNUSED__, void *ev) +{ + Ecore_X_Event_Key_Up *e; + + e = ev; + if (e->keyname) free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static void +_ecore_x_event_free_xdnd_enter(void *data __UNUSED__, void *ev) +{ + Ecore_X_Event_Xdnd_Enter *e; + int i; + + e = ev; + for (i = 0; i < e->num_types; i++) + free(e->types[i]); + free(e->types); + free(e); +} + +static void +_ecore_x_event_free_selection_notify(void *data __UNUSED__, void *ev) +{ + Ecore_X_Event_Selection_Notify *e; + Ecore_X_Selection_Data *sel; + + e = ev; + sel = e->data; + if (sel->free) + sel->free(sel); + free(e->target); + free(e); +} + +/* FIXME: handle this event */ +void +_ecore_x_event_handle_key_press(xcb_generic_event_t *event) +{ + xcb_key_press_event_t *ev; +/* Ecore_X_Event_Key_Down *e; */ +/* char *keyname; */ +/* int val; */ +/* char buf[256]; */ +/* KeySym sym; */ +/* XComposeStatus status; */ + + ev = (xcb_key_press_event_t *)event; +/* e = calloc(1, sizeof(Ecore_X_Event_Key_Down)); */ +/* if (!e) return; */ +/* keyname = XKeysymToString(XKeycodeToKeysym(xevent->xkey.display, */ +/* xevent->xkey.keycode, 0)); */ +/* if (!keyname) */ +/* { */ +/* snprintf(buf, sizeof(buf), "Keycode-%i", xevent->xkey.keycode); */ +/* keyname = buf; */ +/* } */ +/* e->keyname = strdup(keyname); */ +/* if (!e->keyname) */ +/* { */ +/* free(e); */ +/* return; */ +/* } */ +/* val = XLookupString((XKeyEvent *)xevent, buf, sizeof(buf), &sym, &status); */ +/* if (val > 0) */ +/* { */ +/* buf[val] = 0; */ +/* e->key_compose = ecore_txt_convert(nl_langinfo(CODESET), "UTF-8", buf); */ +/* } */ +/* else e->key_compose = NULL; */ +/* keyname = XKeysymToString(sym); */ +/* if (keyname) e->keysymbol = strdup(keyname); */ +/* else e->keysymbol = strdup(e->keyname); */ +/* if (!e->keysymbol) */ +/* { */ +/* if (e->keyname) free(e->keyname); */ +/* if (e->key_compose) free(e->key_compose); */ +/* free(e); */ +/* return; */ +/* } */ +/* if (xevent->xkey.subwindow) e->win = xevent->xkey.subwindow; */ +/* else e->win = xevent->xkey.window; */ +/* e->event_win = xevent->xkey.window; */ +/* e->time = xevent->xkey.time; */ +/* e->modifiers = xevent->xkey.state; */ +/* _ecore_x_event_last_time = e->time; */ +/* ecore_event_add(ECORE_X_EVENT_KEY_DOWN, e, _ecore_x_event_free_key_down, NULL); */ +} + +/* FIXME: handle this event */ +void +_ecore_x_event_handle_key_release(xcb_generic_event_t *event) +{ + xcb_key_release_event_t *ev; +/* Ecore_X_Event_Key_Up *e; */ +/* char *keyname; */ +/* int val; */ +/* char buf[256]; */ +/* KeySym sym; */ +/* XComposeStatus status; */ + + ev = (xcb_key_release_event_t *)event; +/* e = calloc(1, sizeof(Ecore_X_Event_Key_Up)); */ +/* if (!e) return; */ +/* keyname = XKeysymToString(XKeycodeToKeysym(xevent->xkey.display, */ +/* xevent->xkey.keycode, 0)); */ +/* if (!keyname) */ +/* { */ +/* snprintf(buf, sizeof(buf), "Keycode-%i", xevent->xkey.keycode); */ +/* keyname = buf; */ +/* } */ +/* e->keyname = strdup(keyname); */ +/* if (!e->keyname) */ +/* { */ +/* free(e); */ +/* return; */ +/* } */ +/* val = XLookupString((XKeyEvent *)xevent, buf, sizeof(buf), &sym, &status); */ +/* if (val > 0) */ +/* { */ +/* buf[val] = 0; */ +/* e->key_compose = ecore_txt_convert("ISO8859-1", "UTF-8", buf); */ +/* } */ +/* else e->key_compose = NULL; */ +/* keyname = XKeysymToString(sym); */ +/* if (keyname) e->keysymbol = strdup(keyname); */ +/* else e->keysymbol = strdup(e->keyname); */ +/* if (!e->keysymbol) */ +/* { */ +/* if (e->keyname) free(e->keyname); */ +/* if (e->key_compose) free(e->key_compose); */ +/* free(e); */ +/* return; */ +/* } */ +/* if (xevent->xkey.subwindow) e->win = xevent->xkey.subwindow; */ +/* else e->win = xevent->xkey.window; */ +/* e->event_win = xevent->xkey.window; */ +/* e->time = xevent->xkey.time; */ +/* e->modifiers = xevent->xkey.state; */ +/* _ecore_x_event_last_time = e->time; */ +/* ecore_event_add(ECORE_X_EVENT_KEY_UP, e, _ecore_x_event_free_key_up, NULL); */ +} + +void +_ecore_x_event_handle_button_press(xcb_generic_event_t *event) +{ + xcb_button_press_event_t *ev; + int i; + + ev = (xcb_button_press_event_t *)event; + if ((ev->detail > 3) && (ev->detail < 8)) + { + Ecore_X_Event_Mouse_Wheel *e; + + e = malloc(sizeof(Ecore_X_Event_Mouse_Wheel)); + + if (!e) + return; + + e->modifiers = ev->state; + e->direction = 0; + e->z = 0; + if (ev->detail == 4) + { + e->direction = 0; + e->z = -1; + } + else if (ev->detail == 5) + { + e->direction = 0; + e->z = 1; + } + else if (ev->detail == 6) + { + e->direction = 1; + e->z = -1; + } + else if (ev->detail == 7) + { + e->direction = 1; + e->z = 1; + } + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + + if (ev->child) + e->win = ev->child; + else + e->win = ev->event; + + e->event_win = ev->event; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_WHEEL, e, NULL, NULL); + for (i = 0; i < _ecore_window_grabs_num; i++) + { + if ((_ecore_window_grabs[i] == ev->event) || + (_ecore_window_grabs[i] == ev->child)) + { + int replay = 0; + + if (_ecore_window_grab_replay_func) + replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data, + ECORE_X_EVENT_MOUSE_WHEEL, + e); + /* FIXME: xcb_key_press_event_t does not save the */ + /* connection. So I use the current one */ + if (replay) + xcb_allow_events(_ecore_xcb_conn, + XCB_ALLOW_REPLAY_POINTER, + ev->time); + else + xcb_allow_events(_ecore_xcb_conn, + XCB_ALLOW_ASYNC_POINTER, + ev->time); + break; + } + } + } + else + { + { + Ecore_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_Button_Down *e; + + if (_ecore_xcb_mouse_down_did_triple) + { + _ecore_xcb_mouse_down_last_window = 0; + _ecore_xcb_mouse_down_last_last_window = 0; + _ecore_xcb_mouse_down_last_event_window = 0; + _ecore_xcb_mouse_down_last_last_event_window = 0; + _ecore_xcb_mouse_down_last_time = 0; + _ecore_xcb_mouse_down_last_last_time = 0; + } + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Button_Down)); + if (!e) return; + e->button = ev->detail; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + e->time = ev->time; + if (e->win == e->event_win) + { + if (((int)(e->time - _ecore_xcb_mouse_down_last_time) <= + (int)(1000 * _ecore_xcb_double_click_time)) && + (e->win == _ecore_xcb_mouse_down_last_window) && + (e->event_win == _ecore_xcb_mouse_down_last_event_window) + ) + e->double_click = 1; + if (((int)(e->time - _ecore_xcb_mouse_down_last_last_time) <= + (int)(2 * 1000 * _ecore_xcb_double_click_time)) && + (e->win == _ecore_xcb_mouse_down_last_window) && + (e->win == _ecore_xcb_mouse_down_last_last_window) && + (e->event_win == _ecore_xcb_mouse_down_last_event_window) && + (e->event_win == _ecore_xcb_mouse_down_last_last_event_window) + ) + { + e->triple_click = 1; + _ecore_xcb_mouse_down_did_triple = 1; + } + else + _ecore_xcb_mouse_down_did_triple = 0; + } + if (!e->double_click && !e->triple_click) + _ecore_xcb_mouse_up_count = 0; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL); + for (i = 0; i < _ecore_window_grabs_num; i++) + { + if ((_ecore_window_grabs[i] == ev->event) || + (_ecore_window_grabs[i] == ev->child)) + { + int replay = 0; + + if (_ecore_window_grab_replay_func) + replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data, + ECORE_X_EVENT_MOUSE_BUTTON_DOWN, + e); + /* FIXME: xcb_key_press_event_t does not save the */ + /* connection. So I use the current one */ + if (replay) + xcb_allow_events(_ecore_xcb_conn, + XCB_ALLOW_REPLAY_POINTER, + ev->time); + else + xcb_allow_events(_ecore_xcb_conn, + XCB_ALLOW_ASYNC_POINTER, + ev->time); + break; + } + } + if (e->win == e->event_win) + { + if (!_ecore_xcb_mouse_down_did_triple) + { + _ecore_xcb_mouse_down_last_last_window = _ecore_xcb_mouse_down_last_window; + if (ev->child) + _ecore_xcb_mouse_down_last_window = ev->child; + else + _ecore_xcb_mouse_down_last_window = ev->event; + _ecore_xcb_mouse_down_last_last_event_window = _ecore_xcb_mouse_down_last_event_window; + _ecore_xcb_mouse_down_last_event_window = ev->event; + _ecore_xcb_mouse_down_last_last_time = _ecore_xcb_mouse_down_last_time; + _ecore_xcb_mouse_down_last_time = ev->time; + } + } + } + } +} + +void +_ecore_x_event_handle_button_release(xcb_generic_event_t *event) +{ + xcb_button_release_event_t *ev; + + ev = (xcb_button_release_event_t *)event; + /* filter out wheel buttons */ + if ((ev->detail <= 3) || (ev->detail > 7)) + { + { + Ecore_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_Button_Up *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Button_Up)); + if (!e) return; + e->button = ev->detail; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + e->time = ev->time; + _ecore_xcb_mouse_up_count++; + if (e->win == e->event_win) + { + if ((_ecore_xcb_mouse_up_count >= 2) && + ((int)(e->time - _ecore_xcb_mouse_down_last_time) <= + (int)(1000 * _ecore_xcb_double_click_time)) && + (e->win == _ecore_xcb_mouse_down_last_window) && + (e->event_win == _ecore_xcb_mouse_down_last_event_window) + ) + e->double_click = 1; + if ((_ecore_xcb_mouse_up_count >= 3) && + ((int)(e->time - _ecore_xcb_mouse_down_last_last_time) <= + (int)(2 * 1000 * _ecore_xcb_double_click_time)) && + (e->win == _ecore_xcb_mouse_down_last_window) && + (e->win == _ecore_xcb_mouse_down_last_last_window) && + (e->event_win == _ecore_xcb_mouse_down_last_event_window) && + (e->event_win == _ecore_xcb_mouse_down_last_last_event_window) + ) + e->triple_click = 1; + } + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL); + } + } +} + +void +_ecore_x_event_handle_motion_notify(xcb_generic_event_t *event) +{ + xcb_motion_notify_event_t *ev; + Ecore_X_Event_Mouse_Move *e; + + ev = (xcb_motion_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + + /* Xdnd handling */ + _ecore_x_dnd_drag(e->root.x, e->root.y); + + ecore_event_add(ECORE_X_EVENT_MOUSE_MOVE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_enter_notify(xcb_generic_event_t *event) +{ + xcb_enter_notify_event_t *ev; + + ev = (xcb_enter_notify_event_t *)event; + + { + Ecore_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_In *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_In)); + if (!e) return; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + switch (ev->mode) { + case XCB_NOTIFY_MODE_NORMAL: + e->mode = ECORE_X_EVENT_MODE_NORMAL; + break; + case XCB_NOTIFY_MODE_GRAB: + e->mode = ECORE_X_EVENT_MODE_GRAB; + break; + case XCB_NOTIFY_MODE_UNGRAB: + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + break; + default: + e->mode = ECORE_X_EVENT_MODE_NORMAL; + break; + } + switch (ev->detail) { + case XCB_NOTIFY_DETAIL_ANCESTOR: + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + break; + case XCB_NOTIFY_DETAIL_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + break; + case XCB_NOTIFY_DETAIL_INFERIOR: + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + break; + default: + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + break; + } + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_MOUSE_IN, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_leave_notify(xcb_generic_event_t *event) +{ + xcb_leave_notify_event_t *ev; + + ev = (xcb_leave_notify_event_t *)event; + { + Ecore_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_Out *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out)); + if (!e) return; + e->modifiers = ev->state; + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) e->win = ev->child; + else e->win = ev->event; + e->event_win = ev->event; + switch (ev->mode) { + case XCB_NOTIFY_MODE_NORMAL: + e->mode = ECORE_X_EVENT_MODE_NORMAL; + break; + case XCB_NOTIFY_MODE_GRAB: + e->mode = ECORE_X_EVENT_MODE_GRAB; + break; + case XCB_NOTIFY_MODE_UNGRAB: + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + break; + default: + e->mode = ECORE_X_EVENT_MODE_NORMAL; + break; + } + switch (ev->detail) { + case XCB_NOTIFY_DETAIL_ANCESTOR: + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + break; + case XCB_NOTIFY_DETAIL_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + break; + case XCB_NOTIFY_DETAIL_INFERIOR: + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + break; + default: + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + break; + } + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_OUT, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_focus_in(xcb_generic_event_t *event) +{ + xcb_focus_in_event_t *ev; + Ecore_X_Event_Window_Focus_In *e; + + ev = (xcb_focus_in_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_In)); + if (!e) return; + e->win = ev->event; + switch (ev->mode) { + case XCB_NOTIFY_MODE_NORMAL: + e->mode = ECORE_X_EVENT_MODE_NORMAL; + break; + case XCB_NOTIFY_MODE_GRAB: + e->mode = ECORE_X_EVENT_MODE_GRAB; + break; + case XCB_NOTIFY_MODE_UNGRAB: + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + break; + case XCB_NOTIFY_MODE_WHILE_GRABBED: + e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED; + break; + } + switch (ev->detail) { + case XCB_NOTIFY_DETAIL_ANCESTOR: + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + break; + case XCB_NOTIFY_DETAIL_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + break; + case XCB_NOTIFY_DETAIL_INFERIOR: + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + break; + case XCB_NOTIFY_DETAIL_POINTER: + e->detail = ECORE_X_EVENT_DETAIL_POINTER; + break; + case XCB_NOTIFY_DETAIL_POINTER_ROOT: + e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT; + break; + case XCB_NOTIFY_DETAIL_NONE: + e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE; + break; + } + e->time = _ecore_xcb_event_last_time; + _ecore_xcb_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL); +} + +void +_ecore_x_event_handle_focus_out(xcb_generic_event_t *event) +{ + xcb_focus_out_event_t *ev; + Ecore_X_Event_Window_Focus_Out *e; + + ev = (xcb_focus_out_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_Out)); + if (!e) return; + e->win = ev->event; + switch (ev->mode) { + case XCB_NOTIFY_MODE_NORMAL: + e->mode = ECORE_X_EVENT_MODE_NORMAL; + break; + case XCB_NOTIFY_MODE_GRAB: + e->mode = ECORE_X_EVENT_MODE_GRAB; + break; + case XCB_NOTIFY_MODE_UNGRAB: + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + break; + case XCB_NOTIFY_MODE_WHILE_GRABBED: + e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED; + break; + } + switch (ev->detail) { + case XCB_NOTIFY_DETAIL_ANCESTOR: + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + break; + case XCB_NOTIFY_DETAIL_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + break; + case XCB_NOTIFY_DETAIL_INFERIOR: + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + break; + case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL: + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + break; + case XCB_NOTIFY_DETAIL_POINTER: + e->detail = ECORE_X_EVENT_DETAIL_POINTER; + break; + case XCB_NOTIFY_DETAIL_POINTER_ROOT: + e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT; + break; + case XCB_NOTIFY_DETAIL_NONE: + e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE; + break; + } + e->time = _ecore_xcb_event_last_time; + _ecore_xcb_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL); +} + +void +_ecore_x_event_handle_keymap_notify(xcb_generic_event_t *event __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_expose(xcb_generic_event_t *event) +{ + xcb_expose_event_t *ev; + Ecore_X_Event_Window_Damage *e; + + ev = (xcb_expose_event_t *)event, + e = calloc(1, sizeof(Ecore_X_Event_Window_Damage)); + if (!e) return; + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->count = ev->count; + ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_graphics_expose(xcb_generic_event_t *event) +{ + xcb_graphics_exposure_event_t *ev; + Ecore_X_Event_Window_Damage *e; + + ev = (xcb_graphics_exposure_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Damage)); + if (!e) return; + e->win = ev->drawable; + e->time = _ecore_xcb_event_last_time; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->count = ev->count; + ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_visibility_notify(xcb_generic_event_t *event) +{ + xcb_visibility_notify_event_t *ev; + + ev = (xcb_visibility_notify_event_t *)event; + if (ev->state != XCB_VISIBILITY_PARTIALLY_OBSCURED) + { + Ecore_X_Event_Window_Visibility_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Visibility_Change)); + if (!e) return; + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + if (ev->state == XCB_VISIBILITY_FULLY_OBSCURED) + e->fully_obscured = 1; + else + e->fully_obscured = 0; + ecore_event_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_create_notify(xcb_generic_event_t *event) +{ + xcb_create_notify_event_t *ev; + Ecore_X_Event_Window_Create *e; + + ev = (xcb_create_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Create)); + if (!e) return; + e->win = ev->window; + if (ev->override_redirect) + e->override = 1; + else + e->override = 0; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_CREATE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_destroy_notify(xcb_generic_event_t *event) +{ + xcb_destroy_notify_event_t *ev; + Ecore_X_Event_Window_Destroy *e; + + ev = (xcb_destroy_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy)); + if (!e) return; + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + if (e->win == _ecore_xcb_event_last_window) _ecore_xcb_event_last_window = 0; + ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e, NULL, NULL); +} + +void +_ecore_x_event_handle_unmap_notify(xcb_generic_event_t *event) +{ + xcb_unmap_notify_event_t *ev; + Ecore_X_Event_Window_Hide *e; + + ev = (xcb_unmap_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Hide)); + if (!e) return; + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_map_notify(xcb_generic_event_t *event) +{ + xcb_map_notify_event_t *ev; + Ecore_X_Event_Window_Show *e; + + ev = (xcb_map_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Show)); + if (!e) return; + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW, e, NULL, NULL); +} + +void +_ecore_x_event_handle_map_request(xcb_generic_event_t *event) +{ + xcb_map_request_event_t *ev; + Ecore_X_Event_Window_Show_Request *e; + + ev = (xcb_map_request_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Show_Request)); + if (!e) return; + e->win = ev->window; + e->parent = ev->parent; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_reparent_notify(xcb_generic_event_t *event) +{ + xcb_reparent_notify_event_t *ev; + Ecore_X_Event_Window_Reparent *e; + + ev = (xcb_reparent_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent)); + if (!e) return; + e->win = ev->window; + e->parent = ev->parent; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_REPARENT, e, NULL, NULL); +} + +void +_ecore_x_event_handle_configure_notify(xcb_generic_event_t *event) +{ + xcb_configure_notify_event_t *ev; + Ecore_X_Event_Window_Configure *e; + + ev = (xcb_configure_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Configure)); + if (!e) return; + e->win = ev->window; + e->abovewin = ev->above_sibling; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->border = ev->border_width; + e->override = ev->override_redirect; + /* send_event is bit 7 (0x80) of response_type */ + e->from_wm = ev->response_type & 0x80; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_configure_request(xcb_generic_event_t *event) +{ + xcb_configure_request_event_t *ev; + Ecore_X_Event_Window_Configure_Request *e; + + ev = (xcb_configure_request_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request)); + if (!e) return; + e->win = ev->window; + e->abovewin = ev->sibling; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->border = ev->border_width; + e->value_mask = ev->value_mask; + switch (ev->stack_mode) { + case XCB_STACK_MODE_ABOVE: + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + break; + case XCB_STACK_MODE_BELOW: + e->detail = ECORE_X_WINDOW_STACK_BELOW; + break; + case XCB_STACK_MODE_TOP_IF: + e->detail = ECORE_X_WINDOW_STACK_TOP_IF; + break; + case XCB_STACK_MODE_BOTTOM_IF: + e->detail = ECORE_X_WINDOW_STACK_BOTTOM_IF; + break; + case XCB_STACK_MODE_OPPOSITE: + e->detail = ECORE_X_WINDOW_STACK_OPPOSITE; + break; + } + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gravity_notify(xcb_generic_event_t *event __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_resize_request(xcb_generic_event_t *event) +{ + xcb_resize_request_event_t *ev; + Ecore_X_Event_Window_Resize_Request *e; + + ev = (xcb_resize_request_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Resize_Request)); + if (!e) return; + e->win = ev->window; + e->w = ev->width; + e->h = ev->height; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_circulate_notify(xcb_generic_event_t *event) +{ + xcb_circulate_notify_event_t *ev; + Ecore_X_Event_Window_Stack *e; + + ev = (xcb_circulate_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Stack)); + if (!e) return; + e->win = ev->window; + e->event_win = ev->event; + if (ev->place == XCB_PLACE_ON_TOP) + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + else + e->detail = ECORE_X_WINDOW_STACK_BELOW; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_STACK, e, NULL, NULL); +} + +void +_ecore_x_event_handle_circulate_request(xcb_generic_event_t *event) +{ + xcb_circulate_request_event_t *ev; + Ecore_X_Event_Window_Stack_Request *e; + + ev = (xcb_circulate_request_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Stack_Request)); + if (!e) return; + e->win = ev->window; + e->parent = ev->event; + if (ev->place == XCB_PLACE_ON_TOP) + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + else + e->detail = ECORE_X_WINDOW_STACK_BELOW; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_property_notify(xcb_generic_event_t *event) +{ +#if 0 /* for now i disabled this. nice idea though this is - it leaves a lot + * to be desired for efficiency that is better left to the app layer + */ + if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLASS) + { + Ecore_X_Event_Window_Prop_Name_Class_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Name_Class_Change)); + if (!e) return; + ecore_x_window_prop_name_class_get(xevent->xproperty.window, + &(e->name), &(e->clas)); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE, e, _ecore_x_event_free_window_prop_name_class_change, NULL); + } + else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_NAME)) + { + Ecore_X_Event_Window_Prop_Title_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Title_Change)); + if (!e) return; + e->title = ecore_x_window_prop_title_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_title_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_NAME) + { + Ecore_X_Event_Window_Prop_Visible_Title_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Title_Change)); + if (!e) return; + e->title = ecore_x_window_prop_visible_title_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_visible_title_change, NULL); + } + else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_ICON_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_ICON_NAME)) + { + Ecore_X_Event_Window_Prop_Icon_Name_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Icon_Name_Change)); + if (!e) return; + e->name = ecore_x_window_prop_icon_name_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_icon_name_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME) + { + Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change)); + if (!e) return; + e->name = ecore_x_window_prop_visible_icon_name_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_visible_icon_name_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLIENT_MACHINE) + { + Ecore_X_Event_Window_Prop_Client_Machine_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Client_Machine_Change)); + if (!e) return; + e->name = ecore_x_window_prop_client_machine_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE, e, _ecore_x_event_free_window_prop_client_machine_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_PID) + { + Ecore_X_Event_Window_Prop_Pid_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Pid_Change)); + if (!e) return; + e->pid = ecore_x_window_prop_pid_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_DESKTOP) + { + Ecore_X_Event_Window_Prop_Desktop_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Desktop_Change)); + if (!e) return; + e->desktop = ecore_x_window_prop_desktop_get(xevent->xproperty.window); + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL); + } + else +#endif + { + xcb_property_notify_event_t *ev; + Ecore_X_Event_Window_Property *e; + + ev = (xcb_property_notify_event_t *)event; + e = calloc(1,sizeof(Ecore_X_Event_Window_Property)); + if (!e) return; + e->win = ev->window; + e->atom = ev->atom; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROPERTY, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_selection_clear(xcb_generic_event_t *event) +{ + xcb_selection_clear_event_t *ev; + Ecore_X_Selection_Intern *d; + Ecore_X_Event_Selection_Clear *e; + Ecore_X_Atom sel; + + ev = (xcb_selection_clear_event_t *)event; + if (!(d = _ecore_x_selection_get(ev->selection))) + return; + if (ev->time > d->time) + { + _ecore_x_selection_set(XCB_NONE, NULL, 0, + ev->selection); + } + + /* Generate event for app cleanup */ + e = malloc(sizeof(Ecore_X_Event_Selection_Clear)); + e->win = ev->owner; + e->time = ev->time; + sel = ev->selection; + if (sel == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else + e->selection = ECORE_X_SELECTION_CLIPBOARD; + ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL); + +} + +void +_ecore_x_event_handle_selection_request(xcb_generic_event_t *event) +{ + xcb_selection_request_event_t *ev; + Ecore_X_Selection_Intern *sd; + xcb_selection_notify_event_t sn_event; + void *data; + + ev = (xcb_selection_request_event_t *)event; + /* FIXME: is it the correct value ? */ + sn_event.response_type = XCB_SELECTION_NOTIFY; + sn_event.pad0 = 0; + /* FIXME: is it the correct value ? */ + sn_event.sequence = 0; + sn_event.time = XCB_CURRENT_TIME; + sn_event.requestor = ev->requestor; + sn_event.selection = ev->selection; + sn_event.target = ev->target; + + if ((sd = _ecore_x_selection_get(ev->selection)) && + (sd->win == ev->owner)) + { + if (!ecore_x_selection_convert(ev->selection, ev->target, + &data) == -1) + { + /* Refuse selection, conversion to requested target failed */ + sn_event.property = XCB_NONE; + } + else + { + /* FIXME: This does not properly handle large data transfers */ + ecore_x_window_prop_property_set(ev->requestor, + ev->property, + ev->target, + 8, data, sd->length); + sn_event.property = ev->property; + free(data); + } + } + else + { + sn_event.property = XCB_NONE; + return; + } + + /* FIXME: I use _ecore_xcb_conn, as ev has no information on the connection */ + xcb_send_event(_ecore_xcb_conn, 0, + ev->requestor, 0, (const char *)&sn_event); +} + +/* FIXME: round trip */ +void +_ecore_x_event_handle_selection_notify(xcb_generic_event_t *event) +{ + xcb_selection_notify_event_t *ev; + Ecore_X_Event_Selection_Notify *e; + unsigned char *data = NULL; + Ecore_X_Atom selection; + int num_ret; + uint8_t format; + + ev = (xcb_selection_notify_event_t *)event; + selection = ev->selection; + + if (ev->target == ECORE_X_ATOM_SELECTION_TARGETS) + { + ecore_x_window_prop_property_get_prefetch(ev->requestor, + ev->property, + ECORE_X_ATOM_ATOM); + ecore_x_window_prop_property_get_fetch(); + format = ecore_x_window_prop_property_get(ev->requestor, + ev->property, + ECORE_X_ATOM_ATOM, + 32, + &data, + &num_ret); + if (!format) return; + } + else + { + ecore_x_window_prop_property_get_prefetch(ev->requestor, + ev->property, + XCB_GET_PROPERTY_TYPE_ANY); + ecore_x_window_prop_property_get_fetch(); + format = ecore_x_window_prop_property_get(ev->requestor, + ev->property, + ECORE_X_ATOM_ATOM, + 8, + &data, + &num_ret); + if (!format) return; + } + + e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify)); + if (!e) return; + e->win = ev->requestor; + e->time = ev->time; + e->target = _ecore_x_selection_target_get(ev->target); + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + e->selection = ECORE_X_SELECTION_XDND; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + e->selection = ECORE_X_SELECTION_CLIPBOARD; + else + { + free(e); + return; + } + e->data = _ecore_x_selection_parse(e->target, data, num_ret, format); + + ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, _ecore_x_event_free_selection_notify, NULL); +} + +void +_ecore_x_event_handle_colormap_notify(xcb_generic_event_t *event) +{ + xcb_colormap_notify_event_t *ev; + Ecore_X_Event_Window_Colormap *e; + + ev = (xcb_colormap_notify_event_t *)event; + e = calloc(1,sizeof(Ecore_X_Event_Window_Colormap)); + if (!e) return; + e->win = ev->window; + e->cmap = ev->colormap; + if (ev->state == XCB_COLORMAP_STATE_INSTALLED) + e->installed = 1; + else + e->installed = 0; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL); +} + +void +_ecore_x_event_handle_client_message(xcb_generic_event_t *event) +{ + /* Special client message event handling here. need to put LOTS of if */ + /* checks here and generate synthetic events per special message known */ + /* otherwise generate generic client message event. this would handle*/ + /* netwm, ICCCM, gnomewm, old kde and mwm hint client message protocols */ + + xcb_client_message_event_t *ev; + + ev = (xcb_client_message_event_t *)event; + if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS) && + (ev->format == 32) && + (ev->data.data32[0] == (uint32_t)ECORE_X_ATOM_WM_DELETE_WINDOW)) + { + Ecore_X_Event_Window_Delete_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Delete_Request)); + if (!e) return; + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL); + } + + else if ((ev->type == ECORE_X_ATOM_NET_WM_MOVERESIZE) && + (ev->format == 32) && + /* Ignore move and resize with keyboard */ + (ev->data.data32[2] < 9)) + { + Ecore_X_Event_Window_Move_Resize_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Move_Resize_Request)); + if (!e) return; + e->win = ev->window; + e->x = ev->data.data32[0]; + e->y = ev->data.data32[1]; + e->direction = ev->data.data32[2]; + e->button = ev->data.data32[3]; + e->source = ev->data.data32[4]; + ecore_event_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, e, NULL, NULL); + } + + /* Xdnd Client Message Handling Begin */ + /* Message Type: XdndEnter target */ + else if (ev->type == ECORE_X_ATOM_XDND_ENTER) + { + Ecore_X_Event_Xdnd_Enter *e; + Ecore_X_DND_Target *target; + uint32_t three; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter)); + if (!e) return; + + target = _ecore_x_dnd_target_get(); + target->state = ECORE_X_DND_TARGET_ENTERED; + + target = _ecore_x_dnd_target_get(); + target->source = ev->data.data32[0]; + target->win = ev->window; + target->version = ev->data.data32[1] >> 24; + if (target->version > ECORE_X_DND_VERSION) + { + printf("DND: Requested version %d, we only support up to %d\n", target->version, + ECORE_X_DND_VERSION); + return; + } + + /* FIXME: roud trip, but I don't know how to suppress it */ + if ((three = ev->data.data32[1] & 0x1UL)) + { + /* source supports more than 3 types, fetch property */ + unsigned char *data; + Ecore_X_Atom *types; + int num_ret; + int i; + uint8_t format; + + ecore_x_window_prop_property_get_prefetch(target->source, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM); + ecore_x_window_prop_property_get_fetch(); + format = ecore_x_window_prop_property_get(target->source, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, + 32, + &data, + &num_ret); + if (!format) + { + printf("DND: Could not fetch data type list from source window, aborting.\n"); + return; + } + types = (Ecore_X_Atom *)data; + e->types = calloc(num_ret, sizeof(char *)); + if (e->types) + { + xcb_get_atom_name_cookie_t *cookies; + + cookies = (xcb_get_atom_name_cookie_t *)malloc(sizeof(xcb_get_atom_name_cookie_t) * num_ret); + for (i = 0; i < num_ret; i++) + cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, types[i]); + for (i = 0; i < num_ret; i++) + { + xcb_get_atom_name_reply_t *reply; + char *name; + + reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL); + if (reply) + { + name = (char *)malloc(sizeof (char) * (reply->name_len + 1)); + memcpy(name, + xcb_get_atom_name_name(reply), + reply->name_len); + name[reply->name_len] = '\0'; + e->types[i] = name; + free(reply); + } + } + free(cookies); + } + e->num_types = num_ret; + } + else + { + int i = 0; + + e->types = calloc(3, sizeof(char *)); + if (e->types) + { + xcb_get_atom_name_cookie_t cookies[3]; + + for (i = 0; i < 3; i++) + cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[i + 2]); + for (i = 0; i < 3; i++) + { + xcb_get_atom_name_reply_t *reply; + char *name; + + reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL); + if (reply && (ev->data.data32[i + 2])) + { + name = (char *)malloc(sizeof (char) * (reply->name_len + 1)); + memcpy(name, + xcb_get_atom_name_name(reply), + reply->name_len); + name[reply->name_len] = '\0'; + e->types[i] = name; + } + if (reply) free(reply); + } + } + e->num_types = i; + } + + e->win = target->win; + e->source = target->source; + ecore_event_add(ECORE_X_EVENT_XDND_ENTER, e, _ecore_x_event_free_xdnd_enter, NULL); + } + + /* Message Type: XdndPosition target */ + else if (ev->type == ECORE_X_ATOM_XDND_POSITION) + { + Ecore_X_Event_Xdnd_Position *e; + Ecore_X_DND_Target *target; + + target = _ecore_x_dnd_target_get(); + if ((target->source != (Ecore_X_Window)ev->data.data32[0]) || + (target->win != ev->window)) + return; + + target->pos.x = (int16_t)ev->data.data32[2] >> 16; + target->pos.y = (int16_t)ev->data.data32[2] & 0xFFFFUL; + target->action = ev->data.data32[4]; /* Version 2 */ + + target->time = (target->version >= 1) ? + ev->data.data32[3] : XCB_CURRENT_TIME; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Position)); + if (!e) return; + e->win = target->win; + e->source = target->source; + e->position.x = target->pos.x; + e->position.y = target->pos.y; + e->action = target->action; + ecore_event_add(ECORE_X_EVENT_XDND_POSITION, e, NULL, NULL); + } + + /* Message Type: XdndStatus source */ + else if (ev->type == ECORE_X_ATOM_XDND_STATUS) + { + Ecore_X_Event_Xdnd_Status *e; + Ecore_X_DND_Source *source; + + source = _ecore_x_dnd_source_get(); + /* Make sure source/target match */ + if ((source->win != ev->window ) || + (source->dest != ev->data.data32[0])) + return; + + source->await_status = 0; + + source->will_accept = ev->data.data32[1] & 0x1UL; + source->suppress = (ev->data.data32[1] & 0x2UL) ? 0 : 1; + + source->rectangle.x = (int16_t)ev->data.data32[2] >> 16; + source->rectangle.y = (int16_t)ev->data.data32[2] & 0xFFFFUL; + source->rectangle.width = (uint16_t)ev->data.data32[3] >> 16; + source->rectangle.height = (uint16_t)ev->data.data32[3] & 0xFFFFUL; + + source->accepted_action = ev->data.data32[4]; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Status)); + if (!e) return; + e->win = source->win; + e->target = source->dest; + e->will_accept = source->will_accept; + e->rectangle.x = source->rectangle.x; + e->rectangle.y = source->rectangle.y; + e->rectangle.width = source->rectangle.width; + e->rectangle.height = source->rectangle.height; + e->action = source->accepted_action; + + ecore_event_add(ECORE_X_EVENT_XDND_STATUS, e, NULL, NULL); + } + + /* Message Type: XdndLeave target */ + /* Pretend the whole thing never happened, sort of */ + else if (ev->type == ECORE_X_ATOM_XDND_LEAVE) + { + Ecore_X_Event_Xdnd_Leave *e; + Ecore_X_DND_Target *target; + + target = _ecore_x_dnd_target_get(); + if ((target->source != (Ecore_X_Window)ev->data.data32[0]) || + (target->win != ev->window)) + return; + + target->state = ECORE_X_DND_TARGET_IDLE; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Leave)); + if (!e) return; + e->win = ev->window; + e->source = ev->data.data32[0]; + ecore_event_add(ECORE_X_EVENT_XDND_LEAVE, e, NULL, NULL); + } + + /* Message Type: XdndDrop target */ + else if (ev->type == ECORE_X_ATOM_XDND_DROP) + { + Ecore_X_Event_Xdnd_Drop *e; + Ecore_X_DND_Target *target; + + target = _ecore_x_dnd_target_get(); + /* Match source/target */ + if ((target->source != (Ecore_X_Window)ev->data.data32[0]) || + (target->win != ev->window)) + return; + + target->time = (target->version >= 1) ? + ev->data.data32[2] : _ecore_xcb_event_last_time; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Drop)); + if (!e) return; + e->win = target->win; + e->source = target->source; + e->action = target->action; + e->position.x = target->pos.x; + e->position.y = target->pos.y; + ecore_event_add(ECORE_X_EVENT_XDND_DROP, e, NULL, NULL); + } + + /* Message Type: XdndFinished source */ + else if (ev->type == ECORE_X_ATOM_XDND_FINISHED) + { + Ecore_X_Event_Xdnd_Finished *e; + Ecore_X_DND_Source *source; + uint8_t completed = 1; + + source = _ecore_x_dnd_source_get(); + /* Match source/target */ + if ((source->win != ev->window) || + (source->dest != ev->data.data32[0])) + return; + + if ((source->version >= 5) && (ev->data.data32[1] & 0x1UL)) + { + /* Target successfully performed drop action */ + ecore_x_selection_xdnd_clear(); + source->state = ECORE_X_DND_SOURCE_IDLE; + } + else + { + completed = 0; + source->state = ECORE_X_DND_SOURCE_CONVERTING; + + /* FIXME: Probably need to add a timer to switch back to idle + * and discard the selection data */ + } + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Finished)); + if (!e) return; + e->win = source->win; + e->target = source->dest; + e->completed = completed; + if (source->version >= 5) + { + source->accepted_action = ev->data.data32[2]; + e->action = source->accepted_action; + } + else + { + source->accepted_action = 0; + e->action = source->action; + } + + ecore_event_add(ECORE_X_EVENT_XDND_FINISHED, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_NET_WM_STATE) + { + Ecore_X_Event_Window_State_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request)); + if (!e) return; + e->win = ev->window; + if (ev->data.data32[0] == 0) + e->action = ECORE_X_WINDOW_STATE_ACTION_REMOVE; + else if (ev->data.data32[0] == 1) + e->action = ECORE_X_WINDOW_STATE_ACTION_ADD; + else if (ev->data.data32[0] == 2) + e->action = ECORE_X_WINDOW_STATE_ACTION_TOGGLE; + else + { + free(e); + return; + } + e->state[0] = _ecore_x_netwm_state_get(ev->data.data32[1]); + if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN) + { + xcb_get_atom_name_reply_t *reply; + char *name; + + /* FIXME: round trip */ + reply = xcb_get_atom_name_reply(_ecore_xcb_conn, + xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[1]), + NULL); + if (reply) + { + name = (char *)malloc(sizeof (char) * (reply->name_len + 1)); + memcpy(name, + xcb_get_atom_name_name(reply), + reply->name_len); + name[reply->name_len] = '\0'; + printf("Unknown state: %s\n", name); + free(name); + free(reply); + } + } + e->state[1] = _ecore_x_netwm_state_get(ev->data.data32[2]); + if (e->state[1] == ECORE_X_WINDOW_STATE_UNKNOWN) + { + xcb_get_atom_name_reply_t *reply; + char *name; + + reply = xcb_get_atom_name_reply(_ecore_xcb_conn, + xcb_get_atom_name_unchecked(_ecore_xcb_conn, ev->data.data32[2]), + NULL); + if (reply) + { + name = (char *)malloc(sizeof (char) * (reply->name_len + 1)); + memcpy(name, + xcb_get_atom_name_name(reply), + reply->name_len); + name[reply->name_len] = '\0'; + printf("Unknown state: %s\n", name); + free(name); + } + } + e->source = ev->data.data32[3]; + + ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_WM_CHANGE_STATE) + && (ev->format == 32) + && (ev->data.data32[0] == XCB_WM_ICONIC_STATE)) + { + Ecore_X_Event_Window_State_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request)); + if (!e) return; + e->win = ev->window; + e->action = ECORE_X_WINDOW_STATE_ACTION_ADD; + e->state[0] = ECORE_X_WINDOW_STATE_ICONIFIED; + + ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_NET_WM_DESKTOP) + && (ev->format == 32)) + { + Ecore_X_Event_Desktop_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Desktop_Change)); + if (!e) return; + e->win = ev->window; + e->desk = ev->data.data32[0]; + e->source = ev->data.data32[1]; + + ecore_event_add(ECORE_X_EVENT_DESKTOP_CHANGE, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS)) + { + Ecore_X_Event_Frame_Extents_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Frame_Extents_Request)); + if (!e) return; + e->win = ev->window; + + ecore_event_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS) + && ((Ecore_X_Atom)ev->data.data32[0] == ECORE_X_ATOM_NET_WM_PING) + && (ev->format == 32)) + { + Ecore_X_Event_Ping *e; + + e = calloc(1, sizeof(Ecore_X_Event_Ping)); + if (!e) return; + e->win = ev->window; + e->time = ev->data.data32[1]; + e->event_win = ev->data.data32[2]; + + ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) && + (ev->format == 8)) + { + _ecore_x_netwm_startup_info_begin(ev->window, (char *)ev->data.data8); + } + else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO) && + (ev->format == 8)) + { + _ecore_x_netwm_startup_info(ev->window, (char *)ev->data.data8); + } + else if ((ev->type == 27777) + && (ev->data.data32[0] == 0x7162534) + && (ev->format == 32) + && (ev->window == _ecore_xcb_private_window)) + { + /* a grab sync marker */ + if (ev->data.data32[1] == 0x10000001) + _ecore_x_window_grab_remove(ev->data.data32[2]); + else if (ev->data.data32[1] == 0x10000002) + _ecore_x_key_grab_remove(ev->data.data32[2]); + } + else + { + Ecore_X_Event_Client_Message *e; + int i; + + e = calloc(1, sizeof(Ecore_X_Event_Client_Message)); + if (!e) return; + e->win = ev->window; + e->message_type = ev->type; + e->format = ev->format; + for (i = 0; i < 5; i++) + e->data.l[i] = ev->data.data32[i]; + + ecore_event_add(ECORE_X_EVENT_CLIENT_MESSAGE, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_mapping_notify(xcb_generic_event_t *event __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_shape_change(xcb_generic_event_t *event) +{ +#ifdef ECORE_X_SHAPE + xcb_shape_notify_event_t *ev; + Ecore_X_Event_Window_Shape *e; + + ev = (xcb_shape_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Window_Shape)); + if (!e) return; + e->win = ev->affected_window; + e->time = ev->server_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL); +#else + event = NULL; +#endif /* ECORE_X_SHAPE */ +} + +void +_ecore_x_event_handle_screensaver_notify(xcb_generic_event_t *event) +{ +#ifdef ECORE_X_SCREENSAVER + xcb_screensaver_notify_event_t *ev; + Ecore_X_Event_Screensaver_Notify *e; + + ev = (xcb_screensaver_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Screensaver_Notify)); + if (!e) return; + e->win = ev->window; + if (ev->state == XCB_SCREENSAVER_STATE_ON) + e->on = 1; + else + e->on = 0; + e->time = ev->time; + ecore_event_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, e, NULL, NULL); +#else + event = NULL; +#endif /* ECORE_X_SCREENSAVER */ +} + +void +_ecore_x_event_handle_sync_counter(xcb_generic_event_t *event) +{ +#ifdef ECORE_X_SYNC + xcb_sync_counter_notify_event_t *ev; + Ecore_X_Event_Sync_Counter *e; + + ev = (xcb_sync_counter_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Sync_Counter)); + if (!e) return; + e->time = ev->timestamp; + ecore_event_add(ECORE_X_EVENT_SYNC_COUNTER, e, NULL, NULL); +#else + event = NULL; +#endif /* ECORE_X_SYNC */ +} + +void +_ecore_x_event_handle_sync_alarm(xcb_generic_event_t *event) +{ +#ifdef ECORE_X_SYNC + xcb_sync_alarm_notify_event_t *ev; + Ecore_X_Event_Sync_Alarm *e; + + ev = (xcb_sync_alarm_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Sync_Alarm)); + if (!e) return; + e->time = ev->timestamp; + e->alarm = ev->alarm; + ecore_event_add(ECORE_X_EVENT_SYNC_ALARM, e, NULL, NULL); +#else + event = NULL; +#endif /* ECORE_X_SYNC */ +} + +/* FIXME: round trip */ +void +_ecore_x_event_handle_randr_change(xcb_generic_event_t *event) +{ +#ifdef ECORE_X_RANDR + xcb_randr_screen_change_notify_event_t *ev; + Ecore_X_Event_Screen_Change *e; + + ev = (xcb_randr_screen_change_notify_event_t *)event; + + if ((ev->response_type & ~0x80) != XCB_CONFIGURE_NOTIFY) + { + xcb_query_extension_reply_t *rep; + + rep = xcb_query_extension_reply(_ecore_xcb_conn, + xcb_query_extension_unchecked(_ecore_xcb_conn, + strlen("randr"), + "randr"), + NULL); + + if ((!rep) || + (((ev->response_type & ~0x80) - rep->first_event) != XCB_RANDR_SCREEN_CHANGE_NOTIFY)) + printf("ERROR: Can't update RandR config!\n"); + if (rep) + free(rep); + } + + e = calloc(1, sizeof(Ecore_X_Event_Screen_Change)); + if (!e) return; + e->win = ev->request_window; + e->root = ev->root; + e->width = ev->width; + e->height = ev->height; + ecore_event_add(ECORE_X_EVENT_SCREEN_CHANGE, e, NULL, NULL); +#else + event = NULL; +#endif /* ECORE_X_RANDR */ +} + +void +_ecore_x_event_handle_fixes_selection_notify(xcb_generic_event_t *event) +{ +#ifdef ECORE_X_FIXES + /* Nothing here yet */ +#else + event = NULL; +#endif /* ECORE_X_FIXES */ +} + +void +_ecore_x_event_handle_damage_notify(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCBDAMAGE + xcb_damage_notify_event_t *ev; + Ecore_X_Event_Damage *e; + + ev = (xcb_damage_notify_event_t *)event; + e = calloc(1, sizeof(Ecore_X_Event_Damage)); + if (!e) return; + + e->level = ev->level; + e->drawable = ev->drawable; + e->damage = ev->damage; + /* FIXME: XCB has no 'more' member in xcb_damage_notify_event_t */ +/* e->more = ev->more; */ + e->time = ev->timestamp; + e->area.x = ev->area.x; + e->area.y = ev->area.y; + e->area.width = ev->area.width; + e->area.height = ev->area.height; + e->geometry.x = ev->geometry.x; + e->geometry.y = ev->geometry.y; + e->geometry.width = ev->geometry.width; + e->geometry.height = ev->geometry.height; + + ecore_event_add(ECORE_X_EVENT_DAMAGE_NOTIFY, e, NULL, NULL); +#else + event = NULL; +#endif /* ECORE_XCBDAMAGE */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_fixes.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_fixes.c new file mode 100644 index 0000000000..db3d462711 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_fixes.c @@ -0,0 +1,581 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_Fixes_Group X Fixes Extension Functions + * + * Functions related to the X Fixes extension. + */ + + +#ifdef ECORE_XCB_FIXES +static int _xfixes_available = 0; +static xcb_xfixes_query_version_cookie_t _ecore_xcb_xfixes_init_cookie; +#endif /* ECORE_XCB_FIXES */ + + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_xfixes_init and + _ecore_xcb_xfixes_init_finalize. The first one gets the cookies and + the second one gets the replies and set the atoms. */ + +void +_ecore_x_xfixes_init(const xcb_query_extension_reply_t *reply) +{ +#ifdef ECORE_XCB_FIXES + if (reply && (reply->present)) + _ecore_xcb_xfixes_init_cookie = xcb_xfixes_query_version_unchecked(_ecore_xcb_conn, 4, 0); +#endif /* ECORE_XCB_FIXES */ +} + +void +_ecore_x_xfixes_init_finalize(void) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_query_version_reply_t *reply; + + reply = xcb_xfixes_query_version_reply(_ecore_xcb_conn, + _ecore_xcb_xfixes_init_cookie, NULL); + + if (reply) + { + if (reply->major_version >= 3) + _xfixes_available = 1; + free(reply); + } +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Return whether the X server supports the Fixes Extension. + * @return 1 if the X Fixes Extension is available, 0 otherwise. + * + * Return 1 if the X server supports the Fixes Extension version 3.0, + * 0 otherwise. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI int +ecore_x_xfixes_query(void) +{ +#ifdef ECORE_XCB_FIXES + return _xfixes_available; +#else + return 0; +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Create a region from rectangles. + * @param rects The rectangles used to initialize the region. + * @param num The number of rectangles. + * @return The newly created region. + * + * Create a region initialized to the specified list of rectangles + * @p rects. The rectangles may be specified in any order, their union + * becomes the region. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new(Ecore_X_Rectangle *rects, + int num) +{ + Ecore_X_Region region = XCB_NONE; + +#ifdef ECORE_XCB_FIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region(_ecore_xcb_conn, region, num, (xcb_rectangle_t *)rects); +#endif /* ECORE_XCB_FIXES */ + + return region; +} + + +/** + * Create a region from a pixmap. + * @param bitmap The bitmap used to initialize the region. + * @return The newly created region. + * + * Creates a region initialized to the set of 'one' pixels in @p bitmap + * (which must be of depth 1, else Match error). + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap) +{ + Ecore_X_Region region = XCB_NONE; + +#ifdef ECORE_XCB_FIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_bitmap(_ecore_xcb_conn, region, bitmap); +#endif /* ECORE_XCB_FIXES */ + + return region; +} + + +/** + * Create a region from a window. + * @param window The window used to initialize the region. + * @param type The type of the region. + * @return The newly created region. + * + * Creates a region initialized to the specified @p window region. See + * the Shape extension for the definition of Bounding and Clip + * regions. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_window(Ecore_X_Window window, + Ecore_X_Region_Type type) +{ + Ecore_X_Region region = XCB_NONE; + +#ifdef ECORE_XCB_FIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_window(_ecore_xcb_conn, region, window, type); +#endif /* ECORE_XCB_FIXES */ + + return region; +} + + +/** + * Create a region from a graphic context. + * @param gc The graphic context used to initialize the region. + * @return The newly created region. + * + * Creates a region initialized from the clip list of @p gc. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_gc(Ecore_X_GC gc) +{ + Ecore_X_Region region = XCB_NONE; + +#ifdef ECORE_XCB_FIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_gc(_ecore_xcb_conn, region, gc); +#endif /* ECORE_XCB_FIXES */ + + return region; +} + + +/** + * Create a region from a picture. + * @param picture The picture used to initialize the region. + * @return The newly created region. + * + * Creates a region initialized from the clip list of @p picture. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_picture(Ecore_X_Picture picture) +{ + Ecore_X_Region region = XCB_NONE; + +#ifdef ECORE_XCB_FIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_picture(_ecore_xcb_conn, region, picture); +#endif /* ECORE_XCB_FIXES */ + + return region; +} + + +/** + * Destroy a region. + * @param region The region to destroy. + * + * Destroy the specified @p region. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_del(Ecore_X_Region region) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_destroy_region(_ecore_xcb_conn, region); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Set the content of a region. + * @param region The region to destroy. + * @param rects The rectangles used to set the region. + * @param num The number of rectangles. + * + * Replace the current contents of @p region with the region formed + * by the union of the rectangles @p rects. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_set(Ecore_X_Region region, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_set_region(_ecore_xcb_conn, region, num, (xcb_rectangle_t *)rects); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Copy the content of a region. + * @param dest The destination region. + * @param source The source region. + * + * Replace the contents of @p dest with the contents of @p source. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_copy(Ecore_X_Region dest, + Ecore_X_Region source) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_copy_region(_ecore_xcb_conn, source, dest); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Make the union of two regions. + * @param dest The destination region. + * @param source1 The first source region. + * @param source2 The second source region. + * + * Replace the contents of @p dest with the union of @p source1 and + * @p source2. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_combine(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_union_region(_ecore_xcb_conn, source1, source2, dest); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Make the intersection of two regions. + * @param dest The destination region. + * @param source1 The first source region. + * @param source2 The second source region. + * + * Replace the contents of @p dest with the intersection of @p source1 and + * @p source2. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_intersect(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_intersect_region(_ecore_xcb_conn, source1, source2, dest); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Make the substraction of two regions. + * @param dest The destination region. + * @param source1 The first source region. + * @param source2 The second source region. + * + * Replace the contents of @p dest with the substraction of @p source1 by + * @p source2. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_subtract(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_subtract_region(_ecore_xcb_conn, source1, source2, dest); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Make the substraction of regions by bounds. + * @param dest The destination region. + * @param bounds The bounds. + * @param source The source region. + * + * The @p source region is subtracted from the region specified by + * @p bounds. The result is placed in @p dest, replacing its + * contents. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_invert(Ecore_X_Region dest, + Ecore_X_Rectangle *bounds, + Ecore_X_Region source) +{ +#ifdef ECORE_XCB_FIXES + xcb_rectangle_t rect; + + rect.x = bounds->x; + rect.y = bounds->y; + rect.width = bounds->width; + rect.height = bounds->height; + xcb_xfixes_invert_region(_ecore_xcb_conn, source, rect, dest); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Translate a region. + * @param region The region to translate. + * @param dx The horizontal translation. + * @param dy The vertical translation. + * + * The @p region is translated by @p dx and @p dy in place. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_translate(Ecore_X_Region region, + int dx, + int dy) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_translate_region(_ecore_xcb_conn, region, dx, dy); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Extent a region. + * @param dest The destination region. + * @param source The source region. + * + * The extents of the @p source region are placed in @p dest. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_extents(Ecore_X_Region dest, + Ecore_X_Region source) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_region_extents(_ecore_xcb_conn, source, dest); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Sends the XFixesFetchRegion request. + * @param region Requested region. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_fetch_prefetch(Ecore_X_Region region) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_fetch_region_cookie_t cookie; + + cookie = xcb_xfixes_fetch_region_unchecked(_ecore_xcb_conn, region); + _ecore_xcb_cookie_cache(cookie.sequence); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Gets the reply of the XFixesFetchRegion request sent by ecore_xcb_region_fetch_prefetch(). + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_fetch_fetch(void) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_fetch_region_cookie_t cookie; + xcb_xfixes_fetch_region_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_xfixes_fetch_region_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Return the rectangles that compose a region. + * @param region The region (Unused). + * @param num The number of returned rectangles. + * @param bounds The returned bounds of the region. + * @return The returned rectangles. + * + * The @p region passed to ecore_xcb_region_fetch_prefetch() is + * returned as a list of rectagles in XY-banded order. + * + * To use this function, you must call before, and in order, + * ecore_xcb_region_fetch_prefetch(), which sends the XFixesFetchRegion request, + * then ecore_xcb_region_fetch_fetch(), which gets the reply. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Rectangle * +ecore_x_region_fetch(Ecore_X_Region region __UNUSED__, + int *num, + Ecore_X_Rectangle *bounds) +{ + Ecore_X_Rectangle extents = { 0, 0, 0, 0}; + Ecore_X_Rectangle *rects = NULL; +#ifdef ECORE_XCB_FIXES + int n; + xcb_xfixes_fetch_region_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + { + if (num) *num = 0; + if (bounds) *bounds = extents; + return NULL; + } + n = xcb_xfixes_fetch_region_rectangles_length(reply); + rects = (Ecore_X_Rectangle *)malloc(n * sizeof(Ecore_X_Rectangle)); + if (!rects) + { + if (num) *num = 0; + if (bounds) *bounds = extents; + + return NULL; + } + + if (num) *num = n; + if (bounds) + { + bounds->x = reply->extents.x; + bounds->y = reply->extents.y; + bounds->width = reply->extents.width; + bounds->height = reply->extents.height; + } + memcpy(rects, + xcb_xfixes_fetch_region_rectangles(reply), + sizeof(Ecore_X_Rectangle) * n); + + return rects; +#else + if (num) *num = 0; + if (bounds) *bounds = extents; + return NULL; +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Expand a region. + * @param dest The destination region. + * @param source The source region. + * @param left The number of pixels to add on the left. + * @param right The number of pixels to add on the right. + * @param top The number of pixels to add at the top. + * @param bottom The number of pixels to add at the bottom. + * + * Put in @p dest the area specified by expanding each rectangle in + * the @p source region by the specified number of pixels to the + * @p left, @p right, @p top and @p bottom. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_expand(Ecore_X_Region dest, + Ecore_X_Region source, + unsigned int left, + unsigned int right, + unsigned int top, + unsigned int bottom) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_expand_region(_ecore_xcb_conn, source, dest, left, right, top, bottom); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Change clip-mask in a graphic context to the specified region. + * @param region The region to change. + * @param gc The clip-mask graphic context. + * @param x_origin The horizontal translation. + * @param y_origin The vertical translation. + * + * Changes clip-mask in @p gc to the specified @p region and + * sets the clip origin with the values of @p x_origin and @p y_origin. + * Output will be clippped to remain contained within the region. The + * clip origin is interpreted relative to the origin of whatever + * destination drawable is specified in a graphics request. The + * region is interpreted relative to the clip origin. Future changes + * to region have no effect on the gc clip-mask. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_gc_clip_set(Ecore_X_Region region, + Ecore_X_GC gc, + int x_origin, + int y_origin) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_set_gc_clip_region(_ecore_xcb_conn, gc, region, x_origin, y_origin); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Change the shape extension of a window. + * @param region The region. + * @param dest The window whose shape is changed. + * @param type The kind of shape. + * @param x_offset The horizontal offset. + * @param y_offset The vertical offset. + * + * Set the specified Shape extension region of @p window to @p region, + * offset by @p x_offset and @p y_offset. Future changes to region + * have no effect on the window shape. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_window_shape_set(Ecore_X_Region region, + Ecore_X_Window dest, + Ecore_X_Shape_Type type, + int x_offset, + int y_offset) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_set_window_shape_region(_ecore_xcb_conn, dest, type, x_offset, y_offset, region); +#endif /* ECORE_XCB_FIXES */ +} + + +/** + * Change clip-mask in picture to the specified region. + * @param region The region. + * @param picture The picture. + * @param x_origin The X coordinate of the origin. + * @param y_origin The Y coordinate of the origin. + * + * Changes clip-mask in picture to the specified @p region + * and sets the clip origin. Input and output will be clipped to + * remain contained within the region. The clip origin is interpreted + * relative to the origin of the drawable associated with @p picture. The + * region is interpreted relative to the clip origin. Future changes + * to region have no effect on the picture clip-mask. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_picture_clip_set(Ecore_X_Region region, + Ecore_X_Picture picture, + int x_origin, + int y_origin) +{ +#ifdef ECORE_XCB_FIXES + xcb_xfixes_set_picture_clip_region(_ecore_xcb_conn, picture, region, x_origin, y_origin); +#endif /* ECORE_XCB_FIXES */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_gc.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_gc.c new file mode 100644 index 0000000000..0a4ec22442 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_gc.c @@ -0,0 +1,45 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * Creates a new default graphics context associated with the given + * drawable. + * @param drawable Drawable to create graphics context with. If @c 0 is + * given instead, the default root window is used. + * @return The new default graphics context. + * + * Creates a new default graphics context associated with @p + * drawable. The graphic context can be used with any destination + * drawable having the same root and depth as @p drawable. Use with + * other drawables results in a BadMatch error. + */ +EAPI Ecore_X_GC +ecore_x_gc_new(Ecore_X_Drawable drawable) +{ + xcb_gcontext_t gc; + + if (!drawable) drawable = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + gc = xcb_generate_id(_ecore_xcb_conn); + xcb_create_gc(_ecore_xcb_conn, gc, drawable, 0, NULL); + + return gc; +} + + +/** + * Deletes and frees the given graphics context. + * @param gc The given graphics context. + * + * Destroyes the graphic context @p gc as well as the associated + * storage. + */ +EAPI void +ecore_x_gc_del(Ecore_X_GC gc) +{ + xcb_free_gc(_ecore_xcb_conn, gc); +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_icccm.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_icccm.c new file mode 100644 index 0000000000..1d4c6ecec4 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_icccm.c @@ -0,0 +1,1923 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* + * Various ICCCM related functions. + * + * This is ALL the code involving anything ICCCM related, for both WM and + * client. + */ + +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + +#include + + +/** + * @defgroup Ecore_X_ICCCM_Group ICCCM related functions. + * + * Functions related to ICCCM. + */ + + +typedef enum { + USPosition = 1 << 0, + USSize = 1 << 1, + PPosition = 1 << 2, + PSize = 1 << 3, + PMinSize = 1 << 4, + PMaxSize = 1 << 5, + PResizeInc = 1 << 6, + PAspect = 1 << 7, + PBaseSize = 1 << 8, + PWinGravity = 1 << 9 +} SizeHintsFlags; + + +static int _ecore_x_icccm_size_hints_get (const void *reply, + Ecore_X_Atom property, + xcb_size_hints_t *hints) +{ + uint32_t s; + + if (!hints) return 0; + + if (!reply) return 0; + if ((((xcb_get_property_reply_t *)reply)->type != ECORE_X_ATOM_WM_SIZE_HINTS) && + ((((xcb_get_property_reply_t *)reply)->format != 8) || + (((xcb_get_property_reply_t *)reply)->format != 16) || + (((xcb_get_property_reply_t *)reply)->format != 32)) && + (((xcb_get_property_reply_t *)reply)->value_len < 15)) /* OldNumPropSizeElements = 15 (pre-ICCCM) */ + return 0; + + memcpy(hints, + xcb_get_property_value((xcb_get_property_reply_t *)reply), + ((xcb_get_property_reply_t *)reply)->value_len); + + s = (USPosition | USSize | + PPosition | PSize | + PMinSize | PMaxSize | + PResizeInc | PAspect); + + if (((xcb_get_property_reply_t *)reply)->value_len >= 18) /* NumPropSizeElements = 18 (ICCCM version 1) */ + s |= (PBaseSize | PWinGravity); + else + { + xcb_size_hints_set_base_size(hints, 0, 0); + xcb_size_hints_set_win_gravity(hints, 0); + } + /* FIXME: is it necessary ? */ + /* hints->flags &= s; */ /* get rid of unwanted bits */ + + return 1; +} + + +/** + * Sets the state of a window. + * @param window The window. + * @param state The state. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_state_set(Ecore_X_Window window, + Ecore_X_Window_State_Hint state) +{ + uint32_t c[2]; + + if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + c[0] = XCB_WM_WITHDRAWN_STATE; + else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + c[0] = XCB_WM_NORMAL_STATE; + else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + c[0] = XCB_WM_ICONIC_STATE; + c[1] = 0; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_STATE, ECORE_X_ATOM_WM_STATE, 32, + 2, c); +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_state_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_STATE, + ECORE_X_ATOM_WM_STATE, + 0L, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_state_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_state_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Gets the state of a window. + * @param window The window. + * @return The state of the window + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_state_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_state_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI Ecore_X_Window_State_Hint +ecore_x_icccm_state_get(Ecore_X_Window window __UNUSED__) +{ + xcb_get_property_reply_t *reply; + uint8_t *prop; + Ecore_X_Window_State_Hint hint = ECORE_X_WINDOW_STATE_HINT_NONE; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return hint; + + if ((reply->type == 0) || + (reply->format != 8) || + (reply->value_len != 2)) + return hint; + + prop = (uint8_t *)xcb_get_property_value(reply); + switch (prop[0]) { + case XCB_WM_WITHDRAWN_STATE: + hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + break; + case XCB_WM_NORMAL_STATE: + hint = ECORE_X_WINDOW_STATE_HINT_NORMAL; + break; + case XCB_WM_ICONIC_STATE: + hint = ECORE_X_WINDOW_STATE_HINT_ICONIC; + break; + default: + hint = ECORE_X_WINDOW_STATE_HINT_NONE; + break; + } + + return hint; +} + +/** + * Sends the ClientMessage event with the DeleteWindow property. + * @param window The window. + * @param time The time. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_delete_window_send(Ecore_X_Window window, + Ecore_X_Time time) +{ + ecore_x_client_message32_send(window, ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_EVENT_MASK_NONE, + ECORE_X_ATOM_WM_DELETE_WINDOW, + time, 0, 0, 0); +} + +/** + * Sends the ClientMessage event with the TakeFocus property. + * @param window The window. + * @param time The time. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_take_focus_send(Ecore_X_Window window, + Ecore_X_Time time) +{ + ecore_x_client_message32_send(window, ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_EVENT_MASK_NONE, + ECORE_X_ATOM_WM_TAKE_FOCUS, + time, 0, 0, 0); +} + +/** + * Sends the ClientMessage event with the SaveYourself property. + * @param window The window. + * @param time The time. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_save_yourself_send(Ecore_X_Window window, + Ecore_X_Time time) +{ + ecore_x_client_message32_send(window, ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_EVENT_MASK_NONE, + ECORE_X_ATOM_WM_SAVE_YOURSELF, + time, 0, 0, 0); +} + +/** + * Sends the ConfigureNotify event with the StructureNotify property. + * @param window The window. + * @param x The X coordinate. + * @param y The Y coordinate. + * @param width The width. + * @param height The height. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_move_resize_send(Ecore_X_Window window, + int x, + int y, + int width, + int height) +{ + xcb_configure_notify_event_t ev; + + ev.response_type = XCB_CONFIGURE_NOTIFY | 0x80; + ev.pad0 = 0; + ev.sequence = 0; + ev.event = window; + ev.window = window; + ev.above_sibling = 0; + ev.x = x; + ev.y = y; + ev.width = width; + ev.height = height; + ev.border_width = 0; + ev.override_redirect = 0; + xcb_send_event(_ecore_xcb_conn, 0, window, + XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *)&ev); +} + +/** + * Sets the hints of a window. + * @param window The window. + * @param accepts_focus AcceptFocus hint + * @param initial_state Initial state flags. + * @param icon_pixmap Icon pixmap. + * @param icon_mask Icon mask. + * @param icon_window Icon window. + * @param window_group Group window. + * @param is_urgent IsUrgent flag. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_hints_set(Ecore_X_Window window, + int accepts_focus, + Ecore_X_Window_State_Hint initial_state, + Ecore_X_Pixmap icon_pixmap, + Ecore_X_Pixmap icon_mask, + Ecore_X_Window icon_window, + Ecore_X_Window window_group, + int is_urgent) +{ + xcb_wm_hints_t *hints; + + hints = xcb_alloc_wm_hints(); + if (!hints) + return; + + xcb_wm_hints_set_input(hints, accepts_focus); + if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + xcb_wm_hints_set_withdrawn(hints); + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + xcb_wm_hints_set_normal(hints); + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + xcb_wm_hints_set_iconic(hints); + if (icon_pixmap != 0) + xcb_wm_hints_set_icon_pixmap(hints, icon_pixmap); + if (icon_mask != 0) + xcb_wm_hints_set_icon_mask(hints, icon_mask); + if (icon_window != 0) + xcb_wm_hints_set_icon_window(hints, icon_window); + if (window_group != 0) + xcb_wm_hints_set_window_group(hints, window_group); + if (is_urgent) + xcb_wm_hints_set_urgent(hints); + xcb_set_wm_hints(_ecore_xcb_conn, window, hints); + free(hints); +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_hints_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_HINTS, + ECORE_X_ATOM_WM_HINTS, + 0L, XCB_NUM_WM_HINTS_ELEMENTS); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_hints_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_hints_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Gets the hints of a window. + * @param window The window. + * @param accepts_focus AcceptFocus hint + * @param initial_state Initial state flags. + * @param icon_pixmap Icon pixmap. + * @param icon_mask Icon mask. + * @param icon_window Icon window. + * @param window_group Group window. + * @param is_urgent IsUrgent flag. + * @return 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_hints_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_hints_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI int +ecore_x_icccm_hints_get(Ecore_X_Window window __UNUSED__, + int *accepts_focus, + Ecore_X_Window_State_Hint *initial_state, + Ecore_X_Pixmap *icon_pixmap, + Ecore_X_Pixmap *icon_mask, + Ecore_X_Window *icon_window, + Ecore_X_Window *window_group, + int *is_urgent) +{ + xcb_wm_hints_t *hints; + xcb_get_property_reply_t *reply; + + if (accepts_focus) + *accepts_focus = 1; + if (initial_state) + *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + if (icon_pixmap) + *icon_pixmap = 0; + if (icon_mask) + *icon_mask = 0; + if (icon_window) + *icon_window = 0; + if (window_group) + *window_group = 0; + if (is_urgent) + *is_urgent = 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + if ((reply->type != ECORE_X_ATOM_WM_HINTS) || + (reply->value_len < (XCB_NUM_WM_HINTS_ELEMENTS - 1)) || + (reply->format != 32)) + return 0; + + hints = xcb_alloc_wm_hints(); + if (!hints) + return 0; + + memcpy(hints, xcb_get_property_value(reply), reply->value_len); + + if ((xcb_wm_hints_is_input_hint(hints)) && (accepts_focus)) + { + if (xcb_wm_hints_get_input(hints)) + *accepts_focus = 1; + else + *accepts_focus = 0; + } + if ((xcb_wm_hints_is_state_hint(hints)) && (initial_state)) + { + if (xcb_wm_hints_state_is_withdrawn(hints)) + *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + else if (xcb_wm_hints_state_is_normal(hints)) + *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + else if (xcb_wm_hints_state_is_iconic(hints)) + *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC; + } + if ((xcb_wm_hints_is_icon_pixmap_hint(hints)) && (icon_pixmap)) + { + *icon_pixmap = xcb_wm_hints_get_icon_pixmap(hints); + } + if ((xcb_wm_hints_is_icon_mask_hint(hints)) && (icon_mask)) + { + *icon_mask = xcb_wm_hints_get_icon_mask(hints); + } + if ((xcb_wm_hints_is_icon_window_hint(hints)) && (icon_window)) + { + *icon_window = xcb_wm_hints_get_icon_window(hints); + } + if ((xcb_wm_hints_is_window_group_hint(hints)) && (window_group)) + { + if (reply->value_len < XCB_NUM_WM_HINTS_ELEMENTS) + *window_group = 0; + else + *window_group = xcb_wm_hints_get_window_group(hints); + } + if ((xcb_wm_hints_is_x_urgency_hint(hints)) && (is_urgent)) + { + *is_urgent = 1; + } + + free(hints); + + return 1; +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_size_pos_hints_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_NORMAL_HINTS, + ECORE_X_ATOM_WM_SIZE_HINTS, + 0L, 18); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_size_pos_hints_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_size_pos_hints_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Sets the hints of a window. + * @param window The window. + * @param request_pos Request position flag. + * @param gravity Gravity. + * @param min_w Minimum width. + * @param min_h Minimum height. + * @param max_w Maximum width. + * @param max_h Maximum height. + * @param base_w Base width + * @param base_h Base height + * @param step_x X step coordinate. + * @param step_y Y step coordinate. + * @param min_aspect Minimum aspect ratio. + * @param max_aspect Maximum aspect ratio. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_size_pos_hints_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_size_pos_hints_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_size_pos_hints_set(Ecore_X_Window window, + int request_pos, + Ecore_X_Gravity gravity, + int min_w, + int min_h, + int max_w, + int max_h, + int base_w, + int base_h, + int step_x, + int step_y, + double min_aspect, + double max_aspect) +{ + xcb_size_hints_t *hint; + xcb_get_property_reply_t *reply; + + hint = xcb_alloc_size_hints(); + if (!hint) + return; + + reply = _ecore_xcb_reply_get(); + if (!reply || + (reply->type != ECORE_X_ATOM_WM_SIZE_HINTS) || + ((reply->format != 8) && + (reply->format != 16) && + (reply->format != 32)) || + (reply->value_len < 15)) + return; + + xcb_size_hints_set_flag_none(hint); + if (request_pos) + { + xcb_size_hints_set_flag_us_position(hint); + } + if (gravity != ECORE_X_GRAVITY_NW) + { + xcb_size_hints_set_win_gravity(hint, (uint8_t)gravity); + } + if ((min_w > 0) || (min_h > 0)) + { + xcb_size_hints_set_min_size(hint, min_w, min_h); + } + if ((max_w > 0) || (max_h > 0)) + { + xcb_size_hints_set_max_size(hint, max_w, max_h); + } + if ((base_w > 0) || (base_h > 0)) + { + xcb_size_hints_set_base_size(hint, base_w, base_h); + } + if ((step_x > 1) || (step_y > 1)) + { + xcb_size_hints_set_resize_inc(hint, step_x, step_y); + } + if ((min_aspect > 0.0) || (max_aspect > 0.0)) + { + xcb_size_hints_set_aspect(hint, + (int32_t)(min_aspect * 10000), + 10000, + (int32_t)(max_aspect * 10000), + 10000); + } + xcb_set_wm_normal_hints(_ecore_xcb_conn, window, hint); + + free(hint); +} + +/** + * Gets the hints of a window. + * @param window The window. + * @param request_pos Request position flag. + * @param gravity Gravity. + * @param min_w Minimum width. + * @param min_h Minimum height. + * @param max_w Maximum width. + * @param max_h Maximum height. + * @param base_w Base width + * @param base_h Base height + * @param step_x X step coordinate. + * @param step_y Y step coordinate. + * @param min_aspect Minimum aspect ratio. + * @param max_aspect M + * @return 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_size_pos_hints_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_size_pos_hints_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI int +ecore_x_icccm_size_pos_hints_get(Ecore_X_Window window __UNUSED__, + int *request_pos, + Ecore_X_Gravity *gravity, + int *min_w, + int *min_h, + int *max_w, + int *max_h, + int *base_w, + int *base_h, + int *step_x, + int *step_y, + double *min_aspect, + double *max_aspect) +{ + xcb_size_hints_t *hint; + xcb_get_property_reply_t *reply; + int32_t minw = 0; + int32_t minh = 0; + int32_t maxw = 32767; + int32_t maxh = 32767; + int32_t basew = -1; + int32_t baseh = -1; + int32_t stepx = -1; + int32_t stepy = -1; + double mina = 0.0; + double maxa = 0.0; + + if (request_pos) *request_pos = 0; + if (gravity) *gravity = ECORE_X_GRAVITY_NW; + if (min_w) *min_w = minw; + if (min_h) *min_h = minh; + if (max_w) *max_w = maxw; + if (max_h) *max_h = maxh; + if (base_w) *base_w = basew; + if (base_h) *base_h = baseh; + if (step_x) *step_x = stepx; + if (step_y) *step_y = stepy; + if (min_aspect) *min_aspect = mina; + if (max_aspect) *max_aspect = maxa; + + + hint = xcb_alloc_size_hints(); + if (!hint) return 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + if (!_ecore_x_icccm_size_hints_get(reply, ECORE_X_ATOM_WM_NORMAL_HINTS, hint)) + return 0; + + if (xcb_size_hints_is_us_position(hint) || xcb_size_hints_is_p_position(hint)) + { + if (request_pos) + *request_pos = 1; + } + if (xcb_size_hints_is_p_win_gravity(hint)) + { + if (gravity) + *gravity = xcb_size_hints_get_win_gravity(hint); + } + if (xcb_size_hints_is_p_min_size(hint)) + { + xcb_size_hints_get_min_size(hint, &minw, &minh); + } + if (xcb_size_hints_is_p_max_size(hint)) + { + xcb_size_hints_get_max_size(hint, &maxw, &maxh); + if (maxw < minw) + maxw = minw; + if (maxh < minh) + maxh = minh; + } + if (xcb_size_hints_is_p_base_size(hint)) + { + xcb_size_hints_get_base_size(hint, &basew, &baseh); + if (basew > minw) + minw = basew; + if (baseh > minh) + minh = baseh; + } + if (xcb_size_hints_is_p_resize_inc(hint)) + { + xcb_size_hints_get_increase(hint, &stepx, &stepy); + if (stepx < 1) + stepx = 1; + if (stepy < 1) + stepy = 1; + } + if (xcb_size_hints_is_p_aspect(hint)) + { + int32_t min_aspect_num; + int32_t min_aspect_den; + int32_t max_aspect_num; + int32_t max_aspect_den; + + xcb_size_hints_get_min_aspect(hint, &min_aspect_num, &min_aspect_den); + if (min_aspect_den > 0) + mina = ((double)min_aspect_num) / ((double)min_aspect_den); + xcb_size_hints_get_max_aspect(hint, &max_aspect_num, &max_aspect_den); + if (max_aspect_den > 0) + maxa = ((double)max_aspect_num) / ((double)max_aspect_den); + } + + if (min_w) + *min_w = minw; + if (min_h) + *min_h = minh; + if (max_w) + *max_w = maxw; + if (max_h) + *max_h = maxh; + if (base_w) + *base_w = basew; + if (base_h) + *base_h = baseh; + if (step_x) + *step_x = stepx; + if (step_y) + *step_y = stepy; + if (min_aspect) + *min_aspect = mina; + if (max_aspect) + *max_aspect = maxa; + + free(hint); + + return 1; +} + +/** + * Set the title of a window + * @param window The window. + * @param title The title. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_title_set(Ecore_X_Window window, + const char *title) +{ + /* FIXME: to do: utf8 */ + +/* xprop.value = NULL; */ +/* #ifdef X_HAVE_UTF8_STRING */ +/* list[0] = strdup(t); */ +/* ret = */ +/* Xutf8TextListToTextProperty(_ecore_xcb_conn, list, 1, XUTF8StringStyle, */ +/* &xprop); */ +/* #else */ +/* list[0] = strdup(t); */ +/* ret = */ +/* XmbTextListToTextProperty(_ecore_xcb_conn, list, 1, XStdICCTextStyle, */ +/* &xprop); */ +/* #endif */ + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_NAME, ECORE_X_ATOM_STRING, 8, + strlen(title), title); +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_title_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_NAME, + XCB_GET_PROPERTY_TYPE_ANY, + 0L, 128); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_title_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_title_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Gets the title of a window. + * @param window The window (Unused). + * @return The title of the window + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_title_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_title_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI char * +ecore_x_icccm_title_get(Ecore_X_Window window __UNUSED__) +{ + char *title = NULL; + xcb_get_property_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return NULL; + + if (reply->type == ECORE_X_ATOM_UTF8_STRING) + { + int length; + + /* FIXME: verify the value of length */ + length = (reply->value_len * reply->format) / 8; + title = (char *)malloc((length + 1) * sizeof(char)); + memcpy(title, xcb_get_property_value(reply), length); + title[length] = '\0'; + } + /* not in UTF8, so we convert */ + else + { + /* convert to utf8 */ + + /* FIXME: to do... */ + +/* #ifdef X_HAVE_UTF8_STRING */ +/* ret = Xutf8TextPropertyToTextList(_ecore_xcb_conn, &xprop, */ +/* &list, &num); */ +/* #else */ +/* ret = XmbTextPropertyToTextList(_ecore_xcb_conn, &xprop, */ +/* &list, &num); */ +/* #endif */ + +/* if ((ret == XLocaleNotSupported) || */ +/* (ret == XNoMemory) || (ret == XConverterNotFound)) */ +/* { */ +/* t = strdup((char *)xprop.value); */ +/* } */ +/* else if ((ret >= Success) && (num > 0)) */ +/* { */ +/* t = strdup(list[0]); */ +/* } */ +/* if (list) */ +/* XFreeStringList(list); */ +/* } */ + +/* if (xprop.value) XFree(xprop.value); */ + } + + return title; +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_protocol_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_ATOM_ATOM, 0, 1000000L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_protocol_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_protocol_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Set or unset a wm protocol property. + * @param window The Window + * @param protocol The protocol to enable/disable + * @param on On/Off + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_protocol_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_protocol_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_protocol_set(Ecore_X_Window window, + Ecore_X_WM_Protocol protocol, + int on) +{ + xcb_get_property_reply_t *reply; + Ecore_X_Atom *protos = NULL; + Ecore_X_Atom proto; + uint32_t protos_count = 0; + uint8_t already_set = 0; + + /* Check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return; + + proto = _ecore_xcb_atoms_wm_protocols[protocol]; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + if ((reply->type == ECORE_X_ATOM_ATOM) && (reply->format == 32)) + { + uint32_t i; + + protos_count = reply->value_len / sizeof(Ecore_X_Atom); + protos = (Ecore_X_Atom *)xcb_get_property_value(reply); + for (i = 0; i < protos_count; i++) + { + if (protos[i] == proto) + { + already_set = 1; + break; + } + } + } + + if (on) + { + Ecore_X_Atom *new_protos = NULL; + + if (already_set) + return; + new_protos = (Ecore_X_Atom *)malloc((protos_count + 1) * sizeof(Ecore_X_Atom)); + if (!new_protos) + return; + memcpy(new_protos, protos, reply->value_len); + new_protos[protos_count] = proto; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_ATOM_ATOM, 32, + protos_count + 1, new_protos); + free(new_protos); + } + else + { + uint32_t i; + + if (!already_set) + return; + for (i = 0; i < protos_count; i++) + { + if (protos[i] == proto) + { + uint32_t j; + + for (j = i + 1; j < protos_count; j++) + protos[j - 1] = protos[j]; + if (protos_count > 1) + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_ATOM_ATOM, 32, + protos_count - 1, protos); + else + xcb_delete_property(_ecore_xcb_conn, window, + ECORE_X_ATOM_WM_PROTOCOLS); + return; + } + } + } +} + +/** + * Determines whether a protocol is set for a window. + * @param window The Window (Unused). + * @param protocol The protocol to query. + * @return 1 if the protocol is set, else 0. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_protocol_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_protocol_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI int +ecore_x_icccm_protocol_isset(Ecore_X_Window window __UNUSED__, + Ecore_X_WM_Protocol protocol) +{ + xcb_get_property_reply_t *reply; + Ecore_X_Atom *protos = NULL; + Ecore_X_Atom proto; + uint32_t i; + uint8_t ret = 0; + + /* check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return 0; + + proto = _ecore_xcb_atoms_wm_protocols[protocol]; + + reply = _ecore_xcb_reply_get(); + if (!reply || (reply->type != ECORE_X_ATOM_ATOM) || (reply->format != 32)) + { + return 0; + } + + protos = (Ecore_X_Atom *)xcb_get_property_value(reply); + for (i = 0; i < reply->value_len; i++) + if (protos[i] == proto) + { + ret = 1; + break; + } + + return ret; +} + +/** + * Set a window name & class. + * @param window The window + * @param name The name string + * @param class The class string + * + * Set the name and class of @p window to respectively @p name and @p class. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_name_class_set(Ecore_X_Window window, + const char *name, + const char *class) +{ + char *class_string; + char *s; + int length_name; + int length_class; + + length_name = strlen(name); + length_class = strlen(class); + class_string = (char *)malloc(sizeof(char) * (length_name + length_class + 2)); + if (!class_string) + return; + s = class_string; + if (length_name) + { + strcpy(s, name); + s += length_name + 1; + } + else + *s++ = '\0'; + if(length_class) + strcpy(s, class); + else + *s = '\0'; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_CLASS, ECORE_X_ATOM_STRING, 8, + length_name + length_class + 2, (void *)class_string); + free(class_string); +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_name_class_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_CLASS, + ECORE_X_ATOM_STRING, + 0, 2048L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_name_class_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_name_class_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get a window name and class. + * @param window The window (Unused). + * @param name The name string. + * @param class The class string. + * + * Store the name and class of @p window into respectively @p name and + * @p class. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_name_class_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_name_class_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_name_class_get(Ecore_X_Window window __UNUSED__, + char **name, + char **class) +{ + xcb_get_property_reply_t *reply; + void *data; + char *n = NULL; + char *c = NULL; + int length; + int length_name; + int length_class; + + + if (name) *name = NULL; + if (class) *class = NULL; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return; + + if ((reply->type != ECORE_X_ATOM_STRING) || + (reply->format != 8)) + return; + + length = reply->value_len; + data = xcb_get_property_value(reply); + /* data contains the name string and the class string */ + /* separated by the NULL character. data is not NULL-terminated */ + length_name = strlen(data); + n = (char *)malloc(sizeof(char) * (length_name + 1)); + if (!n) + return; + length_class = length - length_name - 1; + c = (char *)malloc(sizeof(char) * (length_class + 1)); + if (!c) + { + free(n); + return; + } + + memcpy(n, data, length_name); + n[length_name] = '\0'; + length_class = length - length_name - 1; + data += length_name + 1; + memcpy(c, data, length_class); + c[length_class] = '\0'; + + if (name) + *name = n; + if (class) + *class = c; +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_client_machine_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root, + ECORE_X_ATOM_WM_CLIENT_MACHINE, + XCB_GET_PROPERTY_TYPE_ANY, + 0L, 1000000L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_client_machine_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_client_machine_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get a window client machine string. + * @param window The window + * @return The windows client machine string + * + * Return the client machine of a window. String must be free'd when done with. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_client_machine_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_client_machine_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI char * +ecore_x_icccm_client_machine_get(Ecore_X_Window window) +{ + char *name; + + name = ecore_x_window_prop_string_get(window, ECORE_X_ATOM_WM_CLIENT_MACHINE); + return name; +} + +/** + * Sets the WM_COMMAND property for @a win. + * + * @param window The window. + * @param argc Number of arguments. + * @param argv Arguments. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_command_set(Ecore_X_Window window, + int argc, + char **argv) +{ + void *buf; + char *b; + int nbytes; + int i; + + for (i = 0, nbytes = 0; i < argc; i++) + { + nbytes += strlen(argv[i]) + 1; + } + buf = malloc(sizeof(char) * nbytes); + if (!buf) + return; + b = (char *)buf; + for (i = 0; i < argc; i++) + { + if (argv[i]) + { + strcpy(b, argv[i]); + b += strlen(argv[i]) + 1; + } + else + *b++ = '\0'; + } + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_COMMAND, ECORE_X_ATOM_STRING, 8, + nbytes, buf); + free(buf); +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_command_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_COMMAND, + XCB_GET_PROPERTY_TYPE_ANY, + 0L, 1000000L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_command_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_command_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the WM_COMMAND property for a window. + * + * @param win The window. + * @param argc Number of arguments. + * @param argv Arguments. + * + * Return the command of @p window and store it in @p argv. @p argc + * contains the number of arguments. String must be free'd when done with. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_command_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_command_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_command_get(Ecore_X_Window window __UNUSED__, + int *argc, + char ***argv) +{ + xcb_get_property_reply_t *reply; + char **v; + char *data; + char *cp; + char *start; + uint32_t value_len; + int c; + int i; + int j; + + if (argc) *argc = 0; + if (argv) *argv = NULL; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return; + + if ((reply->type != ECORE_X_ATOM_STRING) || + (reply->format != 8)) + return; + + value_len = reply->value_len; + data = (char *)xcb_get_property_value(reply); + if (value_len && (data[value_len - 1] == '\0')) + value_len--; + + c = 1; + for (cp = (char *)data, i = value_len; i > 0; cp++, i--) + { + if (*cp == '\0') c++; + } + v = (char **)malloc((c + 1) * sizeof(char *)); + if (!v) + return; + + start = (char *)malloc((value_len + 1) * sizeof(char)); + if (!start) + { + free(v); + return; + } + + memcpy (start, (char *) data, value_len); + start[value_len] = '\0'; + for (cp = start, i = value_len + 1, j = 0; i > 0; cp++, i--) { + if (*cp == '\0') { + v[j] = start; + start = (cp + 1); + j++; + } + } + + if (c < 1) + { + if (v) + free(v); + return; + } + + if (argc) *argc = c; + if (argv) + { + (*argv) = malloc(c * sizeof(char *)); + if (!*argv) + { + free(v); + if (argc) *argc = 0; + return; + } + for (i = 0; i < c; i++) + { + if (v[i]) + (*argv)[i] = strdup(v[i]); + else + (*argv)[i] = strdup(""); + } + } + + free(v); +} + +/** + * Set a window icon name. + * @param window The window. + * @param title The icon name string. + * + * Set @p window icon name. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_icon_name_set(Ecore_X_Window window, + const char *title) +{ + /* FIXME: do the UTF8 conversion... */ + +/* #ifdef X_HAVE_UTF8_STRING */ +/* list[0] = strdup(t); */ +/* ret = Xutf8TextListToTextProperty(_ecore_xcb_conn, list, 1, */ +/* XUTF8StringStyle, &xprop); */ +/* #else */ +/* list[0] = strdup(t); */ +/* ret = XmbTextListToTextProperty(_ecore_xcb_conn, list, 1, */ +/* XStdICCTextStyle, &xprop); */ +/* #endif */ + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_ICON_NAME, ECORE_X_ATOM_WM_ICON_NAME, + 8, strlen(title), title); +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_icon_name_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_ICON_NAME, + XCB_GET_PROPERTY_TYPE_ANY, + 0L, 128L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_icon_name_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_icon_name_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get a window icon name. + * @param window The window. + * @return The windows icon name string. + * + * Return the icon name of @p window. String must be free'd when done with. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_icon_name_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_icon_name_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI char * +ecore_x_icccm_icon_name_get(Ecore_X_Window window __UNUSED__) +{ + xcb_get_property_reply_t *reply; + char *title = NULL; + + reply = _ecore_xcb_reply_get(); + if (!reply) return NULL; + + printf ("[XCB] reply->bytes_afer (should be 0): %d\n", ((xcb_get_property_reply_t *)reply)->bytes_after); + + if (reply->type == ECORE_X_ATOM_UTF8_STRING) + { + int length; + + /* FIXME: verify the value of length */ + length = reply->value_len * reply->format / 8; + title = (char *)malloc((length + 1) * sizeof(char)); + memcpy(title, xcb_get_property_value(reply), length); + title[length] = '\0'; + } + /* not in UTF8, so we convert */ + else + { + /* FIXME: do the UTF8... */ + + /* convert to utf8 */ +/* #ifdef X_HAVE_UTF8_STRING */ +/* ret = Xutf8TextPropertyToTextList(_ecore_xcb_conn, &xprop, */ +/* &list, &num); */ +/* #else */ +/* ret = XmbTextPropertyToTextList(_ecore_xcb_conn, &xprop, */ +/* &list, &num); */ +/* #endif */ + +/* if ((ret == XLocaleNotSupported) || */ +/* (ret == XNoMemory) || (ret == XConverterNotFound)) */ +/* { */ +/* t = strdup((char *)xprop.value); */ +/* } */ +/* else if (ret >= Success) */ +/* { */ +/* if ((num >= 1) && (list)) */ +/* { */ +/* t = strdup(list[0]); */ +/* } */ +/* if (list) */ +/* XFreeStringList(list); */ +/* } */ +/* } */ + +/* if (xprop.value) XFree(xprop.value); */ + } + + return title; +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_colormap_window_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? ((xcb_screen_t *)_ecore_xcb_screen)->root : window, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + ECORE_X_ATOM_WINDOW, + 0L, LONG_MAX); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_colormap_window_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_colormap_window_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Add a subwindow to the list of windows that need a different colormap installed. + * @param window The toplevel window + * @param sub_window The subwindow to be added to the colormap windows list + * + * Add @p sub_window to the list of windows that need a different + * colormap installed. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_colormap_window_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_colormap_window_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_colormap_window_set(Ecore_X_Window window, + Ecore_X_Window sub_window) +{ + void *data = NULL; + xcb_get_property_reply_t *reply; + uint32_t num; + + if (window == 0) + window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + reply = _ecore_xcb_reply_get(); + if (!reply || (reply->format != 32) || (reply->value_len == 0)) + { + data = calloc(1, sizeof(Ecore_X_Window)); + if (!data) + { + if (reply) free(reply); + return; + } + num = 1; + } + else + { + Ecore_X_Window *newset = NULL; + Ecore_X_Window *oldset = NULL; + uint32_t i; + + num = reply->value_len; + data = calloc(num + 1, sizeof(Ecore_X_Window)); + if (!data) + return; + + newset = (Ecore_X_Window *)data; + oldset = (Ecore_X_Window *)xcb_get_property_value(reply); + for (i = 0; i < num; ++i) + { + if (oldset[i] == sub_window) + { + free(newset); + return; + } + + newset[i] = oldset[i]; + } + + newset[num++] = sub_window; + } + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + ECORE_X_ATOM_WINDOW, + 32, num, data); + free(data); +} + +/** + * Remove a window from the list of colormap windows. + * @param window The toplevel window + * @param sub_window The window to be removed from the colormap window list. + * + * Remove @p sub_window from the list of colormap windows. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_colormap_window_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_colormap_window_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_colormap_window_unset(Ecore_X_Window window, + Ecore_X_Window sub_window) +{ + void *data = NULL; + Ecore_X_Window *oldset = NULL; + Ecore_X_Window *newset = NULL; + xcb_get_property_reply_t *reply; + uint32_t num; + uint32_t i; + uint32_t j; + uint32_t k = 0; + + if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + reply = _ecore_xcb_reply_get(); + if (!reply || (reply->format != 32) || (reply->value_len == 0)) + return; + + num = reply->value_len; + oldset = (Ecore_X_Window *)xcb_get_property_value(reply); + for (i = 0; i < num; i++) + { + if (oldset[i] == sub_window) + { + if (num == 1) + { + xcb_delete_property(_ecore_xcb_conn, window, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS); + return; + } + else + { + data = calloc(num - 1, sizeof(Ecore_X_Window)); + newset = (Ecore_X_Window *)data; + for (j = 0; j < num; ++j) + if (oldset[j] != sub_window) + newset[k++] = oldset[j]; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + ECORE_X_ATOM_WINDOW, + 32, k, data); + free(newset); + return; + } + } + } +} + +/** + * Specify that a window is transient for another top-level window and should be handled accordingly. + * @param window The transient window + * @param forwindow The toplevel window + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_transient_for_set(Ecore_X_Window window, + Ecore_X_Window forwindow) +{ + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_TRANSIENT_FOR, ECORE_X_ATOM_WINDOW, 32, + 1, (void *)&forwindow); +} + +/** + * Remove the transient_for setting from a window. + * @param window The window. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_transient_for_unset(Ecore_X_Window window) +{ + xcb_delete_property(_ecore_xcb_conn, window, ECORE_X_ATOM_WM_TRANSIENT_FOR); +} + +/* + * Sends the GetProperty request. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_transient_for_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_WM_TRANSIENT_FOR, + ECORE_X_ATOM_WINDOW, + 0L, 1L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetProperty request sent by ecore_x_icccm_transient_for_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_transient_for_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the window this window is transient for, if any. + * @param window The window to check (Unused). + * @return The window ID of the top-level window, or 0 if the property does not exist. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_transient_for_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_transient_for_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI Ecore_X_Window +ecore_x_icccm_transient_for_get(Ecore_X_Window window __UNUSED__) +{ + xcb_get_property_reply_t *reply; + Ecore_X_Window forwin = 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return forwin; + + if ((reply->format != 32) || + (reply->value_len == 0) || + (reply->type != ECORE_X_ATOM_WINDOW)) + return forwin; + + forwin = *(Ecore_X_Window *)xcb_get_property_value(reply); + + return forwin; +} + +/** + * Set the window role hint. + * @param window The window + * @param role The role string. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_window_role_set(Ecore_X_Window window, + const char *role) +{ + ecore_x_window_prop_string_set(window, ECORE_X_ATOM_WM_WINDOW_ROLE, + (char *)role); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_window_role_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root, + ECORE_X_ATOM_WM_WINDOW_ROLE, XCB_GET_PROPERTY_TYPE_ANY, + 0L, 1000000L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_icccm_window_role_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_window_role_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the window role. + * @param window The window. + * @return The window's role string. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_window_role_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_window_role_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI char * +ecore_x_icccm_window_role_get(Ecore_X_Window window) +{ + return ecore_x_window_prop_string_get(window, ECORE_X_ATOM_WM_WINDOW_ROLE); +} + +/** + * Set the window's client leader. + * @param window The window + * @param leader The client leader window + * + * All non-transient top-level windows created by an app other than + * the main window must have this property set to the app's main window. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_client_leader_set(Ecore_X_Window window, + Ecore_X_Window leader) +{ + ecore_x_window_prop_window_set(window, ECORE_X_ATOM_WM_CLIENT_LEADER, + &leader, 1); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_client_leader_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window, + ECORE_X_ATOM_WM_CLIENT_LEADER, + ECORE_X_ATOM_WINDOW, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_icccm_client_leader_get_prefetch(). + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_client_leader_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the window's client leader. + * @param window The window + * @return The window's client leader window, or 0 if unset. + * + * To use this function, you must call before, and in order, + * ecore_x_icccm_client_leader_get_prefetch(), which sends the GetProperty request, + * then ecore_x_icccm_client_leader_get_fetch(), which gets the reply. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI Ecore_X_Window +ecore_x_icccm_client_leader_get(Ecore_X_Window window) +{ + Ecore_X_Window leader; + + if (ecore_x_window_prop_window_get(window, ECORE_X_ATOM_WM_CLIENT_LEADER, + &leader, 1) > 0) + return leader; + + return 0; +} + +/** + * Send the ClientMessage event with the ChangeState property. + * @param window The window. + * @param root The root window. + * @ingroup Ecore_X_ICCCM_Group + */ +EAPI void +ecore_x_icccm_iconic_request_send(Ecore_X_Window window, + Ecore_X_Window root) +{ + xcb_client_message_event_t ev; + + if (!window) return; + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + /* send_event is bit 7 (0x80) of response_type */ + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 32; + ev.sequence = 0; + ev.window = window; + ev.type = ECORE_X_ATOM_WM_CHANGE_STATE; + ev.data.data32[0] = XCB_WM_ICONIC_STATE; + + xcb_send_event(_ecore_xcb_conn, 0, root, + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&ev); +} + +/* FIXME: there are older E hints, gnome hints and mwm hints and new netwm */ +/* hints. each should go in their own file/section so we know which */ +/* is which. also older kde hints too. we should try support as much */ +/* as makese sense to support */ diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_mwm.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_mwm.c new file mode 100644 index 0000000000..f96c4cf5d9 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_mwm.c @@ -0,0 +1,149 @@ +/* + * Various MWM related functions. + * + * This is ALL the code involving anything MWM related. for both WM and + * client. + */ + +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + + +/** + * @defgroup Ecore_X_MWM_Group MWM related functions. + * + * Functions related to MWM. + */ + +#define ECORE_X_MWM_HINTS_FUNCTIONS (1 << 0) +#define ECORE_X_MWM_HINTS_DECORATIONS (1 << 1) +#define ECORE_X_MWM_HINTS_INPUT_MODE (1 << 2) +#define ECORE_X_MWM_HINTS_STATUS (1 << 3) + +typedef struct _mwmhints +{ + uint32_t flags; + uint32_t functions; + uint32_t decorations; + int32_t inputmode; + uint32_t status; +} +MWMHints; + + +/** + * Sends the GetProperty request. + * @param window Window whose MWM hints are requested. + * @ingroup Ecore_X_MWM_Group + */ +EAPI void +ecore_x_mwm_hints_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root, + ECORE_X_ATOM_MOTIF_WM_HINTS, + ECORE_X_ATOM_MOTIF_WM_HINTS, + 0, LONG_MAX); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_mwm_hints_get_prefetch(). + * @ingroup Ecore_X_MWM_Group + */ +EAPI void +ecore_x_mwm_hints_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * To document. + * @param window Unused. + * @param fhint To document. + * @param dhint To document. + * @param ihint To document. + * @return 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_mwm_hints_get_prefetch(), which sends the GetProperty request, + * then ecore_x_mwm_hints_get_fetch(), which gets the reply. + * @ingroup Ecore_X_MWM_Group + */ +EAPI int +ecore_x_mwm_hints_get(Ecore_X_Window window __UNUSED__, + Ecore_X_MWM_Hint_Func *fhint, + Ecore_X_MWM_Hint_Decor *dhint, + Ecore_X_MWM_Hint_Input *ihint) +{ + MWMHints *mwmhints = NULL; + int ret = 0; + xcb_get_property_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + if ((reply->format != 32) || + (reply->value_len == 0)) + return 0; + + mwmhints = xcb_get_property_value(reply); + if (reply->value_len >= 4) + { + if (dhint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_DECORATIONS) + *dhint = mwmhints->decorations; + else + *dhint = ECORE_X_MWM_HINT_DECOR_ALL; + } + if (fhint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_FUNCTIONS) + *fhint = mwmhints->functions; + else + *fhint = ECORE_X_MWM_HINT_FUNC_ALL; + } + if (ihint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_INPUT_MODE) + *ihint = mwmhints->inputmode; + else + *ihint = ECORE_X_MWM_HINT_INPUT_MODELESS; + } + ret = 1; + } + + return ret; +} + +/** + * Sets the borderless flag of a window using MWM. + * @param window The window. + * @param borderless The borderless flag. + * @ingroup Ecore_X_MWM_Group + */ +EAPI void +ecore_x_mwm_borderless_set(Ecore_X_Window window, + int borderless) +{ + uint32_t data[5] = {0, 0, 0, 0, 0}; + + data[0] = 2; /* just set the decorations hint! */ + data[2] = !borderless; + + if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_MOTIF_WM_HINTS, ECORE_X_ATOM_MOTIF_WM_HINTS, + 32, 5, data); +} + diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_netwm.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_netwm.c new file mode 100644 index 0000000000..27eacf1d0a --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_netwm.c @@ -0,0 +1,3197 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* + * _NET_WM... aka Extended Window Manager Hint (EWMH) functions. + */ + +#include "Ecore_Data.h" +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + + +/** + * @defgroup Ecore_X_NetWM_Group Extended Window Manager Hint (EWMH) functions + * + * Functions related to the Extended Window Manager Hint (EWMH). + */ + + +typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info; + +struct _Ecore_X_Startup_Info +{ + Ecore_X_Window win; + + int init; + + int buffer_size; + char *buffer; + + int length; + + /* These are the sequence info fields */ + char *id; + char *name; + int screen; + char *bin; + char *icon; + int desktop; + int timestamp; + char *description; + char *wmclass; + int silent; +}; + +#if 0 +static void _ecore_x_window_prop_string_utf8_get_prefetch(Ecore_X_Window window, Ecore_X_Atom atom); +static void _ecore_x_window_prop_string_utf8_get_fetch(void); +#endif +static void _ecore_x_window_prop_string_utf8_set(Ecore_X_Window window, Ecore_X_Atom atom, const char *str); +static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window window, Ecore_X_Atom atom); +#if 0 /* Unused */ +static int _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info); +static int _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, char *data); +#endif +static void _ecore_x_netwm_startup_info_free(void *data); + +/* + * Local variables + */ + +static Ecore_Hash *startup_info = NULL; + +/** + * Initialize the NetWM module + */ +EAPI void +ecore_x_netwm_init(void) +{ + startup_info = ecore_hash_new(ecore_direct_hash, ecore_direct_compare); + if (startup_info) + { + ecore_hash_set_free_value(startup_info, _ecore_x_netwm_startup_info_free); + } +} + +/** + * Shutdown the NetWM module + */ +EAPI void +ecore_x_netwm_shutdown(void) +{ + if (startup_info) + ecore_hash_destroy(startup_info); + startup_info = NULL; +} + +/** + * Set the _NET_SUPPORTING_WM_CHECK property. + * @param root The root window. + * @param check The child window. + * @param wm_name The name of the Window Manager. + * + * Set the _NET_SUPPORTING_WM_CHECK property on the @p root window to be + * the ID of the child window @p check created by the Window Manager. + * @p check also have the _NET_WM_NAME property set to the name + * @p wm_name of the Window Manager. + * + * The Window MUST call that function to indicate that a compliant + * window manager is active. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_wm_identify(Ecore_X_Window root, + Ecore_X_Window check, + const char *wm_name) +{ + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1); + ecore_x_window_prop_window_set(check, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1); + _ecore_x_window_prop_string_utf8_set(check, ECORE_X_ATOM_NET_WM_NAME, wm_name); + /* This one isn't mandatory */ + _ecore_x_window_prop_string_utf8_set(root, ECORE_X_ATOM_NET_WM_NAME, wm_name); +} + +/** + * Set the _NET_SUPPORTED property. + * @param root The root window. + * @param supported The supported hints. + * @param num The number of hints. + * + * Set the _NET_SUPPORTED property on the @p root window. The hints + * that the Window Manager supports are stored in @p supported. + * + * The Window Manager MUST set this property to indicate which hints + * it supports. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_supported_set(Ecore_X_Window root, + Ecore_X_Atom *supported, + int num) +{ + ecore_x_window_prop_atom_set(root, ECORE_X_ATOM_NET_SUPPORTED, supported, num); +} + +/** + * Sends the GetProperty request. + * @param root The root window + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_supported_get_prefetch(Ecore_X_Window root) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, root, + ECORE_X_ATOM_NET_SUPPORTED, ECORE_X_ATOM_ATOM, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_supported_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_supported_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the hints supported by the Window Manager. + * @param root The root window. + * @param supported The supported hints. + * @param num The number of atoms. + * @return 1 on success, 0 otherwise. + * + * Get the hints supported by the Window Manager. @p root is the root + * window. The hints are stored in @p supported. The number of hints + * is stored in @p num. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_supported_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_supported_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_supported_get(Ecore_X_Window root, + Ecore_X_Atom **supported, + int *num) +{ + int num_ret; + + if (num) *num = 0UL; + if (supported) *supported = NULL; + + num_ret = ecore_x_window_prop_xid_list_get(root, + ECORE_X_ATOM_NET_SUPPORTED, + ECORE_X_ATOM_ATOM, + supported); + if (num_ret <= 0) + return 0; + + if (num) *num = (uint32_t)num_ret; + return 1; +} + +/** + * Set the _NET_NUMBER_OF_DESKTOPS property. + * @param root The root window. + * @param n_desks The number of desktops. + * + * Set the number of desktops @p n_desks of the Window Manager by + * sending the _NET_NUMBER_OF_DESKTOPS to the @p root window. + * + * The Window Manager SHOULD set and update this property to indicate + * the number of virtual desktops. A Pager can request a change in the + * number of desktops by using that function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_count_set(Ecore_X_Window root, + unsigned int n_desks) +{ + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS, + &n_desks, 1); +} + +/** + * Set the _NET_VIRTUAL_ROOTS property. + * @param root The root window. + * @param vroots The virtual root windows. + * @param n_desks The number of desks. + * + * Set the number of virtual desktops by sending the + * _NET_VIRTUAL_ROOTS property to the @p root window. @p vroots is an + * array of window and @p n_desks is the number of windows. + * + * A Window Manager that implements virtual desktops by reparent + * client windows to a child of the root window MUST use that + * function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_roots_set(Ecore_X_Window root, + Ecore_X_Window *vroots, + unsigned int n_desks) +{ + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_VIRTUAL_ROOTS, vroots, n_desks); +} + +/** + * Set the _NET_DESKTOP_NAMES property. + * @param root The root window. + * @param names The names of the virtual desktops. + * @param n_desks The number of virtual desktops. + * + * Set the name of each virtual desktop by sending the + * _NET_DESKTOP_NAMES to the @p root window. @p names are the names of + * the virtual desktops and @p n_desks is the number of virtual + * desktops. + * + * A Pager MAY use that function. @p n_desks may be different from the + * one passed to ecore_x_netwm_desk_count_set(). If it less or equal, + * then the desktops with high numbers are unnamed. If it is larger, + * then the excess names are considered to be reserved in case the + * number of desktops is increased. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_names_set(Ecore_X_Window root, + const char **names, + unsigned int n_desks) +{ + char ss[32]; + char *buf; + const char *s; + uint32_t i; + uint32_t len; + uint32_t l; + + buf = NULL; + len = 0; + + for (i = 0; i < n_desks; i++) + { + s = (names) ? names[i] : NULL; + if (!s) + { + /* Default to "Desk-" */ + sprintf(ss, "Desk-%d", i); + s = ss; + } + + l = strlen(s) + 1; + buf = realloc(buf, len + l); + memcpy(buf + len, s, l); + len += l; + } + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, root, + ECORE_X_ATOM_NET_DESKTOP_NAMES, + ECORE_X_ATOM_UTF8_STRING, + 8, len, (const void *)buf); + free(buf); +} + +/** + * Set the _NET_DESKTOP_GEOMETRY property. + * @param root The root window. + * @param width The width of the desktop. + * @param height The height of the desktop. + * + * Set the common @p width and @p height of all desktops by sending + * the _NET_DESKTOP_GEOMETRY to the @p root window. + * + * This size is equal to the screen size if the Window Manager doesn't + * support large desktops, otherwise it's equal to the virtual size of + * the desktop. The Window Manager SHOULD set this property. A Pager + * can request a change in the desktop geometry by using this + * function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_size_set(Ecore_X_Window root, + unsigned int width, + unsigned int height) +{ + uint32_t size[2]; + + size[0] = width; + size[1] = height; + ecore_x_window_prop_card32_set(root, + ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, + size, 2); +} + +/** + * Set the _NET_DESKTOP_VIEWPORT property. + * @param root The root window. + * @param origins An array of paris of coordiantes. + * @param n_desks The number of virtual desktops. + * + * Set the top left corner of each desktop's viewport by sending the + * _NET_DESKTOP_VIEWPORT property to the @p root window. @p origins + * contains each pair of X coordinate and Y coordinate of the top left + * corner of each desktop's viewport. + * + * If the Window Manager does not support large desktops, the + * coordinates MUST be (0,0). A Pager can request to change the + * viewport for the current desktop by using this function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_viewports_set(Ecore_X_Window root, + unsigned int *origins, + unsigned int n_desks) +{ + ecore_x_window_prop_card32_set(root, + ECORE_X_ATOM_NET_DESKTOP_VIEWPORT, + origins, 2 * n_desks); +} + +/** + * Set the _NET_DESKTOP_LAYOUT property. + * @param root The root window. + * @param orientation + * @param columns + * @param rows + * @param starting_corner + * + * Set the layout of virtual desktops relative to each other by + * sending the _NET_DESKTOP_LAYOUT to the @p root window. + * @p orientation defines the orientation of the virtual desktop. 0 + * means horizontal layout, 1 means vertical layout. @p columns is + * the number of desktops in the X direction and @p rows is the number + * in the Y direction. @p starting_corner is the corner containing the + * first desktop. The values for @p starting_corner are 0 (top-left), + * 1 (top-right), 2 (bottom-right) and 3 (bottom-left). + * + * When the orientation is horizontal the desktops are laid out in + * rows, with the first desktop in the specified starting corner. So a + * layout with four columns and three rows starting in + * the top-left corner looks like this: + * + * +--+--+--+--+ + * | 0| 1| 2| 3| + * +--+--+--+--+ + * | 4| 5| 6| 7| + * +--+--+--+--+ + * | 8| 9|10|11| + * +--+--+--+--+ + * + * With @p starting_corner being bottom-right, it looks like this: + * + * +--+--+--+--+ + * |11|10| 9| 8| + * +--+--+--+--+ + * | 7| 6| 5| 4| + * +--+--+--+--+ + * | 3| 2| 1| 0| + * +--+--+--+--+ + * + * When the orientation is vertical the layout with four columns and + * three rows starting in the top-left corner looks like: + * + * +--+--+--+--+ + * | 0| 3| 6| 9| + * +--+--+--+--+ + * | 1| 4| 7|10| + * +--+--+--+--+ + * | 2| 5| 8|11| + * +--+--+--+--+ + * + * With @p starting_corner being top-right, it looks like: + * + * +--+--+--+--+ + * | 9| 6| 3| 0| + * +--+--+--+--+ + * |10| 7| 4| 1| + * +--+--+--+--+ + * |11| 8| 5| 2| + * +--+--+--+--+ + * + * This function MUST be used by a Pager and NOT by the Window + * Manager. When using this function, the Pager must own a manager + * selection. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_layout_set(Ecore_X_Window root, + int orientation, + int columns, + int rows, + int starting_corner) +{ + uint32_t layout[4]; + + layout[0] = orientation; + layout[1] = columns; + layout[2] = rows; + layout[3] = starting_corner; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT, layout, 4); +} + +/** + * Set the _NET_WORKAREA property. + * @param root The root window. + * @param areas An array of areas. + * @param n_desks The number of desks. + * + * Set the work area for each desktop by sending the _NET_WORKAREA + * property to the @p root window. An area contains the geometry (X + * and Y coordinates, width and height). These geometries are + * specified relative to the viewport on each desktop and specify an + * area that is completely contained within the viewport. @p areas + * stores these geometries. @p n_desks is the number of geometry to + * set. + * + * This function MUST be set by the Window Manager. It is used by + * desktop applications to place desktop icons appropriately. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_workareas_set(Ecore_X_Window root, + unsigned int *areas, + unsigned int n_desks) +{ + ecore_x_window_prop_card32_set(root, + ECORE_X_ATOM_NET_WORKAREA, + areas, 4 * n_desks); +} + +/** + * Set the _NET_CURRENT_DESKTOP property. + * @param root The root window. + * @param desk The index of the current desktop. + * + * Set the current desktop by sending the _NET_CURRENT_DESKTOP to the + * @p root window. @p deskmust be an integer number between 0 and the + * number of desks (set by ecore_x_netwm_desk_count_set()) -1. + * + * This function MUST be called by the Window Manager. If a Pagerwants + * to switch to naother desktop, it MUST call that function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desk_current_set(Ecore_X_Window root, + unsigned int desk) +{ + ecore_x_window_prop_card32_set(root, + ECORE_X_ATOM_NET_CURRENT_DESKTOP, + &desk, 1); +} + +/** + * Set the _NET_SHOWING_DESKTOP property. + * @param root The root window + * @param on 0 to hide the desktop, non 0 to show it. + * + * Set or unset the desktop in a "showing mode" by sending the + * _NET_SHOWING_DESKTOP property to the @p root window. If @p on is 0, + * the windows are hidden and the desktop background is displayed and + * focused. + * + * If a Pager wants to enter or leave the mode, it MUST use this + * function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, + int on) +{ + uint32_t val; + + val = (on) ? 1 : 0; + ecore_x_window_prop_card32_set(root, + ECORE_X_ATOM_NET_SHOWING_DESKTOP, + &val, 1); +} + +/* + * Client status + */ + +/** + * Set the _NET_CLIENT_LIST property. + * @param root The root window. + * @param p_clients An array of windows. + * @param n_clients The number of windows. + * + * Map all the X windows managed by the window manager from the oldest + * to the newest by sending the _NET_CLIENT_LIST property to the + * @p root window. The X windows are stored in @p p_clients and their + * number in @p n_clients. + * + * This function SHOULD be called by the Window Manager. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_client_list_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, + unsigned int n_clients) +{ + ecore_x_window_prop_window_set(root, + ECORE_X_ATOM_NET_CLIENT_LIST, + p_clients, n_clients); +} + +/** + * Set the _NET_CLIENT_LIST_STACKING property. + * @param root The root window. + * @param p_clients An array of windows. + * @param n_clients The number of windows. + * + * Stack all the X windows managed by the window manager from bottom + * to top order by sending the _NET_CLIENT_LIST_STACKING property to the + * @p root window. The X windows are stored in @p p_clients and their + * number in @p n_clients. + * + * This function SHOULD be called by the Window Manager. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, + unsigned int n_clients) +{ + ecore_x_window_prop_window_set(root, + ECORE_X_ATOM_NET_CLIENT_LIST_STACKING, + p_clients, n_clients); +} + +/** + * Set the _NET_ACTIVE_WINDOW property. + * @param root The root window. + * @param window The widow to activate. + * + * Activate @p window by sending the _NET_ACTIVE_WINDOW property to + * the @p root window. + * + * If a Client wants to activate another window, it MUST call this + * function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_client_active_set(Ecore_X_Window root, + Ecore_X_Window window) +{ + ecore_x_window_prop_window_set(root, + ECORE_X_ATOM_NET_ACTIVE_WINDOW, + &window, 1); +} + +/** + * Set the _NET_WM_NAME property. + * @param window The widow to activate. + * @param name The title name of the window. + * + * Set the title name of @p window to @p name by sending the + * _NET_WM_NAME property to @p window. + * + * The Client SHOULD set the title of @p window in UTF-8 encoding. If + * set, the Window Manager should use this in preference to WM_NAME. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_name_set(Ecore_X_Window window, + const char *name) +{ + _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_NAME, name); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_name_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_NAME, ECORE_X_ATOM_UTF8_STRING, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_name_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_name_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the title of a window. + * @param window The window. + * @param name The title name. + * @return Returns always 1. + * + * Retrieve the title name of @p window and store it in @p name. The + * function returns always 1. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_name_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_name_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_name_get(Ecore_X_Window window, + char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(window, ECORE_X_ATOM_NET_WM_NAME); + return 1; +} + +/** + * Set the _NET_STARTUP_ID property. + * @param window The window. + * @param id The ID name. + * + * Set the ID @p id used for the startup sequence by sending the + * property _NET_STARTUP_ID to @p window. The ID name should be + * encoded in UTF-8. + * + * If a new value for the property is set, the Window Manager + * should update the window's status accordingly (update its virtual + * desktop, etc.). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_startup_id_set(Ecore_X_Window window, + const char *id) +{ + _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_STARTUP_ID, id); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_startup_id_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_STARTUP_ID, ECORE_X_ATOM_UTF8_STRING, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_startup_id_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_startup_id_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the startup ID name of a window. + * @param window The window + * @param id The ID name + * @return Return always 1. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_startup_id_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_startup_id_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_startup_id_get(Ecore_X_Window window, + char **id) +{ + if (id) + *id = _ecore_x_window_prop_string_utf8_get(window, ECORE_X_ATOM_NET_STARTUP_ID); + return 1; +} + +/** + * Set the _NET_WM_VISIBLE_NAME property. + * @param window The widow to activate. + * @param name The title name of the window. + * + * Set the title name of @p window to @p name by sending the + * _NET_WM_VISIBLE_NAME property to @p window, when the Window Manager + * displays a window name other than by calling + * ecore_x_netwm_name_set(). + * + * The Client SHOULD set the title of @p window in UTF-8 + * encoding. This function is used for displaying title windows like + * [xterm1], [xterm2], ... thereby allowing Pagers to display the same + * title as the Window Manager. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_visible_name_set(Ecore_X_Window window, + const char *name) +{ + _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_VISIBLE_NAME, + name); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_visible_name_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_VISIBLE_NAME, ECORE_X_ATOM_UTF8_STRING, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_visible_name_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_visible_name_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the visible title of a window. + * @param window The window. + * @param name The title name. + * @return Returns always 1. + * + * Retrieve the visible title name of @p window and store it in @p name. The + * function returns always 1. + * @param window The window + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_visible_name_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_visible_name_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_visible_name_get(Ecore_X_Window window, + char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(window, + ECORE_X_ATOM_NET_WM_VISIBLE_NAME); + return 1; +} + +/** + * Set the _NET_WM_ICON_NAME property. + * @param window The widow to activate. + * @param name The icon name of the window. + * + * Set the icon name of @p window to @p name by sending the + * _NET_WM_ICON_NAME property to @p window. + * + * The Client SHOULD set the title of @p window in UTF-8 encoding. If + * set, the Window Manager should use this in preference to WM_ICON_NAME. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icon_name_set(Ecore_X_Window window, + const char *name) +{ + _ecore_x_window_prop_string_utf8_set(window, ECORE_X_ATOM_NET_WM_ICON_NAME, + name); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icon_name_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_ICON_NAME, ECORE_X_ATOM_UTF8_STRING, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_icon_name_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icon_name_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the icon name of a window. + * @param window The window. + * @param name The icon name. + * @return Returns always 1. + * + * Retrieve the icon name of @p window and store it in @p name. The + * function returns always 1. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_icon_name_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_icon_name_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_icon_name_get(Ecore_X_Window window, + char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(window, + ECORE_X_ATOM_NET_WM_ICON_NAME); + return 1; +} + +/** + * Set the _NET_WM_VISIBLE_ICON_NAME property. + * @param window The widow to activate. + * @param name The title name of the window. + * + * Set the icon name of @p window to @p name by sending the + * _NET_WM_VISIBLE_ICON_NAME property to @p window, when the Window Manager + * displays a icon name other than by calling + * ecore_x_netwm_icon_name_set(). + * + * The Client SHOULD set the icon name in UTF-8 + * encoding. The Window Manager MUST use this function is it display + * an icon name other than with ecore_x_netwm_icon_name_set(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_visible_icon_name_set(Ecore_X_Window window, + const char *name) +{ + _ecore_x_window_prop_string_utf8_set(window, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME, + name); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_visible_icon_name_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME, ECORE_X_ATOM_UTF8_STRING, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_visible_icon_name_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_visible_icon_name_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the visible icon name of a window. + * @param window The window. + * @param name The icon name. + * @return Returns always 1. + * + * Retrieve the visible icon name of @p window and store it in + * @p name. The function returns always 1. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_visible_icon_name_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_visible_icon_name_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_visible_icon_name_get(Ecore_X_Window window, + char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(window, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME); + return 1; +} + +/** + * Set the _NET_WM_DESKTOP property. + * @param window The window. + * @param desk The desktop index. + * + * Set on which desktop the @p window is in by sending the + * _NET_WM_DESKTOP property to @p window. @p desk is the index of + * the desktop, starting from 0. To indicate that the window should + * appear on all desktops, @p desk must be equal to 0xFFFFFFFF. + * + * A Client MAY choose not to set this property, in which case the + * Window Manager SHOULD place it as it wishes. + * + * The Window Manager should honor _NET_WM_DESKTOP whenever a + * withdrawn window requests to be mapped. + * + * A Client can request a change of desktop for a non-withdrawn window + * by sending a _NET_WM_DESKTOP client message to the root window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desktop_set(Ecore_X_Window window, + unsigned int desk) +{ + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desktop_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_DESKTOP, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_desktop_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desktop_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the visible icon name of a window. + * @param window The window. + * @param desk The desktop index. + * @return 1 on success, 0 otherwise. + * + * Retrieve the desktop index in which @p window is displayed and + * store it in @p desk. If @p desk value is 0xFFFFFFFF, the window + * appears on all desktops. The function returns 1 on success, 0 + * otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_desktop_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_desktop_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_desktop_get(Ecore_X_Window window, + unsigned int *desk) +{ + int ret; + uint32_t tmp; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_DESKTOP, + &tmp, 1); + + if (desk) *desk = tmp; + return (ret == 1) ? 1 : 0; +} + +/** + * Set the _NET_WM_STRUT property. + * @param window The window + * @param left The number of pixels at the left of the screen. + * @param right The number of pixels at the right of the screen. + * @param top The number of pixels at the top of the screen. + * @param bottom The number of pixels at the bottom of the screen. + * + * Set space at the edje of the screen by sending the _NET_WM_STRUT + * property to @p window if @p window is to reserve that space. + * @p left, @p right, @p top and @p bottom are respectively the number + * of pixels at the left, right, top and bottom of the screen. + * + * This property is deprecated and ecore_x_netwm_strut_partial_set() + * should be used instead. However, Clients MAY set this property in + * addition to _NET_WM_STRUT_PARTIAL to ensure backward compatibility + * with Window Managers supporting older versions of the + * Specification. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_strut_set(Ecore_X_Window window, + int left, + int right, + int top, + int bottom) +{ + uint32_t strut[4]; + + strut[0] = left; + strut[1] = right; + strut[2] = top; + strut[3] = bottom; + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_STRUT, strut, 4); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_strut_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_STRUT, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_strut_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_strut_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* + * _NET_WM_STRUT is deprecated + */ + +/** + * Get the space at the edje of the screen. + * @param window The window + * @param left The number of pixels at the left of the screen. + * @param right The number of pixels at the right of the screen. + * @param top The number of pixels at the top of the screen. + * @param bottom The number of pixels at the bottom of the screen. + * @return 1 on success, 0 otherwise. + * + * Retrieve the space at the edje of the screen if @p window is to + * reserve such space. The number of pixels at the left, right, top + * and bottom of the screen are respectively stored in @p left, + * @p right, @p top and @p bottom. This function returns 1 on success, + * 0 otherwise. + * + * This property is deprecated. See ecore_x_netwm_strut_set() for more + * informations. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_strut_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_strut_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_strut_get(Ecore_X_Window window, + int *left, + int *right, + int *top, + int *bottom) +{ + uint32_t strut[4]; + int ret = 0; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_STRUT, strut, 4); + if (ret != 4) + return 0; + + if (left) *left = strut[0]; + if (right) *right = strut[1]; + if (top) *top = strut[2]; + if (bottom) *bottom = strut[3]; + + return 1; +} + +/** + * Set the _NET_WM_STRUT_PARTIAL property. + * @param window The window + * @param left The number of pixels at the left of the screen. + * @param right The number of pixels at the right of the screen. + * @param top The number of pixels at the top of the screen. + * @param bottom The number of pixels at the bottom of the screen. + * @param left_start_y The number of pixels. + * @param left_end_y The number of pixels. + * @param right_start_y The number of pixels. + * @param right_end_y The number of pixels. + * @param top_start_x The number of pixels. + * @param top_end_x The number of pixels. + * @param bottom_start_x The number of pixels. + * @param bottom_end_x The number of pixels. + * + * Set space at the edje of the screen by sending the + * _NET_WM_STRUT_PARTIAL property to @p window if @p window is to + * reserve that space. @p left, @p right, @p top and @p bottom are + * respectively the number of pixels at the left, right, top and + * bottom of the screen. + * + * TODO: more description for that function. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_strut_partial_set(Ecore_X_Window window, + int left, + int right, + int top, + int bottom, + int left_start_y, + int left_end_y, + int right_start_y, + int right_end_y, + int top_start_x, + int top_end_x, + int bottom_start_x, + int bottom_end_x) +{ + unsigned int strut[12]; + + strut[0] = left; + strut[1] = right; + strut[2] = top; + strut[3] = bottom; + strut[4] = left_start_y; + strut[5] = left_end_y; + strut[6] = right_start_y; + strut[7] = right_end_y; + strut[8] = top_start_x; + strut[9] = top_end_x; + strut[10] = bottom_start_x; + strut[11] = bottom_end_x; + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_strut_partial_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_strut_partial_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_strut_partial_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the space at the edje of the screen of a window. + * @param window The window + * @param left The number of pixels at the left of the screen. + * @param right The number of pixels at the right of the screen. + * @param top The number of pixels at the top of the screen. + * @param bottom The number of pixels at the bottom of the screen. + * @param left_start_y The number of pixels. + * @param left_end_y The number of pixels. + * @param right_start_y The number of pixels. + * @param right_end_y The number of pixels. + * @param top_start_x The number of pixels. + * @param top_end_x The number of pixels. + * @param bottom_start_x The number of pixels. + * @param bottom_end_x The number of pixels. + * + * Retrieve the space at the edje of the screen if @p window is to + * reserve such space. The number of pixels at the left, right, top + * and bottom of the screen are respectively stored in @p left, + * @p right, @p top and @p bottom. This function returns 1 on success, + * 0 otherwise. + * + * TODO: more description for that function. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_strut_partial_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_strut_partial_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_strut_partial_get(Ecore_X_Window window, + int *left, + int *right, + int *top, + int *bottom, + int *left_start_y, + int *left_end_y, + int *right_start_y, + int *right_end_y, + int *top_start_x, + int *top_end_x, + int *bottom_start_x, + int *bottom_end_x) +{ + uint32_t strut[12]; + int ret = 0; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12); + if (ret != 12) + return 0; + + if (left) *left = strut[0]; + if (right) *right = strut[1]; + if (top) *top = strut[2]; + if (bottom) *bottom = strut[3]; + if (left_start_y) *left_start_y = strut[4]; + if (left_end_y) *left_end_y = strut[5]; + if (right_start_y) *right_start_y = strut[6]; + if (right_end_y) *right_end_y = strut[7]; + if (top_start_x) *top_start_x = strut[8]; + if (top_end_x) *top_end_x = strut[9]; + if (bottom_start_x) *bottom_start_x = strut[10]; + if (bottom_end_x) *bottom_end_x = strut[11]; + return 1; +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icons_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_ICON, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_icons_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icons_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Retrieve hte possible icons of a window. + * @param window The window + * @param icon An array of icons. + * @param num The number of icons. + * @return 1 on success, 0 otherwise. + * + * Retrieve an array of possible icons of @p window. The icons are + * stored in @p icon and their number in @p num. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_icons_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_icons_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_icons_get(Ecore_X_Window window, + Ecore_X_Icon **icon, + int *num) +{ + uint32_t *data; + uint32_t *p; + uint32_t *src; + uint32_t icons; + uint32_t len; + uint32_t i; + int num_ret; + + if (num) *num = 0UL; + if (icon) *icon = NULL; + + num_ret = ecore_x_window_prop_card32_list_get(window, + ECORE_X_ATOM_NET_WM_ICON, + &data); + if ((num_ret <= 0) || !data) + return 0; + + if (num_ret < 2) + { + free(data); + return 0; + } + + /* Check how many icons there are */ + icons = 0; + p = data; + while (p) + { + len = p[0] * p[1]; + p += (len + 2); + if ((p - data) > num_ret) + { + free(data); + return 0; + } + icons++; + + if ((p - data) == num_ret) + p = NULL; + } + if (num) *num = icons; + + /* If the user doesn't want the icons, return */ + if (!icon) + { + free(data); + return 1; + } + + /* Allocate memory */ + *icon = malloc(icons * sizeof(Ecore_X_Icon)); + if (!(*icon)) + { + free(data); + return 0; + } + + /* Fetch the icons */ + p = data; + for (i = 0; i < icons; i++) + { + uint32_t *ps, *pd, *pe; + + len = p[0] * p[1]; + ((*icon)[i]).width = p[0]; + ((*icon)[i]).height = p[1]; + src = &(p[2]); + ((*icon)[i]).data = malloc(len * sizeof(uint32_t)); + if (!((*icon)[i]).data) + { + while (i) + free(((*icon)[--i]).data); + free(*icon); + free(data); + return 0; + } + + pd = ((*icon)[i]).data; + ps = src; + pe = ps + len; + for (; ps < pe; ps++) + { + uint32_t r, g, b, a; + + a = (*ps >> 24) & 0xff; + r = (((*ps >> 16) & 0xff) * a) / 255; + g = (((*ps >> 8) & 0xff) * a) / 255; + b = (((*ps ) & 0xff) * a) / 255; + *pd = (a << 24) | (r << 16) | (g << 8) | (b); + pd++; + } + p += (len + 2); + } + + free(data); + + return 1; +} + +/** + * Set the _NET_WM_ICON_GEOMETRY property. + * @param window The window. + * @param x The X coordinate of the icon. + * @param y The Y coordinate of the icon. + * @param width The width of the icon. + * @param height The height of the icon. + * + * Set the geometry of the icon of @p window by sending the + * _NET_WM_ICON_GEOMETRY property to @p window. @p x, @p y, @p width + * and @p height specify respectively the X coordinate, the Y + * coordinate, the width and the height of the icon. + * + * Stand alone tools like a taskbar or an iconbox MAY use this + * function. This functions makes possible for a Window Manager to + * display a nice animation like morphing the window into its icon. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icon_geometry_set(Ecore_X_Window window, + int x, + int y, + int width, + int height) +{ + uint32_t geometry[4]; + + geometry[0] = (uint32_t)x; + geometry[1] = (uint32_t)y; + geometry[2] = (uint32_t)width; + geometry[3] = (uint32_t)height; + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icon_geometry_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_icon_geometry_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_icon_geometry_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the geometry of an icon. + * @param window The window + * @param x x + * @param x The X coordinate of the icon. + * @param y The Y coordinate of the icon. + * @param width The width of the icon. + * @param height The height of the icon. + * @return 1 on success, 0 othrwise. + * + * Retrieve the geometry of the icon of @p window. The geometry is + * stored in @p x, @p y, @p width and @p height. The function returns + * 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_icon_geometry_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_icon_geometry_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_icon_geometry_get(Ecore_X_Window window, + int *x, + int *y, + int *width, + int *height) +{ + uint32_t geometry[4]; + int ret; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4); + if (ret != 4) + return 0; + + if (x) *x = geometry[0]; + if (y) *y = geometry[1]; + if (width) *width = geometry[2]; + if (height) *height = geometry[3]; + + return 1; +} + +/** + * Set the _NET_WM_PID property. + * @param window The window. + * @param pid The process ID. + * + * Set the process ID of the client owning @p window by sending the + * _NET_WM_PID property to @p window. + * + * This function MAY be used by the Window Manager to kill windows + * which do not respond to the _NET_WM_PING protocol. + * + * If _NET_WM_PID is set, the ICCCM-specified property + * WM_CLIENT_MACHINE MUST also be set. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_pid_set(Ecore_X_Window window, + int pid) +{ + unsigned int tmp; + + tmp = pid; + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_PID, + &tmp, 1); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_pid_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_PID, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_pid_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_pid_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the process ID of a client window. + * @param window The window. + * @param pid The process ID. + * @return 1 on success, 0 otherwise. + * + * Retrieve the process ID of @p window and store it in @p pid. This + * function returns 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_pid_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_pid_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_pid_get(Ecore_X_Window window, + int *pid) +{ + int ret; + uint32_t tmp; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_PID, + &tmp, 1); + if (pid) *pid = tmp; + + return (ret == 1) ? 1 : 0; +} + +/** + * Set the _NET_WM_HANDLED_ICONS property. + * @param window The window. + * + * Indicate to the Window Manager that it does not need to provide + * icons for the iconified @p window by sending the + * _NET_WM_HANDLED_ICONS property to @p window. + * + * This function can be used by a Pager on one of its own toplevel + * windows (for example if the Client is a taskbar and provides + * buttons for iconified windows). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_handled_icons_set(Ecore_X_Window window) +{ + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_handled_icons_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_HANDLED_ICONS, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_handled_icons_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_handled_icons_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Return wheter the Client handles icons or not. + * @param window The window. + * @return 1 if icons are handled, 0 otherwise. + * + * Return whether the client handles icons or not if @p window is + * iconified. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_handled_icons_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_handled_icons_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_handled_icons_get(Ecore_X_Window window) +{ + int ret = 0; + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0); + return (ret == 0) ? 1 : 0; +} + +/** + * Set the _NET_WM_USER_TIME property. + * @param window The window. + * @param time The last user activity time in the window. + * + * Set the XServer time at which last user activity in @p window took + * place by sending the _NET_WM_USER_TIME property to @p window. @p + * time contains that XServer time in seconds. + * + * This function allows a Window Manager to alter the focus, stacking, + * and/or placement behavior of windows when they are mapped depending + * on whether the new window was created by a user action or is a + * "pop-up" window activated by a timer or some other event. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_user_time_set(Ecore_X_Window window, + unsigned int time) +{ + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_USER_TIME, + &time, 1); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_user_time_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_USER_TIME, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_user_time_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_user_time_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the last user activity time in the window. + * @param window The window. + * @param time The returned time. + * @return 1 on success, 0 otherwise. + * + * Return the XServer time at which last user activity in @p window + * took place. The time is stored in @p time. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_user_time_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_user_time_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_user_time_get(Ecore_X_Window window, + unsigned int *time) +{ + int ret; + uint32_t tmp; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_USER_TIME, + &tmp, 1); + if (time) *time = tmp; + return (ret == 1) ? 1 : 0; +} + +Ecore_X_Window_State +_ecore_x_netwm_state_get(Ecore_X_Atom a) +{ + if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL) + return ECORE_X_WINDOW_STATE_MODAL; + else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY) + return ECORE_X_WINDOW_STATE_STICKY; + else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT) + return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT; + else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ) + return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ; + else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED) + return ECORE_X_WINDOW_STATE_SHADED; + else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR) + return ECORE_X_WINDOW_STATE_SKIP_TASKBAR; + else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER) + return ECORE_X_WINDOW_STATE_SKIP_PAGER; + else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN) + return ECORE_X_WINDOW_STATE_HIDDEN; + else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN) + return ECORE_X_WINDOW_STATE_FULLSCREEN; + else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE) + return ECORE_X_WINDOW_STATE_ABOVE; + else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW) + return ECORE_X_WINDOW_STATE_BELOW; + else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION) + return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION; + else + return ECORE_X_WINDOW_STATE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_x_netwm_state_atom_get(Ecore_X_Window_State s) +{ + switch(s) + { + case ECORE_X_WINDOW_STATE_MODAL: + return ECORE_X_ATOM_NET_WM_STATE_MODAL; + case ECORE_X_WINDOW_STATE_STICKY: + return ECORE_X_ATOM_NET_WM_STATE_STICKY; + case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT: + return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT; + case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ: + return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ; + case ECORE_X_WINDOW_STATE_SHADED: + return ECORE_X_ATOM_NET_WM_STATE_SHADED; + case ECORE_X_WINDOW_STATE_SKIP_TASKBAR: + return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR; + case ECORE_X_WINDOW_STATE_SKIP_PAGER: + return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER; + case ECORE_X_WINDOW_STATE_HIDDEN: + return ECORE_X_ATOM_NET_WM_STATE_HIDDEN; + case ECORE_X_WINDOW_STATE_FULLSCREEN: + return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN; + case ECORE_X_WINDOW_STATE_ABOVE: + return ECORE_X_ATOM_NET_WM_STATE_ABOVE; + case ECORE_X_WINDOW_STATE_BELOW: + return ECORE_X_ATOM_NET_WM_STATE_BELOW; + case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION: + return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION; + default: + return 0; + } +} + +/** + * Set the _NET_WM_STATE property. + * @param window The window. + * @param state An array of window hints. + * @param num The number of hints. + * + * Set a list of hints describing @p window state by sending the + * _NET_WM_STATE property to @p window. The hints are stored in the + * array @p state. @p num must contain the number of hints. + * + * The Window Manager SHOULD honor _NET_WM_STATE whenever a withdrawn + * window requests to be mapped. A Client wishing to change the state + * of a window MUST send a _NET_WM_STATE client message to the root + * window. The Window Manager MUST keep this property updated to + * reflect the current state of the window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_window_state_set(Ecore_X_Window window, + Ecore_X_Window_State *state, + unsigned int num) +{ + Ecore_X_Atom *set; + uint32_t i; + + if (!num) + { + ecore_x_window_prop_property_del(window, ECORE_X_ATOM_NET_WM_STATE); + return; + } + + set = malloc(num * sizeof(Ecore_X_Atom)); + if (!set) return; + + for (i = 0; i < num; i++) + set[i] = _ecore_x_netwm_state_atom_get(state[i]); + + ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_STATE, set, num); + + free(set); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_window_state_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_STATE, ECORE_X_ATOM_ATOM, + 0, 0x7fffffff);; + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_state_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_window_state_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the hints describing the window state. + * @param window The window. + * @param state The returned hins. + * @param num The number of hints. + * @return 1 on success, 0 otherwise. + * + * Retrieve the hints describing @p window state. The state is + * returned in @p state. The nummber of hints is stored in @p + * num. This function returns 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_window_state_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_window_state_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_window_state_get(Ecore_X_Window window, + Ecore_X_Window_State **state, + unsigned int *num) +{ + Ecore_X_Atom *atoms; + int num_ret; + int i; + + if (num) *num = 0; + if (state) *state = NULL; + + num_ret = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_STATE, + &atoms); + if (num_ret <= 0) + return 0; + + if (state) + { + *state = malloc(num_ret * sizeof(Ecore_X_Window_State)); + if (*state) + for (i = 0; i < num_ret; ++i) + (*state)[i] = _ecore_x_netwm_state_get(atoms[i]); + + if (num) *num = num_ret; + } + + free(atoms); + + return 1; +} + +static Ecore_X_Window_Type +_ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP) + return ECORE_X_WINDOW_TYPE_DESKTOP; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK) + return ECORE_X_WINDOW_TYPE_DOCK; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR) + return ECORE_X_WINDOW_TYPE_TOOLBAR; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU) + return ECORE_X_WINDOW_TYPE_MENU; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY) + return ECORE_X_WINDOW_TYPE_UTILITY; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH) + return ECORE_X_WINDOW_TYPE_SPLASH; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG) + return ECORE_X_WINDOW_TYPE_DIALOG; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL) + return ECORE_X_WINDOW_TYPE_NORMAL; + else + return ECORE_X_WINDOW_TYPE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type) +{ + switch (type) + { + case ECORE_X_WINDOW_TYPE_DESKTOP: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP; + case ECORE_X_WINDOW_TYPE_DOCK: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK; + case ECORE_X_WINDOW_TYPE_TOOLBAR: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR; + case ECORE_X_WINDOW_TYPE_MENU: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU; + case ECORE_X_WINDOW_TYPE_UTILITY: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY; + case ECORE_X_WINDOW_TYPE_SPLASH: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH; + case ECORE_X_WINDOW_TYPE_DIALOG: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG; + case ECORE_X_WINDOW_TYPE_NORMAL: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL; + default: + return 0; + } +} + +/* + * FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR + * , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG + */ + +/** + * Set the _NET_WM_WINDOW_TYPE property. + * @param window The window. + * @param type The functional type of the window. + * + * Set the functional @p type of @p window by sending _NET_WM_WINDOW_TYPE + * property to @p window. + * + * This property SHOULD be set by the Client before mapping. This + * property SHOULD be used by the window manager in determining the + * decoration, stacking position and other behavior of the window. The + * Client SHOULD specify window types in order of preference (the first + * being most preferable). + * + * This hint is intended to replace the MOTIF hints. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_window_type_set(Ecore_X_Window window, + Ecore_X_Window_Type type) +{ + Ecore_X_Atom atom; + + atom = _ecore_x_netwm_window_type_atom_get(type); + ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atom, 1); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_window_type_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_WINDOW_TYPE, ECORE_X_ATOM_ATOM, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_type_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_window_type_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* FIXME: Maybe return 0 on some conditions? */ + +/** + * Get the functional type of a window. + * @param window The window. + * @param type The function type of the window. + * @return 1 on success, 0 otherwise. + * + * Retrieve the functional type of @p window. The type is stored in + * @p type. This function returns 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_window_type_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_window_type_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_window_type_get(Ecore_X_Window window, + Ecore_X_Window_Type *type) +{ + Ecore_X_Atom *atoms; + int num; + int i; + + if (type) *type = ECORE_X_WINDOW_TYPE_NORMAL; + + num = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atoms); + if (num < 0) + { + /* IMO this is not the place to mix netwm and icccm /kwo */ + /* Check if WM_TRANSIENT_FOR is set */ + + /* Disable it for xcb */ + +/* if ((type) && (ecore_x_icccm_transient_for_get(window))) */ +/* *type = ECORE_X_WINDOW_TYPE_DIALOG; */ +/* return 1; */ + } + + if (type) + { + for (i = 0; i < num; ++i) + { + *type = _ecore_x_netwm_window_type_type_get(atoms[i]); + if (*type != ECORE_X_WINDOW_TYPE_UNKNOWN) + break; + } + } + + free(atoms); + + return 1; +} + +static Ecore_X_Atom +_ecore_x_netwm_action_atom_get(Ecore_X_Action action) +{ + switch (action) + { + case ECORE_X_ACTION_MOVE: + return ECORE_X_ATOM_NET_WM_ACTION_MOVE; + case ECORE_X_ACTION_RESIZE: + return ECORE_X_ATOM_NET_WM_ACTION_RESIZE; + case ECORE_X_ACTION_MINIMIZE: + return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE; + case ECORE_X_ACTION_SHADE: + return ECORE_X_ATOM_NET_WM_ACTION_SHADE; + case ECORE_X_ACTION_STICK: + return ECORE_X_ATOM_NET_WM_ACTION_STICK; + case ECORE_X_ACTION_MAXIMIZE_HORZ: + return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ; + case ECORE_X_ACTION_MAXIMIZE_VERT: + return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT; + case ECORE_X_ACTION_FULLSCREEN: + return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN; + case ECORE_X_ACTION_CHANGE_DESKTOP: + return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP; + case ECORE_X_ACTION_CLOSE: + return ECORE_X_ATOM_NET_WM_ACTION_CLOSE; + default: + return 0; + } +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_allowed_action_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, ECORE_X_ATOM_ATOM, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_allowed_action_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_allowed_action_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* FIXME: Get complete list */ + +/** + * Check whether an action is supported by a window. + * @param window The window + * @param action The action + * @return 1 if set, 0 otherwise. + * + * Return whether the user operation @p action is supported by the + * Window Manager for @p window. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_allowed_action_isset(Ecore_X_Window window, + Ecore_X_Action action) +{ + Ecore_X_Atom *atoms; + Ecore_X_Atom atom; + int num; + int ret = 0; + int i; + + num = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + &atoms); + if (num <= 0) + return ret; + + atom = _ecore_x_netwm_action_atom_get(action); + + for (i = 0; i < num; ++i) + { + if (atom == atoms[i]) + { + ret = 1; + break; + } + } + + free(atoms); + + return ret; +} + +/* FIXME: Set complete list */ +/** + * Set the _NET_WM_ALLOWED_ACTIONS property. + * @param window The window. + * @param action An array of allowed actions. + * @param num The number of actions. + * + * Set the user operations that the Window Manager supports for + * @p window by sending the _NET_WM_ALLOWED_ACTIONS property to + * @p window. @p action stores @p num actions. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_allowed_action_set(Ecore_X_Window window, + Ecore_X_Action *action, + unsigned int num) +{ + Ecore_X_Atom *set; + unsigned int i; + + if (!num) + { + ecore_x_window_prop_property_del(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS); + return; + } + + set = malloc(num * sizeof(Ecore_X_Atom)); + if (!set) return; + + for (i = 0; i < num; i++) + set[i] = _ecore_x_netwm_action_atom_get(action[i]); + + ecore_x_window_prop_atom_set(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, set, num); + + free(set); +} + +/** + * Get the allowed actions supported by a window. + * @param window The window. + * @param action The returned array of the actions. + * @param num The number of actions. + * @return 1 on success, 0 otherwise. + * + * Retrieve the user operations that the Window Manager supports for + * @p window and store them in @p action. The number of actions is + * stored in @p num. This function returns 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_allowed_action_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_allowed_action_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_allowed_action_get(Ecore_X_Window window, + Ecore_X_Action **action, + unsigned int *num) +{ + Ecore_X_Atom *atoms; + int num_ret; + int i; + + if (num) *num = 0; + if (action) *action = NULL; + + num_ret = ecore_x_window_prop_atom_list_get(window, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + &atoms); + if (num_ret <= 0) + return 0; + + if (action) + { + *action = malloc(num_ret * sizeof(Ecore_X_Action)); + if (*action) + for (i = 0; i < num_ret; ++i) + (*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]); + + if (num) *num = num_ret; + } + + free(atoms); + + return 1; +} + +/** + * Set the _NET_WM_WINDOW_OPACITY property. + * @param window The window. + * @param opacity The opacity value. + * + * Set the desired opacity of @p window by sending the + * _NET_WM_WINDOW_OPACITY property to @p window. @p opacity is 0 for a + * transparent window and 0xffffffff for an opaque window. @p opacity + * must be multiplied with the original alpha value of @p window + * (which is 1 for visuals not including an alpha component) so that + * @p window content is modulated by the opacity value. + * + * Window Managers acting as compositing managers MAY take this into + * account when displaying a window. Window Managers MUST forward the + * value of this property to any enclosing frame window. This + * property MAY change while the window is mapped and the Window + * Manager MUST respect changes while the window is mapped. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_opacity_set(Ecore_X_Window window, + unsigned int opacity) +{ + uint32_t op = opacity; + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &op, 1); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_opacity_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_opacity_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_opacity_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the opacity value of a window. + * @param window The window. + * @param opacity The returned opacity. + * @return 1 on success, 0 otherwise. + * + * Retriee the opacity value of @p window and store it in + * @p opacity. This function returns 1 on sucess, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_opacity_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_opacity_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_opacity_get(Ecore_X_Window window, + unsigned int *opacity) +{ + int ret; + unsigned int tmp; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &tmp, 1); + if (opacity) *opacity = tmp; + return ret == 1 ? 1 : 0; +} + +/** + * Set the _NET_FRAME_EXTENTS property. + * @param window The window. + * @param fl The number of pixels of the left border of the window. + * @param fr The number of pixels of the right border of the window. + * @param ft The number of pixels of the top border of the window. + * @param fb The number of pixels of the bottom border of the window. + * + * Set the border witdh of @p window by sending the _NET_FRAME_EXTENTS + * property to @p window. @p fl, @p fr, @p ft and @p fb are respectively + * the number of pixels of the left, right, top and bottom border of + * @p window. + * + * The Window Manager MUST set _NET_FRAME_EXTENTS to the extents of + * the window's frame. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_frame_size_set(Ecore_X_Window window, + int fl, + int fr, + int ft, + int fb) +{ + uint32_t frames[4]; + + frames[0] = fl; + frames[1] = fr; + frames[2] = ft; + frames[3] = fb; + ecore_x_window_prop_card32_set(window, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4); +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_frame_size_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_FRAME_EXTENTS, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_frame_size_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_frame_size_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the frame extent of a window. + * @param window The window. + * @param fl The number of pixels of the left border of the window. + * @param fr The number of pixels of the right border of the window. + * @param ft The number of pixels of the top border of the window. + * @param fb The number of pixels of the bottom border of the window. + * @return 1 on success, 0 otherwise. + * + * Retrieve the frame extents of @p window. The number of pixels of + * the left, right, top and bottom border of @p window are + * respectively stored in @p fl, @p fr, @p ft anfd @p fb. TYhis + * function retuirns 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_frame_size_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_frame_size_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_frame_size_get(Ecore_X_Window window, + int *fl, + int *fr, + int *ft, + int *fb) +{ + uint32_t frames[4]; + int ret = 0; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4); + if (ret != 4) + return 0; + + if (fl) *fl = frames[0]; + if (fr) *fr = frames[1]; + if (ft) *ft = frames[2]; + if (fb) *fb = frames[3]; + return 1; +} + +/** + * Sends the GetProperty request. + * @param window The window. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_sync_counter_get_prefetch(Ecore_X_Window window) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER, ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetProperty request sent by ecore_x_netwm_sync_counter_get_prefetch(). + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_sync_counter_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the X ID of a X Sync counter. + * @param window The window. + * @param counter The X ID of the Sync counter. + * @return 1 on success, 0 otherwise. + * + * Retrieve the X ID of the X Sync counter of @p window and store it + * in @p counter. This function returns 1 on success, 0 otherwise. + * + * To use this function, you must call before, and in order, + * ecore_x_netwm_frame_size_get_prefetch(), which sends the GetProperty request, + * then ecore_x_netwm_frame_size_get_fetch(), which gets the reply. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_netwm_sync_counter_get(Ecore_X_Window window, + Ecore_X_Sync_Counter *counter) +{ + int ret; + unsigned int tmp; + + ret = ecore_x_window_prop_card32_get(window, ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER, + &tmp, 1); + + if (counter) *counter = tmp; + return (ret == 1) ? 1 : 0; +} + +/** + * Send a _NET_WM_PING property event. + * @param window The window. + * + * Send a ClientMessage event from @p window with the _NET_WM_PING + * property set. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_ping_send(Ecore_X_Window window) +{ + xcb_client_message_event_t ev; + + if (!window) return; + + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 32; + ev.sequence = 0; + ev.window = window; + ev.type = ECORE_X_ATOM_WM_PROTOCOLS; + ev.data.data32[0] = ECORE_X_ATOM_NET_WM_PING; + ev.data.data32[1] = XCB_CURRENT_TIME; + ev.data.data32[2] = window; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + ev.data.data32[5] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +} + +/** + * Send a _NET_WM_SYNC_REQUEST property event. + * @param window The window. + * @param serial The update request number. + * + * Send a ClientMessage event from @p window with the _NET_WM_SYNC_REQUEST + * property set. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_sync_request_send(Ecore_X_Window window, + unsigned int serial) +{ + xcb_client_message_event_t ev; + + if (!window) return; + + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 32; + ev.window = window; + ev.type = ECORE_X_ATOM_WM_PROTOCOLS; + ev.data.data32[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST; + ev.data.data32[1] = XCB_CURRENT_TIME; + ev.data.data32[2] = serial; + /* FIXME: imho, the following test is useless as serial is non negative */ + /* should we remove it ? */ + ev.data.data32[3] = (serial < 0) ? ~0L : 0L; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, window, 0, (const char *)&ev); +} + +/** + * Send a _NET_WM_STATE property event. + * @param window The window. + * @param root The root window. + * @param s1 The first state to alter. + * @param s2 The second state to alter. + * @param set 0 to unset the property, set it otherwise. + * + * Send a ClientMessage event from @p window to the @p root window + * with the _NET_WM_STATE property set. This change the state of a + * mapped window. @p s1 is the first state to alter. @p s2 is the + * second state to alter. If @p set value is 0, the property is + * removed (or unset), otherwise, the property is set. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_state_request_send(Ecore_X_Window window, + Ecore_X_Window root, + Ecore_X_Window_State s1, + Ecore_X_Window_State s2, + int set) +{ + xcb_client_message_event_t ev; + + if (!window) return; + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 32; + ev.window = window; + ev.type = ECORE_X_ATOM_NET_WM_STATE; + ev.data.data32[0] = !!set; + ev.data.data32[1] = _ecore_x_netwm_state_atom_get(s1); + ev.data.data32[2] = _ecore_x_netwm_state_atom_get(s2); + /* 1 == normal client, if someone wants to use this + * function in a pager, this should be 2 */ + ev.data.data32[3] = 1; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&ev); +} + +/** + * Send a _NET_WM_DESKTOP property event. + * @param window The window. + * @param root The root window. + * @param desktop The new desktop index. + * + * Send a ClientMessage event from @p window to the @p root window + * with the _NET_WM_DESKTOP property set. This change the state of a + * non-withdrawn window. @p desktop is the new desktop index to set. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI void +ecore_x_netwm_desktop_request_send(Ecore_X_Window window, + Ecore_X_Window root, + unsigned int desktop) +{ + xcb_client_message_event_t ev; + + if (!window) return; + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ev.response_type = XCB_CLIENT_MESSAGE | 0x80; + ev.format = 32; + ev.window = window; + ev.type = ECORE_X_ATOM_NET_WM_DESKTOP; + ev.data.data32[0] = desktop; + + xcb_send_event(_ecore_xcb_conn, 0, root, + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&ev); +} + +int +_ecore_x_netwm_startup_info_begin(Ecore_X_Window window, + char *data) +{ +#if 0 + Ecore_X_Startup_Info *info; + + if (!startup_info) return 0; + info = ecore_hash_get(startup_info, (void *)window); + if (info) + { + printf("Already got info for win: 0x%x\n", window); + _ecore_x_netwm_startup_info_free(info); + } + info = calloc(1, sizeof(Ecore_X_Startup_Info)); + if (!info) return 0; + info->win = win; + info->length = 0; + info->buffer_size = 161; + info->buffer = calloc(info->buffer_size, sizeof(char)); + if (!info->buffer) + { + _ecore_x_netwm_startup_info_free(info); + return 0; + } + memcpy(info->buffer, data, 20); + info->length += 20; + info->buffer[info->length] = 0; + ecore_hash_set(startup_info, (void *)info->win, info); + if (strlen(info->buffer) != 20) + { + /* We have a '\0' in there, the message is done */ + _ecore_x_netwm_startup_info_process(info); + } +#else + window = XCB_NONE; + data = NULL; +#endif + + return 1; +} + +int +_ecore_x_netwm_startup_info(Ecore_X_Window window, + char *data) +{ +#if 0 + Ecore_X_Startup_Info *info; + char *p; + + if (!startup_info) return 0; + info = ecore_hash_get(startup_info, (void *)window); + if (!info) return 0; + if ((info->length + 20) > info->buffer_size) + { + info->buffer_size += 160; + info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char)); + if (!info->buffer) + { + ecore_hash_remove(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + } + memcpy(info->buffer + info->length, data, 20); + p = info->buffer + info->length; + info->length += 20; + info->buffer[info->length] = 0; + if (strlen(p) != 20) + { + /* We have a '\0' in there, the message is done */ + _ecore_x_netwm_startup_info_process(info); + } +#else + window = XCB_NONE; + data = NULL; +#endif + + return 1; +} + +/* + * Set UTF-8 string property + */ +static void +_ecore_x_window_prop_string_utf8_set(Ecore_X_Window window, + Ecore_X_Atom atom, + const char *str) +{ + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + atom, ECORE_X_ATOM_UTF8_STRING, + 8, strlen(str), str); +} + +#if 0 +static void +_ecore_x_window_prop_string_utf8_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, window, + atom, ECORE_X_ATOM_UTF8_STRING, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +static void +_ecore_x_window_prop_string_utf8_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} +#endif + +/* + * Get UTF-8 string property + */ +static char * +_ecore_x_window_prop_string_utf8_get(Ecore_X_Window window __UNUSED__, + Ecore_X_Atom atom __UNUSED__) +{ + xcb_get_property_reply_t *reply; + char *str; + int length; + + reply = _ecore_xcb_reply_get(); + if (!reply) return NULL; + + if ((reply->format != 8) || + (reply->value_len <= 0)) + return NULL; + + length = reply->value_len; + str = (char *)malloc (sizeof (char) * (length + 1)); + if (!str) + { + return NULL; + } + memcpy(str, xcb_get_property_value(reply), length); + str[length] = '\0'; + + return str; +} + +#if 0 /* Unused */ +/* + * Process startup info + */ +static int +_ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info) +{ + Ecore_X_Event_Startup_Sequence *e; + int event; + char *p; + + p = strchr(info->buffer, ':'); + if (!p) + { + ecore_hash_remove(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + *p = 0; + if (!strcmp(info->buffer, "new")) + { + if (info->init) + event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE; + else + event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW; + info->init = 1; + } + else if (!strcmp(info->buffer, "change")) + { + event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE; + } + else if (!strcmp(info->buffer, "remove")) + event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE; + else + { + ecore_hash_remove(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + + p++; + + if (!_ecore_x_netwm_startup_info_parse(info, p)) + { + ecore_hash_remove(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + + if (info->init) + { + e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence)); + if (!e) + { + ecore_hash_remove(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + e->win = info->win; + ecore_event_add(event, e, NULL, NULL); + } + + if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE) + { + ecore_hash_remove(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + } + else + { + /* Discard buffer */ + info->length = 0; + info->buffer[0] = 0; + } + return 1; +} + +/* + * Parse startup info + */ +static int +_ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, + char *data) +{ + + while (*data) + { + int in_quot_sing, in_quot_dbl, escaped; + char *p, *pp; + char *key; + char value[1024]; + + /* Skip space */ + while (*data == ' ') data++; + /* Get key */ + key = data; + data = strchr(key, '='); + if (!data) return 0; + *data = 0; + data++; + + /* Get value */ + p = data; + pp = value; + in_quot_dbl = 0; + in_quot_sing = 0; + escaped = 0; + while (*p) + { + if ((pp - value) >= 1024) return 0; + if (escaped) + { + *pp = *p; + pp++; + escaped = 0; + } + else if (in_quot_sing) + { + if (*p == '\\') + escaped = 1; + else if (*p == '\'') + in_quot_sing = 0; + else + { + *pp = *p; + pp++; + } + } + else if (in_quot_dbl) + { + if (*p == '\\') + escaped = 1; + else if (*p == '\"') + in_quot_dbl = 0; + else + { + *pp = *p; + pp++; + } + } + else + { + if (*p == '\\') + escaped = 1; + else if (*p == '\'') + in_quot_sing = 1; + else if (*p == '\"') + in_quot_dbl = 1; + else if (*p == ' ') + { + break; + } + else + { + *pp = *p; + pp++; + } + } + p++; + } + if ((in_quot_dbl) || (in_quot_sing)) return 0; + data = p; + *pp = 0; + + /* Parse info */ + if (!strcmp(key, "ID")) + { + if ((info->id) && (strcmp(info->id, value))) return 0; + info->id = strdup(value); + p = strstr(value, "_TIME"); + if (p) + { + info->timestamp = atoi(p + 5); + } + } + else if (!strcmp(key, "NAME")) + { + if (info->name) free(info->name); + info->name = strdup(value); + } + else if (!strcmp(key, "SCREEN")) + { + info->screen = atoi(value); + } + else if (!strcmp(key, "BIN")) + { + if (info->bin) free(info->bin); + info->bin = strdup(value); + } + else if (!strcmp(key, "ICON")) + { + if (info->icon) free(info->icon); + info->icon = strdup(value); + } + else if (!strcmp(key, "DESKTOP")) + { + info->desktop = atoi(value); + } + else if (!strcmp(key, "TIMESTAMP")) + { + if (!info->timestamp) + info->timestamp = atoi(value); + } + else if (!strcmp(key, "DESCRIPTION")) + { + if (info->description) free(info->description); + info->description = strdup(value); + } + else if (!strcmp(key, "WMCLASS")) + { + if (info->wmclass) free(info->wmclass); + info->wmclass = strdup(value); + } + else if (!strcmp(key, "SILENT")) + { + info->silent = atoi(value); + } + else + { + printf("Ecore X Sequence, Unknown: %s=%s\n", key, value); + } + } + if (!info->id) return 0; + return 1; +} +#endif + +/* + * Free startup info struct + */ +static void +_ecore_x_netwm_startup_info_free(void *data) +{ + Ecore_X_Startup_Info *info; + + info = data; + if (!info) return; + if (info->buffer) free(info->buffer); + if (info->id) free(info->id); + if (info->name) free(info->name); + if (info->bin) free(info->bin); + if (info->icon) free(info->icon); + if (info->description) free(info->description); + if (info->wmclass) free(info->wmclass); + free(info); +} + +/* + * Is screen composited? + */ + +/* FIXME: one round trip can be removed. Can we keep it ? */ + +/** + * Check whether a screen is composited or not. + * @param screen The screen index. + * + * Return 1 if @p screen is composited, 0 otherwise. + * @ingroup Ecore_X_NetWM_Group + */ +EAPI int +ecore_x_screen_is_composited(int screen) +{ + char buf[32]; + xcb_intern_atom_cookie_t cookie_atom; + xcb_get_selection_owner_cookie_t cookie_owner; + xcb_intern_atom_reply_t *reply_atom; + xcb_get_selection_owner_reply_t *reply_owner; + Ecore_X_Window window; + Ecore_X_Atom atom; + + snprintf(buf, sizeof(buf), "_NET_WM_CM_S%d", screen); + cookie_atom = xcb_intern_atom_unchecked(_ecore_xcb_conn, 1, + strlen(buf), buf); + reply_atom = xcb_intern_atom_reply(_ecore_xcb_conn, cookie_atom, NULL); + if (!reply_atom) return 0; + atom = reply_atom->atom; + free(reply_atom); + + cookie_owner = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, atom); + reply_owner = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie_owner, NULL); + if (!reply_owner) return 0; + + window = reply_owner->owner; + free(reply_owner); + + return window != XCB_NONE; +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_pixmap.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_pixmap.c new file mode 100644 index 0000000000..f976f93493 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_pixmap.c @@ -0,0 +1,117 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_Pixmap_Group X Pixmap Functions + * + * Functions that operate on pixmaps. + */ + + +/** + * Creates a new pixmap. + * @param win Window used to determine which screen of the display the + * pixmap should be created on. If 0, the default root window + * is used. + * @param w Width of the new pixmap. + * @param h Height of the new pixmap. + * @param dep Depth of the pixmap. If 0, the default depth of the default + * screen is used. + * @return New pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI Ecore_X_Pixmap +ecore_x_pixmap_new(Ecore_X_Window win, + int w, + int h, + int dep) +{ + Ecore_X_Pixmap pmap; + + if (win == 0) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + if (dep == 0) dep = ((xcb_screen_t *)_ecore_xcb_screen)->root_depth; + + pmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, dep, pmap, win, w, h); + + return pmap; +} + + +/** + * Deletes the reference to the given pixmap. + * + * If no other clients have a reference to the given pixmap, the server + * will destroy it. + * + * @param pmap The given pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_del(Ecore_X_Pixmap pmap) +{ + xcb_free_pixmap(_ecore_xcb_conn, pmap); +} + + +/** + * Pastes a rectangular area of the given pixmap onto the given drawable. + * @param pmap The given pixmap. + * @param dest The given drawable. + * @param gc The graphics context which governs which operation will + * be used to paste the area onto the drawable. + * @param sx The X position of the area on the pixmap. + * @param sy The Y position of the area on the pixmap. + * @param w The width of the area. + * @param h The height of the area. + * @param dx The X position at which to paste the area on @p dest. + * @param dy The Y position at which to paste the area on @p dest. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_paste(Ecore_X_Pixmap pmap, + Ecore_X_Drawable dest, + Ecore_X_GC gc, + int sx, + int sy, + int w, + int h, + int dx, + int dy) +{ + xcb_copy_area(_ecore_xcb_conn, pmap, dest, gc, sx, sy, dx, dy, w, h); +} + + +/** + * Retrieves the size of the given pixmap. + * @param pmap The given pixmap. + * @param x Pointer to an integer in which to store the X position. + * @param y Pointer to an integer in which to store the Y position. + * @param w Pointer to an integer in which to store the width. + * @param h Pointer to an integer in which to store the height. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, int *x, int *y, int *w, int *h) +{ + if (pmap) + ecore_x_drawable_geometry_get(pmap, x, y, w, h); +} + + +/** + * Retrieves the depth of the given pixmap. + * @param pmap The given pixmap. + * @return The depth of the pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI int +ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap) +{ + return ecore_x_drawable_depth_get(pmap); +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_private.h b/legacy/ecore/src/lib/ecore_x/ecore_xcb_private.h new file mode 100644 index 0000000000..bb9982ab42 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_private.h @@ -0,0 +1,310 @@ +#ifndef __ECORE_XCB_PRIVATE_H__ +#define __ECORE_XCB_PRIVATE_H__ + +#include "config.h" + +#include + +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +#ifndef XK_MISCELLANY +# define XK_MISCELLANY 1 +#endif /* XK_MISCELLANY */ + +#include +#include +#include +#include +#ifdef ECORE_XCB_CURSOR +# include +#endif /* ECORE_XCB_CURSOR */ +#ifdef ECORE_XCB_DAMAGE +# include +#endif /* ECORE_XCB_DAMAGE */ +#ifdef ECORE_XCB_DPMS +# include +#endif /* ECORE_XCB_DPMS */ +#ifdef ECORE_XCB_RANDR +# include +#endif /* ECORE_XCB_RANDR */ +#ifdef ECORE_XCB_RENDER +# include +#endif /* ECORE_XCB_RENDER */ +#ifdef ECORE_XCB_SCREENSAVER +# include +#endif /* ECORE_XCB_SCREENSAVER */ +#ifdef ECORE_XCB_SHAPE +# include +#endif /* ECORE_XCB_SHAPE */ +#ifdef ECORE_XCB_SYNC +# include +#endif /* ECORE_XCB_SYNC */ +#ifdef ECORE_XCB_XFIXES +# include +#endif /* ECORE_XCB_XFIXES */ +#ifdef ECORE_XCB_XINERAMA +# include +#endif /* ECORE_XCB_XINERAMA */ +#ifdef ECORE_XCB_XPRINT +# include +#endif /* ECORE_XCB_XPRINT */ + +#include "ecore_private.h" +#include "Ecore_X.h" + +/* FIXME: this is for simulation only */ +#include "Ecore_Txt.h" + +typedef struct _Ecore_X_Selection_Intern Ecore_X_Selection_Intern; + +struct _Ecore_X_Selection_Intern +{ + Ecore_X_Window win; + Ecore_X_Atom selection; + unsigned char *data; + int length; + Ecore_X_Time time; +}; + +typedef struct _Ecore_X_Selection_Converter Ecore_X_Selection_Converter; + +struct _Ecore_X_Selection_Converter +{ + Ecore_X_Atom target; + int (*convert)(char *target, void *data, int size, + void **data_ret, int *size_ret); + Ecore_X_Selection_Converter *next; +}; + +typedef struct _Ecore_X_Selection_Parser Ecore_X_Selection_Parser; + +struct _Ecore_X_Selection_Parser +{ + char *target; + void *(*parse)(const char *target, void *data, int size, int format); + Ecore_X_Selection_Parser *next; +}; + +typedef struct _Ecore_X_DND_Source +{ + int version; + Ecore_X_Window win, dest; + + enum { + ECORE_X_DND_SOURCE_IDLE, + ECORE_X_DND_SOURCE_DRAGGING, + ECORE_X_DND_SOURCE_DROPPED, + ECORE_X_DND_SOURCE_CONVERTING + } state; + + struct { + short x, y; + unsigned short width, height; + } rectangle; + + Ecore_X_Time time; + + Ecore_X_Atom action, accepted_action; + + int will_accept; + int suppress; + + int await_status; +} Ecore_X_DND_Source; + +typedef struct _Ecore_X_DND_Target +{ + int version; + Ecore_X_Window win, source; + + enum { + ECORE_X_DND_TARGET_IDLE, + ECORE_X_DND_TARGET_ENTERED + } state; + + struct { + int x, y; + } pos; + + Ecore_X_Time time; + + Ecore_X_Atom action, accepted_action; + + int will_accept; +} Ecore_X_DND_Target; + + +extern Ecore_X_Connection *_ecore_xcb_conn; +extern Ecore_X_Screen *_ecore_xcb_screen; +extern double _ecore_xcb_double_click_time; +extern Ecore_X_Time _ecore_xcb_event_last_time; +extern Ecore_X_Window _ecore_xcb_event_last_window; +extern int16_t _ecore_xcb_event_last_root_x; +extern int16_t _ecore_xcb_event_last_root_y; +extern int _ecore_xcb_xcursor; + +extern Ecore_X_Atom _ecore_xcb_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM]; + +extern int _ecore_window_grabs_num; +extern Ecore_X_Window *_ecore_window_grabs; +extern int (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event); +extern void *_ecore_window_grab_replay_data; + +extern Ecore_X_Window _ecore_xcb_private_window; + + +void _ecore_x_error_handler_init(void); + +void _ecore_x_event_handle_key_press (xcb_generic_event_t *event); +void _ecore_x_event_handle_key_release (xcb_generic_event_t *event); +void _ecore_x_event_handle_button_press (xcb_generic_event_t *event); +void _ecore_x_event_handle_button_release (xcb_generic_event_t *event); +void _ecore_x_event_handle_motion_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_enter_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_leave_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_focus_in (xcb_generic_event_t *event); +void _ecore_x_event_handle_focus_out (xcb_generic_event_t *event); +void _ecore_x_event_handle_keymap_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_expose (xcb_generic_event_t *event); +void _ecore_x_event_handle_graphics_expose (xcb_generic_event_t *event); +void _ecore_x_event_handle_visibility_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_create_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_destroy_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_unmap_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_map_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_map_request (xcb_generic_event_t *event); +void _ecore_x_event_handle_reparent_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_configure_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_configure_request (xcb_generic_event_t *event); +void _ecore_x_event_handle_gravity_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_resize_request (xcb_generic_event_t *event); +void _ecore_x_event_handle_circulate_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_circulate_request (xcb_generic_event_t *event); +void _ecore_x_event_handle_property_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_selection_clear (xcb_generic_event_t *event); +void _ecore_x_event_handle_selection_request (xcb_generic_event_t *event); +void _ecore_x_event_handle_selection_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_colormap_notify (xcb_generic_event_t *event); +void _ecore_x_event_handle_client_message (xcb_generic_event_t *event); +void _ecore_x_event_handle_mapping_notify (xcb_generic_event_t *event); +#ifdef ECORE_XCB_DAMAGE +void _ecore_x_event_handle_damage_notify (xcb_generic_event_t *event); +#endif /* ECORE_XCB_DAMAGE */ +#ifdef ECORE_XCB_RANDR +void _ecore_x_event_handle_randr_change (xcb_generic_event_t *event); +#endif /* ECORE_XCB_RANDR */ +#ifdef ECORE_XCB_SCREENSAVER +void _ecore_x_event_handle_screensaver_notify (xcb_generic_event_t *event); +#endif /* ECORE_XCB_SCREENSAVER */ +#ifdef ECORE_XCB_SHAPE +void _ecore_x_event_handle_shape_change (xcb_generic_event_t *event); +#endif /* ECORE_XCB_SHAPE */ +#ifdef ECORE_XCB_SYNC +void _ecore_x_event_handle_sync_counter (xcb_generic_event_t *event); +void _ecore_x_event_handle_sync_alarm (xcb_generic_event_t *event); +#endif /* ECORE_XCB_SYNC */ +#ifdef ECORE_XCB_FIXES +void _ecore_x_event_handle_fixes_selection_notify(xcb_generic_event_t *event); +#endif /* ECORE_XCB_FIXES */ + + +/* requests / replies */ +int _ecore_x_reply_init (); +void _ecore_x_reply_shutdown (); +void _ecore_xcb_cookie_cache (unsigned int cookie); +unsigned int _ecore_xcb_cookie_get (void); +void _ecore_xcb_reply_cache (void *reply); +void *_ecore_xcb_reply_get (void); + + +/* atoms */ +extern Ecore_X_Atom ECORE_X_ATOM_ATOM; +extern Ecore_X_Atom ECORE_X_ATOM_CARDINAL; +extern Ecore_X_Atom ECORE_X_ATOM_STRING; +extern Ecore_X_Atom ECORE_X_ATOM_WINDOW; +extern Ecore_X_Atom ECORE_X_ATOM_E_FRAME_SIZE; +extern Ecore_X_Atom ECORE_X_ATOM_WM_SIZE_HINTS; + +void _ecore_x_atom_init (void); +void _ecore_x_atom_init_finalize (void); + + +/* damage */ +void _ecore_x_damage_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_damage_init_finalize (void); + + +/* from dnd */ +void _ecore_x_dnd_init (void); +void _ecore_x_dnd_shutdown (void); +Ecore_X_DND_Source *_ecore_x_dnd_source_get (void); +Ecore_X_DND_Target *_ecore_x_dnd_target_get (void); +void _ecore_x_dnd_drag (int x, + int y); + + +/* dpms */ +void _ecore_x_dpms_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_dpms_init_finalize (void); + + +/* netwm */ +Ecore_X_Window_State _ecore_x_netwm_state_get(Ecore_X_Atom a); +int _ecore_x_netwm_startup_info_begin(Ecore_X_Window win, char *data); +int _ecore_x_netwm_startup_info(Ecore_X_Window win, char *data); + + +/* randr */ +void _ecore_x_randr_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_randr_init_finalize (void); + + +/* selection */ +void _ecore_x_selection_init(void); +void _ecore_x_selection_shutdown(void); +Ecore_X_Atom _ecore_x_selection_target_atom_get(const char *target); +char *_ecore_x_selection_target_get(Ecore_X_Atom target); +Ecore_X_Selection_Intern *_ecore_x_selection_get(Ecore_X_Atom selection); +int _ecore_x_selection_set(Ecore_X_Window w, const void *data, int len, Ecore_X_Atom selection); +int _ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret); +void *_ecore_x_selection_parse(const char *target, void *data, int size, int format); + + +/* screensaver */ +void _ecore_x_screensaver_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_screensaver_init_finalize (void); + + +/* shape */ +void _ecore_x_shape_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_shape_init_finalize (void); + + +/* sync */ +void _ecore_x_sync_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_sync_init_finalize (void); + + +/* xfixes */ +void _ecore_x_xfixes_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_xfixes_init_finalize (void); + + +/* xinerama */ +void _ecore_x_xinerama_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_xinerama_init_finalize (void); + + +/* xprint */ +void _ecore_x_xprint_init (const xcb_query_extension_reply_t *reply); +void _ecore_x_xprint_init_finalize (void); + +/* to categorize */ +void _ecore_x_sync_magic_send(int val, Ecore_X_Window swin); +void _ecore_x_window_grab_remove(Ecore_X_Window win); +void _ecore_x_key_grab_remove(Ecore_X_Window win); + + +#endif /* __ECORE_XCB_PRIVATE_H__*/ diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_randr.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_randr.c new file mode 100644 index 0000000000..d2e0b9d3ba --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_randr.c @@ -0,0 +1,544 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_RandR_Group X RandR Extension Functions + * + * Functions related to the X RandR extension. + */ + + +#ifdef ECORE_XCB_RANDR +static int _randr_available = 0; +static xcb_randr_query_version_cookie_t _ecore_xcb_randr_init_cookie; +#endif /* ECORE_XCB_RANDR */ + + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_randr_init and + _ecore_xcb_randr_init_finalize. The first one gets the cookies and + the second one gets the replies and set the atoms. */ + +void +_ecore_x_randr_init(const xcb_query_extension_reply_t *reply) +{ +#ifdef ECORE_XCB_RANDR + if (reply && (reply->present)) + _ecore_xcb_randr_init_cookie = xcb_randr_query_version_unchecked(_ecore_xcb_conn, 1, 2); +#endif /* ECORE_XCB_RANDR */ +} + +void +_ecore_x_randr_init_finalize(void) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_query_version_reply_t *reply; + + reply = xcb_randr_query_version_reply(_ecore_xcb_conn, + _ecore_xcb_randr_init_cookie, NULL); + + if (reply) + { + if ((reply->major_version >= 1) && + (reply->minor_version >= 1)) + _randr_available = 1; + free(reply); + } +#endif /* ECORE_XCB_RANDR */ +} + +/** + * Return whether the X server supports the RandR Extension. + * @return 1 if the X RandR Extension is available, 0 otherwise. + * + * Return 1 if the X server supports the RandR Extension version 1.1, + * 0 otherwise. + * @ingroup Ecore_X_RandR_Group + */ +EAPI int +ecore_x_randr_query(void) +{ +#ifdef ECORE_XCB_RANDR + return _randr_available; +#else + return 0; +#endif /* ECORE_XCB_RANDR */ +} + + +static Ecore_X_Window +_xcb_randr_root_to_screen(Ecore_X_Window root) +{ + xcb_screen_iterator_t iter; + + iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + for (; iter.rem; xcb_screen_next(&iter)) + { + if (iter.data->root == root) + return iter.data->root; + } + + return XCB_NONE; +} + +/** + * Select if the ScreenChangeNotify events will be sent. + * @param window The window. + * @param on 1 to enable, 0 to disable. + * @return 1 on success, 0 otherwise. + * + * If @p on value is @c 1, ScreenChangeNotify events + * will be sent when the screen configuration changes, either from + * this protocol extension, or due to detected external screen + * configuration changes. ScreenChangeNotify may also be sent when + * this request executes if the screen configuration has changed since + * the client connected, to avoid race conditions. + * @ingroup Ecore_X_RandR_Group + */ +EAPI int +ecore_x_randr_events_select(Ecore_X_Window window, + int on) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_select_input(_ecore_xcb_conn, window, + on ? XCB_RANDR_SCREEN_CHANGE_NOTIFY : 0); + return 1; +#else + return 0; +#endif /* ECORE_XCB_RANDR */ +} + +/** + * Sends the GetScreenInfo request. + * @param window Window whose properties are requested. + * @ingroup Ecore_X_RandR_Group + */ +EAPI void +ecore_x_randr_get_screen_info_prefetch(Ecore_X_Window window) +{ + xcb_randr_get_screen_info_cookie_t cookie; + + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, + _xcb_randr_root_to_screen(window)); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetScreenInfo request sent by ecore_x_randr_get_screen_info_prefetch(). + * @ingroup Ecore_X_RandR_Group + */ +EAPI void +ecore_x_randr_get_screen_info_fetch(void) +{ + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply =xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get the set of rotations and reflections. + * @param root The window (Unused). + * @return The set of rotations and reflections. + * + * Get the set of rotations and reflections supported by the screen + * associated to @p window (passed to + * ecore_x_randr_get_screen_info_prefetch()). + * + * To use this function, you must call before, and in order, + * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request, + * then ecore_x_randr_get_screen_info_fetch(), which gets the reply. + * @ingroup Ecore_X_RandR_Group + */ +EAPI Ecore_X_Randr_Rotation +ecore_x_randr_screen_rotations_get(Ecore_X_Window root __UNUSED__) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + return reply->rotations; +#else + return 0; +#endif /* ECORE_XCB_RANDR */ +} + +/** + * Get the rotation. + * @param root The window (Unused). + * @return The rotation. + * + * Get the rotation supported by the screen + * associated to @p window (passed to + * ecore_x_randr_get_screen_info_prefetch()). + * + * To use this function, you must call before, and in order, + * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request, + * then ecore_x_randr_get_screen_info_fetch(), which gets the reply. + * @ingroup Ecore_X_RandR_Group + */ +EAPI Ecore_X_Randr_Rotation +ecore_x_randr_screen_rotation_get(Ecore_X_Window root __UNUSED__) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + return reply->rotation; +#else + return 0; +#endif /* ECORE_XCB_RANDR */ +} + +/** + * Get the frame buffer sizes. + * @param root The window (Unused). + * @param num The number of sizes. + * @return The sizes. + * + * Get the list of possible frame buffer sizes (at the normal + * orientation supported by the screen associated to @p window (passed + * to ecore_x_randr_get_screen_info_prefetch()). Each size indicates + * both the linear physical size of the screen and the pixel size. + * + * To use this function, you must call before, and in order, + * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request, + * then ecore_x_randr_get_screen_info_fetch(), which gets the reply. + * @ingroup Ecore_X_RandR_Group + */ +EAPI Ecore_X_Screen_Size * +ecore_x_randr_screen_sizes_get(Ecore_X_Window root __UNUSED__, + int *num) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_reply_t *reply; + xcb_randr_screen_size_t *sizes; + Ecore_X_Screen_Size *ret; + int n; + int i; + + if (num) *num = 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return NULL; + + n = xcb_randr_get_screen_info_sizes_length(reply); + ret = calloc(n, sizeof(Ecore_X_Screen_Size)); + if (!ret) return NULL; + + if (num) *num = n; + sizes = xcb_randr_get_screen_info_sizes(reply); + for (i = 0; i < n; i++) + { + ret[i].width = sizes[i].width; + ret[i].height = sizes[i].height; + } + + return ret; +#else + if (num) *num = 0; + return NULL; +#endif /* ECORE_XCB_RANDR */ +} + +/** + * Get the current frame buffer size. + * @param root The window (Unused). + * @return The active size. + * + * Get the active frame buffer size supported by the screen associated + * to @p window (passed to + * ecore_x_randr_get_screen_info_prefetch()). + * + * To use this function, you must call before, and in order, + * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request, + * then ecore_x_randr_get_screen_info_fetch(), which gets the reply. + * @ingroup Ecore_X_RandR_Group + */ +EAPI Ecore_X_Screen_Size +ecore_x_randr_current_screen_size_get(Ecore_X_Window root __UNUSED__) +{ + Ecore_X_Screen_Size ret = { -1, -1 }; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_reply_t *reply; + xcb_randr_screen_size_t *sizes; + uint16_t size_index; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return ret; + + size_index = reply->sizeID; + sizes = xcb_randr_get_screen_info_sizes(reply); + if (size_index < reply->nSizes) + { + ret.width = sizes[size_index].mwidth; + ret.height = sizes[size_index].mheight; + } +#endif /* ECORE_XCB_RANDR */ + + return ret; +} + +/** + * Get the current refresh rate. + * @param root The window (Unused). + * @return The current refresh rate. + * + * Get the current refresh rate supported by the screen associated + * to @p window (passed to + * ecore_x_randr_get_screen_info_prefetch()). + * + * To use this function, you must call before, and in order, + * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request, + * then ecore_x_randr_get_screen_info_fetch(), which gets the reply. + * @ingroup Ecore_X_RandR_Group + */ +EAPI Ecore_X_Screen_Refresh_Rate +ecore_x_randr_current_screen_refresh_rate_get(Ecore_X_Window root __UNUSED__) +{ + Ecore_X_Screen_Refresh_Rate ret = { -1 }; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return ret; + + ret.rate = reply->rate; +#endif /* ECORE_XCB_RANDR */ + + return ret; +} + +/** + * Get the refresh rates. + * @param root The window (Unused). + * @param num The number of refresh rates. + * @return The refresh rates. + * + * Get the list of refresh rates for each size supported by the screen + * associated to @p window (passed to + * ecore_x_randr_get_screen_info_prefetch()). Each element + * of 'sizes' has a corresponding element in 'refresh'. An empty list + * indicates no known rates, or a device for which refresh is not + * relevant. + * + * To use this function, you must call before, and in order, + * ecore_x_randr_get_screen_info_prefetch(), which sends the GetScreenInfo request, + * then ecore_x_randr_get_screen_info_fetch(), which gets the reply. + * @ingroup Ecore_X_RandR_Group + */ +EAPI Ecore_X_Screen_Refresh_Rate * +ecore_x_randr_screen_refresh_rates_get(Ecore_X_Window root __UNUSED__, + int size_id __UNUSED__, + int *num) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_reply_t *reply; + Ecore_X_Screen_Refresh_Rate *ret; + Ecore_X_Screen_Refresh_Rate *tmp; + xcb_randr_refresh_rates_iterator_t iter; + uint16_t n; + + if (num) *num = 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return NULL; + + n = reply->nSizes; + ret = calloc(n, sizeof(Ecore_X_Screen_Refresh_Rate)); + if (!ret) + return NULL; + + if (num) *num = n; + + /* FIXME: maybe there's a missing function in xcb randr implementation */ + iter = xcb_randr_get_screen_info_rates_iterator(reply); + tmp = ret; + for (; iter.rem; xcb_randr_refresh_rates_next(&iter), tmp++) + { + tmp->rate = iter.data->nRates;; + } + + return ret; +#else + if (num) *num = 0; + return NULL; +#endif /* ECORE_XCB_RANDR */ +} + +/* FIXME: round trip. Should we remove it ? */ + +/** + * Set the screen rotation. + * @param root The root window. + * @param rot The rotation. + * + * Set the rotation of the screen associated to @p root. + * + * Note that that function is blocking. + * @ingroup Ecore_X_RandR_Group + */ +EAPI void +ecore_x_randr_screen_rotation_set(Ecore_X_Window root, + Ecore_X_Randr_Rotation rot) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_set_screen_config_cookie_t cookie; + xcb_randr_set_screen_config_reply_t *reply_config; + xcb_randr_get_screen_info_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return; + + cookie = xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root, + XCB_CURRENT_TIME, + reply->config_timestamp, + reply->sizeID, + rot, + 0); + reply_config = xcb_randr_set_screen_config_reply(_ecore_xcb_conn, cookie, NULL); + if (reply_config) + free(reply_config); +#endif /* ECORE_XCB_RANDR */ +} + +/* FIXME: round trip. Should we remove it ? */ + +/** + * Set the screen size. + * @param root The root window. + * @param size The size. + * + * Set the size of the screen associated to @p root. + * + * Note that that function is blocking. + * @ingroup Ecore_X_RandR_Group + */ +EAPI int +ecore_x_randr_screen_size_set(Ecore_X_Window root, + Ecore_X_Screen_Size size) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_set_screen_config_cookie_t cookie; + xcb_randr_set_screen_config_reply_t *reply_config; + xcb_randr_get_screen_info_reply_t *reply; + xcb_randr_screen_size_iterator_t iter; + int size_index = -1; + int i; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + iter = xcb_randr_get_screen_info_sizes_iterator(reply); + for (i = 0; iter.rem; xcb_randr_screen_size_next(&iter), i++) + { + if ((iter.data->width = size.width) && + (iter.data->height = size.height) && + (iter.data->mwidth = size.width) && + (iter.data->mheight = size.height)) + { + size_index = i; + break; + } + } + if (size_index == -1) return 0; + + cookie = xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root, + XCB_CURRENT_TIME, + reply->config_timestamp, + size_index, + XCB_RANDR_ROTATION_ROTATE_0, + 0); + reply_config = xcb_randr_set_screen_config_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply_config) + return 0; + + free(reply_config); + + return 1; +#else + return 0; +#endif /* ECORE_XCB_RANDR */ +} + +/* FIXME: round trip. Should we remove it ? */ + +/** + * Set the screen refresh rate. + * @param root The root window. + * @param size The size. + * @param rate The refresh rate. + * + * Set the size and the refresh rate of the screen associated to + * @p root. + * + * Note that that function is blocking. + * @ingroup Ecore_X_RandR_Group + */ +EAPI int +ecore_x_randr_screen_refresh_rate_set(Ecore_X_Window root, + Ecore_X_Screen_Size size, + Ecore_X_Screen_Refresh_Rate rate) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_set_screen_config_cookie_t cookie; + xcb_randr_set_screen_config_reply_t *reply_config; + xcb_randr_get_screen_info_reply_t *reply; + xcb_randr_screen_size_iterator_t iter; + int size_index = -1; + int i; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + iter = xcb_randr_get_screen_info_sizes_iterator(reply); + for (i = 0; iter.rem; xcb_randr_screen_size_next(&iter), i++) + { + if ((iter.data->width = size.width) && + (iter.data->height = size.height) && + (iter.data->mwidth = size.width) && + (iter.data->mheight = size.height)) + { + size_index = i; + break; + } + } + if (size_index == -1) return 0; + + cookie = xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root, + XCB_CURRENT_TIME, + reply->config_timestamp, + size_index, + XCB_RANDR_ROTATION_ROTATE_0, + rate.rate); + reply_config = xcb_randr_set_screen_config_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply_config) + return 0; + + free(reply_config); + + return 1; +#else + return 0; +#endif /* ECORE_XCB_RANDR */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_reply.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_reply.c new file mode 100644 index 0000000000..d599c7ad94 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_reply.c @@ -0,0 +1,131 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include + +#include + + +/* + * FIXME: + * - in ecore_xcb_cookie_cache, should provide better error management + * when memory allocation fails + * - Use an array instead of a list + * - Is ecore_xcb_reply_free really needed ? + * _ecore_xcb_reply_cache frees the current reply and + * _ecore_x_reply_shutdown frees the last reply to free. + * I keep it in case it is need for memory improvements, + * but its code is commented. + */ + +static Ecore_List *_ecore_xcb_cookies = NULL; +static void *_ecore_xcb_reply = NULL; + +typedef struct _Ecore_Xcb_Data Ecore_Xcb_Data; + +struct _Ecore_Xcb_Data +{ + unsigned int cookie; +}; + + +int +_ecore_x_reply_init () +{ + _ecore_xcb_cookies = ecore_list_new(); + if (!_ecore_xcb_cookies) + return 0; + + if (!ecore_list_init(_ecore_xcb_cookies)) + { + ecore_list_destroy(_ecore_xcb_cookies); + return 0; + } + + if (!ecore_list_set_free_cb(_ecore_xcb_cookies, ECORE_FREE_CB(free))) + { + ecore_list_destroy(_ecore_xcb_cookies); + return 0; + } + + return 1; +} + +void +_ecore_x_reply_shutdown () +{ + if (_ecore_xcb_reply) + free(_ecore_xcb_reply); + + if (!_ecore_xcb_cookies) + return; + + ecore_list_destroy(_ecore_xcb_cookies); +} + +void +_ecore_xcb_cookie_cache (unsigned int cookie) +{ + Ecore_Xcb_Data *data; + + if (!_ecore_xcb_cookies) + return; + + data = (Ecore_Xcb_Data *)malloc(sizeof(Ecore_Xcb_Data)); + if (!data) + return; + + data->cookie = cookie; + + if (!ecore_list_append(_ecore_xcb_cookies, data)) + { + free(data); + return; + } +} + +unsigned int +_ecore_xcb_cookie_get (void) +{ + Ecore_Xcb_Data *data; + unsigned int cookie; + + if (!_ecore_xcb_cookies) + return 0; + + data = ecore_list_remove_first(_ecore_xcb_cookies); + if (data) + { + cookie = data->cookie; + free(data); + + return cookie; + } + + return 0; +} + +void +_ecore_xcb_reply_cache (void *reply) +{ + if (_ecore_xcb_reply) + free(_ecore_xcb_reply); + _ecore_xcb_reply = reply; +} + +void * +_ecore_xcb_reply_get (void) +{ + return _ecore_xcb_reply; +} + +EAPI void +ecore_xcb_reply_free() +{ +/* if (_ecore_xcb_reply) */ +/* { */ +/* free(_ecore_xcb_reply); */ +/* _ecore_xcb_reply = NULL; */ +/* } */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_screensaver.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_screensaver.c new file mode 100644 index 0000000000..f78e57b34b --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_screensaver.c @@ -0,0 +1,372 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_ScrenSaver_Group X Shape extension + * + * These functions use the shape extension of the X server to change + * shape of given windows. + */ + + +/** + * Return whether the X server supports the ScrenSaver Extension. + * @return 1 if the X ScrenSaver Extension is available, 0 otherwise. + * + * Return 1 if the X server supports the ScrenSaver Extension version 1.0, + * 0 otherwise. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI int +ecore_x_screensaver_event_available_get(void) +{ + return 1; +} + + +/** + * Sends the QueryInfo request. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_idle_time_prefetch(void) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_screensaver_query_info_cookie_t cookie; + + cookie = xcb_screensaver_query_info_unchecked(_ecore_xcb_conn, ((xcb_screen_t *)_ecore_xcb_screen)->root); + _ecore_xcb_cookie_cache(cookie.sequence); +#endif /* ECORE_XCB_SCREENSAVER */ +} + + +/** + * Gets the reply of the QueryInfo request sent by ecore_x_get_screensaver_prefetch(). + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_idle_time_fetch(void) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_screensaver_query_info_cookie_t cookie; + xcb_screensaver_query_info_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_screensaver_query_info_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +#endif /* ECORE_XCB_SCREENSAVER */ +} + + +/** + * Get the number of seconds since the last input was received. + * @return The number of seconds. + * + * Get the number of milliseconds since the last input was received + * from the user on any of the input devices. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI int +ecore_x_screensaver_idle_time_get(void) +{ + int idle = 0; +#ifdef ECORE_XCB_SCREENSAVER + xcb_screensaver_query_info_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + + if (!reply) return 0; + + /* FIXME: check if it is ms_since_user_input or ms_until_server */ + idle = reply->ms_since_user_input / 1000; +#endif /* ECORE_XCB_SCREENSAVER */ + + return idle; +} + + +/** + * Set the parameters of the screen saver. + * @param timeout The timeout, in second. + * @param interval The interval, in seconds. + * @param blank 0 to disable screen blanking, otherwise enable it. + * @param expose Allow Expose generation event or not. + * + * Set the parameters of the screen saver. @p timeout is the timeout, + * in seconds, until the screen saver turns on. @p interval is the + * interval, in seconds, between screen saver alterations. @p blank + * specifies how to enable screen blanking. @p expose specifies the + * screen save control values. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_set(int timeout, + int interval, + int blank, + int expose) +{ + xcb_set_screen_saver(_ecore_xcb_conn, + (int16_t)timeout, + (int16_t)interval, + (uint8_t)blank, + (uint8_t)expose); +} + + +/** + * Sends the GetScreenSaver request. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_get_screensaver_prefetch(void) +{ + xcb_get_screen_saver_cookie_t cookie; + + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetScreenSaver request sent by ecore_x_get_screensaver_prefetch(). + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_get_screensaver_fetch(void) +{ + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + + +/** + * Set the timeout of the screen saver. + * @param timeout The timeout to set. + * + * Set the @p timeout, in seconds, until the screen saver turns on. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_timeout_set(double timeout) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + xcb_set_screen_saver(_ecore_xcb_conn, + (int16_t)timeout, + reply->interval, + reply->prefer_blanking, + reply->allow_exposures); +} + + +/** + * Get the timeout of the screen saver. + * @return The timeout. + * + * Get the @p timeout, in seconds, until the screen saver turns on. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI double +ecore_x_screensaver_timeout_get(void) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0.0; + + return (double)reply->timeout; +} + + +/** + * Set the interval of the screen saver. + * @param interval The interval to set. + * + * Set the @p interval, in seconds, between screen saver alterations. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_interval_set(double interval) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + xcb_set_screen_saver(_ecore_xcb_conn, + reply->timeout, + (int16_t)interval, + reply->prefer_blanking, + reply->allow_exposures); +} + + +/** + * Get the interval of the screen saver. + * @return The interval. + * + * Get the @p interval, in seconds, between screen saver alterations. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI double +ecore_x_screensaver_interval_get(void) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0.0; + + return (double)reply->interval; +} + + +/** + * Set the screen blanking. + * @param blank The blank to set. + * + * @p blank specifies how to enable screen blanking. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_blank_set(double blank) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + xcb_set_screen_saver(_ecore_xcb_conn, + reply->timeout, + reply->interval, + (uint8_t)blank, + reply->allow_exposures); +} + + +/** + * Get the screen blanking. + * @return The blanking. + * + * Get the screen blanking. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI double +ecore_x_screensaver_blank_get(void) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0.0; + + return (double)reply->prefer_blanking; +} + + +/** + * Set the screen save control values. + * @param expose The expose to set. + * + * Set the screen save control values. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_expose_set(double expose) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return; + + xcb_set_screen_saver(_ecore_xcb_conn, + reply->timeout, + reply->interval, + reply->prefer_blanking, + (uint8_t)expose); +} + + +/** + * Get the screen save control values. + * @return The expose. + * + * Get the screen save control values. + * + * To use this function, you must call before, and in order, + * ecore_x_get_screensaver_prefetch(), which sends the GetScreenSaver request, + * then ecore_x_get_screensaver_fetch(), which gets the reply. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI double +ecore_x_screensaver_expose_get(void) +{ + xcb_get_screen_saver_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0.0; + + return (double)reply->allow_exposures; +} + + +/** + * Specifies if the Screen Saver NotifyMask event should be generated. + * @param on 0 to disable the generation of the event, otherwise enable it. + * + * Specifies if the Screen Saver NotifyMask event on the screen + * associated with drawable should be generated for this client. If + * @p on is set to @c 0, the generation is disabled, otherwise, it is + * enabled. + * @ingroup Ecore_X_ScrenSaver_Group + */ +EAPI void +ecore_x_screensaver_event_listen_set(int on) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_screensaver_select_input(_ecore_xcb_conn, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + on ? XCB_SCREENSAVER_EVENT_NOTIFY_MASK : 0); +#endif /* ECORE_XCB_SCREENSAVER */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_selection.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_selection.c new file mode 100644 index 0000000000..dd4d07517d --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_selection.c @@ -0,0 +1,1062 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + +static Ecore_X_Selection_Intern selections[4]; +static Ecore_X_Selection_Converter *converters = NULL; +static Ecore_X_Selection_Parser *parsers = NULL; + +static int _ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret); +static int _ecore_x_selection_data_default_free(void *data); +static void *_ecore_x_selection_parser_files(const char *target, void *data, int size, int format); +static int _ecore_x_selection_data_files_free(void *data); +static void *_ecore_x_selection_parser_text(const char *target, void *data, int size, int format); +static int _ecore_x_selection_data_text_free(void *data); +static void *_ecore_x_selection_parser_targets(const char *target, void *data, int size, int format); +static int _ecore_x_selection_data_targets_free(void *data); + +#define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x)) + +void +_ecore_x_selection_init(void) +{ + /* Initialize global data */ + memset(selections, 0, sizeof(selections)); + + /* Initialize converters */ + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT, + _ecore_x_selection_converter_text); +#ifdef X_HAVE_UTF8_STRING + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING, + _ecore_x_selection_converter_text); +#endif + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT, + _ecore_x_selection_converter_text); + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING, + _ecore_x_selection_converter_text); + + /* Initialize parsers */ + ecore_x_selection_parser_add("text/plain", + _ecore_x_selection_parser_text); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING, + _ecore_x_selection_parser_text); + ecore_x_selection_parser_add("text/uri-list", + _ecore_x_selection_parser_files); + ecore_x_selection_parser_add("_NETSCAPE_URL", + _ecore_x_selection_parser_files); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS, + _ecore_x_selection_parser_targets); +} + +void +_ecore_x_selection_shutdown(void) +{ + Ecore_X_Selection_Converter *cnv; + Ecore_X_Selection_Parser *prs; + + /* free the selection converters */ + cnv = converters; + while (cnv) + { + Ecore_X_Selection_Converter *tmp; + + tmp = cnv->next; + free(cnv); + cnv = tmp; + } + converters = NULL; + + /* free the selection parsers */ + prs = parsers; + while (prs) + { + Ecore_X_Selection_Parser *tmp; + + tmp = prs; + prs = prs->next; + free(tmp->target); + free(tmp); + } + parsers = NULL; +} + +Ecore_X_Selection_Intern * +_ecore_x_selection_get(Ecore_X_Atom selection) +{ + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + return &selections[0]; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + return &selections[1]; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + return &selections[2]; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + return &selections[3]; + else + return NULL; +} + + +/* + * Sends the GetSelectionOwner request. + */ +void +_ecore_xcb_get_selection_owner_prefetch(Ecore_X_Atom selection) +{ + xcb_get_selection_owner_cookie_t cookie; + + cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, selection); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/* + * Gets the reply of the GetSelectionOwner request sent by _ecore_xcb_get_selection_owner_prefetch(). + */ +void +_ecore_xcb_get_selection_owner_fetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + xcb_get_selection_owner_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* + * To use this function, you must call before, and in order, + * _ecore_xcb_get_selection_owner_prefetch(), which sends the GetSelectionOwner request, + * then _ecore_xcb_get_selection_owner_fetch(), which gets the reply. + */ +int +_ecore_x_selection_set(Ecore_X_Window window, + const void *data, + int size, + Ecore_X_Atom selection) +{ + xcb_get_selection_owner_reply_t *reply; + unsigned char *buf = NULL; + int in; + + xcb_set_selection_owner(_ecore_xcb_conn, window, selection, _ecore_xcb_event_last_time); + + reply = _ecore_xcb_reply_get(); + if (!reply || (reply->owner != window)) return 0; + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + in = 0; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + in = 1; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + in = 2; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + in = 3; + else + return 0; + + if (data) + { + selections[in].win = window; + selections[in].selection = selection; + selections[in].length = size; + selections[in].time = _ecore_xcb_event_last_time; + + buf = malloc(size); + memcpy(buf, data, size); + selections[in].data = buf; + } + else + { + if (selections[in].data) + { + free(selections[in].data); + memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data)); + } + } + + return 1; +} + + +/** + * Sends the GetSelectionOwner request. + */ +EAPI void +ecore_x_selection_primary_prefetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + + cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_PRIMARY); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_primary_prefetch(). + */ +EAPI void +ecore_x_selection_primary_fetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + xcb_get_selection_owner_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Claim ownership of the PRIMARY selection and set its data. + * @param window The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_primary_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_primary_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_primary_set(Ecore_X_Window window, + const void *data, + int size) +{ + return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_PRIMARY); +} + +/** + * Release ownership of the primary selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_primary_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_primary_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_primary_clear(void) +{ + return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY); +} + + +/** + * Sends the GetSelectionOwner request. + */ +EAPI void +ecore_x_selection_secondary_prefetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + + cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_SECONDARY); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_secondary_prefetch(). + */ +EAPI void +ecore_x_selection_secondary_fetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + xcb_get_selection_owner_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + + +/** + * Claim ownership of the SECONDARY selection and set its data. + * @param window The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_secondary_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_secondary_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_secondary_set(Ecore_X_Window window, + const void *data, + int size) +{ + return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_SECONDARY); +} + +/** + * Release ownership of the secondary selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_secondary_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_secondary_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_secondary_clear(void) +{ + return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_SECONDARY); +} + + +/** + * Sends the GetSelectionOwner request. + */ +EAPI void +ecore_x_selection_xdnd_prefetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + + cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_XDND); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_xdnd_prefetch(). + */ +EAPI void +ecore_x_selection_xdnd_fetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + xcb_get_selection_owner_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Claim ownership of the XDND selection and set its data. + * @param window The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_xdnd_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_xdnd_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_xdnd_set(Ecore_X_Window window, + const void *data, + int size) +{ + return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_XDND); +} + +/** + * Release ownership of the XDND selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_xdnd_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_xdnd_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_xdnd_clear(void) +{ + return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_XDND); +} + + +/** + * Sends the GetSelectionOwner request. + */ +EAPI void +ecore_x_selection_clipboard_prefetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + + cookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, ECORE_X_ATOM_SELECTION_CLIPBOARD); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetSelectionOwner request sent by ecore_x_selection_clipboard_prefetch(). + */ +EAPI void +ecore_x_selection_clipboard_fetch(void) +{ + xcb_get_selection_owner_cookie_t cookie; + xcb_get_selection_owner_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Claim ownership of the CLIPBOARD selection and set its data. + * @param window The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + * + * Get the converted data from a previous CLIPBOARD selection + * request. The buffer must be freed when done with. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_clipboard_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_clipboard_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_clipboard_set(Ecore_X_Window window, + const void *data, + int size) +{ + return _ecore_x_selection_set(window, data, size, ECORE_X_ATOM_SELECTION_CLIPBOARD); +} + +/** + * Release ownership of the clipboard selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + * To use this function, you must call before, and in order, + * ecore_x_selection_clipboard_prefetch(), which sends the GetSelectionOwner request, + * then ecore_x_selection_clipboard_fetch(), which gets the reply. + */ +EAPI int +ecore_x_selection_clipboard_clear(void) +{ + return _ecore_x_selection_set(XCB_NONE, NULL, 0, ECORE_X_ATOM_SELECTION_CLIPBOARD); +} + + +/* FIXME: roundtrip if target is not handled in the tests */ +Ecore_X_Atom +_ecore_x_selection_target_atom_get(const char *target) +{ + Ecore_X_Atom x_target = XCB_NONE; + + if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) + x_target = ECORE_X_ATOM_TEXT; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT)) + x_target = ECORE_X_ATOM_COMPOUND_TEXT; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING)) + x_target = ECORE_X_ATOM_STRING; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING)) + x_target = ECORE_X_ATOM_UTF8_STRING; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME)) + x_target = ECORE_X_ATOM_FILE_NAME; + else + { + xcb_intern_atom_cookie_t cookie; + xcb_intern_atom_reply_t *reply; + + cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, + strlen(target), target); + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + return XCB_NONE; + x_target = reply->atom; + free(reply); + } + + return x_target; +} + + +/* FIXME: roundtrip if target is not handled in the tests */ +char * +_ecore_x_selection_target_get(Ecore_X_Atom target) +{ + if (target == ECORE_X_ATOM_FILE_NAME) + return strdup(ECORE_X_SELECTION_TARGET_FILENAME); + else if (target == ECORE_X_ATOM_STRING) + return strdup(ECORE_X_SELECTION_TARGET_STRING); + else if (target == ECORE_X_ATOM_UTF8_STRING) + return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING); + else if (target == ECORE_X_ATOM_TEXT) + return strdup(ECORE_X_SELECTION_TARGET_TEXT); + else + { + xcb_get_atom_name_cookie_t cookie; + xcb_get_atom_name_reply_t *reply; + char *name; + + cookie = xcb_get_atom_name_unchecked(_ecore_xcb_conn, target); + reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + return NULL; + name = (char *)malloc(sizeof(char) * (reply->length + 1)); + if (!name) + { + free(reply); + return NULL; + } + memcpy(name, xcb_get_atom_name_name(reply), reply->length); + name[reply->length] = '\0'; + free(reply); + return name; + } +} + +static void +_ecore_x_selection_request(Ecore_X_Window window, + Ecore_X_Atom selection, + const char *target_str) +{ + Ecore_X_Atom target, prop; + + target = _ecore_x_selection_target_atom_get(target_str); + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD; + else + return; + + xcb_convert_selection(_ecore_xcb_conn, window, + selection, target, prop, + XCB_CURRENT_TIME); +} + +EAPI void +ecore_x_selection_primary_request(Ecore_X_Window window, + const char *target) +{ + _ecore_x_selection_request(window, ECORE_X_ATOM_SELECTION_PRIMARY, target); +} + +EAPI void +ecore_x_selection_secondary_request(Ecore_X_Window window, + const char *target) +{ + _ecore_x_selection_request(window, ECORE_X_ATOM_SELECTION_SECONDARY, target); +} + +EAPI void +ecore_x_selection_xdnd_request(Ecore_X_Window window, + const char *target) +{ + Ecore_X_Atom atom; + Ecore_X_DND_Target *_target; + + _target = _ecore_x_dnd_target_get(); + atom = _ecore_x_selection_target_atom_get(target); + xcb_convert_selection(_ecore_xcb_conn, window, + ECORE_X_ATOM_SELECTION_XDND, atom, + ECORE_X_ATOM_SELECTION_PROP_XDND, + _target->time); +} + +EAPI void +ecore_x_selection_clipboard_request(Ecore_X_Window window, const char *target) +{ + _ecore_x_selection_request(window, ECORE_X_ATOM_SELECTION_CLIPBOARD, target); +} + +EAPI void +ecore_x_selection_converter_atom_add(Ecore_X_Atom target, + int (*func)(char *target, + void *data, + int size, + void **data_ret, + int *size_ret)) +{ + Ecore_X_Selection_Converter *cnv; + + cnv = converters; + if (converters) + { + while (1) + { + if (cnv->target == target) + { + cnv->convert = func; + return; + } + if (cnv->next) + cnv = cnv->next; + else + break; + } + + cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter)); + cnv = cnv->next; + } + else + { + converters = calloc(1, sizeof(Ecore_X_Selection_Converter)); + cnv = converters; + } + cnv->target = target; + cnv->convert = func; +} + +EAPI void +ecore_x_selection_converter_add(char *target, + int (*func)(char *target, + void *data, + int size, + void **data_ret, + int *size_ret)) +{ + Ecore_X_Atom x_target; + + if (!func || !target) + return; + + x_target = _ecore_x_selection_target_atom_get(target); + + ecore_x_selection_converter_atom_add(x_target, func); +} + +EAPI void +ecore_x_selection_converter_atom_del(Ecore_X_Atom target) +{ + Ecore_X_Selection_Converter *cnv, *prev_cnv; + + prev_cnv = NULL; + cnv = converters; + + while (cnv) + { + if (cnv->target == target) + { + if (prev_cnv) + prev_cnv->next = cnv->next; + else + converters = cnv->next; /* This was the first converter */ + free(cnv); + + return; + } + prev_cnv = cnv; + cnv = cnv->next; + } +} + +EAPI void +ecore_x_selection_converter_del(char *target) +{ + Ecore_X_Atom x_target; + + if (!target) + return; + + x_target = _ecore_x_selection_target_atom_get(target); + ecore_x_selection_converter_atom_del(x_target); +} + +EAPI int +ecore_x_selection_notify_send(Ecore_X_Window requestor, + Ecore_X_Atom selection, + Ecore_X_Atom target, + Ecore_X_Atom property, + Ecore_X_Time time) +{ + xcb_selection_notify_event_t ev; + + ev.time = time; + ev.requestor = requestor; + ev.selection = selection; + ev.target = target; + ev.property = property; + /* send_event is bit 7 (0x80) of response_type */ + ev.response_type = 0x80; + + xcb_send_event(_ecore_xcb_conn, 0, + requestor, 0, (const char *)&ev); + return 1; +} + +/* Locate and run conversion callback for specified selection target */ +EAPI int +ecore_x_selection_convert(Ecore_X_Atom selection, + Ecore_X_Atom target, + void **data_ret) +{ + Ecore_X_Selection_Intern *sel; + Ecore_X_Selection_Converter *cnv; + void *data; + char *tgt_str; + int size; + + sel = _ecore_x_selection_get(selection); + tgt_str = _ecore_x_selection_target_get(target); + + for (cnv = converters; cnv; cnv = cnv->next) + { + if (cnv->target == target) + { + int r; + r = cnv->convert(tgt_str, sel->data, sel->length, &data, &size); + free(tgt_str); + if (r) + { + *data_ret = data; + return r; + } + else + return 0; + } + } + + /* Default, just return the data */ + *data_ret = malloc(sel->length); + memcpy(*data_ret, sel->data, sel->length); + free(tgt_str); + return 1; +} + +/* TODO: We need to work out a mechanism for automatic conversion to any requested + * locale using Ecore_Txt functions */ +/* Converter for standard non-utf8 text targets */ +static int +_ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret) +{ + + /* FIXME: to do... */ + +/* XTextProperty text_prop; */ +/* char *mystr; */ +/* XICCEncodingStyle style; */ + +/* if (!data || !size) */ +/* return 0; */ + +/* if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) */ +/* style = XTextStyle; */ +/* else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT)) */ +/* style = XCompoundTextStyle; */ +/* else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING)) */ +/* style = XStringStyle; */ +/* #ifdef X_HAVE_UTF8_STRING */ +/* else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING)) */ +/* style = XUTF8StringStyle; */ +/* #endif */ +/* else */ +/* return 0; */ + +/* if (!(mystr = strdup(data))) */ +/* return 0; */ + +/* #ifdef X_HAVE_UTF8_STRING */ +/* if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success) */ +/* { */ +/* int bufsize = strlen((char *)text_prop.value) + 1; */ +/* *data_ret = malloc(bufsize); */ +/* memcpy(*data_ret, text_prop.value, bufsize); */ +/* *size_ret = bufsize; */ +/* XFree(text_prop.value); */ +/* free(mystr); */ +/* return 1; */ +/* } */ +/* #else */ +/* if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success) */ +/* { */ +/* int bufsize = strlen(text_prop.value) + 1; */ +/* *data_ret = malloc(bufsize); */ +/* memcpy(*data_ret, text_prop.value, bufsize); */ +/* *size_ret = bufsize; */ +/* XFree(text_prop.value); */ +/* free(mystr); */ +/* return 1; */ +/* } */ +/* #endif */ +/* else */ +/* { */ +/* free(mystr); */ +/* return 0; */ +/* } */ + + return 0; +} + +EAPI void +ecore_x_selection_parser_add(const char *target, + void *(*func)(const char *target, + void *data, + int size, + int format)) +{ + Ecore_X_Selection_Parser *prs; + + if (!target) + return; + + prs = parsers; + if (parsers) + { + while (prs->next) + { + if (!strcmp(prs->target, target)) + { + prs->parse = func; + return; + } + prs = prs->next; + } + + prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser)); + prs = prs->next; + } + else + { + parsers = calloc(1, sizeof(Ecore_X_Selection_Parser)); + prs = parsers; + } + prs->target = strdup(target); + prs->parse = func; +} + +EAPI void +ecore_x_selection_parser_del(const char *target) +{ + Ecore_X_Selection_Parser *prs, *prev_prs; + + if (!target) + return; + + prev_prs = NULL; + prs = parsers; + + while (prs) + { + if (!strcmp(prs->target, target)) + { + if (prev_prs) + prev_prs->next = prs->next; + else + parsers = prs->next; /* This was the first parser */ + free(prs->target); + free(prs); + + return; + } + prev_prs = prs; + prs = prs->next; + } +} + +/* Locate and run conversion callback for specified selection target */ +void * +_ecore_x_selection_parse(const char *target, void *data, int size, int format) +{ + Ecore_X_Selection_Parser *prs; + Ecore_X_Selection_Data *sel; + + for (prs = parsers; prs; prs = prs->next) + { + if (!strcmp(prs->target, target)) + { + sel = prs->parse(target, data, size, format); + return sel; + } + } + + /* Default, just return the data */ + sel = calloc(1, sizeof(Ecore_X_Selection_Data)); + sel->free = _ecore_x_selection_data_default_free; + sel->length = size; + sel->format = format; + sel->data = data; + return sel; +} + +static int +_ecore_x_selection_data_default_free(void *data) +{ + Ecore_X_Selection_Data *sel; + + sel = data; + free(sel->data); + free(sel); + return 1; +} + +static void * +_ecore_x_selection_parser_files(const char *target, void *_data, int size, int format __UNUSED__) +{ + Ecore_X_Selection_Data_Files *sel; + char *data = _data; + int i, is; + char *tmp; + + if (strcmp(target, "text/uri-list") && + strcmp(target, "_NETSCAPE_URL")) + return NULL; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files)); + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free; + + if (data[size - 1]) + { + /* Isn't nul terminated */ + size++; + data = realloc(data, size); + data[size - 1] = 0; + } + + tmp = malloc(size); + i = 0; + is = 0; + while ((is < size) && (data[is])) + { + if ((i == 0) && (data[is] == '#')) + { + for (; ((data[is]) && (data[is] != '\n')); is++); + } + else + { + if ((data[is] != '\r') && + (data[is] != '\n')) + { + tmp[i++] = data[is++]; + } + else + { + while ((data[is] == '\r') || (data[is] == '\n')) is++; + tmp[i] = 0; + sel->num_files++; + sel->files = realloc(sel->files, sel->num_files * sizeof(char *)); + sel->files[sel->num_files - 1] = strdup(tmp); + tmp[0] = 0; + i = 0; + } + } + } + if (i > 0) + { + tmp[i] = 0; + sel->num_files++; + sel->files = realloc(sel->files, sel->num_files * sizeof(char *)); + sel->files[sel->num_files - 1] = strdup(tmp); + } + free(tmp); + free(data); + + ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES; + ECORE_X_SELECTION_DATA(sel)->length = sel->num_files; + + return ECORE_X_SELECTION_DATA(sel); +} + +static int +_ecore_x_selection_data_files_free(void *data) +{ + Ecore_X_Selection_Data_Files *sel; + int i; + + sel = data; + if (sel->files) + { + for (i = 0; i < sel->num_files; i++) + free(sel->files[i]); + free(sel->files); + } + free(sel); + return 0; +} + +static void * +_ecore_x_selection_parser_text(const char *target __UNUSED__, + void *_data, + int size, + int format __UNUSED__) +{ + Ecore_X_Selection_Data_Text *sel; + char *data = _data; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text)); + + if (data[size - 1]) + { + /* Isn't nul terminated */ + size++; + data = realloc(data, size); + data[size - 1] = 0; + } + + sel->text = (char *)data; + ECORE_X_SELECTION_DATA(sel)->length = size; + ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT; + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free; + return sel; +} + +static int +_ecore_x_selection_data_text_free(void *data) +{ + Ecore_X_Selection_Data_Text *sel; + + sel = data; + free(sel->text); + free(sel); + return 1; +} + +static void * +_ecore_x_selection_parser_targets(const char *target __UNUSED__, + void *data, + int size, + int format __UNUSED__) +{ + Ecore_X_Selection_Data_Targets *sel; + uint32_t *targets; + xcb_get_atom_name_cookie_t *cookies; + int i; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets)); + targets = (uint32_t *)data; + + sel->num_targets = size - 2; + sel->targets = malloc((size - 2) * sizeof(char *)); + cookies = (xcb_get_atom_name_cookie_t *)malloc ((size - 2) * sizeof (xcb_get_atom_name_cookie_t)); + for (i = 0; i < size - 2; i++) + cookies[i] = xcb_get_atom_name_unchecked(_ecore_xcb_conn, targets[i + 2]); + + /* FIXME: do we let the declaration of reply inside the loop ? */ + for (i = 0; i < size - 2; i++) + { + xcb_get_atom_name_reply_t *reply; + char *name; + int length; + + reply =xcb_get_atom_name_reply(_ecore_xcb_conn, cookies[i], NULL); + length = xcb_get_atom_name_name_length(reply); + name = (char *)malloc (length + 1); + memcpy(name, xcb_get_atom_name_name(reply), length); + name[length] = '\0'; + sel->targets[i - 2] = name; + } + free(cookies); + free(data); + + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free; + ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS; + ECORE_X_SELECTION_DATA(sel)->length = size; + return sel; +} + +static int +_ecore_x_selection_data_targets_free(void *data) +{ + Ecore_X_Selection_Data_Targets *sel; + int i; + + sel = data; + + if (sel->targets) + { + for (i = 0; i < sel->num_targets; i++) + free(sel->targets[i]); + free(sel->targets); + } + free(sel); + return 1; +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_shape.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_shape.c new file mode 100644 index 0000000000..a85b2b7059 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_shape.c @@ -0,0 +1,290 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_Shape_Group X Shape extension + * + * Functions that use the shape extension of the X server to change shape of given windows. + */ + + +#ifdef ECORE_XCB_SHAPE +static int _shape_available = 0; +static xcb_shape_query_version_cookie_t _ecore_xcb_shape_init_cookie; +#endif /* ECORE_XCB_SHAPE */ + + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_shape_init and + _ecore_xcb_shape_init_finalize. The first one gets the cookies and + the second one gets the replies. */ + +void +_ecore_x_shape_init(const xcb_query_extension_reply_t *reply) +{ +#ifdef ECORE_XCB_SHAPE + if (reply && (reply->present)) + _ecore_xcb_shape_init_cookie = xcb_shape_query_version_unchecked(_ecore_xcb_conn); +#endif /* ECORE_XCB_SHAPE */ +} + +void +_ecore_x_shape_init_finalize(void) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_query_version_reply_t *reply; + + reply = xcb_shape_query_version_reply(_ecore_xcb_conn, + _ecore_xcb_shape_init_cookie, + NULL); + if (reply) + { + _shape_available = 1; + free(reply); + } +#endif /* ECORE_XCB_SHAPE */ +} + + +/** + * Sets the shape of the given window to the given pixmap. + * @param dest_win The given window. + * @param source_mask A 2-bit depth pixmap that provides the new shape of the window. + * + * Sets the shape of the window @p dest_win to the pixmap @p source_mask. + * @ingroup Ecore_X_Shape_Group + */ +EAPI void +ecore_x_window_shape_mask_set(Ecore_X_Window dest_win, + Ecore_X_Pixmap source_mask) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_mask(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, source_mask); +#endif /* ECORE_XCB_SHAPE */ +} + +EAPI void +ecore_x_window_shape_window_set(Ecore_X_Window dest_win, + Ecore_X_Window shape_win) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, shape_win); +#endif /* ECORE_XCB_SHAPE */ +} + +EAPI void +ecore_x_window_shape_window_set_xy(Ecore_X_Window dest_win, + Ecore_X_Window shape_win, + int x, + int y) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, x, y, shape_win); +#endif /* ECORE_XCB_SHAPE */ +} + + +/** + * Sets the shape of the given window to a rectangle. + * @param dest_win The given window. + * @param x The X coordinate of the top left corner of the rectangle. + * @param y The Y coordinate of the top left corner of the rectangle. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + * + * Sets the shape of the window @p dest_win to a rectangle defined by + * @p x, @p y, @p width and @p height. + * @ingroup Ecore_X_Shape_Group + */ +EAPI void +ecore_x_window_shape_rectangle_set(Ecore_X_Window dest_win, + int x, + int y, + int width, + int height) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 1, &rect); +#endif /* ECORE_XCB_SHAPE */ +} + +EAPI void +ecore_x_window_shape_rectangles_set(Ecore_X_Window dest_win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_SHAPE + if (num > 0) + xcb_shape_rectangles(_ecore_xcb_conn, + XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, + 0, dest_win, 0, 0, num, (xcb_rectangle_t *)rects); + else + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 0, NULL); +#endif /* ECORE_XCB_SHAPE */ +} + +EAPI void +ecore_x_window_shape_window_add(Ecore_X_Window dest_win, + Ecore_X_Window shape_win) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, 0, 0, shape_win); +#endif /* ECORE_XCB_SHAPE */ +} + +EAPI void +ecore_x_window_shape_window_add_xy(Ecore_X_Window dest_win, + Ecore_X_Window shape_win, + int x, + int y) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, dest_win, x, y, shape_win); +#endif /* ECORE_XCB_SHAPE */ +} + +EAPI void +ecore_x_window_shape_rectangle_add(Ecore_X_Window dest_win, + int x, + int y, + int width, + int height) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 1, &rect); +#endif /* ECORE_XCB_SHAPE */ +} + +EAPI void +ecore_x_window_shape_rectangle_clip(Ecore_X_Window dest_win, + int x, + int y, + int width, + int height) +{ + xcb_rectangle_t rect; + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + xcb_shape_rectangles(_ecore_xcb_conn, + XCB_SHAPE_SO_INTERSECT, XCB_SHAPE_SK_BOUNDING, + 0, dest_win, 0, 0, 1, &rect); +} + +EAPI void +ecore_x_window_shape_rectangles_add(Ecore_X_Window dest_win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_SHAPE + if (num > 0) + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, num, (const xcb_rectangle_t *)rects); + else + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING, 0, dest_win, 0, 0, 0, NULL); +#endif /* ECORE_XCB_SHAPE */ +} + + +/** + * Sends the ShapeGetRectangles request. + * @param window Requested window. + * @ingroup Ecore_X_Shape_Group + */ +EAPI void +ecore_x_window_shape_rectangles_get_prefetch(Ecore_X_Window window) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_get_rectangles_cookie_t cookie; + + cookie = xcb_shape_get_rectangles_unchecked(_ecore_xcb_conn, window, XCB_SHAPE_SK_BOUNDING); + _ecore_xcb_cookie_cache(cookie.sequence); +#endif /* ECORE_XCB_SHAPE */ +} + + +/** + * Gets the reply of the ShapeGetRectangles request sent by ecore_x_window_shape_rectangles_get_prefetch(). + * @ingroup Ecore_X_Shape_Group + */ +EAPI void +ecore_x_window_shape_rectangles_get_fetch(void) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_get_rectangles_cookie_t cookie; + xcb_shape_get_rectangles_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_shape_get_rectangles_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +#endif /* ECORE_XCB_SHAPE */ +} + + +/** + * To document. + * @param window Unused. + * @param num_ret To document. + * @return To document. + * + * To use this function, you must call before, and in order, + * ecore_x_window_shape_rectangles_get_prefetch(), which sends the ShapeGetRectangles request, + * then ecore_x_window_shape_rectangles_get_fetch(), which gets the reply. + * @ingroup Ecore_X_Shape_Group + */ +EAPI Ecore_X_Rectangle * +ecore_x_window_shape_rectangles_get(Ecore_X_Window window __UNUSED__, + int *num_ret) +{ + Ecore_X_Rectangle *rects = NULL; + uint32_t num = 0; +#ifdef ECORE_XCB_SHAPE + xcb_shape_get_rectangles_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + { + if (num_ret) *num_ret = 0; + return NULL; + } + + num = reply->rectangles_len; + rects = malloc(sizeof(Ecore_X_Rectangle) * num); + if (rects) + memcpy (rects, + xcb_shape_get_rectangles_rectangles(reply), + num * sizeof (Ecore_X_Rectangle)); + else + num = 0; +#endif /* ECORE_XCB_SHAPE */ + + if (num_ret) *num_ret = num; + + return rects; +} + +EAPI void +ecore_x_window_shape_events_select(Ecore_X_Window dest_win, + int on) +{ +#ifdef ECORE_XCB_SHAPE + xcb_shape_select_input(_ecore_xcb_conn, dest_win, on ? 1 : 0); +#endif /* ECORE_XCB_SHAPE */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_sync.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_sync.c new file mode 100644 index 0000000000..05fbfb6b6c --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_sync.c @@ -0,0 +1,135 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_Sync_Group X Sync Extension Functions + * + * Functions related to the X Sync extension. + */ + + +#ifdef ECORE_XCB_SYNC +static int _sync_available = 0; +static xcb_sync_initialize_cookie_t _ecore_xcb_sync_init_cookie; +#endif /* ECORE_XCB_SYNC */ + + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_sync_init and + _ecore_xcb_sync_init_finalize. The first one gets the cookies and + the second one gets the replies and set the atoms. */ + +void +_ecore_x_sync_init(const xcb_query_extension_reply_t *reply) +{ +#ifdef ECORE_XCB_SYNC + if (reply && (reply->present)) + _ecore_xcb_sync_init_cookie = xcb_sync_initialize_unchecked(_ecore_xcb_conn); +#endif /* ECORE_XCB_SYNC */ +} + +void +_ecore_x_sync_init_finalize(void) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_initialize_reply_t *reply; + + reply = xcb_sync_initialize_reply(_ecore_xcb_conn, + _ecore_xcb_sync_init_cookie, NULL); + + if (reply) + { + if (reply->major_version >= 3) + _sync_available = 1; + free(reply); + } +#endif /* ECORE_XCB_SYNC */ +} + + +/** + * Return whether the X server supports the Sync Extension. + * @return 1 if the X Sync Extension is available, 0 otherwise. + * + * Return 1 if the X server supports the Sync Extension version 3.0, + * 0 otherwise. + * @ingroup Ecore_X_Sync_Group + */ +EAPI int +ecore_x_sync_query(void) +{ +#ifdef ECORE_XCB_SYNC + return _sync_available; +#else + return 0; +#endif /* ECORE_XCB_SYNC */ +} + + +/** + * Create a new alarm. + * @param counter A counter. + * @return A newly created alarm. + * + * Create a new alarm. + * @ingroup Ecore_X_Sync_Group + */ +EAPI Ecore_X_Sync_Alarm +ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter) +{ +#ifdef ECORE_XCB_SYNC + uint32_t value_list[6]; + xcb_sync_int64_t init; + Ecore_X_Sync_Alarm alarm; + uint32_t value_mask; + + init.lo = 0; + init.hi = 0; + xcb_sync_set_counter(_ecore_xcb_conn, counter, init); + + value_mask = + XCB_SYNC_CA_COUNTER | XCB_SYNC_CA_VALUE_TYPE | + XCB_SYNC_CA_VALUE | XCB_SYNC_CA_TEST_TYPE | + XCB_SYNC_CA_DELTA | XCB_SYNC_CA_EVENTS; + value_list[0] = counter; + value_list[1] = XCB_SYNC_VALUETYPE_ABSOLUTE; + value_list[2] = 1; + value_list[3] = XCB_SYNC_TESTTYPE_POSITIVE_COMPARISON; + value_list[4] = 1; + value_list[5] = 1; + alarm = xcb_generate_id(_ecore_xcb_conn); + xcb_sync_create_alarm(_ecore_xcb_conn, + alarm, + value_mask, + (const uint32_t *)value_list); + + ecore_x_sync(); + return alarm; +#else + return 0; +#endif /* ECORE_XCB_SYNC */ +} + + +/** + * Delete an alarm. + * @param alarm The alarm to delete. + * @return 1 on success, 0 otherwise. + * + * Delete the @p alarm. Returns 1 on success, 0 otherwise. + * @ingroup Ecore_X_Sync_Group + */ +EAPI int +ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_destroy_alarm(_ecore_xcb_conn, alarm); + return 1; +#else + return 0; +#endif /* ECORE_XCB_SYNC */ +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_window.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_window.c new file mode 100644 index 0000000000..8b47a5a4c6 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_window.c @@ -0,0 +1,2028 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "Ecore.h" +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + + +static int ignore_num = 0; +static Ecore_X_Window *ignore_list = NULL; + +static Ecore_X_Window _ecore_x_window_at_xy_get(Ecore_X_Window base, + int16_t base_x, + int16_t base_y, + int16_t x, + int16_t y, + Ecore_X_Window *skip, + int skip_num); + +#ifdef ECORE_XCB_RENDER +static Ecore_X_Window _ecore_x_window_argb_internal_new(Ecore_X_Window parent, + int16_t x, + int16_t y, + uint16_t w, + uint16_t h, + uint8_t override_redirect, + uint8_t save_under); +#endif /* ECORE_XCB_RENDER */ + + +/** + * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions + * + * Functions that can be used to create an X window. + */ + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_new(Ecore_X_Window parent, + int x, + int y, + int width, + int height) +{ + uint32_t value_list[9]; + Ecore_X_Window window; + xcb_visualid_t vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT }; + uint32_t value_mask; + + if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + value_mask = + XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | + XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT | + XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE; + + value_list[0] = XCB_NONE; + value_list[1] = 0; + value_list[2] = XCB_GRAVITY_NORTH_WEST; + value_list[3] = XCB_GRAVITY_NORTH_WEST; + value_list[4] = XCB_BACKING_STORE_NOT_USEFUL; + value_list[5] = 0; + value_list[6] = 0; + value_list[7] = + XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE; + value_list[8] = XCB_EVENT_MASK_NO_EVENT; + + window = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, + XCB_WINDOW_CLASS_COPY_FROM_PARENT, + window, parent, x, y, width, height, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + vis, + value_mask, + value_list); + + if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) ecore_x_window_defaults_set(window); + return window; +} + +/** + * Creates a window with the override redirect attribute set to @c True. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_override_new(Ecore_X_Window parent, + int x, + int y, + int width, + int height) +{ + uint32_t value_list[9]; + Ecore_X_Window window; + xcb_visualid_t vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT }; + uint32_t value_mask; + + if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + value_mask = + XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | + XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT | + XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE; + + value_list[0] = XCB_NONE; + value_list[1] = 0; + value_list[2] = XCB_GRAVITY_NORTH_WEST; + value_list[3] = XCB_GRAVITY_NORTH_WEST; + value_list[4] = XCB_BACKING_STORE_NOT_USEFUL; + value_list[5] = 1; + value_list[6] = 0; + value_list[7] = + XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE; + value_list[8] = XCB_EVENT_MASK_NO_EVENT; + + window = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, + XCB_WINDOW_CLASS_COPY_FROM_PARENT, + window, parent, x, y, width, height, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + vis, + value_mask, + value_list); + return window; +} + +/** + * Creates a new input window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_input_new(Ecore_X_Window parent, + int x, + int y, + int width, + int height) +{ + uint32_t value_list[3]; + Ecore_X_Window window; + xcb_visualid_t vis = { XCB_WINDOW_CLASS_COPY_FROM_PARENT }; + uint32_t value_mask; + + if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + value_mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE; + + value_list[0] = 1; + value_list[1] = + XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE; + value_list[2] = XCB_EVENT_MASK_NO_EVENT; + + window = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, + XCB_WINDOW_CLASS_COPY_FROM_PARENT, + window, parent, x, y, width, height, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + vis, + value_mask, + value_list); + + if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) + { + } + + return window; +} + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param width Width. + * @param height Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_manager_argb_new(Ecore_X_Window parent, + int x, + int y, + int width, + int height) +{ + Ecore_X_Window window = 0; + +#ifdef ECORE_XCB_RENDER + window = _ecore_x_window_argb_internal_new(parent, + x, y, width, height, + 1, 0); +#endif /* ECORE_XCB_RENDER */ + + return window; +} + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param width Width. + * @param height Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_argb_new(Ecore_X_Window parent, + int x, + int y, + int width, + int height) +{ + Ecore_X_Window window = 0; + +#ifdef ECORE_XCB_RENDER + window = _ecore_x_window_argb_internal_new(parent, + x, y, width, height, + 0, 0); +#endif /* ECORE_XCB_RENDER */ + + return window; +} + +/** + * Creates a window with the override redirect attribute set to @c True. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param width Width. + * @param height Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_override_argb_new(Ecore_X_Window parent, + int x, + int y, + int width, + int height) +{ + Ecore_X_Window window = 0; + +#ifdef ECORE_XCB_RENDER + window = _ecore_x_window_argb_internal_new(parent, + x, y, width, height, + 1, 0); +#endif /* ECORE_XCB_RENDER */ + + return window; +} + +/** + * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions + * + * Functions to destroy X windows. + */ + +/** + * Deletes the given window. + * @param window The given window. + * @ingroup Ecore_X_Window_Destroy_Group + */ +EAPI void +ecore_x_window_del(Ecore_X_Window window) +{ + /* sorry sir, deleting the root window doesn't sound like + * a smart idea. + */ + if (window) + xcb_destroy_window(_ecore_xcb_conn, window); +} + +/** + * Sends a delete request to the given window. + * @param window The given window. + * @ingroup Ecore_X_Window_Destroy_Group + */ +EAPI void +ecore_x_window_delete_request_send(Ecore_X_Window window) +{ + xcb_client_message_event_t ev; + + /* sorry sir, deleting the root window doesn't sound like + * a smart idea. + */ + if (window == 0) + return; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.sequence = 0; + ev.window = window; + ev.type = ECORE_X_ATOM_WM_PROTOCOLS; + ev.data.data32[0] = ECORE_X_ATOM_WM_DELETE_WINDOW; + ev.data.data32[1] = XCB_CURRENT_TIME; + + xcb_send_event(_ecore_xcb_conn, 0, window, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +} + +/** + * @defgroup Ecore_X_Window_Configure_Group X Window Configure Functions + * + * Functions to configure X windows. + */ + + +/** + * Configures the given window with the given mask. + * @param window The given window. + * @param mask The given mask. + * @param x The X coordinate of the window. + * @param y The Y coordinate of the window. + * @param width The width of the window. + * @param height The height of the window. + * @param border_width The border width of the window. + * @param sibling The sibling window of the window. + * @param stack_mode The stack mode of the window. + * @ingroup Ecore_X_Window_Configure_Group + */ +EAPI void +ecore_x_window_configure(Ecore_X_Window window, + Ecore_X_Window_Configure_Mask mask, + int x, + int y, + int width, + int height, + int border_width, + Ecore_X_Window sibling, + int stack_mode) +{ + uint32_t *value_list; + uint32_t value_mask; + int length = 0; + + if (!window) + return; + + value_mask = mask; + for ( ; value_mask; value_mask >>= 1) + if (value_mask & 1) + length++; + value_list = (uint32_t *)malloc(sizeof(uint32_t) * length); + if (!value_list) + return; + + value_mask = mask; + for ( ; value_mask; value_mask >>= 1, value_list++) + if (value_mask & 1) + { + switch (value_mask) { + case XCB_CONFIG_WINDOW_X: + *value_list = x; + break; + case XCB_CONFIG_WINDOW_Y: + *value_list = y; + break; + case XCB_CONFIG_WINDOW_WIDTH: + *value_list = width; + break; + case XCB_CONFIG_WINDOW_HEIGHT: + *value_list = height; + break; + case XCB_CONFIG_WINDOW_BORDER_WIDTH: + *value_list = border_width; + break; + case XCB_CONFIG_WINDOW_SIBLING: + *value_list = sibling; + break; + case XCB_CONFIG_WINDOW_STACK_MODE: + *value_list = stack_mode; + break; + } + } + + xcb_configure_window(_ecore_xcb_conn, window, mask, value_list); + free(value_list); +} + +/** + * Moves a window to the position @p x, @p y. + * + * The position is relative to the upper left hand corner of the + * parent window. + * + * @param window The window to move. + * @param x X position. + * @param y Y position. + * @ingroup Ecore_X_Window_Configure_Group + */ +EAPI void +ecore_x_window_move(Ecore_X_Window window, + int x, + int y) +{ + uint32_t value_list[2]; + uint32_t value_mask; + + if (!window) + return; + + value_mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y; + + value_list[0] = x; + value_list[1] = y; + + xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list); +} + +/** + * Resizes a window. + * @param window The window to resize. + * @param width New width of the window. + * @param height New height of the window. + * @ingroup Ecore_X_Window_Configure_Group + */ +EAPI void +ecore_x_window_resize(Ecore_X_Window window, + int width, + int height) +{ + uint32_t value_list[2]; + uint32_t value_mask; + + if (!window) + return; + + if (width < 1) width = 1; + if (height < 1) height = 1; + + value_mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; + + value_list[0] = width; + value_list[1] = height; + + xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list); +} + +/** + * Moves and resizes a window. + * @param window The window to move and resize. + * @param x New X position of the window. + * @param y New Y position of the window. + * @param width New width of the window. + * @param height New height of the window. + * @ingroup Ecore_X_Window_Configure_Group + */ +EAPI void +ecore_x_window_move_resize(Ecore_X_Window window, + int x, + int y, + int width, + int height) +{ + uint32_t value_list[4]; + uint32_t value_mask; + + if (!window) + return; + + if (width < 1) width = 1; + if (height < 1) height = 1; + + value_mask = + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; + + value_list[0] = x; + value_list[1] = y; + value_list[2] = width; + value_list[3] = height; + + xcb_configure_window(_ecore_xcb_conn, window, value_mask, value_list); +} + +/** + * Sets the width of the border of the given window. + * @param window The given window. + * @param border_width The new border width. + * @ingroup Ecore_X_Window_Configure_Group + */ +EAPI void +ecore_x_window_border_width_set(Ecore_X_Window window, + int border_width) +{ + uint32_t value_list; + + /* doesn't make sense to call this on a root window */ + if (!window) + return; + + value_list = border_width; + + xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_BORDER_WIDTH, &value_list); +} + +/** + * Raises the given window. + * @param window The window to raise. + * @ingroup Ecore_X_Window_Configure_Group + */ +EAPI void +ecore_x_window_raise(Ecore_X_Window window) +{ + uint32_t value_list; + + if (!window) + return; + + value_list = XCB_STACK_MODE_ABOVE; + + xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_STACK_MODE, &value_list); +} + +/** + * Lowers the given window. + * @param window The window to lower. + * @ingroup Ecore_X_Window_Configure_Group + */ +EAPI void +ecore_x_window_lower(Ecore_X_Window window) +{ + uint32_t value_list; + + if (!window) + return; + + value_list = XCB_STACK_MODE_BELOW; + + xcb_configure_window(_ecore_xcb_conn, window, XCB_CONFIG_WINDOW_STACK_MODE, &value_list); +} + +/** + * @defgroup Evas_X_Window_Change_Properties_Group X Window Change Property Functions + * + * Functions that change window properties. + */ + +/** + * Sets the default properties for the given window. + * + * The default properties set for the window are @c WM_CLIENT_MACHINE and + * @c _NET_WM_PID. + * + * @param window The given window. + * @ingroup Ecore_X_Window_Change_Property_Group + */ +EAPI void +ecore_x_window_defaults_set(Ecore_X_Window window) +{ + char buf[MAXHOSTNAMELEN]; + pid_t pid; + int argc; + char **argv; + + /* + * Set WM_CLIENT_MACHINE. + */ + gethostname(buf, MAXHOSTNAMELEN); + buf[MAXHOSTNAMELEN - 1] = '\0'; + /* The ecore function uses UTF8 which Xlib may not like (especially + * with older clients) */ + /* ecore_xcb_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE, + (char *)buf); */ + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + ECORE_X_ATOM_WM_CLIENT_MACHINE, + ECORE_X_ATOM_STRING, + 8, strlen(buf), buf); + + /* + * Set _NET_WM_PID + */ + pid = getpid(); + ecore_x_netwm_pid_set(window, pid); + + ecore_x_netwm_window_type_set(window, ECORE_X_WINDOW_TYPE_NORMAL); + + ecore_app_args_get(&argc, &argv); + ecore_x_icccm_command_set(window, argc, argv); +} + +/** + * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions + * + * Functions to change the visibility of X windows. + */ + +/** + * Shows a window. + * + * Synonymous to "mapping" a window in X Window System terminology. + * + * @param window The window to show. + * @ingroup Ecore_X_Window_Visibility_Group + */ +EAPI void +ecore_x_window_show(Ecore_X_Window window) +{ + xcb_map_window(_ecore_xcb_conn, window); +} + +/** + * Hides a window. + * + * Synonymous to "unmapping" a window in X Window System terminology. + * + * @param window The window to hide. + * @ingroup Ecore_X_Window_Visibility_Group + */ +EAPI void +ecore_x_window_hide(Ecore_X_Window window) +{ + xcb_unmap_notify_event_t ev; + Ecore_X_Window root; + + /* ICCCM: SEND unmap event... */ + root = window; + /* FIXME: is it correct ? */ + if (xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem == 1) + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + else + { + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *rep; + Ecore_X_Drawable draw; + + /* FIXME: can we avoid round trips, here ? */ + draw = window; + cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, draw); + rep = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); + if (!rep) + return; + root = rep->root; + free(rep); + } + ev.response_type = XCB_UNMAP_NOTIFY; + ev.pad0 = 0; + ev.sequence = 0; + ev.event = root; + ev.window = window; + ev.from_configure = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&ev); + xcb_unmap_window(_ecore_xcb_conn, window); +} + +/** + * @defgroup Ecore_X_Window_Input_Focus_Group X Window Input Focus Functions + * + * Functions that manage the focus of an X Window. + */ + +/** + * Sets the focus to the window @p window. + * @param window The window to focus. + * @ingroup Ecore_X_Window_Input_Focus_Group + */ +EAPI void +ecore_x_window_focus(Ecore_X_Window window) +{ + Ecore_X_Time time = XCB_CURRENT_TIME; + + if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + /* xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_NONE, win, time); */ + xcb_set_input_focus(_ecore_xcb_conn, + XCB_INPUT_FOCUS_POINTER_ROOT, window, time); +} + +/** + * Sets the focus to the given window at a specific time. + * @param window The window to focus. + * @param time When to set the focus to the window. + * @ingroup Ecore_X_Window_Input_Focus_Group + */ +EAPI void +ecore_x_window_focus_at_time(Ecore_X_Window window, + Ecore_X_Time time) +{ + if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + /* xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_NONE, win, time); */ + xcb_set_input_focus(_ecore_xcb_conn, + XCB_INPUT_FOCUS_POINTER_ROOT, window, time); +} + +/** + * @defgroup Ecore_X_Window_Reparent_Group X Window Reparent Functions + * + * Functions that retrieve or changes the parent window of a window. + */ + +/** + * Moves a window to within another window at a given position. + * @param window The window to reparent. + * @param new_parent The new parent window. + * @param x X position within new parent window. + * @param y Y position within new parent window. + * @ingroup Ecore_X_Window_Reparent_Group + */ +EAPI void +ecore_x_window_reparent(Ecore_X_Window window, + Ecore_X_Window new_parent, + int x, + int y) +{ + if (new_parent == 0) new_parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + xcb_reparent_window(_ecore_xcb_conn, window, new_parent, x, y); +} + + +/** + * @defgroup Ecore_X_Window_Change_Attributes_Group X Window Change Attributes Functions + * + * Functions that change the attributes of a window. + */ + +/** + * Sets the background pixmap of the given window. + * @param window The given window. + * @param pixmap The pixmap to set to. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_pixmap_set(Ecore_X_Window window, + Ecore_X_Pixmap pixmap) +{ + uint32_t value_list; + + value_list = pixmap; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_BACK_PIXMAP, &value_list); +} + +/** + * Sets the background color of the given window. + * @param window The given window. + * @param red The red component of the color to set to. + * @param green The green component of the color to set to. + * @param blue The blue component of the color to set to. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_background_color_set(Ecore_X_Window window, + unsigned short red, + unsigned short green, + unsigned short blue) +{ + xcb_alloc_color_cookie_t cookie; + xcb_alloc_color_reply_t *rep; + uint32_t value_list; + + /* FIXME: should I provide a reply, and not the color components, here ? */ + /* (because of roundtrips) */ + cookie = xcb_alloc_color_unchecked(_ecore_xcb_conn, + ((xcb_screen_t *)_ecore_xcb_screen)->default_colormap, + red, green, blue); + rep = xcb_alloc_color_reply(_ecore_xcb_conn, cookie, NULL); + if (!rep) + return; + + value_list = rep->pixel; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_BACK_PIXEL, &value_list); + free(rep); +} + +/** + * Sets the bit gravity of the given window. + * @param window The given window. + * @param gravity The gravity. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_pixel_gravity_set(Ecore_X_Window window, + Ecore_X_Gravity gravity) +{ + uint32_t value_list; + + value_list = gravity; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_BIT_GRAVITY, &value_list); +} + +/** + * Sets the gravity of the given window. + * @param window The given window. + * @param gravity The gravity. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_gravity_set(Ecore_X_Window window, + Ecore_X_Gravity gravity) +{ + uint32_t value_list; + + value_list = gravity; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_WIN_GRAVITY, &value_list); +} + +/** + * Sets the override attribute of the given window. + * @param window The given window. + * @param override_redirect The override_redirect boolean. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_override_set(Ecore_X_Window window, + int override_redirect) +{ + uint32_t value_list; + + value_list = override_redirect; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_OVERRIDE_REDIRECT, &value_list); +} + +/** + * Shows the cursor of the given window. + * @param window The given window. + * @param show If set to @c 0, hide the cursor. Show it otherwise. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_cursor_show(Ecore_X_Window window, + int show) +{ + if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + if (!show) + { + Ecore_X_Cursor cursor; + Ecore_X_Drawable draw; + Ecore_X_Pixmap pixmap; + Ecore_X_Pixmap mask; + Ecore_X_GC gc; + xcb_point_t point; + uint32_t value_list; + + draw = window; + pixmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, + 1, pixmap, draw, + 1, 1); + mask = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, + 1, mask, draw, + 1, 1); + + gc = xcb_generate_id(_ecore_xcb_conn); + xcb_create_gc (_ecore_xcb_conn, gc, draw, 0, NULL); + value_list = 0; + xcb_change_gc(_ecore_xcb_conn, gc, XCB_GC_FOREGROUND, &value_list); + + draw = mask; + point.x = 0; + point.y = 0; + xcb_poly_point(_ecore_xcb_conn, XCB_COORD_MODE_ORIGIN, draw, + gc, 1, &point); + + xcb_free_gc(_ecore_xcb_conn, gc); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_create_cursor(_ecore_xcb_conn, cursor, + pixmap, mask, + 0, 0, 0, + 0, 0, 0, + 0, 0); + value_list = cursor; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_CURSOR, &value_list); + + xcb_free_cursor(_ecore_xcb_conn, cursor); + xcb_free_pixmap(_ecore_xcb_conn, mask); + xcb_free_pixmap(_ecore_xcb_conn, pixmap); + } + else + { + uint32_t value_list; + + value_list = 0; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_CURSOR, &value_list); + } +} + +/** + * Sets the cursor of the given window. + * @param window The given window. + * @param cursor The given cursor. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_cursor_set(Ecore_X_Window window, + Ecore_X_Cursor cursor) +{ + uint32_t value_list; + + value_list = cursor; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_CURSOR, &value_list); +} + +/** + * Todo + * @param window The given window. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_container_manage(Ecore_X_Window window) +{ + uint32_t value_list; + + value_list = + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_EVENT_MASK, &value_list); + +} + +/** + * Todo + * @param window The given window. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_client_manage(Ecore_X_Window window) +{ + uint32_t value_list; + + value_list = + XCB_EVENT_MASK_VISIBILITY_CHANGE | +/* XCB_EVENT_MASK_RESIZE_REDIRECT | */ + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_EVENT_MASK, &value_list); +#ifdef ECORE_XCB_SHAPE + xcb_shape_select_input(_ecore_xcb_conn, window, 1); +#endif /* ECORE_XCB_SHAPE */ +} + +/** + * Todo + * @param window The given window. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_sniff(Ecore_X_Window window) +{ + uint32_t value_list; + + value_list = + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_PROPERTY_CHANGE; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_EVENT_MASK, &value_list); +} + +/** + * Todo + * @param window The given window. + * @ingroup Ecore_X_Window_Change_Attributes_Group + */ +EAPI void +ecore_x_window_client_sniff(Ecore_X_Window window) +{ + uint32_t value_list; + + value_list = + XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE; + xcb_change_window_attributes(_ecore_xcb_conn, window, + XCB_CW_EVENT_MASK, &value_list); +#ifdef ECORE_XCB_SHAPE + xcb_shape_select_input(_ecore_xcb_conn, window, 1); +#endif /* ECORE_XCB_SHAPE */ +} + +/** + * Clears an area of the given window. + * @param window The given window. + * @param x The X coordinate of the area. + * @param y The Y coordinate of the area. + * @param width The width of the area. + * @param height The height of the area. + * @ingroup Ecore_X_Window_Clear_Area_Group + */ +EAPI void +ecore_x_window_area_clear(Ecore_X_Window window, + int x, + int y, + int width, + int height) +{ + xcb_clear_area(_ecore_xcb_conn, 0, window, x, y, width, height); +} + +/** + * Exposes an area of the given window. + * @param window The given window. + * @param x The X coordinate of the area. + * @param y The Y coordinate of the area. + * @param width The width of the area. + * @param height The height of the area. + * @ingroup Ecore_X_Window_Clear_Area_Group + */ +EAPI void +ecore_x_window_area_expose(Ecore_X_Window window, + int x, + int y, + int width, + int height) +{ + xcb_clear_area(_ecore_xcb_conn, 1, window, x, y, width, height); +} + + +/** + * @defgroup Ecore_X_Window_Save_Set_Group X Window Change Save Set Functions + * + * Functions that either inserts or deletes the specified window from + * the client's save-set. + */ + +/** + * Inserts the window in the client's save-set. + * @param window The window to insert in the client's save-set. + * @ingroup Ecore_X_Window_Save_Set_Group + */ +EAPI void +ecore_x_window_save_set_add(Ecore_X_Window window) +{ + xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_INSERT, window); +} + +/** + * Deletes the window from the client's save-set. + * @param window The window to delete from the client's save-set. + * @ingroup Ecore_X_Window_Save_Set_Group + */ +EAPI void +ecore_x_window_save_set_del(Ecore_X_Window window) +{ + xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_DELETE, window); +} + +/****************************** + * + * Request that have a reply + * + ******************************/ + + +/** + * Sends the GetInputFocus request. + * @ingroup Ecore_X_Window_Input_Focus_Group + */ +EAPI void +ecore_x_get_input_focus_prefetch(void) +{ + xcb_get_input_focus_cookie_t cookie; + + cookie = xcb_get_input_focus_unchecked(_ecore_xcb_conn); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetInputFocus request sent by ecore_x_get_input_focus_prefetch(). + * @ingroup Ecore_X_Window_Input_Focus_Group + */ +EAPI void +ecore_x_get_input_focus_fetch(void) +{ + xcb_get_input_focus_cookie_t cookie; + xcb_get_input_focus_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Gets the window that has focus. + * @return The window that has focus. + * + * Returns the window that has the focus. If an error aoocured, @c 0 + * is returned, otherwise the function returns the window that has focus. + * + * To use this function, you must call before, and in order, + * ecore_x_get_input_focus_prefetch(), which sends the GetInputFocus request, + * then ecore_x_get_input_focus_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Input_Focus_Group + */ +EAPI Ecore_X_Window +ecore_x_window_focus_get(void) +{ + xcb_get_input_focus_reply_t *reply; + Ecore_X_Window window = 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) return window; + + return reply->focus; +} + + +/** + * @defgroup Ecore_X_Window_Get_Attributes_Group X Window Get Attributes Functions + * + * Functions that get the attributes of a window. + */ + + +/** + * Sends the GetWindowAttributes request. + * @ingroup Ecore_X_Window_Get_Attributes_Group + */ +EAPI void +ecore_x_get_window_attributes_prefetch(Ecore_X_Window window) +{ + xcb_get_window_attributes_cookie_t cookie; + + cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the GetWindowAttributes request sent by ecore_x_get_window_attributes_prefetch(). + * @ingroup Ecore_X_Window_Get_Attributes_Group + */ +EAPI void +ecore_x_get_window_attributes_fetch(void) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Retrieves the attributes of a window. + * @param windows Unused. + * @param att_ret Pointer to an Ecore_X_Window_Attributes + * structure in which the attributes of a window + * are to be stored. + * + * Retrieves the attributes of a window. If + * @p att_ret is @c NULL, the function does nothing. If an error + * occurred, @p att_ret is set to 0. Otherwise, the @p att_ret structure + * is filled with the attributes os the requested window. + * + * To use this function, you must call before, and in order, + * ecore_x_get_window_attributes_prefetch(), which sends the GetWindowAttributes request, + * then ecore_x_get_window_attributes_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Get_Attributes_Group + */ +EAPI int +ecore_x_window_attributes_get(Ecore_X_Window window __UNUSED__, + Ecore_X_Window_Attributes *att_ret) +{ + xcb_get_window_attributes_reply_t *reply; + + if (!att_ret) return 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes)); + + if (reply->map_state != XCB_MAP_STATE_UNMAPPED) att_ret->visible = 1; + if (reply->map_state == XCB_MAP_STATE_VIEWABLE) att_ret->viewable = 1; + if (reply->override_redirect) att_ret->override = 1; + if (reply->_class == XCB_WINDOW_CLASS_INPUT_ONLY) att_ret->input_only = 1; + if (reply->save_under) att_ret->save_under = 1; + + att_ret->event_mask.mine = reply->your_event_mask; + att_ret->event_mask.all = reply->all_event_masks; + att_ret->event_mask.no_propagate = reply->do_not_propagate_mask; + att_ret->window_gravity = reply->win_gravity; + att_ret->pixel_gravity = reply->bit_gravity; + att_ret->colormap = reply->colormap; + att_ret->visual = reply->visual; + + return 1; +} + +/** + * Finds out whether the given window is currently visible. + * @param window Unused. + * @return 1 if the window is visible, otherwise 0. + * + * Finds out whether the given window is currently visible. + * If an error occurred, or if the window is not visible, 0 is + * returned. Otherwise 1 is returned. + * + * To use this function, you must call before, and in order, + * ecore_x_get_window_attributes_prefetch(), which sends the GetWindowAttributes request, + * then ecore_x_get_window_attributes_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Get_Attributes_Group + */ +EAPI int +ecore_x_window_visible_get(Ecore_X_Window window __UNUSED__) +{ + xcb_get_window_attributes_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + return (reply->map_state == XCB_MAP_STATE_VIEWABLE) ? 1 : 0; +} + + +/** + * Sends the QueryPointer request. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI void +ecore_x_pointer_xy_get_prefetch(Ecore_X_Window window) +{ + xcb_query_pointer_cookie_t cookie; + + cookie = xcb_query_pointer_unchecked(_ecore_xcb_conn, window); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the QueryPointer request sent by ecore_x_query_pointer_prefetch(). + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI void +ecore_x_pointer_xy_get_fetch(void) +{ + xcb_query_pointer_cookie_t cookie; + xcb_query_pointer_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_query_pointer_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Retrieves the coordinates of the pointer. + * @param window Unused. + * @param x The X coordinate of the pointer. + * @param y The Y coordinate of the pointer. + * + * Retrieves the coordinates of the pointer. + * If the window used in + * ecore_x_query_pointer_prefetch() is not on the same screen than + * the root window or if an error occured, @p x and @p y are set + * to 0. Otherwise, they are respectively set to the X and Y + * coordinates of the pointer. + * + * To use this function, you must call before, and in order, + * ecore_x_query_pointer_prefetch(), which sends the QueryPointer request, + * then ecore_x_query_pointer_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI void +ecore_x_pointer_xy_get(Ecore_X_Window window __UNUSED__, + int *x, + int *y) +{ + xcb_query_pointer_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + { + if (x) *x = 0; + if (y) *y = 0; + + return; + } + + if (x) *x = reply->win_x; + if (y) *y = reply->win_y; +} + + +/** + * Sends the QueryTree request. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI void +ecore_x_query_tree_prefetch(Ecore_X_Window window) +{ + xcb_query_tree_cookie_t cookie; + + cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, window); + _ecore_xcb_cookie_cache(cookie.sequence); +} + +/** + * Gets the reply of the QueryTree request sent by ecore_x_query_tree_prefetch(). + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI void +ecore_x_query_tree_fetch(void) +{ + xcb_query_tree_cookie_t cookie; + xcb_query_tree_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Retrieves the parent window of the given window. + * @param window Unused. + * @return The parent window of @p window. + * + * Retrieves the parent window of the given window. If + * an error occured, @c 0 is returned. + * + * To use this function, you must call before, and in order, + * ecore_x_query_tree_prefetch(), which sends the QueryTree request, + * then ecore_x_query_tree_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI Ecore_X_Window +ecore_x_window_parent_get(Ecore_X_Window window __UNUSED__) +{ + xcb_query_tree_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + return reply->parent; +} + + +/** + * Retrieves the children windows of the given window. + * @param window Unused. + * @param num children windows count. + * @return The children windows. + * + * Retrieves the children windows of the given window. If + * an error occured, @c 0 is returned. + * + * To use this function, you must call before, and in order, + * ecore_x_query_tree_prefetch(), which sends the QueryTree request, + * then ecore_x_query_tree_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI Ecore_X_Window * +ecore_x_window_children_get(Ecore_X_Window window __UNUSED__, + int *num) +{ + xcb_query_tree_reply_t *reply; + Ecore_X_Window *windows = NULL; + + if (num) *num = 0; + reply = _ecore_xcb_reply_get(); + if (!reply) return NULL; + + windows = malloc(reply->children_len); + if (!windows) + return NULL; + + if (num) *num = reply->children_len; + memcpy(windows, + xcb_query_tree_children(reply), + sizeof(Ecore_X_Window) * reply->children_len); + + return windows; +} + +/* FIXME: I've tried to remove the round trips. 3 cookies are */ +/* created at the beginning of the function. Because of */ +/* the recursivity of the algo, I can't find better trick */ +static Ecore_X_Window +_ecore_x_window_at_xy_get(Ecore_X_Window base, + int16_t base_x, + int16_t base_y, + int16_t x, + int16_t y, + Ecore_X_Window *skip, + int skip_num) +{ + xcb_window_iterator_t iter_children; + xcb_get_window_attributes_cookie_t cookie_get_window_attributes; + xcb_get_geometry_cookie_t cookie_get_geometry; + xcb_query_tree_cookie_t cookie_query_tree; + xcb_get_window_attributes_reply_t *reply_get_window_attributes; + xcb_get_geometry_reply_t *reply_get_geometry; + xcb_query_tree_reply_t *reply_query_tree; + Ecore_X_Window window = 0; + Ecore_X_Window child = 0; + int16_t win_x; + int16_t win_y; + uint16_t win_width; + uint16_t win_height; + + cookie_get_window_attributes = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, base); + cookie_get_geometry = xcb_get_geometry_unchecked(_ecore_xcb_conn, base); + cookie_query_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, base); + + reply_get_window_attributes = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_get_window_attributes, NULL); + if (!reply_get_window_attributes) + { + reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL); + if (reply_get_geometry) free(reply_get_geometry); + reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL); + if (reply_query_tree) free(reply_query_tree); + return window; + } + + if (reply_get_window_attributes->map_state != XCB_MAP_STATE_VIEWABLE) + { + free(reply_get_window_attributes); + reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL); + if (reply_get_geometry) free(reply_get_geometry); + reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL); + if (reply_query_tree) free(reply_query_tree); + return window; + } + + free(reply_get_window_attributes); + + reply_get_geometry = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_get_geometry, NULL); + if (!reply_get_geometry) + { + reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL); + if (reply_query_tree) free(reply_query_tree); + return window; + } + + win_x = reply_get_geometry->x; + win_y = reply_get_geometry->y; + win_width = reply_get_geometry->width; + win_height = reply_get_geometry->height; + + free(reply_get_geometry); + + win_x += base_x; + win_y += base_y; + + if (!((x >= win_x) && + (y >= win_y) && + (x < (int16_t)(win_x + win_width)) && + (y < (int16_t)(win_y + win_height)))) + { + reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL); + if (reply_query_tree) free(reply_query_tree); + return window; + } + + reply_query_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_query_tree, NULL); + if (!reply_query_tree) + { + if (skip) + { + int i; + + for (i = 0; i < skip_num; i++) + if (base == skip[i]) + return window; + } + return base; + } + + iter_children = xcb_query_tree_children_iterator(reply_query_tree); + for (; iter_children.rem; xcb_window_next(&iter_children)) + { + if (skip) + { + int j; + + for (j = 0; j < skip_num; j++) + if (*iter_children.data == skip[j]) + continue; + } + child = _ecore_x_window_at_xy_get(*iter_children.data, win_x, win_y, x, y, skip, skip_num); + if (child) + { + free(reply_query_tree); + + return child; + } + } + + if (skip) + { + int i; + + for (i = 0; i < skip_num; i++) + if (base == skip[i]) + { + /* We return 0. child has an xid equal to 0 */ + free(reply_query_tree); + return child; + } + } + + free(reply_query_tree); + + return base; +} + +/** + * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions + * + * Functions that change or retrieve the geometry of X windows. + */ + +/** + * Retrieves the top, visible window at the given location. + * @param x The given X position. + * @param y The given Y position. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_at_xy_get(int x, + int y) +{ + Ecore_X_Window window; + Ecore_X_Window root; + + /* FIXME: Proper function to determine current root/virtual root + * window missing here */ + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ecore_x_grab(); + window = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0); + ecore_x_ungrab(); + + return window ? window : root; +} + +/** + * Retrieves the top, visible window at the given location, + * but skips the windows in the list. + * @param x The given X position. + * @param y The given Y position. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_at_xy_with_skip_get(int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Ecore_X_Window window; + Ecore_X_Window root; + + /* FIXME: Proper function to determine current root/virtual root + * window missing here */ + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ecore_x_grab(); + window = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num); + ecore_x_ungrab(); + + return window ? window : root; +} + +/** + * Retrieves the top, visible window at the given location, + * but begins at the @p begin window instead of the root one. + * @param begin The window from which we begin. + * @param x The given X position. + * @param y The given Y position. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, + int x, + int y) +{ + Ecore_X_Window window; + + ecore_x_grab(); + window = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0); + ecore_x_ungrab(); + + return window ? window : begin; +} + + + +/* FIXME: Should I provide the replies (or the cookies), instead of + creating them in the function ? */ +#ifdef ECORE_XCB_RENDER +static Ecore_X_Window +_ecore_x_window_argb_internal_new(Ecore_X_Window parent, + int16_t x, + int16_t y, + uint16_t w, + uint16_t h, + uint8_t override_redirect, + uint8_t save_under) +{ + uint32_t value_list[10]; + xcb_screen_iterator_t iter_screen; + xcb_visualtype_iterator_t iter_visualtype; + xcb_render_query_pict_formats_cookie_t cookie_pict_format; + xcb_render_query_pict_formats_reply_t *rep_pict_format; + Ecore_X_Screen *screen = NULL; + Ecore_X_Window win = { 0 }; + xcb_visualid_t vis = { 0 }; + Ecore_X_Colormap colormap; + uint32_t value_mask; + + cookie_pict_format = xcb_render_query_pict_formats_unchecked(_ecore_xcb_conn); + + if (parent == 0) + { + parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + screen = ((xcb_screen_t *)_ecore_xcb_screen); + } + else + { + xcb_screen_iterator_t iter_screen; + xcb_get_geometry_reply_t *rep; + Ecore_X_Drawable draw; + Ecore_X_Window root; + + draw = parent; + rep = xcb_get_geometry_reply(_ecore_xcb_conn, + xcb_get_geometry_unchecked(_ecore_xcb_conn, + draw), + NULL); + if (!rep) + return win; + + root = rep->root; + + free(rep); + + for (; iter_screen.rem; xcb_screen_next(&iter_screen)) + { + if (iter_screen.data->root == root) + { + screen = iter_screen.data; + } + } + } + if (!screen) + return win; + + /* we get the X visual types */ + iter_screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + for (; iter_screen.rem; xcb_screen_next(&iter_screen)) { + if (iter_screen.data == screen) { + xcb_depth_iterator_t iter_depth; + + iter_depth = xcb_screen_allowed_depths_iterator(iter_screen.data); + for (; iter_depth.rem; xcb_depth_next(&iter_depth)) { + if (iter_depth.data->depth == 32) { + iter_visualtype = xcb_depth_visuals_iterator(iter_depth.data); + break; + } + } + } + } + + /* we get the X render visual id */ + rep_pict_format = xcb_render_query_pict_formats_reply(_ecore_xcb_conn, + cookie_pict_format, + NULL); + if (!rep_pict_format) + return win; + + for (; iter_visualtype.rem; xcb_visualtype_next(&iter_visualtype)) { + if (iter_visualtype.data->_class == XCB_VISUAL_CLASS_TRUE_COLOR) { + xcb_render_pictforminfo_iterator_t iter_forminfo; + xcb_render_pictscreen_iterator_t iter_pictscreen; + xcb_render_pictformat_t pict_format = { 0 }; + + iter_forminfo = xcb_render_query_pict_formats_formats_iterator(rep_pict_format); + for (; iter_forminfo.rem; xcb_render_pictforminfo_next(&iter_forminfo)) { + if ((iter_forminfo.data->type == XCB_RENDER_PICT_TYPE_DIRECT) && + (iter_forminfo.data->direct.alpha_mask)) { + pict_format = iter_forminfo.data->id; + break; + } + } + if (pict_format == 0) { + free(rep_pict_format); + return win; + } + iter_pictscreen = xcb_render_query_pict_formats_screens_iterator(rep_pict_format); + for (; iter_pictscreen.rem; xcb_render_pictscreen_next(&iter_pictscreen)) { + xcb_render_pictdepth_iterator_t iter_depth; + + iter_depth = xcb_render_pictscreen_depths_iterator(iter_pictscreen.data); + for (; iter_depth.rem; xcb_render_pictdepth_next(&iter_depth)) { + xcb_render_pictvisual_iterator_t iter_visual; + + iter_visual = xcb_render_pictdepth_visuals_iterator(iter_depth.data); + for (; iter_visual.rem; xcb_render_pictvisual_next(&iter_visual)) { + if ((iter_visual.data->visual == iter_visualtype.data->visual_id) && + (pict_format == iter_visual.data->format)) { + vis = iter_visual.data->visual; + break; + } + } + } + } + } + } + + free(rep_pict_format); + + if (vis == 0) + return win; + + colormap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_colormap(_ecore_xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap, win, vis); + + value_mask = + XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | + XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT | + XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE | + XCB_CW_COLORMAP; + + value_list[0] = XCB_NONE; + value_list[1] = 0; + value_list[2] = XCB_GRAVITY_NORTH_WEST; + value_list[3] = XCB_GRAVITY_NORTH_WEST; + value_list[4] = XCB_BACKING_STORE_NOT_USEFUL; + value_list[5] = override_redirect; + value_list[6] = save_under; + value_list[7] = + XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE; + value_list[8] = XCB_EVENT_MASK_NO_EVENT; + value_list[9] = colormap; + + win = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, + 32, /* depth */ + win, parent, + x, y, w, h, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + vis, + value_mask, + value_list); + + xcb_free_colormap(_ecore_xcb_conn, colormap); + + if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) + ecore_x_window_defaults_set(win); + + return win; +} +#endif /* ECORE_XCB_RENDER */ + + + +/* FIXME: round trip */ +EAPI int +ecore_x_window_argb_get(Ecore_X_Window win) +{ + uint8_t ret = 0; +#ifdef ECORE_XCB_RENDER + xcb_render_pictforminfo_iterator_t iter_forminfo; + xcb_render_pictscreen_iterator_t iter_pictscreen; + xcb_render_pictformat_t pict_format = { 0 }; + xcb_render_query_pict_formats_reply_t *rep_pictformat; + xcb_get_window_attributes_reply_t *rep; + xcb_visualid_t visual; + + rep = xcb_get_window_attributes_reply(_ecore_xcb_conn, + xcb_get_window_attributes_unchecked(_ecore_xcb_conn, + win), + NULL); + if (!rep) + return ret; + + visual = rep->visual; + + free(rep); + + rep_pictformat = xcb_render_query_pict_formats_reply(_ecore_xcb_conn, + xcb_render_query_pict_formats_unchecked(_ecore_xcb_conn), + NULL); + if (!rep_pictformat) + return ret; + + iter_forminfo = xcb_render_query_pict_formats_formats_iterator(rep_pictformat); + for (; iter_forminfo.rem; xcb_render_pictforminfo_next(&iter_forminfo)) + { + if ((iter_forminfo.data->type == XCB_RENDER_PICT_TYPE_DIRECT) && + (iter_forminfo.data->direct.alpha_mask)) + { + pict_format = iter_forminfo.data->id; + break; + } + } + if (pict_format == 0) + { + free(rep_pictformat); + + return ret; + } + + iter_pictscreen = xcb_render_query_pict_formats_screens_iterator(rep_pictformat); + for (; iter_pictscreen.rem; xcb_render_pictscreen_next(&iter_pictscreen)) + { + xcb_render_pictdepth_iterator_t iter_depth; + + iter_depth = xcb_render_pictscreen_depths_iterator(iter_pictscreen.data); + for (; iter_depth.rem; xcb_render_pictdepth_next(&iter_depth)) + { + xcb_render_pictvisual_iterator_t iter_visual; + + iter_visual = xcb_render_pictdepth_visuals_iterator(iter_depth.data); + for (; iter_visual.rem; xcb_render_pictvisual_next(&iter_visual)) + { + if ((iter_visual.data->visual == visual) && + (pict_format == iter_visual.data->format)) + { + ret = 1; + break; + } + } + } + } + + free(rep_pictformat); +#endif /* ECORE_XCB_RENDER */ + + return ret; +} + + + + +/** + * Set if a window should be ignored. + * @param window The given window. + * @param ignore if to ignore + */ +EAPI void +ecore_x_window_ignore_set(Ecore_X_Window window, + int ignore) +{ + int i, j; + + if (ignore) + { + if (ignore_list) + { + for (i = 0; i < ignore_num; i++) + { + if (window == ignore_list[i]) + return; + } + ignore_list = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window)); + if (!ignore_list) return; + ignore_list[ignore_num++] = window; + } + else + { + ignore_num = 0; + ignore_list = malloc(sizeof(Ecore_X_Window)); + ignore_list[ignore_num++] = window; + } + } + else + { + if (!ignore_list) return; + for (i = 0, j = 0; i < ignore_num; i++) + { + if (window != ignore_list[i]) + ignore_list[i] = ignore_list[j++]; + else + ignore_num--; + } + ignore_list = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window)); + } +} + +/** + * Get the ignore list + * @param num number of windows in the list + * @return list of windows to ignore + */ +EAPI Ecore_X_Window * +ecore_x_window_ignore_list(int *num) +{ + if (num) *num = ignore_num; + return ignore_list; +} + +/** + * Retrieves the size of the given window. + * @param win The given window. + * @param w Pointer to an integer into which the width is to be stored. + * @param h Pointer to an integer into which the height is to be stored. + * + * To use this function, you must call before, and in order, + * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request, + * then ecore_x_drawable_geometry_get_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_size_get(Ecore_X_Window window, + int *width, + int *height) +{ + if (window == 0) + window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ecore_x_drawable_geometry_get(window, NULL, NULL, width, height); +} + +/** + * Retrieves the geometry of the given window. + * @param win The given window. + * @param x Pointer to an integer in which the X position is to be stored. + * @param y Pointer to an integer in which the Y position is to be stored. + * @param w Pointer to an integer in which the width is to be stored. + * @param h Pointer to an integer in which the height is to be stored. + * + * To use this function, you must call before, and in order, + * ecore_x_drawable_geometry_get_prefetch(), which sends the GetGeometry request, + * then ecore_x_drawable_geometry_get_fetch(), which gets the reply. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_geometry_get(Ecore_X_Window window, + int *x, + int *y, + int *width, + int *height) +{ + if (!window) + window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ecore_x_drawable_geometry_get(window, x, y, width, height); +} + +/** + * Retrieves the width of the border of the given window. + * @param win The given window. + * @return Width of the border of @p win. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI int +ecore_x_window_border_width_get(Ecore_X_Window win) +{ + /* doesn't make sense to call this on a root window */ + if (!win) + return 0; + + return ecore_x_drawable_border_width_get(win); +} + +/** + * Retrieves the depth of the given window. + * @param win The given window. + * @return Depth of the window. + */ +EAPI int +ecore_x_window_depth_get(Ecore_X_Window win) +{ + return ecore_x_drawable_depth_get(win); +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_window_prop.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_window_prop.c new file mode 100644 index 0000000000..c7b81afe24 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_window_prop.c @@ -0,0 +1,871 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" +#include "Ecore_X_Atoms.h" + + +/* + * Set CARD32 (array) property + */ +EAPI void +ecore_x_window_prop_card32_set(Ecore_X_Window win, + Ecore_X_Atom atom, + unsigned int *val, + unsigned int num) +{ + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + atom, ECORE_X_ATOM_CARDINAL, 32, num, (const void *)val); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @param atom The atom. + */ +EAPI void +ecore_x_window_prop_card32_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window, + atom, + ECORE_X_ATOM_CARDINAL, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_prop_card32_get_prefetch(). + */ +EAPI void +ecore_x_window_prop_card32_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* + * Get CARD32 (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_card32_get(Ecore_X_Window win __UNUSED__, + Ecore_X_Atom atom __UNUSED__, + unsigned int *val, + unsigned int len) +{ + xcb_get_property_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply || + (reply->type != ECORE_X_ATOM_CARDINAL) || + (reply->format != 32)) + return -1; + + if (reply->value_len < len) + len = xcb_get_property_value_length(reply); + + if (val) + memcpy(val, xcb_get_property_value(reply), len); + + return (int)len; +} + +/* + * Get CARD32 (array) property of any length + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_card32_list_get(Ecore_X_Window win __UNUSED__, + Ecore_X_Atom atom __UNUSED__, + unsigned int **plist) +{ + xcb_get_property_reply_t *reply; + int num = -1; + + if (plist) + *plist = NULL; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return -1; + + if ((reply->type == XCB_NONE) || + (reply->value_len == 0)) + num = 0; + else if ((reply->type == ECORE_X_ATOM_CARDINAL) && + (reply->format == 32)) + { + uint32_t *val; + + num = xcb_get_property_value_length(reply); + if (plist) + { + val = (uint32_t *)malloc (num); + if (!val) + goto error; + + memcpy(val, xcb_get_property_value(reply), num); + *plist = val; + } + } + + error: + + return num; +} + +/* + * Set X ID (array) property + */ +EAPI void +ecore_x_window_prop_xid_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID *xids, + unsigned int num) +{ + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + atom, type, 32, num, xids); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @param atom The atom. + * @param type The atom type. + */ +EAPI void +ecore_x_window_prop_xid_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom, + Ecore_X_Atom type) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window, + atom, + type, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_prop_xid_get_prefetch(). + */ +EAPI void +ecore_x_window_prop_xid_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* + * Get X ID (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_xid_get(Ecore_X_Window win __UNUSED__, + Ecore_X_Atom atom __UNUSED__, + Ecore_X_Atom type __UNUSED__, + Ecore_X_ID *xids, + unsigned int len) +{ + xcb_get_property_reply_t *reply; + int num = len; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return -1; + + if (reply->type == XCB_NONE) + num = 0; + else if (reply->format == 32) + { + if (reply->value_len < len) + num = xcb_get_property_value_length(reply); + + if (xids) + memcpy(xids, xcb_get_property_value(reply), num); + } + + return num; +} + +/* + * Get X ID (array) property + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * The returned array must be freed with free(). + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_xid_list_get(Ecore_X_Window win __UNUSED__, + Ecore_X_Atom atom __UNUSED__, + Ecore_X_Atom type __UNUSED__, + Ecore_X_ID **pxids) +{ + xcb_get_property_reply_t *reply; + int num = -1; + + if (pxids) + *pxids = NULL; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return -1; + + if ((reply->type == XCB_NONE) || + (reply->value_len == 0)) + num = 0; + else if ((reply->type == ECORE_X_ATOM_CARDINAL) && + (reply->format == 32)) + { + uint32_t *val; + + num = xcb_get_property_value_length(reply); + if (pxids) + { + val = (uint32_t *)malloc (num); + if (!val) + return -1; + + memcpy(val, xcb_get_property_value(reply), num); + *pxids = val; + } + } + + return num; +} + +/* + * Remove/add/toggle X ID list item. + */ +EAPI void +ecore_x_window_prop_xid_list_change(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID item, + int op) +{ + Ecore_X_ID *lst; + int i; + int num; + + num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst); + if (num < 0) + return; /* Error - assuming invalid window */ + + /* Is it there? */ + for (i = 0; i < num; i++) + { + if (lst[i] == item) + break; + } + + if (i < num) + { + /* Was in list */ + if (op == ECORE_X_PROP_LIST_ADD) + goto done; + /* Remove it */ + num--; + for (; i < num; i++) + lst[i] = lst[i + 1]; + } + else + { + /* Was not in list */ + if (op == ECORE_X_PROP_LIST_REMOVE) + goto done; + /* Add it */ + num++; + lst = realloc(lst, num * sizeof(Ecore_X_ID)); + lst[i] = item; + } + + ecore_x_window_prop_xid_set(win, atom, type, lst, num); + + done: + if (lst) + free(lst); +} + +/* + * Set Atom (array) property + */ +EAPI void +ecore_x_window_prop_atom_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom *list, + unsigned int num) +{ + ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_ATOM, list, num); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @param atom Property atom. + */ +EAPI void +ecore_x_window_prop_atom_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window, + atom, + ECORE_X_ATOM_ATOM, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_prop_atom_get_prefetch(). + */ +EAPI void +ecore_x_window_prop_atom_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* + * Get Atom (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_atom_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom *list, + unsigned int len) +{ + return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_ATOM, list, len); +} + +/* + * Get Atom (array) property + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * The returned array must be freed with free(). + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_atom_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom **plist) +{ + return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_ATOM, plist); +} + +/* + * Remove/add/toggle atom list item. + */ +EAPI void +ecore_x_window_prop_atom_list_change(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom item, + int op) +{ + ecore_x_window_prop_xid_list_change(win, atom, ECORE_X_ATOM_ATOM, item, op); +} + +/* + * Set Window (array) property + */ +EAPI void +ecore_x_window_prop_window_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window *list, + unsigned int num) +{ + ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_WINDOW, list, num); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @param atom The atom. + */ +EAPI void +ecore_x_window_prop_window_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom atom) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window, + atom, + ECORE_X_ATOM_WINDOW, + 0, 0x7fffffff); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_prop_window_get_prefetch(). + */ +EAPI void +ecore_x_window_prop_window_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/* + * Get Window (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_window_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window *list, + unsigned int len) +{ + return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_WINDOW, list, len); +} + +/* + * Get Window (array) property + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * The returned array must be freed with free(). + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_window_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window **plist) +{ + return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_WINDOW, plist); +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +EAPI Ecore_X_Atom +ecore_x_window_prop_any_type(void) +{ + return XCB_GET_PROPERTY_TYPE_ANY; +} + +/** + * To be documented. + * @param window The window. + * @param property The property atom. + * @param type The type atom. + * @param size The size. + * @param data The data. + * @param number The size of the data. + * + * FIXME: To be fixed. + */ +EAPI void +ecore_x_window_prop_property_set(Ecore_X_Window window, + Ecore_X_Atom property, + Ecore_X_Atom type, + int size, + void *data, + int number) +{ + if (window == 0) window = ((xcb_screen_t *)_ecore_xcb_screen)->root; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, window, + property, type, + size, number, data); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @param property Property atom. + * @param type Type atom. + */ +EAPI void +ecore_x_window_prop_property_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom property, + Ecore_X_Atom type) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root, + property, type, 0, LONG_MAX); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_prop_property_get_prefetch(). + */ +EAPI void +ecore_x_window_prop_property_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * To be documented. + * @param window The window (Unused). + * @param property The property atom (Unused). + * @param type The type atom (Unused). + * @param size The size (Unused). + * @param data The returned data. + * @param num The size of the data. + * @return 1 on success, 0 otherwise. + * + * FIXME: To be fixed. + */ +EAPI int +ecore_x_window_prop_property_get(Ecore_X_Window window __UNUSED__, + Ecore_X_Atom property __UNUSED__, + Ecore_X_Atom type __UNUSED__, + int size __UNUSED__, + unsigned char **data, + int *num) +{ + xcb_get_property_reply_t *reply; + + /* make sure these are initialized */ + if (num) *num = 0L; + + if (data) + *data = NULL; + else /* we can't store the retrieved data, so just return */ + return 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return 0; + + if ((reply->format != size) || + (reply->value_len == 0)) + return 0; + + *data = malloc(reply->value_len); + if (!*data) + return 0; + + memcpy(*data, xcb_get_property_value(reply), + xcb_get_property_value_length(reply)); + + if (num) + *num = reply->value_len; + + return reply->format; +} + +EAPI void +ecore_x_window_prop_property_del(Ecore_X_Window window, + Ecore_X_Atom property) +{ + xcb_delete_property(_ecore_xcb_conn, window, property); +} + +/** + * Sends the ListProperties request. + * @param window Window whose properties are requested. + */ +EAPI void +ecore_x_window_prop_list_prefetch(Ecore_X_Window window) +{ + xcb_list_properties_cookie_t cookie; + + cookie = xcb_list_properties_unchecked(_ecore_xcb_conn, window); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the ListProperties request sent by ecore_x_window_prop_list_prefetch(). + */ +EAPI void +ecore_x_window_prop_list_fetch(void) +{ + xcb_list_properties_cookie_t cookie; + xcb_list_properties_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_list_properties_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + + +/** + * To be documented. + * @param window The window (Unused). + * @param num_ret The number of atoms. + * @return The returned atoms. + * + * FIXME: To be fixed. + */ +EAPI Ecore_X_Atom * +ecore_x_window_prop_list(Ecore_X_Window window __UNUSED__, + int *num_ret) +{ + xcb_list_properties_reply_t *reply; + Ecore_X_Atom *atoms; + + if (num_ret) *num_ret = 0; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return NULL; + + atoms = (Ecore_X_Atom *)malloc(reply->atoms_len * sizeof(Ecore_X_Atom)); + if (!atoms) + return NULL; + memcpy(atoms, + xcb_list_properties_atoms(reply), + reply->atoms_len * sizeof(Ecore_X_Atom)); + if(num_ret) + *num_ret = reply->atoms_len; + + return atoms; +} + +/** + * Set a window string property. + * @param win The window + * @param type The property + * @param str The string + * + * Set a window string property + */ +EAPI void +ecore_x_window_prop_string_set(Ecore_X_Window win, + Ecore_X_Atom type, + const char *str) +{ + if (win == 0) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + type, ECORE_X_ATOM_UTF8_STRING, + 8, strlen(str), str); +} + +/** + * Sends the GetProperty request. + * @param window Window whose properties are requested. + * @param type The atom. + */ +EAPI void +ecore_x_window_prop_string_get_prefetch(Ecore_X_Window window, + Ecore_X_Atom type) +{ + xcb_get_property_cookie_t cookie; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, + window ? window : ((xcb_screen_t *)_ecore_xcb_screen)->root, + type, XCB_GET_PROPERTY_TYPE_ANY, 0L, 1000000L); + _ecore_xcb_cookie_cache(cookie.sequence); +} + + +/** + * Gets the reply of the GetProperty request sent by ecore_x_window_prop_string_get_prefetch(). + */ +EAPI void +ecore_x_window_prop_string_get_fetch(void) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +} + +/** + * Get a window string property. + * @param window The window + * @param type The property + * + * Return window string property of a window. String must be free'd when done. + * + * To use this function, you must call before, and in order, + * ecore_x_window_prop_string_get_prefetch(), which sends the GetProperty request, + * then ecore_x_window_prop_string_get_fetch(), which gets the reply. + */ +EAPI char * +ecore_x_window_prop_string_get(Ecore_X_Window window __UNUSED__, + Ecore_X_Atom type __UNUSED__) +{ + xcb_get_property_reply_t *reply; + char *str = NULL; + + reply = _ecore_xcb_reply_get(); + if (!reply) + return NULL; + + if (reply->type == ECORE_X_ATOM_UTF8_STRING) + { + int length; + + length = reply->value_len; + str = (char *)malloc(length + 1); + memcpy(str, + xcb_get_property_value(reply), + length); + str[length] = '\0'; + } + else + { + /* FIXME: to be done... */ + +/* #ifdef X_HAVE_UTF8_STRING */ +/* s = Xutf8TextPropertyToTextList(_ecore_xcb_conn, &xtp, */ +/* &list, &items); */ +/* #else */ +/* s = XmbTextPropertyToTextList(_ecore_xcb_conn, &xtp, */ +/* &list, &items); */ +/* #endif */ +/* if ((s == XLocaleNotSupported) || */ +/* (s == XNoMemory) || (s == XConverterNotFound)) */ +/* { */ +/* str = strdup((char *)xtp.value); */ +/* } */ +/* else if ((s >= Success) && (items > 0)) */ +/* { */ +/* str = strdup(list[0]); */ +/* } */ +/* if (list) */ +/* XFreeStringList(list); */ + } + + return str; +} + +/* FIXME : round trips because of GetWMProtocols */ +/* should we rewrite its code ? */ +EAPI int +ecore_x_window_prop_protocol_isset(Ecore_X_Window window, + Ecore_X_WM_Protocol protocol) +{ + Ecore_X_Atom *protos; + Ecore_X_Atom proto; + uint32_t protos_count; + uint32_t i; + uint8_t ret = 0; + + /* check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return ret; + + proto = _ecore_xcb_atoms_wm_protocols[protocol]; + + if (!xcb_get_wm_protocols(_ecore_xcb_conn, window, &protos_count, &protos)) + return ret; + + for (i = 0; i < protos_count; i++) + if (protos[i] == proto) + { + ret = 1; + break; + } + + free(protos); + + return ret; +} + +/** + * To be documented. + * @param window The window. + * @param num_ret The number of WM protocols. + * @return The returned WM protocols. + * + * FIXME: To be fixed. + */ + +/* FIXME : round trips because of get_wm_protocols */ +/* should we rewrite its code ? */ + +EAPI Ecore_X_WM_Protocol * +ecore_x_window_prop_protocol_list_get(Ecore_X_Window window, + int *num_ret) +{ + Ecore_X_WM_Protocol *prot_ret = NULL; + Ecore_X_Atom *protos; + uint32_t protos_count; + uint32_t i; + + if (!xcb_get_wm_protocols(_ecore_xcb_conn, window, &protos_count, &protos)) + return NULL; + + if ((!protos) || (protos_count <= 0)) return NULL; + + prot_ret = calloc(1, protos_count * sizeof(Ecore_X_WM_Protocol)); + if (!prot_ret) + { + free(protos); + return NULL; + } + for (i = 0; i < protos_count; i++) + { + Ecore_X_WM_Protocol j; + + prot_ret[i] = -1; + for (j = 0; j < ECORE_X_WM_PROTOCOL_NUM; j++) + { + if (_ecore_xcb_atoms_wm_protocols[j] == protos[i]) + prot_ret[i] = j; + } + } + free(protos); + *num_ret = protos_count; + + return prot_ret; +} diff --git a/legacy/ecore/src/lib/ecore_x/ecore_xcb_xinerama.c b/legacy/ecore/src/lib/ecore_x/ecore_xcb_xinerama.c new file mode 100644 index 0000000000..52aaf96070 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/ecore_xcb_xinerama.c @@ -0,0 +1,197 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "ecore_xcb_private.h" + + +/** + * @defgroup Ecore_X_Xinerama_Group X Xinerama Extension Functions + * + * Functions related to the X Xinerama extension. + */ + + +#ifdef ECORE_XCB_XINERAMA +static int _xinerama_available = 0; +static xcb_xinerama_query_version_cookie_t _ecore_xcb_xinerama_init_cookie; +#endif /* ECORE_XCB_XINERAMA */ + + +/* To avoid round trips, the initialization is separated in 2 + functions: _ecore_xcb_xinerama_init and + _ecore_xcb_xinerama_init_finalize. The first one gets the cookies and + the second one gets the replies. */ + +void +_ecore_x_xinerama_init(const xcb_query_extension_reply_t *reply) +{ +#ifdef ECORE_XCB_XINERAMA + if (reply && (reply->present)) + _ecore_xcb_xinerama_init_cookie = xcb_xinerama_query_version_unchecked(_ecore_xcb_conn, 1, 2); +#endif /* ECORE_XCB_XINERAMA */ +} + +void +_ecore_x_xinerama_init_finalize(void) +{ +#ifdef ECORE_XCB_XINERAMA + xcb_xinerama_query_version_reply_t *reply; + + reply = xcb_xinerama_query_version_reply(_ecore_xcb_conn, + _ecore_xcb_xinerama_init_cookie, NULL); + + if (reply) + { + if ((reply->major >= 1) && + (reply->minor >= 1)) + _xinerama_available = 1; + free(reply); + } +#endif /* ECORE_XCB_XINERAMA */ +} + + +/** + * Return whether the X server supports the Xinerama Extension. + * @return 1 if the X Xinerama Extension is available, 0 otherwise. + * + * Return 1 if the X server supports the Fixes Xinerama version 1.1, + * 0 otherwise. + * @ingroup Ecore_X_Xinerama_Group + */ +EAPI int +ecore_x_xinerama_query(void) +{ +#ifdef ECORE_XCB_XINERAMA + return _xinerama_available; +#else + return 0; +#endif /* ECORE_XCB_XINERAMA */ +} + + +/** + * Sends the XineramaQueryScreens request. + * @ingroup Ecore_X_Xinerama_Group + */ +EAPI void +ecore_x_xinerama_query_screens_prefetch(void) +{ +#ifdef ECORE_XCB_XINERAMA + xcb_xinerama_query_screens_cookie_t cookie; + + cookie = xcb_xinerama_query_screens_unchecked(_ecore_xcb_conn); + _ecore_xcb_cookie_cache(cookie.sequence); +#endif /* ECORE_XCB_XINERAMA */ +} + + +/** + * Gets the reply of the XineramaQueryScreens request sent by ecore_x_xinerama_query_screens_prefetch(). + * @ingroup Ecore_X_Xinerama_Group + */ +EAPI void +ecore_x_xinerama_query_screens_fetch(void) +{ +#ifdef ECORE_XCB_XINERAMA + xcb_xinerama_query_screens_cookie_t cookie; + xcb_xinerama_query_screens_reply_t *reply; + + cookie.sequence = _ecore_xcb_cookie_get(); + reply = xcb_xinerama_query_screens_reply(_ecore_xcb_conn, cookie, NULL); + _ecore_xcb_reply_cache(reply); +#endif /* ECORE_XCB_XINERAMA */ +} + + +/** + * Return the number of screens. + * @return The screen count. + * + * Return the number of screens. + * + * To use this function, you must call before, and in order, + * ecore_x_xinerama_query_screens_prefetch(), which sends the XineramaQueryScreens request, + * then ecore_x_xinerama_query_screens_fetch(), which gets the reply. + * @ingroup Ecore_X_Xinerama_Group + */ +EAPI int +ecore_x_xinerama_screen_count_get(void) +{ + int screen_count = 0; +#ifdef ECORE_XCB_XINERAMA + xcb_xinerama_screen_info_iterator_t iter; + xcb_xinerama_query_screens_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) return 0; + + iter = xcb_xinerama_query_screens_screen_info_iterator(reply); + screen_count = iter.rem; +#endif /* ECORE_XCB_XINERAMA */ + + return screen_count; +} + + +/** + * Get the geometry of the screen. + * @param screen The screen (Unused). + * @param x The X coordinate of the screen. + * @param y The Y coordinate of the screen + * @param width The width of the screen + * @param height The height of the screen + * @return 1 on success, 0 otherwise. + * + * Get the geometry of the screen whose number is @p screen. The + * returned values are stored in @p x, @p y, @p width and @p height. + * + * To use this function, you must call before, and in order, + * ecore_x_xinerama_query_screens_prefetch(), which sends the XineramaQueryScreens request, + * then ecore_x_xinerama_query_screens_fetch(), which gets the reply. + * @ingroup Ecore_X_Xinerama_Group + */ +EAPI int +ecore_x_xinerama_screen_geometry_get(int screen, + int *x, + int *y, + int *width, + int *height) +{ +#ifdef ECORE_XCB_XINERAMA + xcb_xinerama_screen_info_iterator_t iter; + xcb_xinerama_query_screens_reply_t *reply; + + reply = _ecore_xcb_reply_get(); + if (!reply) + { + if (x) *x = 0; + if (y) *y = 0; + if (width) *width = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels; + if (height) *height = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_pixels; + + return 0; + } + + iter = xcb_xinerama_query_screens_screen_info_iterator(reply); + for (; iter.rem; screen--, xcb_xinerama_screen_info_next(&iter)) + { + if (screen == 0) + { + if (x) *x = iter.data->x_org; + if (y) *y = iter.data->y_org; + if (width) *width = iter.data->width; + if (height) *height = iter.data->height; + return 1; + } + } +#endif /* ECORE_XCB_XINERAMA */ + + if (x) *x = 0; + if (y) *y = 0; + if (width) *width = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels; + if (height) *height = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_pixels; + + return 0; +}