xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

wndproc.c (15778B)


      1 /*
      2  *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
      3  *Copyright (C) Colin Harrison 2005-2008
      4  *
      5  *Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  *"Software"), to deal in the Software without restriction, including
      8  *without limitation the rights to use, copy, modify, merge, publish,
      9  *distribute, sublicense, and/or sell copies of the Software, and to
     10  *permit persons to whom the Software is furnished to do so, subject to
     11  *the following conditions:
     12  *
     13  *The above copyright notice and this permission notice shall be
     14  *included in all copies or substantial portions of the Software.
     15  *
     16  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
     20  *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
     21  *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     22  *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  *Except as contained in this notice, the name of the copyright holder(s)
     25  *and author(s) shall not be used in advertising or otherwise to promote
     26  *the sale, use or other dealings in this Software without prior written
     27  *authorization from the copyright holder(s) and author(s).
     28  *
     29  * Authors:	Harold L Hunt II
     30  *              Colin Harrison
     31  */
     32 
     33 #define WINVER 0x0600
     34 
     35 #ifdef HAVE_XWIN_CONFIG_H
     36 #include <xwin-config.h>
     37 #endif
     38 
     39 #include <sys/types.h>
     40 #include <sys/time.h>
     41 #include <limits.h>
     42 
     43 #include <xcb/xproto.h>
     44 #include <xcb/xcb_aux.h>
     45 
     46 #include "internal.h"
     47 #include "winclipboard.h"
     48 
     49 /*
     50  * Constants
     51  */
     52 
     53 #define WIN_POLL_TIMEOUT	1
     54 
     55 /*
     56  * Process X events up to specified timeout
     57  */
     58 
     59 static int
     60 winProcessXEventsTimeout(HWND hwnd, xcb_window_t iWindow, xcb_connection_t *conn,
     61                          ClipboardConversionData *data, ClipboardAtoms *atoms, int iTimeoutSec)
     62 {
     63     int iConnNumber;
     64     struct timeval tv;
     65     int iReturn;
     66 
     67     winDebug("winProcessXEventsTimeout () - pumping X events, timeout %d seconds\n",
     68              iTimeoutSec);
     69 
     70     /* Get our connection number */
     71     iConnNumber = xcb_get_file_descriptor(conn);
     72 
     73     /* Loop for X events */
     74     while (1) {
     75         fd_set fdsRead;
     76         long remainingTime;
     77 
     78         /* Process X events */
     79         iReturn = winClipboardFlushXEvents(hwnd, iWindow, conn, data, atoms);
     80 
     81         winDebug("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n", iReturn);
     82 
     83         if ((WIN_XEVENTS_NOTIFY_DATA == iReturn) || (WIN_XEVENTS_NOTIFY_TARGETS == iReturn) || (WIN_XEVENTS_FAILED == iReturn)) {
     84           /* Bail out */
     85           return iReturn;
     86         }
     87 
     88         /* We need to ensure that all pending requests are sent */
     89         xcb_flush(conn);
     90 
     91         /* Setup the file descriptor set */
     92         FD_ZERO(&fdsRead);
     93         FD_SET(iConnNumber, &fdsRead);
     94 
     95         /* Adjust timeout */
     96         remainingTime = iTimeoutSec * 1000;
     97         tv.tv_sec = remainingTime / 1000;
     98         tv.tv_usec = (remainingTime % 1000) * 1000;
     99 
    100         /* Break out if no time left */
    101         if (remainingTime <= 0)
    102             return WIN_XEVENTS_SUCCESS;
    103 
    104         /* Wait for an X event */
    105         iReturn = select(iConnNumber + 1,       /* Highest fds number */
    106                          &fdsRead,      /* Read mask */
    107                          NULL,  /* No write mask */
    108                          NULL,  /* No exception mask */
    109                          &tv);  /* Timeout */
    110         if (iReturn < 0) {
    111             ErrorF("winProcessXEventsTimeout - Call to select () failed: %d.  "
    112                    "Bailing.\n", iReturn);
    113             break;
    114         }
    115 
    116         if (!FD_ISSET(iConnNumber, &fdsRead)) {
    117             winDebug("winProcessXEventsTimeout - Spurious wake, select() returned %d\n", iReturn);
    118         }
    119     }
    120 
    121     return WIN_XEVENTS_SUCCESS;
    122 }
    123 
    124 /*
    125  * Process a given Windows message
    126  */
    127 
    128 LRESULT CALLBACK
    129 winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    130 {
    131     static xcb_connection_t *conn;
    132     static xcb_window_t iWindow;
    133     static ClipboardAtoms *atoms;
    134     static BOOL fRunning;
    135 
    136     /* Branch on message type */
    137     switch (message) {
    138     case WM_DESTROY:
    139     {
    140         winDebug("winClipboardWindowProc - WM_DESTROY\n");
    141 
    142         /* Remove clipboard listener */
    143         RemoveClipboardFormatListener(hwnd);
    144     }
    145         return 0;
    146 
    147     case WM_WM_QUIT:
    148     {
    149         winDebug("winClipboardWindowProc - WM_WM_QUIT\n");
    150         fRunning = FALSE;
    151         PostQuitMessage(0);
    152     }
    153         return 0;
    154 
    155     case WM_CREATE:
    156     {
    157         ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
    158 
    159         winDebug("winClipboardWindowProc - WM_CREATE\n");
    160 
    161         conn = cwcp->pClipboardDisplay;
    162         iWindow = cwcp->iClipboardWindow;
    163         atoms = cwcp->atoms;
    164         fRunning = TRUE;
    165 
    166         AddClipboardFormatListener(hwnd);
    167     }
    168         return 0;
    169 
    170     case WM_CLIPBOARDUPDATE:
    171     {
    172         xcb_generic_error_t *error;
    173         xcb_void_cookie_t cookie_set;
    174 
    175         winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Enter\n");
    176 
    177         /*
    178          * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
    179          * because some applications deal with the clipboard in a manner
    180          * that causes the clipboard owner to be NULL when they are in
    181          * fact taking ownership.  One example of this is the Win32
    182          * native compile of emacs.
    183          */
    184 
    185         /* Bail when we still own the clipboard */
    186         if (hwnd == GetClipboardOwner()) {
    187 
    188             winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    189                      "We own the clipboard, returning.\n");
    190             winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
    191 
    192             return 0;
    193         }
    194 
    195         /* Bail when shutting down */
    196         if (!fRunning)
    197             return 0;
    198 
    199         /*
    200          * Do not take ownership of the X11 selections when something
    201          * other than CF_TEXT or CF_UNICODETEXT has been copied
    202          * into the Win32 clipboard.
    203          */
    204         if (!IsClipboardFormatAvailable(CF_TEXT)
    205             && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
    206 
    207             xcb_get_selection_owner_cookie_t cookie_get;
    208             xcb_get_selection_owner_reply_t *reply;
    209 
    210             winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    211                      "Clipboard does not contain CF_TEXT nor "
    212                      "CF_UNICODETEXT.\n");
    213 
    214             /*
    215              * We need to make sure that the X Server has processed
    216              * previous XSetSelectionOwner messages.
    217              */
    218             xcb_aux_sync(conn);
    219 
    220             winDebug("winClipboardWindowProc - XSync done.\n");
    221 
    222             /* Release PRIMARY selection if owned */
    223             cookie_get = xcb_get_selection_owner(conn, XCB_ATOM_PRIMARY);
    224             reply = xcb_get_selection_owner_reply(conn, cookie_get, NULL);
    225             if (reply) {
    226                 if (reply->owner == iWindow) {
    227                     winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    228                              "PRIMARY selection is owned by us, releasing.\n");
    229                     xcb_set_selection_owner(conn, XCB_NONE, XCB_ATOM_PRIMARY, XCB_CURRENT_TIME);
    230                 }
    231                 free(reply);
    232             }
    233 
    234             /* Release CLIPBOARD selection if owned */
    235             cookie_get = xcb_get_selection_owner(conn, atoms->atomClipboard);
    236             reply = xcb_get_selection_owner_reply(conn, cookie_get, NULL);
    237             if (reply) {
    238                 if (reply->owner == iWindow) {
    239                     winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    240                              "CLIPBOARD selection is owned by us, releasing\n");
    241                     xcb_set_selection_owner(conn, XCB_NONE, atoms->atomClipboard, XCB_CURRENT_TIME);
    242                 }
    243                 free(reply);
    244             }
    245 
    246             winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
    247 
    248             return 0;
    249         }
    250 
    251         /* Reassert ownership of PRIMARY */
    252         cookie_set = xcb_set_selection_owner_checked(conn, iWindow, XCB_ATOM_PRIMARY, XCB_CURRENT_TIME);
    253         error = xcb_request_check(conn, cookie_set);
    254         if (error) {
    255             ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    256                    "Could not reassert ownership of PRIMARY\n");
    257             free(error);
    258         } else {
    259             winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    260                      "Reasserted ownership of PRIMARY\n");
    261         }
    262 
    263         /* Reassert ownership of the CLIPBOARD */
    264         cookie_set = xcb_set_selection_owner_checked(conn, iWindow, atoms->atomClipboard, XCB_CURRENT_TIME);
    265         error = xcb_request_check(conn, cookie_set);
    266         if (error) {
    267             ErrorF("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    268                     "Could not reassert ownership of CLIPBOARD\n");
    269             free(error);
    270         }
    271         else {
    272             winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE - "
    273                      "Reasserted ownership of CLIPBOARD\n");
    274         }
    275 
    276         /* Flush the pending SetSelectionOwner event now */
    277         xcb_flush(conn);
    278     }
    279         winDebug("winClipboardWindowProc - WM_CLIPBOARDUPDATE: Exit\n");
    280         return 0;
    281 
    282     case WM_DESTROYCLIPBOARD:
    283         /*
    284          * NOTE: Intentionally do nothing.
    285          * Changes in the Win32 clipboard are handled by WM_CLIPBOARDUPDATE
    286          * above.  We only process this message to conform to the specs
    287          * for delayed clipboard rendering in Win32.  You might think
    288          * that we need to release ownership of the X11 selections, but
    289          * we do not, because a WM_CLIPBOARDUPDATE message will closely
    290          * follow this message and reassert ownership of the X11
    291          * selections, handling the issue for us.
    292          */
    293         winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
    294         return 0;
    295 
    296     case WM_RENDERALLFORMATS:
    297         winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n");
    298 
    299         /*
    300           WM_RENDERALLFORMATS is sent as we are shutting down, to render the
    301           clipboard so its contents remains available to other applications.
    302 
    303           Unfortunately, this can't work without major changes. The server is
    304           already waiting for us to stop, so we can't ask for the rendering of
    305           clipboard text now.
    306         */
    307 
    308         return 0;
    309 
    310     case WM_RENDERFORMAT:
    311     {
    312         int iReturn;
    313         BOOL pasted = FALSE;
    314         xcb_atom_t selection;
    315         ClipboardConversionData data;
    316         int best_target = 0;
    317 
    318         winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n",
    319                  (int)wParam);
    320 
    321         selection = winClipboardGetLastOwnedSelectionAtom(atoms);
    322         if (selection == XCB_NONE) {
    323             ErrorF("winClipboardWindowProc - no monitored selection is owned\n");
    324             goto fake_paste;
    325         }
    326 
    327         winDebug("winClipboardWindowProc - requesting targets for selection from owner\n");
    328 
    329         /* Request the selection's supported conversion targets */
    330         xcb_convert_selection(conn, iWindow, selection, atoms->atomTargets,
    331                               atoms->atomLocalProperty, XCB_CURRENT_TIME);
    332 
    333         /* Process X events */
    334         data.incr = NULL;
    335         data.incrsize = 0;
    336 
    337         iReturn = winProcessXEventsTimeout(hwnd,
    338                                            iWindow,
    339                                            conn,
    340                                            &data,
    341                                            atoms,
    342                                            WIN_POLL_TIMEOUT);
    343 
    344         if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) {
    345             ErrorF
    346                 ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n");
    347             goto fake_paste;
    348         }
    349 
    350         /* Choose the most preferred target */
    351         {
    352             struct target_priority
    353             {
    354                 xcb_atom_t target;
    355                 unsigned int priority;
    356             };
    357 
    358             struct target_priority target_priority_table[] =
    359                 {
    360                     { atoms->atomUTF8String,   0 },
    361                     // { atoms->atomCompoundText, 1 }, not implemented (yet?)
    362                     { XCB_ATOM_STRING,         2 },
    363                 };
    364 
    365             int best_priority = INT_MAX;
    366 
    367             int i,j;
    368             for (i = 0 ; data.targetList[i] != 0; i++)
    369                 {
    370                     for (j = 0; j < ARRAY_SIZE(target_priority_table); j ++)
    371                         {
    372                             if ((data.targetList[i] == target_priority_table[j].target) &&
    373                                 (target_priority_table[j].priority < best_priority))
    374                                 {
    375                                     best_target = target_priority_table[j].target;
    376                                     best_priority = target_priority_table[j].priority;
    377                                 }
    378                         }
    379                 }
    380         }
    381 
    382         free(data.targetList);
    383         data.targetList = 0;
    384 
    385         winDebug("winClipboardWindowProc - best target is %d\n", best_target);
    386 
    387         /* No useful targets found */
    388         if (best_target == 0)
    389           goto fake_paste;
    390 
    391         winDebug("winClipboardWindowProc - requesting selection from owner\n");
    392 
    393         /* Request the selection contents */
    394         xcb_convert_selection(conn, iWindow, selection, best_target,
    395                               atoms->atomLocalProperty, XCB_CURRENT_TIME);
    396 
    397         /* Process X events */
    398         iReturn = winProcessXEventsTimeout(hwnd,
    399                                            iWindow,
    400                                            conn,
    401                                            &data,
    402                                            atoms,
    403                                            WIN_POLL_TIMEOUT);
    404 
    405         /*
    406          * winProcessXEventsTimeout had better have seen a notify event,
    407          * or else we are dealing with a buggy or old X11 app.
    408          */
    409         if (WIN_XEVENTS_NOTIFY_DATA != iReturn) {
    410             ErrorF
    411                 ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n");
    412         }
    413         else {
    414             pasted = TRUE;
    415         }
    416 
    417          /*
    418           * If we couldn't get the data from the X clipboard, we
    419           * have to paste some fake data to the Win32 clipboard to
    420           * satisfy the requirement that we write something to it.
    421           */
    422     fake_paste:
    423         if (!pasted)
    424           {
    425             /* Paste no data, to satisfy required call to SetClipboardData */
    426             SetClipboardData(CF_UNICODETEXT, NULL);
    427             SetClipboardData(CF_TEXT, NULL);
    428           }
    429 
    430         winDebug("winClipboardWindowProc - WM_RENDERFORMAT - Returning.\n");
    431         return 0;
    432     }
    433     }
    434 
    435     /* Let Windows perform default processing for unhandled messages */
    436     return DefWindowProc(hwnd, message, wParam, lParam);
    437 }
    438 
    439 /*
    440  * Process any pending Windows messages
    441  */
    442 
    443 BOOL
    444 winClipboardFlushWindowsMessageQueue(HWND hwnd)
    445 {
    446     MSG msg;
    447 
    448     /* Flush the messaging window queue */
    449     /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage,
    450      * as this will filter out many non-window-specific messages that
    451      * are sent to our thread, such as WM_QUIT.
    452      */
    453     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
    454         /* Dispatch the message if not WM_QUIT */
    455         if (msg.message == WM_QUIT)
    456             return FALSE;
    457         else
    458             DispatchMessage(&msg);
    459     }
    460 
    461     return TRUE;
    462 }