1 /**************************************************************
4 * Aqua pasteboard <-> X cut buffer
5 * Greg Parker gparker@cs.stanford.edu March 8, 2001
6 **************************************************************/
8 * Copyright (c) 2001 Greg Parker. All Rights Reserved.
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
28 * Except as contained in this notice, the name(s) of the above copyright
29 * holders shall not be used in advertising or otherwise to promote the sale,
30 * use or other dealings in this Software without prior written authorization.
33 #ifdef HAVE_XORG_CONFIG_H
34 #include <xorg-config.h>
36 #include "quartzPasteboard.h"
38 #include <X11/Xatom.h>
39 #include "windowstr.h"
40 #include "propertyst.h"
41 #include "scrnintstr.h"
42 #include "selection.h"
45 extern Selection
*CurrentSelections
;
46 extern int NumCurrentSelections
;
49 // Helper function to read the X11 cut buffer
50 // FIXME: What about multiple screens? Currently, this reads the first
51 // CUT_BUFFER0 from the first screen where the buffer content is a string.
52 // Returns a string on the heap that the caller must free.
53 // Returns NULL if there is no cut text or there is not enough memory.
54 static char * QuartzReadCutBuffer(void)
59 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
60 ScreenPtr pScreen
= screenInfo
.screens
[i
];
63 pProp
= wUserProps (WindowTable
[pScreen
->myNum
]);
64 while (pProp
&& pProp
->propertyName
!= XA_CUT_BUFFER0
) {
67 if (! pProp
) continue;
68 if (pProp
->type
!= XA_STRING
) continue;
69 if (pProp
->format
!= 8) continue;
71 text
= xalloc(1 + pProp
->size
);
73 memcpy(text
, pProp
->data
, pProp
->size
);
74 text
[pProp
->size
] = '\0';
78 // didn't find any text
82 // Write X cut buffer to Mac OS X pasteboard
83 // Called by ProcessInputEvents() in response to request from X server thread.
84 void QuartzWritePasteboard(void)
87 text
= QuartzReadCutBuffer();
89 QuartzWriteCocoaPasteboard(text
);
94 #define strequal(a, b) (0 == strcmp((a), (b)))
96 // Read Mac OS X pasteboard into X cut buffer
97 // Called by ProcessInputEvents() in response to request from X server thread.
98 void QuartzReadPasteboard(void)
100 char *oldText
= QuartzReadCutBuffer();
101 char *text
= QuartzReadCocoaPasteboard();
103 // Compare text with current cut buffer contents.
104 // Change the buffer if both exist and are different
105 // OR if there is new text but no old text.
106 // Otherwise, don't clear the selection unnecessarily.
108 if ((text
&& oldText
&& !strequal(text
, oldText
)) ||
109 (text
&& !oldText
)) {
112 for (scrn
= 0; scrn
< screenInfo
.numScreens
; scrn
++) {
113 ScreenPtr pScreen
= screenInfo
.screens
[scrn
];
114 // Set the cut buffers on each screen
115 // fixme really on each screen?
116 ChangeWindowProperty(WindowTable
[pScreen
->myNum
], XA_CUT_BUFFER0
,
117 XA_STRING
, 8, PropModeReplace
,
118 strlen(text
), (pointer
)text
, TRUE
);
121 // Undo any current X selection (similar to code in dispatch.c)
122 // FIXME: what about secondary selection?
123 // FIXME: only touch first XA_PRIMARY selection?
125 while ((sel
< NumCurrentSelections
) &&
126 CurrentSelections
[sel
].selection
!= XA_PRIMARY
)
128 if (sel
< NumCurrentSelections
) {
129 // Notify client if necessary
130 if (CurrentSelections
[sel
].client
) {
133 event
.u
.u
.type
= SelectionClear
;
134 event
.u
.selectionClear
.time
= GetTimeInMillis();
135 event
.u
.selectionClear
.window
= CurrentSelections
[sel
].window
;
136 event
.u
.selectionClear
.atom
= CurrentSelections
[sel
].selection
;
137 TryClientEvents(CurrentSelections
[sel
].client
, &event
, 1,
138 NoEventMask
, NoEventMask
/*CantBeFiltered*/,
143 // FIXME: need to erase .selection too? dispatch.c doesn't
144 CurrentSelections
[sel
].pWin
= NullWindow
;
145 CurrentSelections
[sel
].window
= None
;
146 CurrentSelections
[sel
].client
= NullClient
;
150 if (text
) free(text
);
151 if (oldText
) free(oldText
);