From 61543a8933ea8870cc8add946fc73534866f2e6d Mon Sep 17 00:00:00 2001 From: doursse Date: Fri, 13 Apr 2007 17:15:19 +0000 Subject: [PATCH] Here is ecore_x with XCB backend. * The XCB backend is disabled by default during the configuration. To enable it, add --enable-ecore-x-xcb. See the messages that configure displays when it finishes. * The way XCB is detected, and used in src/lib/ecore_x/Makefile.am should be improved * Any program that uses ecore_evas does not need to be modified. Any program that uses ecore_x may need some changes. That is, adding some functions (_prefetch and _fetch ones). No other change is needed. See the documention of any _get functions, as these are the ones that need those functions. * There are some missing parts, especially everything that involves the keyboard, as porting Xlib functions related to strings (utf8 stuff, XKeysymToString, etc...) is an horror. So keyboard events are not working yet. * I tried to write as much documentation as I could. But there is certainly some missing doc here and there. there are certainly other things that I have forgotten. Improvements of that backend: * the creation of an ecore_evas is faster. Especially when done over an ssh connection (on my computer, 7-10s with Xlib, 1.5s with XCB, over an ssh) * A Window Manager should be more responsive. But it's not tomorrow that e17 will use it :) Have fun ! SVN revision: 29500 --- legacy/ecore/configure.in | 91 +- legacy/ecore/src/lib/ecore_evas/Makefile.am | 6 +- .../src/lib/ecore_evas/ecore_evas_private.h | 41 +- .../ecore/src/lib/ecore_evas/ecore_evas_x.c | 810 ++++- legacy/ecore/src/lib/ecore_x/Ecore_X.h | 143 +- legacy/ecore/src/lib/ecore_x/Makefile.am | 75 + legacy/ecore/src/lib/ecore_x/ecore_xcb.c | 1824 ++++++++++ legacy/ecore/src/lib/ecore_x/ecore_xcb_atom.c | 607 ++++ .../ecore/src/lib/ecore_x/ecore_xcb_cursor.c | 270 ++ .../ecore/src/lib/ecore_x/ecore_xcb_damage.c | 138 + legacy/ecore/src/lib/ecore_x/ecore_xcb_dnd.c | 749 ++++ legacy/ecore/src/lib/ecore_x/ecore_xcb_dpms.c | 451 +++ .../src/lib/ecore_x/ecore_xcb_drawable.c | 129 + legacy/ecore/src/lib/ecore_x/ecore_xcb_e.c | 29 + .../ecore/src/lib/ecore_x/ecore_xcb_events.c | 2063 +++++++++++ .../ecore/src/lib/ecore_x/ecore_xcb_fixes.c | 581 +++ legacy/ecore/src/lib/ecore_x/ecore_xcb_gc.c | 45 + .../ecore/src/lib/ecore_x/ecore_xcb_icccm.c | 1923 ++++++++++ legacy/ecore/src/lib/ecore_x/ecore_xcb_mwm.c | 149 + .../ecore/src/lib/ecore_x/ecore_xcb_netwm.c | 3197 +++++++++++++++++ .../ecore/src/lib/ecore_x/ecore_xcb_pixmap.c | 117 + .../ecore/src/lib/ecore_x/ecore_xcb_private.h | 310 ++ .../ecore/src/lib/ecore_x/ecore_xcb_randr.c | 544 +++ .../ecore/src/lib/ecore_x/ecore_xcb_reply.c | 131 + .../src/lib/ecore_x/ecore_xcb_screensaver.c | 372 ++ .../src/lib/ecore_x/ecore_xcb_selection.c | 1062 ++++++ .../ecore/src/lib/ecore_x/ecore_xcb_shape.c | 290 ++ legacy/ecore/src/lib/ecore_x/ecore_xcb_sync.c | 135 + .../ecore/src/lib/ecore_x/ecore_xcb_window.c | 2028 +++++++++++ .../src/lib/ecore_x/ecore_xcb_window_prop.c | 871 +++++ .../src/lib/ecore_x/ecore_xcb_xinerama.c | 197 + 31 files changed, 19155 insertions(+), 223 deletions(-) create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_atom.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_cursor.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_damage.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_dnd.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_dpms.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_drawable.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_e.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_events.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_fixes.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_gc.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_icccm.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_mwm.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_netwm.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_pixmap.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_private.h create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_randr.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_reply.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_screensaver.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_selection.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_shape.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_sync.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_window.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_window_prop.c create mode 100644 legacy/ecore/src/lib/ecore_x/ecore_xcb_xinerama.c 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; +}