aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llwindow
diff options
context:
space:
mode:
authorArmin Weatherwax2009-06-08 11:10:27 +0200
committerMcCabe Maxsted2009-09-04 11:34:24 -0700
commit3f0082a9dda60432b8b759e09f19b495d9d5275c (patch)
tree989f5e10f9b9891ec7718b5ee2406582b6c0e352 /linden/indra/llwindow
parentRebranded startup loading page to Imprudence (diff)
downloadmeta-impy-3f0082a9dda60432b8b759e09f19b495d9d5275c.zip
meta-impy-3f0082a9dda60432b8b759e09f19b495d9d5275c.tar.gz
meta-impy-3f0082a9dda60432b8b759e09f19b495d9d5275c.tar.bz2
meta-impy-3f0082a9dda60432b8b759e09f19b495d9d5275c.tar.xz
Linux middle mouse button paste/primary selection support and gtk clipboard handler (fixes crashbug using synergy mouse-keyboard-clipboard-sharing over lan)
modified: linden/doc/contributions.txt modified: linden/indra/llui/llclipboard.cpp modified: linden/indra/llui/llclipboard.h modified: linden/indra/llui/llfloater.cpp modified: linden/indra/llui/llfloater.h modified: linden/indra/llui/lllineeditor.cpp modified: linden/indra/llui/lllineeditor.h modified: linden/indra/llui/lltexteditor.cpp modified: linden/indra/llui/lltexteditor.h modified: linden/indra/llui/llview.cpp modified: linden/indra/llui/llview.h modified: linden/indra/llwindow/CMakeLists.txt new file: linden/indra/llwindow/llmousehandler.cpp modified: linden/indra/llwindow/llmousehandler.h modified: linden/indra/llwindow/llwindow.cpp modified: linden/indra/llwindow/llwindow.h modified: linden/indra/llwindow/llwindowsdl.cpp modified: linden/indra/llwindow/llwindowsdl.h modified: linden/indra/newview/lltool.cpp modified: linden/indra/newview/lltool.h modified: linden/indra/newview/llviewertexteditor.cpp modified: linden/indra/newview/llviewertexteditor.h modified: linden/indra/newview/llviewerwindow.cpp modified: linden/indra/newview/llviewerwindow.h (cherry picked from commit 594f4830922f4294dda432fa748935adffaeed8f)
Diffstat (limited to '')
-rw-r--r--linden/indra/llwindow/CMakeLists.txt1
-rw-r--r--linden/indra/llwindow/llmousehandler.cpp59
-rw-r--r--linden/indra/llwindow/llmousehandler.h21
-rw-r--r--linden/indra/llwindow/llwindow.cpp16
-rw-r--r--linden/indra/llwindow/llwindow.h6
-rw-r--r--linden/indra/llwindow/llwindowsdl.cpp570
-rw-r--r--linden/indra/llwindow/llwindowsdl.h13
7 files changed, 204 insertions, 482 deletions
diff --git a/linden/indra/llwindow/CMakeLists.txt b/linden/indra/llwindow/CMakeLists.txt
index 95e315f..afce0c0 100644
--- a/linden/indra/llwindow/CMakeLists.txt
+++ b/linden/indra/llwindow/CMakeLists.txt
@@ -46,6 +46,7 @@ set(llwindows_HEADER_FILES
46 46
47set(viewer_SOURCE_FILES 47set(viewer_SOURCE_FILES
48 llwindow.cpp 48 llwindow.cpp
49 llmousehandler.cpp
49 ) 50 )
50 51
51set(viewer_HEADER_FILES 52set(viewer_HEADER_FILES
diff --git a/linden/indra/llwindow/llmousehandler.cpp b/linden/indra/llwindow/llmousehandler.cpp
new file mode 100644
index 0000000..ae2f147
--- /dev/null
+++ b/linden/indra/llwindow/llmousehandler.cpp
@@ -0,0 +1,59 @@
1/**
2 * @file llmousehandler.cpp
3 * @brief LLMouseHandler class implementation
4 *
5 * $LicenseInfo:firstyear=2001&license=viewergpl$
6 *
7 * Copyright (c) 2001-2007, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32#include "llmousehandler.h"
33
34//virtual
35BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
36{
37 BOOL handled = FALSE;
38 if (down)
39 {
40 switch (clicktype)
41 {
42 case CLICK_LEFT: handled = handleMouseDown(x, y, mask); break;
43 case CLICK_RIGHT: handled = handleRightMouseDown(x, y, mask); break;
44 case CLICK_MIDDLE: handled = handleMiddleMouseDown(x, y, mask); break;
45 case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
46 }
47 }
48 else
49 {
50 switch (clicktype)
51 {
52 case CLICK_LEFT: handled = handleMouseUp(x, y, mask); break;
53 case CLICK_RIGHT: handled = handleRightMouseUp(x, y, mask); break;
54 case CLICK_MIDDLE: handled = handleMiddleMouseUp(x, y, mask); break;
55 case CLICK_DOUBLELEFT: handled = handleDoubleClick(x, y, mask); break;
56 }
57 }
58 return handled;
59}
diff --git a/linden/indra/llwindow/llmousehandler.h b/linden/indra/llwindow/llmousehandler.h
index dba1fc1..45f837b 100644
--- a/linden/indra/llwindow/llmousehandler.h
+++ b/linden/indra/llwindow/llmousehandler.h
@@ -32,9 +32,10 @@
32#ifndef LL_MOUSEHANDLER_H 32#ifndef LL_MOUSEHANDLER_H
33#define LL_MOUSEHANDLER_H 33#define LL_MOUSEHANDLER_H
34 34
35#include "llstring.h" 35#include "linden_common.h"
36#include "llrect.h"
36 37
37// Abstract interface. 38// Mostly-abstract interface.
38// Intended for use via multiple inheritance. 39// Intended for use via multiple inheritance.
39// A class may have as many interfaces as it likes, but never needs to inherit one more than once. 40// A class may have as many interfaces as it likes, but never needs to inherit one more than once.
40 41
@@ -48,13 +49,23 @@ public:
48 SHOW_IF_NOT_BLOCKED, 49 SHOW_IF_NOT_BLOCKED,
49 SHOW_ALWAYS, 50 SHOW_ALWAYS,
50 } EShowToolTip; 51 } EShowToolTip;
52 typedef enum {
53 CLICK_LEFT,
54 CLICK_MIDDLE,
55 CLICK_RIGHT,
56 CLICK_DOUBLELEFT
57 } EClickType;
58 virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
51 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0; 59 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0;
52 virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0; 60 virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0;
53 virtual BOOL handleHover(S32 x, S32 y, MASK mask) = 0; 61 virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) = 0;
54 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) = 0; 62 virtual BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) = 0;
55 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) = 0;
56 virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) = 0; 63 virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) = 0;
57 virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) = 0; 64 virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) = 0;
65 virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask) = 0;
66
67 virtual BOOL handleHover(S32 x, S32 y, MASK mask) = 0;
68 virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) = 0;
58 virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) = 0; 69 virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) = 0;
59 virtual EShowToolTip getShowToolTip() { return SHOW_IF_NOT_BLOCKED; }; 70 virtual EShowToolTip getShowToolTip() { return SHOW_IF_NOT_BLOCKED; };
60 virtual const std::string& getName() const = 0; 71 virtual const std::string& getName() const = 0;
diff --git a/linden/indra/llwindow/llwindow.cpp b/linden/indra/llwindow/llwindow.cpp
index 44908fb..b4c8ff0 100644
--- a/linden/indra/llwindow/llwindow.cpp
+++ b/linden/indra/llwindow/llwindow.cpp
@@ -307,6 +307,22 @@ void *LLWindow::getMediaWindow()
307 return getPlatformWindow(); 307 return getPlatformWindow();
308} 308}
309 309
310//virtual
311BOOL LLWindow::isPrimaryTextAvailable()
312{
313 return FALSE; // no
314}
315//virtual
316BOOL LLWindow::pasteTextFromPrimary(LLWString &dst)
317{
318 return FALSE; // fail
319}
320// virtual
321BOOL LLWindow::copyTextToPrimary(const LLWString &src)
322{
323 return FALSE; // fail
324}
325
310// static 326// static
311std::string LLWindow::getFontListSans() 327std::string LLWindow::getFontListSans()
312{ 328{
diff --git a/linden/indra/llwindow/llwindow.h b/linden/indra/llwindow/llwindow.h
index ffc117f..821de2f 100644
--- a/linden/indra/llwindow/llwindow.h
+++ b/linden/indra/llwindow/llwindow.h
@@ -184,9 +184,15 @@ public:
184 virtual void captureMouse() = 0; 184 virtual void captureMouse() = 0;
185 virtual void releaseMouse() = 0; 185 virtual void releaseMouse() = 0;
186 virtual void setMouseClipping( BOOL b ) = 0; 186 virtual void setMouseClipping( BOOL b ) = 0;
187
187 virtual BOOL isClipboardTextAvailable() = 0; 188 virtual BOOL isClipboardTextAvailable() = 0;
188 virtual BOOL pasteTextFromClipboard(LLWString &dst) = 0; 189 virtual BOOL pasteTextFromClipboard(LLWString &dst) = 0;
189 virtual BOOL copyTextToClipboard(const LLWString &src) = 0; 190 virtual BOOL copyTextToClipboard(const LLWString &src) = 0;
191
192 virtual BOOL isPrimaryTextAvailable();
193 virtual BOOL pasteTextFromPrimary(LLWString &dst);
194 virtual BOOL copyTextToPrimary(const LLWString &src);
195
190 virtual void flashIcon(F32 seconds) = 0; 196 virtual void flashIcon(F32 seconds) = 0;
191 virtual F32 getGamma() = 0; 197 virtual F32 getGamma() = 0;
192 virtual BOOL setGamma(const F32 gamma) = 0; // Set the gamma 198 virtual BOOL setGamma(const F32 gamma) = 0; // Set the gamma
diff --git a/linden/indra/llwindow/llwindowsdl.cpp b/linden/indra/llwindow/llwindowsdl.cpp
index 8111aaf..5209e6f 100644
--- a/linden/indra/llwindow/llwindowsdl.cpp
+++ b/linden/indra/llwindow/llwindowsdl.cpp
@@ -188,11 +188,12 @@ Display* LLWindowSDL::get_SDL_Display(void)
188 188
189 189
190LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width, 190LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width,
191 S32 height, U32 flags, 191 S32 height, U32 flags,
192 BOOL fullscreen, BOOL clearBg, 192 BOOL fullscreen, BOOL clearBg,
193 BOOL disable_vsync, BOOL use_gl, 193 BOOL disable_vsync, BOOL use_gl,
194 BOOL ignore_pixel_depth, U32 fsaa_samples) 194 BOOL ignore_pixel_depth, U32 fsaa_samples)
195 : LLWindow(fullscreen, flags), mGamma(1.0f) 195 : LLWindow(fullscreen, flags), Lock_Display(NULL),
196 Unlock_Display(NULL), mGamma(1.0f)
196{ 197{
197 // Initialize the keyboard 198 // Initialize the keyboard
198 gKeyboard = new LLKeyboardSDL(); 199 gKeyboard = new LLKeyboardSDL();
@@ -717,9 +718,33 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
717#endif 718#endif
718 719
719#if LL_X11 720#if LL_X11
720 init_x11clipboard(); 721 /* Grab the window manager specific information */
722 SDL_SysWMinfo info;
723 SDL_VERSION(&info.version);
724 if ( SDL_GetWMInfo(&info) )
725 {
726 /* Save the information for later use */
727 if ( info.subsystem == SDL_SYSWM_X11 )
728 {
729 mSDL_Display = info.info.x11.display;
730 mSDL_XWindowID = info.info.x11.wmwindow;
731 Lock_Display = info.info.x11.lock_func;
732 Unlock_Display = info.info.x11.unlock_func;
733 }
734 else
735 {
736 llwarns << "We're not running under X11? Wild."
737 << llendl;
738 }
739 }
740 else
741 {
742 llwarns << "We're not running under any known WM. Wild."
743 << llendl;
744 }
721#endif // LL_X11 745#endif // LL_X11
722 746
747
723 //make sure multisampling is disabled by default 748 //make sure multisampling is disabled by default
724 glDisable(GL_MULTISAMPLE_ARB); 749 glDisable(GL_MULTISAMPLE_ARB);
725 750
@@ -763,8 +788,12 @@ BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL
763void LLWindowSDL::destroyContext() 788void LLWindowSDL::destroyContext()
764{ 789{
765 llinfos << "destroyContext begins" << llendl; 790 llinfos << "destroyContext begins" << llendl;
791
766#if LL_X11 792#if LL_X11
767 quit_x11clipboard(); 793 mSDL_Display = NULL;
794 mSDL_XWindowID = None;
795 Lock_Display = NULL;
796 Unlock_Display = NULL;
768#endif // LL_X11 797#endif // LL_X11
769 798
770 // Clean up remaining GL state before blowing away window 799 // Clean up remaining GL state before blowing away window
@@ -1212,523 +1241,125 @@ void LLWindowSDL::flashIcon(F32 seconds)
1212#endif // LL_X11 1241#endif // LL_X11
1213} 1242}
1214 1243
1215#if LL_X11 1244#if LL_GTK
1216/* Lots of low-level X11 stuff to handle X11 copy-and-paste */ 1245BOOL LLWindowSDL::isClipboardTextAvailable()
1217
1218/* Our X11 clipboard support is a bit bizarre in various
1219 organically-grown ways. Ideally it should be fixed to do
1220 real string-type negotiation (this would make pasting to
1221 xterm faster and pasting to UTF-8 emacs work properly), but
1222 right now it has the rare and desirable trait of being
1223 generally stable and working. */
1224
1225typedef Atom x11clipboard_type;
1226
1227/* PRIMARY and CLIPBOARD are the two main kinds of
1228 X11 clipboard. A third are the CUT_BUFFERs which an
1229 obsolete holdover from X10 days and use a quite orthogonal
1230 mechanism. CLIPBOARD is the type whose design most
1231 closely matches SL's own win32-alike explicit copy-and-paste
1232 paradigm.
1233
1234 Pragmatically we support all three to varying degrees. When
1235 we paste into SL, it is strictly from CLIPBOARD. When we copy,
1236 we support (to as full an extent as the clipboard content type
1237 allows) CLIPBOARD, PRIMARY, and CUT_BUFFER0.
1238 */
1239static x11clipboard_type get_x11_readwrite_clipboard_type(void)
1240{
1241 return XInternAtom(LLWindowSDL::get_SDL_Display(), "CLIPBOARD", False);
1242}
1243
1244static x11clipboard_type get_x11_write_clipboard_type(void)
1245{
1246 return XA_PRIMARY;
1247}
1248
1249/* This is where our own private cutbuffer goes - we don't use
1250 a regular cutbuffer (XA_CUT_BUFFER0 etc) for intermediate
1251 storage because their use isn't really defined for holding UTF8. */
1252static x11clipboard_type get_x11_cutbuffer_clipboard_type(void)
1253{
1254 return XInternAtom(LLWindowSDL::get_SDL_Display(), "SECONDLIFE_CUTBUFFER", False);
1255}
1256
1257/* Some X11 atom-generators */
1258static Atom get_x11_targets_atom(void)
1259{
1260 return XInternAtom(LLWindowSDL::get_SDL_Display(), "TARGETS", False);
1261}
1262
1263static Atom get_x11_text_atom(void)
1264{
1265 return XInternAtom(LLWindowSDL::get_SDL_Display(), "TEXT", False);
1266}
1267
1268/* These defines, and convert_data/convert_x11clipboard,
1269 mostly exist to support non-text or unusually-encoded
1270 clipboard data, which we don't really have a need for at
1271 the moment. */
1272#define SDLCLIPTYPE(A, B, C, D) (int)(((A)<<24)|((B)<<16)|((C)<<8)|((D)<<0))
1273#define FORMAT_PREFIX "SECONDLIFE_x11clipboard_0x"
1274
1275static
1276x11clipboard_type convert_format(int type)
1277{ 1246{
1278 if (!gWindowImplementation) 1247 if (ll_try_gtk_init())
1279 { 1248 {
1280 llwarns << "!gWindowImplementation in convert_format()" 1249 GtkClipboard * const clipboard =
1281 << llendl; 1250 gtk_clipboard_get(GDK_NONE);
1282 return XA_STRING; 1251 return gtk_clipboard_wait_is_text_available(clipboard) ?
1283 } 1252 TRUE : FALSE;
1284
1285 switch (type)
1286 {
1287 case SDLCLIPTYPE('T', 'E', 'X', 'T'):
1288 // old-style X11 clipboard, strictly only ISO 8859-1 encoding
1289 return XA_STRING;
1290 case SDLCLIPTYPE('U', 'T', 'F', '8'):
1291 // newer de-facto UTF8 clipboard atom
1292 return XInternAtom(gWindowImplementation->mSDL_Display,
1293 "UTF8_STRING", False);
1294 default:
1295 {
1296 /* completely arbitrary clipboard types... we don't actually use
1297 these right now, and support is skeletal. */
1298 char format[sizeof(FORMAT_PREFIX)+8+1]; /* Flawfinder: ignore */
1299
1300 snprintf(format, sizeof(format), "%s%08lx", FORMAT_PREFIX, (unsigned long)type);
1301 return XInternAtom(gWindowImplementation->mSDL_Display,
1302 format, False);
1303 } 1253 }
1304 } 1254 return FALSE; // failure
1305} 1255}
1306 1256
1307/* convert platform string to x11 clipboard format. for our 1257BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &text)
1308 purposes this is pretty trivial right now. */
1309static int
1310convert_data(int type, char *dst, const char *src, int srclen)
1311{ 1258{
1312 int dstlen; 1259 if (ll_try_gtk_init())
1313
1314 dstlen = 0;
1315 switch (type)
1316 { 1260 {
1317 case SDLCLIPTYPE('T', 'E', 'X', 'T'): 1261 GtkClipboard * const clipboard =
1318 case SDLCLIPTYPE('U', 'T', 'F', '8'): 1262 gtk_clipboard_get(GDK_NONE);
1319 if (src == NULL) 1263 gchar * const data = gtk_clipboard_wait_for_text(clipboard);
1320 { 1264 if (data)
1321 break;
1322 }
1323 if ( srclen == 0 )
1324 srclen = strlen(src); /* Flawfinder: ignore */
1325
1326 dstlen = srclen + 1;
1327
1328 if ( dst ) // assume caller made it big enough by asking us
1329 { 1265 {
1330 memcpy(dst, src, srclen); /* Flawfinder: ignore */ 1266 text = LLWString(utf8str_to_wstring(data));
1331 dst[srclen] = '\0'; 1267 g_free(data);
1268 return TRUE;
1332 } 1269 }
1333 break;
1334
1335 default:
1336 llwarns << "convert_data: Unknown medium type" << llendl;
1337 break;
1338 } 1270 }
1339 return(dstlen); 1271 return FALSE; // failure
1340} 1272}
1341 1273
1342/* Convert x11clipboard data to platform string. This too is 1274BOOL LLWindowSDL::copyTextToClipboard(const LLWString &text)
1343 pretty trivial for our needs right now, and just about identical
1344 to above. */
1345static int
1346convert_x11clipboard(int type, char *dst, const char *src, int srclen)
1347{ 1275{
1348 int dstlen; 1276 if (ll_try_gtk_init())
1349
1350 dstlen = 0;
1351 switch (type)
1352 { 1277 {
1353 case SDLCLIPTYPE('U', 'T', 'F', '8'): 1278 const std::string utf8 = wstring_to_utf8str(text);
1354 case SDLCLIPTYPE('T', 'E', 'X', 'T'): 1279 GtkClipboard * const clipboard =
1355 if (src == NULL) 1280 gtk_clipboard_get(GDK_NONE);
1356 { 1281 gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
1357 break; 1282 return TRUE;
1358 }
1359 if ( srclen == 0 )
1360 srclen = strlen(src); /* Flawfinder: ignore */
1361
1362 dstlen = srclen + 1;
1363
1364 if ( dst ) // assume caller made it big enough by asking us
1365 {
1366 memcpy(dst, src, srclen); /* Flawfinder: ignore */
1367 dst[srclen] = '\0';
1368 }
1369 break;
1370
1371 default:
1372 llwarns << "convert_x11clipboard: Unknown medium type" << llendl;
1373 break;
1374 } 1283 }
1375 return dstlen; 1284 return FALSE; // failure
1376}
1377
1378int
1379LLWindowSDL::is_empty_x11clipboard(void)
1380{
1381 int retval;
1382
1383 maybe_lock_display();
1384 retval = ( XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type()) == None );
1385 maybe_unlock_display();
1386
1387 return(retval);
1388} 1285}
1389 1286
1390void 1287BOOL LLWindowSDL::isPrimaryTextAvailable()
1391LLWindowSDL::put_x11clipboard(int type, int srclen, const char *src)
1392{ 1288{
1393 x11clipboard_type format; 1289 if (ll_try_gtk_init())
1394 int dstlen;
1395 char *dst;
1396
1397 format = convert_format(type);
1398 dstlen = convert_data(type, NULL, src, srclen);
1399
1400 dst = (char *)malloc(dstlen);
1401 if ( dst != NULL )
1402 { 1290 {
1403 maybe_lock_display(); 1291 GtkClipboard * const clipboard =
1404 Window root = DefaultRootWindow(mSDL_Display); 1292 gtk_clipboard_get(GDK_SELECTION_PRIMARY);
1405 convert_data(type, dst, src, srclen); 1293 return gtk_clipboard_wait_is_text_available(clipboard) ?
1406 // Cutbuffers are only allowed to have STRING atom types, 1294 TRUE : FALSE;
1407 // but Emacs puts UTF8 inside them anyway. We cautiously
1408 // don't.
1409 if (type == SDLCLIPTYPE('T','E','X','T'))
1410 {
1411 // dstlen-1 so we don't include the trailing \0
1412 llinfos << "X11: Populating cutbuffer." <<llendl;
1413 XChangeProperty(mSDL_Display, root,
1414 XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace,
1415 (unsigned char*)dst, dstlen-1);
1416 } else {
1417 // Should we clear the cutbuffer if we can't put the selection in
1418 // it because it's a UTF8 selection? Eh, no great reason I think.
1419 //XDeleteProperty(SDL_Display, root, XA_CUT_BUFFER0);
1420 }
1421 // Private cutbuffer of an appropriate type.
1422 XChangeProperty(mSDL_Display, root,
1423 get_x11_cutbuffer_clipboard_type(), format, 8, PropModeReplace,
1424 (unsigned char*)dst, dstlen-1);
1425 free(dst);
1426
1427 /* Claim ownership of both PRIMARY and CLIPBOARD */
1428 XSetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type(),
1429 mSDL_XWindowID, CurrentTime);
1430 XSetSelectionOwner(mSDL_Display, get_x11_write_clipboard_type(),
1431 mSDL_XWindowID, CurrentTime);
1432
1433 maybe_unlock_display();
1434 } 1295 }
1296 return FALSE; // failure
1435} 1297}
1436 1298
1437void 1299BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &text)
1438LLWindowSDL::get_x11clipboard(int type, int *dstlen, char **dst)
1439{ 1300{
1440 x11clipboard_type format; 1301 if (ll_try_gtk_init())
1441
1442 *dstlen = 0;
1443 format = convert_format(type);
1444
1445 Window owner;
1446 Atom selection;
1447 Atom seln_type;
1448 int seln_format;
1449 unsigned long nbytes;
1450 unsigned long overflow;
1451 char *src;
1452
1453 maybe_lock_display();
1454 owner = XGetSelectionOwner(mSDL_Display, get_x11_readwrite_clipboard_type());
1455 maybe_unlock_display();
1456 if (owner == None)
1457 {
1458 // Fall right back to ancient X10 cut-buffers
1459 owner = DefaultRootWindow(mSDL_Display);
1460 selection = XA_CUT_BUFFER0;
1461 } else if (owner == mSDL_XWindowID)
1462 {
1463 // Use our own uncooked opaque string property
1464 owner = DefaultRootWindow(mSDL_Display);
1465 selection = get_x11_cutbuffer_clipboard_type();
1466 }
1467 else
1468 {
1469 // Use full-on X11-style clipboard negotiation with the owning app
1470 int selection_response = 0;
1471 SDL_Event event;
1472
1473 owner = mSDL_XWindowID;
1474 maybe_lock_display();
1475 selection = XInternAtom(mSDL_Display, "SDL_SELECTION", False);
1476 XConvertSelection(mSDL_Display, get_x11_readwrite_clipboard_type(), format,
1477 selection, owner, CurrentTime);
1478 maybe_unlock_display();
1479 llinfos << "X11: Waiting for clipboard to arrive." <<llendl;
1480 while ( ! selection_response )
1481 {
1482 // Only look for SYSWMEVENTs, or we may lose keypresses
1483 // etc.
1484 SDL_PumpEvents();
1485 if (1 == SDL_PeepEvents(&event, 1, SDL_GETEVENT,
1486 SDL_SYSWMEVENTMASK) )
1487 {
1488 if ( event.type == SDL_SYSWMEVENT )
1489 {
1490 XEvent xevent =
1491 event.syswm.msg->event.xevent;
1492
1493 if ( (xevent.type == SelectionNotify)&&
1494 (xevent.xselection.requestor == owner) )
1495 selection_response = 1;
1496 }
1497 } else {
1498 llinfos << "X11: Waiting for SYSWM event..." << llendl;
1499 }
1500 }
1501 llinfos << "X11: Clipboard arrived." <<llendl;
1502 }
1503
1504 maybe_lock_display();
1505 if ( XGetWindowProperty(mSDL_Display, owner, selection, 0, INT_MAX/4,
1506 False, format, &seln_type, &seln_format,
1507 &nbytes, &overflow, (unsigned char **)&src) == Success )
1508 { 1302 {
1509 if ( seln_type == format ) 1303 GtkClipboard * const clipboard =
1510 { 1304 gtk_clipboard_get(GDK_SELECTION_PRIMARY);
1511 *dstlen = convert_x11clipboard(type, NULL, src, nbytes); 1305 gchar * const data = gtk_clipboard_wait_for_text(clipboard);
1512 *dst = (char *)realloc(*dst, *dstlen); 1306 if (data)
1513 if ( *dst == NULL )
1514 *dstlen = 0;
1515 else
1516 convert_x11clipboard(type, *dst, src, nbytes);
1517 }
1518 XFree(src);
1519 }
1520 maybe_unlock_display();
1521}
1522
1523int clipboard_filter_callback(const SDL_Event *event)
1524{
1525 /* Post all non-window manager specific events */
1526 if ( event->type != SDL_SYSWMEVENT )
1527 {
1528 return(1);
1529 }
1530
1531 /* Handle window-manager specific clipboard events */
1532 switch (event->syswm.msg->event.xevent.type) {
1533 /* Copy the selection from SECONDLIFE_CUTBUFFER to the requested property */
1534 case SelectionRequest: {
1535 XSelectionRequestEvent *req;
1536 XEvent sevent;
1537 int seln_format;
1538 unsigned long nbytes;
1539 unsigned long overflow;
1540 unsigned char *seln_data;
1541
1542 req = &event->syswm.msg->event.xevent.xselectionrequest;
1543 sevent.xselection.type = SelectionNotify;
1544 sevent.xselection.display = req->display;
1545 sevent.xselection.selection = req->selection;
1546 sevent.xselection.target = None;
1547 sevent.xselection.property = None;
1548 sevent.xselection.requestor = req->requestor;
1549 sevent.xselection.time = req->time;
1550 if ( XGetWindowProperty(LLWindowSDL::get_SDL_Display(), DefaultRootWindow(LLWindowSDL::get_SDL_Display()),
1551 get_x11_cutbuffer_clipboard_type(), 0, INT_MAX/4, False, req->target,
1552 &sevent.xselection.target, &seln_format,
1553 &nbytes, &overflow, &seln_data) == Success )
1554 { 1307 {
1555 if ( sevent.xselection.target == req->target) 1308 text = LLWString(utf8str_to_wstring(data));
1556 { 1309 g_free(data);
1557 if ( sevent.xselection.target == XA_STRING || 1310 return TRUE;
1558 sevent.xselection.target ==
1559 convert_format(SDLCLIPTYPE('U','T','F','8')) )
1560 {
1561 if ( seln_data[nbytes-1] == '\0' )
1562 --nbytes;
1563 }
1564 XChangeProperty(LLWindowSDL::get_SDL_Display(), req->requestor, req->property,
1565 req->target, seln_format, PropModeReplace,
1566 seln_data, nbytes);
1567 sevent.xselection.property = req->property;
1568 } else if (get_x11_targets_atom() == req->target) {
1569 /* only advertise what we currently support */
1570 const int num_supported = 3;
1571 Atom supported[num_supported] = {
1572 XA_STRING, // will be over-written below
1573 get_x11_text_atom(),
1574 get_x11_targets_atom()
1575 };
1576 supported[0] = sevent.xselection.target;
1577 XChangeProperty(LLWindowSDL::get_SDL_Display(), req->requestor,
1578 req->property, XA_ATOM, 32, PropModeReplace,
1579 (unsigned char*)supported,
1580 num_supported);
1581 sevent.xselection.property = req->property;
1582 llinfos << "Clipboard: An app asked us what selections format we offer." << llendl;
1583 } else {
1584 llinfos << "Clipboard: An app requested an unsupported selection format " << req->target << ", we have " << sevent.xselection.target << llendl;
1585 sevent.xselection.target = None;
1586 }
1587 XFree(seln_data);
1588 } 1311 }
1589 int sendret =
1590 XSendEvent(LLWindowSDL::get_SDL_Display(),req->requestor,False,0,&sevent);
1591 if ((sendret==BadValue) || (sendret==BadWindow))
1592 llwarns << "Clipboard SendEvent failed" << llendl;
1593 XSync(LLWindowSDL::get_SDL_Display(), False);
1594 }
1595 break;
1596 } 1312 }
1597 1313 return FALSE; // failure
1598 /* Post the event for X11 clipboard reading above */
1599 return(1);
1600} 1314}
1601 1315
1602int 1316BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text)
1603LLWindowSDL::init_x11clipboard(void)
1604{ 1317{
1605 SDL_SysWMinfo info; 1318 if (ll_try_gtk_init())
1606 int retval;
1607
1608 /* Grab the window manager specific information */
1609 retval = -1;
1610 SDL_SetError("SDL is not running on known window manager");
1611
1612 SDL_VERSION(&info.version);
1613 if ( SDL_GetWMInfo(&info) )
1614 { 1319 {
1615 /* Save the information for later use */ 1320 const std::string utf8 = wstring_to_utf8str(text);
1616 if ( info.subsystem == SDL_SYSWM_X11 ) 1321 GtkClipboard * const clipboard =
1617 { 1322 gtk_clipboard_get(GDK_SELECTION_PRIMARY);
1618 mSDL_Display = info.info.x11.display; 1323 gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length());
1619 mSDL_XWindowID = info.info.x11.wmwindow; 1324 return TRUE;
1620 Lock_Display = info.info.x11.lock_func;
1621 Unlock_Display = info.info.x11.unlock_func;
1622
1623 /* Enable the special window hook events */
1624 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
1625 SDL_SetEventFilter(clipboard_filter_callback);
1626
1627 retval = 0;
1628 }
1629 else
1630 {
1631 SDL_SetError("SDL is not running on X11");
1632 }
1633 } 1325 }
1634 return(retval); 1326 return FALSE; // failure
1635}
1636
1637void
1638LLWindowSDL::quit_x11clipboard(void)
1639{
1640 mSDL_Display = NULL;
1641 mSDL_XWindowID = None;
1642 Lock_Display = NULL;
1643 Unlock_Display = NULL;
1644
1645 SDL_SetEventFilter(NULL); // Stop custom event filtering
1646} 1327}
1647 1328
1648/************************************************/ 1329#else
1649 1330
1650BOOL LLWindowSDL::isClipboardTextAvailable() 1331BOOL LLWindowSDL::isClipboardTextAvailable()
1651{ 1332{
1652 return !is_empty_x11clipboard(); 1333 return FALSE; // unsupported
1653} 1334}
1654 1335
1655BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst) 1336BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst)
1656{ 1337{
1657 int cliplen; // seems 1 or 2 bytes longer than expected 1338 return FALSE; // unsupported
1658 char *cliptext = NULL;
1659 get_x11clipboard(SDLCLIPTYPE('U','T','F','8'), &cliplen, &cliptext);
1660 if (cliptext)
1661 {
1662 llinfos << "X11: Got UTF8 clipboard text." << llendl;
1663 // at some future time we can use cliplen instead of relying on \0,
1664 // if we ever grok non-ascii, non-utf8 encodings on the clipboard.
1665 std::string clip_str(cliptext);
1666 // we can't necessarily trust the incoming text to be valid UTF-8,
1667 // but utf8str_to_wstring() seems to do an appropriate level of
1668 // validation for avoiding over-reads.
1669 dst = utf8str_to_wstring(clip_str);
1670 /*llinfos << "X11 pasteTextFromClipboard: cliplen=" << cliplen <<
1671 " strlen(cliptext)=" << strlen(cliptext) <<
1672 " clip_str.length()=" << clip_str.length() <<
1673 " dst.length()=" << dst.length() <<
1674 llendl;*/
1675 free(cliptext);
1676 return TRUE; // success
1677 }
1678 get_x11clipboard(SDLCLIPTYPE('T','E','X','T'), &cliplen, &cliptext);
1679 if (cliptext)
1680 {
1681 llinfos << "X11: Got ISO 8859-1 clipboard text." << llendl;
1682 std::string clip_str(cliptext);
1683 std::string utf8_str = rawstr_to_utf8(clip_str);
1684 dst = utf8str_to_wstring(utf8_str);
1685 free(cliptext);
1686 }
1687 return FALSE; // failure
1688} 1339}
1340
1689 1341
1690BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s) 1342BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s)
1691{ 1343{
1692 std::string utf8text = wstring_to_utf8str(s); 1344 return FALSE; // unsupported
1693 const char* cstr = utf8text.c_str();
1694 if (cstr == NULL)
1695 {
1696 return FALSE;
1697 }
1698 int cstrlen = strlen(cstr); /* Flawfinder: ignore */
1699 int i;
1700 for (i=0; i<cstrlen; ++i)
1701 {
1702 if (0x80 & (unsigned char)cstr[i])
1703 {
1704 // Found an 8-bit character; use new-style UTF8 clipboard
1705 llinfos << "X11: UTF8 copyTextToClipboard" << llendl;
1706 put_x11clipboard(SDLCLIPTYPE('U','T','F','8'), cstrlen, cstr);
1707 return TRUE;
1708 }
1709 }
1710 // Didn't find any 8-bit characters; use old-style ISO 8859-1 clipboard
1711 llinfos << "X11: ISO 8859-1 copyTextToClipboard" << llendl;
1712 put_x11clipboard(SDLCLIPTYPE('T','E','X','T'), cstrlen, cstr);
1713 return TRUE;
1714} 1345}
1715#else
1716 1346
1717BOOL LLWindowSDL::isClipboardTextAvailable() 1347BOOL LLWindowSDL::isPrimaryTextAvailable()
1718{ 1348{
1719 return FALSE; // unsupported 1349 return FALSE; // unsupported
1720} 1350}
1721 1351
1722BOOL LLWindowSDL::pasteTextFromClipboard(LLWString &dst) 1352BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst)
1723{ 1353{
1724 return FALSE; // unsupported 1354 return FALSE; // unsupported
1725} 1355}
1726 1356
1727BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s) 1357BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s)
1728{ 1358{
1729 return FALSE; // unsupported 1359 return FALSE; // unsupported
1730} 1360}
1731#endif // LL_X11 1361
1362#endif // LL_GTK
1732 1363
1733LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions) 1364LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions)
1734{ 1365{
@@ -2538,8 +2169,7 @@ S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 typ
2538 buttons = GTK_BUTTONS_YES_NO; 2169 buttons = GTK_BUTTONS_YES_NO;
2539 break; 2170 break;
2540 } 2171 }
2541 win = gtk_message_dialog_new(NULL, flags, messagetype, buttons, "%s", 2172 win = gtk_message_dialog_new(NULL,flags, messagetype, buttons, "%s", text.c_str());
2542 text.c_str());
2543 2173
2544# if LL_X11 2174# if LL_X11
2545 // Make GTK tell the window manager to associate this 2175 // Make GTK tell the window manager to associate this
diff --git a/linden/indra/llwindow/llwindowsdl.h b/linden/indra/llwindow/llwindowsdl.h
index 36baec6..54baf01 100644
--- a/linden/indra/llwindow/llwindowsdl.h
+++ b/linden/indra/llwindow/llwindowsdl.h
@@ -79,9 +79,15 @@ public:
79 /*virtual*/ void captureMouse(); 79 /*virtual*/ void captureMouse();
80 /*virtual*/ void releaseMouse(); 80 /*virtual*/ void releaseMouse();
81 /*virtual*/ void setMouseClipping( BOOL b ); 81 /*virtual*/ void setMouseClipping( BOOL b );
82
82 /*virtual*/ BOOL isClipboardTextAvailable(); 83 /*virtual*/ BOOL isClipboardTextAvailable();
83 /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst); 84 /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
84 /*virtual*/ BOOL copyTextToClipboard(const LLWString & src); 85 /*virtual*/ BOOL copyTextToClipboard(const LLWString & src);
86
87 /*virtual*/ BOOL isPrimaryTextAvailable();
88 /*virtual*/ BOOL pasteTextFromPrimary(LLWString &dst);
89 /*virtual*/ BOOL copyTextToPrimary(const LLWString & src);
90
85 /*virtual*/ void flashIcon(F32 seconds); 91 /*virtual*/ void flashIcon(F32 seconds);
86 /*virtual*/ F32 getGamma(); 92 /*virtual*/ F32 getGamma();
87 /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma 93 /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma
@@ -123,7 +129,6 @@ public:
123 // Not great that these are public, but they have to be accessible 129 // Not great that these are public, but they have to be accessible
124 // by non-class code and it's better than making them global. 130 // by non-class code and it's better than making them global.
125#if LL_X11 131#if LL_X11
126 // These are set up by the X11 clipboard initialization code
127 Window mSDL_XWindowID; 132 Window mSDL_XWindowID;
128 Display *mSDL_Display; 133 Display *mSDL_Display;
129#endif 134#endif
@@ -206,12 +211,6 @@ protected:
206 211
207#if LL_X11 212#if LL_X11
208private: 213private:
209 // more X11 clipboard stuff
210 int init_x11clipboard(void);
211 void quit_x11clipboard(void);
212 int is_empty_x11clipboard(void);
213 void put_x11clipboard(int type, int srclen, const char *src);
214 void get_x11clipboard(int type, int *dstlen, char **dst);
215 void x11_set_urgent(BOOL urgent); 214 void x11_set_urgent(BOOL urgent);
216 BOOL mFlashing; 215 BOOL mFlashing;
217 LLTimer mFlashTimer; 216 LLTimer mFlashTimer;