Added Copy and Paste functions to GHOST.
[blender-staging.git] / intern / ghost / intern / GHOST_SystemX11.cpp
index 14383ad36244ea78e830b1e0243c5f6fdc131562..cfd77e5cef12e86e94386cd98a1b150318e1af00 100644 (file)
@@ -95,6 +95,9 @@
 #include <unistd.h>
 
 #include <vector>
+//these are for copy and select copy
+static char *txt_cut_buffer= NULL;
+static char *txt_select_buffer= NULL;
 
 using namespace std;
 
@@ -336,7 +339,7 @@ GHOST_SystemX11::processEvent(XEvent *xe)
        if (!window) {
                return;
        }
-
+       
        switch (xe->type) {
                case Expose:
                {
@@ -504,8 +507,57 @@ GHOST_SystemX11::processEvent(XEvent *xe)
                case MappingNotify:
                case ReparentNotify:
                        break;
-
-       default: {
+               case SelectionRequest:
+               {
+                       XEvent nxe;
+                       Atom target, string, compound_text, c_string;
+                       XSelectionRequestEvent *xse = &xe->xselectionrequest;
+                       
+                       target = XInternAtom(m_display, "TARGETS", False);
+                       string = XInternAtom(m_display, "STRING", False);
+                       compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
+                       c_string = XInternAtom(m_display, "C_STRING", False);
+                       
+                       /* support obsolete clients */
+                       if (xse->property == None) {
+                               xse->property = xse->target;
+                       }
+                       
+                       nxe.xselection.type = SelectionNotify;
+                       nxe.xselection.requestor = xse->requestor;
+                       nxe.xselection.property = xse->property;
+                       nxe.xselection.display = xse->display;
+                       nxe.xselection.selection = xse->selection;
+                       nxe.xselection.target = xse->target;
+                       nxe.xselection.time = xse->time;
+                       
+                       /*Check to see if the requestor is asking for String*/
+                       if(xse->target == string || xse->target == compound_text || xse->target == c_string) {
+                               if (xse->selection == XInternAtom(m_display, "PRIMARY", False)) {
+                                       XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace, (unsigned char*)txt_select_buffer, strlen(txt_select_buffer));
+                               } else if (xse->selection == XInternAtom(m_display, "CLIPBOARD", False)) {
+                                       XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace, (unsigned char*)txt_cut_buffer, strlen(txt_cut_buffer));
+                               }
+                       } else if (xse->target == target) {
+                               Atom alist[4];
+                               alist[0] = target;
+                               alist[1] = string;
+                               alist[2] = compound_text;
+                               alist[3] = c_string;
+                               XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 32, PropModeReplace, (unsigned char*)alist, 4);
+                               XFlush(m_display);
+                       } else  {
+                               //Change property to None because we do not support anything but STRING
+                               nxe.xselection.property = None;
+                       }
+                       
+                       //Send the event to the client 0 0 == False, SelectionNotify
+                       XSendEvent(m_display, xse->requestor, 0, 0, &nxe);
+                       XFlush(m_display);
+                       break;
+               }
+               
+               default: {
                        if(xe->type == window->GetXTablet().MotionEvent) 
                        {
                                XDeviceMotionEvent* data = (XDeviceMotionEvent*)xe;
@@ -876,3 +928,113 @@ convertXKey(
 }
 
 #undef GXMAP
+
+       GHOST_TUns8*
+GHOST_SystemX11::
+getClipboard(int flag
+) const {
+       //Flag 
+       //0 = Regular clipboard 1 = selection
+       static Atom Primary_atom, clip_String, compound_text;
+       Atom rtype;
+       Window m_window, owner;
+       unsigned char *data, *tmp_data;
+       int bits;
+       unsigned long len, bytes;
+       XEvent xevent;
+       
+       vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+       vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+       GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
+       m_window = window->getXWindow();
+
+       clip_String = XInternAtom(m_display, "_BLENDER_STRING", False);
+       compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
+
+       //lets check the owner and if it is us then return the static buffer
+       if(flag == 0) {
+               Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
+               owner = XGetSelectionOwner(m_display, Primary_atom);
+               if (owner == m_window) {
+                       data = (unsigned char*) malloc(strlen(txt_cut_buffer));
+                       strcpy((char*)data, txt_cut_buffer);
+                       return (GHOST_TUns8*)data;
+               } else if (owner == None) {
+                       return NULL;
+               }
+       } else {
+               Primary_atom = XInternAtom(m_display, "PRIMARY", False);
+               owner = XGetSelectionOwner(m_display, Primary_atom);
+               if (owner == m_window) {
+                       data = (unsigned char*) malloc(strlen(txt_select_buffer));
+                       strcpy((char*)data, txt_select_buffer);
+                       return (GHOST_TUns8*)data;
+               } else if (owner == None) {
+                       return NULL;
+               }
+       }
+
+       if(!Primary_atom) {
+               return NULL;
+       }
+       
+       XDeleteProperty(m_display, m_window, Primary_atom);
+       XConvertSelection(m_display, Primary_atom, compound_text, clip_String, m_window, CurrentTime); //XA_STRING
+       XFlush(m_display);
+
+       //This needs to change so we do not wait for ever or check owner first
+       while(1) {
+               XNextEvent(m_display, &xevent);
+               if(xevent.type == SelectionNotify) {
+                       if(XGetWindowProperty(m_display, m_window, xevent.xselection.property, 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) {
+                               tmp_data = (unsigned char*) malloc(strlen((char*)data));
+                               strcpy((char*)tmp_data, (char*)data);
+                               XFree(data);
+                               return (GHOST_TUns8*)tmp_data;
+                       }
+                       return NULL;
+               }
+       }
+}
+
+       void
+GHOST_SystemX11::
+putClipboard(
+GHOST_TInt8 *buffer, int flag) const
+{
+       static Atom Primary_atom;
+       Window m_window, owner;
+       
+       if(!buffer) {return;}
+       
+       if(flag == 0) {
+               Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
+               if(txt_cut_buffer) { free((void*)txt_cut_buffer); }
+               
+               txt_cut_buffer = (char*) malloc(strlen(buffer));
+               strcpy(txt_cut_buffer, buffer);
+       } else {
+               Primary_atom = XInternAtom(m_display, "PRIMARY", False);
+               if(txt_select_buffer) { free((void*)txt_select_buffer); }
+               
+               txt_select_buffer = (char*) malloc(strlen(buffer));
+               strcpy(txt_select_buffer, buffer);
+       }
+       
+       vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+       vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+       GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
+       m_window = window->getXWindow();
+
+       if(!Primary_atom) {
+               return;
+       }
+       
+       XSetSelectionOwner(m_display, Primary_atom, m_window, CurrentTime);
+       owner = XGetSelectionOwner(m_display, Primary_atom);
+       if (owner != m_window)
+               printf("failed to own primary\n");
+       
+       return;
+}
+