Forráskód Böngészése

Added clipboard support on linux using X11.

We're still using SDL1.2, but now some functions use X11, so if we every fully switch to X11, we can keep at least some of the code.

Courtesy of http://www.libsdl.org/projects/scrap/, which was gratefully released into the public domain.
cib 12 éve
szülő
commit
91d9caad0e

+ 0 - 2
Core/Contents/CMakeLists.txt

@@ -249,9 +249,7 @@ IF("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
   endif()
   PKG_CHECK_MODULES(X11 x11)
   IF(${X11_FOUND})
-    LINK_DIRECTORIES(${X11_LIBRARY_DIRS})
     INCLUDE_DIRECTORIES(${X11_INCLUDE_DIRS})
-    TARGET_LINK_LIBRARIES(Polycore ${X11_LIBRARIES})
     SET_TARGET_PROPERTIES(Polycore PROPERTIES COMPILE_FLAGS "-DUSE_X11")
   ELSE()
     message( FATAL_ERROR "You seem to be using Linux, but X11 is not installed. Please install X11." )

+ 407 - 2
Core/Contents/Source/PolySDLCore.cpp

@@ -32,6 +32,10 @@
 #include "PolyRectangle.h"
 
 #include <SDL/SDL.h>
+#include <SDL/SDL_syswm.h>
+#include <stdio.h>
+#include <limits.h>
+
 #include <iostream>
 
 #include <unistd.h>
@@ -40,6 +44,17 @@
 #include <sys/wait.h>
 #include <pwd.h>
 
+#ifdef USE_X11
+	// SDL scrap
+	#define T(A, B, C, D)	(int)((A<<24)|(B<<16)|(C<<8)|(D<<0))
+
+	int init_scrap(void);
+	int lost_scrap(void);
+	void put_scrap(int type, int srclen, const char *src);
+	void get_scrap(int type, int *dstlen, char **dst);
+	// end SDL scrap
+#endif
+
 using namespace Polycode;
 using std::vector;
 
@@ -96,6 +111,11 @@ SDLCore::SDLCore(PolycodeView *view, int _xRes, int _yRes, bool fullScreen, bool
 		SDL_JoystickOpen(i);
 		input->addJoystick(i);
 	}
+	
+	// Start listening to clipboard events.
+	// (Yes on X11 you need to actively listen to
+	//  clipboard events and respond to them)
+	init_scrap();
 
 	((OpenGLRenderer*)renderer)->initOSSpecific();
 	CoreServices::getInstance()->installModule(new GLSLShaderModule());	
@@ -401,11 +421,21 @@ CoreMutex *SDLCore::createMutex() {
 }
 
 void SDLCore::copyStringToClipboard(const String& str) {
-
+#ifdef USE_X11
+	put_scrap(T('T', 'E', 'X', 'T'), str.size(), str.c_str());
+#endif
 }
 
 String SDLCore::getClipboardString() {
-	return "";
+#ifdef USE_X11
+	int dstlen;
+	char* buffer;
+	get_scrap(T('T', 'E', 'X', 'T'), &dstlen, &buffer);
+	
+	String rval(buffer, dstlen);
+	free(buffer);
+	return rval;
+#endif
 }
 
 void SDLCore::createFolder(const String& folderPath) {
@@ -456,3 +486,378 @@ void SDLCore::resizeTo(int xRes, int yRes) {
 	renderer->Resize(xRes, yRes);
 }
 
+
+#ifdef USE_X11
+// SDL_scrap.c
+// Credits to Sam Lantinga for making this
+// Changes include:
+// - All non-X11 stuff was removed
+// - Uses the X11 CLIPBOARD atom in addition to PRIMARY
+// =======================================
+
+
+/* Handle clipboard text and data in arbitrary formats */
+
+/* Miscellaneous defines */
+#define PUBLIC
+#define PRIVATE	static
+
+#define X11_SCRAP
+
+typedef Atom scrap_type;
+
+static Display *SDL_Display;
+static Window SDL_Window;
+static void (*Lock_Display)(void);
+static void (*Unlock_Display)(void);
+
+#define FORMAT_PREFIX	"SDL_scrap_0x"
+
+PRIVATE scrap_type
+convert_format(int type)
+{
+  switch (type)
+    {
+
+    case T('T', 'E', 'X', 'T'):
+      return XA_STRING;
+
+    default:
+      {
+        char format[sizeof(FORMAT_PREFIX)+8+1];
+
+        sprintf(format, "%s%08lx", FORMAT_PREFIX, (unsigned long)type);
+
+        return XInternAtom(SDL_Display, format, False);
+      }
+    }
+}
+
+/* Convert internal data to scrap format */
+PRIVATE int
+convert_data(int type, char *dst, const char *src, int srclen)
+{
+  int dstlen;
+
+  dstlen = 0;
+  switch (type)
+    {
+    case T('T', 'E', 'X', 'T'):
+      if ( dst )
+        {
+          while ( --srclen >= 0 )
+            {
+              if ( *src == '\r' )
+                {
+                  *dst++ = '\n';
+                  ++dstlen;
+                }
+              else
+                {
+                  *dst++ = *src;
+                  ++dstlen;
+                }
+              ++src;
+            }
+            *dst = '\0';
+            ++dstlen;
+        }
+      else
+        {
+          while ( --srclen >= 0 )
+            {
+              if ( *src == '\r' )
+                {
+                  ++dstlen;
+                }
+              else
+                {
+                  ++dstlen;
+                }
+              ++src;
+            }
+            ++dstlen;
+        }
+      break;
+
+    default:
+      if ( dst )
+        {
+          *(int *)dst = srclen;
+          dst += sizeof(int);
+          memcpy(dst, src, srclen);
+        }
+      dstlen = sizeof(int)+srclen;
+      break;
+    }
+    return(dstlen);
+}
+
+/* Convert scrap data to internal format */
+PRIVATE int
+convert_scrap(int type, char *dst, char *src, int srclen)
+{
+  int dstlen;
+
+  dstlen = 0;
+  switch (type)
+    {
+    case T('T', 'E', 'X', 'T'):
+      {
+        if ( srclen == 0 )
+          srclen = strlen(src);
+        if ( dst )
+          {
+            while ( --srclen >= 0 )
+              {
+                if ( *src == '\n' )
+                  {
+                    *dst++ = '\r';
+                    ++dstlen;
+                  }
+                else
+                  {
+                    *dst++ = *src;
+                    ++dstlen;
+                  }
+                ++src;
+              }
+              *dst = '\0';
+              ++dstlen;
+          }
+        else
+          {
+            while ( --srclen >= 0 )
+              {
+                ++dstlen;
+                ++src;
+              }
+              ++dstlen;
+          }
+        }
+      break;
+
+    default:
+      dstlen = *(int *)src;
+      if ( dst )
+        {
+          if ( srclen == 0 )
+            memcpy(dst, src+sizeof(int), dstlen);
+          else
+            memcpy(dst, src+sizeof(int), srclen-sizeof(int));
+        }
+      break;
+    }
+  return dstlen;
+}
+
+/* The system message filter function -- handle clipboard messages */
+PRIVATE int clipboard_filter(const SDL_Event *event);
+
+PUBLIC int
+init_scrap(void)
+{
+  SDL_SysWMinfo info;
+  int retval;
+
+  /* Grab the window manager specific information */
+  retval = -1;
+  SDL_SetError("SDL is not running on known window manager");
+
+  SDL_VERSION(&info.version);
+  if ( SDL_GetWMInfo(&info) )
+    {
+      /* Save the information for later use */
+/* * */
+      if ( info.subsystem == SDL_SYSWM_X11 )
+        {
+          SDL_Display = info.info.x11.display;
+          SDL_Window = info.info.x11.window;
+          Lock_Display = info.info.x11.lock_func;
+          Unlock_Display = info.info.x11.unlock_func;
+
+          /* Enable the special window hook events */
+          SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+          SDL_SetEventFilter(clipboard_filter);
+
+          retval = 0;
+        }
+      else
+        {
+          SDL_SetError("SDL is not running on X11");
+        }
+    }
+  return(retval);
+}
+
+PUBLIC int
+lost_scrap(void)
+{
+  int retval;
+
+/* * */
+  Lock_Display();
+  retval = ( XGetSelectionOwner(SDL_Display, XA_PRIMARY) != SDL_Window );
+  Unlock_Display();
+
+  return(retval);
+}
+
+PUBLIC void
+put_scrap(int type, int srclen, const char *src)
+{
+  scrap_type format;
+  int dstlen;
+  char *dst;
+
+  format = convert_format(type);
+  dstlen = convert_data(type, NULL, src, srclen);
+
+/* * */
+  dst = (char *)malloc(dstlen);
+  if ( dst != NULL )
+    {
+      Lock_Display();
+      convert_data(type, dst, src, srclen);
+      XChangeProperty(SDL_Display, DefaultRootWindow(SDL_Display),
+        XA_CUT_BUFFER0, format, 8, PropModeReplace, (unsigned char*) dst, dstlen);
+      free(dst);
+      Atom XA_CLIPBOARD = XInternAtom(SDL_Display, "CLIPBOARD", 0);
+      if ( lost_scrap() ) {
+        XSetSelectionOwner(SDL_Display, XA_PRIMARY, SDL_Window, CurrentTime);
+        XSetSelectionOwner(SDL_Display, XA_CLIPBOARD, SDL_Window, CurrentTime);
+      }
+      Unlock_Display();
+    }
+
+}
+
+PUBLIC void
+get_scrap(int type, int *dstlen, char **dst)
+{
+  scrap_type format;
+
+  *dstlen = 0;
+  format = convert_format(type);
+
+/* * */
+  {
+    Window owner;
+    Atom selection;
+    Atom seln_type;
+    int seln_format;
+    unsigned long nbytes;
+    unsigned long overflow;
+    char *src;
+
+    Lock_Display();
+    Atom XA_CLIPBOARD = XInternAtom(SDL_Display, "CLIPBOARD", 0);
+    owner = XGetSelectionOwner(SDL_Display, XA_PRIMARY);
+    Unlock_Display();
+    if ( (owner == None) || (owner == SDL_Window) )
+      {
+        owner = DefaultRootWindow(SDL_Display);
+        selection = XA_CUT_BUFFER0;
+      }
+    else
+      {
+        int selection_response = 0;
+        SDL_Event event;
+
+        owner = SDL_Window;
+        Lock_Display();
+        selection = XInternAtom(SDL_Display, "SDL_SELECTION", False);
+        XConvertSelection(SDL_Display, XA_PRIMARY, format,
+                                        selection, owner, CurrentTime);
+        XConvertSelection(SDL_Display, XA_CLIPBOARD, format,
+                                        selection, owner, CurrentTime);
+        Unlock_Display();
+        while ( ! selection_response )
+          {
+            SDL_WaitEvent(&event);
+            if ( event.type == SDL_SYSWMEVENT )
+              {
+                XEvent xevent = event.syswm.msg->event.xevent;
+
+                if ( (xevent.type == SelectionNotify) &&
+                     (xevent.xselection.requestor == owner) )
+                    selection_response = 1;
+              }
+          }
+      }
+    Lock_Display();
+    if ( XGetWindowProperty(SDL_Display, owner, selection, 0, INT_MAX/4,
+                            False, format, &seln_type, &seln_format,
+                       &nbytes, &overflow, (unsigned char **)&src) == Success )
+      {
+        if ( seln_type == format )
+          {
+            *dstlen = convert_scrap(type, NULL, src, nbytes);
+            *dst = (char *)malloc(*dstlen);
+            if ( *dst == NULL )
+              *dstlen = 0;
+            else
+              convert_scrap(type, *dst, src, nbytes);
+          }
+        XFree(src);
+      }
+    }
+    Unlock_Display();
+}
+
+PRIVATE int clipboard_filter(const SDL_Event *event)
+{
+  /* Post all non-window manager specific events */
+  if ( event->type != SDL_SYSWMEVENT ) {
+    return(1);
+  }
+
+  /* Handle window-manager specific clipboard events */
+  switch (event->syswm.msg->event.xevent.type) {
+    /* Copy the selection from XA_CUT_BUFFER0 to the requested property */
+    case SelectionRequest: {
+      XSelectionRequestEvent *req;
+      XEvent sevent;
+      int seln_format;
+      unsigned long nbytes;
+      unsigned long overflow;
+      unsigned char *seln_data;
+
+      req = &event->syswm.msg->event.xevent.xselectionrequest;
+      sevent.xselection.type = SelectionNotify;
+      sevent.xselection.display = req->display;
+      sevent.xselection.selection = req->selection;
+      sevent.xselection.target = None;
+      sevent.xselection.property = None;
+      sevent.xselection.requestor = req->requestor;
+      sevent.xselection.time = req->time;
+      if ( XGetWindowProperty(SDL_Display, DefaultRootWindow(SDL_Display),
+                              XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target,
+                              &sevent.xselection.target, &seln_format,
+                              &nbytes, &overflow, &seln_data) == Success )
+        {
+          if ( sevent.xselection.target == req->target )
+            {
+              if ( sevent.xselection.target == XA_STRING )
+                {
+                  if ( seln_data[nbytes-1] == '\0' )
+                    --nbytes;
+                }
+              XChangeProperty(SDL_Display, req->requestor, req->property,
+                sevent.xselection.target, seln_format, PropModeReplace,
+                                                      seln_data, nbytes);
+              sevent.xselection.property = req->property;
+            }
+          XFree(seln_data);
+        }
+      XSendEvent(SDL_Display,req->requestor,False,0,&sevent);
+      XSync(SDL_Display, False);
+    }
+    break;
+  }
+
+  /* Post the event for X11 clipboard reading above */
+  return(1);
+}
+
+#endif // USE_X11

+ 1 - 1
IDE/Build/Linux/Makefile

@@ -2,7 +2,7 @@ CC=g++
 CFLAGS=-I../../Contents/Include -I../../../Release/Linux/Framework/Core/Dependencies/include -I../../../Release/Linux/Framework/Core/Dependencies/include/AL -I../../../Release/Linux/Framework/Core/include -I../../../Release/Linux/Framework/Modules/include -I../../../Release/Linux/Framework/Modules/Dependencies/include -I../../../Release/Linux/Framework/Modules/Dependencies/include/bullet -DUSE_POLYCODEUI_FILE_DIALOGS -DUSE_POLYCODEUI_MENUBAR
 LDFLAGS=-lrt -ldl -lpthread ../../../Release/Linux/Framework/Core/lib/libPolycore.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libfreetype.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisfile.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbis.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibogg.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libopenal.so ../../../Release/Linux/Framework/Core/Dependencies/lib/libphysfs.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libpng15.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../../Release/Linux/Framework/Modules/lib/libPolycode2DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBox2D.a ../../../Release/Linux/Framework/Modules/lib/libPolycode3DPhysics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletDynamics.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletCollision.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libLinearMath.a ../../../Release/Linux/Framework/Modules/lib/libPolycodeUI.a
 LDFLAGS_DEBUG=-lrt -ldl -lpthread ../../../Release/Linux/Framework/Core/lib/libPolycore_d.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libfreetype_d.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisfiled.a ../../../Release/Linux/Framework/Core/Dependencies/lib/liblibvorbisd.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libliboggd.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libopenal.so ../../../Release/Linux/Framework/Core/Dependencies/lib/libphysfsd.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libpng15d.a ../../../Release/Linux/Framework/Core/Dependencies/lib/libz.a -lGL -lGLU -lSDL ../../../Release/Linux/Framework/Modules/lib/libPolycode2DPhysics_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBox2D_d.a ../../../Release/Linux/Framework/Modules/lib/libPolycode3DPhysics_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletDynamics_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libBulletCollision_d.a ../../../Release/Linux/Framework/Modules/Dependencies/lib/libLinearMath_d.a ../../../Release/Linux/Framework/Modules/lib/libPolycodeUI_d.a
-SRCS=../../Contents/Source/ExampleBrowserWindow.cpp ../../Contents/Source/PolycodeEditorManager.cpp  ../../Contents/Source/PolycodeProject.cpp        ../../Contents/Source/PolycodeScreenEditor.cpp ../../Contents/Source/ExportProjectWindow.cpp  ../../Contents/Source/PolycodeFontEditor.cpp     ../../Contents/Source/PolycodeProjectBrowser.cpp ../../Contents/Source/PolycodeSpriteEditor.cpp ../../Contents/Source/NewFileWindow.cpp        ../../Contents/Source/PolycodeFrame.cpp          ../../Contents/Source/PolycodeProjectEditor.cpp  ../../Contents/Source/PolycodeTextEditor.cpp ../../Contents/Source/NewProjectWindow.cpp     ../../Contents/Source/PolycodeIDEApp.cpp         ../../Contents/Source/PolycodeProjectManager.cpp ../../Contents/Source/PolycodeToolLauncher.cpp ../../Contents/Source/PolycodeConsole.cpp      ../../Contents/Source/PolycodeImageEditor.cpp    ../../Contents/Source/PolycodeProps.cpp          ../../Contents/Source/TextureBrowser.cpp ../../Contents/Source/PolycodeEditor.cpp       ../../Contents/Source/PolycodeMaterialEditor.cpp ../../Contents/Source/PolycodeRemoteDebugger.cpp ../../Contents/Source/ToolWindows.cpp ../../Contents/Source/PolycodeClipboard.cpp ../../Contents/Source/SettingsWindow.cpp
+SRCS=../../Contents/Source/ExampleBrowserWindow.cpp ../../Contents/Source/PolycodeEditorManager.cpp  ../../Contents/Source/PolycodeProject.cpp        ../../Contents/Source/PolycodeScreenEditor.cpp ../../Contents/Source/ExportProjectWindow.cpp  ../../Contents/Source/PolycodeFontEditor.cpp     ../../Contents/Source/PolycodeProjectBrowser.cpp ../../Contents/Source/PolycodeSpriteEditor.cpp ../../Contents/Source/NewFileWindow.cpp        ../../Contents/Source/PolycodeFrame.cpp          ../../Contents/Source/PolycodeProjectEditor.cpp  ../../Contents/Source/PolycodeTextEditor.cpp ../../Contents/Source/NewProjectWindow.cpp     ../../Contents/Source/PolycodeIDEApp.cpp         ../../Contents/Source/PolycodeProjectManager.cpp ../../Contents/Source/PolycodeToolLauncher.cpp ../../Contents/Source/PolycodeConsole.cpp      ../../Contents/Source/PolycodeImageEditor.cpp    ../../Contents/Source/PolycodeProps.cpp          ../../Contents/Source/TextureBrowser.cpp ../../Contents/Source/PolycodeEditor.cpp       ../../Contents/Source/PolycodeMaterialEditor.cpp ../../Contents/Source/PolycodeRemoteDebugger.cpp ../../Contents/Source/ToolWindows.cpp ../../Contents/Source/PolycodeClipboard.cpp ../../Contents/Source/SettingsWindow.cpp -lX11
 
 default:
 	mkdir -p ./Build