#include #include #include #include #include #include #include #include #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", 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); } 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++; } void csx_display_error(struct csx_display *display, 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 = display->major; event.minor_code = display->minor; error_handler(display->xdisplay, &event); } static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) { struct csx_display *display = data; display->shm_formats |= (1 << format); } struct wl_shm_listener shm_listenter = { shm_format }; static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { struct csx_display *display = data; if (strcmp(interface, "wl_compositor") == 0) { display->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); } else if (strcmp(interface, "wl_shell") == 0) { display->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1); } else if (strcmp(interface, "wl_shm") == 0) { display->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); wl_shm_add_listener(display->shm, &shm_listenter, display); } else if (strcmp(interface, "wl_seat") == 0) { csx_display_add_seat(display, id, version); } } static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { } static const struct wl_registry_listener registry_listener = { registry_handle_global, registry_handle_global_remove }; static XID resource_alloc(struct _XDisplay *xdisplay) { struct csx_display *display = csx_display(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; xdisplay = malloc(size); if (!xdisplay) return NULL; memset(xdisplay, 0, size); display = csx_display((Display *) xdisplay); display->xdisplay = (Display *) xdisplay; display->display = wl_display_connect(NULL); if (!display->display) { free(xdisplay); return NULL; } display->registry = wl_display_get_registry(display->display); wl_registry_add_listener(display->registry, ®istry_listener, display); wl_display_roundtrip(display->display); if (display->shm == NULL) { fprintf(stderr, "No wl_shm global\n"); free(xdisplay); return NULL; } wl_display_roundtrip(display->display); /* FIXME: Don't hardcode number of roundtrips */ wl_display_roundtrip(display->display); if (display->shm_formats == 0) { fprintf(stderr, "no shm formats available\n"); free(xdisplay); return NULL; } csx_display_add_resource(display, NULL); /* None resource */ display->depth24_visuals[0].visualid = csx_display_add_resource(display, &display->depth24_visuals[0]); display->depth24_visuals[0].class = DirectColor; display->depth24_visuals[0].red_mask = 0x00ff0000; display->depth24_visuals[0].green_mask = 0x0000ff00; display->depth24_visuals[0].blue_mask = 0x000000ff; display->depth24_visuals[0].bits_per_rgb = 8; display->depth24_visuals[0].map_entries = 2^24; display->depth24_visuals[0].visualid = csx_display_add_resource(display, &display->depth32_visuals[0]); display->depth24_visuals[0].class = DirectColor; display->depth24_visuals[0].red_mask = 0x00ff0000; display->depth24_visuals[0].green_mask = 0x0000ff00; display->depth24_visuals[0].blue_mask = 0x000000ff; display->depth24_visuals[0].bits_per_rgb = 8; display->depth24_visuals[0].map_entries = 2^32; display->depths[0].depth = 24; display->depths[0].nvisuals = 1; display->depths[0].visuals = display->depth24_visuals; display->depths[1].depth = 32; display->depths[1].nvisuals = 1; 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; display->screens[0].height = 600; display->screens[0].mwidth = 290; display->screens[0].mheight = 180; display->screens[0].ndepths = 2; display->screens[0].depths = display->depths; display->screens[0].root_depth = 24; display->screens[0].root_visual = &display->depth24_visuals[0]; display->screens[0].default_gc = None; /* FIXME */ display->screens[0].cmap = None; /* FIXME */ display->screens[0].white_pixel = 0xffffffff; display->screens[0].black_pixel = 0xff000000; display->screens[0].max_maps = 0; display->screens[0].min_maps = 0; display->screens[0].backing_store = NotUseful; display->screens[0].save_unders = False; display->screens[0].root_input_mask = KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | ExposureMask | StructureNotifyMask | SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask; display->serial = 1; display->next_atom = 1; for (p = predefined_atoms; *p; p += strlen(p) + 1) XInternAtom(display->xdisplay, p, False); wl_list_init(&display->event_list); display->next_major = 128; display->next_event = LASTEvent; display->next_error = FirstExtensionError; wl_list_init(&display->extension_list); xdisplay->fd = wl_display_get_fd(display->display); xdisplay->proto_major_version = 11; xdisplay->proto_minor_version = 0; xdisplay->vendor = "Wayland Client Side X Server"; xdisplay->resource_alloc = resource_alloc; xdisplay->byte_order = LSBFirst; xdisplay->bitmap_unit = 32; xdisplay->bitmap_pad = 32; xdisplay->bitmap_bit_order = LSBFirst; #if 0 int nformats; /* number of pixmap formats in list */ ScreenFormat *pixmap_format; /* pixmap format list */ #endif xdisplay->release = 1; #if 0 int qlen; /* Length of input event queue */ unsigned long last_request_read; /* seq number of last event read */ unsigned long request; /* sequence number of last request. */ #endif xdisplay->max_request_size = 1024; #if 0 struct _XrmHashBucketRec *db; #endif xdisplay->display_name = ":wayland"; xdisplay->default_screen = 0; xdisplay->nscreens = 1; xdisplay->screens = display->screens; xdisplay->motion_buffer = 256; xdisplay->min_keycode = 8; xdisplay->max_keycode = 255; if (csx_display_add_xfixes(display) == -1) { free(xdisplay); return NULL; } if (csx_display_add_randr(display) == -1) { free(xdisplay); return NULL; } /* 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; } WL_EXPORT int XConnectionNumber(Display *xdisplay) { struct csx_display *display = csx_display(xdisplay); return wl_display_get_fd(display->display); } WL_EXPORT Status XAddConnectionWatch(Display *xdisplay, XConnectionWatchProc callback, XPointer client_data) { STUB(); return 1; } WL_EXPORT void XRemoveConnectionWatch(Display *xdisplay, XConnectionWatchProc callback, XPointer client_data) { } WL_EXPORT void XProcessInternalConnection(Display *xdisplay, int fd) { } WL_EXPORT int XFlush(Display *xdisplay) { struct csx_display *display = csx_display(xdisplay); return wl_display_flush(display->display); } WL_EXPORT int XCloseDisplay(Display *xdisplay) { struct csx_display *display = csx_display(xdisplay); Atom i; if (display->shm) wl_shm_destroy(display->shm); if (display->shell) wl_shell_destroy(display->shell); if (display->compositor) wl_compositor_destroy(display->compositor); 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); return 0; } 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) { return RootWindow(xdisplay, screen_number); } WL_EXPORT Window XDefaultRootWindow(Display *xdisplay) { return DefaultRootWindow(xdisplay); } WL_EXPORT Window XRootWindowOfScreen(Screen *screen) { return RootWindowOfScreen(screen); } WL_EXPORT Visual * XDefaultVisual(Display *xdisplay, int screen_number) { return DefaultVisual(xdisplay, screen_number); } WL_EXPORT Visual * XDefaultVisualOfScreen(Screen *screen) { return DefaultVisualOfScreen(screen); } WL_EXPORT GC XDefaultGC(Display *xdisplay, int screen_number) { return DefaultGC(xdisplay, screen_number); } WL_EXPORT GC XDefaultGCOfScreen(Screen *screen) { return DefaultGCOfScreen(screen); } WL_EXPORT unsigned long XBlackPixel(Display *xdisplay, int screen_number) { return BlackPixel(xdisplay, screen_number); } WL_EXPORT unsigned long XWhitePixel(Display *xdisplay, int screen_number) { return WhitePixel(xdisplay, screen_number); } WL_EXPORT unsigned long XAllPlanes(void) { return AllPlanes; } WL_EXPORT unsigned long XBlackPixelOfScreen(Screen *screen) { return BlackPixelOfScreen(screen); } WL_EXPORT unsigned long 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; csx_display_enter(display, X_InternAtom, 0); 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_error(display, 0, BadAlloc); 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); csx_display_enter(display, X_GetAtomName, 0); if (atom >= display->next_atom) { csx_display_error(display, 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; } WL_EXPORT int XSetSelectionOwner(Display *xdisplay, Atom selection, Window owner, Time time) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_SetSelectionOwner, 0); STUB(); return 1; } WL_EXPORT Window XGetSelectionOwner(Display *xdisplay, Atom selection) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_GetSelectionOwner, 0); STUB(); return 1; } WL_EXPORT int XConvertSelection(Display *xdisplay, Atom selection, Atom target, Atom property, Window requestor, Time time) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_ConvertSelection, 0); STUB(); return 1; } WL_EXPORT int XGrabServer(Display *xdisplay) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_GrabServer, 0); STUB(); return 1; } WL_EXPORT int XUngrabServer(Display *xdisplay) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_UngrabServer, 0); STUB(); return 1; } void csx_display_add_extension(struct csx_display *display, struct csx_extension *extension, const char *name, int nevents, int nerrors) { extension->name = name; extension->major = display->next_major++; if (nevents > 0) { extension->first_event = display->next_event; display->next_event += nevents; } else { extension->first_event = 0; } if (nerrors > 0) { extension->first_error = display->next_error; display->next_error += nerrors; } else { extension->first_error = 0; } wl_list_insert(display->extension_list.prev, &extension->link); } struct csx_extension * csx_display_get_extension(struct csx_display *display, const char *name) { struct csx_extension *e; wl_list_for_each(e, &display->extension_list, link) if (strcmp(name, e->name) == 0) return e; return NULL; } WL_EXPORT int XQueryExtension(Display *xdisplay, const char *name, int *major, int *first_event, int *first_error) { struct csx_display *display = csx_display(xdisplay); struct csx_extension *e; csx_display_enter(display, X_QueryExtension, 0); e = csx_display_get_extension(display, name); if (e != NULL) { *major = e->major; *first_event = e->first_event; *first_error = e->first_error; return True; } *major = 0; *first_event = 0; *first_error = 0; return False; } WL_EXPORT char ** XListExtensions(Display *xdisplay, int *nextensions) { struct csx_display *display = csx_display(xdisplay); struct csx_extension *e; int len, i; char **list; csx_display_enter(display, X_ListExtensions, 0); len = wl_list_length(&display->extension_list); list = malloc((len + 1) * sizeof list[0]); if (list == NULL) { csx_display_error(display, 0, BadAlloc); return NULL; } i = 0; wl_list_for_each(e, &display->extension_list, link) { list[i] = strdup(e->name); if (list[i] == NULL) { csx_display_error(display, 0, BadAlloc); XFreeExtensionList(list); return NULL; } i++; } *nextensions = len; list[i] = NULL; return list; } WL_EXPORT int XFreeExtensionList(char **list) { int i; for (i = 0; list[i] != NULL; i++) free(list[0]); free(list); return 1; } WL_EXPORT Cursor XCreatePixmapCursor(Display *xdisplay, Pixmap source, Pixmap mask, XColor *foreground, XColor *background, unsigned int x, unsigned int y) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_CreateCursor, 0); STUB(); return 1; } WL_EXPORT Cursor XCreateGlyphCursor(Display *xdisplay, Font source_font, Font mask_font, unsigned int source_char, unsigned int mask_char, XColor const *foreground_color, XColor const *background_color) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_CreateGlyphCursor, 0); STUB(); return 1; } WL_EXPORT int XFreeCursor(Display *xdisplay, Cursor cursor) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_FreeCursor, 0); STUB(); return 1; } WL_EXPORT int XRecolorCursor(Display *xdisplay, Cursor cursor, XColor *foreground_color, XColor *background_color) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_RecolorCursor, 0); STUB(); return 1; } WL_EXPORT Status XQueryBestSize(Display *xdisplay, int class, Drawable which_screen, unsigned int width, unsigned int height, unsigned int *width_return, unsigned int *height_return) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_QueryBestSize, 0); STUB(); return 1; } WL_EXPORT int XSetScreenSaver(Display *xdisplay, int timeout, int interval, int prefer_blanking, int allow_exposures) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_SetScreenSaver, 0); STUB(); return 1; } WL_EXPORT int XGetScreenSaver(Display *xdisplay, int *timeout_return, int *interval_return, int *prefer_blanking_return, int *allow_exposures_return) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_GetScreenSaver, 0); STUB(); return 1; } WL_EXPORT int XAddHost(Display *xdisplay, XHostAddress *host) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_ChangeHosts, 0); STUB(); return 1; } WL_EXPORT int XRemoveHost(Display *xdisplay, XHostAddress *host) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_ChangeHosts, 0); STUB(); return 1; } WL_EXPORT int XAddHosts(Display *xdisplay, XHostAddress *hosts, int n) { int i; for (i = 0; i < n; i++) XAddHost(xdisplay, &hosts[i]); return 1; } WL_EXPORT int XRemoveHosts(Display *xdisplay, XHostAddress *hosts, int n) { int i; for (i = 0; i < n; i++) XRemoveHost(xdisplay, &hosts[i]); return 1; } WL_EXPORT XHostAddress * XListHosts(Display *xdisplay, int *nhosts, Bool* state_return) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_ListHosts, 0); STUB(); return NULL; } WL_EXPORT int XSetAccessControl(Display *xdisplay, int mode) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_SetAccessControl, 0); STUB(); return 1; } WL_EXPORT int XSetCloseDownMode(Display *xdisplay, int close_mode) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_SetCloseDownMode, 0); STUB(); return 1; } WL_EXPORT int XKillClient(Display *xdisplay, XID resource) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_KillClient, 0); STUB(); return 1; } WL_EXPORT int XForceScreenSaver(Display *xdisplay, int mode) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_ForceScreenSaver, 0); STUB(); return 1; } WL_EXPORT int XNoOp(Display *xdisplay) { struct csx_display *display = csx_display(xdisplay); csx_display_enter(display, X_NoOperation, 0); return 1; }