~brandontschaefer/+junk/break-x

« back to all changes in this revision

Viewing changes to hw/xwin/winclipboardwrappers.c

  • Committer: Brandon Schaefer
  • Date: 2014-09-30 19:38:40 UTC
  • Revision ID: brandon.schaefer@canonical.com-20140930193840-a65z6qk8ze02cgsb
* Init commit to back this up

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#ifdef HAVE_XWIN_CONFIG_H
 
34
#include <xwin-config.h>
 
35
#endif
 
36
#include "win.h"
 
37
#include "dixstruct.h"
 
38
#include <X11/Xatom.h>
 
39
 
 
40
/*
 
41
 * Constants
 
42
 */
 
43
 
 
44
#define CLIP_NUM_SELECTIONS             2
 
45
#define CLIP_OWN_PRIMARY                0
 
46
#define CLIP_OWN_CLIPBOARD              1
 
47
 
 
48
/*
 
49
 * Local function prototypes
 
50
 */
 
51
 
 
52
DISPATCH_PROC(winProcEstablishConnection);
 
53
DISPATCH_PROC(winProcSetSelectionOwner);
 
54
 
 
55
/*
 
56
 * References to external symbols
 
57
 */
 
58
 
 
59
extern Bool g_fClipboardLaunched;
 
60
extern Bool g_fClipboardStarted;
 
61
extern Bool g_fClipboard;
 
62
extern Window g_iClipboardWindow;
 
63
extern Atom g_atomLastOwnedSelection;
 
64
extern HWND g_hwndClipboard;
 
65
 
 
66
 
 
67
/*
 
68
 * Wrapper for internal EstablishConnection function.
 
69
 * Initializes internal clients that must not be started until
 
70
 * an external client has connected.
 
71
 */
 
72
 
 
73
int
 
74
winProcEstablishConnection(ClientPtr client)
 
75
{
 
76
    int iReturn;
 
77
    static int s_iCallCount = 0;
 
78
    static unsigned long s_ulServerGeneration = 0;
 
79
 
 
80
    if (s_iCallCount == 0)
 
81
        winDebug("winProcEstablishConnection - Hello\n");
 
82
 
 
83
    /* Do nothing if clipboard is not enabled */
 
84
    if (!g_fClipboard) {
 
85
        ErrorF("winProcEstablishConnection - Clipboard is not enabled, "
 
86
               "returning.\n");
 
87
 
 
88
        /* Unwrap the original function, call it, and return */
 
89
        InitialVector[2] = winProcEstablishConnectionOrig;
 
90
        iReturn = (*winProcEstablishConnectionOrig) (client);
 
91
        winProcEstablishConnectionOrig = NULL;
 
92
        return iReturn;
 
93
    }
 
94
 
 
95
    /* Watch for server reset */
 
96
    if (s_ulServerGeneration != serverGeneration) {
 
97
        /* Save new generation number */
 
98
        s_ulServerGeneration = serverGeneration;
 
99
 
 
100
        /* Reset call count */
 
101
        s_iCallCount = 0;
 
102
    }
 
103
 
 
104
    /* Increment call count */
 
105
    ++s_iCallCount;
 
106
 
 
107
    /*
 
108
     * This procedure is only used for initialization.
 
109
     * We can unwrap the original procedure at this point
 
110
     * so that this function is no longer called until the
 
111
     * server resets and the function is wrapped again.
 
112
     */
 
113
    InitialVector[2] = winProcEstablishConnectionOrig;
 
114
 
 
115
    /*
 
116
     * Call original function and bail if it fails.
 
117
     * NOTE: We must do this first, since we need XdmcpOpenDisplay
 
118
     * to be called before we initialize our clipboard client.
 
119
     */
 
120
    iReturn = (*winProcEstablishConnectionOrig) (client);
 
121
    if (iReturn != 0) {
 
122
        ErrorF("winProcEstablishConnection - ProcEstablishConnection "
 
123
               "failed, bailing.\n");
 
124
        return iReturn;
 
125
    }
 
126
 
 
127
    /* Clear original function pointer */
 
128
    winProcEstablishConnectionOrig = NULL;
 
129
 
 
130
    /* If the clipboard client has already been started, abort */
 
131
    if (g_fClipboardLaunched) {
 
132
        ErrorF("winProcEstablishConnection - Clipboard client already "
 
133
               "launched, returning.\n");
 
134
        return iReturn;
 
135
    }
 
136
 
 
137
    /* Startup the clipboard client if clipboard mode is being used */
 
138
    if (g_fClipboard) {
 
139
        /*
 
140
         * NOTE: The clipboard client is started here for a reason:
 
141
         * 1) Assume you are using XDMCP (e.g. XWin -query %hostname%)
 
142
         * 2) If the clipboard client attaches during X Server startup,
 
143
         *    then it becomes the "magic client" that causes the X Server
 
144
         *    to reset if it exits.
 
145
         * 3) XDMCP calls KillAllClients when it starts up.
 
146
         * 4) The clipboard client is a client, so it is killed.
 
147
         * 5) The clipboard client is the "magic client", so the X Server
 
148
         *    resets itself.
 
149
         * 6) This repeats ad infinitum.
 
150
         * 7) We avoid this by waiting until at least one client (could
 
151
         *    be XDM, could be another client) connects, which makes it
 
152
         *    almost certain that the clipboard client will not connect
 
153
         *    until after XDM when using XDMCP.
 
154
         */
 
155
 
 
156
        /* Create the clipboard client thread */
 
157
        if (!winInitClipboard()) {
 
158
            ErrorF("winProcEstablishConnection - winClipboardInit "
 
159
                   "failed.\n");
 
160
            return iReturn;
 
161
        }
 
162
 
 
163
        ErrorF("winProcEstablishConnection - winInitClipboard returned.\n");
 
164
    }
 
165
 
 
166
    /* Flag that clipboard client has been launched */
 
167
    g_fClipboardLaunched = TRUE;
 
168
 
 
169
    return iReturn;
 
170
}
 
