# HG changeset patch # User Sam Lantinga # Date 1278920215 25200 # Node ID 15d2c6f40c4880dce79a5dd235228800b737eb06 # Parent dbf3fa54109685daa8a1f644da70a9b4fb591b54 Added X11 clipboard support. As far as I know there isn't any real way to tell when the clipboard contents have changed without polling them, so I didn't implement the clipboard update event on X11. diff -r dbf3fa541096 -r 15d2c6f40c48 src/video/x11/SDL_x11clipboard.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11clipboard.c Mon Jul 12 00:36:55 2010 -0700 @@ -0,0 +1,152 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include /* For INT_MAX */ + +#include "SDL_events.h" +#include "SDL_x11video.h" + + +/* Get any application owned window handle for clipboard association */ +static Window +GetWindow(_THIS) +{ + SDL_VideoDisplay *display; + SDL_Window *window; + + display = _this->displays; + if (display) { + window = display->windows; + if (window) { + return ((SDL_WindowData *) window->driverdata)->xwindow; + } + } + return None; +} + +int +X11_SetClipboardText(_THIS, const char *text) +{ + Display *display = ((SDL_VideoData *) _this->driverdata)->display; + Atom format; + Window window; + + /* Get the SDL window that will own the selection */ + window = GetWindow(_this); + if (window == None) { + SDL_SetError("Couldn't find a window to own the selection"); + return -1; + } + + /* If you don't support UTF-8, you might use XA_STRING here */ + format = XInternAtom(display, "UTF8_STRING", False); + XChangeProperty(display, DefaultRootWindow(display), + XA_CUT_BUFFER0, format, 8, PropModeReplace, + (const unsigned char *)text, SDL_strlen(text)); + + if (XGetSelectionOwner(display, XA_PRIMARY) != window) { + XSetSelectionOwner(display, XA_PRIMARY, window, CurrentTime); + } + return 0; +} + +char * +X11_GetClipboardText(_THIS) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + Display *display = videodata->display; + Atom format; + Window window; + Window owner; + Atom selection; + Atom seln_type; + int seln_format; + unsigned long nbytes; + unsigned long overflow; + unsigned char *src; + char *text; + + text = NULL; + + /* Get the SDL window that will own the selection */ + window = GetWindow(_this); + + /* If you don't support UTF-8, you might use XA_STRING here */ + format = XInternAtom(display, "UTF8_STRING", False); + + owner = XGetSelectionOwner(display, XA_PRIMARY); + if ((owner == None) || (owner == window)) { + owner = DefaultRootWindow(display); + selection = XA_CUT_BUFFER0; + } else { + /* Request that the selection owner copy the data to our window */ + owner = window; + selection = XInternAtom(display, "SDL_SELECTION", False); + XConvertSelection(display, XA_PRIMARY, format, selection, owner, + CurrentTime); + + /* FIXME: Should we have a timeout here? */ + videodata->selection_waiting = SDL_TRUE; + while (videodata->selection_waiting) { + SDL_PumpEvents(); + } + } + + if (XGetWindowProperty(display, owner, selection, 0, INT_MAX/4, False, + format, &seln_type, &seln_format, &nbytes, &overflow, &src) + == Success) { + if (seln_type == format) { + text = (char *)SDL_malloc(nbytes+1); + if (text) { + SDL_memcpy(text, src, nbytes); + text[nbytes] = '\0'; + } + } + XFree(src); + } + + if (!text) { + text = SDL_strdup(""); + } + return text; +} + +SDL_bool +X11_HasClipboardText(_THIS) +{ + /* Not an easy way to tell with X11, as far as I know... */ + char *text; + SDL_bool retval; + + text = X11_GetClipboardText(_this); + if (*text) { + retval = SDL_TRUE; + } else { + retval = SDL_FALSE; + } + SDL_free(text); + + return retval; +} + +/* vi: set ts=4 sw=4 expandtab: */ diff -r dbf3fa541096 -r 15d2c6f40c48 src/video/x11/SDL_x11clipboard.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/x11/SDL_x11clipboard.h Mon Jul 12 00:36:55 2010 -0700 @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_x11clipboard_h +#define _SDL_x11clipboard_h + +extern int X11_SetClipboardText(_THIS, const char *text); +extern char *X11_GetClipboardText(_THIS); +extern SDL_bool X11_HasClipboardText(_THIS); + +#endif /* _SDL_x11clipboard_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff -r dbf3fa541096 -r 15d2c6f40c48 src/video/x11/SDL_x11events.c --- a/src/video/x11/SDL_x11events.c Mon Jul 12 00:35:24 2010 -0700 +++ b/src/video/x11/SDL_x11events.c Mon Jul 12 00:36:55 2010 -0700 @@ -25,6 +25,7 @@ #include #include #include +#include /* For INT_MAX */ #include "SDL_x11video.h" #include "../../events/SDL_events_c.h" @@ -33,6 +34,8 @@ #include "SDL_timer.h" #include "SDL_syswm.h" +/*#define DEBUG_XEVENTS*/ + static void X11_DispatchEvent(_THIS) { @@ -286,6 +289,55 @@ } break; + /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ + case SelectionRequest: { + Display *display = videodata->display; + XSelectionRequestEvent *req; + XEvent sevent; + int seln_format; + unsigned long nbytes; + unsigned long overflow; + unsigned char *seln_data; + + req = &xevent.xselectionrequest; +#ifdef DEBUG_XEVENTS + printf("SelectionRequest (requestor = %ld, target = %ld)\n", + req->requestor, req->target); +#endif + + sevent.xselection.type = SelectionNotify; + sevent.xselection.display = req->display; + sevent.xselection.selection = req->selection; + sevent.xselection.target = None; + sevent.xselection.property = None; + sevent.xselection.requestor = req->requestor; + sevent.xselection.time = req->time; + if (XGetWindowProperty(display, DefaultRootWindow(display), + XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target, + &sevent.xselection.target, &seln_format, &nbytes, + &overflow, &seln_data) == Success) { + if (sevent.xselection.target == req->target) { + XChangeProperty(display, req->requestor, req->property, + sevent.xselection.target, seln_format, PropModeReplace, + seln_data, nbytes); + sevent.xselection.property = req->property; + } + XFree(seln_data); + } + XSendEvent(display, req->requestor, False, 0, &sevent); + XSync(display, False); + } + break; + + case SelectionNotify: { +#ifdef DEBUG_XEVENTS + printf("SelectionNotify (requestor = %ld, target = %ld)\n", + xevent.xselection.requestor, xevent.xselection.target); +#endif + videodata->selection_waiting = SDL_FALSE; + } + break; + default:{ #ifdef DEBUG_XEVENTS printf("Unhandled event %d\n", xevent.type); diff -r dbf3fa541096 -r 15d2c6f40c48 src/video/x11/SDL_x11sym.h --- a/src/video/x11/SDL_x11sym.h Mon Jul 12 00:35:24 2010 -0700 +++ b/src/video/x11/SDL_x11sym.h Mon Jul 12 00:36:55 2010 -0700 @@ -37,6 +37,7 @@ SDL_X11_SYM(Bool,XCheckWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return) SDL_X11_SYM(int,XClearWindow,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XCloseDisplay,(Display* a),(a),return) +SDL_X11_SYM(int,XConvertSelection,(Display* a,Atom b,Atom c,Atom d,Window e,Time f),(a,b,c,d,e,f),return) SDL_X11_SYM(int,XCopyArea,(Display* a,Drawable b,Drawable c,GC d,int e,int f,unsigned int g,unsigned int h,int i,int j),(a,b,c,d,e,f,g,h,i,j),return) SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return) SDL_X11_SYM(Cursor,XCreatePixmapCursor,(Display* a,Pixmap b,Pixmap c,XColor* d,XColor* e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return) @@ -71,10 +72,11 @@ SDL_X11_SYM(XModifierKeymap*,XGetModifierMapping,(Display* a),(a),return) SDL_X11_SYM(int,XGetPointerControl,(Display* a,int* b,int* c,int* d),(a,b,c,d),return) SDL_X11_SYM(int,XGetRGBColormaps,(Display* a,Window b,XStandardColormap **c,int *d,Atom e),(a,b,c,d,e),return) +SDL_X11_SYM(Window,XGetSelectionOwner,(Display* a,Atom b),(a,b),return) SDL_X11_SYM(XVisualInfo*,XGetVisualInfo,(Display* a,long b,XVisualInfo* c,int* d),(a,b,c,d),return) -SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),return) SDL_X11_SYM(Status,XGetWindowAttributes,(Display* a,Window b,XWindowAttributes* c),(a,b,c),return) SDL_X11_SYM(int,XGetWindowProperty,(Display* a,Window b,Atom c,long d,long e,Bool f,Atom g,Atom* h,int* i,unsigned long* j,unsigned long *k,unsigned char **l),(a,b,c,d,e,f,g,h,i,j,k,l),return) +SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XGrabKeyboard,(Display* a,Window b,Bool c,int d,int e,Time f),(a,b,c,d,e,f),return) SDL_X11_SYM(int,XGrabPointer,(Display* a,Window b,Bool c,unsigned int d,int e,int f,Window g,Cursor h,Time i),(a,b,c,d,e,f,g,h,i),return) SDL_X11_SYM(int,XGrabServer,(Display* a),(a),return) @@ -114,14 +116,15 @@ SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return) SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return) SDL_X11_SYM(void,XSetRGBColormaps,( Display *a,Window b,XStandardColormap *c,int d,Atom e),(a,b,c,d,e),return) +SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d),return) SDL_X11_SYM(int,XSetTransientForHint,(Display* a,Window b,Window c),(a,b,c),return) -SDL_X11_SYM(int,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),return) SDL_X11_SYM(void,XSetTextProperty,(Display* a,Window b,XTextProperty* c,Atom d),(a,b,c,d),) -SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),) -SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return) SDL_X11_SYM(int,XSetWindowBackground,(Display* a,Window b,unsigned long c),(a,b,c),return) SDL_X11_SYM(int,XSetWindowBackgroundPixmap,(Display* a,Window b,Pixmap c),(a,b,c),return) SDL_X11_SYM(int,XSetWindowColormap,(Display* a,Window b,Colormap c),(a,b,c),return) +SDL_X11_SYM(int,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),return) +SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),) +SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return) SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return) SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return) SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return) diff -r dbf3fa541096 -r 15d2c6f40c48 src/video/x11/SDL_x11video.c --- a/src/video/x11/SDL_x11video.c Mon Jul 12 00:35:24 2010 -0700 +++ b/src/video/x11/SDL_x11video.c Mon Jul 12 00:36:55 2010 -0700 @@ -21,6 +21,8 @@ */ #include "SDL_config.h" +#include /* For getpid() and readlink() */ + #include "SDL_video.h" #include "SDL_mouse.h" #include "../SDL_sysvideo.h" @@ -225,6 +227,10 @@ device->GL_DeleteContext = X11_GLES_DeleteContext; #endif + device->SetClipboardText = X11_SetClipboardText; + device->GetClipboardText = X11_GetClipboardText; + device->HasClipboardText = X11_HasClipboardText; + device->free = X11_DeleteDevice; return device; diff -r dbf3fa541096 -r 15d2c6f40c48 src/video/x11/SDL_x11video.h --- a/src/video/x11/SDL_x11video.h Mon Jul 12 00:35:24 2010 -0700 +++ b/src/video/x11/SDL_x11video.h Mon Jul 12 00:36:55 2010 -0700 @@ -48,6 +48,7 @@ #include "SDL_x11dyn.h" +#include "SDL_x11clipboard.h" #include "SDL_x11events.h" #include "SDL_x11gamma.h" #include "SDL_x11keyboard.h" @@ -69,6 +70,7 @@ int windowlistlength; Atom WM_DELETE_WINDOW; SDL_scancode key_layout[256]; + SDL_bool selection_waiting; } SDL_VideoData; extern SDL_bool X11_UseDirectColorVisuals(void);