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