summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2013-07-03 01:14:29 -0400
committerKristian Høgsberg <krh@bitplanet.net>2013-07-03 01:14:29 -0400
commitc52758cee9526a837b3da46e4b4d01a96b49a417 (patch)
tree79c48c215ed0ed38d62bb851e44895aa9b9a2dd4
parent36d1b5d5ef307d74df4e3d3de3d16a60502e0fa1 (diff)
Improved error handling and atoms
-rw-r--r--NOTES5
-rw-r--r--src/Makefile.am3
-rw-r--r--src/display.c177
-rw-r--r--src/private.h19
-rw-r--r--src/test.c8
-rw-r--r--src/window.c8
6 files changed, 210 insertions, 10 deletions
diff --git a/NOTES b/NOTES
index 181abde..d38bc60 100644
--- a/NOTES
+++ b/NOTES
@@ -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);
diff --git a/src/test.c b/src/test.c
index 0e31203..88e2347 100644
--- a/src/test.c
+++ b/src/test.c
@@ -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();
+}