src/video/x11/SDL_x11clipboard.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 20 Jul 2010 00:57:01 -0700
changeset 4559 f8c3870af5a2
parent 4516 f18bc9935507
child 5246 58265e606e4e
permissions -rw-r--r--
Fixed X11 error when running under window managers that don't support the _NET_SUPPORTING_WM_CHECK protocol.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include <limits.h> /* For INT_MAX */
    25 
    26 #include "SDL_events.h"
    27 #include "SDL_x11video.h"
    28 
    29 
    30 /* If you don't support UTF-8, you might use XA_STRING here */
    31 #ifdef X_HAVE_UTF8_STRING
    32 #define TEXT_FORMAT XInternAtom(display, "UTF8_STRING", False)
    33 #else
    34 #define TEXT_FORMAT XA_STRING
    35 #endif
    36 
    37 /* Get any application owned window handle for clipboard association */
    38 static Window
    39 GetWindow(_THIS)
    40 {
    41     SDL_VideoDisplay *display;
    42     SDL_Window *window;
    43 
    44     display = _this->displays;
    45     if (display) {
    46         window = display->windows;
    47         if (window) {
    48             return ((SDL_WindowData *) window->driverdata)->xwindow;
    49         }
    50     }
    51     return None;
    52 }
    53 
    54 int
    55 X11_SetClipboardText(_THIS, const char *text)
    56 {
    57     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
    58     Atom format;
    59     Window window;
    60 
    61     /* Get the SDL window that will own the selection */
    62     window = GetWindow(_this);
    63     if (window == None) {
    64         SDL_SetError("Couldn't find a window to own the selection");
    65         return -1;
    66     }
    67 
    68     /* Save the selection on the root window */
    69     format = TEXT_FORMAT;
    70     XChangeProperty(display, DefaultRootWindow(display),
    71         XA_CUT_BUFFER0, format, 8, PropModeReplace,
    72         (const unsigned char *)text, SDL_strlen(text));
    73 
    74     if (XGetSelectionOwner(display, XA_PRIMARY) != window) {
    75         XSetSelectionOwner(display, XA_PRIMARY, window, CurrentTime);
    76     }
    77     return 0;
    78 }
    79 
    80 char *
    81 X11_GetClipboardText(_THIS)
    82 {
    83     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    84     Display *display = videodata->display;
    85     Atom format;
    86     Window window;
    87     Window owner;
    88     Atom selection;
    89     Atom seln_type;
    90     int seln_format;
    91     unsigned long nbytes;
    92     unsigned long overflow;
    93     unsigned char *src;
    94     char *text;
    95 
    96     text = NULL;
    97 
    98     /* Get the window that holds the selection */
    99     window = GetWindow(_this);
   100     format = TEXT_FORMAT;
   101     owner = XGetSelectionOwner(display, XA_PRIMARY);
   102     if ((owner == None) || (owner == window)) {
   103         owner = DefaultRootWindow(display);
   104         selection = XA_CUT_BUFFER0;
   105     } else {
   106         /* Request that the selection owner copy the data to our window */
   107         owner = window;
   108         selection = XInternAtom(display, "SDL_SELECTION", False);
   109         XConvertSelection(display, XA_PRIMARY, format, selection, owner,
   110             CurrentTime);
   111 
   112         /* FIXME: Should we have a timeout here? */
   113         videodata->selection_waiting = SDL_TRUE;
   114         while (videodata->selection_waiting) {
   115             SDL_PumpEvents();
   116         }
   117     }
   118 
   119     if (XGetWindowProperty(display, owner, selection, 0, INT_MAX/4, False,
   120             format, &seln_type, &seln_format, &nbytes, &overflow, &src)
   121             == Success) {
   122         if (seln_type == format) {
   123             text = (char *)SDL_malloc(nbytes+1);
   124             if (text) {
   125                 SDL_memcpy(text, src, nbytes);
   126                 text[nbytes] = '\0';
   127             }
   128         }
   129         XFree(src);
   130     }
   131 
   132     if (!text) {
   133         text = SDL_strdup("");
   134     }
   135     return text;
   136 }
   137 
   138 SDL_bool
   139 X11_HasClipboardText(_THIS)
   140 {
   141     /* Not an easy way to tell with X11, as far as I know... */
   142     char *text;
   143     SDL_bool retval;
   144 
   145     text = X11_GetClipboardText(_this);
   146     if (*text) {
   147         retval = SDL_TRUE;
   148     } else {
   149         retval = SDL_FALSE;
   150     }
   151     SDL_free(text);
   152 
   153     return retval;
   154 }
   155 
   156 /* vi: set ts=4 sw=4 expandtab: */