SDL_x11clipboard.c (5524B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 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_internal.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#include "SDL_timer.h" 30 31 32/* If you don't support UTF-8, you might use XA_STRING here */ 33#ifdef X_HAVE_UTF8_STRING 34#define TEXT_FORMAT X11_XInternAtom(display, "UTF8_STRING", False) 35#else 36#define TEXT_FORMAT XA_STRING 37#endif 38 39/* Get any application owned window handle for clipboard association */ 40static Window 41GetWindow(_THIS) 42{ 43 SDL_Window *window; 44 45 window = _this->windows; 46 if (window) { 47 return ((SDL_WindowData *) window->driverdata)->xwindow; 48 } 49 return None; 50} 51 52int 53X11_SetClipboardText(_THIS, const char *text) 54{ 55 Display *display = ((SDL_VideoData *) _this->driverdata)->display; 56 Atom format; 57 Window window; 58 Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0); 59 60 /* Get the SDL window that will own the selection */ 61 window = GetWindow(_this); 62 if (window == None) { 63 return SDL_SetError("Couldn't find a window to own the selection"); 64 } 65 66 /* Save the selection on the root window */ 67 format = TEXT_FORMAT; 68 X11_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 X11_XGetSelectionOwner(display, XA_CLIPBOARD) != window) { 74 X11_XSetSelectionOwner(display, XA_CLIPBOARD, window, CurrentTime); 75 } 76 77 if (X11_XGetSelectionOwner(display, XA_PRIMARY) != window) { 78 X11_XSetSelectionOwner(display, XA_PRIMARY, window, CurrentTime); 79 } 80 return 0; 81} 82 83char * 84X11_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 Uint32 waitStart; 99 Uint32 waitElapsed; 100 Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0); 101 if (XA_CLIPBOARD == None) { 102 SDL_SetError("Couldn't access X clipboard"); 103 return SDL_strdup(""); 104 } 105 106 text = NULL; 107 108 /* Get the window that holds the selection */ 109 window = GetWindow(_this); 110 format = TEXT_FORMAT; 111 owner = X11_XGetSelectionOwner(display, XA_CLIPBOARD); 112 if ((owner == None) || (owner == window)) { 113 owner = DefaultRootWindow(display); 114 selection = XA_CUT_BUFFER0; 115 } else { 116 /* Request that the selection owner copy the data to our window */ 117 owner = window; 118 selection = X11_XInternAtom(display, "SDL_SELECTION", False); 119 X11_XConvertSelection(display, XA_CLIPBOARD, format, selection, owner, 120 CurrentTime); 121 122 /* When using synergy on Linux and when data has been put in the clipboard 123 on the remote (Windows anyway) machine then selection_waiting may never 124 be set to False. Time out after a while. */ 125 waitStart = SDL_GetTicks(); 126 videodata->selection_waiting = SDL_TRUE; 127 while (videodata->selection_waiting) { 128 SDL_PumpEvents(); 129 waitElapsed = SDL_GetTicks() - waitStart; 130 /* Wait one second for a clipboard response. */ 131 if (waitElapsed > 1000) { 132 videodata->selection_waiting = SDL_FALSE; 133 SDL_SetError("Clipboard timeout"); 134 /* We need to set the clipboard text so that next time we won't 135 timeout, otherwise we will hang on every call to this function. */ 136 X11_SetClipboardText(_this, ""); 137 return SDL_strdup(""); 138 } 139 } 140 } 141 142 if (X11_XGetWindowProperty(display, owner, selection, 0, INT_MAX/4, False, 143 format, &seln_type, &seln_format, &nbytes, &overflow, &src) 144 == Success) { 145 if (seln_type == format) { 146 text = (char *)SDL_malloc(nbytes+1); 147 if (text) { 148 SDL_memcpy(text, src, nbytes); 149 text[nbytes] = '\0'; 150 } 151 } 152 X11_XFree(src); 153 } 154 155 if (!text) { 156 text = SDL_strdup(""); 157 } 158 159 return text; 160} 161 162SDL_bool 163X11_HasClipboardText(_THIS) 164{ 165 SDL_bool result = SDL_FALSE; 166 char *text = X11_GetClipboardText(_this); 167 if (text) { 168 result = text[0] != '\0' ? SDL_TRUE : SDL_FALSE; 169 SDL_free(text); 170 } 171 return result; 172} 173 174#endif /* SDL_VIDEO_DRIVER_X11 */ 175 176/* vi: set ts=4 sw=4 expandtab: */