diff --git a/src/arch/ArchHooks/ArchHooks_Unix.cpp b/src/arch/ArchHooks/ArchHooks_Unix.cpp index 9f6412ebdf..57869f838e 100644 --- a/src/arch/ArchHooks/ArchHooks_Unix.cpp +++ b/src/arch/ArchHooks/ArchHooks_Unix.cpp @@ -27,6 +27,12 @@ extern "C" } #endif +#if defined(HAVE_X11) +#include "archutils/Unix/X11Helper.h" +#include +#include +#endif + static bool IsFatalSignal( int signal ) { switch( signal ) @@ -282,6 +288,71 @@ void ArchHooks_Unix::SetTime( tm newtime ) LOG->Trace( "'hwclock --systohc' failed" ); } +RString ArchHooks_Unix::GetClipboard() +{ +#ifdef HAVE_X11 + using namespace X11Helper; + // Why isn't this defined by Xlib headers? + Atom XA_CLIPBOARD = XInternAtom( Dpy, "CLIPBOARD", 0); + Atom pstType; + RString ret; + unsigned char *paste; + unsigned long remainder; + int ck; + Window selOwner; + + ASSERT( Win != None ); + // X11 is weird: instead of the clipboard being stored by the server + // as you'd expect, it's actually a form of IPC, where we send + // a request to the window we're pasting text from, and it sends + // the paste data back. + // XXX: X11 has TWO clipboards, the traditional Ctrl+C Ctrl+V, + // and a second independent clipboard called the "primary selection", + // set simply by selecting a span of text, and pasted with a + // middle click. For now we just use the former, but this causes + // problems in some cases because some (generally older) applications + // only implement the latter. + + // Make sure someone has the clipboard first. + selOwner = XGetSelectionOwner( Dpy, XA_CLIPBOARD ); + if( selOwner == None ) + // There is no clipboard right now. + return ""; + + // Tell the clipboard owner to give us the goods. + // protip: XConvertSelection() puts the result of the request in a + // property on YOUR window. + XConvertSelection( Dpy, XA_CLIPBOARD, XA_STRING, XA_PRIMARY, Win, CurrentTime ); + // XXX: This seems to always return 1 even when it works. (Success == 0) + + // Now we must wait for the clipboard owner to cough it up. + // HACK: What we SHOULD do is XSelectInput() for SelectionNotify before + // calling XConvertSelection and then black on XWindowEvent(), but that + // would require significant cooperation with InputHandler_X11 through + // X11Helper. + // TODO: Said cooperation would be useful as then LowLevelWindow_X11 + // could listen for XFocusInEvent / XFocusOutEvent and send those. + XSync( Dpy, false ); + usleep( 10000 ); + + // Now retrieve the paste from our primary selection property. + // Delete our primary selection so we'll just have null next time. + int unused2; // XXX: "actual format of the property"? What? + unsigned long unused3; + ck = XGetWindowProperty( Dpy, Win, XA_PRIMARY, 0, LONG_MAX, true, XA_STRING, &pstType, &unused2, &unused3, &remainder, &paste ); + if( ck != Success || pstType != XA_STRING ) + // Selection doesn't exist or isn't stringable + return ""; + + ret = RString( (char*) paste); + XFree(paste); + return ret; +#else + LOG->Warn("ArchHooks_Unix: GetClipboard(): Compiled without any supported clipboard source!"); + return ""; +#endif +} + #include "RageFileManager.h" #include diff --git a/src/arch/ArchHooks/ArchHooks_Unix.h b/src/arch/ArchHooks/ArchHooks_Unix.h index 81c52ec522..fc1962f874 100644 --- a/src/arch/ArchHooks/ArchHooks_Unix.h +++ b/src/arch/ArchHooks/ArchHooks_Unix.h @@ -18,6 +18,8 @@ public: bool GoToURL( RString sUrl ); static clockid_t GetClock(); + + RString GetClipboard(); }; #ifdef ARCH_HOOKS