Added X11 clipboard support.
authorSam Lantinga <slouken@libsdl.org>
Mon, 12 Jul 2010 00:36:55 -0700
changeset 450815d2c6f40c48
parent 4507 dbf3fa541096
child 4509 8e91c3947210
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.
src/video/x11/SDL_x11clipboard.c
src/video/x11/SDL_x11clipboard.h
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11sym.h
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/video/x11/SDL_x11clipboard.c	Mon Jul 12 00:36:55 2010 -0700
     1.3 @@ -0,0 +1,152 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997-2010 Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Lesser General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2.1 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Lesser General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Lesser General Public
    1.19 +    License along with this library; if not, write to the Free Software
    1.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@libsdl.org
    1.24 +*/
    1.25 +#include "SDL_config.h"
    1.26 +
    1.27 +#include <limits.h> /* For INT_MAX */
    1.28 +
    1.29 +#include "SDL_events.h"
    1.30 +#include "SDL_x11video.h"
    1.31 +
    1.32 +
    1.33 +/* Get any application owned window handle for clipboard association */
    1.34 +static Window
    1.35 +GetWindow(_THIS)
    1.36 +{
    1.37 +    SDL_VideoDisplay *display;
    1.38 +    SDL_Window *window;
    1.39 +
    1.40 +    display = _this->displays;
    1.41 +    if (display) {
    1.42 +        window = display->windows;
    1.43 +        if (window) {
    1.44 +            return ((SDL_WindowData *) window->driverdata)->xwindow;
    1.45 +        }
    1.46 +    }
    1.47 +    return None;
    1.48 +}
    1.49 +
    1.50 +int
    1.51 +X11_SetClipboardText(_THIS, const char *text)
    1.52 +{
    1.53 +    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
    1.54 +    Atom format;
    1.55 +    Window window;
    1.56 +
    1.57 +    /* Get the SDL window that will own the selection */
    1.58 +    window = GetWindow(_this);
    1.59 +    if (window == None) {
    1.60 +        SDL_SetError("Couldn't find a window to own the selection");
    1.61 +        return -1;
    1.62 +    }
    1.63 +
    1.64 +    /* If you don't support UTF-8, you might use XA_STRING here */
    1.65 +    format = XInternAtom(display, "UTF8_STRING", False);
    1.66 +    XChangeProperty(display, DefaultRootWindow(display),
    1.67 +        XA_CUT_BUFFER0, format, 8, PropModeReplace,
    1.68 +        (const unsigned char *)text, SDL_strlen(text));
    1.69 +
    1.70 +    if (XGetSelectionOwner(display, XA_PRIMARY) != window) {
    1.71 +        XSetSelectionOwner(display, XA_PRIMARY, window, CurrentTime);
    1.72 +    }
    1.73 +    return 0;
    1.74 +}
    1.75 +
    1.76 +char *
    1.77 +X11_GetClipboardText(_THIS)
    1.78 +{
    1.79 +    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    1.80 +    Display *display = videodata->display;
    1.81 +    Atom format;
    1.82 +    Window window;
    1.83 +    Window owner;
    1.84 +    Atom selection;
    1.85 +    Atom seln_type;
    1.86 +    int seln_format;
    1.87 +    unsigned long nbytes;
    1.88 +    unsigned long overflow;
    1.89 +    unsigned char *src;
    1.90 +    char *text;
    1.91 +
    1.92 +    text = NULL;
    1.93 +
    1.94 +    /* Get the SDL window that will own the selection */
    1.95 +    window = GetWindow(_this);
    1.96 +
    1.97 +    /* If you don't support UTF-8, you might use XA_STRING here */
    1.98 +    format = XInternAtom(display, "UTF8_STRING", False);
    1.99 +
   1.100 +    owner = XGetSelectionOwner(display, XA_PRIMARY);
   1.101 +    if ((owner == None) || (owner == window)) {
   1.102 +        owner = DefaultRootWindow(display);
   1.103 +        selection = XA_CUT_BUFFER0;
   1.104 +    } else {
   1.105 +        /* Request that the selection owner copy the data to our window */
   1.106 +        owner = window;
   1.107 +        selection = XInternAtom(display, "SDL_SELECTION", False);
   1.108 +        XConvertSelection(display, XA_PRIMARY, format, selection, owner,
   1.109 +            CurrentTime);
   1.110 +
   1.111 +        /* FIXME: Should we have a timeout here? */
   1.112 +        videodata->selection_waiting = SDL_TRUE;
   1.113 +        while (videodata->selection_waiting) {
   1.114 +            SDL_PumpEvents();
   1.115 +        }
   1.116 +    }
   1.117 +
   1.118 +    if (XGetWindowProperty(display, owner, selection, 0, INT_MAX/4, False,
   1.119 +            format, &seln_type, &seln_format, &nbytes, &overflow, &src)
   1.120 +            == Success) {
   1.121 +        if (seln_type == format) {
   1.122 +            text = (char *)SDL_malloc(nbytes+1);
   1.123 +            if (text) {
   1.124 +                SDL_memcpy(text, src, nbytes);
   1.125 +                text[nbytes] = '\0';
   1.126 +            }
   1.127 +        }
   1.128 +        XFree(src);
   1.129 +    }
   1.130 +
   1.131 +    if (!text) {
   1.132 +        text = SDL_strdup("");
   1.133 +    }
   1.134 +    return text;
   1.135 +}
   1.136 +
   1.137 +SDL_bool
   1.138 +X11_HasClipboardText(_THIS)
   1.139 +{
   1.140 +    /* Not an easy way to tell with X11, as far as I know... */
   1.141 +    char *text;
   1.142 +    SDL_bool retval;
   1.143 +
   1.144 +    text = X11_GetClipboardText(_this);
   1.145 +    if (*text) {
   1.146 +        retval = SDL_TRUE;
   1.147 +    } else {
   1.148 +        retval = SDL_FALSE;
   1.149 +    }
   1.150 +    SDL_free(text);
   1.151 +
   1.152 +    return retval;
   1.153 +}
   1.154 +
   1.155 +/* vi: set ts=4 sw=4 expandtab: */
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/video/x11/SDL_x11clipboard.h	Mon Jul 12 00:36:55 2010 -0700
     2.3 @@ -0,0 +1,33 @@
     2.4 +/*
     2.5 +    SDL - Simple DirectMedia Layer
     2.6 +    Copyright (C) 1997-2010 Sam Lantinga
     2.7 +
     2.8 +    This library is free software; you can redistribute it and/or
     2.9 +    modify it under the terms of the GNU Lesser General Public
    2.10 +    License as published by the Free Software Foundation; either
    2.11 +    version 2.1 of the License, or (at your option) any later version.
    2.12 +
    2.13 +    This library is distributed in the hope that it will be useful,
    2.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.16 +    Lesser General Public License for more details.
    2.17 +
    2.18 +    You should have received a copy of the GNU Lesser General Public
    2.19 +    License along with this library; if not, write to the Free Software
    2.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    2.21 +
    2.22 +    Sam Lantinga
    2.23 +    slouken@libsdl.org
    2.24 +*/
    2.25 +#include "SDL_config.h"
    2.26 +
    2.27 +#ifndef _SDL_x11clipboard_h
    2.28 +#define _SDL_x11clipboard_h
    2.29 +
    2.30 +extern int X11_SetClipboardText(_THIS, const char *text);
    2.31 +extern char *X11_GetClipboardText(_THIS);
    2.32 +extern SDL_bool X11_HasClipboardText(_THIS);
    2.33 +
    2.34 +#endif /* _SDL_x11clipboard_h */
    2.35 +
    2.36 +/* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/video/x11/SDL_x11events.c	Mon Jul 12 00:35:24 2010 -0700
     3.2 +++ b/src/video/x11/SDL_x11events.c	Mon Jul 12 00:36:55 2010 -0700
     3.3 @@ -25,6 +25,7 @@
     3.4  #include <sys/time.h>
     3.5  #include <signal.h>
     3.6  #include <unistd.h>
     3.7 +#include <limits.h>	/* For INT_MAX */
     3.8  
     3.9  #include "SDL_x11video.h"
    3.10  #include "../../events/SDL_events_c.h"
    3.11 @@ -33,6 +34,8 @@
    3.12  #include "SDL_timer.h"
    3.13  #include "SDL_syswm.h"
    3.14  
    3.15 +/*#define DEBUG_XEVENTS*/
    3.16 +
    3.17  static void
    3.18  X11_DispatchEvent(_THIS)
    3.19  {
    3.20 @@ -286,6 +289,55 @@
    3.21          }
    3.22          break;
    3.23  
    3.24 +    /* Copy the selection from XA_CUT_BUFFER0 to the requested property */
    3.25 +    case SelectionRequest: {
    3.26 +            Display *display = videodata->display;
    3.27 +            XSelectionRequestEvent *req;
    3.28 +            XEvent sevent;
    3.29 +            int seln_format;
    3.30 +            unsigned long nbytes;
    3.31 +            unsigned long overflow;
    3.32 +            unsigned char *seln_data;
    3.33 +
    3.34 +            req = &xevent.xselectionrequest;
    3.35 +#ifdef DEBUG_XEVENTS
    3.36 +            printf("SelectionRequest (requestor = %ld, target = %ld)\n",
    3.37 +                req->requestor, req->target);
    3.38 +#endif
    3.39 +
    3.40 +            sevent.xselection.type = SelectionNotify;
    3.41 +            sevent.xselection.display = req->display;
    3.42 +            sevent.xselection.selection = req->selection;
    3.43 +            sevent.xselection.target = None;
    3.44 +            sevent.xselection.property = None;
    3.45 +            sevent.xselection.requestor = req->requestor;
    3.46 +            sevent.xselection.time = req->time;
    3.47 +            if (XGetWindowProperty(display, DefaultRootWindow(display),
    3.48 +                    XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target,
    3.49 +                    &sevent.xselection.target, &seln_format, &nbytes,
    3.50 +                    &overflow, &seln_data) == Success) {
    3.51 +                if (sevent.xselection.target == req->target) {
    3.52 +                    XChangeProperty(display, req->requestor, req->property,
    3.53 +                        sevent.xselection.target, seln_format, PropModeReplace,
    3.54 +                        seln_data, nbytes);
    3.55 +                    sevent.xselection.property = req->property;
    3.56 +                }
    3.57 +                XFree(seln_data);
    3.58 +            }
    3.59 +            XSendEvent(display, req->requestor, False, 0, &sevent);
    3.60 +            XSync(display, False);
    3.61 +        }
    3.62 +        break;
    3.63 +
    3.64 +    case SelectionNotify: {
    3.65 +#ifdef DEBUG_XEVENTS
    3.66 +            printf("SelectionNotify (requestor = %ld, target = %ld)\n",
    3.67 +                xevent.xselection.requestor, xevent.xselection.target);
    3.68 +#endif
    3.69 +            videodata->selection_waiting = SDL_FALSE;
    3.70 +        }
    3.71 +        break;
    3.72 +
    3.73      default:{
    3.74  #ifdef DEBUG_XEVENTS
    3.75              printf("Unhandled event %d\n", xevent.type);
     4.1 --- a/src/video/x11/SDL_x11sym.h	Mon Jul 12 00:35:24 2010 -0700
     4.2 +++ b/src/video/x11/SDL_x11sym.h	Mon Jul 12 00:36:55 2010 -0700
     4.3 @@ -37,6 +37,7 @@
     4.4  SDL_X11_SYM(Bool,XCheckWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return)
     4.5  SDL_X11_SYM(int,XClearWindow,(Display* a,Window b),(a,b),return)
     4.6  SDL_X11_SYM(int,XCloseDisplay,(Display* a),(a),return)
     4.7 +SDL_X11_SYM(int,XConvertSelection,(Display* a,Atom b,Atom c,Atom d,Window e,Time f),(a,b,c,d,e,f),return)
     4.8  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)
     4.9  SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return)
    4.10  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)
    4.11 @@ -71,10 +72,11 @@
    4.12  SDL_X11_SYM(XModifierKeymap*,XGetModifierMapping,(Display* a),(a),return)
    4.13  SDL_X11_SYM(int,XGetPointerControl,(Display* a,int* b,int* c,int* d),(a,b,c,d),return)
    4.14  SDL_X11_SYM(int,XGetRGBColormaps,(Display* a,Window b,XStandardColormap **c,int *d,Atom e),(a,b,c,d,e),return)
    4.15 +SDL_X11_SYM(Window,XGetSelectionOwner,(Display* a,Atom b),(a,b),return)
    4.16  SDL_X11_SYM(XVisualInfo*,XGetVisualInfo,(Display* a,long b,XVisualInfo* c,int* d),(a,b,c,d),return)
    4.17 -SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),return)
    4.18  SDL_X11_SYM(Status,XGetWindowAttributes,(Display* a,Window b,XWindowAttributes* c),(a,b,c),return)
    4.19  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)
    4.20 +SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),return)
    4.21  SDL_X11_SYM(int,XGrabKeyboard,(Display* a,Window b,Bool c,int d,int e,Time f),(a,b,c,d,e,f),return)
    4.22  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)
    4.23  SDL_X11_SYM(int,XGrabServer,(Display* a),(a),return)
    4.24 @@ -114,14 +116,15 @@
    4.25  SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return)
    4.26  SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return)
    4.27  SDL_X11_SYM(void,XSetRGBColormaps,( Display *a,Window b,XStandardColormap *c,int d,Atom e),(a,b,c,d,e),return)
    4.28 +SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d),return)
    4.29  SDL_X11_SYM(int,XSetTransientForHint,(Display* a,Window b,Window c),(a,b,c),return)
    4.30 -SDL_X11_SYM(int,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),return)
    4.31  SDL_X11_SYM(void,XSetTextProperty,(Display* a,Window b,XTextProperty* c,Atom d),(a,b,c,d),)
    4.32 -SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),)
    4.33 -SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return)
    4.34  SDL_X11_SYM(int,XSetWindowBackground,(Display* a,Window b,unsigned long c),(a,b,c),return)
    4.35  SDL_X11_SYM(int,XSetWindowBackgroundPixmap,(Display* a,Window b,Pixmap c),(a,b,c),return)
    4.36  SDL_X11_SYM(int,XSetWindowColormap,(Display* a,Window b,Colormap c),(a,b,c),return)
    4.37 +SDL_X11_SYM(int,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),return)
    4.38 +SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),)
    4.39 +SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return)
    4.40  SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return)
    4.41  SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return)
    4.42  SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return)
     5.1 --- a/src/video/x11/SDL_x11video.c	Mon Jul 12 00:35:24 2010 -0700
     5.2 +++ b/src/video/x11/SDL_x11video.c	Mon Jul 12 00:36:55 2010 -0700
     5.3 @@ -21,6 +21,8 @@
     5.4  */
     5.5  #include "SDL_config.h"
     5.6  
     5.7 +#include <unistd.h> /* For getpid() and readlink() */
     5.8 +
     5.9  #include "SDL_video.h"
    5.10  #include "SDL_mouse.h"
    5.11  #include "../SDL_sysvideo.h"
    5.12 @@ -225,6 +227,10 @@
    5.13      device->GL_DeleteContext = X11_GLES_DeleteContext;
    5.14  #endif
    5.15  
    5.16 +    device->SetClipboardText = X11_SetClipboardText;
    5.17 +    device->GetClipboardText = X11_GetClipboardText;
    5.18 +    device->HasClipboardText = X11_HasClipboardText;
    5.19 +
    5.20      device->free = X11_DeleteDevice;
    5.21  
    5.22      return device;
     6.1 --- a/src/video/x11/SDL_x11video.h	Mon Jul 12 00:35:24 2010 -0700
     6.2 +++ b/src/video/x11/SDL_x11video.h	Mon Jul 12 00:36:55 2010 -0700
     6.3 @@ -48,6 +48,7 @@
     6.4  
     6.5  #include "SDL_x11dyn.h"
     6.6  
     6.7 +#include "SDL_x11clipboard.h"
     6.8  #include "SDL_x11events.h"
     6.9  #include "SDL_x11gamma.h"
    6.10  #include "SDL_x11keyboard.h"
    6.11 @@ -69,6 +70,7 @@
    6.12      int windowlistlength;
    6.13      Atom WM_DELETE_WINDOW;
    6.14      SDL_scancode key_layout[256];
    6.15 +    SDL_bool selection_waiting;
    6.16  } SDL_VideoData;
    6.17  
    6.18  extern SDL_bool X11_UseDirectColorVisuals(void);