src/video/x11/SDL_x11clipboard.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 07 Dec 2012 23:26:28 -0500
changeset 6724 6c5ed0c4cc6d
parent 6420 6f52dc57f05e
child 6885 700f1b25f77f
permissions -rw-r--r--
X11 msgbox: try to protect the existing setlocale() state.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_X11
    24 
    25 #include <limits.h> /* For INT_MAX */
    26 
    27 #include "SDL_events.h"
    28 #include "SDL_x11video.h"
    29 
    30 
    31 /* If you don't support UTF-8, you might use XA_STRING here */
    32 #ifdef X_HAVE_UTF8_STRING
    33 #define TEXT_FORMAT XInternAtom(display, "UTF8_STRING", False)
    34 #else
    35 #define TEXT_FORMAT XA_STRING
    36 #endif
    37 
    38 /* Get any application owned window handle for clipboard association */
    39 static Window
    40 GetWindow(_THIS)
    41 {
    42     SDL_Window *window;
    43 
    44     window = _this->windows;
    45     if (window) {
    46         return ((SDL_WindowData *) window->driverdata)->xwindow;
    47     }
    48     return None;
    49 }
    50 
    51 int
    52 X11_SetClipboardText(_THIS, const char *text)
    53 {
    54     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
    55     Atom format;
    56     Window window;
    57     Atom XA_CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0);
    58 
    59     /* Get the SDL window that will own the selection */
    60     window = GetWindow(_this);
    61     if (window == None) {
    62         SDL_SetError("Couldn't find a window to own the selection");
    63         return -1;
    64     }
    65 
    66     /* Save the selection on the root window */
    67     format = TEXT_FORMAT;
    68     XChangeProperty(display, DefaultRootWindow(display),
    69         XA_CUT_BUFFER0, format, 8, PropModeReplace,
    70         (const unsigned char *)text, SDL_strlen(text));
    71 
    72     if (XA_CLIPBOARD != None &&
    73         XGetSelectionOwner(display, XA_CLIPBOARD) != window) {
    74         XSetSelectionOwner(display, XA_CLIPBOARD, window, CurrentTime);
    75     }
    76 
    77     if (XGetSelectionOwner(display, XA_PRIMARY) != window) {
    78         XSetSelectionOwner(display, XA_PRIMARY, window, CurrentTime);
    79     }
    80     return 0;
    81 }
    82 
    83 char *
    84 X11_GetClipboardText(_THIS)
    85 {
    86     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    87     Display *display = videodata->display;
    88     Atom format;
    89     Window window;
    90     Window owner;
    91     Atom selection;
    92     Atom seln_type;
    93     int seln_format;
    94     unsigned long nbytes;
    95     unsigned long overflow;
    96     unsigned char *src;
    97     char *text;
    98     Atom XA_CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0);
    99     if (XA_CLIPBOARD == None) {
   100         SDL_SetError("Couldn't access X clipboard");
   101         return NULL;
   102     }
   103 
   104     text = NULL;
   105 
   106     /* Get the window that holds the selection */
   107     window = GetWindow(_this);
   108     format = TEXT_FORMAT;
   109     owner = XGetSelectionOwner(display, XA_CLIPBOARD);
   110     if ((owner == None) || (owner == window)) {
   111         owner = DefaultRootWindow(display);
   112         selection = XA_CUT_BUFFER0;
   113     } else {
   114         /* Request that the selection owner copy the data to our window */
   115         owner = window;
   116         selection = XInternAtom(display, "SDL_SELECTION", False);
   117         XConvertSelection(display, XA_CLIPBOARD, format, selection, owner,
   118             CurrentTime);
   119 
   120         /* FIXME: Should we have a timeout here? */
   121         videodata->selection_waiting = SDL_TRUE;
   122         while (videodata->selection_waiting) {
   123             SDL_PumpEvents();
   124         }
   125     }
   126 
   127     if (XGetWindowProperty(display, owner, selection, 0, INT_MAX/4, False,
   128             format, &seln_type, &seln_format, &nbytes, &overflow, &src)
   129             == Success) {
   130         if (seln_type == format) {
   131             text = (char *)SDL_malloc(nbytes+1);
   132             if (text) {
   133                 SDL_memcpy(text, src, nbytes);
   134                 text[nbytes] = '\0';
   135             }
   136         }
   137         XFree(src);
   138     }
   139 
   140     if (!text) {
   141         text = SDL_strdup("");
   142     }
   143     
   144     return text;
   145 }
   146 
   147 SDL_bool
   148 X11_HasClipboardText(_THIS)
   149 {
   150     SDL_bool result = SDL_FALSE;
   151     char *text = X11_GetClipboardText(_this);
   152     if (text) {
   153         result = (SDL_strlen(text)>0) ? SDL_TRUE : SDL_FALSE;
   154         SDL_free(text);
   155     }    
   156     return result;
   157 }
   158 
   159 #endif /* SDL_VIDEO_DRIVER_X11 */
   160 
   161 /* vi: set ts=4 sw=4 expandtab: */