efl/src/lib/ecore_x/ecore_x_netwm.c

2088 lines
51 KiB
C

/*
* _NET_WM... aka Extended Window Manager Hint (EWMH) functions.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Ecore.h"
#include "ecore_x_private.h"
#include "Ecore_X.h"
typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info;
struct _Ecore_X_Startup_Info
{
Ecore_X_Window win;
int init;
int buffer_size;
char *buffer;
int length;
/* These are the sequence info fields */
char *id;
char *name;
int screen;
char *bin;
char *icon;
int desktop;
int timestamp;
char *description;
char *wmclass;
int silent;
};
static void _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win,
Ecore_X_Atom atom,
const char *str);
static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win,
Ecore_X_Atom atom);
#if 0 /* Unused */
static int _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info);
static int _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
char *data);
#endif /* if 0 */
static void _ecore_x_netwm_startup_info_free(void *data);
/*
* Convenience macros
*/
#define _ATOM_SET_UTF8_STRING_LIST(win, atom, string, cnt) \
XChangeProperty(_ecore_x_disp, \
win, \
atom, \
ECORE_X_ATOM_UTF8_STRING, \
8, \
PropModeReplace, \
(unsigned char *)string, \
cnt)
/*
* Local variables
*/
static Eina_Hash *startup_info = NULL;
EAPI void
ecore_x_netwm_init(void)
{
LOGFN;
startup_info = eina_hash_string_superfast_new(
_ecore_x_netwm_startup_info_free);
}
EAPI void
ecore_x_netwm_shutdown(void)
{
LOGFN;
if (startup_info)
eina_hash_free(startup_info);
startup_info = NULL;
}
/*
* WM identification
*/
EAPI void
ecore_x_netwm_wm_identify(Ecore_X_Window root,
Ecore_X_Window check,
const char *wm_name)
{
LOGFN;
ecore_x_window_prop_window_set(check,
ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
&check,
1);
_ecore_x_window_prop_string_utf8_set(check,
ECORE_X_ATOM_NET_WM_NAME,
wm_name);
/* This one isn't mandatory */
_ecore_x_window_prop_string_utf8_set(root,
ECORE_X_ATOM_NET_WM_NAME,
wm_name);
ecore_x_window_prop_window_set(root,
ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK,
&check,
1);
}
/*
* Set supported atoms
*/
EAPI void
ecore_x_netwm_supported_set(Ecore_X_Window root,
Ecore_X_Atom *supported,
int num)
{
LOGFN;
ecore_x_window_prop_atom_set(root,
ECORE_X_ATOM_NET_SUPPORTED,
supported,
num);
}
EAPI Eina_Bool
ecore_x_netwm_supported_get(Ecore_X_Window root,
Ecore_X_Atom **supported,
int *num)
{
int num_ret;
EINA_SAFETY_ON_NULL_RETURN_VAL(supported, EINA_FALSE);
if (num)
*num = 0;
LOGFN;
num_ret = ecore_x_window_prop_atom_list_get(root, ECORE_X_ATOM_NET_SUPPORTED,
supported);
if (num_ret <= 0)
return EINA_FALSE;
if (num)
*num = num_ret;
return EINA_TRUE;
}
/*
* Desktop configuration and status
*/
EAPI void
ecore_x_netwm_desk_count_set(Ecore_X_Window root,
unsigned int n_desks)
{
LOGFN;
ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS,
&n_desks, 1);
}
EAPI void
ecore_x_netwm_desk_roots_set(Ecore_X_Window root,
Ecore_X_Window *vroots,
unsigned int n_desks)
{
LOGFN;
ecore_x_window_prop_window_set(root,
ECORE_X_ATOM_NET_VIRTUAL_ROOTS,
vroots,
n_desks);
}
EAPI void
ecore_x_netwm_desk_names_set(Ecore_X_Window root,
const char **names,
unsigned int n_desks)
{
char ss[32], *buf, *t;
const char *s;
unsigned int i;
int l, len;
LOGFN;
buf = NULL;
len = 0;
for (i = 0; i < n_desks; i++)
{
s = (names) ? names[i] : NULL;
if (!s)
{
/* Default to "Desk-<number>" */
sprintf(ss, "Desk-%u", i);
s = ss;
}
l = strlen(s) + 1;
t = realloc(buf, len + l);
if (t)
{
buf = t;
memcpy(buf + len, s, l);
}
len += l;
}
_ATOM_SET_UTF8_STRING_LIST(root, ECORE_X_ATOM_NET_DESKTOP_NAMES, buf, len);
if (_ecore_xlib_sync) ecore_x_sync();
free(buf);
}
EAPI void
ecore_x_netwm_desk_size_set(Ecore_X_Window root,
unsigned int width,
unsigned int height)
{
unsigned int size[2];
LOGFN;
size[0] = width;
size[1] = height;
ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, size,
2);
}
EAPI void
ecore_x_netwm_desk_viewports_set(Ecore_X_Window root,
unsigned int *origins,
unsigned int n_desks)
{
LOGFN;
ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT,
origins, 2 * n_desks);
}
EAPI void
ecore_x_netwm_desk_layout_set(Ecore_X_Window root,
int orientation,
int columns,
int rows,
int starting_corner)
{
unsigned int layout[4];
LOGFN;
layout[0] = orientation;
layout[1] = columns;
layout[2] = rows;
layout[3] = starting_corner;
ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT,
layout, 4);
}
EAPI void
ecore_x_netwm_desk_workareas_set(Ecore_X_Window root,
unsigned int *areas,
unsigned int n_desks)
{
LOGFN;
ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas,
4 * n_desks);
}
EAPI unsigned int *
ecore_x_netwm_desk_workareas_get(Ecore_X_Window root, unsigned int *n_desks)
{
int ret;
unsigned int *areas = NULL;
if (!root) root = DefaultRootWindow(_ecore_x_disp);
ret = ecore_x_window_prop_card32_list_get(root, ECORE_X_ATOM_NET_WORKAREA,
&areas);
if (!areas)
{
if (n_desks) *n_desks = 0;
return 0;
}
if (n_desks) *n_desks = ret / 4;
return areas;
}
EAPI void
ecore_x_netwm_desk_current_set(Ecore_X_Window root,
unsigned int desk)
{
LOGFN;
ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, &desk,
1);
}
EAPI void
ecore_x_netwm_showing_desktop_set(Ecore_X_Window root,
Eina_Bool on)
{
unsigned int val;
LOGFN;
val = (on) ? 1 : 0;
ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, &val,
1);
}
/*
* Client status
*/
/* Mapping order */
EAPI void
ecore_x_netwm_client_list_set(Ecore_X_Window root,
Ecore_X_Window *p_clients,
unsigned int n_clients)
{
LOGFN;
ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST,
p_clients, n_clients);
}
/* Stacking order */
EAPI void
ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root,
Ecore_X_Window *p_clients,
unsigned int n_clients)
{
LOGFN;
ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING,
p_clients, n_clients);
}
EAPI void
ecore_x_netwm_client_active_set(Ecore_X_Window root,
Ecore_X_Window win)
{
LOGFN;
ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_ACTIVE_WINDOW,
&win, 1);
}
EAPI void
ecore_x_netwm_client_active_request(Ecore_X_Window root,
Ecore_X_Window win,
int type,
Ecore_X_Window current_win)
{
XEvent xev = { 0 };
LOGFN;
if (!root)
root = DefaultRootWindow(_ecore_x_disp);
xev.xclient.type = ClientMessage;
xev.xclient.display = _ecore_x_disp;
xev.xclient.window = win;
xev.xclient.message_type = ECORE_X_ATOM_NET_ACTIVE_WINDOW;
xev.xclient.format = 32;
xev.xclient.data.l[0] = type;
xev.xclient.data.l[1] = CurrentTime;
xev.xclient.data.l[2] = current_win;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
XSendEvent(_ecore_x_disp, root, False,
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
if (_ecore_xlib_sync) ecore_x_sync();
}
EAPI void
ecore_x_netwm_name_set(Ecore_X_Window win,
const char *name)
{
LOGFN;
_ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_NAME, name);
}
EAPI int
ecore_x_netwm_name_get(Ecore_X_Window win,
char **name)
{
LOGFN;
if (name)
*name = _ecore_x_window_prop_string_utf8_get(win,
ECORE_X_ATOM_NET_WM_NAME);
return 1;
}
EAPI void
ecore_x_netwm_startup_id_set(Ecore_X_Window win,
const char *id)
{
LOGFN;
_ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_STARTUP_ID, id);
}
EAPI int
ecore_x_netwm_startup_id_get(Ecore_X_Window win,
char **id)
{
LOGFN;
if (id)
*id = _ecore_x_window_prop_string_utf8_get(win,
ECORE_X_ATOM_NET_STARTUP_ID);
return 1;
}
EAPI void
ecore_x_netwm_visible_name_set(Ecore_X_Window win,
const char *name)
{
LOGFN;
_ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME,
name);
}
EAPI int
ecore_x_netwm_visible_name_get(Ecore_X_Window win,
char **name)
{
LOGFN;
if (name)
*name = _ecore_x_window_prop_string_utf8_get(
win,
ECORE_X_ATOM_NET_WM_VISIBLE_NAME);
return 1;
}
EAPI void
ecore_x_netwm_icon_name_set(Ecore_X_Window win,
const char *name)
{
LOGFN;
_ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME,
name);
}
EAPI int
ecore_x_netwm_icon_name_get(Ecore_X_Window win,
char **name)
{
LOGFN;
if (name)
*name = _ecore_x_window_prop_string_utf8_get(
win,
ECORE_X_ATOM_NET_WM_ICON_NAME);
return 1;
}
EAPI void
ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win,
const char *name)
{
LOGFN;
_ecore_x_window_prop_string_utf8_set(win,
ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME,
name);
}
EAPI int
ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win,
char **name)
{
LOGFN;
if (name)
*name = _ecore_x_window_prop_string_utf8_get(
win,
ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME);
return 1;
}
EAPI void
ecore_x_netwm_desktop_set(Ecore_X_Window win,
unsigned int desk)
{
LOGFN;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1);
}
EAPI Eina_Bool
ecore_x_netwm_desktop_get(Ecore_X_Window win,
unsigned int *desk)
{
int ret;
unsigned int tmp;
LOGFN;
ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP,
&tmp, 1);
if (desk)
*desk = tmp;
return ret == 1 ? EINA_TRUE : EINA_FALSE;
}
/*
* _NET_WM_STRUT is deprecated
*/
EAPI void
ecore_x_netwm_strut_set(Ecore_X_Window win,
int left,
int right,
int top,
int bottom)
{
unsigned int strut[4];
LOGFN;
strut[0] = left;
strut[1] = right;
strut[2] = top;
strut[3] = bottom;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4);
}
/*
* _NET_WM_STRUT is deprecated
*/
EAPI Eina_Bool
ecore_x_netwm_strut_get(Ecore_X_Window win,
int *left,
int *right,
int *top,
int *bottom)
{
int ret = 0;
unsigned int strut[4];
LOGFN;
ret = ecore_x_window_prop_card32_get(win,
ECORE_X_ATOM_NET_WM_STRUT,
strut,
4);
if (ret != 4)
return EINA_FALSE;
if (left)
*left = strut[0];
if (right)
*right = strut[1];
if (top)
*top = strut[2];
if (bottom)
*bottom = strut[3];
return EINA_TRUE;
}
EAPI void
ecore_x_netwm_strut_partial_set(Ecore_X_Window win,
int left,
int right,
int top,
int bottom,
int left_start_y,
int left_end_y,
int right_start_y,
int right_end_y,
int top_start_x,
int top_end_x,
int bottom_start_x,
int bottom_end_x)
{
unsigned int strut[12];
LOGFN;
strut[0] = left;
strut[1] = right;
strut[2] = top;
strut[3] = bottom;
strut[4] = left_start_y;
strut[5] = left_end_y;
strut[6] = right_start_y;
strut[7] = right_end_y;
strut[8] = top_start_x;
strut[9] = top_end_x;
strut[10] = bottom_start_x;
strut[11] = bottom_end_x;
ecore_x_window_prop_card32_set(win,
ECORE_X_ATOM_NET_WM_STRUT_PARTIAL,
strut,
12);
}
EAPI Eina_Bool
ecore_x_netwm_strut_partial_get(Ecore_X_Window win,
int *left,
int *right,
int *top,
int *bottom,
int *left_start_y,
int *left_end_y,
int *right_start_y,
int *right_end_y,
int *top_start_x,
int *top_end_x,
int *bottom_start_x,
int *bottom_end_x)
{
int ret = 0;
unsigned int strut[12];
LOGFN;
ret = ecore_x_window_prop_card32_get(win,
ECORE_X_ATOM_NET_WM_STRUT_PARTIAL,
strut,
12);
if (ret != 12)
return EINA_FALSE;
if (left)
*left = strut[0];
if (right)
*right = strut[1];
if (top)
*top = strut[2];
if (bottom)
*bottom = strut[3];
if (left_start_y)
*left_start_y = strut[4];
if (left_end_y)
*left_end_y = strut[5];
if (right_start_y)
*right_start_y = strut[6];
if (right_end_y)
*right_end_y = strut[7];
if (top_start_x)
*top_start_x = strut[8];
if (top_end_x)
*top_end_x = strut[9];
if (bottom_start_x)
*bottom_start_x = strut[10];
if (bottom_end_x)
*bottom_end_x = strut[11];
return EINA_TRUE;
}
EAPI void
ecore_x_netwm_icons_set(Ecore_X_Window win,
Ecore_X_Icon *icon,
int num)
{
unsigned int *data, *p, *p2;
unsigned int i, size, x, y;
LOGFN;
size = 0;
for (i = 0; i < (unsigned int)num; i++)
{
size += 2 + (icon[i].width * icon[i].height);
}
data = malloc(size * sizeof(unsigned int));
if (!data) return;
p = data;
for (i = 0; i < (unsigned int)num; i++)
{
p[0] = icon[i].width;
p[1] = icon[i].height;
p += 2;
p2 = icon[i].data;
for (y = 0; y < icon[i].height; y++)
{
for (x = 0; x < icon[i].width; x++)
{
unsigned int r, g, b, a;
a = (*p2 >> 24) & 0xff;
r = (*p2 >> 16) & 0xff;
g = (*p2 >> 8 ) & 0xff;
b = (*p2 ) & 0xff;
if ((a > 0) && (a < 255))
{
// unpremul
r = (r * 255) / a;
g = (g * 255) / a;
b = (b * 255) / a;
}
*p = (a << 24) | (r << 16) | (g << 8) | b;
p++;
p2++;
}
}
}
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_ICON,
data, size);
free(data);
}
EAPI Eina_Bool
ecore_x_netwm_icons_get(Ecore_X_Window win,
Ecore_X_Icon **icon,
int *num)
{
unsigned int *data, *p;
unsigned int *src;
unsigned int len, icons, i;
int num_ret;
LOGFN;
if (num)
*num = 0;
if (icon)
*icon = NULL;
num_ret = ecore_x_window_prop_card32_list_get(win, ECORE_X_ATOM_NET_WM_ICON,
&data);
if (num_ret <= 0)
return EINA_FALSE;
if (!data)
return EINA_FALSE;
if (num_ret < 2)
{
free(data);
return EINA_FALSE;
}
/* Check how many icons there are */
icons = 0;
p = data;
while (p)
{
len = p[0] * p[1];
p += (len + 2);
if ((p - data) > num_ret)
{
free(data);
return EINA_FALSE;
}
icons++;
if ((p - data) == num_ret)
p = NULL;
}
if (num)
*num = icons;
/* If the user doesn't want the icons, return */
if (!icon)
{
free(data);
return EINA_TRUE;
}
/* Allocate memory */
*icon = malloc(icons * sizeof(Ecore_X_Icon));
if (!(*icon))
{
free(data);
return EINA_FALSE;
}
/* Fetch the icons */
p = data;
for (i = 0; i < icons; i++)
{
unsigned int *ps, *pd, *pe;
len = p[0] * p[1];
((*icon)[i]).width = p[0];
((*icon)[i]).height = p[1];
src = &(p[2]);
((*icon)[i]).data = malloc(len * sizeof(unsigned int));
if (!((*icon)[i]).data)
{
while (i)
free(((*icon)[--i]).data);
free(*icon);
free(data);
return EINA_FALSE;
}
pd = ((*icon)[i]).data;
ps = src;
pe = ps + len;
for (; ps < pe; ps++)
{
unsigned int r, g, b, a;
a = (*ps >> 24) & 0xff;
r = (((*ps >> 16) & 0xff) * a) / 255;
g = (((*ps >> 8) & 0xff) * a) / 255;
b = (((*ps) & 0xff) * a) / 255;
*pd = (a << 24) | (r << 16) | (g << 8) | (b);
pd++;
}
p += (len + 2);
}
free(data);
return EINA_TRUE;
}
EAPI void
ecore_x_netwm_icon_geometry_set(Ecore_X_Window win,
int x,
int y,
int width,
int height)
{
unsigned int geometry[4];
LOGFN;
geometry[0] = x;
geometry[1] = y;
geometry[2] = width;
geometry[3] = height;
ecore_x_window_prop_card32_set(win,
ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
geometry,
4);
}
EAPI Eina_Bool
ecore_x_netwm_icon_geometry_get(Ecore_X_Window win,
int *x,
int *y,
int *width,
int *height)
{
int ret;
unsigned int geometry[4];
LOGFN;
ret = ecore_x_window_prop_card32_get(win,
ECORE_X_ATOM_NET_WM_ICON_GEOMETRY,
geometry,
4);
if (ret != 4)
return EINA_FALSE;
if (x)
*x = geometry[0];
if (y)
*y = geometry[1];
if (width)
*width = geometry[2];
if (height)
*height = geometry[3];
return EINA_TRUE;
}
EAPI void
ecore_x_netwm_pid_set(Ecore_X_Window win,
int pid)
{
unsigned int tmp;
LOGFN;
tmp = pid;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_PID,
&tmp, 1);
}
EAPI Eina_Bool
ecore_x_netwm_pid_get(Ecore_X_Window win,
int *pid)
{
int ret;
unsigned int tmp;
LOGFN;
ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_PID,
&tmp, 1);
if (pid)
*pid = tmp;
return ret == 1 ? EINA_TRUE : EINA_FALSE;
}
EAPI void
ecore_x_netwm_handled_icons_set(Ecore_X_Window win)
{
LOGFN;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
NULL, 0);
}
EAPI Eina_Bool
ecore_x_netwm_handled_icons_get(Ecore_X_Window win)
{
int ret = 0;
LOGFN;
ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS,
NULL, 0);
return ret == 0 ? EINA_TRUE : EINA_FALSE;
}
EAPI void
ecore_x_netwm_user_time_set(Ecore_X_Window win,
unsigned int tim)
{
LOGFN;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_USER_TIME,
&tim, 1);
}
EAPI Eina_Bool
ecore_x_netwm_user_time_get(Ecore_X_Window win,
unsigned int *tim)
{
int ret;
unsigned int tmp;
LOGFN;
ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME,
&tmp, 1);
if (tim)
*tim = tmp;
return ret == 1 ? EINA_TRUE : EINA_FALSE;
}
Ecore_X_Window_State
_ecore_x_netwm_state_get(Ecore_X_Atom a)
{
if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL)
return ECORE_X_WINDOW_STATE_MODAL;
else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY)
return ECORE_X_WINDOW_STATE_STICKY;
else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT)
return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT;
else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ)
return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ;
else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED)
return ECORE_X_WINDOW_STATE_SHADED;
else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR)
return ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER)
return ECORE_X_WINDOW_STATE_SKIP_PAGER;
else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN)
return ECORE_X_WINDOW_STATE_HIDDEN;
else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN)
return ECORE_X_WINDOW_STATE_FULLSCREEN;
else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE)
return ECORE_X_WINDOW_STATE_ABOVE;
else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW)
return ECORE_X_WINDOW_STATE_BELOW;
else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION)
return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION;
else
return ECORE_X_WINDOW_STATE_UNKNOWN;
}
static Ecore_X_Atom
_ecore_x_netwm_state_atom_get(Ecore_X_Window_State s)
{
switch (s)
{
case ECORE_X_WINDOW_STATE_MODAL:
return ECORE_X_ATOM_NET_WM_STATE_MODAL;
case ECORE_X_WINDOW_STATE_STICKY:
return ECORE_X_ATOM_NET_WM_STATE_STICKY;
case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT;
case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ;
case ECORE_X_WINDOW_STATE_SHADED:
return ECORE_X_ATOM_NET_WM_STATE_SHADED;
case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR;
case ECORE_X_WINDOW_STATE_SKIP_PAGER:
return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER;
case ECORE_X_WINDOW_STATE_HIDDEN:
return ECORE_X_ATOM_NET_WM_STATE_HIDDEN;
case ECORE_X_WINDOW_STATE_FULLSCREEN:
return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN;
case ECORE_X_WINDOW_STATE_ABOVE:
return ECORE_X_ATOM_NET_WM_STATE_ABOVE;
case ECORE_X_WINDOW_STATE_BELOW:
return ECORE_X_ATOM_NET_WM_STATE_BELOW;
case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION;
default:
return 0;
}
}
EAPI void
ecore_x_netwm_window_state_set(Ecore_X_Window win,
Ecore_X_Window_State *state,
unsigned int num)
{
Ecore_X_Atom *set;
unsigned int i;
LOGFN;
if (!num)
{
ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_STATE);
return;
}
set = malloc(num * sizeof(Ecore_X_Atom));
if (!set)
return;
for (i = 0; i < num; i++)
set[i] = _ecore_x_netwm_state_atom_get(state[i]);
ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_STATE, set, num);
free(set);
}
EAPI Eina_Bool
ecore_x_netwm_window_state_get(Ecore_X_Window win,
Ecore_X_Window_State **state,
unsigned int *num)
{
int num_ret, i;
Ecore_X_Atom *atoms;
LOGFN;
if (num)
*num = 0;
if (state)
*state = NULL;
num_ret = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_STATE,
&atoms);
if (num_ret <= 0)
return EINA_FALSE;
if (state)
{
*state = malloc(num_ret * sizeof(Ecore_X_Window_State));
if (*state)
for (i = 0; i < num_ret; ++i)
(*state)[i] = _ecore_x_netwm_state_get(atoms[i]);
if (num)
*num = num_ret;
}
free(atoms);
return EINA_TRUE;
}
static Ecore_X_Window_Type
_ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom)
{
if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP)
return ECORE_X_WINDOW_TYPE_DESKTOP;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK)
return ECORE_X_WINDOW_TYPE_DOCK;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR)
return ECORE_X_WINDOW_TYPE_TOOLBAR;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU)
return ECORE_X_WINDOW_TYPE_MENU;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY)
return ECORE_X_WINDOW_TYPE_UTILITY;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH)
return ECORE_X_WINDOW_TYPE_SPLASH;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG)
return ECORE_X_WINDOW_TYPE_DIALOG;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL)
return ECORE_X_WINDOW_TYPE_NORMAL;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
return ECORE_X_WINDOW_TYPE_DROPDOWN_MENU;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU)
return ECORE_X_WINDOW_TYPE_POPUP_MENU;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP)
return ECORE_X_WINDOW_TYPE_TOOLTIP;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION)
return ECORE_X_WINDOW_TYPE_NOTIFICATION;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO)
return ECORE_X_WINDOW_TYPE_COMBO;
else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND)
return ECORE_X_WINDOW_TYPE_DND;
else
return ECORE_X_WINDOW_TYPE_UNKNOWN;
}
static Ecore_X_Atom
_ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type)
{
switch (type)
{
case ECORE_X_WINDOW_TYPE_DESKTOP:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP;
case ECORE_X_WINDOW_TYPE_DOCK:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK;
case ECORE_X_WINDOW_TYPE_TOOLBAR:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR;
case ECORE_X_WINDOW_TYPE_MENU:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU;
case ECORE_X_WINDOW_TYPE_UTILITY:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY;
case ECORE_X_WINDOW_TYPE_SPLASH:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH;
case ECORE_X_WINDOW_TYPE_DIALOG:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG;
case ECORE_X_WINDOW_TYPE_NORMAL:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL;
case ECORE_X_WINDOW_TYPE_DROPDOWN_MENU:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
case ECORE_X_WINDOW_TYPE_POPUP_MENU:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU;
case ECORE_X_WINDOW_TYPE_TOOLTIP:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP;
case ECORE_X_WINDOW_TYPE_NOTIFICATION:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION;
case ECORE_X_WINDOW_TYPE_COMBO:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO;
case ECORE_X_WINDOW_TYPE_DND:
return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND;
default:
return 0;
}
}
/*
* FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR
* , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG
*/
EAPI void
ecore_x_netwm_window_type_set(Ecore_X_Window win,
Ecore_X_Window_Type type)
{
Ecore_X_Atom atom;
LOGFN;
atom = _ecore_x_netwm_window_type_atom_get(type);
ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
&atom, 1);
}
/* FIXME: Maybe return 0 on some conditions? */
EAPI Eina_Bool
ecore_x_netwm_window_type_get(Ecore_X_Window win,
Ecore_X_Window_Type *type)
{
int num;
Ecore_X_Atom *atoms = NULL;
LOGFN;
if (type)
*type = ECORE_X_WINDOW_TYPE_NORMAL;
num = ecore_x_window_prop_atom_list_get(win,
ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
&atoms);
if ((type) && (num >= 1) && (atoms))
*type = _ecore_x_netwm_window_type_type_get(atoms[0]);
free(atoms);
if (num >= 1)
return EINA_TRUE;
return EINA_FALSE;
}
EAPI int
ecore_x_netwm_window_types_get(Ecore_X_Window win,
Ecore_X_Window_Type **types)
{
int num, i;
Ecore_X_Atom *atoms = NULL;
Ecore_X_Window_Type *atoms2 = NULL;
LOGFN;
if (types)
*types = NULL;
num = ecore_x_window_prop_atom_list_get(win,
ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
&atoms);
if ((num <= 0) || (!atoms))
{
if (atoms)
free(atoms);
return 0;
}
atoms2 = malloc(num * sizeof(Ecore_X_Window_Type));
if (!atoms2)
{
if (atoms) free(atoms);
return 0;
}
for (i = 0; i < num; i++)
atoms2[i] = _ecore_x_netwm_window_type_type_get(atoms[i]);
free(atoms);
if (types)
*types = atoms2;
else
free(atoms2);
return num;
}
static Ecore_X_Atom
_ecore_x_netwm_action_atom_get(Ecore_X_Action action)
{
switch (action)
{
case ECORE_X_ACTION_MOVE:
return ECORE_X_ATOM_NET_WM_ACTION_MOVE;
case ECORE_X_ACTION_RESIZE:
return ECORE_X_ATOM_NET_WM_ACTION_RESIZE;
case ECORE_X_ACTION_MINIMIZE:
return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE;
case ECORE_X_ACTION_SHADE:
return ECORE_X_ATOM_NET_WM_ACTION_SHADE;
case ECORE_X_ACTION_STICK:
return ECORE_X_ATOM_NET_WM_ACTION_STICK;
case ECORE_X_ACTION_MAXIMIZE_HORZ:
return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ;
case ECORE_X_ACTION_MAXIMIZE_VERT:
return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT;
case ECORE_X_ACTION_FULLSCREEN:
return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN;
case ECORE_X_ACTION_CHANGE_DESKTOP:
return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP;
case ECORE_X_ACTION_CLOSE:
return ECORE_X_ATOM_NET_WM_ACTION_CLOSE;
case ECORE_X_ACTION_ABOVE:
return ECORE_X_ATOM_NET_WM_ACTION_ABOVE;
case ECORE_X_ACTION_BELOW:
return ECORE_X_ATOM_NET_WM_ACTION_BELOW;
default:
return 0;
}
}
/* FIXME: Get complete list */
EAPI Eina_Bool
ecore_x_netwm_allowed_action_isset(Ecore_X_Window win,
Ecore_X_Action action)
{
int num, i;
Ecore_X_Atom *atoms, atom;
Eina_Bool ret = EINA_FALSE;
LOGFN;
num = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE,
&atoms);
if (num <= 0)
return ret;
atom = _ecore_x_netwm_action_atom_get(action);
for (i = 0; i < num; ++i)
{
if (atom == atoms[i])
{
ret = 1;
break;
}
}
free(atoms);
return ret;
}
/* FIXME: Set complete list */
EAPI void
ecore_x_netwm_allowed_action_set(Ecore_X_Window win,
Ecore_X_Action *action,
unsigned int num)
{
Ecore_X_Atom *set;
unsigned int i;
LOGFN;
if (!num)
{
ecore_x_window_prop_property_del(win,
ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS);
return;
}
set = malloc(num * sizeof(Ecore_X_Atom));
if (!set)
return;
for (i = 0; i < num; i++)
set[i] = _ecore_x_netwm_action_atom_get(action[i]);
ecore_x_window_prop_atom_set(win,
ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
set,
num);
free(set);
}
EAPI Eina_Bool
ecore_x_netwm_allowed_action_get(Ecore_X_Window win,
Ecore_X_Action **action,
unsigned int *num)
{
int num_ret, i;
Ecore_X_Atom *atoms;
LOGFN;
if (num)
*num = 0;
if (action)
*action = NULL;
num_ret = ecore_x_window_prop_atom_list_get(
win,
ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS,
&atoms);
if (num_ret <= 0)
return EINA_FALSE;
if (action)
{
*action = malloc(num_ret * sizeof(Ecore_X_Action));
if (*action)
for (i = 0; i < num_ret; ++i)
(*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]);
if (num)
*num = num_ret;
}
free(atoms);
return EINA_TRUE;
}
EAPI void
ecore_x_netwm_opacity_set(Ecore_X_Window win,
unsigned int opacity)
{
LOGFN;
ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
&opacity, 1);
}
EAPI Eina_Bool
ecore_x_netwm_opacity_get(Ecore_X_Window win,
unsigned int *opacity)
{
int ret;
unsigned int tmp;
LOGFN;
ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY,
&tmp, 1);
if (opacity)
*opacity = tmp;
return ret == 1 ? EINA_TRUE : EINA_FALSE;
}
EAPI void
ecore_x_netwm_frame_size_set(Ecore_X_Window win,
int fl,
int fr,
int ft,
int fb)
{
unsigned int frames[4];
LOGFN;
frames[0] = fl;
frames[1] = fr;
frames[2] = ft;
frames[3] = fb;
ecore_x_window_prop_card32_set(win,
ECORE_X_ATOM_NET_FRAME_EXTENTS,
frames,
4);
}
EAPI Eina_Bool
ecore_x_netwm_frame_size_get(Ecore_X_Window win,
int *fl,
int *fr,
int *ft,
int *fb)
{
int ret = 0;
unsigned int frames[4];
LOGFN;
ret = ecore_x_window_prop_card32_get(win,
ECORE_X_ATOM_NET_FRAME_EXTENTS,
frames,
4);
if (ret != 4)
return EINA_FALSE;
if (fl)
*fl = frames[0];
if (fr)
*fr = frames[1];
if (ft)
*ft = frames[2];
if (fb)
*fb = frames[3];
return EINA_TRUE;
}
EAPI Eina_Bool
ecore_x_netwm_sync_counter_get(Ecore_X_Window win,
Ecore_X_Sync_Counter *counter)
{
int ret;
unsigned int tmp;
LOGFN;
ret = ecore_x_window_prop_card32_get(
win,
ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER,
&tmp,
1);
if (counter)
*counter = tmp;
return ret == 1 ? EINA_TRUE : EINA_FALSE;
}
EAPI void
ecore_x_netwm_ping_send(Ecore_X_Window win)
{
XEvent xev = { 0 };
if (!win)
return;
LOGFN;
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_NET_WM_PING;
xev.xclient.data.l[1] = _ecore_x_event_last_time;
xev.xclient.data.l[2] = win;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
if (_ecore_xlib_sync) ecore_x_sync();
}
EAPI void
ecore_x_netwm_sync_request_send(Ecore_X_Window win,
unsigned int serial)
{
XSyncValue value;
XEvent xev = { 0 };
if (!win)
return;
LOGFN;
XSyncIntToValue(&value, (int)serial);
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_NET_WM_SYNC_REQUEST;
xev.xclient.data.l[1] = _ecore_x_event_last_time;
xev.xclient.data.l[2] = XSyncValueLow32(value);
xev.xclient.data.l[3] = XSyncValueHigh32(value);
xev.xclient.data.l[4] = 0;
XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev);
if (_ecore_xlib_sync) ecore_x_sync();
}
EAPI void
ecore_x_netwm_state_request_send(Ecore_X_Window win,
Ecore_X_Window root,
Ecore_X_Window_State s1,
Ecore_X_Window_State s2,
Eina_Bool set)
{
XEvent xev = { 0 };
if (!win)
return;
LOGFN;
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_NET_WM_STATE;
xev.xclient.data.l[0] = !!set;
xev.xclient.data.l[1] = _ecore_x_netwm_state_atom_get(s1);
xev.xclient.data.l[2] = _ecore_x_netwm_state_atom_get(s2);
/* 1 == normal client, if someone wants to use this
* function in a pager, this should be 2 */
xev.xclient.data.l[3] = 1;
xev.xclient.data.l[4] = 0;
XSendEvent(_ecore_x_disp, root, False,
SubstructureNotifyMask | SubstructureRedirectMask, &xev);
if (_ecore_xlib_sync) ecore_x_sync();
}
EAPI void
ecore_x_netwm_desktop_request_send(Ecore_X_Window win,
Ecore_X_Window root,
unsigned int desktop)
{
XEvent xev = { 0 };
if (!win)
return;
LOGFN;
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_NET_WM_DESKTOP;
xev.xclient.data.l[0] = desktop;
XSendEvent(_ecore_x_disp, root, False,
SubstructureNotifyMask | SubstructureRedirectMask, &xev);
if (_ecore_xlib_sync) ecore_x_sync();
}
EAPI void
ecore_x_netwm_moveresize_request_send(Ecore_X_Window win,
int x,
int y,
Ecore_X_Netwm_Direction direction,
unsigned int button)
{
XEvent xev = { 0 };
if (!win)
return;
LOGFN;
xev.xclient.window = win;
xev.xclient.type = ClientMessage;
xev.xclient.message_type = ECORE_X_ATOM_NET_WM_MOVERESIZE;
xev.xclient.format = 32;
xev.xclient.data.l[0] = x;
xev.xclient.data.l[1] = y;
xev.xclient.data.l[2] = direction;
xev.xclient.data.l[3] = button;
xev.xclient.data.l[4] = 1;
XSendEvent(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp), False,
SubstructureNotifyMask | SubstructureRedirectMask, &xev);
if (_ecore_xlib_sync) ecore_x_sync();
}
int
_ecore_x_netwm_startup_info_begin(Ecore_X_Window win EINA_UNUSED,
char *data EINA_UNUSED)
{
#if 0
Ecore_X_Startup_Info *info;
unsigned char *exists = 0;
if (!startup_info)
return 0;
info = eina_hash_find(startup_info, (void *)win);
if (info)
{
exists = 1;
WRN("Already got info for win: 0x%x", win);
_ecore_x_netwm_startup_info_free(info);
}
info = calloc(1, sizeof(Ecore_X_Startup_Info));
if (!info)
return 0;
info->win = win;
info->length = 0;
info->buffer_size = 161;
info->buffer = calloc(info->buffer_size, sizeof(char));
if (!info->buffer)
{
_ecore_x_netwm_startup_info_free(info);
return 0;
}
memcpy(info->buffer, data, 20);
info->length += 20;
info->buffer[info->length] = 0;
if (exists)
eina_hash_modify(startup_info, (void *)info->win, info);
else
eina_hash_add(startup_info, (void *)info->win, info);
if (strlen(info->buffer) != 20)
/* We have a '\0' in there, the message is done */
_ecore_x_netwm_startup_info_process(info);
#endif /* if 0 */
return 1;
}
int
_ecore_x_netwm_startup_info(Ecore_X_Window win EINA_UNUSED,
char *data EINA_UNUSED)
{
#if 0
Ecore_X_Startup_Info *info;
char *p;
if (!startup_info)
return 0;
info = eina_hash_find(startup_info, (void *)win);
if (!info)
return 0;
if ((info->length + 20) > info->buffer_size)
{
info->buffer_size += 160;
info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char));
if (!info->buffer)
{
eina_hash_del(startup_info, (void *)info->win);
_ecore_x_netwm_startup_info_free(info);
return 0;
}
}
memcpy(info->buffer + info->length, data, 20);
p = info->buffer + info->length;
info->length += 20;
info->buffer[info->length] = 0;
if (strlen(p) != 20)
/* We have a '\0' in there, the message is done */
_ecore_x_netwm_startup_info_process(info);
#endif /* if 0 */
return 1;
}
/*
* Set UTF-8 string property
*/
static void
_ecore_x_window_prop_string_utf8_set(Ecore_X_Window win,
Ecore_X_Atom atom,
const char *str)
{
XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8,
PropModeReplace, (unsigned char *)str, strlen(str));
if (_ecore_xlib_sync) ecore_x_sync();
}
/*
* Get UTF-8 string property
*/
static char *
_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win,
Ecore_X_Atom atom)
{
char *str;
unsigned char *prop_ret;
Atom type_ret;
unsigned long bytes_after, num_ret;
int format_ret;
str = NULL;
prop_ret = NULL;
XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False,
ECORE_X_ATOM_UTF8_STRING, &type_ret,
&format_ret, &num_ret, &bytes_after, &prop_ret);
if (_ecore_xlib_sync) ecore_x_sync();
if (prop_ret && num_ret > 0 && format_ret == 8)
{
str = malloc(num_ret + 1);
if (str)
{
memcpy(str, prop_ret, num_ret);
str[num_ret] = '\0';
}
}
if (prop_ret)
XFree(prop_ret);
return str;
}
#if 0 /* Unused */
/*
* Process startup info
*/
static int
_ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info)
{
Ecore_X_Event_Startup_Sequence *e;
int event;
char *p;
p = strchr(info->buffer, ':');
if (!p)
{
eina_hash_del(startup_info, (void *)info->win);
_ecore_x_netwm_startup_info_free(info);
return 0;
}
*p = 0;
if (!strcmp(info->buffer, "new"))
{
if (info->init)
event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
else
event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW;
info->init = 1;
}
else if (!strcmp(info->buffer, "change"))
event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE;
else if (!strcmp(info->buffer, "remove"))
event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE;
else
{
eina_hash_del(startup_info, (void *)info->win);
_ecore_x_netwm_startup_info_free(info);
return 0;
}
p++;
if (!_ecore_x_netwm_startup_info_parse(info, p))
{
eina_hash_del(startup_info, (void *)info->win);
_ecore_x_netwm_startup_info_free(info);
return 0;
}
if (info->init)
{
e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence));
if (!e)
{
eina_hash_del(startup_info, (void *)info->win);
_ecore_x_netwm_startup_info_free(info);
return 0;
}
e->win = info->win;
ecore_event_add(event, e, NULL, NULL);
}
if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE)
{
eina_hash_del(startup_info, (void *)info->win);
_ecore_x_netwm_startup_info_free(info);
}
else
{
/* Discard buffer */
info->length = 0;
info->buffer[0] = 0;
}
return 1;
}
/*
* Parse startup info
*/
static int
_ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info,
char *data)
{
while (*data)
{
int in_quot_sing, in_quot_dbl, escaped;
char *p, *pp;
char *key;
char value[1024];
/* Skip space */
while (*data == ' ')
data++;
/* Get key */
key = data;
data = strchr(key, '=');
if (!data)
return 0;
*data = 0;
data++;
/* Get value */
p = data;
pp = value;
in_quot_dbl = 0;
in_quot_sing = 0;
escaped = 0;
while (*p)
{
if ((pp - value) >= 1024)
return 0;
if (escaped)
{
*pp = *p;
pp++;
escaped = 0;
}
else if (in_quot_sing)
{
if (*p == '\\')
escaped = 1;
else if (*p == '\'')
in_quot_sing = 0;
else
{
*pp = *p;
pp++;
}
}
else if (in_quot_dbl)
{
if (*p == '\\')
escaped = 1;
else if (*p == '\"')
in_quot_dbl = 0;
else
{
*pp = *p;
pp++;
}
}
else
{
if (*p == '\\')
escaped = 1;
else if (*p == '\'')
in_quot_sing = 1;
else if (*p == '\"')
in_quot_dbl = 1;
else if (*p == ' ')
break;
else
{
*pp = *p;
pp++;
}
}
p++;
}
if ((in_quot_dbl) || (in_quot_sing))
return 0;
data = p;
*pp = 0;
/* Parse info */
if (!strcmp(key, "ID"))
{
if ((info->id) && (strcmp(info->id, value)))
return 0;
info->id = strdup(value);
p = strstr(value, "_TIME");
if (p)
info->timestamp = atoi(p + 5);
}
else if (!strcmp(key, "NAME"))
{
if (info->name)
free(info->name);
info->name = strdup(value);
}
else if (!strcmp(key, "SCREEN"))
info->screen = atoi(value);
else if (!strcmp(key, "BIN"))
{
if (info->bin)
free(info->bin);
info->bin = strdup(value);
}
else if (!strcmp(key, "ICON"))
{
if (info->icon)
free(info->icon);
info->icon = strdup(value);
}
else if (!strcmp(key, "DESKTOP"))
info->desktop = atoi(value);
else if (!strcmp(key, "TIMESTAMP"))
{
if (!info->timestamp)
info->timestamp = atoi(value);
}
else if (!strcmp(key, "DESCRIPTION"))
{
if (info->description)
free(info->description);
info->description = strdup(value);
}
else if (!strcmp(key, "WMCLASS"))
{
if (info->wmclass)
free(info->wmclass);
info->wmclass = strdup(value);
}
else if (!strcmp(key, "SILENT"))
info->silent = atoi(value);
else
ERR("Ecore X Sequence, Unknown: %s=%s", key, value);
}
if (!info->id)
return 0;
return 1;
}
#endif /* if 0 */
/*
* Free startup info struct
*/
static void
_ecore_x_netwm_startup_info_free(void *data)
{
Ecore_X_Startup_Info *info;
info = data;
if (!info)
return;
if (info->buffer)
free(info->buffer);
if (info->id)
free(info->id);
if (info->name)
free(info->name);
if (info->bin)
free(info->bin);
if (info->icon)
free(info->icon);
if (info->description)
free(info->description);
if (info->wmclass)
free(info->wmclass);
free(info);
}
/*
* Is screen composited?
*/
EAPI Eina_Bool
ecore_x_screen_is_composited(int screen)
{
Ecore_X_Window win;
Ecore_X_Atom atom;
char buf[32];
LOGFN;
snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
atom = XInternAtom(_ecore_x_disp, buf, True);
if (atom == None) return EINA_FALSE;
win = XGetSelectionOwner(_ecore_x_disp, atom);
if (_ecore_xlib_sync) ecore_x_sync();
return (win != None) ? EINA_TRUE : EINA_FALSE;
}
EAPI void
ecore_x_screen_is_composited_set(int screen,
Ecore_X_Window win)
{
Ecore_X_Atom atom;
char buf[32];
LOGFN;
snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen);
atom = XInternAtom(_ecore_x_disp, buf, False);
if (atom == None) return;
XSetSelectionOwner(_ecore_x_disp, atom, win, _ecore_x_event_last_time);
if (_ecore_xlib_sync) ecore_x_sync();
}