#include "ecore_xcb_private.h" #ifdef ECORE_XCB_RENDER # include #endif #ifdef ECORE_XCB_SHAPE # include #endif #ifdef ECORE_XCB_XPRINT #include #endif /* local function prototypes */ static Ecore_X_Window _ecore_xcb_window_argb_internal_new(Ecore_X_Window parent, int x, int y, int w, int h, uint8_t override_redirect, uint8_t save_under); static Ecore_X_Window _ecore_xcb_window_at_xy_get(Ecore_X_Window base, int bx, int by, int x, int y, Ecore_X_Window *skip, int skip_num); static int _ecore_xcb_window_modifiers_get(unsigned int state); static xcb_visualtype_t *_ecore_xcb_window_find_visual_by_id(xcb_visualid_t id); #ifdef ECORE_XCB_XPRINT static xcb_screen_t *_ecore_xcb_window_screen_of_display(int screen); #endif /* local variables */ static int ignore_num = 0; static Ecore_X_Window *ignore_list = NULL; /* external variables */ int _ecore_xcb_button_grabs_num = 0; int _ecore_xcb_key_grabs_num = 0; Ecore_X_Window *_ecore_xcb_button_grabs = NULL; Ecore_X_Window *_ecore_xcb_key_grabs = NULL; Eina_Bool (*_ecore_xcb_window_grab_replay_func)(void *data, int type, void *event); void *_ecore_xcb_window_grab_replay_data; /** * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions * @ingroup Ecore * * 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 w, int h) { Ecore_X_Window win; uint32_t mask, mask_list[9]; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; /* NB: Order here is very important due to xcb_cw_t enum */ 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); mask_list[0] = XCB_BACK_PIXMAP_NONE; mask_list[1] = 0; mask_list[2] = XCB_GRAVITY_NORTH_WEST; mask_list[3] = XCB_GRAVITY_NORTH_WEST; mask_list[4] = XCB_BACKING_STORE_NOT_USEFUL; mask_list[5] = 0; mask_list[6] = 0; mask_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); mask_list[8] = XCB_EVENT_MASK_NO_EVENT; win = xcb_generate_id(_ecore_xcb_conn); xcb_create_window(_ecore_xcb_conn, XCB_COPY_FROM_PARENT, win, parent, x, y, w, h, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, mask, mask_list); if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) ecore_x_window_defaults_set(win); return win; } /** * 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 w, int h) { Ecore_X_Window win; uint32_t mask, mask_list[9]; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; /* NB: Order here is very important due to xcb_cw_t enum */ 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); mask_list[0] = XCB_BACK_PIXMAP_NONE; mask_list[1] = 0; mask_list[2] = XCB_GRAVITY_NORTH_WEST; mask_list[3] = XCB_GRAVITY_NORTH_WEST; mask_list[4] = XCB_BACKING_STORE_NOT_USEFUL; mask_list[5] = 1; mask_list[6] = 0; mask_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); mask_list[8] = XCB_EVENT_MASK_NO_EVENT; win = xcb_generate_id(_ecore_xcb_conn); xcb_create_window(_ecore_xcb_conn, XCB_COPY_FROM_PARENT, win, parent, x, y, w, h, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, mask, mask_list); return win; } /** * 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 w, int h) { Ecore_X_Window win; uint32_t mask, mask_list[3]; LOGFN(__FILE__, __LINE__, __FUNCTION__) CHECK_XCB_CONN; if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; /* NB: Order here is very important due to xcb_cw_t enum */ mask = (XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE); mask_list[0] = 1; mask_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); mask_list[2] = XCB_EVENT_MASK_NO_EVENT; win = xcb_generate_id(_ecore_xcb_conn); xcb_create_window(_ecore_xcb_conn, XCB_COPY_FROM_PARENT, win, parent, x, y, w, h, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, mask, mask_list); return win; } /** * 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_manager_argb_new(Ecore_X_Window parent, int x, int y, int w, int h) { Ecore_X_Window win = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); win = _ecore_xcb_window_argb_internal_new(parent, x, y, w, h, 1, 0); return win; } /** * 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_argb_new(Ecore_X_Window parent, int x, int y, int w, int h) { Ecore_X_Window win = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); win = _ecore_xcb_window_argb_internal_new(parent, x, y, w, h, 0, 0); return win; } /** * 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_argb_new(Ecore_X_Window parent, int x, int y, int w, int h) { Ecore_X_Window win = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); win = _ecore_xcb_window_argb_internal_new(parent, x, y, w, h, 1, 0); return win; } /** * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions * @ingroup Ecore * * Functions to destroy X windows. */ /** * Deletes the given window. * @param win The given window. * @ingroup Ecore_X_Window_Destroy_Group */ EAPI void ecore_x_window_free(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (win) { /* xcb_destroy_notify_event_t ev; */ /* Ecore_X_Window root; */ /* 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 *reply; */ /* cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); */ /* reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); */ /* if (!reply) return; */ /* root = reply->root; */ /* free(reply); */ /* } */ /* memset(&ev, 0, sizeof(xcb_destroy_notify_event_t)); */ /* ev.response_type = XCB_DESTROY_NOTIFY; */ /* ev.window = win; */ /* ev.event = root; */ /* xcb_send_event(_ecore_xcb_conn, 0, root, */ /* XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | */ /* XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, */ /* (const char *)&ev); */ xcb_destroy_window(_ecore_xcb_conn, win); // ecore_x_flush(); } } /** * Sends a delete request to the given window. * @param win The given window. * @ingroup Ecore_X_Window_Destroy_Group */ EAPI void ecore_x_window_delete_request_send(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!win) return; ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, XCB_EVENT_MASK_NO_EVENT, ECORE_X_ATOM_WM_DELETE_WINDOW, XCB_CURRENT_TIME, 0, 0, 0); } EAPI void ecore_x_window_configure(Ecore_X_Window win, Ecore_X_Window_Configure_Mask mask, int x, int y, int w, int h, int border_width, Ecore_X_Window sibling, int stack_mode) { uint16_t vmask = 0; uint32_t vlist[7]; unsigned int i = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) return; if (mask & XCB_CONFIG_WINDOW_X) { vmask |= XCB_CONFIG_WINDOW_X; vlist[i++] = x; } if (mask & XCB_CONFIG_WINDOW_Y) { vmask |= XCB_CONFIG_WINDOW_Y; vlist[i++] = y; } if (mask & XCB_CONFIG_WINDOW_WIDTH) { vmask |= XCB_CONFIG_WINDOW_WIDTH; vlist[i++] = w; } if (mask & XCB_CONFIG_WINDOW_HEIGHT) { vmask |= XCB_CONFIG_WINDOW_HEIGHT; vlist[i++] = h; } if (mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) { vmask |= XCB_CONFIG_WINDOW_BORDER_WIDTH; vlist[i++] = border_width; } if (mask & XCB_CONFIG_WINDOW_SIBLING) { vmask |= XCB_CONFIG_WINDOW_SIBLING; vlist[i++] = sibling; } if (mask & XCB_CONFIG_WINDOW_STACK_MODE) { vmask |= XCB_CONFIG_WINDOW_STACK_MODE; vlist[i++] = stack_mode; } xcb_configure_window(_ecore_xcb_conn, win, vmask, (const uint32_t *)&vlist); // ecore_x_flush(); } /** * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions * @ingroup Ecore * * Functions that change or retrieve the geometry of X windows. */ /** * 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 win The window to move. * @param x X position. * @param y Y position. * @ingroup Ecore_X_Window_Geometry_Group */ EAPI void ecore_x_window_move(Ecore_X_Window win, int x, int y) { uint32_t list[2], mask; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) return; mask = (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y); list[0] = x; list[1] = y; xcb_configure_window(_ecore_xcb_conn, win, mask, (const uint32_t *)&list); // ecore_x_flush(); } /** * Resizes a window. * @param win The window to resize. * @param w New width of the window. * @param h New height of the window. * @ingroup Ecore_X_Window_Geometry_Group */ EAPI void ecore_x_window_resize(Ecore_X_Window win, int w, int h) { uint32_t list[2], mask; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) return; if (w < 1) w = 1; if (h < 1) h = 1; mask = (XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT); list[0] = w; list[1] = h; xcb_configure_window(_ecore_xcb_conn, win, mask, (const uint32_t *)&list); // ecore_x_flush(); } /** * Moves and resizes a window. * @param win The window to move and resize. * @param x New X position of the window. * @param y New Y position of the window. * @param w New width of the window. * @param h New height of the window. * @ingroup Ecore_X_Window_Geometry_Group */ EAPI void ecore_x_window_move_resize(Ecore_X_Window win, int x, int y, int w, int h) { uint32_t list[4], mask; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) return; if (w < 1) w = 1; if (h < 1) h = 1; mask = (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT); list[0] = x; list[1] = y; list[2] = w; list[3] = h; xcb_configure_window(_ecore_xcb_conn, win, mask, (const uint32_t *)&list); // ecore_x_flush(); } /** * 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) { LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!win) return 0; return ecore_x_drawable_border_width_get(win); } /** * Sets the width of the border of the given window. * @param win The given window. * @param width The new border width. * @ingroup Ecore_X_Window_Geometry_Group */ EAPI void ecore_x_window_border_width_set(Ecore_X_Window win, int border_width) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) return; list = border_width; xcb_configure_window(_ecore_xcb_conn, win, XCB_CONFIG_WINDOW_BORDER_WIDTH, &list); // ecore_x_flush(); } /** * @defgroup Ecore_X_Window_Z_Order_Group X Window Z Order Functions * @ingroup Ecore * * Functions that change the Z order of X windows. */ /** * Raises the given window. * @param win The window to raise. * @ingroup Ecore_X_Window_Z_Order_Group */ EAPI void ecore_x_window_raise(Ecore_X_Window win) { uint32_t list[] = { XCB_STACK_MODE_ABOVE }; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; xcb_configure_window(_ecore_xcb_conn, win, XCB_CONFIG_WINDOW_STACK_MODE, list); // ecore_x_flush(); } /** * Lowers the given window. * @param win The window to lower. * @ingroup Ecore_X_Window_Z_Order_Group */ EAPI void ecore_x_window_lower(Ecore_X_Window win) { uint32_t list[] = { XCB_STACK_MODE_BELOW }; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; xcb_configure_window(_ecore_xcb_conn, win, XCB_CONFIG_WINDOW_STACK_MODE, list); // ecore_x_flush(); } /** * 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) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return ecore_x_drawable_depth_get(win); } /** * @defgroup Ecore_X_Window_Properties_Group X Window Property Functions * @ingroup Ecore * * Functions that set 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 win The given window. * @ingroup Ecore_X_Window_Properties_Group */ EAPI void ecore_x_window_defaults_set(Ecore_X_Window win) { char buff[MAXHOSTNAMELEN], **argv; int argc; pid_t pid; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; gethostname(buff, MAXHOSTNAMELEN); buff[MAXHOSTNAMELEN - 1] = '\0'; xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, ECORE_X_ATOM_WM_CLIENT_MACHINE, ECORE_X_ATOM_STRING, 8, strlen(buff), buff); pid = getpid(); ecore_x_netwm_pid_set(win, pid); ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL); ecore_app_args_get(&argc, &argv); ecore_x_icccm_command_set(win, argc, argv); } /** * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions * @ingroup Ecore * * Functions to access and change the visibility of X windows. */ /** * Shows a window. * * Synonymous to "mapping" a window in X Window System terminology. * * @param win The window to show. * @ingroup Ecore_X_Window_Visibility */ EAPI void ecore_x_window_show(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (win) xcb_map_window(_ecore_xcb_conn, win); } /** * Hides a window. * * Synonymous to "unmapping" a window in X Window System terminology. * * @param win The window to hide. * @ingroup Ecore_X_Window_Visibility */ EAPI void ecore_x_window_hide(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (win) { xcb_unmap_notify_event_t ev; Ecore_X_Window root; 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 *reply; cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return; root = reply->root; free(reply); } xcb_unmap_window(_ecore_xcb_conn, win); memset(&ev, 0, sizeof(xcb_unmap_notify_event_t)); ev.response_type = XCB_UNMAP_NOTIFY; ev.window = win; ev.event = root; 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); // ecore_x_flush(); } } /** * @defgroup Ecore_X_Window_Focus_Functions X Window Focus Functions * @ingroup Ecore * * Functions that give the focus to an X Window. */ /** * Sets the focus to the window @p win. * @param win The window to focus. * @ingroup Ecore_X_Window_Focus_Functions */ EAPI void ecore_x_window_focus(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_PARENT, win, XCB_CURRENT_TIME); // ecore_x_flush(); } /** * Sets the focus to the given window at a specific time. * @param win The window to focus. * @param t When to set the focus to the window. * @ingroup Ecore_X_Window_Focus_Functions */ EAPI void ecore_x_window_focus_at_time(Ecore_X_Window win, Ecore_X_Time time EINA_UNUSED) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_PARENT, win, XCB_CURRENT_TIME); // ecore_x_flush(); } /** * @defgroup Ecore_X_Window_Parent_Group X Window Parent Functions * @ingroup Ecore * * Functions that retrieve or changes the parent window of a window. */ /** * Moves a window to within another window at a given position. * @param win 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_Parent_Group */ EAPI void ecore_x_window_reparent(Ecore_X_Window win, Ecore_X_Window parent, int x, int y) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; xcb_reparent_window(_ecore_xcb_conn, win, parent, x, y); // ecore_x_flush(); } EAPI void ecore_x_window_pixmap_set(Ecore_X_Window win, Ecore_X_Pixmap pixmap) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = pixmap; xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_BACK_PIXMAP, &list); // ecore_x_flush(); } /** * Sets the background color of the given window. * @param win The given window * @param r red value (0...65536, 16 bits) * @param g green value (0...65536, 16 bits) * @param b blue value (0...65536, 16 bits) */ EAPI void ecore_x_window_background_color_set(Ecore_X_Window win, unsigned short red, unsigned short green, unsigned short blue) { xcb_alloc_color_cookie_t cookie; xcb_alloc_color_reply_t *reply; uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; cookie = xcb_alloc_color_unchecked(_ecore_xcb_conn, ((xcb_screen_t *)_ecore_xcb_screen)->default_colormap, red, green, blue); reply = xcb_alloc_color_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return; list = reply->pixel; free(reply); xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_BACK_PIXEL, &list); // ecore_x_flush(); } EAPI void ecore_x_window_pixel_gravity_set(Ecore_X_Window win, Ecore_X_Gravity gravity) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = gravity; xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_BIT_GRAVITY, &list); // ecore_x_flush(); } EAPI void ecore_x_window_gravity_set(Ecore_X_Window win, Ecore_X_Gravity gravity) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = gravity; xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_WIN_GRAVITY, &list); // ecore_x_flush(); } EAPI void ecore_x_window_override_set(Ecore_X_Window win, Eina_Bool override) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = override; xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_OVERRIDE_REDIRECT, &list); // ecore_x_flush(); } /** * @brief Show the cursor on a window of type Ecore_X_Window. * @param win The window for which the cursor will be showed. * @param show Enables the show of the cursor on the window if equals EINA_TRUE, disables if equals EINA_FALSE. */ EAPI void ecore_x_window_cursor_show(Ecore_X_Window win, Eina_Bool show) { uint32_t list = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; if (!show) { Ecore_X_Cursor cursor; Ecore_X_Pixmap p, m; Ecore_X_GC gc; xcb_point_t point; p = xcb_generate_id(_ecore_xcb_conn); xcb_create_pixmap(_ecore_xcb_conn, 1, p, win, 1, 1); m = xcb_generate_id(_ecore_xcb_conn); xcb_create_pixmap(_ecore_xcb_conn, 1, m, win, 1, 1); gc = xcb_generate_id(_ecore_xcb_conn); xcb_create_gc(_ecore_xcb_conn, gc, win, 0, NULL); xcb_change_gc(_ecore_xcb_conn, gc, XCB_GC_FOREGROUND, &list); point.x = 0; point.y = 0; xcb_poly_point(_ecore_xcb_conn, XCB_COORD_MODE_ORIGIN, win, gc, 1, &point); xcb_free_gc(_ecore_xcb_conn, gc); cursor = xcb_generate_id(_ecore_xcb_conn); xcb_create_cursor(_ecore_xcb_conn, cursor, p, m, 0, 0, 0, 0, 0, 0, 0, 0); list = cursor; xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_CURSOR, &list); xcb_free_cursor(_ecore_xcb_conn, cursor); xcb_free_pixmap(_ecore_xcb_conn, m); xcb_free_pixmap(_ecore_xcb_conn, p); } else { xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_CURSOR, &list); } // ecore_x_flush(); } EAPI void ecore_x_window_cursor_set(Ecore_X_Window win, Ecore_X_Cursor cursor) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = cursor; xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_CURSOR, &list); // ecore_x_flush(); } EAPI void ecore_x_window_container_manage(Ecore_X_Window win) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY); xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_EVENT_MASK, &list); // ecore_x_flush(); } EAPI void ecore_x_window_client_manage(Ecore_X_Window win) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = (XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_COLOR_MAP_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY); xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_EVENT_MASK, &list); #ifdef ECORE_XCB_SHAPE xcb_shape_select_input(_ecore_xcb_conn, win, EINA_TRUE); #endif // ecore_x_flush(); } EAPI void ecore_x_window_sniff(Ecore_X_Window win) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = (XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE); xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_EVENT_MASK, &list); // ecore_x_flush(); } EAPI void ecore_x_window_client_sniff(Ecore_X_Window win) { uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; list = (XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_COLOR_MAP_CHANGE); xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_EVENT_MASK, &list); #ifdef ECORE_XCB_SHAPE xcb_shape_select_input(_ecore_xcb_conn, win, EINA_TRUE); #endif // ecore_x_flush(); } EAPI void ecore_x_window_area_clear(Ecore_X_Window win, int x, int y, int w, int h) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; xcb_clear_area(_ecore_xcb_conn, 0, win, x, y, w, h); // ecore_x_flush(); } EAPI void ecore_x_window_area_expose(Ecore_X_Window win, int x, int y, int w, int h) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; xcb_clear_area(_ecore_xcb_conn, 1, win, x, y, w, h); // ecore_x_flush(); } EAPI void ecore_x_window_save_set_add(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_INSERT, win); } EAPI void ecore_x_window_save_set_del(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_DELETE, win); } /** * gets the window that has focus. * @return The window that has focus. * @ingroup Ecore_X_Window_Focus_Functions */ EAPI Ecore_X_Window ecore_x_window_focus_get(void) { xcb_get_input_focus_cookie_t cookie; xcb_get_input_focus_reply_t *reply; Ecore_X_Window focus = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; cookie = xcb_get_input_focus_unchecked(_ecore_xcb_conn); reply = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return 0; focus = reply->focus; free(reply); return focus; } EAPI int ecore_x_window_argb_get(Ecore_X_Window win) { uint8_t ret = 0; #ifdef ECORE_XCB_RENDER Ecore_X_Visual visual; #endif LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; // if (!win) return ret; #ifdef ECORE_XCB_RENDER /* grab the window's visual */ visual = _ecore_xcb_window_visual_get(win); /* check if this visual supports alpha */ ret = _ecore_xcb_render_visual_supports_alpha(visual); #endif return ret; } EAPI Eina_Bool ecore_x_window_manage(Ecore_X_Window win) { xcb_get_window_attributes_cookie_t cookie; xcb_get_window_attributes_reply_t *reply; xcb_void_cookie_t change_cookie; xcb_generic_error_t *err; uint32_t list; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; cookie = xcb_get_window_attributes(_ecore_xcb_conn, win); reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return EINA_FALSE; ecore_x_sync(); // needed list = (XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_RESIZE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | reply->your_event_mask); free(reply); change_cookie = xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_EVENT_MASK, &list); ecore_x_sync(); // needed err = xcb_request_check(_ecore_xcb_conn, change_cookie); if (err) { _ecore_xcb_error_handle(err); free(err); return EINA_FALSE; } return EINA_TRUE; } EAPI Eina_Bool ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret) { xcb_get_window_attributes_cookie_t cookie; xcb_get_window_attributes_reply_t *reply; xcb_get_geometry_cookie_t gcookie; xcb_get_geometry_reply_t *greply; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, win); reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return EINA_FALSE; memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes)); if (reply->map_state != XCB_MAP_STATE_UNMAPPED) att_ret->visible = EINA_TRUE; if (reply->map_state == XCB_MAP_STATE_VIEWABLE) att_ret->viewable = EINA_TRUE; if (reply->override_redirect) att_ret->override = EINA_TRUE; if (reply->_class == XCB_WINDOW_CLASS_INPUT_ONLY) att_ret->input_only = EINA_TRUE; if (reply->save_under) att_ret->save_under = EINA_TRUE; 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 = _ecore_xcb_window_find_visual_by_id(reply->visual); free(reply); gcookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); greply = xcb_get_geometry_reply(_ecore_xcb_conn, gcookie, NULL); if (!greply) return EINA_TRUE; /* xcb_translate_coordinates_reply_t *trans; */ /* xcb_query_tree_cookie_t tcookie; */ /* xcb_query_tree_reply_t *treply; */ /* tcookie = xcb_query_tree(_ecore_xcb_conn, win); */ /* treply = xcb_query_tree_reply(_ecore_xcb_conn, tcookie, NULL); */ /* trans = */ /* xcb_translate_coordinates_reply(_ecore_xcb_conn, */ /* xcb_translate_coordinates(_ecore_xcb_conn, */ /* win, treply->parent, greply->x, greply->y), NULL); */ /* free(treply); */ att_ret->root = greply->root; att_ret->depth = greply->depth; // att_ret->x = trans->dst_x; // att_ret->y = trans->dst_y; att_ret->x = greply->x; att_ret->y = greply->y; att_ret->w = greply->width; att_ret->h = greply->height; att_ret->border = greply->border_width; // free(trans); free(greply); return EINA_TRUE; } /** * 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. * @ingroup Ecore_X_Window_Geometry_Group */ EAPI void ecore_x_window_size_get(Ecore_X_Window win, int *width, int *height) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; ecore_x_drawable_geometry_get(win, NULL, NULL, width, height); } /** * Set if a window should be ignored. * @param win The given window. * @param ignore if to ignore */ EAPI void ecore_x_window_ignore_set(Ecore_X_Window win, int ignore) { int i = 0, j = 0, count = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (ignore) { if (ignore_list) { for (i = 0; i < ignore_num; i++) if (win == ignore_list[i]) return; ignore_list = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window)); if (!ignore_list) return; ignore_list[ignore_num++] = win; } else { ignore_num = 0; ignore_list = malloc(sizeof(Ecore_X_Window)); if (!ignore_list) return; ignore_list[ignore_num++] = win; } } else { if (!ignore_list) return; for (count = ignore_num, i = 0, j = 0; i < count; i++) { if (win != ignore_list[i]) ignore_list[j++] = ignore_list[i]; else ignore_num--; } if (ignore_num <= 0) { free(ignore_list); ignore_list = NULL; return; } 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) { LOGFN(__FILE__, __LINE__, __FUNCTION__); if (num) *num = ignore_num; return ignore_list; } /** * 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; uint8_t i, num; Ecore_X_Window *roots = NULL; #ifdef ECORE_XCB_XPRINT const xcb_query_extension_reply_t *ext_reply; #endif LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!num_ret) return NULL; if (num_ret) *num_ret = 0; /* if (xcb_connection_has_error(_ecore_xcb_conn)) */ /* { */ /* DBG("XCB Connection Has Error !!!"); */ /* return NULL; */ /* } */ num = ecore_x_screen_count_get(); #ifdef ECORE_XCB_XPRINT ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_x_print_id); if ((ext_reply) && (ext_reply->present)) { xcb_x_print_print_query_screens_cookie_t cookie; xcb_x_print_print_query_screens_reply_t *reply; cookie = xcb_x_print_print_query_screens_unchecked(_ecore_xcb_conn); reply = xcb_x_print_print_query_screens_reply(_ecore_xcb_conn, cookie, NULL); if (reply) { xcb_window_t *screens; int psnum = 0, overlap = 0, j = 0, k = 0; psnum = xcb_x_print_print_query_screens_roots_length(reply); screens = xcb_x_print_print_query_screens_roots(reply); for (i = 0; i < num; i++) { for (j = 0; j < psnum; j++) { xcb_screen_t *s; if ((s = _ecore_xcb_window_screen_of_display(i))) { if (s->root == screens[j]) overlap++; } } } if (!(roots = malloc((num - overlap) * sizeof(Ecore_X_Window)))) return NULL; for (i = 0; i < num; i++) { Eina_Bool is_print = EINA_FALSE; for (j = 0; j < psnum; j++) { xcb_screen_t *s; if ((s = _ecore_xcb_window_screen_of_display(i))) { if (s->root == screens[j]) { is_print = EINA_TRUE; break; } } } if (!is_print) { xcb_screen_t *s; if ((s = _ecore_xcb_window_screen_of_display(i))) { roots[k] = s->root; k++; } } } if (num_ret) *num_ret = k; free(reply); } else { /* Fallback to default method */ iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); if (!(roots = malloc(num * sizeof(Ecore_X_Window)))) return NULL; if (num_ret) *num_ret = num; for (i = 0; iter.rem; xcb_screen_next(&iter), i++) roots[i] = iter.data->root; } } else { /* Fallback to default method */ iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); if (!(roots = malloc(num * sizeof(Ecore_X_Window)))) return NULL; if (num_ret) *num_ret = num; for (i = 0; iter.rem; xcb_screen_next(&iter), i++) roots[i] = iter.data->root; } #else iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); if (!(roots = malloc(num * sizeof(Ecore_X_Window)))) return NULL; if (num_ret) *num_ret = num; for (i = 0; iter.rem; xcb_screen_next(&iter), i++) roots[i] = iter.data->root; #endif return roots; } EAPI Ecore_X_Window * ecore_x_window_children_get(Ecore_X_Window win, int *num) { xcb_query_tree_cookie_t cookie; xcb_query_tree_reply_t *reply; Ecore_X_Window *windows = NULL; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (num) *num = 0; cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, win); reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return NULL; if (num) *num = reply->children_len; if (reply->children_len > 0) { windows = malloc(sizeof(Ecore_X_Window) * reply->children_len); if (windows) { unsigned int i = 0; xcb_window_t *w; w = xcb_query_tree_children(reply); for (i = 0; i < reply->children_len; i++) windows[i] = w[i]; } } free(reply); return windows; } /** * Retrieves the root window a given window is on. * @param win The window to get the root window of * @return The root window of @p win * @ingroup Ecore_X_Window_Geometry_Group */ EAPI Ecore_X_Window ecore_x_window_root_get(Ecore_X_Window win) { xcb_get_geometry_cookie_t gcookie; xcb_get_geometry_reply_t *greply; Ecore_X_Window window = 0; /* LOGFN(__FILE__, __LINE__, __FUNCTION__); */ CHECK_XCB_CONN; gcookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); greply = xcb_get_geometry_reply(_ecore_xcb_conn, gcookie, NULL); if (!greply) return 0; window = greply->root; free(greply); return window; } EAPI Ecore_X_Window ecore_x_window_root_first_get(void) { return ((xcb_screen_t *)_ecore_xcb_screen)->root; } /** * Retrieves the geometry of the given window. * * Note that the x & y coordingates are relative to your parent. In * particular for reparenting window managers - relative to you window border. * If you want screen coordinates either walk the window tree to the root, * else for ecore_evas applications see ecore_evas_geometry_get(). Elementary * applications can use elm_win_screen_position_get(). * * @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. * @ingroup Ecore_X_Window_Geometry_Group */ EAPI void ecore_x_window_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; ecore_x_drawable_geometry_get(win, x, y, w, h); } /** * 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 root, win = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; root = ((xcb_screen_t *)_ecore_xcb_screen)->root; ecore_x_grab(); win = _ecore_xcb_window_at_xy_get(root, 0, 0, x, y, NULL, 0); ecore_x_ungrab(); return win ? win : 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. * @param skip The list of windows to be skipped. * @param skip_num The number of windows to be skipped. * @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 root, win = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; root = ((xcb_screen_t *)_ecore_xcb_screen)->root; ecore_x_grab(); win = _ecore_xcb_window_at_xy_get(root, 0, 0, x, y, skip, skip_num); ecore_x_ungrab(); return win ? win : root; } EAPI Ecore_X_Window ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y) { Ecore_X_Window win = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; ecore_x_grab(); win = _ecore_xcb_window_at_xy_get(begin, 0, 0, x, y, NULL, 0); ecore_x_ungrab(); return win ? win : begin; } /** * Retrieves the parent window of the given window. * @param win The given window. * @return The parent window of @p win. * @ingroup Ecore_X_Window_Parent_Group */ EAPI Ecore_X_Window ecore_x_window_parent_get(Ecore_X_Window win) { xcb_query_tree_cookie_t cookie; xcb_query_tree_reply_t *reply; Ecore_X_Window window = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; // if (!win) return 0; cookie = xcb_query_tree(_ecore_xcb_conn, win); reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return 0; window = reply->parent; free(reply); return window; } /** * Finds out whether the given window is currently visible. * @param win The given window. * @return 1 if the window is visible, otherwise 0. * @ingroup Ecore_X_Window_Visibility_Group */ EAPI int ecore_x_window_visible_get(Ecore_X_Window win) { xcb_get_window_attributes_cookie_t cookie; xcb_get_window_attributes_reply_t *reply; int ret = EINA_FALSE; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, win); reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return EINA_FALSE; if (reply->map_state == XCB_MAP_STATE_VIEWABLE) ret = EINA_TRUE; free(reply); return ret; } EAPI void ecore_x_window_button_grab(Ecore_X_Window win, int button, Ecore_X_Event_Mask mask, int mod, int any_mod) { int i = 0; uint16_t m, locks[8], ev; uint8_t b; Ecore_X_Window *t; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; b = button; if (b == 0) b = XCB_BUTTON_INDEX_ANY; m = _ecore_xcb_window_modifiers_get(mod); if (any_mod) m = XCB_MOD_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 = mask; for (i = 0; i < 8; i++) xcb_grab_button(_ecore_xcb_conn, 0, win, ev, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, b, m | locks[i]); _ecore_xcb_button_grabs_num++; t = realloc(_ecore_xcb_button_grabs, _ecore_xcb_button_grabs_num * sizeof(Ecore_X_Window)); if (!t) return; _ecore_xcb_button_grabs = t; _ecore_xcb_button_grabs[_ecore_xcb_button_grabs_num - 1] = win; } EAPI void ecore_x_window_button_ungrab(Ecore_X_Window win, int button, int mod, int any_mod) { int i = 0; uint16_t m = 0, locks[8]; uint8_t b; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; b = button; if (b == 0) b = XCB_BUTTON_INDEX_ANY; m = _ecore_xcb_window_modifiers_get(mod); if (any_mod) m = XCB_MOD_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, b, win, m | locks[i]); _ecore_xcb_sync_magic_send(1, win); } EAPI void ecore_x_window_key_grab(Ecore_X_Window win, const char *key, int mod, int any_mod) { xcb_keycode_t keycode = XCB_NO_SYMBOL; uint16_t m = 0, locks[8]; int i = 0; Ecore_X_Window *t; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; keycode = _ecore_xcb_keymap_string_to_keycode(key); if (keycode == XCB_NO_SYMBOL) return; m = _ecore_xcb_window_modifiers_get(mod); if (any_mod) m = XCB_MOD_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, 0, win, m | locks[i], keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); _ecore_xcb_key_grabs_num++; t = realloc(_ecore_xcb_key_grabs, _ecore_xcb_key_grabs_num * sizeof(Ecore_X_Window)); if (!t) return; _ecore_xcb_key_grabs = t; _ecore_xcb_key_grabs[_ecore_xcb_key_grabs_num - 1] = win; } EAPI void ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key, int mod, int any_mod) { xcb_keycode_t keycode = XCB_NO_SYMBOL; uint16_t m = 0, locks[8]; int i = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; keycode = _ecore_xcb_keymap_string_to_keycode(key); if (keycode == XCB_NO_SYMBOL) return; m = _ecore_xcb_window_modifiers_get(mod); if (any_mod) m = XCB_MOD_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, win, m | locks[i]); _ecore_xcb_sync_magic_send(2, win); } /* local functions */ Ecore_X_Window _ecore_xcb_window_root_of_screen_get(int screen) { xcb_screen_iterator_t iter; CHECK_XCB_CONN; iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); for (; iter.rem; --screen, xcb_screen_next(&iter)) if (screen == 0) { xcb_screen_t *s; if ((s = iter.data)) return s->root; } return 0; } static Ecore_X_Window _ecore_xcb_window_argb_internal_new(Ecore_X_Window parent, int x, int y, int w, int h, uint8_t override_redirect, uint8_t save_under) { Ecore_X_Window win = 0; #ifdef ECORE_XCB_RENDER uint32_t value_list[10]; uint32_t value_mask; uint32_t vis; Ecore_X_Colormap colormap; #endif LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; #ifdef ECORE_XCB_RENDER if (parent == 0) parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; vis = _ecore_xcb_render_find_visual_id(XCB_RENDER_PICT_TYPE_DIRECT, EINA_TRUE); colormap = xcb_generate_id(_ecore_xcb_conn); xcb_create_colormap(_ecore_xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap, parent, 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_BACK_PIXMAP_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, 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); #endif return win; } static Ecore_X_Window _ecore_xcb_window_at_xy_get(Ecore_X_Window base, int bx, int by, int x, int y, Ecore_X_Window *skip, int skip_num) { xcb_query_tree_cookie_t cookie; xcb_query_tree_reply_t *reply; Ecore_X_Window *windows = NULL; int wx, wy, ww, wh, num, i = 0; Eina_Bool skipit = EINA_FALSE; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (!ecore_x_window_visible_get(base)) return 0; ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh); wx += bx; wy += by; if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh)))) return 0; cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, base); reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return 0; num = reply->children_len; windows = xcb_query_tree_children(reply); for (i = (num - 1); i >= 0; --i) { skipit = EINA_FALSE; if (skip) { int j = 0; for (j = 0; j < skip_num; j++) { if (windows[i] == skip[j]) { skipit = EINA_TRUE; goto onward; } } } onward: if (!skipit) { Ecore_X_Window child = 0; child = _ecore_xcb_window_at_xy_get(windows[i], wx, wy, x, y, skip, skip_num); if (child) { if (reply) free(reply); return child; } } } if (reply) free(reply); return base; } Ecore_X_Visual _ecore_xcb_window_visual_get(Ecore_X_Window win) { xcb_get_window_attributes_cookie_t cookie; xcb_get_window_attributes_reply_t *reply; Ecore_X_Visual visual = 0; CHECK_XCB_CONN; cookie = xcb_get_window_attributes(_ecore_xcb_conn, win); reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); if (!reply) return 0; visual = _ecore_xcb_window_find_visual_by_id(reply->visual); free(reply); return visual; } void _ecore_xcb_window_button_grab_remove(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (_ecore_xcb_button_grabs_num > 0) { int i = 0, shuffle = 0; for (i = 0; i < _ecore_xcb_button_grabs_num; i++) { if (shuffle) _ecore_xcb_button_grabs[i - 1] = _ecore_xcb_button_grabs[i]; if ((!shuffle) && (_ecore_xcb_button_grabs[i] == win)) shuffle = 1; } if (shuffle) { Ecore_X_Window *t; _ecore_xcb_button_grabs_num--; if (_ecore_xcb_button_grabs_num <= 0) { free(_ecore_xcb_button_grabs); _ecore_xcb_button_grabs = NULL; return; } t = realloc(_ecore_xcb_button_grabs, _ecore_xcb_button_grabs_num * sizeof(Ecore_X_Window)); if (!t) return; _ecore_xcb_button_grabs = t; } } } void _ecore_xcb_window_key_grab_remove(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; if (_ecore_xcb_key_grabs_num > 0) { int i = 0, shuffle = 0; for (i = 0; i < _ecore_xcb_key_grabs_num; i++) { if (shuffle) _ecore_xcb_key_grabs[i - 1] = _ecore_xcb_key_grabs[i]; if ((!shuffle) && (_ecore_xcb_key_grabs[i] == win)) shuffle = 1; } if (shuffle) { Ecore_X_Window *t; _ecore_xcb_key_grabs_num--; if (_ecore_xcb_key_grabs_num <= 0) { free(_ecore_xcb_key_grabs); _ecore_xcb_key_grabs = NULL; return; } t = realloc(_ecore_xcb_key_grabs, _ecore_xcb_key_grabs_num * sizeof(Ecore_X_Window)); if (!t) return; _ecore_xcb_key_grabs = t; } } } void _ecore_xcb_window_grab_allow_events(Ecore_X_Window event_win, Ecore_X_Window child_win, int type, void *event, Ecore_X_Time timestamp) { int i = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); CHECK_XCB_CONN; for (i = 0; i < _ecore_xcb_button_grabs_num; i++) { if ((_ecore_xcb_button_grabs[i] == event_win) || (_ecore_xcb_button_grabs[i] == child_win)) { Eina_Bool replay = EINA_FALSE; if (_ecore_xcb_window_grab_replay_func) { replay = _ecore_xcb_window_grab_replay_func(_ecore_xcb_window_grab_replay_data, type, event); } if (replay) { xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_REPLAY_POINTER, timestamp); } else { xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_POINTER, timestamp); } break; } } } static int _ecore_xcb_window_modifiers_get(unsigned int state) { int xmodifiers = 0; if (state & ECORE_EVENT_MODIFIER_SHIFT) xmodifiers |= ECORE_X_MODIFIER_SHIFT; if (state & ECORE_EVENT_MODIFIER_CTRL) xmodifiers |= ECORE_X_MODIFIER_CTRL; if (state & ECORE_EVENT_MODIFIER_ALT) xmodifiers |= ECORE_X_MODIFIER_ALT; if (state & ECORE_EVENT_MODIFIER_WIN) xmodifiers |= ECORE_X_MODIFIER_WIN; if (state & ECORE_EVENT_MODIFIER_ALTGR) xmodifiers |= ECORE_X_MODIFIER_ALTGR; if (state & ECORE_EVENT_LOCK_SCROLL) xmodifiers |= ECORE_X_LOCK_SCROLL; if (state & ECORE_EVENT_LOCK_NUM) xmodifiers |= ECORE_X_LOCK_NUM; if (state & ECORE_EVENT_LOCK_CAPS) xmodifiers |= ECORE_X_LOCK_CAPS; if (state & ECORE_EVENT_LOCK_SHIFT) xmodifiers |= ECORE_X_LOCK_SHIFT; return xmodifiers; } static xcb_visualtype_t * _ecore_xcb_window_find_visual_by_id(xcb_visualid_t id) { xcb_depth_iterator_t diter; xcb_visualtype_iterator_t viter; CHECK_XCB_CONN; diter = xcb_screen_allowed_depths_iterator(_ecore_xcb_screen); for (; diter.rem; xcb_depth_next(&diter)) { viter = xcb_depth_visuals_iterator(diter.data); for (; viter.rem; xcb_visualtype_next(&viter)) { if (viter.data->visual_id == id) return viter.data; } } return 0; } #ifdef ECORE_XCB_XPRINT static xcb_screen_t * _ecore_xcb_window_screen_of_display(int screen) { xcb_screen_iterator_t iter; CHECK_XCB_CONN; iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); for (; iter.rem; --screen, xcb_screen_next(&iter)) if (screen == 0) return iter.data; return NULL; } #endif