forked from enlightenment/efl
1265 lines
32 KiB
C
1265 lines
32 KiB
C
/*
|
|
* Various ICCCM related functions.
|
|
*
|
|
* This is ALL the code involving anything ICCCM related. for both WM and
|
|
* client.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif /* ifdef HAVE_CONFIG_H */
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "Ecore.h"
|
|
#include "ecore_x_private.h"
|
|
#include "Ecore_X.h"
|
|
#include "Ecore_X_Atoms.h"
|
|
|
|
EAPI void
|
|
ecore_x_icccm_init(void)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_state_set(Ecore_X_Window win,
|
|
Ecore_X_Window_State_Hint state)
|
|
{
|
|
unsigned long c[2];
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
|
|
c[0] = WithdrawnState;
|
|
else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
|
|
c[0] = NormalState;
|
|
else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
|
|
c[0] = IconicState;
|
|
|
|
c[1] = None;
|
|
XChangeProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE,
|
|
ECORE_X_ATOM_WM_STATE, 32, PropModeReplace,
|
|
(unsigned char *)c, 2);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
EAPI Ecore_X_Window_State_Hint
|
|
ecore_x_icccm_state_get(Ecore_X_Window win)
|
|
{
|
|
unsigned char *prop_ret = NULL;
|
|
Atom type_ret;
|
|
unsigned long bytes_after, num_ret;
|
|
int format_ret;
|
|
Ecore_X_Window_State_Hint hint;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
hint = ECORE_X_WINDOW_STATE_HINT_NONE;
|
|
XGetWindowProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE,
|
|
0, 0x7fffffff, False, ECORE_X_ATOM_WM_STATE,
|
|
&type_ret, &format_ret, &num_ret, &bytes_after,
|
|
&prop_ret);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if ((prop_ret) && (num_ret == 2))
|
|
{
|
|
if (prop_ret[0] == WithdrawnState)
|
|
hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
|
|
else if (prop_ret[0] == NormalState)
|
|
hint = ECORE_X_WINDOW_STATE_HINT_NORMAL;
|
|
else if (prop_ret[0] == IconicState)
|
|
hint = ECORE_X_WINDOW_STATE_HINT_ICONIC;
|
|
}
|
|
|
|
if (prop_ret)
|
|
XFree(prop_ret);
|
|
|
|
return hint;
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_delete_window_send(Ecore_X_Window win,
|
|
Ecore_X_Time t)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
|
|
ECORE_X_EVENT_MASK_NONE,
|
|
ECORE_X_ATOM_WM_DELETE_WINDOW,
|
|
t, 0, 0, 0);
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_take_focus_send(Ecore_X_Window win,
|
|
Ecore_X_Time t)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
|
|
ECORE_X_EVENT_MASK_NONE,
|
|
ECORE_X_ATOM_WM_TAKE_FOCUS,
|
|
t, 0, 0, 0);
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_save_yourself_send(Ecore_X_Window win,
|
|
Ecore_X_Time t)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
|
|
ECORE_X_EVENT_MASK_NONE,
|
|
ECORE_X_ATOM_WM_SAVE_YOURSELF,
|
|
t, 0, 0, 0);
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_move_resize_send(Ecore_X_Window win,
|
|
int x,
|
|
int y,
|
|
int w,
|
|
int h)
|
|
{
|
|
XEvent ev;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
ev.type = ConfigureNotify;
|
|
ev.xconfigure.display = _ecore_x_disp;
|
|
ev.xconfigure.event = win;
|
|
ev.xconfigure.window = win;
|
|
ev.xconfigure.x = x;
|
|
ev.xconfigure.y = y;
|
|
ev.xconfigure.width = w;
|
|
ev.xconfigure.height = h;
|
|
ev.xconfigure.border_width = 0;
|
|
ev.xconfigure.above = None;
|
|
ev.xconfigure.override_redirect = False;
|
|
XSendEvent(_ecore_x_disp, win, False, StructureNotifyMask, &ev);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_hints_set(Ecore_X_Window win,
|
|
Eina_Bool accepts_focus,
|
|
Ecore_X_Window_State_Hint initial_state,
|
|
Ecore_X_Pixmap icon_pixmap,
|
|
Ecore_X_Pixmap icon_mask,
|
|
Ecore_X_Window icon_window,
|
|
Ecore_X_Window window_group,
|
|
Eina_Bool is_urgent)
|
|
{
|
|
XWMHints *hints;
|
|
|
|
hints = XAllocWMHints();
|
|
if (!hints)
|
|
return;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
hints->flags = InputHint | StateHint;
|
|
hints->input = accepts_focus;
|
|
if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
|
|
hints->initial_state = WithdrawnState;
|
|
else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
|
|
hints->initial_state = NormalState;
|
|
else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
|
|
hints->initial_state = IconicState;
|
|
|
|
if (icon_pixmap != 0)
|
|
{
|
|
hints->icon_pixmap = icon_pixmap;
|
|
hints->flags |= IconPixmapHint;
|
|
}
|
|
|
|
if (icon_mask != 0)
|
|
{
|
|
hints->icon_mask = icon_mask;
|
|
hints->flags |= IconMaskHint;
|
|
}
|
|
|
|
if (icon_window != 0)
|
|
{
|
|
hints->icon_window = icon_window;
|
|
hints->flags |= IconWindowHint;
|
|
}
|
|
|
|
if (window_group != 0)
|
|
{
|
|
hints->window_group = window_group;
|
|
hints->flags |= WindowGroupHint;
|
|
}
|
|
|
|
if (is_urgent)
|
|
hints->flags |= XUrgencyHint;
|
|
|
|
XSetWMHints(_ecore_x_disp, win, hints);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
XFree(hints);
|
|
}
|
|
|
|
EAPI Eina_Bool
|
|
ecore_x_icccm_hints_get(Ecore_X_Window win,
|
|
Eina_Bool *accepts_focus,
|
|
Ecore_X_Window_State_Hint *initial_state,
|
|
Ecore_X_Pixmap *icon_pixmap,
|
|
Ecore_X_Pixmap *icon_mask,
|
|
Ecore_X_Window *icon_window,
|
|
Ecore_X_Window *window_group,
|
|
Eina_Bool *is_urgent)
|
|
{
|
|
XWMHints *hints;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (accepts_focus)
|
|
*accepts_focus = EINA_TRUE;
|
|
|
|
if (initial_state)
|
|
*initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
|
|
|
|
if (icon_pixmap)
|
|
*icon_pixmap = 0;
|
|
|
|
if (icon_mask)
|
|
*icon_mask = 0;
|
|
|
|
if (icon_window)
|
|
*icon_window = 0;
|
|
|
|
if (window_group)
|
|
*window_group = 0;
|
|
|
|
if (is_urgent)
|
|
*is_urgent = EINA_FALSE;
|
|
|
|
hints = XGetWMHints(_ecore_x_disp, win);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (hints)
|
|
{
|
|
if ((hints->flags & InputHint) && (accepts_focus))
|
|
{
|
|
if (hints->input)
|
|
*accepts_focus = EINA_TRUE;
|
|
else
|
|
*accepts_focus = EINA_FALSE;
|
|
}
|
|
|
|
if ((hints->flags & StateHint) && (initial_state))
|
|
{
|
|
if (hints->initial_state == WithdrawnState)
|
|
*initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
|
|
else if (hints->initial_state == NormalState)
|
|
*initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
|
|
else if (hints->initial_state == IconicState)
|
|
*initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
|
|
}
|
|
|
|
if ((hints->flags & IconPixmapHint) && (icon_pixmap))
|
|
*icon_pixmap = hints->icon_pixmap;
|
|
|
|
if ((hints->flags & IconMaskHint) && (icon_mask))
|
|
*icon_mask = hints->icon_mask;
|
|
|
|
if ((hints->flags & IconWindowHint) && (icon_window))
|
|
*icon_window = hints->icon_window;
|
|
|
|
if ((hints->flags & WindowGroupHint) && (window_group))
|
|
*window_group = hints->window_group;
|
|
|
|
if ((hints->flags & XUrgencyHint) && (is_urgent))
|
|
*is_urgent = EINA_TRUE;
|
|
|
|
XFree(hints);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win,
|
|
Eina_Bool request_pos,
|
|
Ecore_X_Gravity gravity,
|
|
int min_w,
|
|
int min_h,
|
|
int max_w,
|
|
int max_h,
|
|
int base_w,
|
|
int base_h,
|
|
int step_x,
|
|
int step_y,
|
|
double min_aspect,
|
|
double max_aspect)
|
|
{
|
|
XSizeHints hint;
|
|
long mask;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask))
|
|
memset(&hint, 0, sizeof(XSizeHints));
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
|
|
hint.flags = 0;
|
|
if (request_pos)
|
|
hint.flags |= USPosition;
|
|
|
|
if (gravity != ECORE_X_GRAVITY_NW)
|
|
{
|
|
hint.flags |= PWinGravity;
|
|
hint.win_gravity = gravity;
|
|
}
|
|
|
|
if ((min_w > 0) || (min_h > 0))
|
|
{
|
|
hint.flags |= PMinSize;
|
|
hint.min_width = min_w;
|
|
hint.min_height = min_h;
|
|
}
|
|
|
|
if ((max_w > 0) || (max_h > 0))
|
|
{
|
|
hint.flags |= PMaxSize;
|
|
hint.max_width = max_w;
|
|
hint.max_height = max_h;
|
|
}
|
|
|
|
if ((base_w > 0) || (base_h > 0))
|
|
{
|
|
hint.flags |= PBaseSize;
|
|
hint.base_width = base_w;
|
|
hint.base_height = base_h;
|
|
}
|
|
|
|
if ((step_x > 1) || (step_y > 1))
|
|
{
|
|
hint.flags |= PResizeInc;
|
|
hint.width_inc = step_x;
|
|
hint.height_inc = step_y;
|
|
}
|
|
|
|
if ((min_aspect > 0.0) || (max_aspect > 0.0))
|
|
{
|
|
hint.flags |= PAspect;
|
|
hint.min_aspect.x = min_aspect * 10000;
|
|
hint.min_aspect.y = 10000;
|
|
hint.max_aspect.x = max_aspect * 10000;
|
|
hint.max_aspect.y = 10000;
|
|
}
|
|
|
|
XSetWMNormalHints(_ecore_x_disp, win, &hint);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
EAPI Eina_Bool
|
|
ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win,
|
|
Eina_Bool *request_pos,
|
|
Ecore_X_Gravity *gravity,
|
|
int *min_w,
|
|
int *min_h,
|
|
int *max_w,
|
|
int *max_h,
|
|
int *base_w,
|
|
int *base_h,
|
|
int *step_x,
|
|
int *step_y,
|
|
double *min_aspect,
|
|
double *max_aspect)
|
|
{
|
|
XSizeHints hint;
|
|
long mask;
|
|
|
|
int minw = 0, minh = 0;
|
|
int maxw = 32767, maxh = 32767;
|
|
int basew = -1, baseh = -1;
|
|
int stepx = -1, stepy = -1;
|
|
double mina = 0.0, maxa = 0.0;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask))
|
|
{
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
if ((hint.flags & USPosition) || ((hint.flags & PPosition)))
|
|
{
|
|
if (request_pos)
|
|
*request_pos = EINA_TRUE;
|
|
}
|
|
else if (request_pos)
|
|
*request_pos = EINA_FALSE;
|
|
|
|
if (hint.flags & PWinGravity)
|
|
{
|
|
if (gravity)
|
|
*gravity = hint.win_gravity;
|
|
}
|
|
else if (gravity)
|
|
*gravity = ECORE_X_GRAVITY_NW;
|
|
|
|
if (hint.flags & PMinSize)
|
|
{
|
|
minw = hint.min_width;
|
|
minh = hint.min_height;
|
|
}
|
|
|
|
if (hint.flags & PMaxSize)
|
|
{
|
|
maxw = hint.max_width;
|
|
maxh = hint.max_height;
|
|
if (maxw < minw)
|
|
maxw = minw;
|
|
|
|
if (maxh < minh)
|
|
maxh = minh;
|
|
}
|
|
|
|
if (hint.flags & PBaseSize)
|
|
{
|
|
basew = hint.base_width;
|
|
baseh = hint.base_height;
|
|
if (basew > minw)
|
|
minw = basew;
|
|
|
|
if (baseh > minh)
|
|
minh = baseh;
|
|
}
|
|
|
|
if (hint.flags & PResizeInc)
|
|
{
|
|
stepx = hint.width_inc;
|
|
stepy = hint.height_inc;
|
|
if (stepx < 1)
|
|
stepx = 1;
|
|
|
|
if (stepy < 1)
|
|
stepy = 1;
|
|
}
|
|
|
|
if (hint.flags & PAspect)
|
|
{
|
|
if (hint.min_aspect.y > 0)
|
|
mina = ((double)hint.min_aspect.x) / ((double)hint.min_aspect.y);
|
|
|
|
if (hint.max_aspect.y > 0)
|
|
maxa = ((double)hint.max_aspect.x) / ((double)hint.max_aspect.y);
|
|
}
|
|
|
|
if (min_w)
|
|
*min_w = minw;
|
|
|
|
if (min_h)
|
|
*min_h = minh;
|
|
|
|
if (max_w)
|
|
*max_w = maxw;
|
|
|
|
if (max_h)
|
|
*max_h = maxh;
|
|
|
|
if (base_w)
|
|
*base_w = basew;
|
|
|
|
if (base_h)
|
|
*base_h = baseh;
|
|
|
|
if (step_x)
|
|
*step_x = stepx;
|
|
|
|
if (step_y)
|
|
*step_y = stepy;
|
|
|
|
if (min_aspect)
|
|
*min_aspect = mina;
|
|
|
|
if (max_aspect)
|
|
*max_aspect = maxa;
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_title_set(Ecore_X_Window win,
|
|
const char *t)
|
|
{
|
|
char *list[1];
|
|
XTextProperty xprop;
|
|
int ret;
|
|
|
|
if (!t)
|
|
return;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
xprop.value = NULL;
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
list[0] = strdup(t);
|
|
ret =
|
|
Xutf8TextListToTextProperty(_ecore_x_disp, list, 1, XUTF8StringStyle,
|
|
&xprop);
|
|
#else /* ifdef X_HAVE_UTF8_STRING */
|
|
list[0] = strdup(t);
|
|
ret =
|
|
XmbTextListToTextProperty(_ecore_x_disp, list, 1, XStdICCTextStyle,
|
|
&xprop);
|
|
#endif /* ifdef X_HAVE_UTF8_STRING */
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (ret >= Success)
|
|
{
|
|
XSetWMName(_ecore_x_disp, win, &xprop);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (xprop.value)
|
|
XFree(xprop.value);
|
|
}
|
|
else if (XStringListToTextProperty(list, 1, &xprop) >= Success)
|
|
{
|
|
XSetWMName(_ecore_x_disp, win, &xprop);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (xprop.value)
|
|
XFree(xprop.value);
|
|
}
|
|
|
|
free(list[0]);
|
|
}
|
|
|
|
EAPI char *
|
|
ecore_x_icccm_title_get(Ecore_X_Window win)
|
|
{
|
|
XTextProperty xprop;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
xprop.value = NULL;
|
|
if (XGetWMName(_ecore_x_disp, win, &xprop) >= Success)
|
|
{
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (xprop.value)
|
|
{
|
|
char **list = NULL;
|
|
char *t = NULL;
|
|
int num = 0;
|
|
int ret;
|
|
|
|
if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING)
|
|
t = strdup((char *)xprop.value);
|
|
else
|
|
{
|
|
/* convert to utf8 */
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop,
|
|
&list, &num);
|
|
#else /* ifdef X_HAVE_UTF8_STRING */
|
|
ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop,
|
|
&list, &num);
|
|
#endif /* ifdef X_HAVE_UTF8_STRING */
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
|
|
if ((ret == XLocaleNotSupported) ||
|
|
(ret == XNoMemory) || (ret == XConverterNotFound))
|
|
t = strdup((char *)xprop.value);
|
|
else if ((ret >= Success) && (num > 0))
|
|
t = strdup(list[0]);
|
|
|
|
if (list)
|
|
XFreeStringList(list);
|
|
}
|
|
|
|
if (xprop.value)
|
|
XFree(xprop.value);
|
|
|
|
return t;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Set protocol atoms explicitly
|
|
* @param win The Window
|
|
* @param protos An array of protocol atoms
|
|
* @param num the number of members of the array
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_protocol_atoms_set(Ecore_X_Window win,
|
|
Ecore_X_Atom *protos,
|
|
int num)
|
|
{
|
|
Atom *protos2 = alloca(sizeof(Atom) * num);
|
|
int i;
|
|
|
|
for (i = 0; i < num; i++) protos2[i] = protos[i];
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (num > 0)
|
|
XSetWMProtocols(_ecore_x_disp, win, protos2, num);
|
|
else
|
|
XDeleteProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_PROTOCOLS);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
/**
|
|
* Set or unset a wm protocol property.
|
|
* @param win The Window
|
|
* @param protocol The protocol to enable/disable
|
|
* @param on On/Off
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_protocol_set(Ecore_X_Window win,
|
|
Ecore_X_WM_Protocol protocol,
|
|
Eina_Bool on)
|
|
{
|
|
Atom *protos = NULL;
|
|
Atom proto;
|
|
int protos_count = 0;
|
|
int already_set = 0;
|
|
int i;
|
|
|
|
/* Check for invalid values */
|
|
if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
|
|
return;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
proto = _ecore_x_atoms_wm_protocols[protocol];
|
|
|
|
if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
|
|
{
|
|
protos = NULL;
|
|
protos_count = 0;
|
|
}
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
for (i = 0; i < protos_count; i++)
|
|
{
|
|
if (protos[i] == proto)
|
|
{
|
|
already_set = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (on)
|
|
{
|
|
Atom *new_protos = NULL;
|
|
|
|
if (already_set)
|
|
goto leave;
|
|
|
|
new_protos = malloc((protos_count + 1) * sizeof(Atom));
|
|
if (!new_protos)
|
|
goto leave;
|
|
|
|
for (i = 0; i < protos_count; i++)
|
|
new_protos[i] = protos[i];
|
|
new_protos[protos_count] = proto;
|
|
XSetWMProtocols(_ecore_x_disp, win, new_protos, protos_count + 1);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
free(new_protos);
|
|
}
|
|
else
|
|
{
|
|
if (!already_set)
|
|
goto leave;
|
|
|
|
for (i = 0; i < protos_count; i++)
|
|
{
|
|
if (protos[i] == proto)
|
|
{
|
|
int j;
|
|
|
|
for (j = i + 1; j < protos_count; j++)
|
|
protos[j - 1] = protos[j];
|
|
if (protos_count > 1)
|
|
XSetWMProtocols(_ecore_x_disp, win, protos,
|
|
protos_count - 1);
|
|
else
|
|
XDeleteProperty(_ecore_x_disp, win,
|
|
ECORE_X_ATOM_WM_PROTOCOLS);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
|
|
goto leave;
|
|
}
|
|
}
|
|
}
|
|
|
|
leave:
|
|
if (protos)
|
|
XFree(protos);
|
|
}
|
|
|
|
/**
|
|
* Determines whether a protocol is set for a window.
|
|
* @param win The Window
|
|
* @param protocol The protocol to query
|
|
* @return 1 if the protocol is set, else 0.
|
|
*/
|
|
EAPI Eina_Bool
|
|
ecore_x_icccm_protocol_isset(Ecore_X_Window win,
|
|
Ecore_X_WM_Protocol protocol)
|
|
{
|
|
Atom proto, *protos = NULL;
|
|
int i, protos_count = 0;
|
|
Eina_Bool ret = EINA_FALSE;
|
|
|
|
/* check for invalid values */
|
|
if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
|
|
return EINA_FALSE;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
proto = _ecore_x_atoms_wm_protocols[protocol];
|
|
|
|
if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
|
|
return EINA_FALSE;
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
|
|
for (i = 0; i < protos_count; i++)
|
|
if (protos[i] == proto)
|
|
{
|
|
ret = EINA_TRUE;
|
|
break;
|
|
}
|
|
|
|
if (protos)
|
|
XFree(protos);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Set a window name & class.
|
|
* @param win The window
|
|
* @param n The name string
|
|
* @param c The class string
|
|
*
|
|
* Set a window name * class
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_name_class_set(Ecore_X_Window win,
|
|
const char *n,
|
|
const char *c)
|
|
{
|
|
XClassHint *xch;
|
|
|
|
xch = XAllocClassHint();
|
|
if (!xch)
|
|
return;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
xch->res_name = (char *)n;
|
|
xch->res_class = (char *)c;
|
|
XSetClassHint(_ecore_x_disp, win, xch);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
XFree(xch);
|
|
}
|
|
|
|
/**
|
|
* Get a window name & class.
|
|
* @param win The window
|
|
* @param n The name string
|
|
* @param c The class string
|
|
*
|
|
* Get a window name * class
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_name_class_get(Ecore_X_Window win,
|
|
char **n,
|
|
char **c)
|
|
{
|
|
XClassHint xch;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (n)
|
|
*n = NULL;
|
|
|
|
if (c)
|
|
*c = NULL;
|
|
|
|
xch.res_name = NULL;
|
|
xch.res_class = NULL;
|
|
if (XGetClassHint(_ecore_x_disp, win, &xch))
|
|
{
|
|
if (n)
|
|
if (xch.res_name)
|
|
*n = strdup(xch.res_name);
|
|
|
|
if (c)
|
|
if (xch.res_class)
|
|
*c = strdup(xch.res_class);
|
|
|
|
XFree(xch.res_name);
|
|
XFree(xch.res_class);
|
|
}
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
/**
|
|
* Get a window client machine string.
|
|
* @param win The window
|
|
* @return The windows client machine string
|
|
*
|
|
* Return the client machine of a window. String must be free'd when done with.
|
|
*/
|
|
EAPI char *
|
|
ecore_x_icccm_client_machine_get(Ecore_X_Window win)
|
|
{
|
|
char *name;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
name = ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_CLIENT_MACHINE);
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Sets the WM_COMMAND property for @a win.
|
|
*
|
|
* @param win The window.
|
|
* @param argc Number of arguments.
|
|
* @param argv Arguments.
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_command_set(Ecore_X_Window win,
|
|
int argc,
|
|
char **argv)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
XSetCommand(_ecore_x_disp, win, argv, argc);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
/**
|
|
* Get the WM_COMMAND property for @a win.
|
|
*
|
|
* Return the command of a window. String must be free'd when done with.
|
|
*
|
|
* @param win The window.
|
|
* @param argc Number of arguments.
|
|
* @param argv Arguments.
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_command_get(Ecore_X_Window win,
|
|
int *argc,
|
|
char ***argv)
|
|
{
|
|
int i, c;
|
|
char **v;
|
|
Eina_Bool success;
|
|
|
|
if (argc)
|
|
*argc = 0;
|
|
|
|
if (argv)
|
|
*argv = NULL;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
success = XGetCommand(_ecore_x_disp, win, &v, &c);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (!success) return;
|
|
|
|
if (c < 1)
|
|
{
|
|
if (v)
|
|
XFreeStringList(v);
|
|
|
|
return;
|
|
}
|
|
|
|
if (argc)
|
|
*argc = c;
|
|
|
|
if (argv)
|
|
{
|
|
(*argv) = malloc(c * sizeof(char *));
|
|
if (!*argv)
|
|
{
|
|
XFreeStringList(v);
|
|
if (argc)
|
|
*argc = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < c; i++)
|
|
{
|
|
if (v[i])
|
|
(*argv)[i] = strdup(v[i]);
|
|
else
|
|
(*argv)[i] = strdup("");
|
|
}
|
|
}
|
|
|
|
XFreeStringList(v);
|
|
}
|
|
|
|
/**
|
|
* Set a window icon name.
|
|
* @param win The window
|
|
* @param t The icon name string
|
|
*
|
|
* Set a window icon name
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_icon_name_set(Ecore_X_Window win,
|
|
const char *t)
|
|
{
|
|
char *list[1];
|
|
XTextProperty xprop;
|
|
int ret;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
xprop.value = NULL;
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
list[0] = strdup(t);
|
|
ret = Xutf8TextListToTextProperty(_ecore_x_disp, list, 1,
|
|
XUTF8StringStyle, &xprop);
|
|
#else /* ifdef X_HAVE_UTF8_STRING */
|
|
list[0] = strdup(t);
|
|
ret = XmbTextListToTextProperty(_ecore_x_disp, list, 1,
|
|
XStdICCTextStyle, &xprop);
|
|
#endif /* ifdef X_HAVE_UTF8_STRING */
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (ret >= Success)
|
|
{
|
|
XSetWMIconName(_ecore_x_disp, win, &xprop);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (xprop.value)
|
|
XFree(xprop.value);
|
|
}
|
|
else if (XStringListToTextProperty(list, 1, &xprop) >= Success)
|
|
{
|
|
XSetWMIconName(_ecore_x_disp, win, &xprop);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (xprop.value)
|
|
XFree(xprop.value);
|
|
}
|
|
|
|
free(list[0]);
|
|
}
|
|
|
|
/**
|
|
* Get a window icon name.
|
|
* @param win The window
|
|
* @return The windows icon name string
|
|
*
|
|
* Return the icon name of a window. String must be free'd when done with.
|
|
*/
|
|
EAPI char *
|
|
ecore_x_icccm_icon_name_get(Ecore_X_Window win)
|
|
{
|
|
XTextProperty xprop;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
xprop.value = NULL;
|
|
if (XGetWMIconName(_ecore_x_disp, win, &xprop) >= Success)
|
|
{
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (xprop.value)
|
|
{
|
|
char **list = NULL;
|
|
char *t = NULL;
|
|
int num = 0;
|
|
int ret;
|
|
|
|
if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING)
|
|
t = strdup((char *)xprop.value);
|
|
else
|
|
{
|
|
/* convert to utf8 */
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop,
|
|
&list, &num);
|
|
#else /* ifdef X_HAVE_UTF8_STRING */
|
|
ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop,
|
|
&list, &num);
|
|
#endif /* ifdef X_HAVE_UTF8_STRING */
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
|
|
if ((ret == XLocaleNotSupported) ||
|
|
(ret == XNoMemory) || (ret == XConverterNotFound))
|
|
t = strdup((char *)xprop.value);
|
|
else if (ret >= Success)
|
|
{
|
|
if ((num >= 1) && (list))
|
|
t = strdup(list[0]);
|
|
|
|
if (list)
|
|
XFreeStringList(list);
|
|
}
|
|
}
|
|
|
|
if (xprop.value)
|
|
XFree(xprop.value);
|
|
|
|
return t;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Add a subwindow to the list of windows that need a different colormap installed.
|
|
* @param win The toplevel window
|
|
* @param subwin The subwindow to be added to the colormap windows list
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_colormap_window_set(Ecore_X_Window win,
|
|
Ecore_X_Window subwin)
|
|
{
|
|
int num = 0, i;
|
|
unsigned char *old_data = NULL;
|
|
unsigned char *data = NULL;
|
|
Window *oldset = NULL;
|
|
Window *newset = NULL;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (!ecore_x_window_prop_property_get(win,
|
|
ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
|
|
XA_WINDOW, 32, &old_data, &num))
|
|
{
|
|
newset = calloc(1, sizeof(Window));
|
|
if (!newset)
|
|
{
|
|
if (old_data) free(old_data);
|
|
return;
|
|
}
|
|
|
|
newset[0] = subwin;
|
|
num = 1;
|
|
data = (unsigned char *)newset;
|
|
}
|
|
else
|
|
{
|
|
newset = calloc(num + 1, sizeof(Window));
|
|
oldset = (Window *)old_data;
|
|
if (!newset)
|
|
{
|
|
if (old_data) free(old_data);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < num; ++i)
|
|
{
|
|
if (oldset[i] == subwin)
|
|
{
|
|
free(old_data);
|
|
free(newset);
|
|
return;
|
|
}
|
|
|
|
newset[i] = oldset[i];
|
|
}
|
|
|
|
newset[num++] = subwin;
|
|
data = (unsigned char *)newset;
|
|
}
|
|
|
|
ecore_x_window_prop_property_set(win,
|
|
ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
|
|
XA_WINDOW, 32, data, num);
|
|
free(newset);
|
|
free(old_data);
|
|
}
|
|
|
|
/**
|
|
* Remove a window from the list of colormap windows.
|
|
* @param win The toplevel window
|
|
* @param subwin The window to be removed from the colormap window list.
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_colormap_window_unset(Ecore_X_Window win,
|
|
Ecore_X_Window subwin)
|
|
{
|
|
int num = 0, i, j, k = 0;
|
|
unsigned char *old_data = NULL;
|
|
unsigned char *data = NULL;
|
|
Window *oldset = NULL;
|
|
Window *newset = NULL;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (!ecore_x_window_prop_property_get(win,
|
|
ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
|
|
XA_WINDOW, 32, &old_data, &num))
|
|
{
|
|
if (old_data) free(old_data);
|
|
return;
|
|
}
|
|
|
|
oldset = (Window *)old_data;
|
|
for (i = 0; i < num; i++)
|
|
{
|
|
if (oldset[i] == subwin)
|
|
{
|
|
if (num == 1)
|
|
{
|
|
XDeleteProperty(_ecore_x_disp,
|
|
win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
free(old_data);
|
|
|
|
old_data = NULL;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
newset = calloc(num - 1, sizeof(Window));
|
|
data = (unsigned char *)newset;
|
|
for (j = 0; j < num; ++j)
|
|
if (oldset[j] != subwin)
|
|
newset[k++] = oldset[j];
|
|
|
|
ecore_x_window_prop_property_set(
|
|
win,
|
|
ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
|
|
XA_WINDOW,
|
|
32,
|
|
data,
|
|
k);
|
|
free(old_data);
|
|
|
|
old_data = NULL;
|
|
free(newset);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (old_data)
|
|
free(old_data);
|
|
}
|
|
|
|
/**
|
|
* Specify that a window is transient for another top-level window and should be handled accordingly.
|
|
* @param win the transient window
|
|
* @param forwin the toplevel window
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_transient_for_set(Ecore_X_Window win,
|
|
Ecore_X_Window forwin)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
XSetTransientForHint(_ecore_x_disp, win, forwin);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
/**
|
|
* Remove the transient_for setting from a window.
|
|
* @param win The window
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_transient_for_unset(Ecore_X_Window win)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
XDeleteProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_TRANSIENT_FOR);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
/**
|
|
* Get the window this window is transient for, if any.
|
|
* @param win The window to check
|
|
* @return The window ID of the top-level window, or 0 if the property does not exist.
|
|
*/
|
|
EAPI Ecore_X_Window
|
|
ecore_x_icccm_transient_for_get(Ecore_X_Window win)
|
|
{
|
|
Window forwin;
|
|
Eina_Bool success;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
success = XGetTransientForHint(_ecore_x_disp, win, &forwin);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
if (success)
|
|
return (Ecore_X_Window)forwin;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Set the window role hint.
|
|
* @param win The window
|
|
* @param role The role string
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_window_role_set(Ecore_X_Window win,
|
|
const char *role)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_WINDOW_ROLE,
|
|
(char *)role);
|
|
}
|
|
|
|
/**
|
|
* Get the window role.
|
|
* @param win The window
|
|
* @return The window's role string.
|
|
*/
|
|
EAPI char *
|
|
ecore_x_icccm_window_role_get(Ecore_X_Window win)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
return ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_WINDOW_ROLE);
|
|
}
|
|
|
|
/**
|
|
* Set the window's client leader.
|
|
* @param win The window
|
|
* @param l The client leader window
|
|
*
|
|
* All non-transient top-level windows created by an app other than
|
|
* the main window must have this property set to the app's main window.
|
|
*/
|
|
EAPI void
|
|
ecore_x_icccm_client_leader_set(Ecore_X_Window win,
|
|
Ecore_X_Window l)
|
|
{
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
ecore_x_window_prop_window_set(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
|
|
&l, 1);
|
|
}
|
|
|
|
/**
|
|
* Get the window's client leader.
|
|
* @param win The window
|
|
* @return The window's client leader window, or 0 if unset */
|
|
EAPI Ecore_X_Window
|
|
ecore_x_icccm_client_leader_get(Ecore_X_Window win)
|
|
{
|
|
Ecore_X_Window l;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (ecore_x_window_prop_window_get(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
|
|
&l, 1) > 0)
|
|
return l;
|
|
|
|
return 0;
|
|
}
|
|
|
|
EAPI void
|
|
ecore_x_icccm_iconic_request_send(Ecore_X_Window win,
|
|
Ecore_X_Window root)
|
|
{
|
|
XEvent xev = { 0 };
|
|
|
|
if (!win)
|
|
return;
|
|
|
|
LOGFN(__FILE__, __LINE__, __FUNCTION__);
|
|
if (!root)
|
|
root = DefaultRootWindow(_ecore_x_disp);
|
|
|
|
xev.xclient.type = ClientMessage;
|
|
xev.xclient.serial = 0;
|
|
xev.xclient.send_event = True;
|
|
xev.xclient.display = _ecore_x_disp;
|
|
xev.xclient.window = win;
|
|
xev.xclient.format = 32;
|
|
xev.xclient.message_type = ECORE_X_ATOM_WM_CHANGE_STATE;
|
|
xev.xclient.data.l[0] = IconicState;
|
|
|
|
XSendEvent(_ecore_x_disp, root, False,
|
|
SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
|
if (_ecore_xlib_sync) ecore_x_sync();
|
|
}
|
|
|
|
/* FIXME: there are older E hints, gnome hints and mwm hints and new netwm */
|
|
/* hints. each should go in their own file/section so we know which */
|
|
/* is which. also older kde hints too. we should try support as much */
|
|
/* as makese sense to support */
|