diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2013-07-03 01:14:29 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2013-07-03 01:14:29 -0400 |
commit | c52758cee9526a837b3da46e4b4d01a96b49a417 (patch) | |
tree | 79c48c215ed0ed38d62bb851e44895aa9b9a2dd4 | |
parent | 36d1b5d5ef307d74df4e3d3de3d16a60502e0fa1 (diff) |
Improved error handling and atoms
-rw-r--r-- | NOTES | 5 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/display.c | 177 | ||||
-rw-r--r-- | src/private.h | 19 | ||||
-rw-r--r-- | src/test.c | 8 | ||||
-rw-r--r-- | src/window.c | 8 |
6 files changed, 210 insertions, 10 deletions
@@ -19,4 +19,7 @@ window and then subwindow. csx sends the immediate Expose rects, xlib sends the final result (the subwindow rect and the split up rects around it)... Expose compression? We could do lazy exposure - events in XNextEvent().
\ No newline at end of file + events in XNextEvent(). + + - Foreign windows and such (GLX import context) can never work... + diff --git a/src/Makefile.am b/src/Makefile.am index 7800eff..197d391 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,8 @@ include_HEADERS = Xlib-wayland.h libX11_wayland_la_LIBADD = $(CSX_LIBS) libX11_wayland_la_CPPFLAGS = $(CSX_CFLAGS) libX11_wayland_la_SOURCES = \ - display.c resource.c window.c pixmap.c event.c input.c private.h + display.c resource.c window.c pixmap.c event.c input.c private.h \ + hints.c xim.c noinst_PROGRAMS = csx-test xlib-test diff --git a/src/display.c b/src/display.c index daaa135..61b632b 100644 --- a/src/display.c +++ b/src/display.c @@ -1,33 +1,59 @@ + #include <stdint.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <wayland-client.h> -#include "Xlib-wayland.h" +#include <X11/Xproto.h> +#include <X11/Xlib.h> #include "private.h" -void -csx_display_bad_alloc(struct csx_display *display) +static int +default_error_handler(Display *xdisplay, XErrorEvent *event) { - fprintf(stderr, "error bad alloc\n"); + fprintf(stderr, "x error: error code %d, request %d/%d\n", + event->error_code, event->request_code, event->minor_code); exit(1); } +static XErrorHandler error_handler; + +void +csx_display_error(struct csx_display *display, + int major, int minor, XID resourceid, int error) +{ + XErrorEvent event; + + event.type = X_Error; + event.display = display->xdisplay; + event.resourceid = resourceid; + event.serial = display->serial; + event.error_code = error; + event.request_code = major; + event.minor_code = minor; + + error_handler(display->xdisplay, &event); +} + void csx_display_bad_window(struct csx_display *display) { - fprintf(stderr, "error bad window\n"); - exit(1); + csx_display_error(display, 0, 0, 0, BadWindow); } void csx_display_bad_match(struct csx_display *display) { - fprintf(stderr, "error bad match\n"); - exit(1); + csx_display_error(display, 0, 0, 0, BadMatch); +} + +void +csx_display_bad_alloc(struct csx_display *display) +{ + csx_display_error(display, 0, 0, 0, BadMatch); } static void @@ -83,11 +109,30 @@ resource_alloc(struct _XDisplay *xdisplay) return csx_display_add_resource(display, NULL); } +static const char *predefined_atoms = + "PRIMARY\0" "SECONDARY\0" "ARC\0" "ATOM\0" "BITMAP\0" "CARDINAL\0" + "COLORMAP\0" "CURSOR\0" "CUT_BUFFER0\0" "CUT_BUFFER1\0" "CUT_BUFFER2\0" + "CUT_BUFFER3\0" "CUT_BUFFER4\0" "CUT_BUFFER5\0" "CUT_BUFFER6\0" + "CUT_BUFFER7\0" "DRAWABLE\0" "FONT\0" "INTEGER\0" "PIXMAP\0" "POINT\0" + "RECTANGLE\0" "RESOURCE_MANAGER\0" "RGB_COLOR_MAP\0" "RGB_BEST_MAP\0" + "RGB_BLUE_MAP\0" "RGB_DEFAULT_MAP\0" "RGB_GRAY_MAP\0" "RGB_GREEN_MAP\0" + "RGB_RED_MAP\0" "STRING\0" "VISUALID\0" "WINDOW\0" "WM_COMMAND\0" + "WM_HINTS\0" "WM_CLIENT_MACHINE\0" "WM_ICON_NAME\0" "WM_ICON_SIZE\0" + "WM_NAME\0" "WM_NORMAL_HINTS\0" "WM_SIZE_HINTS\0" "WM_ZOOM_HINTS\0" + "MIN_SPACE\0" "NORM_SPACE\0" "MAX_SPACE\0" "END_SPACE\0" + "SUPERSCRIPT_X\0" "SUPERSCRIPT_Y\0" "SUBSCRIPT_X\0" "SUBSCRIPT_Y\0" + "UNDERLINE_POSITION\0" "UNDERLINE_THICKNESS\0" "STRIKEOUT_ASCENT\0" + "STRIKEOUT_DESCENT\0" "ITALIC_ANGLE\0" "X_HEIGHT\0" "QUAD_WIDTH\0" + "WEIGHT\0" "POINT_SIZE\0" "RESOLUTION\0" "COPYRIGHT\0" "NOTICE\0" + "FONT_NAME\0" "FAMILY_NAME\0" "FULL_NAME\0" "CAP_HEIGHT\0" + "WM_CLASS\0" "WM_TRANSIENT_FOR\0" "PHINEAS\0" "FERB\0"; + WL_EXPORT Display * XOpenDisplay(const char *display_name) { _XPrivDisplay xdisplay; struct csx_display *display; + const char *p; int size; size = sizeof *xdisplay + sizeof *display; @@ -167,6 +212,11 @@ XOpenDisplay(const char *display_name) display->screens[0].white_pixel = 0xffffffff; display->screens[0].black_pixel = 0xff000000; + display->serial = 1; + display->next_atom = 1; + for (p = predefined_atoms; *p; p += strlen(p) + 1) + XInternAtom(display->xdisplay, p, False); + #if 0 int max_maps, min_maps; /* max and min color maps */ int backing_store; /* Never, WhenMapped, Always */ @@ -208,6 +258,7 @@ WL_EXPORT int XCloseDisplay(Display *xdisplay) { struct csx_display *display = csx_display(xdisplay); + int i; if (display->shm) wl_shm_destroy(display->shm); @@ -221,9 +272,23 @@ XCloseDisplay(Display *xdisplay) wl_registry_destroy(display->registry); wl_display_disconnect(display->display); + + for (i = 1; i < display->next_atom; i++) + free(display->atom_map[i]); + free(xdisplay); } +WL_EXPORT XErrorHandler +XSetErrorHandler(XErrorHandler handler) +{ + XErrorHandler old_handler; + + old_handler = error_handler; + error_handler = handler; + + return old_handler; +} WL_EXPORT Window XRootWindow(Display *xdisplay, int screen_number) @@ -296,3 +361,99 @@ XWhitePixelOfScreen(Screen *screen) { return WhitePixelOfScreen(screen); } + +static const uint32_t prime = 984908819; + +static uint32_t +hash_atom(const char *name) +{ + uint32_t h = 0; + int i; + + for (i = 0; name[i]; i++) + h = h * prime + name[i]; + + return h; +} + +WL_EXPORT Atom +XInternAtom(Display *xdisplay, const char *name, Bool only_if_exists) +{ + struct csx_display *display = csx_display(xdisplay); + uint32_t h, mask, i; + struct csx_atom *atom; + + h = hash_atom(name); + mask = ARRAY_LENGTH(display->atom_table) - 1; + for (i = 0; i < ARRAY_LENGTH(display->atom_table); i++) { + atom = display->atom_table[(h + i) & mask]; + if (atom == NULL) + break; + if (atom->hash == h && strcmp(atom->name, name) == 0) + return atom->value; + } + + if (i == ARRAY_LENGTH(display->atom_table)) { + /* FIXME: Grow table */ + csx_display_bad_alloc(display); + return None; + } + + if (only_if_exists) + return None; + + atom = malloc(sizeof *atom); + atom->hash = h; + atom->name = strdup(name); + atom->value = display->next_atom++; + + display->atom_table[(h + i) & mask] = atom; + display->atom_map[atom->value] = atom; + + return atom->value; +} + +WL_EXPORT Status +XInternAtoms(Display *display, char **names, int count, + Bool only_if_exists, Atom *atoms_return) +{ + int i; + + for (i = 0; i < count; i++) + atoms_return[i] = + XInternAtom(display, names[i], only_if_exists); + + return 1; +} + +WL_EXPORT char * +XGetAtomName(Display *xdisplay, Atom atom) +{ + struct csx_display *display = csx_display(xdisplay); + + if (atom >= display->next_atom) { + csx_display_error(display, X_GetAtomName, 0, atom, BadAtom); + return NULL; + } + + return strdup(display->atom_map[atom]->name); +} + +WL_EXPORT Status +XGetAtomNames(Display *display, Atom *atoms, int count, char **names_return) +{ + int i; + + for (i = 0; i < count; i++) + names_return[i] = XGetAtomName(display, atoms[i]); + + return 1; +} + +WL_EXPORT int +XFree(void *data) +{ + free(data); + + return 1; +} diff --git a/src/private.h b/src/private.h index 197dd48..0bd4fe9 100644 --- a/src/private.h +++ b/src/private.h @@ -1,15 +1,26 @@ +#include <stdio.h> #include <pixman.h> #include <wayland-client.h> +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + #define container_of(ptr, type, member) ({ \ const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) +#define STUB() do { fprintf(stderr, "%s is a lie\n", __func__); } while (0) + struct csx_event { XEvent xevent; struct wl_list link; }; +struct csx_atom { + uint32_t hash; + char *name; + Atom value; +}; + struct csx_display { struct wl_display *display; struct wl_registry *registry; @@ -33,6 +44,10 @@ struct csx_display { Visual depth24_visuals[1]; Visual depth32_visuals[1]; unsigned long serial; + + struct csx_atom *atom_table[256]; + struct csx_atom *atom_map[256]; + Atom next_atom; }; static inline struct csx_display * @@ -44,6 +59,10 @@ csx_display(Display *display) XID cxs_display_add_resource(struct csx_display *display, void *p); void csx_display_remove_resource(struct csx_display *display, XID id); void *csx_display_lookup_resource(struct csx_display *display, XID id); + +void csx_display_error(struct csx_display *display, + int major, int minor, XID resourceid, int error); + void csx_display_bad_alloc(struct csx_display *display); void csx_display_bad_window(struct csx_display *display); void csx_display_bad_match(struct csx_display *display); @@ -77,6 +77,7 @@ int main(int argc, char *argv[]) Window win, sub; XID root; XSetWindowAttributes attributes; + Atom atom; display = XOpenDisplay(NULL); root = XRootWindow(display, 0); @@ -100,6 +101,13 @@ int main(int argc, char *argv[]) printf("created window %d and subwindow %d\n", win, sub); + atom = XInternAtom(display, "FOO", False); + printf("FOO atom is %u\n", atom); + atom = XInternAtom(display, "BAR", False); + printf("BAR atom is %u\n", atom); + atom = XInternAtom(display, "WINDOW", False); + printf("WINDOW atom is %u\n", atom); + XMapWindow(display, win); /* Wait for ReparentNotify to get more similar behavior diff --git a/src/window.c b/src/window.c index 298ba0e..f639c91 100644 --- a/src/window.c +++ b/src/window.c @@ -557,3 +557,11 @@ XDestroySubwindows(Display *xdisplay, Window xwindow) wl_list_for_each_reverse_safe(child, next, &window->child_list, link) csx_window_destroy(child); } + +WL_EXPORT int +XChangeProperty(Display *xdisplay, Window xwindow, + Atom property, Atom type, int format, int mode, + const unsigned char *data, int nelements) +{ + STUB(); +} |