171
 
 
172
/*
 
173
 * Wrapper for internal SetSelectionOwner function.
 
174
 * Grabs ownership of Windows clipboard when X11 clipboard owner changes.
 
175
 */
 
176
 
 
177
int
 
178
winProcSetSelectionOwner(ClientPtr client)
 
179
{
 
180
    int i;
 
181
    DrawablePtr pDrawable;
 
182
    WindowPtr pWindow = None;
 
183
    Bool fOwnedToNotOwned = FALSE;
 
184
    static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None };
 
185
    static unsigned long s_ulServerGeneration = 0;
 
186
 
 
187
    REQUEST(xSetSelectionOwnerReq);
 
188
 
 
189
    REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
 
190
 
 
191
    winDebug("winProcSetSelectionOwner - Hello.\n");
 
192
 
 
193
    /* Watch for server reset */
 
194
    if (s_ulServerGeneration != serverGeneration) {
 
195
        /* Save new generation number */
 
196
        s_ulServerGeneration = serverGeneration;
 
197
 
 
198
        /* Initialize static variables */
 
199
        for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
 
200
            s_iOwners[i] = None;
 
201
    }
 
202
 
 
203
    /* Abort if clipboard not completely initialized yet */
 
204
    if (!g_fClipboardStarted) {
 
205
        /* ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, "
 
206
           "aborting.\n"); */
 
207
        goto winProcSetSelectionOwner_Done;
 
208
    }
 
209
 
 
210
    /* Grab window if we have one */
 
211
    if (None != stuff->window) {
 
212
        /* Grab the Window from the request */
 
213
        int rc =
 
214
            dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess);
 
215
        if (rc != Success) {
 
216
            ErrorF("winProcSetSelectionOwner - Found BadWindow, aborting.\n");
 
217
            goto winProcSetSelectionOwner_Done;
 
218
        }
 
219
    }
 
220
 
 
221
    /* Now we either have a valid window or None */
 
222
 
 
223
    /* Save selection owners for monitored selections, ignore other selections */
 
224
    if (XA_PRIMARY == stuff->selection) {
 
225
        /* Look for owned -> not owned transition */
 
226
        if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) {
 
227
            fOwnedToNotOwned = TRUE;
 
228
 
 
229
            winDebug("winProcSetSelectionOwner - PRIMARY - Going from "
 
230
                     "owned to not owned.\n");
 
231
 
 
232
            /* Adjust last owned selection */
 
233
            if (None != s_iOwners[CLIP_OWN_CLIPBOARD])
 
234
                g_atomLastOwnedSelection = MakeAtom("CLIPBOARD", 9, TRUE);
 
235
            else
 
236
                g_atomLastOwnedSelection = None;
 
237
        }
 
238
 
 
239
        /* Save new selection owner or None */
 
240
        s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;
 
241
 
 
242
        winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
 
243
                 stuff->window);
 
244
    }
 
245
    else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) {
 
246
        /* Look for owned -> not owned transition */
 
247
        if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) {
 
248
            fOwnedToNotOwned = TRUE;
 
249
 
 
250
            winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from "
 
251
                     "owned to not owned.\n");
 
252
 
 
253
            /* Adjust last owned selection */
 
254
            if (None != s_iOwners[CLIP_OWN_PRIMARY])
 
255
                g_atomLastOwnedSelection = XA_PRIMARY;
 
256
            else
 
257
                g_atomLastOwnedSelection = None;
 
258
        }
 
259
 
 
260
        /* Save new selection owner or None */
 
261
        s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;
 
