135c4bbdfSmrg/*
235c4bbdfSmrg *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
335c4bbdfSmrg *Copyright (C) Colin Harrison 2005-2008
435c4bbdfSmrg *
535c4bbdfSmrg *Permission is hereby granted, free of charge, to any person obtaining
635c4bbdfSmrg * a copy of this software and associated documentation files (the
735c4bbdfSmrg *"Software"), to deal in the Software without restriction, including
835c4bbdfSmrg *without limitation the rights to use, copy, modify, merge, publish,
935c4bbdfSmrg *distribute, sublicense, and/or sell copies of the Software, and to
1035c4bbdfSmrg *permit persons to whom the Software is furnished to do so, subject to
1135c4bbdfSmrg *the following conditions:
1235c4bbdfSmrg *
1335c4bbdfSmrg *The above copyright notice and this permission notice shall be
1435c4bbdfSmrg *included in all copies or substantial portions of the Software.
1535c4bbdfSmrg *
1635c4bbdfSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1735c4bbdfSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1835c4bbdfSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1935c4bbdfSmrg *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
2035c4bbdfSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2135c4bbdfSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2235c4bbdfSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2335c4bbdfSmrg *
2435c4bbdfSmrg *Except as contained in this notice, the name of the copyright holder(s)
2535c4bbdfSmrg *and author(s) shall not be used in advertising or otherwise to promote
2635c4bbdfSmrg *the sale, use or other dealings in this Software without prior written
2735c4bbdfSmrg *authorization from the copyright holder(s) and author(s).
2835c4bbdfSmrg *
2935c4bbdfSmrg * Authors:	Harold L Hunt II
3035c4bbdfSmrg *              Colin Harrison
3135c4bbdfSmrg */
3235c4bbdfSmrg
33ed6184dfSmrg#define WINVER 0x0600
34ed6184dfSmrg
3535c4bbdfSmrg#ifdef HAVE_XWIN_CONFIG_H
3635c4bbdfSmrg#include <xwin-config.h>
3735c4bbdfSmrg#endif
3835c4bbdfSmrg
3935c4bbdfSmrg#include <sys/types.h>
4035c4bbdfSmrg#include <sys/time.h>
4135c4bbdfSmrg#include <limits.h>
4235c4bbdfSmrg
43ed6184dfSmrg#include <xcb/xproto.h>
44ed6184dfSmrg#include <xcb/xcb_aux.h>
4535c4bbdfSmrg
4635c4bbdfSmrg#include "internal.h"
4735c4bbdfSmrg#include "winclipboard.h"
4835c4bbdfSmrg
4935c4bbdfSmrg/*
5035c4bbdfSmrg * Constants
5135c4bbdfSmrg */
5235c4bbdfSmrg
5335c4bbdfSmrg#define WIN_POLL_TIMEOUT	1
5435c4bbdfSmrg
5535c4bbdfSmrg/*
5635c4bbdfSmrg * Process X events up to specified timeout
5735c4bbdfSmrg */
5835c4bbdfSmrg
5935c4bbdfSmrgstatic int
60ed6184dfSmrgwinProcessXEventsTimeout(HWND hwnd, xcb_window_t iWindow, xcb_connection_t *conn,
6135c4bbdfSmrg                         ClipboardConversionData *data, ClipboardAtoms *atoms, int iTimeoutSec)
6235c4bbdfSmrg{
6335c4bbdfSmrg    int iConnNumber;
6435c4bbdfSmrg    struct timeval tv;
6535c4bbdfSmrg    int iReturn;
6635c4bbdfSmrg
67ed6184dfSmrg    winDebug("winProcessXEventsTimeout () - pumping X events, timeout %d seconds\n",
6835c4bbdfSmrg             iTimeoutSec);
6935c4bbdfSmrg
7035c4bbdfSmrg    /* Get our connection number */
71ed6184dfSmrg    iConnNumber = xcb_get_file_descriptor(conn);
7235c4bbdfSmrg
7335c4bbdfSmrg    /* Loop for X events */
7435c4bbdfSmrg    while (1) {
7535c4bbdfSmrg        fd_set fdsRead;
7635c4bbdfSmrg        long remainingTime;
7735c4bbdfSmrg
7835c4bbdfSmrg        /* Process X events */
79ed6184dfSmrg        iReturn = winClipboardFlushXEvents(hwnd, iWindow, conn, data, atoms);
8035c4bbdfSmrg
8135c4bbdfSmrg        winDebug("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", iReturn);
8235c4bbdfSmrg
8335c4bbdfSmrg        if ((WIN_XEVENTS_NOTIFY_DATA == iReturn) || (WIN_XEVENTS_NOTIFY_TARGETS == iReturn) || (WIN_XEVENTS_FAILED == iReturn)) {
8435c4bbdfSmrg          /* Bail out */
8535c4bbdfSmrg          return iReturn;
8635c4bbdfSmrg        }
8735c4bbdfSmrg
8835c4bbdfSmrg        /* We need to ensure that all pending requests are sent */
89ed6184dfSmrg        xcb_flush(conn);
9035c4bbdfSmrg
9135c4bbdfSmrg        /* Setup the file descriptor set */
9235c4bbdfSmrg        FD_ZERO(&fdsRead);
9335c4bbdfSmrg        FD_SET(iConnNumber, &fdsRead);
9435c4bbdfSmrg
9535c4bbdfSmrg        /* Adjust timeout */
96ed6184dfSmrg        remainingTime = iTimeoutSec * 1000;
9735c4bbdfSmrg        tv.tv_sec = remainingTime / 1000;
9835c4bbdfSmrg        tv.tv_usec = (remainingTime % 1000) * 1000;
9935c4bbdfSmrg
10035c4bbdfSmrg        /* Break out if no time left */
10135c4bbdfSmrg        if (remainingTime <= 0)
10235c4bbdfSmrg            return WIN_XEVENTS_SUCCESS;
10335c4bbdfSmrg
10435c4bbdfSmrg        /* Wait for an X event */
10535c4bbdfSmrg        iReturn = select(iConnNumber + 1,       /* Highest fds number */
10635c4bbdfSmrg                         &fdsRead,      /* Read mask */
10735c4bbdfSmrg                         NULL,  /* No write mask */
10835c4bbdfSmrg                         NULL,  /* No exception mask */
10935c4bbdfSmrg                         &tv);  /* Timeout */
11035c4bbdfSmrg        if (iReturn < 0) {
11135c4bbdfSmrg            ErrorF("winProcessXEventsTimeout - Call to select () failed: %d.  "
11235c4bbdfSmrg                   "Bailing.\n", iReturn);
11335c4bbdfSmrg            break;
11435c4bbdfSmrg        }
11535c4bbdfSmrg
11635c4bbdfSmrg        if (!FD_ISSET(iConnNumber, &fdsRead)) {
11735c4bbdfSmrg            winDebug("winProcessXEventsTimeout - Spurious wake, select() returned %d\n", iReturn);
11835c4bbdfSmrg        }
11935c4bbdfSmrg    }
12035c4bbdfSmrg
12135c4bbdfSmrg    return WIN_XEVENTS_SUCCESS;
12235c4bbdfSmrg}
12335c4bbdfSmrg
12435c4bbdfSmrg/*
12535c4bbdfSmrg * Process a given Windows message
12635c4bbdfSmrg */
12735c4bbdfSmrg
12835c4bbdfSmrgLRESULT CALLBACK
12935c4bbdfSmrgwinClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
13035c4bbdfSmrg{
131ed6184dfSmrg    static xcb_connection_t *conn;
132ed6184dfSmrg    static xcb_window_t iWindow;
13335c4bbdfSmrg    static ClipboardAtoms *atoms;
134ed6184dfSmrg    static BOOL fRunning;
13535c4bbdfSmrg
13635c4bbdfSmrg    /* Branch on message type */
13735c4bbdfSmrg    switch (message) {
13835c4bbdfSmrg    case WM_DESTROY:
13935c4bbdfSmrg    {
14035c4bbdfSmrg        winDebug("winClipboardWindowProc - WM_DESTROY\n");
14135c4bbdfSmrg
142ed6184dfSmrg        /* Remove clipboard listener */
143ed6184dfSmrg        RemoveClipboardFormatListener(hwnd);
14435c4bbdfSmrg    }
14535c4bbdfSmrg        return 0;
14635c4bbdfSmrg
14735c4bbdfSmrg    case WM_WM_QUIT:
14835c4bbdfSmrg    {
14935c4bbdfSmrg        winDebug("winClipboardWindowProc - WM_WM_QUIT\n");
15035c4bbdfSmrg        fRunning = FALSE;
15135c4bbdfSmrg        PostQuitMessage(0);
15235c4bbdfSmrg    }
15335c4bbdfSmrg        return 0;
15435c4bbdfSmrg
15535c4bbdfSmrg    case WM_CREATE:
15635c4bbdfSmrg    {
15735c4bbdfSmrg        ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
15835c4bbdfSmrg
15935c4bbdfSmrg        winDebug("winClipboardWindowProc - WM_CREATE\n");
16035c4bbdfSmrg
161ed6184dfSmrg        conn = cwcp->pClipboardDisplay;
16235c4bbdfSmrg        iWindow = cwcp->iClipboardWindow;
16335c4bbdfSmrg        atoms = cwcp->atoms;
16435c4bbdfSmrg        fRunning = TRUE;
16535c4bbdfSmrg
166ed6184dfSmrg        AddClipboardFormatListener(hwnd);
16735c4bbdfSmrg    }
16835c4bbdfSmrg        return 0;
16935c4bbdfSmrg
17035c4bbdfSmrg    case WM_CLIPBOARDUPDATE:
17135c4bbdfSmrg    {
172ed6184dfSmrg        xcb_generic_error_t *error;
173ed6184dfSmrg        xcb_void_cookie_t cookie_set;
17435c4bbdfSmrg
175ed6184dfSmrg        winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Enter\n");
17635c4bbdfSmrg
17735c4bbdfSmrg        /*
17835c4bbdfSmrg         * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
17935c4bbdfSmrg         * because some applications deal with the clipboard in a manner
18035c4bbdfSmrg         * that causes the clipboard owner to be NULL when they are in
18135c4bbdfSmrg         * fact taking ownership.  One example of this is the Win32
18235c4bbdfSmrg         * native compile of emacs.
18335c4bbdfSmrg         */
18435c4bbdfSmrg
18535c4bbdfSmrg        /* Bail when we still own the clipboard */
18635c4bbdfSmrg        if (hwnd == GetClipboardOwner()) {
18735c4bbdfSmrg
188ed6184dfSmrg            winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
18935c4bbdfSmrg                     "We own the clipboard, returning.\n");
190ed6184dfSmrg            winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
191ed6184dfSmrg
19235c4bbdfSmrg            return 0;
19335c4bbdfSmrg        }
19435c4bbdfSmrg
19535c4bbdfSmrg        /* Bail when shutting down */
19635c4bbdfSmrg        if (!fRunning)
19735c4bbdfSmrg            return 0;
19835c4bbdfSmrg
19935c4bbdfSmrg        /*
20035c4bbdfSmrg         * Do not take ownership of the X11 selections when something
20135c4bbdfSmrg         * other than CF_TEXT or CF_UNICODETEXT has been copied
20235c4bbdfSmrg         * into the Win32 clipboard.
20335c4bbdfSmrg         */
20435c4bbdfSmrg        if (!IsClipboardFormatAvailable(CF_TEXT)
20535c4bbdfSmrg            && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
20635c4bbdfSmrg
207ed6184dfSmrg            xcb_get_selection_owner_cookie_t cookie_get;
208ed6184dfSmrg            xcb_get_selection_owner_reply_t *reply;
209ed6184dfSmrg
210ed6184dfSmrg            winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
21135c4bbdfSmrg                     "Clipboard does not contain CF_TEXT nor "
21235c4bbdfSmrg                     "CF_UNICODETEXT.\n");
21335c4bbdfSmrg
21435c4bbdfSmrg            /*
21535c4bbdfSmrg             * We need to make sure that the X Server has processed
21635c4bbdfSmrg             * previous XSetSelectionOwner messages.
21735c4bbdfSmrg             */
218ed6184dfSmrg            xcb_aux_sync(conn);
21935c4bbdfSmrg
22035c4bbdfSmrg            winDebug("winClipboardWindowProc - XSync done.\n");
22135c4bbdfSmrg
22235c4bbdfSmrg            /* Release PRIMARY selection if owned */
223ed6184dfSmrg            cookie_get = xcb_get_selection_owner(conn, XCB_ATOM_PRIMARY);
224ed6184dfSmrg            reply = xcb_get_selection_owner_reply(conn, cookie_get, NULL);
225ed6184dfSmrg            if (reply) {
226ed6184dfSmrg                if (reply->owner == iWindow) {
227ed6184dfSmrg                    winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
228ed6184dfSmrg                             "PRIMARY selection is owned by us, releasing.\n");
229ed6184dfSmrg                    xcb_set_selection_owner(conn, XCB_NONE, XCB_ATOM_PRIMARY, XCB_CURRENT_TIME);
230ed6184dfSmrg                }
231ed6184dfSmrg                free(reply);
23235c4bbdfSmrg            }
23335c4bbdfSmrg
23435c4bbdfSmrg            /* Release CLIPBOARD selection if owned */
235ed6184dfSmrg            cookie_get = xcb_get_selection_owner(conn, atoms->atomClipboard);
236ed6184dfSmrg            reply = xcb_get_selection_owner_reply(conn, cookie_get, NULL);
237ed6184dfSmrg            if (reply) {
238ed6184dfSmrg                if (reply->owner == iWindow) {
239ed6184dfSmrg                    winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
240ed6184dfSmrg                             "CLIPBOARD selection is owned by us, releasing\n");
241ed6184dfSmrg                    xcb_set_selection_owner(conn, XCB_NONE, atoms->atomClipboard, XCB_CURRENT_TIME);
242ed6184dfSmrg                }
243ed6184dfSmrg                free(reply);
24435c4bbdfSmrg            }
245ed6184dfSmrg
246ed6184dfSmrg            winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
247ed6184dfSmrg
24835c4bbdfSmrg            return 0;
24935c4bbdfSmrg        }
25035c4bbdfSmrg
25135c4bbdfSmrg        /* Reassert ownership of PRIMARY */
252ed6184dfSmrg        cookie_set = xcb_set_selection_owner_checked(conn, iWindow, XCB_ATOM_PRIMARY, XCB_CURRENT_TIME);
253ed6184dfSmrg        error = xcb_request_check(conn, cookie_set);
254ed6184dfSmrg        if (error) {
255ed6184dfSmrg            ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
25635c4bbdfSmrg                   "Could not reassert ownership of PRIMARY\n");
257ed6184dfSmrg            free(error);
258ed6184dfSmrg        } else {
259ed6184dfSmrg            winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
26035c4bbdfSmrg                     "Reasserted ownership of PRIMARY\n");
26135c4bbdfSmrg        }
26235c4bbdfSmrg
26335c4bbdfSmrg        /* Reassert ownership of the CLIPBOARD */
264ed6184dfSmrg        cookie_set = xcb_set_selection_owner_checked(conn, iWindow, atoms->atomClipboard, XCB_CURRENT_TIME);
265ed6184dfSmrg        error = xcb_request_check(conn, cookie_set);
266ed6184dfSmrg        if (error) {
267ed6184dfSmrg            ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
26835c4bbdfSmrg                    "Could not reassert ownership of CLIPBOARD\n");
269ed6184dfSmrg            free(error);
27035c4bbdfSmrg        }
27135c4bbdfSmrg        else {
272ed6184dfSmrg            winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
27335c4bbdfSmrg                     "Reasserted ownership of CLIPBOARD\n");
27435c4bbdfSmrg        }
27535c4bbdfSmrg
27635c4bbdfSmrg        /* Flush the pending SetSelectionOwner event now */
277ed6184dfSmrg        xcb_flush(conn);
27835c4bbdfSmrg    }
279ed6184dfSmrg        winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
28035c4bbdfSmrg        return 0;
28135c4bbdfSmrg
28235c4bbdfSmrg    case WM_DESTROYCLIPBOARD:
28335c4bbdfSmrg        /*
28435c4bbdfSmrg         * NOTE: Intentionally do nothing.
285ed6184dfSmrg         * Changes in the Win32 clipboard are handled by WM_CLIPBOARDUPDATE
28635c4bbdfSmrg         * above.  We only process this message to conform to the specs
28735c4bbdfSmrg         * for delayed clipboard rendering in Win32.  You might think
28835c4bbdfSmrg         * that we need to release ownership of the X11 selections, but
289ed6184dfSmrg         * we do not, because a WM_CLIPBOARDUPDATE message will closely
29035c4bbdfSmrg         * follow this message and reassert ownership of the X11
29135c4bbdfSmrg         * selections, handling the issue for us.
29235c4bbdfSmrg         */
29335c4bbdfSmrg        winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
29435c4bbdfSmrg        return 0;
29535c4bbdfSmrg
29635c4bbdfSmrg    case WM_RENDERALLFORMATS:
29735c4bbdfSmrg        winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n");
29835c4bbdfSmrg
29935c4bbdfSmrg        /*
30035c4bbdfSmrg          WM_RENDERALLFORMATS is sent as we are shutting down, to render the
301ed6184dfSmrg          clipboard so its contents remains available to other applications.
30235c4bbdfSmrg
30335c4bbdfSmrg          Unfortunately, this can't work without major changes. The server is
30435c4bbdfSmrg          already waiting for us to stop, so we can't ask for the rendering of
30535c4bbdfSmrg          clipboard text now.
30635c4bbdfSmrg        */
30735c4bbdfSmrg
30835c4bbdfSmrg        return 0;
30935c4bbdfSmrg
31035c4bbdfSmrg    case WM_RENDERFORMAT:
31135c4bbdfSmrg    {
31235c4bbdfSmrg        int iReturn;
313ed6184dfSmrg        BOOL pasted = FALSE;
314ed6184dfSmrg        xcb_atom_t selection;
31535c4bbdfSmrg        ClipboardConversionData data;
31635c4bbdfSmrg        int best_target = 0;
31735c4bbdfSmrg
31835c4bbdfSmrg        winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n",
31935c4bbdfSmrg                 (int)wParam);
32035c4bbdfSmrg
32135c4bbdfSmrg        selection = winClipboardGetLastOwnedSelectionAtom(atoms);
322ed6184dfSmrg        if (selection == XCB_NONE) {
32335c4bbdfSmrg            ErrorF("winClipboardWindowProc - no monitored selection is owned\n");
32435c4bbdfSmrg            goto fake_paste;
32535c4bbdfSmrg        }
32635c4bbdfSmrg
32735c4bbdfSmrg        winDebug("winClipboardWindowProc - requesting targets for selection from owner\n");
32835c4bbdfSmrg
32935c4bbdfSmrg        /* Request the selection's supported conversion targets */
330ed6184dfSmrg        xcb_convert_selection(conn, iWindow, selection, atoms->atomTargets,
331ed6184dfSmrg                              atoms->atomLocalProperty, XCB_CURRENT_TIME);
33235c4bbdfSmrg
33335c4bbdfSmrg        /* Process X events */
334ed6184dfSmrg        data.incr = NULL;
335ed6184dfSmrg        data.incrsize = 0;
336ed6184dfSmrg
33735c4bbdfSmrg        iReturn = winProcessXEventsTimeout(hwnd,
33835c4bbdfSmrg                                           iWindow,
339ed6184dfSmrg                                           conn,
34035c4bbdfSmrg                                           &data,
34135c4bbdfSmrg                                           atoms,
34235c4bbdfSmrg                                           WIN_POLL_TIMEOUT);
34335c4bbdfSmrg
34435c4bbdfSmrg        if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) {
34535c4bbdfSmrg            ErrorF
34635c4bbdfSmrg                ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n");
34735c4bbdfSmrg            goto fake_paste;
34835c4bbdfSmrg        }
34935c4bbdfSmrg
35035c4bbdfSmrg        /* Choose the most preferred target */
35135c4bbdfSmrg        {
35235c4bbdfSmrg            struct target_priority
35335c4bbdfSmrg            {
354ed6184dfSmrg                xcb_atom_t target;
35535c4bbdfSmrg                unsigned int priority;
35635c4bbdfSmrg            };
35735c4bbdfSmrg
35835c4bbdfSmrg            struct target_priority target_priority_table[] =
35935c4bbdfSmrg                {
360ed6184dfSmrg                    { atoms->atomUTF8String,   0 },
361ed6184dfSmrg                    // { atoms->atomCompoundText, 1 }, not implemented (yet?)
362ed6184dfSmrg                    { XCB_ATOM_STRING,         2 },
36335c4bbdfSmrg                };
36435c4bbdfSmrg
36535c4bbdfSmrg            int best_priority = INT_MAX;
36635c4bbdfSmrg
36735c4bbdfSmrg            int i,j;
36835c4bbdfSmrg            for (i = 0 ; data.targetList[i] != 0; i++)
36935c4bbdfSmrg                {
3701b5d61b8Smrg                    for (j = 0; j < ARRAY_SIZE(target_priority_table); j ++)
37135c4bbdfSmrg                        {
37235c4bbdfSmrg                            if ((data.targetList[i] == target_priority_table[j].target) &&
37335c4bbdfSmrg                                (target_priority_table[j].priority < best_priority))
37435c4bbdfSmrg                                {
37535c4bbdfSmrg                                    best_target = target_priority_table[j].target;
37635c4bbdfSmrg                                    best_priority = target_priority_table[j].priority;
37735c4bbdfSmrg                                }
37835c4bbdfSmrg                        }
37935c4bbdfSmrg                }
38035c4bbdfSmrg        }
38135c4bbdfSmrg
38235c4bbdfSmrg        free(data.targetList);
38335c4bbdfSmrg        data.targetList = 0;
38435c4bbdfSmrg
38535c4bbdfSmrg        winDebug("winClipboardWindowProc - best target is %d\n", best_target);
38635c4bbdfSmrg
38735c4bbdfSmrg        /* No useful targets found */
38835c4bbdfSmrg        if (best_target == 0)
38935c4bbdfSmrg          goto fake_paste;
39035c4bbdfSmrg
39135c4bbdfSmrg        winDebug("winClipboardWindowProc - requesting selection from owner\n");
39235c4bbdfSmrg
39335c4bbdfSmrg        /* Request the selection contents */
394ed6184dfSmrg        xcb_convert_selection(conn, iWindow, selection, best_target,
395ed6184dfSmrg                              atoms->atomLocalProperty, XCB_CURRENT_TIME);
39635c4bbdfSmrg
39735c4bbdfSmrg        /* Process X events */
39835c4bbdfSmrg        iReturn = winProcessXEventsTimeout(hwnd,
39935c4bbdfSmrg                                           iWindow,
400ed6184dfSmrg                                           conn,
40135c4bbdfSmrg                                           &data,
40235c4bbdfSmrg                                           atoms,
40335c4bbdfSmrg                                           WIN_POLL_TIMEOUT);
40435c4bbdfSmrg
40535c4bbdfSmrg        /*
40635c4bbdfSmrg         * winProcessXEventsTimeout had better have seen a notify event,
40735c4bbdfSmrg         * or else we are dealing with a buggy or old X11 app.
40835c4bbdfSmrg         */
40935c4bbdfSmrg        if (WIN_XEVENTS_NOTIFY_DATA != iReturn) {
41035c4bbdfSmrg            ErrorF
41135c4bbdfSmrg                ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n");
41235c4bbdfSmrg        }
41335c4bbdfSmrg        else {
41435c4bbdfSmrg            pasted = TRUE;
41535c4bbdfSmrg        }
41635c4bbdfSmrg
41735c4bbdfSmrg         /*
41835c4bbdfSmrg          * If we couldn't get the data from the X clipboard, we
41935c4bbdfSmrg          * have to paste some fake data to the Win32 clipboard to
42035c4bbdfSmrg          * satisfy the requirement that we write something to it.
42135c4bbdfSmrg          */
42235c4bbdfSmrg    fake_paste:
42335c4bbdfSmrg        if (!pasted)
42435c4bbdfSmrg          {
42535c4bbdfSmrg            /* Paste no data, to satisfy required call to SetClipboardData */
42635c4bbdfSmrg            SetClipboardData(CF_UNICODETEXT, NULL);
42735c4bbdfSmrg            SetClipboardData(CF_TEXT, NULL);
42835c4bbdfSmrg          }
42935c4bbdfSmrg
43035c4bbdfSmrg        winDebug("winClipboardWindowProc - WM_RENDERFORMAT - Returning.\n");
43135c4bbdfSmrg        return 0;
43235c4bbdfSmrg    }
43335c4bbdfSmrg    }
43435c4bbdfSmrg
43535c4bbdfSmrg    /* Let Windows perform default processing for unhandled messages */
43635c4bbdfSmrg    return DefWindowProc(hwnd, message, wParam, lParam);
43735c4bbdfSmrg}
43835c4bbdfSmrg
43935c4bbdfSmrg/*
44035c4bbdfSmrg * Process any pending Windows messages
44135c4bbdfSmrg */
44235c4bbdfSmrg
443ed6184dfSmrgBOOL
44435c4bbdfSmrgwinClipboardFlushWindowsMessageQueue(HWND hwnd)
44535c4bbdfSmrg{
44635c4bbdfSmrg    MSG msg;
44735c4bbdfSmrg
44835c4bbdfSmrg    /* Flush the messaging window queue */
44935c4bbdfSmrg    /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage,
45035c4bbdfSmrg     * as this will filter out many non-window-specific messages that
45135c4bbdfSmrg     * are sent to our thread, such as WM_QUIT.
45235c4bbdfSmrg     */
45335c4bbdfSmrg    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
45435c4bbdfSmrg        /* Dispatch the message if not WM_QUIT */
45535c4bbdfSmrg        if (msg.message == WM_QUIT)
45635c4bbdfSmrg            return FALSE;
45735c4bbdfSmrg        else
45835c4bbdfSmrg            DispatchMessage(&msg);
45935c4bbdfSmrg    }
46035c4bbdfSmrg
46135c4bbdfSmrg    return TRUE;
46235c4bbdfSmrg}
463