<commit_before>/*
 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
 */

#include <string.h>

#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_free(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 Ecore_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.
 */<commit_msg>Add xcb_flush right after xcb_unmap_window<commit_after>/*
 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
 */

#include <string.h>

#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_free(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 Ecore_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);
   xcb_flush(_ecore_xcb_conn);
}

/**
 * @defgroup Ecore_X_Window_Input_Focus_Group X Window Input Focus Functions
 *
 * Functions that manage the focus of an X Window.
 */
{'fraction_non_alphanumeric': 0.07144859158219274, 'fraction_numerical': 0.007567618068855982, 'mean_word_length': 1.9029086717743575, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 176, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4497586', 'n_tokens_mistral': 14505, 'n_tokens_neox': 14010, 'n_words': 3115}