diff options
author | Jon Turney <jon.turney@dronecode.org.uk> | 2018-06-30 16:00:16 +0100 |
---|---|---|
committer | Jon Turney <jon.turney@dronecode.org.uk> | 2019-06-17 18:11:07 +0100 |
commit | 3fae9573a83ac8d7b177ebdf3ae68d6f5e1d6e52 (patch) | |
tree | 6aeac143eea0fab9e2e33810e38f6b1daa812af6 | |
parent | a5ef6cc5464c5af191a89934a2caf58f31987636 (diff) |
hw/xwin: xcbify clipboard integration
Convert clipboard integration code from libX11 to xcb
This drops support for COMPOUND_TEXT. Presumably some ancient
(pre-2000) clients exist which support that, but not UTF8_STRING, but we
don't have an example to test with. (Given the nature of the thing, the
users of those clients probably work in CJK languages)
Supporting COMPOUND_TEXT would also involve writing (or extracting from
Xlib) support for the ISO 2022 encoding.
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | hw/xwin/winclipboard/internal.h | 30 | ||||
-rw-r--r-- | hw/xwin/winclipboard/meson.build | 7 | ||||
-rw-r--r-- | hw/xwin/winclipboard/textconv.c | 9 | ||||
-rw-r--r-- | hw/xwin/winclipboard/thread.c | 276 | ||||
-rw-r--r-- | hw/xwin/winclipboard/winclipboard.h | 5 | ||||
-rw-r--r-- | hw/xwin/winclipboard/wndproc.c | 122 | ||||
-rw-r--r-- | hw/xwin/winclipboard/xevents.c | 651 | ||||
-rw-r--r-- | hw/xwin/winclipboard/xwinclip.c | 35 | ||||
-rw-r--r-- | hw/xwin/winclipboardinit.c | 8 |
10 files changed, 483 insertions, 662 deletions
diff --git a/configure.ac b/configure.ac index 6d2231284..5494bdf29 100644 --- a/configure.ac +++ b/configure.ac @@ -2146,7 +2146,7 @@ if test "x$XWIN" = xyes; then AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) AC_CHECK_TOOL(WINDRES, windres) - PKG_CHECK_MODULES([XWINMODULES],[x11 xau xdmcp xfixes x11-xcb xcb-aux xcb-composite xcb-image xcb-ewmh xcb-icccm]) + PKG_CHECK_MODULES([XWINMODULES],[x11 xau xdmcp x11-xcb xcb-aux xcb-composite xcb-image xcb-ewmh xcb-icccm xcb-xfixes]) if test "x$WINDOWSDRI" = xauto; then PKG_CHECK_EXISTS([windowsdriproto], [WINDOWSDRI=yes], [WINDOWSDRI=no]) diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h index 2c4a20426..bb862a258 100644 --- a/hw/xwin/winclipboard/internal.h +++ b/hw/xwin/winclipboard/internal.h @@ -31,8 +31,9 @@ #ifndef WINCLIPBOARD_INTERNAL_H #define WINCLIPBOARD_INTERNAL_H -/* X headers */ -#include <X11/Xlib.h> +#include <xcb/xproto.h> +#include <X11/Xfuncproto.h> // for _X_ATTRIBUTE_PRINTF +#include <X11/Xdefs.h> // for Bool type /* Windows headers */ #include <X11/Xwindows.h> @@ -67,15 +68,14 @@ void * winclipboardthread.c */ - typedef struct { - Atom atomClipboard; - Atom atomLocalProperty; - Atom atomUTF8String; - Atom atomCompoundText; - Atom atomTargets; - Atom atomIncr; + xcb_atom_t atomClipboard; + xcb_atom_t atomLocalProperty; + xcb_atom_t atomUTF8String; + xcb_atom_t atomCompoundText; + xcb_atom_t atomTargets; + xcb_atom_t atomIncr; } ClipboardAtoms; /* @@ -89,8 +89,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); typedef struct { - Display *pClipboardDisplay; - Window iClipboardWindow; + xcb_connection_t *pClipboardDisplay; + xcb_window_t iClipboardWindow; ClipboardAtoms *atoms; } ClipboardWindowCreationParams; @@ -100,17 +100,17 @@ typedef struct typedef struct { - Atom *targetList; + xcb_atom_t *targetList; unsigned char *incr; unsigned long int incrsize; } ClipboardConversionData; int winClipboardFlushXEvents(HWND hwnd, - Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atom); - + xcb_window_t iWindow, xcb_connection_t * pDisplay, + ClipboardConversionData *data, ClipboardAtoms *atoms); -Atom +xcb_atom_t winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms); void diff --git a/hw/xwin/winclipboard/meson.build b/hw/xwin/winclipboard/meson.build index 0395eb32d..c239f5325 100644 --- a/hw/xwin/winclipboard/meson.build +++ b/hw/xwin/winclipboard/meson.build @@ -12,8 +12,10 @@ xwin_clipboard = static_library( include_directories: inc, c_args: '-DHAVE_XWIN_CONFIG_H', dependencies: [ - dependency('x11'), - dependency('xfixes'), + dependency('xcb'), + dependency('xcb-aux'), + dependency('xcb-icccm'), + dependency('xcb-xfixes'), ], ) @@ -27,7 +29,6 @@ executable( srcs_xwinclip, link_with: xwin_clipboard, link_args: ['-lgdi32', '-lpthread'], - dependencies: [dependency('x11')], install: true, ) diff --git a/hw/xwin/winclipboard/textconv.c b/hw/xwin/winclipboard/textconv.c index 9c9cb3529..651ccc666 100644 --- a/hw/xwin/winclipboard/textconv.c +++ b/hw/xwin/winclipboard/textconv.c @@ -32,15 +32,6 @@ #include <xwin-config.h> #endif -/* - * Including any server header might define the macro _XSERVER64 on 64 bit machines. - * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen. - * So let's undef that macro if necessary. - */ -#ifdef _XSERVER64 -#undef _XSERVER64 -#endif - #include <stdlib.h> #include "internal.h" diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c index 4dd819e75..a1beb760f 100644 --- a/hw/xwin/winclipboard/thread.c +++ b/hw/xwin/winclipboard/thread.c @@ -36,19 +36,9 @@ #define HAS_WINSOCK 1 #endif -/* - * Including any server header might define the macro _XSERVER64 on 64 bit machines. - * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen. - * So let's undef that macro if necessary. - */ -#ifdef _XSERVER64 -#undef _XSERVER64 -#endif - #include <assert.h> #include <unistd.h> #include <fcntl.h> -#include <setjmp.h> #include <pthread.h> #include <locale.h> #include <sys/param.h> // for MAX() macro @@ -59,9 +49,11 @@ #include <errno.h> #endif -#include <X11/Xatom.h> -#include <X11/Xlocale.h> -#include <X11/extensions/Xfixes.h> +#include <xcb/xcb.h> +#include <xcb/xcb_aux.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xfixes.h> + #include "winclipboard.h" #include "internal.h" @@ -79,9 +71,6 @@ */ static HWND g_hwndClipboard = NULL; -static jmp_buf g_jmpEntry; -static XIOErrorHandler g_winClipboardOldIOErrorHandler; -static pthread_t g_winClipboardProcThread; int xfixes_event_base; int xfixes_error_base; @@ -91,13 +80,23 @@ int xfixes_error_base; */ static HWND -winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms); - -static int - winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr); +winClipboardCreateMessagingWindow(xcb_connection_t *conn, xcb_window_t iWindow, ClipboardAtoms *atoms); -static int - winClipboardIOErrorHandler(Display * pDisplay); +static xcb_atom_t +intern_atom(xcb_connection_t *conn, const char *atomName) +{ + xcb_intern_atom_reply_t *atom_reply; + xcb_intern_atom_cookie_t atom_cookie; + xcb_atom_t atom = XCB_ATOM_NONE; + + atom_cookie = xcb_intern_atom(conn, 0, strlen(atomName), atomName); + atom_reply = xcb_intern_atom_reply(conn, atom_cookie, NULL); + if (atom_reply) { + atom = atom_reply->atom; + free(atom_reply); + } + return atom; +} /* * Create X11 and Win32 messaging windows, and run message processing loop @@ -106,13 +105,12 @@ static int */ Bool -winClipboardProc(char *szDisplay) +winClipboardProc(char *szDisplay, xcb_auth_info_t *auth_info) { ClipboardAtoms atoms; int iReturn; HWND hwnd = NULL; int iConnectionNumber = 0; - #ifdef HAS_DEVWINDOWS int fdMessageQueue = 0; #else @@ -120,67 +118,27 @@ winClipboardProc(char *szDisplay) #endif fd_set fdsRead; int iMaxDescriptor; - Display *pDisplay = NULL; - Window iWindow = None; + xcb_connection_t *conn; + xcb_window_t iWindow = XCB_NONE; int iSelectError; Bool fShutdown = FALSE; - static Bool fErrorHandlerSet = FALSE; ClipboardConversionData data; + int screen; winDebug("winClipboardProc - Hello\n"); - { - const char *locale; - - /* Allow multiple threads to access Xlib */ - if (XInitThreads() == 0) { - ErrorF("winClipboardProc - XInitThreads failed.\n"); - } - - /* - * setlocale applies to all threads in the current process. - * Apply locale specified in LANG environment variable. - */ - locale = setlocale(LC_ALL, ""); - if (!locale) { - ErrorF("winClipboardProc - setlocale failed.\n"); - } - - /* See if X supports the current locale */ - if (XSupportsLocale() == FALSE) { - ErrorF("Warning: Locale '%s' not supported by X, falling back to 'C' locale.\n", locale); - setlocale(LC_ALL, "C"); - } - } - - g_winClipboardProcThread = pthread_self(); - - /* Set error handler */ - if (!fErrorHandlerSet) { - XSetErrorHandler(winClipboardErrorHandler); - g_winClipboardOldIOErrorHandler = - XSetIOErrorHandler(winClipboardIOErrorHandler); - fErrorHandlerSet = TRUE; - } - - /* Set jump point for Error exits */ - if (setjmp(g_jmpEntry)) { - ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n"); - goto winClipboardProc_Done; - } - /* Make sure that the display opened */ - pDisplay = XOpenDisplay(szDisplay); - if (pDisplay == NULL) { + conn = xcb_connect_to_display_with_auth_info(szDisplay, auth_info, &screen); + if (xcb_connection_has_error(conn)) { ErrorF("winClipboardProc - Failed opening the display, giving up\n"); goto winClipboardProc_Done; } - ErrorF("winClipboardProc - XOpenDisplay () returned and " + ErrorF("winClipboardProc - xcb_connect () returned and " "successfully opened the display.\n"); /* Get our connection number */ - iConnectionNumber = XConnectionNumber(pDisplay); + iConnectionNumber = xcb_get_file_descriptor(conn); #ifdef HAS_DEVWINDOWS /* Open a file descriptor for the windows message queue */ @@ -196,56 +154,75 @@ winClipboardProc(char *szDisplay) iMaxDescriptor = iConnectionNumber + 1; #endif - if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base)) + const xcb_query_extension_reply_t *xfixes_query; + xfixes_query = xcb_get_extension_data(conn, &xcb_xfixes_id); + if (!xfixes_query->present) ErrorF ("winClipboardProc - XFixes extension not present\n"); + xfixes_event_base = xfixes_query->first_event; + xfixes_error_base = xfixes_query->first_error; + /* Must advise server of XFIXES version we require */ + xcb_xfixes_query_version_unchecked(conn, 1, 0); /* Create atoms */ - atoms.atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False); - atoms.atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False); - atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False); - atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False); - atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False); - atoms.atomIncr = XInternAtom (pDisplay, "INCR", False); + atoms.atomClipboard = intern_atom(conn, "CLIPBOARD"); + atoms.atomLocalProperty = intern_atom(conn, "CYGX_CUT_BUFFER"); + atoms.atomUTF8String = intern_atom(conn, "UTF8_STRING"); + atoms.atomCompoundText = intern_atom(conn, "COMPOUND_TEXT"); + atoms.atomTargets = intern_atom(conn, "TARGETS"); + atoms.atomIncr = intern_atom(conn, "INCR"); + + xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screen); + xcb_window_t root_window_id = root_screen->root; /* Create a messaging window */ - iWindow = XCreateSimpleWindow(pDisplay, - XDefaultRootWindow(pDisplay), - 1, 1, - 500, 500, - 0, - XBlackPixel(pDisplay, 0), - XBlackPixel(pDisplay, 0)); - if (iWindow == 0) { + iWindow = xcb_generate_id(conn); + xcb_void_cookie_t cookie = xcb_create_window_checked(conn, + XCB_COPY_FROM_PARENT, + iWindow, + root_window_id, + 1, 1, + 500, 500, + 0, + XCB_WINDOW_CLASS_INPUT_ONLY, + XCB_COPY_FROM_PARENT, + 0, + NULL); + + xcb_generic_error_t *error; + if ((error = xcb_request_check(conn, cookie))) { ErrorF("winClipboardProc - Could not create an X window.\n"); + free(error); goto winClipboardProc_Done; } - XStoreName(pDisplay, iWindow, "xwinclip"); + xcb_icccm_set_wm_name(conn, iWindow, XCB_ATOM_STRING, 8, strlen("xwinclip"), "xwinclip"); /* Select event types to watch */ - if (XSelectInput(pDisplay, iWindow, PropertyChangeMask) == BadWindow) - ErrorF("winClipboardProc - XSelectInput generated BadWindow " - "on messaging window\n"); - - XFixesSelectSelectionInput (pDisplay, - iWindow, - XA_PRIMARY, - XFixesSetSelectionOwnerNotifyMask | - XFixesSelectionWindowDestroyNotifyMask | - XFixesSelectionClientCloseNotifyMask); + const static uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; + cookie = xcb_change_window_attributes_checked(conn, iWindow, XCB_CW_EVENT_MASK, values); + if ((error = xcb_request_check(conn, cookie))) { + ErrorF("winClipboardProc - Could not set event mask on messaging window\n"); + free(error); + } - XFixesSelectSelectionInput (pDisplay, - iWindow, - atoms.atomClipboard, - XFixesSetSelectionOwnerNotifyMask | - XFixesSelectionWindowDestroyNotifyMask | - XFixesSelectionClientCloseNotifyMask); + xcb_xfixes_select_selection_input(conn, + iWindow, + XCB_ATOM_PRIMARY, + XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE); + xcb_xfixes_select_selection_input(conn, + iWindow, + atoms.atomClipboard, + XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE); /* Initialize monitored selection state */ winClipboardInitMonitoredSelections(); /* Create Windows messaging window */ - hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms); + hwnd = winClipboardCreateMessagingWindow(conn, iWindow, &atoms); /* Save copy of HWND */ g_hwndClipboard = hwnd; @@ -253,20 +230,18 @@ winClipboardProc(char *szDisplay) /* Assert ownership of selections if Win32 clipboard is owned */ if (NULL != GetClipboardOwner()) { /* PRIMARY */ - iReturn = XSetSelectionOwner(pDisplay, XA_PRIMARY, - iWindow, CurrentTime); - if (iReturn == BadAtom || iReturn == BadWindow || - XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) { + cookie = xcb_set_selection_owner_checked(conn, iWindow, XCB_ATOM_PRIMARY, XCB_CURRENT_TIME); + if ((error = xcb_request_check(conn, cookie))) { ErrorF("winClipboardProc - Could not set PRIMARY owner\n"); + free(error); goto winClipboardProc_Done; } /* CLIPBOARD */ - iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard, - iWindow, CurrentTime); - if (iReturn == BadAtom || iReturn == BadWindow || - XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) { + cookie = xcb_set_selection_owner_checked(conn, iWindow, atoms.atomClipboard, XCB_CURRENT_TIME); + if ((error = xcb_request_check(conn, cookie))) { ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n"); + free(error); goto winClipboardProc_Done; } } @@ -278,8 +253,7 @@ winClipboardProc(char *szDisplay) while (1) { /* Process X events */ - winClipboardFlushXEvents(hwnd, - iWindow, pDisplay, &data, &atoms); + winClipboardFlushXEvents(hwnd, iWindow, conn, &data, &atoms); /* Process Windows messages */ if (!winClipboardFlushWindowsMessageQueue(hwnd)) { @@ -289,7 +263,7 @@ winClipboardProc(char *szDisplay) } /* We need to ensure that all pending requests are sent */ - XFlush(pDisplay); + xcb_flush(conn); /* Setup the file descriptor set */ /* @@ -371,12 +345,13 @@ winClipboardProc(char *szDisplay) } /* Close our X window */ - if (pDisplay && iWindow) { - iReturn = XDestroyWindow(pDisplay, iWindow); - if (iReturn == BadWindow) - ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n"); + if (!xcb_connection_has_error(conn) && iWindow) { + cookie = xcb_destroy_window_checked(conn, iWindow); + if ((error = xcb_request_check(conn, cookie))) + ErrorF("winClipboardProc - XDestroyWindow failed.\n"); else ErrorF("winClipboardProc - XDestroyWindow succeeded.\n"); + free(error); } #ifdef HAS_DEVWINDOWS @@ -385,26 +360,15 @@ winClipboardProc(char *szDisplay) close(fdMessageQueue); #endif -#if 0 /* - * FIXME: XCloseDisplay hangs if we call it - * - * XCloseDisplay() calls XSync(), so any outstanding errors are reported. - * If we are built into the server, this can deadlock if the server is - * in the process of exiting and waiting for this thread to exit. + * xcb_disconnect() does not sync, so is safe to call even when we are built + * into the server. Unlike XCloseDisplay() there will be no deadlock if the + * server is in the process of exiting and waiting for this thread to exit. */ - - /* Discard any remaining events */ - XSync(pDisplay, TRUE); - - /* Select event types to watch */ - XSelectInput(pDisplay, XDefaultRootWindow(pDisplay), None); - - /* Close our X display */ - if (pDisplay) { - XCloseDisplay(pDisplay); + if (!xcb_connection_has_error(conn)) { + /* Close our X display */ + xcb_disconnect(conn); } -#endif /* global clipboard variable reset */ g_hwndClipboard = NULL; @@ -417,7 +381,7 @@ winClipboardProc(char *szDisplay) */ static HWND -winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms) +winClipboardCreateMessagingWindow(xcb_connection_t *conn, xcb_window_t iWindow, ClipboardAtoms *atoms) { WNDCLASSEX wc; ClipboardWindowCreationParams cwcp; @@ -439,7 +403,7 @@ winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAt RegisterClassEx(&wc); /* Information to be passed to WM_CREATE */ - cwcp.pClipboardDisplay = pDisplay; + cwcp.pClipboardDisplay = conn; cwcp.iClipboardWindow = iWindow; cwcp.atoms = atoms; @@ -467,42 +431,6 @@ winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAt return hwnd; } -/* - * winClipboardErrorHandler - Our application specific error handler - */ - -static int -winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr) -{ - char pszErrorMsg[100]; - - XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg)); - ErrorF("winClipboardErrorHandler - ERROR: \n\t%s\n" - "\tSerial: %lu, Request Code: %d, Minor Code: %d\n", - pszErrorMsg, pErr->serial, pErr->request_code, pErr->minor_code); - return 0; -} - -/* - * winClipboardIOErrorHandler - Our application specific IO error handler - */ - -static int -winClipboardIOErrorHandler(Display * pDisplay) -{ - ErrorF("winClipboardIOErrorHandler!\n"); - - if (pthread_equal(pthread_self(), g_winClipboardProcThread)) { - /* Restart at the main entry point */ - longjmp(g_jmpEntry, 2); - } - - if (g_winClipboardOldIOErrorHandler) - g_winClipboardOldIOErrorHandler(pDisplay); - - return 0; -} - void winClipboardWindowDestroy(void) { diff --git a/hw/xwin/winclipboard/winclipboard.h b/hw/xwin/winclipboard/winclipboard.h index 2ae27fd2b..5b25e6e42 100644 --- a/hw/xwin/winclipboard/winclipboard.h +++ b/hw/xwin/winclipboard/winclipboard.h @@ -27,7 +27,10 @@ #ifndef WINCLIPBOARD_H #define WINCLIPBOARD_H -Bool winClipboardProc(char *szDisplay); +#include <X11/Xdefs.h> // for Bool type +#include <xcb/xcb.h> + +Bool winClipboardProc(char *szDisplay, xcb_auth_info_t *auth_info); void winFixClipboardChain(void); diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c index d1f7d4cfb..5af52778d 100644 --- a/hw/xwin/winclipboard/wndproc.c +++ b/hw/xwin/winclipboard/wndproc.c @@ -36,20 +36,12 @@ #include <xwin-config.h> #endif -/* - * Including any server header might define the macro _XSERVER64 on 64 bit machines. - * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen. - * So let's undef that macro if necessary. - */ -#ifdef _XSERVER64 -#undef _XSERVER64 -#endif - #include <sys/types.h> #include <sys/time.h> #include <limits.h> -#include <X11/Xatom.h> +#include <xcb/xproto.h> +#include <xcb/xcb_aux.h> #include "internal.h" #include "winclipboard.h" @@ -65,7 +57,7 @@ */ static int -winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, +winProcessXEventsTimeout(HWND hwnd, xcb_window_t iWindow, xcb_connection_t *conn, ClipboardConversionData *data, ClipboardAtoms *atoms, int iTimeoutSec) { int iConnNumber; @@ -76,7 +68,7 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, iTimeoutSec); /* Get our connection number */ - iConnNumber = XConnectionNumber(pDisplay); + iConnNumber = xcb_get_file_descriptor(conn); /* Loop for X events */ while (1) { @@ -84,7 +76,7 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, long remainingTime; /* Process X events */ - iReturn = winClipboardFlushXEvents(hwnd, iWindow, pDisplay, data, atoms); + iReturn = winClipboardFlushXEvents(hwnd, iWindow, conn, data, atoms); winDebug("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", iReturn); @@ -94,7 +86,7 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, } /* We need to ensure that all pending requests are sent */ - XFlush(pDisplay); + xcb_flush(conn); /* Setup the file descriptor set */ FD_ZERO(&fdsRead); @@ -136,8 +128,8 @@ winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay, LRESULT CALLBACK winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - static Display *pDisplay; - static Window iWindow; + static xcb_connection_t *conn; + static xcb_window_t iWindow; static ClipboardAtoms *atoms; static Bool fRunning; @@ -169,7 +161,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - WM_CREATE\n"); - pDisplay = cwcp->pClipboardDisplay; + conn = cwcp->pClipboardDisplay; iWindow = cwcp->iClipboardWindow; atoms = cwcp->atoms; fRunning = TRUE; @@ -183,7 +175,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_CLIPBOARDUPDATE: { - int iReturn; + xcb_generic_error_t *error; + xcb_void_cookie_t cookie_set; winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Enter\n"); @@ -217,6 +210,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (!IsClipboardFormatAvailable(CF_TEXT) && !IsClipboardFormatAvailable(CF_UNICODETEXT)) { + xcb_get_selection_owner_cookie_t cookie_get; + xcb_get_selection_owner_reply_t *reply; + winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " "Clipboard does not contain CF_TEXT nor " "CF_UNICODETEXT.\n"); @@ -225,33 +221,33 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) * We need to make sure that the X Server has processed * previous XSetSelectionOwner messages. */ - XSync(pDisplay, FALSE); + xcb_aux_sync(conn); winDebug("winClipboardWindowProc - XSync done.\n"); /* Release PRIMARY selection if owned */ - iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY); - if (iReturn == iWindow) { - winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " - "PRIMARY selection is owned by us.\n"); - XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime); + cookie_get = xcb_get_selection_owner(conn, XCB_ATOM_PRIMARY); + reply = xcb_get_selection_owner_reply(conn, cookie_get, NULL); + if (reply) { + if (reply->owner == iWindow) { + winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " + "PRIMARY selection is owned by us, releasing.\n"); + xcb_set_selection_owner(conn, XCB_NONE, XCB_ATOM_PRIMARY, XCB_CURRENT_TIME); + } + free(reply); } - else if (BadWindow == iReturn || BadAtom == iReturn) - ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " - "XGetSelectionOwner failed for PRIMARY: %d\n", - iReturn); /* Release CLIPBOARD selection if owned */ - iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard); - if (iReturn == iWindow) { - winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " - "CLIPBOARD selection is owned by us, releasing\n"); - XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime); + cookie_get = xcb_get_selection_owner(conn, atoms->atomClipboard); + reply = xcb_get_selection_owner_reply(conn, cookie_get, NULL); + if (reply) { + if (reply->owner == iWindow) { + winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " + "CLIPBOARD selection is owned by us, releasing\n"); + xcb_set_selection_owner(conn, XCB_NONE, atoms->atomClipboard, XCB_CURRENT_TIME); + } + free(reply); } - else if (BadWindow == iReturn || BadAtom == iReturn) - ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " - "XGetSelectionOwner failed for CLIPBOARD: %d\n", - iReturn); winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n"); @@ -259,26 +255,24 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } /* Reassert ownership of PRIMARY */ - iReturn = XSetSelectionOwner(pDisplay, - XA_PRIMARY, iWindow, CurrentTime); - if (iReturn == BadAtom || iReturn == BadWindow || - XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) { + cookie_set = xcb_set_selection_owner_checked(conn, iWindow, XCB_ATOM_PRIMARY, XCB_CURRENT_TIME); + error = xcb_request_check(conn, cookie_set); + if (error) { ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " "Could not reassert ownership of PRIMARY\n"); - } - else { + free(error); + } else { winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " "Reasserted ownership of PRIMARY\n"); } /* Reassert ownership of the CLIPBOARD */ - iReturn = XSetSelectionOwner(pDisplay, - atoms->atomClipboard, iWindow, CurrentTime); - - if (iReturn == BadAtom || iReturn == BadWindow || - XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) { + cookie_set = xcb_set_selection_owner_checked(conn, iWindow, atoms->atomClipboard, XCB_CURRENT_TIME); + error = xcb_request_check(conn, cookie_set); + if (error) { ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " "Could not reassert ownership of CLIPBOARD\n"); + free(error); } else { winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - " @@ -286,7 +280,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } /* Flush the pending SetSelectionOwner event now */ - XFlush(pDisplay); + xcb_flush(conn); } winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n"); return 0; @@ -323,7 +317,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { int iReturn; Bool pasted = FALSE; - Atom selection; + xcb_atom_t selection; ClipboardConversionData data; int best_target = 0; @@ -331,7 +325,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) (int)wParam); selection = winClipboardGetLastOwnedSelectionAtom(atoms); - if (selection == None) { + if (selection == XCB_NONE) { ErrorF("winClipboardWindowProc - no monitored selection is owned\n"); goto fake_paste; } @@ -339,11 +333,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - requesting targets for selection from owner\n"); /* Request the selection's supported conversion targets */ - XConvertSelection(pDisplay, - selection, - atoms->atomTargets, - atoms->atomLocalProperty, - iWindow, CurrentTime); + xcb_convert_selection(conn, iWindow, selection, atoms->atomTargets, + atoms->atomLocalProperty, XCB_CURRENT_TIME); /* Process X events */ data.incr = NULL; @@ -351,7 +342,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) iReturn = winProcessXEventsTimeout(hwnd, iWindow, - pDisplay, + conn, &data, atoms, WIN_POLL_TIMEOUT); @@ -366,17 +357,15 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { struct target_priority { - Atom target; + xcb_atom_t target; unsigned int priority; }; struct target_priority target_priority_table[] = { -#ifdef X_HAVE_UTF8_STRING { atoms->atomUTF8String, 0 }, -#endif - { atoms->atomCompoundText, 1 }, - { XA_STRING, 2 }, + // { atoms->atomCompoundText, 1 }, not implemented (yet?) + { XCB_ATOM_STRING, 2 }, }; int best_priority = INT_MAX; @@ -408,16 +397,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) winDebug("winClipboardWindowProc - requesting selection from owner\n"); /* Request the selection contents */ - XConvertSelection(pDisplay, - selection, - best_target, - atoms->atomLocalProperty, - iWindow, CurrentTime); + xcb_convert_selection(conn, iWindow, selection, best_target, + atoms->atomLocalProperty, XCB_CURRENT_TIME); /* Process X events */ iReturn = winProcessXEventsTimeout(hwnd, iWindow, - pDisplay, + conn, &data, atoms, WIN_POLL_TIMEOUT); diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c index 36e136148..672e7e139 100644 --- a/hw/xwin/winclipboard/xevents.c +++ b/hw/xwin/winclipboard/xevents.c @@ -34,20 +34,11 @@ #include <xwin-config.h> #endif -/* - * Including any server header might define the macro _XSERVER64 on 64 bit machines. - * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen. - * So let's undef that macro if necessary. - */ -#ifdef _XSERVER64 -#undef _XSERVER64 -#endif - #include <limits.h> #include <wchar.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/extensions/Xfixes.h> + +#include <xcb/xcb.h> +#include <xcb/xfixes.h> #include "winclipboard.h" #include "internal.h" @@ -57,10 +48,12 @@ */ #define CLIP_NUM_SELECTIONS 2 -#define CLIP_OWN_NONE -1 +#define CLIP_OWN_NONE -1 #define CLIP_OWN_PRIMARY 0 #define CLIP_OWN_CLIPBOARD 1 +#define CP_ISO_8559_1 28591 + /* * Global variables */ @@ -72,17 +65,17 @@ Bool fPrimarySelection = TRUE; * Local variables */ -static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None }; +static xcb_window_t s_iOwners[CLIP_NUM_SELECTIONS] = { XCB_NONE, XCB_NONE }; static const char *szSelectionNames[CLIP_NUM_SELECTIONS] = { "PRIMARY", "CLIPBOARD" }; static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE; static void -MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i) +MonitorSelection(xcb_xfixes_selection_notify_event_t * e, unsigned int i) { /* Look for owned -> not owned transition */ - if (None == e->owner && None != s_iOwners[i]) { + if ((XCB_NONE == e->owner) && (XCB_NONE != s_iOwners[i])) { unsigned int other_index; winDebug("MonitorSelection - %s - Going from owned to not owned.\n", @@ -94,36 +87,36 @@ MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i) other_index = CLIP_OWN_CLIPBOARD; if (i == CLIP_OWN_CLIPBOARD) other_index = CLIP_OWN_PRIMARY; - if (None != s_iOwners[other_index]) + if (XCB_NONE != s_iOwners[other_index]) lastOwnedSelectionIndex = other_index; else lastOwnedSelectionIndex = CLIP_OWN_NONE; } /* Save last owned selection */ - if (None != e->owner) { + if (XCB_NONE != e->owner) { lastOwnedSelectionIndex = i; } /* Save new selection owner or None */ s_iOwners[i] = e->owner; - winDebug("MonitorSelection - %s - Now owned by XID %lx\n", + winDebug("MonitorSelection - %s - Now owned by XID %x\n", szSelectionNames[i], e->owner); } -Atom +xcb_atom_t winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms) { if (lastOwnedSelectionIndex == CLIP_OWN_NONE) - return None; + return XCB_NONE; if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY) - return XA_PRIMARY; + return XCB_ATOM_PRIMARY; if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD) return atoms->atomClipboard; - return None; + return XCB_NONE; } @@ -133,102 +126,116 @@ winClipboardInitMonitoredSelections(void) /* Initialize static variables */ int i; for (i = 0; i < CLIP_NUM_SELECTIONS; ++i) - s_iOwners[i] = None; + s_iOwners[i] = XCB_NONE; lastOwnedSelectionIndex = CLIP_OWN_NONE; } -static int -winClipboardSelectionNotifyTargets(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) +static char *get_atom_name(xcb_connection_t *conn, xcb_atom_t atom) { - Atom type; - int format; - unsigned long nitems; - unsigned long after; - Atom *prop; + char *ret; + xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(conn, atom); + xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(conn, cookie, NULL); + if (!reply) + return NULL; + ret = malloc(xcb_get_atom_name_name_length(reply) + 1); + if (ret) { + memcpy(ret, xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); + ret[xcb_get_atom_name_name_length(reply)] = '\0'; + } + free(reply); + return ret; +} +static int +winClipboardSelectionNotifyTargets(HWND hwnd, xcb_window_t iWindow, xcb_connection_t *conn, ClipboardConversionData *data, ClipboardAtoms *atoms) +{ /* Retrieve the selection data and delete the property */ - int iReturn = XGetWindowProperty(pDisplay, - iWindow, - atoms->atomLocalProperty, - 0, - INT_MAX, - True, - AnyPropertyType, - &type, - &format, - &nitems, - &after, - (unsigned char **)&prop); - if (iReturn != Success) { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "XGetWindowProperty () failed, aborting: %d\n", iReturn); + xcb_get_property_cookie_t cookie = xcb_get_property(conn, + TRUE, + iWindow, + atoms->atomLocalProperty, + XCB_GET_PROPERTY_TYPE_ANY, + 0, + INT_MAX); + xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL); + if (!reply) { + ErrorF("winClipboardFlushXEvents - SelectionNotify - " + "XGetWindowProperty () failed\n"); } else { - int i; - data->targetList = malloc((nitems+1)*sizeof(Atom)); - - for (i = 0; i < nitems; i++) - { - Atom atom = prop[i]; - char *pszAtomName = XGetAtomName(pDisplay, atom); - data->targetList[i] = atom; - winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %ld = %s\n", i, atom, pszAtomName); - XFree(pszAtomName); + xcb_atom_t *prop = xcb_get_property_value(reply); + int nitems = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t); + int i; + data->targetList = malloc((nitems+1)*sizeof(xcb_atom_t)); + + for (i = 0; i < nitems; i++) + { + xcb_atom_t atom = prop[i]; + char *pszAtomName = get_atom_name(conn, atom); + data->targetList[i] = atom; + winDebug("winClipboardFlushXEvents - SelectionNotify - target[%d] %d = %s\n", i, atom, pszAtomName); + free(pszAtomName); } data->targetList[nitems] = 0; - XFree(prop); + free(reply); } return WIN_XEVENTS_NOTIFY_TARGETS; } static int -winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) +winClipboardSelectionNotifyData(HWND hwnd, xcb_window_t iWindow, xcb_connection_t *conn, ClipboardConversionData *data, ClipboardAtoms *atoms) { - Atom encoding; + xcb_atom_t encoding; int format; unsigned long int nitems; unsigned long int after; unsigned char *value; - XTextProperty xtpText = { 0 }; + + unsigned char *xtpText_value; + xcb_atom_t xtpText_encoding; + int xtpText_nitems; + Bool fSetClipboardData = TRUE; - int iReturn; - char **ppszTextList = NULL; - int iCount; char *pszReturnData = NULL; + UINT codepage; wchar_t *pwszUnicodeStr = NULL; HGLOBAL hGlobal = NULL; char *pszGlobalData = NULL; /* Retrieve the selection data and delete the property */ - iReturn = XGetWindowProperty(pDisplay, - iWindow, - atoms->atomLocalProperty, - 0, - INT_MAX, - True, - AnyPropertyType, - &encoding, - &format, - &nitems, - &after, - &value); - if (iReturn != Success) { + xcb_get_property_cookie_t cookie = xcb_get_property(conn, + TRUE, + iWindow, + atoms->atomLocalProperty, + XCB_GET_PROPERTY_TYPE_ANY, + 0, + INT_MAX); + xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, NULL); + if (!reply) { ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "XGetWindowProperty () failed, aborting: %d\n", iReturn); + "XGetWindowProperty () failed\n"); goto winClipboardFlushXEvents_SelectionNotify_Done; + } else { + nitems = xcb_get_property_value_length(reply); + value = xcb_get_property_value(reply); + after = reply->bytes_after; + encoding = reply->type; + format = reply->format; + // We assume format == 8 (i.e. data is a sequence of bytes). It's not + // clear how anything else should be handled. + if (format != 8) + ErrorF("SelectionNotify: format is %d, proceeding as if it was 8\n", format); } { - char *pszAtomName = NULL; - + char *pszAtomName; winDebug("SelectionNotify - returned data %lu left %lu\n", nitems, after); - pszAtomName = XGetAtomName(pDisplay, encoding); + pszAtomName = get_atom_name(conn, encoding); winDebug("Notify atom name %s\n", pszAtomName); - XFree(pszAtomName); - pszAtomName = NULL; + free(pszAtomName); } /* INCR reply indicates the start of a incremental transfer */ @@ -244,10 +251,12 @@ winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, Cl if (nitems == 0) { winDebug("winClipboardSelectionNotifyData: ending INCR, actual size %ld\n", data->incrsize); /* a zero-length property indicates the end of the data */ - xtpText.value = data->incr; - xtpText.encoding = encoding; - xtpText.format = format; // XXX: The type of the converted selection is the type of the first partial property. The remaining partial properties must have the same type. - xtpText.nitems = data->incrsize; + xtpText_value = data->incr; + xtpText_encoding = encoding; + // XXX: The type of the converted selection is the type of the first + // partial property. The remaining partial properties must have the + // same type. + xtpText_nitems = data->incrsize; } else { /* Otherwise, continue appending the INCR data */ @@ -261,70 +270,34 @@ winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, Cl else { /* Otherwise, the data is just contained in the property */ winDebug("winClipboardSelectionNotifyData: non-INCR, %ld bytes\n", nitems); - xtpText.value = value; - xtpText.encoding = encoding; - xtpText.format = format; - xtpText.nitems = nitems; + xtpText_value = value; + xtpText_encoding = encoding; + xtpText_nitems = nitems; } -#ifdef X_HAVE_UTF8_STRING - /* Convert the text property to a text list */ - iReturn = Xutf8TextPropertyToTextList(pDisplay, - &xtpText, - &ppszTextList, &iCount); -#endif - - if (iReturn == Success || iReturn > 0) { - /* Conversion succeeded or some unconvertible characters */ - if (ppszTextList != NULL) { - int i; - int iReturnDataLen = 0; - for (i = 0; i < iCount; i++) { - iReturnDataLen += strlen(ppszTextList[i]); - } - pszReturnData = malloc(iReturnDataLen + 1); - pszReturnData[0] = '\0'; - for (i = 0; i < iCount; i++) { - strcat(pszReturnData, ppszTextList[i]); - } - } - else { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "X*TextPropertyToTextList list_return is NULL.\n"); - pszReturnData = malloc(1); - pszReturnData[0] = '\0'; - } - } - else { - ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "X*TextPropertyToTextList returned: "); - switch (iReturn) { - case XNoMemory: - ErrorF("XNoMemory\n"); - break; - case XLocaleNotSupported: - ErrorF("XLocaleNotSupported\n"); - break; - case XConverterNotFound: - ErrorF("XConverterNotFound\n"); - break; - default: - ErrorF("%d\n", iReturn); - break; - } + if (xtpText_encoding == atoms->atomUTF8String) { + pszReturnData = malloc(xtpText_nitems + 1); + memcpy(pszReturnData, xtpText_value, xtpText_nitems); + pszReturnData[xtpText_nitems] = 0; + codepage = CP_UTF8; // code page identifier for utf8 + } else if (xtpText_encoding == XCB_ATOM_STRING) { + // STRING encoding is Latin1 (ISO8859-1) plus tab and newline + pszReturnData = malloc(xtpText_nitems + 1); + memcpy(pszReturnData, xtpText_value, xtpText_nitems); + pszReturnData[xtpText_nitems] = 0; + codepage = CP_ISO_8559_1; // code page identifier for iso-8559-1 + } else if (xtpText_encoding == atoms->atomCompoundText) { + // COMPOUND_TEXT is complex, based on ISO 2022 + ErrorF("SelectionNotify: data in COMPOUND_TEXT encoding which is not implemented, discarding\n"); + pszReturnData = malloc(1); + pszReturnData[0] = '\0'; + } else { // shouldn't happen as we accept no other encodings pszReturnData = malloc(1); pszReturnData[0] = '\0'; } - - if (ppszTextList) - XFreeStringList(ppszTextList); - ppszTextList = NULL; - - /* Free the data returned from XGetWindowProperty */ - XFree(value); - value = NULL; - nitems = 0; + /* Free the data returned from xcb_get_property */ + free(reply); /* Free any INCR data */ if (data->incr) { @@ -336,9 +309,8 @@ winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, Cl /* Convert the X clipboard string to DOS format */ winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData)); - /* Find out how much space needed to convert MBCS to Unicode */ - int iUnicodeLen = MultiByteToWideChar(CP_UTF8, - 0, + /* Find out how much space needed when converted to UTF-16 */ + int iUnicodeLen = MultiByteToWideChar(codepage, 0, pszReturnData, -1, NULL, 0); /* NOTE: iUnicodeLen includes space for null terminator */ @@ -352,15 +324,12 @@ winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, Cl } /* Do the actual conversion */ - MultiByteToWideChar(CP_UTF8, - 0, - pszReturnData, - -1, pwszUnicodeStr, iUnicodeLen); + MultiByteToWideChar(codepage, 0, + pszReturnData, -1, pwszUnicodeStr, iUnicodeLen); /* Allocate global memory for the X clipboard data */ hGlobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(wchar_t) * iUnicodeLen); - free(pszReturnData); /* Check that global memory was allocated */ @@ -404,13 +373,6 @@ winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, Cl winClipboardFlushXEvents_SelectionNotify_Done: /* Free allocated resources */ - if (ppszTextList) - XFreeStringList(ppszTextList); - if (value) { - XFree(value); - value = NULL; - nitems = 0; - } free(pwszUnicodeStr); if (hGlobal && pszGlobalData) GlobalUnlock(hGlobal); @@ -427,105 +389,97 @@ winClipboardSelectionNotifyData(HWND hwnd, Window iWindow, Display *pDisplay, Cl int winClipboardFlushXEvents(HWND hwnd, - Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms) + xcb_window_t iWindow, xcb_connection_t *conn, + ClipboardConversionData *data, ClipboardAtoms *atoms) { - Atom atomClipboard = atoms->atomClipboard; - Atom atomUTF8String = atoms->atomUTF8String; - Atom atomCompoundText = atoms->atomCompoundText; - Atom atomTargets = atoms->atomTargets; + xcb_atom_t atomClipboard = atoms->atomClipboard; + xcb_atom_t atomUTF8String = atoms->atomUTF8String; + xcb_atom_t atomCompoundText = atoms->atomCompoundText; + xcb_atom_t atomTargets = atoms->atomTargets; /* Process all pending events */ - while (XPending(pDisplay)) { - XTextProperty xtpText = { 0 }; - XEvent event; - XSelectionEvent eventSelection; + xcb_generic_event_t *event; + while ((event = xcb_poll_for_event(conn))) { char *pszGlobalData = NULL; - int iReturn; HGLOBAL hGlobal = NULL; - XICCEncodingStyle xiccesStyle; char *pszConvertData = NULL; - char *pszTextList[2] = { NULL }; Bool fAbort = FALSE; Bool fCloseClipboard = FALSE; - /* Get the next event - will not block because one is ready */ - XNextEvent(pDisplay, &event); - /* Branch on the event type */ - switch (event.type) { - /* - * SelectionRequest - */ + switch (event->response_type & ~0x80) { + case XCB_SELECTION_REQUEST: + { + char *xtpText_value = NULL; + int xtpText_nitems; + UINT codepage; - case SelectionRequest: + xcb_selection_request_event_t *selection_request = (xcb_selection_request_event_t *)event; { char *pszAtomName = NULL; - winDebug("SelectionRequest - target %ld\n", - event.xselectionrequest.target); + winDebug("SelectionRequest - target %d\n", selection_request->target); - pszAtomName = XGetAtomName(pDisplay, - event.xselectionrequest.target); + pszAtomName = get_atom_name(conn, selection_request->target); winDebug("SelectionRequest - Target atom name %s\n", pszAtomName); - XFree(pszAtomName); - pszAtomName = NULL; + free(pszAtomName); } /* Abort if invalid target type */ - if (event.xselectionrequest.target != XA_STRING - && event.xselectionrequest.target != atomUTF8String - && event.xselectionrequest.target != atomCompoundText - && event.xselectionrequest.target != atomTargets) { + if (selection_request->target != XCB_ATOM_STRING + && selection_request->target != atomUTF8String + && selection_request->target != atomCompoundText + && selection_request->target != atomTargets) { /* Abort */ fAbort = TRUE; goto winClipboardFlushXEvents_SelectionRequest_Done; } /* Handle targets type of request */ - if (event.xselectionrequest.target == atomTargets) { - Atom atomTargetArr[] = { atomTargets, - atomCompoundText, - atomUTF8String, - XA_STRING - }; + if (selection_request->target == atomTargets) { + xcb_atom_t atomTargetArr[] = + { + atomTargets, + atomUTF8String, + XCB_ATOM_STRING, + // atomCompoundText, not implemented (yet?) + }; /* Try to change the property */ - iReturn = XChangeProperty(pDisplay, - event.xselectionrequest.requestor, - event.xselectionrequest.property, - XA_ATOM, + xcb_void_cookie_t cookie = xcb_change_property_checked(conn, + XCB_PROP_MODE_REPLACE, + selection_request->requestor, + selection_request->property, + XCB_ATOM_ATOM, 32, - PropModeReplace, - (unsigned char *) atomTargetArr, - ARRAY_SIZE(atomTargetArr)); - if (iReturn == BadAlloc - || iReturn == BadAtom - || iReturn == BadMatch - || iReturn == BadValue || iReturn == BadWindow) { + ARRAY_SIZE(atomTargetArr), + (unsigned char *) atomTargetArr); + xcb_generic_error_t *error; + if ((error = xcb_request_check(conn, cookie))) { ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "XChangeProperty failed: %d\n", iReturn); + "xcb_change_property failed"); + free(error); } /* Setup selection notify xevent */ - eventSelection.type = SelectionNotify; - eventSelection.send_event = True; - eventSelection.display = pDisplay; - eventSelection.requestor = event.xselectionrequest.requestor; - eventSelection.selection = event.xselectionrequest.selection; - eventSelection.target = event.xselectionrequest.target; - eventSelection.property = event.xselectionrequest.property; - eventSelection.time = event.xselectionrequest.time; + xcb_selection_notify_event_t eventSelection; + eventSelection.response_type = XCB_SELECTION_NOTIFY; + eventSelection.requestor = selection_request->requestor; + eventSelection.selection = selection_request->selection; + eventSelection.target = selection_request->target; + eventSelection.property = selection_request->property; + eventSelection.time = selection_request->time; /* * Notify the requesting window that * the operation has completed */ - iReturn = XSendEvent(pDisplay, - eventSelection.requestor, - False, 0L, (XEvent *) &eventSelection); - if (iReturn == BadValue || iReturn == BadWindow) { + cookie = xcb_send_event_checked(conn, FALSE, + eventSelection.requestor, + 0, (char *) &eventSelection); + if ((error = xcb_request_check(conn, cookie))) { ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "XSendEvent () failed\n"); + "xcb_send_event() failed\n"); } break; } @@ -567,18 +521,6 @@ winClipboardFlushXEvents(HWND hwnd, goto winClipboardFlushXEvents_SelectionRequest_Done; } - /* Setup the string style */ - if (event.xselectionrequest.target == XA_STRING) - xiccesStyle = XStringStyle; -#ifdef X_HAVE_UTF8_STRING - else if (event.xselectionrequest.target == atomUTF8String) - xiccesStyle = XUTF8StringStyle; -#endif - else if (event.xselectionrequest.target == atomCompoundText) - xiccesStyle = XCompoundTextStyle; - else - xiccesStyle = XStringStyle; - /* Get a pointer to the clipboard text, in desired format */ /* Retrieve clipboard data */ hGlobal = GetClipboardData(CF_UNICODETEXT); @@ -593,62 +535,42 @@ winClipboardFlushXEvents(HWND hwnd, } pszGlobalData = (char *) GlobalLock(hGlobal); - /* Convert the Unicode string to UTF8 (MBCS) */ - int iConvertDataLen = WideCharToMultiByte(CP_UTF8, - 0, - (LPCWSTR) pszGlobalData, - -1, NULL, 0, NULL, NULL); + /* Convert to target string style */ + if (selection_request->target == XCB_ATOM_STRING) { + codepage = CP_ISO_8559_1; // code page identifier for iso-8559-1 + } else if (selection_request->target == atomUTF8String) { + codepage = CP_UTF8; // code page identifier for utf8 + } else if (selection_request->target == atomCompoundText) { + // COMPOUND_TEXT is complex, not (yet) implemented + pszGlobalData = "COMPOUND_TEXT not implemented"; + codepage = CP_UTF8; // code page identifier for utf8 + } + + /* Convert the UTF16 string to required encoding */ + int iConvertDataLen = WideCharToMultiByte(codepage, 0, + (LPCWSTR) pszGlobalData, -1, + NULL, 0, NULL, NULL); /* NOTE: iConvertDataLen includes space for null terminator */ pszConvertData = malloc(iConvertDataLen); - WideCharToMultiByte(CP_UTF8, - 0, - (LPCWSTR) pszGlobalData, - -1, - pszConvertData, - iConvertDataLen, NULL, NULL); + WideCharToMultiByte(codepage, 0, + (LPCWSTR) pszGlobalData, -1, + pszConvertData, iConvertDataLen, NULL, NULL); /* Convert DOS string to UNIX string */ winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData)); - /* Setup our text list */ - pszTextList[0] = pszConvertData; - pszTextList[1] = NULL; - - /* Initialize the text property */ - xtpText.value = NULL; - xtpText.nitems = 0; - - /* Create the text property from the text list */ -#ifdef X_HAVE_UTF8_STRING - iReturn = Xutf8TextListToTextProperty(pDisplay, - pszTextList, - 1, xiccesStyle, &xtpText); -#endif - - if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) { - ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "X*TextListToTextProperty failed: %d\n", iReturn); - - /* Abort */ - fAbort = TRUE; - goto winClipboardFlushXEvents_SelectionRequest_Done; - } - - /* Free the converted string */ - free(pszConvertData); - pszConvertData = NULL; + xtpText_value = strdup(pszConvertData); + xtpText_nitems = iConvertDataLen - 1; - /* data will fit into a single X request (INCR not yet supported) */ + /* data will fit into a single X request? (INCR not yet supported) */ { - long unsigned int maxreqsize = XExtendedMaxRequestSize(pDisplay); - if (maxreqsize == 0) - maxreqsize = XMaxRequestSize(pDisplay); + uint32_t maxreqsize = xcb_get_maximum_request_length(conn); /* covert to bytes and allow for allow for X_ChangeProperty request */ maxreqsize = maxreqsize*4 - 24; - if (xtpText.nitems > maxreqsize) { - ErrorF("winClipboardFlushXEvents - clipboard data size %lu greater than maximum %lu\n", xtpText.nitems, maxreqsize); + if (xtpText_nitems > maxreqsize) { + ErrorF("winClipboardFlushXEvents - clipboard data size %d greater than maximum %u\n", xtpText_nitems, maxreqsize); /* Abort */ fAbort = TRUE; @@ -657,24 +579,27 @@ winClipboardFlushXEvents(HWND hwnd, } /* Copy the clipboard text to the requesting window */ - iReturn = XChangeProperty(pDisplay, - event.xselectionrequest.requestor, - event.xselectionrequest.property, - event.xselectionrequest.target, + xcb_void_cookie_t cookie = xcb_change_property_checked(conn, + XCB_PROP_MODE_REPLACE, + selection_request->requestor, + selection_request->property, + selection_request->target, 8, - PropModeReplace, - xtpText.value, xtpText.nitems); - if (iReturn == BadAlloc || iReturn == BadAtom - || iReturn == BadMatch || iReturn == BadValue - || iReturn == BadWindow) { + xtpText_nitems, xtpText_value); + xcb_generic_error_t *error; + if ((error = xcb_request_check(conn, cookie))) { ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "XChangeProperty failed: %d\n", iReturn); + "xcb_change_property failed\n"); /* Abort */ fAbort = TRUE; goto winClipboardFlushXEvents_SelectionRequest_Done; } + /* Free the converted string */ + free(pszConvertData); + pszConvertData = NULL; + /* Release the clipboard data */ GlobalUnlock(hGlobal); pszGlobalData = NULL; @@ -682,27 +607,25 @@ winClipboardFlushXEvents(HWND hwnd, CloseClipboard(); /* Clean up */ - XFree(xtpText.value); - xtpText.value = NULL; - xtpText.nitems = 0; + free(xtpText_value); + xtpText_value = NULL; /* Setup selection notify event */ - eventSelection.type = SelectionNotify; - eventSelection.send_event = True; - eventSelection.display = pDisplay; - eventSelection.requestor = event.xselectionrequest.requestor; - eventSelection.selection = event.xselectionrequest.selection; - eventSelection.target = event.xselectionrequest.target; - eventSelection.property = event.xselectionrequest.property; - eventSelection.time = event.xselectionrequest.time; + xcb_selection_notify_event_t eventSelection; + eventSelection.response_type = XCB_SELECTION_NOTIFY; + eventSelection.requestor = selection_request->requestor; + eventSelection.selection = selection_request->selection; + eventSelection.target = selection_request->target; + eventSelection.property = selection_request->property; + eventSelection.time = selection_request->time; /* Notify the requesting window that the operation has completed */ - iReturn = XSendEvent(pDisplay, - eventSelection.requestor, - False, 0L, (XEvent *) &eventSelection); - if (iReturn == BadValue || iReturn == BadWindow) { + cookie = xcb_send_event_checked(conn, FALSE, + eventSelection.requestor, + 0, (char *) &eventSelection); + if ((error = xcb_request_check(conn, cookie))) { ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "XSendEvent () failed\n"); + "xcb_send_event() failed\n"); /* Abort */ fAbort = TRUE; @@ -711,12 +634,11 @@ winClipboardFlushXEvents(HWND hwnd, winClipboardFlushXEvents_SelectionRequest_Done: /* Free allocated resources */ - if (xtpText.value) { - XFree(xtpText.value); - xtpText.value = NULL; - xtpText.nitems = 0; + if (xtpText_value) { + free(xtpText_value); } - free(pszConvertData); + if (pszConvertData) + free(pszConvertData); if (hGlobal && pszGlobalData) GlobalUnlock(hGlobal); @@ -726,26 +648,24 @@ winClipboardFlushXEvents(HWND hwnd, */ if (fAbort) { /* Setup selection notify event */ - eventSelection.type = SelectionNotify; - eventSelection.send_event = True; - eventSelection.display = pDisplay; - eventSelection.requestor = event.xselectionrequest.requestor; - eventSelection.selection = event.xselectionrequest.selection; - eventSelection.target = event.xselectionrequest.target; - eventSelection.property = None; - eventSelection.time = event.xselectionrequest.time; + eventSelection.response_type = XCB_SELECTION_NOTIFY; + eventSelection.requestor = selection_request->requestor; + eventSelection.selection = selection_request->selection; + eventSelection.target = selection_request->target; + eventSelection.property = XCB_NONE; + eventSelection.time = selection_request->time; /* Notify the requesting window that the operation is complete */ - iReturn = XSendEvent(pDisplay, - eventSelection.requestor, - False, 0L, (XEvent *) &eventSelection); - if (iReturn == BadValue || iReturn == BadWindow) { + cookie = xcb_send_event_checked(conn, FALSE, + eventSelection.requestor, + 0, (char *) &eventSelection); + if ((error = xcb_request_check(conn, cookie))) { /* * Should not be a problem if XSendEvent fails because * the client may simply have exited. */ ErrorF("winClipboardFlushXEvents - SelectionRequest - " - "XSendEvent () failed for abort event.\n"); + "xcb_send_event() failed for abort event.\n"); } } @@ -755,71 +675,79 @@ winClipboardFlushXEvents(HWND hwnd, CloseClipboard(); } break; + } - /* - * SelectionNotify - */ - - case SelectionNotify: + case XCB_SELECTION_NOTIFY: + { + xcb_selection_notify_event_t *selection_notify = (xcb_selection_notify_event_t *)event; winDebug("winClipboardFlushXEvents - SelectionNotify\n"); { char *pszAtomName; - - pszAtomName = XGetAtomName(pDisplay, - event.xselection.selection); - - winDebug - ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n", - pszAtomName); - XFree(pszAtomName); + pszAtomName = get_atom_name(conn, selection_notify->selection); + winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n", pszAtomName); + free(pszAtomName); } /* - SelectionNotify with property of None indicates either: + SelectionNotify with property of XCB_NONE indicates either: (i) Generated by the X server if no owner for the specified selection exists (perhaps it's disappeared on us mid-transaction), or (ii) Sent by the selection owner when the requested selection conversion could not be performed or server errors prevented the conversion data being returned */ - if (event.xselection.property == None) { + if (selection_notify->property == XCB_NONE) { ErrorF("winClipboardFlushXEvents - SelectionNotify - " - "Conversion to format %ld refused.\n", - event.xselection.target); + "Conversion to format %d refused.\n", + selection_notify->target); return WIN_XEVENTS_FAILED; } - if (event.xselection.target == atomTargets) { - return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms); + if (selection_notify->target == atomTargets) { + return winClipboardSelectionNotifyTargets(hwnd, iWindow, conn, data, atoms); } - return winClipboardSelectionNotifyData(hwnd, iWindow, pDisplay, data, atoms); + return winClipboardSelectionNotifyData(hwnd, iWindow, conn, data, atoms); + } - case SelectionClear: + case XCB_SELECTION_CLEAR: winDebug("SelectionClear - doing nothing\n"); break; - case PropertyNotify: + case XCB_PROPERTY_NOTIFY: + { + xcb_property_notify_event_t *property_notify = (xcb_property_notify_event_t *)event; + /* If INCR is in progress, collect the data */ if (data->incr && - (event.xproperty.atom == atoms->atomLocalProperty) && - (event.xproperty.state == PropertyNewValue)) - return winClipboardSelectionNotifyData(hwnd, iWindow, pDisplay, data, atoms); + (property_notify->atom == atoms->atomLocalProperty) && + (property_notify->state == XCB_PROPERTY_NEW_VALUE)) + return winClipboardSelectionNotifyData(hwnd, iWindow, conn, data, atoms); + + break; + } + case XCB_MAPPING_NOTIFY: break; - case MappingNotify: + case 0: + /* This is just laziness rather than making sure we used _checked everywhere */ + { + xcb_generic_error_t *err = (xcb_generic_error_t *)event; + ErrorF("winClipboardFlushXEvents - Error code: %i, ID: 0x%08x, " + "Major opcode: %i, Minor opcode: %i\n", + err->error_code, err->resource_id, + err->major_code, err->minor_code); + } break; default: - if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) { - XFixesSelectionNotifyEvent *e = - (XFixesSelectionNotifyEvent *) & event; - + if ((event->response_type & ~0x80) == XCB_XFIXES_SELECTION_EVENT_SET_SELECTION_OWNER + xfixes_event_base) { + xcb_xfixes_selection_notify_event_t *e = (xcb_xfixes_selection_notify_event_t *)event; winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n"); /* Save selection owners for monitored selections, ignore other selections */ - if ((e->selection == XA_PRIMARY) && fPrimarySelection) { + if ((e->selection == XCB_ATOM_PRIMARY) && fPrimarySelection) { MonitorSelection(e, CLIP_OWN_PRIMARY); } else if (e->selection == atomClipboard) { @@ -829,9 +757,8 @@ winClipboardFlushXEvents(HWND hwnd, break; /* Selection is being disowned */ - if (e->owner == None) { - winDebug - ("winClipboardFlushXEvents - No window, returning.\n"); + if (e->owner == XCB_NONE) { + winDebug("winClipboardFlushXEvents - No window, returning.\n"); break; } @@ -878,15 +805,25 @@ winClipboardFlushXEvents(HWND hwnd, break; } } - /* XFixesSelectionWindowDestroyNotifyMask */ - /* XFixesSelectionClientCloseNotifyMask */ + /* XCB_XFIXES_SELECTION_EVENT_SELECTION_WINDOW_DESTROY */ + /* XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE */ else { ErrorF("winClipboardFlushXEvents - unexpected event type %d\n", - event.type); + event->response_type); } break; } + + /* I/O errors etc. */ + { + int e = xcb_connection_has_error(conn); + if (e) { + ErrorF("winClipboardFlushXEvents - Fatal error %d on xcb connection\n", e); + break; + } + } } return WIN_XEVENTS_SUCCESS; + } diff --git a/hw/xwin/winclipboard/xwinclip.c b/hw/xwin/winclipboard/xwinclip.c index 6fd1c7598..4df8cd4af 100644 --- a/hw/xwin/winclipboard/xwinclip.c +++ b/hw/xwin/winclipboard/xwinclip.c @@ -35,27 +35,10 @@ #include <xwin-config.h> #endif -/* - * Including any server header might define the macro _XSERVER64 on 64 bit machines. - * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen. - * So let's undef that macro if necessary. - */ -#ifdef _XSERVER64 -#undef _XSERVER64 -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> -/* X headers */ -#include <X11/Xlib.h> -#ifdef X_LOCALE -#include <X11/Xlocale.h> -#else /* X_LOCALE */ -#include <locale.h> -#endif /* X_LOCALE */ - #include "winclipboard.h" /* @@ -87,7 +70,7 @@ main (int argc, char *argv[]) /* Look for -noprimary */ if (!strcmp (argv[i], "-noprimary")) { - fPrimarySelection = False; + fPrimarySelection = 0; continue; } @@ -96,21 +79,7 @@ main (int argc, char *argv[]) exit (1); } - /* Apply locale specified in the LANG environment variable */ - if (!setlocale (LC_ALL, "")) - { - printf ("setlocale() error\n"); - exit (1); - } - - /* See if X supports the current locale */ - if (XSupportsLocale () == False) - { - printf ("Locale not supported by X, falling back to 'C' locale.\n"); - setlocale(LC_ALL, "C"); - } - - winClipboardProc(pszDisplay); + winClipboardProc(pszDisplay, NULL /* Use XAUTHORITY for auth data */); return 0; } diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c index 3324661df..1e920f51f 100644 --- a/hw/xwin/winclipboardinit.c +++ b/hw/xwin/winclipboardinit.c @@ -42,6 +42,8 @@ #define WIN_CLIPBOARD_RETRIES 40 #define WIN_CLIPBOARD_DELAY 1 +extern xcb_auth_info_t *winGetXcbAuthInfo(void); + /* * Local variables */ @@ -55,6 +57,7 @@ static void * winClipboardThreadProc(void *arg) { char szDisplay[512]; + xcb_auth_info_t *auth_info; int clipboardRestarts = 0; while (1) @@ -82,7 +85,10 @@ winClipboardThreadProc(void *arg) /* Flag that clipboard client has been launched */ g_fClipboardStarted = TRUE; - fShutdown = winClipboardProc(szDisplay); + /* Use our generated cookie for authentication */ + auth_info = winGetXcbAuthInfo(); + + fShutdown = winClipboardProc(szDisplay, auth_info); /* Flag that clipboard client has stopped */ g_fClipboardStarted = FALSE; |