diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2013-07-03 12:11:49 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2013-07-10 13:33:01 -0400 |
commit | 66fc0d9690e93e9dc8168fc709152dfdea87bd27 (patch) | |
tree | 97454195024f54c7046d3ddb68136d12d9f554a9 | |
parent | 69f9ef58431e9f392e32066d8f288110311a2480 (diff) |
Add some support for window properties
-rw-r--r-- | src/display.c | 66 | ||||
-rw-r--r-- | src/private.h | 10 | ||||
-rw-r--r-- | src/window.c | 208 |
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(¤t->link, &property->link); + wl_list_remove(¤t->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; +} |