summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2013-07-03 12:11:49 -0400
committerKristian Høgsberg <krh@bitplanet.net>2013-07-10 13:33:01 -0400
commit66fc0d9690e93e9dc8168fc709152dfdea87bd27 (patch)
tree97454195024f54c7046d3ddb68136d12d9f554a9
parent69f9ef58431e9f392e32066d8f288110311a2480 (diff)
Add some support for window properties
-rw-r--r--src/display.c66
-rw-r--r--src/private.h10
-rw-r--r--src/window.c208
3 files changed, 277 insertions, 7 deletions
diff --git a/src/display.c b/src/display.c
index d5c3bff..af6fc92 100644
--- a/src/display.c
+++ b/src/display.c
@@ -7,15 +7,57 @@
#include <wayland-client.h>
#include <X11/Xproto.h>
+#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include "private.h"
+static const char *request_names[] = {
+ "None", "CreateWindow", "ChangeWindowAttributes",
+ "GetWindowAttributes", "DestroyWindow", "DestroySubwindows",
+ "ChangeSaveSet", "ReparentWindow", "MapWindow", "MapSubwindows",
+ "UnmapWindow", "UnmapSubwindows", "ConfigureWindow",
+ "CirculateWindow", "GetGeometry", "QueryTree", "InternAtom",
+ "GetAtomName", "ChangeProperty", "DeleteProperty", "GetProperty",
+ "ListProperties", "SetSelectionOwner", "GetSelectionOwner",
+ "ConvertSelection", "SendEvent", "GrabPointer", "UngrabPointer",
+ "GrabButton", "UngrabButton", "ChangeActivePointerGrab",
+ "GrabKeyboard", "UngrabKeyboard", "GrabKey", "UngrabKey",
+ "AllowEvents", "GrabServer", "UngrabServer", "QueryPointer",
+ "GetMotionEvents", "TranslateCoords", "WarpPointer", "SetInputFocus",
+ "GetInputFocus", "QueryKeymap", "OpenFont", "CloseFont", "QueryFont",
+ "QueryTextExtents", "ListFonts", "ListFontsWithInfo", "SetFontPath",
+ "GetFontPath", "CreatePixmap", "FreePixmap", "CreateGC", "ChangeGC",
+ "CopyGC", "SetDashes", "SetClipRectangles", "FreeGC", "ClearArea",
+ "CopyArea", "CopyPlane", "PolyPoint", "PolyLine", "PolySegment",
+ "PolyRectangle", "PolyArc", "FillPoly", "PolyFillRectangle",
+ "PolyFillArc", "PutImage", "GetImage", "PolyText8", "PolyText16",
+ "ImageText8", "ImageText16", "CreateColormap", "FreeColormap",
+ "CopyColormapAndFree", "InstallColormap", "UninstallColormap",
+ "ListInstalledColormaps", "AllocColor", "AllocNamedColor",
+ "AllocColorCells", "AllocColorPlanes", "FreeColors", "StoreColors",
+ "StoreNamedColor", "QueryColors", "LookupColor", "CreateCursor",
+ "CreateGlyphCursor", "FreeCursor", "RecolorCursor", "QueryBestSize",
+ "QueryExtension", "ListExtensions", "ChangeKeyboardMapping",
+ "GetKeyboardMapping", "ChangeKeyboardControl", "GetKeyboardControl",
+ "Bell", "ChangePointerControl", "GetPointerControl", "SetScreenSaver",
+ "GetScreenSaver", "ChangeHosts", "ListHosts", "SetAccessControl",
+ "SetCloseDownMode", "KillClient", "RotateProperties",
+ "ForceScreenSaver", "SetPointerMapping", "GetPointerMapping",
+ "SetModifierMapping", "GetModifierMapping", "NoOperation"
+};
+
static int
default_error_handler(Display *xdisplay, XErrorEvent *event)
{
- fprintf(stderr, "x error: error code %d, request %d/%d\n",
+ fprintf(stderr, "x error: error code %d, request %d/%d",
event->error_code, event->request_code, event->minor_code);
+ if (event->request_code <= X_NoOperation)
+ fprintf(stderr, " (%s)\n",
+ request_names[event->request_code]);
+ else
+ fprintf(stderr, "\n");
+
exit(1);
}
@@ -24,6 +66,13 @@ static XErrorHandler error_handler = default_error_handler;
void
csx_display_enter(struct csx_display *display, int major, int minor)
{
+#ifdef TRACE
+ if (major <= X_NoOperation)
+ fprintf(stderr, "enter %s\n", request_names[major]);
+ else
+ fprintf(stderr, "enter %d/%d\n", major, minor);
+#endif
+
display->major = major;
display->minor = minor;
display->serial++;
@@ -134,7 +183,7 @@ XOpenDisplay(const char *display_name)
display->xdisplay = (Display *) xdisplay;
display->display = wl_display_connect(display_name);
if (!display->display) {
- free(display);
+ free(xdisplay);
return NULL;
}
@@ -144,7 +193,8 @@ XOpenDisplay(const char *display_name)
wl_display_roundtrip(display->display);
if (display->shm == NULL) {
fprintf(stderr, "No wl_shm global\n");
- exit(1);
+ free(xdisplay);
+ return NULL;
}
wl_display_roundtrip(display->display);
@@ -154,7 +204,8 @@ XOpenDisplay(const char *display_name)
if (display->shm_formats == 0) {
fprintf(stderr, "no shm formats available\n");
- exit(1);
+ free(xdisplay);
+ return NULL;
}
csx_display_add_resource(display, NULL); /* None resource */
@@ -188,6 +239,7 @@ XOpenDisplay(const char *display_name)
display->depths[1].visuals = display->depth32_visuals;
display->root = csx_window_create(display, NULL);
+
display->screens[0].display = (Display *) xdisplay;
display->screens[0].root = display->root->id;
display->screens[0].width = 800;
@@ -223,6 +275,12 @@ XOpenDisplay(const char *display_name)
xdisplay->default_screen = 0;
xdisplay->screens = display->screens;
+ /* Test property on root window. */
+ XChangeProperty(display->xdisplay, display->root->id,
+ XInternAtom(display->xdisplay, "PHINEAS", False),
+ XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &display->root->id, 1);
+
return (Display *) xdisplay;
}
diff --git a/src/private.h b/src/private.h
index 0f595d3..d624aba 100644
--- a/src/private.h
+++ b/src/private.h
@@ -69,6 +69,14 @@ void csx_display_error(struct csx_display *display, XID resourceid, int error);
void csx_display_add_seat(struct csx_display *display,
uint32_t name, uint32_t version);
+struct csx_property {
+ Atom name;
+ Atom type;
+ int format;
+ int nelements;
+ struct wl_list link;
+};
+
struct csx_window {
XID id;
struct csx_window *parent;
@@ -92,7 +100,7 @@ struct csx_window {
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
- /* attrs */
+ struct wl_list property_list;
};
struct csx_window *
diff --git a/src/window.c b/src/window.c
index 8ff8179..7e8f14a 100644
--- a/src/window.c
+++ b/src/window.c
@@ -29,6 +29,8 @@ csx_window_create(struct csx_display *display, struct csx_window *parent)
pixman_region32_init(&window->output_clip);
pixman_region32_init(&window->border_clip);
+ wl_list_init(&window->property_list);
+
return window;
}
@@ -732,16 +734,218 @@ XDestroySubwindows(Display *xdisplay, Window xwindow)
return 1;
}
+static struct csx_property *
+csx_window_get_property(struct csx_window *window, Atom name)
+{
+ struct csx_property *p;
+
+ wl_list_for_each(p, &window->property_list, link)
+ if (p->name == name)
+ return p;
+
+ return NULL;
+}
+
+static struct csx_property *
+csx_property_create(Atom name, Atom type, int format,
+ const void *data1, int nelements1,
+ const void *data2, int nelements2)
+{
+ struct csx_property *property;
+ char *p;
+ int bpe, size;
+
+ bpe = format / 8;
+ size = (nelements1 + nelements2) * bpe;
+ property = malloc(sizeof *property + size);
+ property->name = name;
+ property->type = type;
+ property->format = format;
+ property->nelements = nelements1 + nelements2;
+
+ p = (char *) (property + 1);
+ memcpy(p, data1, nelements1 * bpe);
+ memcpy(p + nelements1 * bpe, data2, nelements2 * bpe);
+
+ return property;
+}
+
WL_EXPORT int
XChangeProperty(Display *xdisplay, Window xwindow,
- Atom property, Atom type, int format, int mode,
+ Atom name, Atom type, int format, int mode,
const unsigned char *data, int nelements)
{
struct csx_display *display = csx_display(xdisplay);
+ struct csx_window *window;
+ struct csx_property *property, *current;
csx_display_enter(display, X_ChangeProperty, 0);
- STUB();
+ if (format != 8 && format != 16 && format != 32) {
+ csx_display_error(display, format, BadValue);
+ return 1;
+ }
+
+ window = csx_display_lookup_resource(display, xwindow);
+ if (window == NULL) {
+ csx_display_error(display, xwindow, BadWindow);
+ return 1;
+ }
+
+ current = csx_window_get_property(window, name);
+ if (current && mode != PropModeReplace) {
+ if (current->type != type ||
+ current->format != format) {
+ csx_display_error(display, format, BadValue);
+ return 1;
+ }
+ }
+
+ if (current && mode == PropModePrepend)
+ property = csx_property_create(name, type, format,
+ data, nelements,
+ current + 1,
+ current->nelements);
+ else if (current && mode == PropModeAppend)
+ property = csx_property_create(name, type, format,
+ current + 1,
+ current->nelements,
+ data, nelements);
+ else
+ property = csx_property_create(name, type, format,
+ data, nelements, NULL, 0);
+
+ if (current) {
+ wl_list_insert(&current->link, &property->link);
+ wl_list_remove(&current->link);
+ free(current);
+ } else {
+ wl_list_insert(&window->property_list, &property->link);
+ }
+
+ return 1;
+}
+
+WL_EXPORT int
+XDeleteProperty(Display *xdisplay, Window xwindow, Atom name)
+{
+ struct csx_display *display = csx_display(xdisplay);
+ struct csx_window *window;
+ struct csx_property *property;
+
+ csx_display_enter(display, X_DeleteProperty, 0);
+
+ window = csx_display_lookup_resource(display, xwindow);
+ if (window == NULL) {
+ csx_display_error(display, xwindow, BadWindow);
+ return 1;
+ }
+
+ property = csx_window_get_property(window, name);
+ if (property) {
+ wl_list_remove(&property->link);
+ free(property);
+ }
return 1;
}
+
+WL_EXPORT int
+XGetWindowProperty(Display *xdisplay, Window xwindow, Atom name,
+ long offset, long length, Bool delete,
+ Atom req_type, Atom *actual_type, int *actual_format,
+ unsigned long *nitems, unsigned long *bytes_after,
+ unsigned char **prop)
+{
+ struct csx_display *display = csx_display(xdisplay);
+ struct csx_window *window;
+ struct csx_property *property;
+ unsigned char *data;
+ long byte_length, copy, index;
+
+ csx_display_enter(display, X_GetProperty, 0);
+
+ window = csx_display_lookup_resource(display, xwindow);
+ if (window == NULL) {
+ csx_display_error(display, xwindow, BadWindow);
+ return 1;
+ }
+
+ property = csx_window_get_property(window, name);
+ if (property == NULL) {
+ *actual_type = None;
+ *actual_format = 0;
+ *bytes_after = 0;
+ return 1;
+ }
+
+ byte_length = property->nelements * property->format / 8;
+ index = offset * 4;
+ if (req_type != AnyPropertyType && req_type != property->type) {
+ *actual_type = property->type;
+ *actual_format = property->format;
+ *bytes_after = byte_length;
+ return 1;
+ }
+
+ if (length < 0 || index > byte_length) {
+ csx_display_error(display, xwindow, BadValue);
+ return 1;
+ }
+
+ *actual_type = property->type;
+ *actual_format = property->format;
+
+ copy = length * 4;
+ if (index + copy > byte_length)
+ copy = byte_length - index;
+
+ *prop = malloc(copy);
+ if (*prop == NULL) {
+ csx_display_error(display, xwindow, BadAlloc);
+ return 1;
+ }
+
+ data = (unsigned char *) (property + 1);
+ memcpy(*prop, data + index, copy);
+ *nitems = copy / (property->format / 8);
+ *bytes_after = byte_length - (index + copy);
+
+ if (delete) {
+ wl_list_remove(&property->link);
+ free(property);
+ }
+
+ return Success;
+}
+
+WL_EXPORT Atom *
+XListProperties(Display *xdisplay, Window xwindow, int *num_prop)
+{
+ struct csx_display *display = csx_display(xdisplay);
+ struct csx_window *window;
+ struct csx_property *property;
+ int i, length;
+ Atom *atoms;
+
+ csx_display_enter(display, X_ListProperties, 0);
+
+ window = csx_display_lookup_resource(display, xwindow);
+ if (window == NULL) {
+ csx_display_error(display, xwindow, BadWindow);
+ return NULL;
+ }
+
+ length = wl_list_length(&window->property_list);
+ atoms = malloc(sizeof *atoms * length);
+ if (atoms == NULL)
+ return NULL;
+
+ i = 0;
+ wl_list_for_each(property, &window->property_list, link)
+ atoms[i++] = property->name;
+
+ *num_prop = length;
+
+ return atoms;
+}