mirror of https://github.com/buggins/dlangui.git
Merge pull request #471 from FreeSlave/x11_getClipboardText
X11 getClipboardText implementation
This commit is contained in:
commit
709e095d27
|
@ -73,7 +73,6 @@ private __gshared
|
|||
int x11screen;
|
||||
XIM xim;
|
||||
|
||||
string localClipboardContent;
|
||||
bool _enableOpengl = false;
|
||||
|
||||
Cursor[CursorType.Hand + 1] x11cursors;
|
||||
|
@ -1313,34 +1312,15 @@ class X11Platform : Platform {
|
|||
return _windowMap.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts application message loop.
|
||||
*
|
||||
* When returned from this method, application is shutting down.
|
||||
*/
|
||||
override int enterMessageLoop() {
|
||||
import core.thread;
|
||||
XEvent event; /* the XEvent declaration !!! */
|
||||
KeySym key; /* a dealie-bob to handle KeyPress Events */
|
||||
char[255] text; /* a char buffer for KeyPress Events */
|
||||
|
||||
Log.d("enterMessageLoop()");
|
||||
XComposeStatus compose;
|
||||
|
||||
protected int numberOfPendingEvents()
|
||||
{
|
||||
import core.sys.posix.sys.select;
|
||||
int x11displayFd = ConnectionNumber(x11display);
|
||||
fd_set fdSet;
|
||||
FD_ZERO(&fdSet);
|
||||
FD_SET(x11displayFd, &fdSet);
|
||||
scope(exit) FD_ZERO(&fdSet);
|
||||
while(!allWindowsClosed()) {
|
||||
// Note: only events we set the mask for are detected!
|
||||
foreach(win; _windowMap) {
|
||||
if (win._needRedraw) {
|
||||
win.redraw();
|
||||
}
|
||||
}
|
||||
XFlush(x11display);
|
||||
|
||||
int eventsInQueue = XEventsQueued(x11display, QueuedAlready);
|
||||
if (!eventsInQueue) {
|
||||
import core.stdc.errno;
|
||||
|
@ -1356,15 +1336,12 @@ class X11Platform : Platform {
|
|||
eventsInQueue = XPending(x11display);
|
||||
}
|
||||
}
|
||||
if (!eventsInQueue) {
|
||||
debug(x11) Log.d("X11: Sleeping");
|
||||
Thread.sleep(dur!("msecs")(10));
|
||||
return eventsInQueue;
|
||||
}
|
||||
foreach(eventIndex; 0..eventsInQueue)
|
||||
|
||||
protected void processXEvent(ref XEvent event)
|
||||
{
|
||||
if (allWindowsClosed())
|
||||
break;
|
||||
XNextEvent(x11display, &event);
|
||||
XComposeStatus compose;
|
||||
switch (event.type) {
|
||||
case ConfigureNotify:
|
||||
X11Window w = findWindow(event.xconfigure.window);
|
||||
|
@ -1599,7 +1576,6 @@ class X11Platform : Platform {
|
|||
selectionEvent.xselection.time = selectionRequest.time;
|
||||
|
||||
if (selectionRequest.target == XA_STRING || selectionRequest.target == atom_UTF8_STRING) {
|
||||
static if (false) {
|
||||
int currentSelectionFormat;
|
||||
Atom currentSelectionType;
|
||||
c_ulong selectionDataLength, overflow;
|
||||
|
@ -1614,11 +1590,6 @@ class X11Platform : Platform {
|
|||
selectionRequest.target, 8, PropModeReplace,
|
||||
selectionDataPtr, cast(int)selectionDataLength);
|
||||
}
|
||||
} else {
|
||||
XChangeProperty(x11display, selectionRequest.requestor, selectionRequest.property,
|
||||
selectionRequest.target, 8, PropModeReplace,
|
||||
cast(ubyte*)localClipboardContent, cast(int)localClipboardContent.length);
|
||||
}
|
||||
selectionEvent.xselection.property = selectionRequest.property;
|
||||
} else if (selectionRequest.target == atom_TARGETS) {
|
||||
Atom[3] supportedFormats = [atom_UTF8_STRING, XA_STRING, atom_TARGETS];
|
||||
|
@ -1631,8 +1602,11 @@ class X11Platform : Platform {
|
|||
}
|
||||
break;
|
||||
case SelectionNotify:
|
||||
Log.d("X11: SelectionNotify event");
|
||||
debug(x11) Log.d("X11: SelectionNotify event");
|
||||
X11Window w = findWindow(event.xselection.requestor);
|
||||
if (w) {
|
||||
waitingForSelection = false;
|
||||
}
|
||||
break;
|
||||
case ClientMessage:
|
||||
debug(x11) Log.d("X11: ClientMessage event");
|
||||
|
@ -1661,27 +1635,122 @@ class X11Platform : Platform {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts application message loop.
|
||||
*
|
||||
* When returned from this method, application is shutting down.
|
||||
*/
|
||||
override int enterMessageLoop() {
|
||||
import core.thread;
|
||||
XEvent event; /* the XEvent declaration !!! */
|
||||
KeySym key; /* a dealie-bob to handle KeyPress Events */
|
||||
char[255] text; /* a char buffer for KeyPress Events */
|
||||
|
||||
Log.d("enterMessageLoop()");
|
||||
|
||||
while(!allWindowsClosed()) {
|
||||
// Note: only events we set the mask for are detected!
|
||||
foreach(win; _windowMap) {
|
||||
if (win._needRedraw) {
|
||||
win.redraw();
|
||||
}
|
||||
}
|
||||
XFlush(x11display);
|
||||
int eventsInQueue = numberOfPendingEvents();
|
||||
if (!eventsInQueue) {
|
||||
debug(x11) Log.d("X11: Sleeping");
|
||||
Thread.sleep(dur!("msecs")(10));
|
||||
}
|
||||
foreach(eventIndex; 0..eventsInQueue)
|
||||
{
|
||||
if (allWindowsClosed())
|
||||
break;
|
||||
if (!numberOfPendingEvents())
|
||||
break;
|
||||
XNextEvent(x11display, &event);
|
||||
processXEvent(event);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// check has clipboard text
|
||||
override bool hasClipboardText(bool mouseBuffer = false) {
|
||||
return (localClipboardContent.length != 0);
|
||||
const selectionType = mouseBuffer ? XA_PRIMARY : atom_CLIPBOARD;
|
||||
return XGetSelectionOwner(x11display, selectionType) != None;
|
||||
}
|
||||
|
||||
protected bool waitingForSelection;
|
||||
/// retrieves text from clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux)
|
||||
override dstring getClipboardText(bool mouseBuffer = false) {
|
||||
return toUTF32(localClipboardContent);
|
||||
const selectionType = mouseBuffer ? XA_PRIMARY : atom_CLIPBOARD;
|
||||
auto owner = XGetSelectionOwner(x11display, selectionType);
|
||||
if (owner == None) {
|
||||
Log.d("Selection owner is none");
|
||||
return ""d;
|
||||
} else {
|
||||
// Find any top-level window
|
||||
XWindow xwindow;
|
||||
foreach(w; _windowMap) {
|
||||
if (w._parent is null && w._win != None) {
|
||||
xwindow = w._win;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (xwindow != None) {
|
||||
import std.datetime;
|
||||
waitingForSelection = true;
|
||||
XConvertSelection(x11display, selectionType, atom_UTF8_STRING, atom_DLANGUI_CLIPBOARD_BUFFER, xwindow, CurrentTime);
|
||||
auto stopWaiting = Clock.currTime() + dur!"msecs"(500);
|
||||
while(waitingForSelection) {
|
||||
if (stopWaiting <= Clock.currTime()) {
|
||||
waitingForSelection = false;
|
||||
setClipboardText(""d);
|
||||
Log.e("Waiting for clipboard contents timeout");
|
||||
return ""d;
|
||||
}
|
||||
XFlush(x11display);
|
||||
int eventsInQueue = numberOfPendingEvents();
|
||||
foreach(eventIndex; 0..eventsInQueue)
|
||||
{
|
||||
if (allWindowsClosed())
|
||||
break;
|
||||
if (!numberOfPendingEvents())
|
||||
break;
|
||||
XEvent event;
|
||||
XNextEvent(x11display, &event);
|
||||
processXEvent(event);
|
||||
}
|
||||
}
|
||||
Atom selectionTarget;
|
||||
int selectionFormat;
|
||||
c_ulong selectionDataLength, overflow;
|
||||
ubyte* selectionDataPtr;
|
||||
if (XGetWindowProperty(x11display, xwindow, atom_DLANGUI_CLIPBOARD_BUFFER, 0, int.max/4, False, 0, &selectionTarget, &selectionFormat, &selectionDataLength, &overflow, &selectionDataPtr) == 0)
|
||||
{
|
||||
scope(exit) XFree(selectionDataPtr);
|
||||
if (selectionTarget == XA_STRING || selectionTarget == atom_UTF8_STRING) {
|
||||
char[] selectionText = cast(char[])selectionDataPtr[0..selectionDataLength];
|
||||
return toUTF32(selectionText);
|
||||
} else {
|
||||
Log.d("Selection type is not a string!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.d("Could not find any window to get selection");
|
||||
}
|
||||
}
|
||||
return ""d;
|
||||
}
|
||||
|
||||
/// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux)
|
||||
override void setClipboardText(dstring text, bool mouseBuffer = false) {
|
||||
localClipboardContent = toUTF8(text);
|
||||
if (!mouseBuffer && atom_CLIPBOARD == None) {
|
||||
Log.e("No CLIPBOARD atom available");
|
||||
return;
|
||||
}
|
||||
auto selection = mouseBuffer ? XA_PRIMARY : atom_CLIPBOARD;
|
||||
XWindow xwindow = None;
|
||||
// Find any top-level window
|
||||
foreach(w; _windowMap) {
|
||||
|
@ -1693,16 +1762,12 @@ class X11Platform : Platform {
|
|||
Log.e("Could not find window to save clipboard text");
|
||||
return;
|
||||
}
|
||||
static if (false) {
|
||||
// This is example of how setting clipboard contents can be implemented without global variable
|
||||
auto textc = text.toUTF8;
|
||||
XChangeProperty(x11display, DefaultRootWindow(x11display), atom_DLANGUI_CLIPBOARD_BUFFER, XA_STRING, 8, PropModeReplace, cast(ubyte*)textc.ptr, cast(int)textc.length);
|
||||
}
|
||||
|
||||
if (mouseBuffer && XGetSelectionOwner(x11display, XA_PRIMARY) != xwindow) {
|
||||
XSetSelectionOwner(x11display, XA_PRIMARY, xwindow, CurrentTime);
|
||||
} else if (XGetSelectionOwner(x11display, atom_CLIPBOARD != xwindow)) {
|
||||
XSetSelectionOwner(x11display, atom_CLIPBOARD, xwindow, CurrentTime);
|
||||
auto textc = text.toUTF8;
|
||||
XChangeProperty(x11display, DefaultRootWindow(x11display), atom_DLANGUI_CLIPBOARD_BUFFER, atom_UTF8_STRING, 8, PropModeReplace, cast(ubyte*)textc.ptr, cast(int)textc.length);
|
||||
|
||||
if (XGetSelectionOwner(x11display, selection) != xwindow) {
|
||||
XSetSelectionOwner(x11display, selection, xwindow, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue