efl/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_window.c

1603 lines
44 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* ifdef HAVE_CONFIG_H */
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include "Ecore.h"
#include "ecore_x_private.h"
#include "Ecore_X.h"
#include "Ecore_X_Atoms.h"
static int ignore_num = 0;
static Ecore_X_Window *ignore_list = NULL;
/**
* @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 w, int h)
{
Window win;
XSetWindowAttributes attr;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (parent == 0)
parent = DefaultRootWindow(_ecore_x_disp);
attr.backing_store = NotUseful;
attr.override_redirect = False;
attr.border_pixel = 0;
attr.background_pixmap = None;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = False;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(_ecore_x_disp, parent,
x, y, w, h, 0,
CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
InputOutput,
CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
CWBackingStore |
CWOverrideRedirect |
/* CWColormap | */
CWBorderPixel |
CWBackPixmap |
CWSaveUnder |
CWDontPropagate |
CWEventMask |
CWBitGravity |
CWWinGravity,
&attr);
if (parent == DefaultRootWindow(_ecore_x_disp))
ecore_x_window_defaults_set(win);
return win;
} /* ecore_x_window_new */
/**
* 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)
{
Window win;
XSetWindowAttributes attr;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (parent == 0)
parent = DefaultRootWindow(_ecore_x_disp);
attr.backing_store = NotUseful;
attr.override_redirect = True;
attr.border_pixel = 0;
attr.background_pixmap = None;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = False;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(_ecore_x_disp, parent,
x, y, w, h, 0,
CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
InputOutput,
CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
CWBackingStore |
CWOverrideRedirect |
/* CWColormap | */
CWBorderPixel |
CWBackPixmap |
CWSaveUnder |
CWDontPropagate |
CWEventMask |
CWBitGravity |
CWWinGravity,
&attr);
return win;
} /* ecore_x_window_override_new */
/**
* 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)
{
Window win;
XSetWindowAttributes attr;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (parent == 0)
parent = DefaultRootWindow(_ecore_x_disp);
attr.override_redirect = True;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(_ecore_x_disp, parent,
x, y, w, h, 0,
CopyFromParent,
InputOnly,
CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/
CWOverrideRedirect |
CWDontPropagate |
CWEventMask,
&attr);
if (parent == DefaultRootWindow(_ecore_x_disp))
{
}
return win;
} /* ecore_x_window_input_new */
/**
* @defgroup Ecore_X_Window_Properties_Group X Window Property Functions
*
* 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_Groups
*/
EAPI void
ecore_x_window_defaults_set(Ecore_X_Window win)
{
long pid;
char buf[MAXHOSTNAMELEN];
char *hostname[1];
int argc;
char **argv;
XTextProperty xprop;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/*
* Set WM_CLIENT_MACHINE.
*/
gethostname(buf, MAXHOSTNAMELEN);
buf[MAXHOSTNAMELEN - 1] = '\0';
hostname[0] = buf;
/* The ecore function uses UTF8 which Xlib may not like (especially
* with older clients) */
/* ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE,
(char *)buf); */
if (XStringListToTextProperty(hostname, 1, &xprop))
{
XSetWMClientMachine(_ecore_x_disp, win, &xprop);
XFree(xprop.value);
}
/*
* Set _NET_WM_PID
*/
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);
} /* ecore_x_window_defaults_set */
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)
{
XWindowChanges xwc;
if (!win)
return;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
xwc.x = x;
xwc.y = y;
xwc.width = w;
xwc.height = h;
xwc.border_width = border_width;
xwc.sibling = sibling;
xwc.stack_mode = stack_mode;
XConfigureWindow(_ecore_x_disp, win, mask, &xwc);
} /* ecore_x_window_configure */
/**
* @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions
*
* 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)
{
/* sorry sir, deleting the root window doesn't sound like
* a smart idea.
*/
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (win)
XDestroyWindow(_ecore_x_disp, win);
} /* ecore_x_window_free */
/**
* 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, j;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
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));
ignore_list[ignore_num++] = win;
}
}
else
{
if (!ignore_list)
return;
for (i = 0, j = 0; i < ignore_num; i++)
{
if (win != ignore_list[i])
ignore_list[i] = ignore_list[j++];
else
ignore_num--;
}
ignore_list = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window));
}
} /* ecore_x_window_ignore_set */
/**
* Get the ignore list
* @param num number of windows in the list
* @return list of windows to ignore
*/
EAPI Ecore_X_Window *
ecore_x_window_ignore_list(int *num)
{
if (num)
*num = ignore_num;
return ignore_list;
} /* ecore_x_window_ignore_list */
/**
* 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)
{
XEvent xev;
/* sorry sir, deleting the root window doesn't sound like
* a smart idea.
*/
if (!win)
return;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
xev.xclient.type = ClientMessage;
xev.xclient.display = _ecore_x_disp;
xev.xclient.window = win;
xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS;
xev.xclient.format = 32;
xev.xclient.data.l[0] = ECORE_X_ATOM_WM_DELETE_WINDOW;
xev.xclient.data.l[1] = CurrentTime;
XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
} /* ecore_x_window_delete_request_send */
/**
* @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions
*
* 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__);
XMapWindow(_ecore_x_disp, win);
} /* ecore_x_window_show */
/**
* 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)
{
XEvent xev;
Window root;
int idum;
unsigned int uidum;
/* ICCCM: SEND unmap event... */
LOGFN(__FILE__, __LINE__, __FUNCTION__);
root = win;
if (ScreenCount(_ecore_x_disp) == 1)
root = DefaultRootWindow(_ecore_x_disp);
else
XGetGeometry(_ecore_x_disp,
win,
&root,
&idum,
&idum,
&uidum,
&uidum,
&uidum,
&uidum);
xev.xunmap.type = UnmapNotify;
xev.xunmap.serial = 0;
xev.xunmap.send_event = True;
xev.xunmap.display = _ecore_x_disp;
xev.xunmap.event = root;
xev.xunmap.window = win;
xev.xunmap.from_configure = False;
XSendEvent(_ecore_x_disp, xev.xunmap.event, False,
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
XUnmapWindow(_ecore_x_disp, win);
} /* ecore_x_window_hide */
/**
* @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions
*
* 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)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
XMoveWindow(_ecore_x_disp, win, x, y);
} /* ecore_x_window_move */
/**
* 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)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (w < 1)
w = 1;
if (h < 1)
h = 1;
XResizeWindow(_ecore_x_disp, win, w, h);
} /* ecore_x_window_resize */
/**
* 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)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (w < 1)
w = 1;
if (h < 1)
h = 1;
XMoveResizeWindow(_ecore_x_disp, win, x, y, w, h);
} /* ecore_x_window_move_resize */
/**
* @defgroup Ecore_X_Window_Focus_Functions X Window Focus Functions
*
* 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__);
if (win == 0)
win = DefaultRootWindow(_ecore_x_disp); // XSetInputFocus(_ecore_x_disp, win, RevertToNone, CurrentTime);
// XSetInputFocus(_ecore_x_disp, win, RevertToPointerRoot, CurrentTime);
XSetInputFocus(_ecore_x_disp, win, RevertToParent, CurrentTime);
} /* ecore_x_window_focus */
/**
* 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 t)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (win == 0)
win = DefaultRootWindow(_ecore_x_disp); // XSetInputFocus(_ecore_x_disp, win, RevertToNone, t);
// XSetInputFocus(_ecore_x_disp, win, PointerRoot, t);
XSetInputFocus(_ecore_x_disp, win, RevertToParent, t);
} /* ecore_x_window_focus_at_time */
/**
* gets the focus to the window @p win.
* @return The window that has focus.
* @ingroup Ecore_X_Window_Focus_Functions
*/
EAPI Ecore_X_Window
ecore_x_window_focus_get(void)
{
Window win;
int revert_mode;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
win = 0;
XGetInputFocus(_ecore_x_disp, &win, &revert_mode);
return win;
} /* ecore_x_window_focus_get */
/**
* @defgroup Ecore_X_Window_Z_Order_Group X Window Z Order Functions
*
* 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)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
XRaiseWindow(_ecore_x_disp, win);
} /* ecore_x_window_raise */
/**
* 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)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
XLowerWindow(_ecore_x_disp, win);
} /* ecore_x_window_lower */
/**
* @defgroup Ecore_X_Window_Parent_Group X Window Parent Functions
*
* 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 new_parent,
int x,
int y)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (new_parent == 0)
new_parent = DefaultRootWindow(_ecore_x_disp);
XReparentWindow(_ecore_x_disp, win, new_parent, x, y);
} /* ecore_x_window_reparent */
/**
* 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 *w, int *h)
{
int dummy_x, dummy_y;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (win == 0)
win = DefaultRootWindow(_ecore_x_disp);
ecore_x_drawable_geometry_get(win, &dummy_x, &dummy_y, w, h);
} /* ecore_x_window_size_get */
/**
* Retrieves the geometry of the given window.
* @param win The given window.
* @param x Pointer to an integer in which the X position is to be stored.
* @param y Pointer to an integer in which the Y position is to be stored.
* @param w Pointer to an integer in which the width is to be stored.
* @param h Pointer to an integer in which the height is to be stored.
* @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__);
if (!win)
win = DefaultRootWindow(_ecore_x_disp);
ecore_x_drawable_geometry_get(win, x, y, w, h);
} /* ecore_x_window_geometry_get */
/**
* 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__);
/* doesn't make sense to call this on a root window */
if (!win)
return 0;
return ecore_x_drawable_border_width_get(win);
} /* ecore_x_window_border_width_get */
/**
* 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 width)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* doesn't make sense to call this on a root window */
if (!win)
return;
XSetWindowBorderWidth (_ecore_x_disp, win, width);
} /* ecore_x_window_border_width_set */
/**
* 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);
} /* ecore_x_window_depth_get */
/**
* To be documented.
*
* FIXME: To be fixed.
*/
EAPI void
ecore_x_window_cursor_show(Ecore_X_Window win, int show)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (win == 0)
win = DefaultRootWindow(_ecore_x_disp);
if (!show)
{
Cursor c;
XColor cl;
Pixmap p, m;
GC gc;
XGCValues gcv;
p = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
m = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1);
gc = XCreateGC(_ecore_x_disp, m, 0, &gcv);
XSetForeground(_ecore_x_disp, gc, 0);
XDrawPoint(_ecore_x_disp, m, gc, 0, 0);
XFreeGC(_ecore_x_disp, gc);
c = XCreatePixmapCursor(_ecore_x_disp, p, m, &cl, &cl, 0, 0);
XDefineCursor(_ecore_x_disp, win, c);
XFreeCursor(_ecore_x_disp, c);
XFreePixmap(_ecore_x_disp, p);
XFreePixmap(_ecore_x_disp, m);
}
else
XDefineCursor(_ecore_x_disp, win, 0);
} /* ecore_x_window_cursor_show */
EAPI void
ecore_x_window_cursor_set(Ecore_X_Window win, Ecore_X_Cursor c)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (c == 0)
XUndefineCursor(_ecore_x_disp, win);
else
XDefineCursor(_ecore_x_disp, win, c);
} /* ecore_x_window_cursor_set */
/**
* 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)
{
XWindowAttributes attr;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
return (XGetWindowAttributes(_ecore_x_disp, win, &attr) &&
(attr.map_state == IsViewable));
} /* ecore_x_window_visible_get */
typedef struct _Shadow Shadow;
struct _Shadow
{
Shadow *parent;
Shadow **children;
Window win;
int children_num;
short x, y;
unsigned short w, h;
};
static Shadow **shadow_base = NULL;
static int shadow_num = 0;
static Shadow *
_ecore_x_window_tree_walk(Window win)
{
Window *list = NULL;
Window parent_win = 0, root_win = 0;
unsigned int num;
Shadow *s, **sl;
XWindowAttributes att;
if (!XGetWindowAttributes(_ecore_x_disp, win, &att))
return NULL; // if (att.class == InputOnly) return NULL;
if (att.map_state != IsViewable)
return NULL;
s = calloc(1, sizeof(Shadow));
if (!s)
return NULL;
s->win = win;
s->x = att.x;
s->y = att.y;
s->w = att.width;
s->h = att.height;
if (XQueryTree(_ecore_x_disp, s->win, &root_win, &parent_win,
&list, &num))
{
s->children = calloc(1, sizeof(Shadow *) * num);
if (s->children)
{
size_t i, j;
s->children_num = num;
for (i = 0; i < num; i++)
{
s->children[i] = _ecore_x_window_tree_walk(list[i]);
if (s->children[i])
s->children[i]->parent = s;
}
/* compress list down */
j = 0;
for (i = 0; i < num; i++)
{
if (s->children[i])
{
s->children[j] = s->children[i];
j++;
}
}
if (j == 0)
{
free(s->children);
s->children = NULL;
s->children_num = 0;
}
else
{
s->children_num = j;
sl = realloc(s->children, sizeof(Shadow *) * j);
if (sl)
s->children = sl;
}
}
}
if (list)
XFree(list);
return s;
} /* _ecore_x_window_tree_walk */
static void
_ecore_x_window_tree_shadow_free1(Shadow *s)
{
int i;
if (!s)
return;
if (s->children)
{
for (i = 0; i < s->children_num; i++)
{
if (s->children[i])
_ecore_x_window_tree_shadow_free1(s->children[i]);
}
free(s->children);
}
free(s);
} /* _ecore_x_window_tree_shadow_free1 */
static void
_ecore_x_window_tree_shadow_free(void)
{
int i;
if (!shadow_base)
return;
for (i = 0; i < shadow_num; i++)
{
if (!shadow_base[i])
continue;
_ecore_x_window_tree_shadow_free1(shadow_base[i]);
}
free(shadow_base);
shadow_base = NULL;
shadow_num = 0;
} /* _ecore_x_window_tree_shadow_free */
static void
_ecore_x_window_tree_shadow_populate(void)
{
Ecore_X_Window *roots;
int i, num;
roots = ecore_x_window_root_list(&num);
if (roots)
{
shadow_base = calloc(1, sizeof(Shadow *) * num);
if (shadow_base)
{
shadow_num = num;
for (i = 0; i < num; i++)
shadow_base[i] = _ecore_x_window_tree_walk(roots[i]);
}
free(roots);
}
} /* _ecore_x_window_tree_shadow_populate */
/*
static int shadow_count = 0;
static void
_ecore_x_window_tree_shadow_start(void)
{
shadow_count++;
if (shadow_count > 1) return;
_ecore_x_window_tree_shadow_populate();
}
static void
_ecore_x_window_tree_shadow_stop(void)
{
shadow_count--;
if (shadow_count != 0) return;
_ecore_x_window_tree_shadow_free();
}
*/
static Shadow *
_ecore_x_window_shadow_tree_find_shadow(Shadow *s, Window win)
{
Shadow *ss;
int i;
if (s->win == win)
return s;
if (s->children)
for (i = 0; i < s->children_num; i++)
{
if (!s->children[i])
continue;
if ((ss =
_ecore_x_window_shadow_tree_find_shadow(s->children[i], win)))
return ss;
}
return NULL;
} /* _ecore_x_window_shadow_tree_find_shadow */
static Shadow *
_ecore_x_window_shadow_tree_find(Window base)
{
Shadow *s;
int i;
for (i = 0; i < shadow_num; i++)
{
if (!shadow_base[i])
continue;
if ((s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base)))
return s;
}
return NULL;
} /* _ecore_x_window_shadow_tree_find */
static Window
_ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s,
int bx,
int by,
int x,
int y,
Ecore_X_Window *skip,
int skip_num)
{
Window child;
int i, j;
int wx, wy;
wx = s->x + bx;
wy = s->y + by;
if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h))))
return 0;
if (s->children)
{
int skipit = 0;
for (i = s->children_num - 1; i >= 0; --i)
{
if (!s->children[i])
continue;
skipit = 0;
if (skip)
for (j = 0; j < skip_num; j++)
{
if (s->children[i]->win == skip[j])
{
skipit = 1;
goto onward;
}
}
onward:
if (!skipit)
if ((child =
_ecore_x_window_shadow_tree_at_xy_get_shadow(s->
children[i
], wx, wy,
x, y, skip,
skip_num)))
return child;
}
}
return s->win;
} /* _ecore_x_window_shadow_tree_at_xy_get_shadow */
static Window
_ecore_x_window_shadow_tree_at_xy_get(Window base, int bx, int by, int x, int y,
Ecore_X_Window *skip, int skip_num)
{
Shadow *s;
if (!shadow_base)
{
_ecore_x_window_tree_shadow_populate();
if (!shadow_base)
return 0;
}
s = _ecore_x_window_shadow_tree_find(base);
if (!s)
return 0;
return _ecore_x_window_shadow_tree_at_xy_get_shadow(s,
bx,
by,
x,
y,
skip,
skip_num);
} /* _ecore_x_window_shadow_tree_at_xy_get */
/**
* Retrieves the top, visible window at the given location,
* but skips the windows in the list. This uses a shadow tree built from the
* window tree that is only updated the first time
* ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time
* it is called after a ecore_x_window_shadow_tree_flush()
* @param base The base window to start searching from (normally root).
* @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_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base,
int x,
int y,
Ecore_X_Window *skip,
int skip_num)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
return _ecore_x_window_shadow_tree_at_xy_get(base,
0,
0,
x,
y,
skip,
skip_num);
} /* ecore_x_window_shadow_tree_at_xy_with_skip_get */
/**
* Retrieves the parent window a given window has. This uses the shadow window
* tree.
* @param root The root window of @p win - if 0, this will be automatically determined with extra processing overhead
* @param win The window to get the parent window of
* @return The parent window of @p win
* @ingroup Ecore_X_Window_Geometry_Group
*/
EAPI Ecore_X_Window
ecore_x_window_shadow_parent_get(Ecore_X_Window root __UNUSED__,
Ecore_X_Window win)
{
Shadow *s;
int i;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!shadow_base)
{
_ecore_x_window_tree_shadow_populate();
if (!shadow_base)
return 0;
}
for (i = 0; i < shadow_num; i++)
{
if (!shadow_base[i])
continue;
s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win);
if (s)
{
if (!s->parent)
return 0;
return s->parent->win;
}
}
return 0;
} /* ecore_x_window_shadow_parent_get */
/**
* Flushes the window shadow tree so nothing is stored.
* @ingroup Ecore_X_Window_Geometry_Group
*/
EAPI void
ecore_x_window_shadow_tree_flush(void)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
_ecore_x_window_tree_shadow_free();
} /* ecore_x_window_shadow_tree_flush */
/**
* 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)
{
XWindowAttributes att;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!XGetWindowAttributes(_ecore_x_disp, win, &att))
return 0;
return att.root;
} /* ecore_x_window_root_get */
static Window
_ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y,
Ecore_X_Window *skip, int skip_num)
{
Window *list = NULL;
Window parent_win = 0, child = 0, root_win = 0;
int i, j, wx, wy, ww, wh;
unsigned int num;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!ecore_x_window_visible_get(base))
return 0;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
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;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num))
return base;
if (list)
{
int skipit = 0;
for (i = num - 1; i >= 0; --i)
{
skipit = 0;
if (skip)
for (j = 0; j < skip_num; j++)
{
if (list[i] == skip[j])
{
skipit = 1;
goto onward;
}
}
onward:
if (!skipit)
if ((child =
_ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip,
skip_num)))
{
XFree(list);
return child;
}
}
XFree(list);
}
return base;
} /* _ecore_x_window_at_xy_get */
/**
* 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 win, root;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* FIXME: Proper function to determine current root/virtual root
* window missing here */
root = DefaultRootWindow(_ecore_x_disp);
ecore_x_grab();
win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0);
ecore_x_ungrab();
return win ? win : root;
} /* ecore_x_window_at_xy_get */
/**
* Retrieves the top, visible window at the given location,
* but skips the windows in the list.
* @param x The given X position.
* @param y The given Y position.
* @return The window at that position.
* @ingroup Ecore_X_Window_Geometry_Group
*/
EAPI Ecore_X_Window
ecore_x_window_at_xy_with_skip_get(int x,
int y,
Ecore_X_Window *skip,
int skip_num)
{
Ecore_X_Window win, root;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
/* FIXME: Proper function to determine current root/virtual root
* window missing here */
root = DefaultRootWindow(_ecore_x_disp);
ecore_x_grab();
win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num);
ecore_x_ungrab();
return win ? win : root;
} /* ecore_x_window_at_xy_with_skip_get */
EAPI Ecore_X_Window
ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y)
{
Ecore_X_Window win;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
ecore_x_grab();
win = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0);
ecore_x_ungrab();
return win ? win : begin;
} /* ecore_x_window_at_xy_begin_get */
/**
* 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)
{
Window root, parent, *children = NULL;
unsigned int num;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
if (!XQueryTree(_ecore_x_disp, win, &root, &parent, &children, &num))
return 0;
if (children)
XFree(children);
return parent;
} /* ecore_x_window_parent_get */
/**
* 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 r,
unsigned short g, unsigned short b)
{
XSetWindowAttributes attr;
Colormap map;
XColor col;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
col.red = r;
col.green = g;
col.blue = b;
map = DefaultColormap(_ecore_x_disp, DefaultScreen(_ecore_x_disp));
XAllocColor(_ecore_x_disp, map, &col);
attr.background_pixel = col.pixel;
XChangeWindowAttributes(_ecore_x_disp, win, CWBackPixel, &attr);
} /* ecore_x_window_background_color_set */
EAPI void
ecore_x_window_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav)
{
XSetWindowAttributes att;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
att.win_gravity = grav;
XChangeWindowAttributes(_ecore_x_disp, win, CWWinGravity, &att);
} /* ecore_x_window_gravity_set */
EAPI void
ecore_x_window_pixel_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav)
{
XSetWindowAttributes att;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
att.bit_gravity = grav;
XChangeWindowAttributes(_ecore_x_disp, win, CWBitGravity, &att);
} /* ecore_x_window_pixel_gravity_set */
EAPI void
ecore_x_window_pixmap_set(Ecore_X_Window win, Ecore_X_Pixmap pmap)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
XSetWindowBackgroundPixmap(_ecore_x_disp, win, pmap);
} /* ecore_x_window_pixmap_set */
EAPI void
ecore_x_window_area_clear(Ecore_X_Window win, int x, int y, int w, int h)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
XClearArea(_ecore_x_disp, win, x, y, w, h, False);
} /* ecore_x_window_area_clear */
EAPI void
ecore_x_window_area_expose(Ecore_X_Window win, int x, int y, int w, int h)
{
LOGFN(__FILE__, __LINE__, __FUNCTION__);
XClearArea(_ecore_x_disp, win, x, y, w, h, True);
} /* ecore_x_window_area_expose */
EAPI void
ecore_x_window_override_set(Ecore_X_Window win, int override)
{
XSetWindowAttributes att;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
att.override_redirect = override;
XChangeWindowAttributes(_ecore_x_disp, win, CWOverrideRedirect, &att);
} /* ecore_x_window_override_set */
#ifdef ECORE_XRENDER
static Ecore_X_Window
_ecore_x_window_argb_internal_new(Ecore_X_Window parent,
int x,
int y,
int w,
int h,
int override,
int saveunder)
{
Window win;
XSetWindowAttributes attr;
XWindowAttributes att;
XVisualInfo *xvi;
XVisualInfo vi_in;
int nvi, i, scr = 0;
XRenderPictFormat *fmt;
Visual *vis;
if (parent == 0)
{
parent = DefaultRootWindow(_ecore_x_disp);
scr = DefaultScreen(_ecore_x_disp);
}
else
{
/* ewww - round trip */
XGetWindowAttributes(_ecore_x_disp, parent, &att);
for (i = 0; i < ScreenCount(_ecore_x_disp); i++)
{
if (att.screen == ScreenOfDisplay(_ecore_x_disp, i))
{
scr = i;
break;
}
}
}
vi_in.screen = scr;
vi_in.depth = 32;
vi_in.class = TrueColor;
xvi = XGetVisualInfo(_ecore_x_disp,
VisualScreenMask |
VisualDepthMask |
VisualClassMask,
&vi_in,
&nvi);
if (!xvi)
return 0;
vis = NULL;
for (i = 0; i < nvi; i++)
{
fmt = XRenderFindVisualFormat(_ecore_x_disp, xvi[i].visual);
if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
{
vis = xvi[i].visual;
break;
}
}
XFree (xvi);
attr.backing_store = NotUseful;
attr.override_redirect = override;
attr.colormap = XCreateColormap(_ecore_x_disp, parent,
vis, AllocNone);
attr.border_pixel = 0;
attr.background_pixmap = None;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = saveunder;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(_ecore_x_disp, parent,
x, y, w, h, 0,
32,
InputOutput,
vis,
CWBackingStore |
CWOverrideRedirect |
CWColormap |
CWBorderPixel |
CWBackPixmap |
CWSaveUnder |
CWDontPropagate |
CWEventMask |
CWBitGravity |
CWWinGravity,
&attr);
XFreeColormap(_ecore_x_disp, attr.colormap);
if (parent == DefaultRootWindow(_ecore_x_disp))
ecore_x_window_defaults_set(win);
return win;
} /* _ecore_x_window_argb_internal_new */
#endif /* ifdef ECORE_XRENDER */
EAPI int
ecore_x_window_argb_get(Ecore_X_Window win)
{
#ifdef ECORE_XRENDER
XWindowAttributes att;
XRenderPictFormat *fmt;
att.visual = 0;
if (!XGetWindowAttributes(_ecore_x_disp, win, &att))
return 0;
fmt = XRenderFindVisualFormat(_ecore_x_disp, att.visual);
if (!fmt)
return 0;
if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
return 1;
return 0;
#else /* ifdef ECORE_XRENDER */
return 0;
#endif /* ifdef ECORE_XRENDER */
} /* ecore_x_window_argb_get */
/**
* 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)
{
#ifdef ECORE_XRENDER
LOGFN(__FILE__, __LINE__, __FUNCTION__);
return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
#else /* ifdef ECORE_XRENDER */
return 0;
#endif /* ifdef ECORE_XRENDER */
} /* ecore_x_window_manager_argb_new */
/**
* 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)
{
#ifdef ECORE_XRENDER
LOGFN(__FILE__, __LINE__, __FUNCTION__);
return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 0, 0);
#else /* ifdef ECORE_XRENDER */
return 0;
#endif /* ifdef ECORE_XRENDER */
} /* ecore_x_window_argb_new */
/**
* 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)
{
#ifdef ECORE_XRENDER
LOGFN(__FILE__, __LINE__, __FUNCTION__);
return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0);
#else /* ifdef ECORE_XRENDER */
return 0;
#endif /* ifdef ECORE_XRENDER */
} /* ecore_x_window_override_argb_new */