262
 
 
263
        winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
 
264
                 stuff->window);
 
265
 
 
266
    }
 
267
    else
 
268
        goto winProcSetSelectionOwner_Done;
 
269
 
 
270
    /*
 
271
     * At this point, if one of the selections is still owned by the 
 
272
     * clipboard manager then it should be marked as unowned since
 
273
     * we will be taking ownership of the Win32 clipboard.
 
274
     */
 
275
    if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
 
276
        s_iOwners[CLIP_OWN_PRIMARY] = None;
 
277
    if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
 
278
        s_iOwners[CLIP_OWN_CLIPBOARD] = None;
 
279
 
 
280
    /*
 
281
     * Handle case when selection is being disowned,
 
282
     * WM_DRAWCLIPBOARD did not do the disowning,
 
283
     * both monitored selections are no longer owned,
 
284
     * an owned to not owned transition was detected,
 
285
     * and we currently own the Win32 clipboard.
 
286
     */
 
287
    if (stuff->window == None
 
288
        && s_iOwners[CLIP_OWN_PRIMARY] == None
 
289
        && s_iOwners[CLIP_OWN_CLIPBOARD] == None
 
290
        && fOwnedToNotOwned
 
291
        && g_hwndClipboard != NULL && g_hwndClipboard == GetClipboardOwner()) {
 
292
        winDebug("winProcSetSelectionOwner - We currently own the "
 
293
                 "clipboard and neither the PRIMARY nor the CLIPBOARD "
 
294
                 "selections are owned, releasing ownership of Win32 "
 
295
                 "clipboard.\n");
 
296
 
 
297
        /* Release ownership of the Windows clipboard */
 
298
        OpenClipboard(NULL);
 
299
        EmptyClipboard();
 
300
        CloseClipboard();
 
301
 
 
302
        goto winProcSetSelectionOwner_Done;
 
303
    }
 
304
 
 
305
    /* Abort if no window at this point */
 
306
    if (None == stuff->window) {
 
307
        winDebug("winProcSetSelectionOwner - No window, returning.\n");
 
308
        goto winProcSetSelectionOwner_Done;
 
309
    }
 
310
 
 
311
    /* Abort if invalid selection */
 
312
    if (!ValidAtom(stuff->selection)) {
 
313
        ErrorF("winProcSetSelectionOwner - Found BadAtom, aborting.\n");
 
314
        goto winProcSetSelectionOwner_Done;
 
315
    }
 
316
 
 
317
    /* Cast Window to Drawable */
 
318
    pDrawable = (DrawablePtr) pWindow;
 
319
 
 
320
    /* Abort if clipboard manager is owning the selection */
 
321
    if (pDrawable->id == g_iClipboardWindow) {
 
322
        winDebug("winProcSetSelectionOwner - We changed ownership, "
 
323
                 "aborting.\n");
 
324
        goto winProcSetSelectionOwner_Done;
 
325
    }
 
326
 
 
327
    /* Abort if root window is taking ownership */
 
328
    if (pDrawable->id == 0) {
 
329
        ErrorF("winProcSetSelectionOwner - Root window taking ownership, "
 
330
               "aborting\n");
 
331
        goto winProcSetSelectionOwner_Done;
 
332
    }
 
333
 
 
334
    /* Close clipboard if we have it open already */
 
335
    if (GetOpenClipboardWindow() == g_hwndClipboard) {
 
336
        CloseClipboard();
 
337
    }
 
338
 
 
339
    /* Access the Windows clipboard */
 
340
    if (!OpenClipboard(g_hwndClipboard)) {
 
341
        ErrorF("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n",
 
342
               (int) GetLastError());
 
343
        goto winProcSetSelectionOwner_Done;
 
344
    }
 
345
 
 
346
    /* Take ownership of the Windows clipboard */
 
347
    if (!EmptyClipboard()) {
 
348
        ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n",
 
349
               (int) GetLastError());
 
350
        goto winProcSetSelectionOwner_Done;
 
351
    }
 
352
 
 
353
    /* Advertise regular text and unicode */
 
354
    SetClipboardData(CF_UNICODETEXT, NULL);
 
355
    SetClipboardData(CF_TEXT, NULL);
 
356
 
 
357
    /* Save handle to last owned selection */
 
358
    g_atomLastOwnedSelection = stuff->selection;
 
359
 
 
360
    /* Release the clipboard */
 
361
    if (!CloseClipboard()) {
 
362
        ErrorF("winProcSetSelectionOwner - CloseClipboard () failed: "
 
363
               "%08x\n", (int) GetLastError());
 
364
        goto winProcSetSelectionOwner_Done;
 
365
    }
 
366
 
 
367
 winProcSetSelectionOwner_Done:
 
368
    return (*winProcSetSelectionOwnerOrig) (client);
 
369
}