2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
c_x11.c
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2017-01-13 04:29:42 +01:00
|
|
|
(c) 2000-2017 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2009-08-17 12:41:51 +02:00
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
2007-12-30 17:41:49 +01:00
|
|
|
any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2009-08-17 12:41:51 +02:00
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2007-12-30 17:41:49 +01:00
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2011-06-03 02:51:09 +02:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
2011-12-31 03:39:20 +01:00
|
|
|
MA 02110-1301, USA.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
#define __C_X11_C
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
#include "x11.h"
|
2014-06-02 02:39:44 +02:00
|
|
|
#include "c_x11.h"
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-04-24 03:00:46 +02:00
|
|
|
//#define DEBUG_ICON 1
|
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
#if 0
|
|
|
|
typedef struct PROPERTY_FORMAT
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
Atom atom;
|
|
|
|
const char *format;
|
|
|
|
};
|
|
|
|
|
|
|
|
static PROPERTY_FORMAT _property_format[] = {
|
|
|
|
{"ARC" XA_ARC, "16iiccii" },
|
|
|
|
{"ATOM", XA_ATOM, "32a" },
|
|
|
|
{"BITMAP", XA_BITMAP, "32x" },
|
|
|
|
{"CARDINAL", XA_CARDINAL, "0c" },
|
|
|
|
{"COLORMAP", XA_COLORMAP, "32x" },
|
|
|
|
{"CURSOR", XA_CURSOR, "32x" },
|
|
|
|
{"DRAWABLE", XA_DRAWABLE, "32x" },
|
|
|
|
{"FONT", XA_FONT, "32x" },
|
|
|
|
{"INTEGER", XA_INTEGER, "0i" },
|
|
|
|
{"PIXMAP", XA_PIXMAP, "32x" },
|
|
|
|
{"POINT", XA_POINT, "16ii" },
|
|
|
|
{"RECTANGLE", XA_RECTANGLE, "16iicc" },
|
|
|
|
{"RGB_COLOR_MAP", XA_RGB_COLOR_MAP, "32xcccccccxx" },
|
|
|
|
{"STRING", XA_STRING, "8s" },
|
|
|
|
{"WINDOW", XA_WINDOW, "32x" },
|
|
|
|
{"VISUALID", XA_VISUALID, "32x" },
|
|
|
|
{"WM_COLORMAP_WINDOWS", 0, "32x" },
|
|
|
|
{"WM_COMMAND", XA_WM_COMMAND, "8s" },
|
|
|
|
{"WM_HINTS", XA_WM_HINTS, "32mbcxxiixx" },
|
|
|
|
{"WM_ICON_NAME", XA_WM_ICON_NAME, "8t" },
|
|
|
|
{"WM_ICON_SIZE", XA_WM_ICON_SIZE, "32cccccc" },
|
|
|
|
{"WM_NAME", XA_WM_NAME, "8t" },
|
|
|
|
{"WM_PROTOCOLS", 0, "32a" },
|
|
|
|
{"WM_SIZE_HINTS", XA_WM_SIZE_HINTS, "32mii" },
|
|
|
|
{"WM_STATE", 0, "32cx" }
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2008-04-05 15:06:08 +02:00
|
|
|
DECLARE_EVENT(EVENT_Change);
|
|
|
|
DECLARE_EVENT(EVENT_Window);
|
|
|
|
|
2008-04-02 03:15:31 +02:00
|
|
|
/*BEGIN_METHOD_VOID(CDESKTOP_init)
|
|
|
|
|
|
|
|
X11_init();
|
|
|
|
|
|
|
|
END_METHOD*/
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_FindWindow, GB_STRING title; GB_STRING klass; GB_STRING role)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
Window *windows;
|
|
|
|
Window win;
|
|
|
|
int count;
|
|
|
|
int i;
|
|
|
|
char *title = MISSING(title) ? NULL : STRING(title);
|
2008-01-17 22:39:26 +01:00
|
|
|
int ltitle = MISSING(title) ? 0 : LENGTH(title);
|
2007-12-30 17:41:49 +01:00
|
|
|
char *klass = MISSING(klass) ? NULL : STRING(klass);
|
2008-01-17 22:39:26 +01:00
|
|
|
int lklass = MISSING(klass) ? 0 : LENGTH(klass);
|
2007-12-30 17:41:49 +01:00
|
|
|
char *role = MISSING(role) ? NULL : STRING(role);
|
2008-01-17 22:39:26 +01:00
|
|
|
int lrole = MISSING(role) ? 0 : LENGTH(role);
|
2007-12-30 17:41:49 +01:00
|
|
|
char *prop;
|
2008-01-17 22:39:26 +01:00
|
|
|
int lprop;
|
2007-12-30 17:41:49 +01:00
|
|
|
GB_ARRAY result;
|
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
2008-01-17 22:39:26 +01:00
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
GB.Array.New(&result, GB_T_INTEGER, 0);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
X11_find_windows(&windows, &count);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
win = windows[i];
|
2011-02-12 02:18:32 +01:00
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
if (ltitle)
|
|
|
|
{
|
|
|
|
X11_get_window_title(win, &prop, &lprop);
|
|
|
|
if (!GB.MatchString(title, ltitle, prop, lprop))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lklass)
|
|
|
|
{
|
|
|
|
X11_get_window_class(win, &prop, &lprop);
|
|
|
|
//qDebug("class = %.*s", lprop, prop);
|
|
|
|
if (!GB.MatchString(klass, lklass, prop, lprop))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lrole)
|
|
|
|
{
|
|
|
|
X11_get_window_role(win, &prop, &lprop);
|
|
|
|
//qDebug("role = %.*s", lprop, prop);
|
|
|
|
if (!GB.MatchString(role, lrole, prop, lprop))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-07-14 20:38:30 +02:00
|
|
|
*((int *)GB.Array.Add(result)) = (int)win;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
GB.ReturnObject(result);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_SendKey, GB_STRING key; GB_BOOLEAN press)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
char *error;
|
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
error = X11_send_key(GB.ToZeroString(ARG(key)), VARG(press));
|
|
|
|
if (error) GB.Error(error);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_PROPERTY(X11_RootWindow)
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
2014-05-17 01:43:36 +02:00
|
|
|
|
2009-07-14 20:38:30 +02:00
|
|
|
GB.ReturnInteger(X11_root);
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_PROPERTY(X11_Time)
|
2012-10-02 10:01:25 +02:00
|
|
|
|
|
|
|
intptr_t time;
|
|
|
|
|
|
|
|
GB.Component.GetInfo("TIME", POINTER(&time));
|
|
|
|
|
|
|
|
GB.ReturnInteger((int)time);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
2014-05-17 01:43:36 +02:00
|
|
|
BEGIN_METHOD(X11_GetWindowProperty, GB_INTEGER window; GB_STRING name)
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
char *value;
|
|
|
|
Atom type;
|
|
|
|
Atom prop;
|
|
|
|
int format;
|
|
|
|
GB_ARRAY array;
|
|
|
|
int i, count;
|
|
|
|
char *name;
|
2008-04-05 15:06:08 +02:00
|
|
|
Window window;
|
2011-11-14 00:18:04 +01:00
|
|
|
GB_VARIANT_VALUE ret;
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
prop = X11_intern_atom(GB.ToZeroString(ARG(name)), FALSE);
|
|
|
|
if (prop == None)
|
|
|
|
{
|
2011-11-14 00:18:04 +01:00
|
|
|
GB.ReturnVariant(NULL);
|
2008-03-31 21:04:28 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-17 01:43:36 +02:00
|
|
|
window = VARG(window);
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2009-07-14 20:38:30 +02:00
|
|
|
value = X11_get_property(window, prop, &type, &format, &count);
|
2008-04-02 03:15:31 +02:00
|
|
|
if (!value)
|
|
|
|
{
|
2011-11-14 00:18:04 +01:00
|
|
|
GB.ReturnVariant(NULL);
|
2008-04-02 03:15:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
if (type == XA_ATOM)
|
|
|
|
{
|
|
|
|
GB.Array.New(&array, GB_T_STRING, count);
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
name = XGetAtomName(X11_display, *((Atom *)value + i));
|
2010-06-05 01:48:53 +02:00
|
|
|
*(char **)GB.Array.Get(array, i) = GB.NewZeroString(name);
|
2008-03-31 21:04:28 +02:00
|
|
|
XFree(name);
|
|
|
|
}
|
2011-11-14 00:18:04 +01:00
|
|
|
|
|
|
|
ret.type = GB_T_OBJECT;
|
|
|
|
ret.value._object = array;
|
|
|
|
GB.ReturnVariant(&ret);
|
2008-03-31 21:04:28 +02:00
|
|
|
}
|
2008-04-05 15:06:08 +02:00
|
|
|
else if (type == X11_UTF8_STRING && format == 8)
|
|
|
|
{
|
|
|
|
count = GB.StringLength(value);
|
|
|
|
GB.Array.New(&array, GB_T_STRING, 0);
|
|
|
|
while (count > 0)
|
|
|
|
{
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (!value[i])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i)
|
2010-06-05 01:48:53 +02:00
|
|
|
*(char **)GB.Array.Add(array) = GB.NewString(value, i);
|
2008-04-05 15:06:08 +02:00
|
|
|
i++;
|
|
|
|
value += i;
|
|
|
|
count -= i;
|
|
|
|
}
|
2011-11-14 00:18:04 +01:00
|
|
|
ret.type = GB_T_OBJECT;
|
|
|
|
ret.value._object = array;
|
|
|
|
GB.ReturnVariant(&ret);
|
2008-04-05 15:06:08 +02:00
|
|
|
}
|
2008-03-31 21:04:28 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
switch(format)
|
|
|
|
{
|
|
|
|
case 16:
|
2009-07-14 20:38:30 +02:00
|
|
|
count = GB.StringLength(value) / sizeof(int);
|
2008-03-31 21:04:28 +02:00
|
|
|
GB.Array.New(&array, GB_T_SHORT, count);
|
2011-04-24 03:00:46 +02:00
|
|
|
/*for (i = 0; i < count; i++)
|
|
|
|
*((short *)GB.Array.Get(array, i)) = *((short *)value + i);*/
|
|
|
|
memcpy(GB.Array.Get(array, 0), value, sizeof(short) * count);
|
2011-11-14 00:18:04 +01:00
|
|
|
|
|
|
|
ret.type = GB_T_OBJECT;
|
|
|
|
ret.value._object = array;
|
|
|
|
GB.ReturnVariant(&ret);
|
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
break;
|
|
|
|
|
2009-07-14 17:35:49 +02:00
|
|
|
case 32: // A "long", not necessarily 32 bits!!
|
2009-07-14 20:38:30 +02:00
|
|
|
count = GB.StringLength(value) / sizeof(long);
|
2008-03-31 21:04:28 +02:00
|
|
|
GB.Array.New(&array, GB_T_INTEGER, count);
|
|
|
|
for (i = 0; i < count; i++)
|
2009-07-14 17:35:49 +02:00
|
|
|
*((int *)GB.Array.Get(array, i)) = *((long *)value + i);
|
2011-11-14 00:18:04 +01:00
|
|
|
|
|
|
|
ret.type = GB_T_OBJECT;
|
|
|
|
ret.value._object = array;
|
|
|
|
GB.ReturnVariant(&ret);
|
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2011-11-14 00:18:04 +01:00
|
|
|
|
|
|
|
ret.type = GB_T_STRING;
|
|
|
|
ret.value._string = value;
|
|
|
|
GB.ReturnVariant(&ret);
|
2008-03-31 21:04:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-17 01:43:36 +02:00
|
|
|
BEGIN_METHOD(X11_SetWindowProperty, GB_INTEGER window; GB_STRING name; GB_STRING type; GB_VARIANT value)
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
Atom type;
|
|
|
|
Atom prop;
|
|
|
|
int format;
|
|
|
|
int count;
|
|
|
|
void *data;
|
|
|
|
void *object;
|
2008-04-05 15:06:08 +02:00
|
|
|
Window window;
|
|
|
|
void *buffer = NULL;
|
2009-07-14 20:38:30 +02:00
|
|
|
#if OS_64BITS
|
|
|
|
long padded_value;
|
|
|
|
long *padded_data;
|
2009-07-14 21:29:56 +02:00
|
|
|
int i;
|
2009-07-14 20:38:30 +02:00
|
|
|
#endif
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
prop = X11_intern_atom(GB.ToZeroString(ARG(name)), TRUE);
|
|
|
|
type = X11_intern_atom(GB.ToZeroString(ARG(type)), TRUE);
|
|
|
|
count = 0;
|
|
|
|
format = 0;
|
|
|
|
|
2014-05-17 01:43:36 +02:00
|
|
|
window = VARG(window);
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
switch(VARG(value).type)
|
|
|
|
{
|
|
|
|
case GB_T_STRING:
|
|
|
|
case GB_T_CSTRING:
|
|
|
|
format = 8;
|
2009-12-24 03:02:05 +01:00
|
|
|
data = VARG(value).value._string;
|
2008-03-31 21:04:28 +02:00
|
|
|
count = GB.StringLength(data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GB_T_BOOLEAN:
|
|
|
|
case GB_T_BYTE:
|
|
|
|
case GB_T_SHORT:
|
|
|
|
case GB_T_INTEGER:
|
|
|
|
format = 32;
|
2009-07-14 20:38:30 +02:00
|
|
|
#if OS_64BITS
|
2010-05-28 09:47:49 +02:00
|
|
|
padded_value = VARG(value).value._integer;
|
|
|
|
data = &padded_value;
|
2009-07-14 20:38:30 +02:00
|
|
|
#else
|
2009-12-24 03:02:05 +01:00
|
|
|
data = &VARG(value).value._integer;
|
2009-07-14 20:38:30 +02:00
|
|
|
#endif
|
2008-03-31 21:04:28 +02:00
|
|
|
count = 1;
|
|
|
|
break;
|
|
|
|
|
2009-07-14 17:35:49 +02:00
|
|
|
default:
|
|
|
|
if (VARG(value).type >= GB_T_OBJECT)
|
2008-03-31 21:04:28 +02:00
|
|
|
{
|
2009-12-24 03:02:05 +01:00
|
|
|
object = VARG(value).value._object;
|
2009-07-14 17:35:49 +02:00
|
|
|
if (GB.Is(object, GB.FindClass("Array")))
|
2008-03-31 21:04:28 +02:00
|
|
|
{
|
2009-07-14 17:35:49 +02:00
|
|
|
data = GB.Array.Get((GB_ARRAY)object, 0);
|
|
|
|
count = GB.Array.Count((GB_ARRAY)object);
|
|
|
|
|
|
|
|
switch((int)GB.Array.Type(object))
|
|
|
|
{
|
|
|
|
case GB_T_BYTE:
|
|
|
|
format = 8;
|
|
|
|
break;
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2009-07-14 17:35:49 +02:00
|
|
|
case GB_T_SHORT:
|
|
|
|
format = 16;
|
|
|
|
break;
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2009-07-14 17:35:49 +02:00
|
|
|
case GB_T_INTEGER:
|
|
|
|
format = 32;
|
2009-07-14 20:38:30 +02:00
|
|
|
#if OS_64BITS
|
|
|
|
padded_data = (long *)alloca(sizeof(long) * count);
|
|
|
|
for (i = 0; i < count; i++)
|
2012-09-17 13:13:32 +02:00
|
|
|
padded_data[i] = *((int *)data + i);
|
2009-07-14 20:38:30 +02:00
|
|
|
data = padded_data;
|
|
|
|
#endif
|
2009-07-14 17:35:49 +02:00
|
|
|
break;
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2009-07-14 17:35:49 +02:00
|
|
|
case GB_T_STRING:
|
|
|
|
if (type == X11_UTF8_STRING)
|
2008-04-05 15:06:08 +02:00
|
|
|
{
|
2009-07-14 17:35:49 +02:00
|
|
|
int i, len;
|
|
|
|
char *p;
|
|
|
|
char **d = (char **)data;
|
|
|
|
|
|
|
|
len = 0;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
len += GB.StringLength(d[i]) + 1;
|
|
|
|
|
|
|
|
GB.Alloc(&buffer, len);
|
|
|
|
|
|
|
|
format = 8;
|
|
|
|
data = buffer;
|
|
|
|
count = len;
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
len = GB.StringLength(d[i]);
|
|
|
|
memcpy(p, d[i], len + 1);
|
|
|
|
p += len + 1;
|
|
|
|
}
|
2010-12-15 16:55:16 +01:00
|
|
|
|
|
|
|
break;
|
2008-04-05 15:06:08 +02:00
|
|
|
}
|
2010-12-15 16:55:16 +01:00
|
|
|
|
2009-07-14 17:35:49 +02:00
|
|
|
default:
|
|
|
|
goto __ERROR;
|
|
|
|
}
|
2008-03-31 21:04:28 +02:00
|
|
|
}
|
|
|
|
}
|
2009-07-14 17:35:49 +02:00
|
|
|
else
|
|
|
|
goto __ERROR;
|
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (format)
|
2008-04-05 15:06:08 +02:00
|
|
|
X11_set_property(window, prop, type, format, data, count);
|
|
|
|
|
|
|
|
if (buffer)
|
|
|
|
GB.Free(&buffer);
|
2009-07-14 17:35:49 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
__ERROR:
|
|
|
|
|
2014-05-17 01:43:36 +02:00
|
|
|
GB.Error("Datatype not supported");
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_InternAtom, GB_STRING atom; GB_BOOLEAN create)
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
2009-07-14 20:38:30 +02:00
|
|
|
|
2012-09-17 13:13:32 +02:00
|
|
|
GB.ReturnInteger(X11_intern_atom(GB.ToZeroString(ARG(atom)), VARGOPT(create, FALSE)));
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_GetAtomName, GB_INTEGER atom)
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
name = XGetAtomName(X11_display, VARG(atom));
|
|
|
|
GB.ReturnNewZeroString(name);
|
|
|
|
XFree(name);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_SendClientMessage, GB_STRING message; GB_OBJECT data; GB_INTEGER window)
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
GB_ARRAY array;
|
2010-05-28 09:47:49 +02:00
|
|
|
void *data = NULL;
|
2008-03-31 21:04:28 +02:00
|
|
|
int count = 0;
|
|
|
|
int format = 0;
|
2009-07-14 20:38:30 +02:00
|
|
|
#if OS_64BITS
|
|
|
|
long *padded_data;
|
2009-07-14 21:29:56 +02:00
|
|
|
int i;
|
2009-07-14 20:38:30 +02:00
|
|
|
#endif
|
2008-03-31 21:04:28 +02:00
|
|
|
|
2008-04-02 03:15:31 +02:00
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
2008-03-31 21:04:28 +02:00
|
|
|
if (!MISSING(data) && VARG(data))
|
|
|
|
{
|
|
|
|
array = VARG(data);
|
|
|
|
data = GB.Array.Get(array, 0);
|
|
|
|
count = GB.Array.Count(array);
|
|
|
|
|
|
|
|
switch((int)GB.Array.Type(array))
|
|
|
|
{
|
|
|
|
case GB_T_BYTE:
|
|
|
|
format = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GB_T_SHORT:
|
|
|
|
format = 16;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GB_T_INTEGER:
|
|
|
|
format = 32;
|
2009-07-14 20:38:30 +02:00
|
|
|
#if OS_64BITS
|
|
|
|
padded_data = (long *)alloca(sizeof(long) * count);
|
|
|
|
for (i = 0; i < count; i++)
|
2012-09-17 13:13:32 +02:00
|
|
|
padded_data[i] = *((int *)data + i);
|
2009-07-14 20:38:30 +02:00
|
|
|
data = padded_data;
|
|
|
|
#endif
|
2008-03-31 21:04:28 +02:00
|
|
|
break;
|
|
|
|
|
2008-04-02 03:15:31 +02:00
|
|
|
/*case GB_T_STRING:
|
2008-03-31 21:04:28 +02:00
|
|
|
format = 32;
|
|
|
|
// TODO: convert strings to Atom
|
2008-04-02 03:15:31 +02:00
|
|
|
break;*/
|
2008-03-31 21:04:28 +02:00
|
|
|
|
|
|
|
default:
|
2012-09-17 13:13:32 +02:00
|
|
|
fprintf(stderr, "gb.desktop: unsupported array datatype for 'Data' argument");
|
2008-03-31 21:04:28 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-05 15:06:08 +02:00
|
|
|
X11_send_client_message(X11_root, VARGOPT(window, X11_root),
|
2008-03-31 21:04:28 +02:00
|
|
|
X11_intern_atom(GB.ToZeroString(ARG(message)), TRUE),
|
|
|
|
data, format, count);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_PROPERTY(X11_EventFilter)
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (READ_PROPERTY)
|
|
|
|
GB.ReturnBoolean(X11_event_filter_enabled);
|
|
|
|
else
|
|
|
|
X11_enable_event_filter(VPROP(GB_BOOLEAN));
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_WatchWindow, GB_INTEGER window; GB_BOOLEAN watch)
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
XWindowAttributes attr;
|
|
|
|
int mask = PropertyChangeMask | StructureNotifyMask;
|
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
XGetWindowAttributes(X11_display, VARG(window), &attr);
|
|
|
|
|
|
|
|
if (VPROP(GB_BOOLEAN))
|
2009-07-14 20:38:30 +02:00
|
|
|
XSelectInput(X11_display, (Window)VARG(window), attr.your_event_mask | mask);
|
2008-04-02 03:15:31 +02:00
|
|
|
else
|
2009-07-14 20:38:30 +02:00
|
|
|
XSelectInput(X11_display, (Window)VARG(window), attr.your_event_mask & ~mask);
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_GetWindowGeometry, GB_INTEGER window)
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
GB_ARRAY array;
|
|
|
|
int *data;
|
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
GB.Array.New(&array, GB_T_INTEGER, 4);
|
|
|
|
data = (int *)GB.Array.Get(array, 0);
|
|
|
|
|
2011-12-11 20:14:04 +01:00
|
|
|
X11_get_window_geometry(VARG(window), &data[0], &data[1], &data[2], &data[3]);
|
|
|
|
//XGetGeometry(X11_display, VARG(window), &root, &data[0], &data[1], (uint *)&data[2], (uint *)&data[3], &ignore, &ignore);
|
2008-04-02 03:15:31 +02:00
|
|
|
GB.ReturnObject(array);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_MakeIcon, GB_OBJECT data; GB_INTEGER width; GB_INTEGER height)
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
GB_ARRAY array;
|
|
|
|
int *data;
|
2009-07-14 21:11:26 +02:00
|
|
|
int count;
|
|
|
|
int size;
|
|
|
|
int width = VARGOPT(width, -1);
|
|
|
|
int height = VARGOPT(height, width);
|
|
|
|
int w, h;
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
array = VARG(data);
|
|
|
|
if (GB.CheckObject(array))
|
|
|
|
return;
|
|
|
|
|
|
|
|
data = (int *)GB.Array.Get(array, 0);
|
2009-07-14 21:11:26 +02:00
|
|
|
count = GB.Array.Count(array);
|
|
|
|
|
|
|
|
if (width < 0)
|
|
|
|
{
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
if (count < 2)
|
|
|
|
break;
|
|
|
|
w = data[0];
|
|
|
|
h = data[1];
|
2011-04-24 03:00:46 +02:00
|
|
|
if (!w || !h)
|
|
|
|
break;
|
|
|
|
#if DEBUG_ICON
|
|
|
|
fprintf(stderr, "%d [%d %d]\n", count, w, h);
|
|
|
|
#endif
|
2009-07-14 21:11:26 +02:00
|
|
|
if (w > width)
|
|
|
|
{
|
|
|
|
width = w;
|
|
|
|
height = h;
|
|
|
|
}
|
|
|
|
size = w * h + 2;
|
|
|
|
data += size;
|
|
|
|
count -= size;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = (int *)GB.Array.Get(array, 0);
|
|
|
|
count = GB.Array.Count(array);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
{
|
|
|
|
if (count < 2)
|
|
|
|
{
|
|
|
|
GB.ReturnNull();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
w = data[0];
|
|
|
|
h = data[1];
|
|
|
|
if (w == width && h == height)
|
|
|
|
break;
|
2011-04-24 03:00:46 +02:00
|
|
|
if (!w || !h)
|
|
|
|
GB.ReturnNull();
|
2009-07-14 21:11:26 +02:00
|
|
|
size = w * h + 2;
|
|
|
|
data += size;
|
|
|
|
count -= size;
|
|
|
|
}
|
2008-04-02 03:15:31 +02:00
|
|
|
|
2009-07-14 21:11:26 +02:00
|
|
|
GB.ReturnObject(IMAGE.Create(w, h, GB_IMAGE_BGRA, (unsigned char *)&data[2]));
|
2008-04-02 03:15:31 +02:00
|
|
|
|
|
|
|
END_METHOD
|
2008-02-02 11:54:13 +01:00
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11_MinimizeWindow, GB_INTEGER window; GB_BOOLEAN minimized)
|
2008-09-30 00:32:27 +02:00
|
|
|
|
2012-10-02 10:01:25 +02:00
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
2008-09-30 00:32:27 +02:00
|
|
|
if (VARG(minimized))
|
|
|
|
{
|
2009-07-14 20:38:30 +02:00
|
|
|
long state = IconicState;
|
2008-09-30 00:32:27 +02:00
|
|
|
|
|
|
|
X11_send_client_message(X11_root, VARG(window),
|
|
|
|
X11_intern_atom("WM_CHANGE_STATE", TRUE),
|
|
|
|
(char *)&state, 32, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
XMapWindow(X11_display, VARG(window));
|
|
|
|
}
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2012-09-17 16:22:26 +02:00
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD_VOID(X11_Flush)
|
2012-09-17 16:22:26 +02:00
|
|
|
|
2012-10-02 10:01:25 +02:00
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
2012-09-17 16:22:26 +02:00
|
|
|
XFlush(X11_display);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD_VOID(X11_Sync)
|
2012-09-17 16:22:26 +02:00
|
|
|
|
2012-10-02 10:01:25 +02:00
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
2012-09-17 16:22:26 +02:00
|
|
|
XSync(X11_display, FALSE);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
BEGIN_METHOD(X11_MoveWindow, GB_INTEGER window; GB_INTEGER x; GB_INTEGER y; GB_INTEGER w; GB_INTEGER h)
|
2012-10-02 10:01:25 +02:00
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
if (MISSING(w) || MISSING(h))
|
|
|
|
XMoveWindow(X11_display, VARG(window), VARG(x), VARG(y));
|
|
|
|
else
|
|
|
|
XMoveResizeWindow(X11_display, VARG(window), VARG(x), VARG(y), VARG(w), VARG(h));
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
BEGIN_METHOD(X11_ResizeWindow, GB_INTEGER window; GB_INTEGER w; GB_INTEGER h)
|
|
|
|
|
|
|
|
XResizeWindow(X11_display, VARG(window), VARG(w), VARG(h));
|
|
|
|
|
|
|
|
END_METHOD
|
2012-10-02 10:01:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
GB_DESC X11Desc[] =
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2014-05-13 01:38:46 +02:00
|
|
|
GB_DECLARE("X11", 0), GB_VIRTUAL_CLASS(),
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-04-02 03:15:31 +02:00
|
|
|
//GB_STATIC_METHOD("Init", NULL, CDESKTOP_init, NULL),
|
2008-03-31 21:04:28 +02:00
|
|
|
|
2014-05-17 01:43:36 +02:00
|
|
|
GB_CONSTANT("None", "i", None),
|
2008-04-05 15:06:08 +02:00
|
|
|
GB_CONSTANT("CurrentTime", "i", CurrentTime),
|
2014-05-17 01:43:36 +02:00
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
GB_STATIC_METHOD("FindWindow", "Integer[]", X11_FindWindow, "[(Title)s(Application)s(Role)s]"),
|
|
|
|
GB_STATIC_METHOD("SendKey", NULL, X11_SendKey, "(Key)s(Press)b"),
|
|
|
|
GB_STATIC_PROPERTY_READ("RootWindow", "i", X11_RootWindow),
|
|
|
|
GB_STATIC_PROPERTY_READ("Time", "i", X11_Time),
|
2014-05-17 01:43:36 +02:00
|
|
|
GB_STATIC_METHOD("GetWindowProperty", "v", X11_GetWindowProperty, "(Window)i(Property)s"),
|
|
|
|
GB_STATIC_METHOD("SetWindowProperty", NULL, X11_SetWindowProperty, "(Window)i(Property)s(Type)s(Value)v"),
|
2014-05-13 01:38:46 +02:00
|
|
|
GB_STATIC_METHOD("InternAtom", "i", X11_InternAtom, "(Atom)s[(Create)b]"),
|
|
|
|
GB_STATIC_METHOD("GetAtomName", "s", X11_GetAtomName, "(Atom)i"),
|
|
|
|
GB_STATIC_METHOD("SendClientMessageToRootWindow", NULL, X11_SendClientMessage, "(Message)s[(Data)Array;(Window)i]"),
|
|
|
|
GB_STATIC_PROPERTY("EventFilter", "b", X11_EventFilter),
|
|
|
|
GB_STATIC_METHOD("WatchWindow", NULL, X11_WatchWindow, "(Window)i(Watch)b"),
|
|
|
|
GB_STATIC_METHOD("GetWindowGeometry", "Integer[]", X11_GetWindowGeometry, "(Window)i"),
|
|
|
|
GB_STATIC_METHOD("MakeIcon", "Image", X11_MakeIcon, "(Data)Array;[(Width)i(Height)h]"),
|
|
|
|
GB_STATIC_METHOD("MinimizeWindow", NULL, X11_MinimizeWindow, "(Window)i(Minimized)b"),
|
|
|
|
GB_STATIC_METHOD("Sync", NULL, X11_Sync, NULL),
|
|
|
|
GB_STATIC_METHOD("Flush", NULL, X11_Flush, NULL),
|
2014-06-02 02:39:44 +02:00
|
|
|
GB_STATIC_METHOD("MoveWindow", NULL, X11_MoveWindow, "(Window)i(X)i(Y)i[(Width)i(Height)i]"),
|
|
|
|
GB_STATIC_METHOD("ResizeWindow", NULL, X11_ResizeWindow, "(Window)i(Width)i(Height)i"),
|
2014-05-17 01:43:36 +02:00
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
GB_END_DECLARE
|
|
|
|
};
|
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
//---- X11Watcher ---------------------------------------------------------
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
static CX11WATCHER *_watcher_list = NULL;
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
void WATCHER_event_filter(XEvent *e)
|
2008-04-05 15:06:08 +02:00
|
|
|
{
|
2014-06-02 02:39:44 +02:00
|
|
|
CX11WATCHER *watcher;
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2014-06-02 02:39:44 +02:00
|
|
|
if (!_watcher_list)
|
|
|
|
return;
|
|
|
|
|
2008-04-05 15:06:08 +02:00
|
|
|
if (e->type == PropertyNotify)
|
|
|
|
{
|
|
|
|
LIST_for_each(watcher, _watcher_list)
|
|
|
|
{
|
|
|
|
if (watcher->window && e->xany.window != watcher->window)
|
|
|
|
continue;
|
|
|
|
if (watcher->property && e->xproperty.atom != watcher->property)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
GB.Raise(watcher, EVENT_Change, 2, GB_T_INTEGER, e->xany.window, GB_T_INTEGER, e->xproperty.atom);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (e->type == ConfigureNotify)
|
|
|
|
{
|
|
|
|
LIST_for_each(watcher, _watcher_list)
|
|
|
|
{
|
|
|
|
if (watcher->window && e->xany.window != watcher->window)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
GB.Raise(watcher, EVENT_Window,
|
|
|
|
5, GB_T_INTEGER, e->xany.window,
|
|
|
|
GB_T_INTEGER, e->xconfigure.x,
|
|
|
|
GB_T_INTEGER, e->xconfigure.y,
|
|
|
|
GB_T_INTEGER, e->xconfigure.width,
|
|
|
|
GB_T_INTEGER, e->xconfigure.height);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD(X11Watcher_new, GB_INTEGER window; GB_STRING property)
|
2008-04-05 15:06:08 +02:00
|
|
|
|
|
|
|
if (X11_init())
|
|
|
|
return;
|
|
|
|
|
|
|
|
WATCHER->window = VARGOPT(window, 0);
|
|
|
|
WATCHER->property = MISSING(property) ? 0 : X11_intern_atom(GB.ToZeroString(ARG(property)), FALSE);
|
|
|
|
|
|
|
|
if (!_watcher_list)
|
2014-06-02 02:39:44 +02:00
|
|
|
X11_enable_event_filter(TRUE);
|
2008-04-05 15:06:08 +02:00
|
|
|
|
|
|
|
LIST_insert(&_watcher_list, WATCHER, &WATCHER->list);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
BEGIN_METHOD_VOID(X11Watcher_free)
|
2008-04-05 15:06:08 +02:00
|
|
|
|
|
|
|
LIST_remove(&_watcher_list, WATCHER, &WATCHER->list);
|
|
|
|
if (!_watcher_list)
|
2014-06-02 02:39:44 +02:00
|
|
|
X11_enable_event_filter(FALSE);
|
2008-04-05 15:06:08 +02:00
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
GB_DESC X11WatcherDesc[] =
|
2008-04-05 15:06:08 +02:00
|
|
|
{
|
2014-06-02 02:39:44 +02:00
|
|
|
GB_DECLARE("X11Watcher", sizeof(CX11WATCHER)),
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2014-05-13 01:38:46 +02:00
|
|
|
GB_METHOD("_new", NULL, X11Watcher_new, "[(Window)i(Property)s]"),
|
|
|
|
GB_METHOD("_free", NULL, X11Watcher_free, NULL),
|
2008-04-05 15:06:08 +02:00
|
|
|
|
2014-05-17 01:43:36 +02:00
|
|
|
GB_EVENT("Property", NULL, "(Window)i(Property)i", &EVENT_Change),
|
|
|
|
GB_EVENT("Configure", NULL, "(Window)i(X)i(Y)i(Width)i(Height)i", &EVENT_Window),
|
2008-05-13 14:52:06 +02:00
|
|
|
|
|
|
|
GB_END_DECLARE
|
2008-04-05 15:06:08 +02:00
|
|
|
};
|