Blindly add a few stuff from VST
[juce-lv2.git] / juce / source / src / native / linux / juce_linux_Clipboard.cpp
blobdf38f6b16649c63f981cc4d750a3052a022a5ff0
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 // (This file gets included by juce_linux_NativeCode.cpp, rather than being
27 // compiled on its own).
28 #if JUCE_INCLUDED_FILE
30 //==============================================================================
31 extern Display* display;
32 extern Window juce_messageWindowHandle;
34 namespace ClipboardHelpers
36 static String localClipboardContent;
37 static Atom atom_UTF8_STRING;
38 static Atom atom_CLIPBOARD;
39 static Atom atom_TARGETS;
41 //==============================================================================
42 static void initSelectionAtoms()
44 static bool isInitialised = false;
45 if (! isInitialised)
47 atom_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
48 atom_CLIPBOARD = XInternAtom (display, "CLIPBOARD", False);
49 atom_TARGETS = XInternAtom (display, "TARGETS", False);
53 //==============================================================================
54 // Read the content of a window property as either a locale-dependent string or an utf8 string
55 // works only for strings shorter than 1000000 bytes
56 static String readWindowProperty (Window window, Atom prop, Atom fmt)
58 String returnData;
59 char* clipData;
60 Atom actualType;
61 int actualFormat;
62 unsigned long numItems, bytesLeft;
64 if (XGetWindowProperty (display, window, prop,
65 0L /* offset */, 1000000 /* length (max) */, False,
66 AnyPropertyType /* format */,
67 &actualType, &actualFormat, &numItems, &bytesLeft,
68 (unsigned char**) &clipData) == Success)
70 if (actualType == atom_UTF8_STRING && actualFormat == 8)
71 returnData = String::fromUTF8 (clipData, numItems);
72 else if (actualType == XA_STRING && actualFormat == 8)
73 returnData = String (clipData, numItems);
75 if (clipData != nullptr)
76 XFree (clipData);
78 jassert (bytesLeft == 0 || numItems == 1000000);
81 XDeleteProperty (display, window, prop);
82 return returnData;
85 //==============================================================================
86 // Send a SelectionRequest to the window owning the selection and waits for its answer (with a timeout) */
87 static bool requestSelectionContent (String& selectionContent, Atom selection, Atom requestedFormat)
89 Atom property_name = XInternAtom (display, "JUCE_SEL", false);
91 // The selection owner will be asked to set the JUCE_SEL property on the
92 // juce_messageWindowHandle with the selection content
93 XConvertSelection (display, selection, requestedFormat, property_name,
94 juce_messageWindowHandle, CurrentTime);
96 int count = 50; // will wait at most for 200 ms
98 while (--count >= 0)
100 XEvent event;
101 if (XCheckTypedWindowEvent (display, juce_messageWindowHandle, SelectionNotify, &event))
103 if (event.xselection.property == property_name)
105 jassert (event.xselection.requestor == juce_messageWindowHandle);
107 selectionContent = readWindowProperty (event.xselection.requestor,
108 event.xselection.property,
109 requestedFormat);
110 return true;
112 else
114 return false; // the format we asked for was denied.. (event.xselection.property == None)
118 // not very elegant.. we could do a select() or something like that...
119 // however clipboard content requesting is inherently slow on x11, it
120 // often takes 50ms or more so...
121 Thread::sleep (4);
124 return false;
128 //==============================================================================
129 // Called from the event loop in juce_linux_Messaging in response to SelectionRequest events
130 void juce_handleSelectionRequest (XSelectionRequestEvent &evt)
132 ClipboardHelpers::initSelectionAtoms();
134 // the selection content is sent to the target window as a window property
135 XSelectionEvent reply;
136 reply.type = SelectionNotify;
137 reply.display = evt.display;
138 reply.requestor = evt.requestor;
139 reply.selection = evt.selection;
140 reply.target = evt.target;
141 reply.property = None; // == "fail"
142 reply.time = evt.time;
144 HeapBlock <char> data;
145 int propertyFormat = 0, numDataItems = 0;
147 if (evt.selection == XA_PRIMARY || evt.selection == ClipboardHelpers::atom_CLIPBOARD)
149 if (evt.target == XA_STRING || evt.target == ClipboardHelpers::atom_UTF8_STRING)
151 // translate to utf8
152 numDataItems = ClipboardHelpers::localClipboardContent.getNumBytesAsUTF8() + 1;
153 data.calloc (numDataItems + 1);
154 ClipboardHelpers::localClipboardContent.copyToUTF8 (data, numDataItems);
155 propertyFormat = 8; // bits/item
157 else if (evt.target == ClipboardHelpers::atom_TARGETS)
159 // another application wants to know what we are able to send
160 numDataItems = 2;
161 propertyFormat = 32; // atoms are 32-bit
162 data.calloc (numDataItems * 4);
163 Atom* atoms = reinterpret_cast<Atom*> (data.getData());
164 atoms[0] = ClipboardHelpers::atom_UTF8_STRING;
165 atoms[1] = XA_STRING;
168 else
170 DBG ("requested unsupported clipboard");
173 if (data != nullptr)
175 const int maxReasonableSelectionSize = 1000000;
177 // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss
178 if (evt.property != None && numDataItems < maxReasonableSelectionSize)
180 XChangeProperty (evt.display, evt.requestor,
181 evt.property, evt.target,
182 propertyFormat /* 8 or 32 */, PropModeReplace,
183 reinterpret_cast<const unsigned char*> (data.getData()), numDataItems);
184 reply.property = evt.property; // " == success"
188 XSendEvent (evt.display, evt.requestor, 0, NoEventMask, (XEvent*) &reply);
191 //==============================================================================
192 void SystemClipboard::copyTextToClipboard (const String& clipText)
194 ClipboardHelpers::initSelectionAtoms();
195 ClipboardHelpers::localClipboardContent = clipText;
197 XSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime);
198 XSetSelectionOwner (display, ClipboardHelpers::atom_CLIPBOARD, juce_messageWindowHandle, CurrentTime);
201 String SystemClipboard::getTextFromClipboard()
203 ClipboardHelpers::initSelectionAtoms();
205 /* 1) try to read from the "CLIPBOARD" selection first (the "high
206 level" clipboard that is supposed to be filled by ctrl-C
207 etc). When a clipboard manager is running, the content of this
208 selection is preserved even when the original selection owner
209 exits.
211 2) and then try to read from "PRIMARY" selection (the "legacy" selection
212 filled by good old x11 apps such as xterm)
214 String content;
215 Atom selection = XA_PRIMARY;
216 Window selectionOwner = None;
218 if ((selectionOwner = XGetSelectionOwner (display, selection)) == None)
220 selection = ClipboardHelpers::atom_CLIPBOARD;
221 selectionOwner = XGetSelectionOwner (display, selection);
224 if (selectionOwner != None)
226 if (selectionOwner == juce_messageWindowHandle)
228 content = ClipboardHelpers::localClipboardContent;
230 else
232 // first try: we want an utf8 string
233 bool ok = ClipboardHelpers::requestSelectionContent (content, selection, ClipboardHelpers::atom_UTF8_STRING);
235 if (! ok)
237 // second chance, ask for a good old locale-dependent string ..
238 ok = ClipboardHelpers::requestSelectionContent (content, selection, XA_STRING);
243 return content;
246 #endif