Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorDiego Borghetti <bdiego@gmail.com>2009-05-18 23:47:04 +0400
committerDiego Borghetti <bdiego@gmail.com>2009-05-18 23:47:04 +0400
commit96348bc772eb7ac2cb8b6114c2d345386585ae74 (patch)
tree6fa1a7adb4c233ab297cb344d258d123d11a3a2e /intern
parent4022380dc6a70b5123282e912743e568a92adde2 (diff)
Commit revision 20062 and 20109 from trunk, also fix a small memory
error on interface, was try to free an incorrect pointer.
Diffstat (limited to 'intern')
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp402
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h22
2 files changed, 301 insertions, 123 deletions
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index c6ce7b628e9..a975322e9ce 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -117,7 +117,15 @@ GHOST_SystemX11(
m_net_fullscreen= XInternAtom(m_display,
"_NET_WM_STATE_FULLSCREEN", False);
m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
-
+ m_targets= XInternAtom(m_display, "TARGETS", False);
+ m_string= XInternAtom(m_display, "STRING", False);
+ m_compound_text= XInternAtom(m_display, "COMPOUND_TEXT", False);
+ m_text= XInternAtom(m_display, "TEXT", False);
+ m_clipboard= XInternAtom(m_display, "CLIPBOARD", False);
+ m_primary= XInternAtom(m_display, "PRIMARY", False);
+ m_xclip_out= XInternAtom(m_display, "XCLIP_OUT", False);
+ m_incr= XInternAtom(m_display, "INCR", False);
+ m_utf8_string= XInternAtom(m_display, "UTF8_STRING", False);
// compute the initial time
timeval tv;
@@ -1004,144 +1012,298 @@ convertXKey(
#undef GXMAP
- GHOST_TUns8*
-GHOST_SystemX11::
-getClipboard(bool selection
-) const {
- //Flag
- //0 = Regular clipboard 1 = selection
- static Atom Primary_atom, clip_String, compound_text, a_text, a_string;
- Atom rtype;
- Window m_window, owner;
- unsigned char *data, *tmp_data;
- int bits, count;
- unsigned long len, bytes;
- XEvent xevent;
-
+/* from xclip.c xcout() v0.11 */
+
+#define XCLIB_XCOUT_NONE 0 /* no context */
+#define XCLIB_XCOUT_SENTCONVSEL 1 /* sent a request */
+#define XCLIB_XCOUT_INCR 2 /* in an incr loop */
+#define XCLIB_XCOUT_FALLBACK 3 /* STRING failed, need fallback to UTF8 */
+#define XCLIB_XCOUT_FALLBACK_UTF8 4 /* UTF8 failed, move to compouned */
+#define XCLIB_XCOUT_FALLBACK_COMP 5 /* compouned failed, move to text. */
+#define XCLIB_XCOUT_FALLBACK_TEXT 6
+
+// Retrieves the contents of a selections.
+void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
+ Atom sel, Atom target, unsigned char **txt,
+ unsigned long *len, unsigned int *context) const
+{
+ Atom pty_type;
+ int pty_format;
+ unsigned char *buffer;
+ unsigned long pty_size, pty_items;
+ unsigned char *ltxt= *txt;
+
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();
+ Window win = window->getXWindow();
+
+ switch (*context) {
+ // There is no context, do an XConvertSelection()
+ case XCLIB_XCOUT_NONE:
+ // Initialise return length to 0
+ if (*len > 0) {
+ free(*txt);
+ *len = 0;
+ }
- clip_String = XInternAtom(m_display, "_BLENDER_STRING", False);
- compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
- a_text= XInternAtom(m_display, "TEXT", False);
- a_string= XInternAtom(m_display, "STRING", False);
-
- //lets check the owner and if it is us then return the static buffer
- if(!selection) {
- 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)+1);
- 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)+1);
- strcpy((char*)data, txt_select_buffer);
- return (GHOST_TUns8*)data;
- } else if (owner == None) {
- return NULL;
- }
- }
+ // Send a selection request
+ XConvertSelection(m_display, sel, target, m_xclip_out, win, CurrentTime);
+ *context = XCLIB_XCOUT_SENTCONVSEL;
+ return;
- 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);
+ case XCLIB_XCOUT_SENTCONVSEL:
+ if (evt.type != SelectionNotify)
+ return;
- //This needs to change so we do not wait for ever or check owner first
- count= 1;
- while(1) {
- XNextEvent(m_display, &xevent);
- if(xevent.type == SelectionNotify) {
- if (xevent.xselection.property == None) {
- /* Ok, the client can't convert the property
- * to some that we can handle, try other types..
- */
- if (count == 1) {
- XConvertSelection(m_display, Primary_atom, a_text, clip_String, m_window, CurrentTime);
- count++;
- }
- else if (count == 2) {
- XConvertSelection(m_display, Primary_atom, a_string, clip_String, m_window, CurrentTime);
- count++;
- }
- else {
- /* Ok, the owner of the selection can't
- * convert the data to something that we can
- * handle.
- */
- return(NULL);
- }
+ if (target == m_utf8_string && evt.xselection.property == None) {
+ *context= XCLIB_XCOUT_FALLBACK_UTF8;
+ return;
+ }
+ else if (target == m_compound_text && evt.xselection.property == None) {
+ *context= XCLIB_XCOUT_FALLBACK_COMP;
+ return;
+ }
+ else if (target == m_text && evt.xselection.property == None) {
+ *context= XCLIB_XCOUT_FALLBACK_TEXT;
+ return;
+ }
+
+ // find the size and format of the data in property
+ XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
+ AnyPropertyType, &pty_type, &pty_format,
+ &pty_items, &pty_size, &buffer);
+ XFree(buffer);
+
+ if (pty_type == m_incr) {
+ // start INCR mechanism by deleting property
+ XDeleteProperty(m_display, win, m_xclip_out);
+ XFlush(m_display);
+ *context = XCLIB_XCOUT_INCR;
+ return;
+ }
+
+ // if it's not incr, and not format == 8, then there's
+ // nothing in the selection (that xclip understands, anyway)
+
+ if (pty_format != 8) {
+ *context = XCLIB_XCOUT_NONE;
+ return;
+ }
+
+ // not using INCR mechanism, just read the property
+ XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
+ False, AnyPropertyType, &pty_type,
+ &pty_format, &pty_items, &pty_size, &buffer);
+
+ // finished with property, delete it
+ XDeleteProperty(m_display, win, m_xclip_out);
+
+ // copy the buffer to the pointer for returned data
+ ltxt = (unsigned char *) malloc(pty_items);
+ memcpy(ltxt, buffer, pty_items);
+
+ // set the length of the returned data
+ *len = pty_items;
+ *txt = ltxt;
+
+ // free the buffer
+ XFree(buffer);
+
+ *context = XCLIB_XCOUT_NONE;
+
+ // complete contents of selection fetched, return 1
+ return;
+
+ case XCLIB_XCOUT_INCR:
+ // To use the INCR method, we basically delete the
+ // property with the selection in it, wait for an
+ // event indicating that the property has been created,
+ // then read it, delete it, etc.
+
+ // make sure that the event is relevant
+ if (evt.type != PropertyNotify)
+ return;
+
+ // skip unless the property has a new value
+ if (evt.xproperty.state != PropertyNewValue)
+ return;
+
+ // check size and format of the property
+ XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
+ AnyPropertyType, &pty_type, &pty_format,
+ &pty_items, &pty_size, (unsigned char **) &buffer);
+
+ if (pty_format != 8) {
+ // property does not contain text, delete it
+ // to tell the other X client that we have read
+ // it and to send the next property
+ XFree(buffer);
+ XDeleteProperty(m_display, win, m_xclip_out);
+ return;
+ }
+
+ if (pty_size == 0) {
+ // no more data, exit from loop
+ XFree(buffer);
+ XDeleteProperty(m_display, win, m_xclip_out);
+ *context = XCLIB_XCOUT_NONE;
+
+ // this means that an INCR transfer is now
+ // complete, return 1
+ return;
+ }
+
+ XFree(buffer);
+
+ // if we have come this far, the propery contains
+ // text, we know the size.
+ XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
+ False, AnyPropertyType, &pty_type, &pty_format,
+ &pty_items, &pty_size, (unsigned char **) &buffer);
+
+ // allocate memory to accommodate data in *txt
+ if (*len == 0) {
+ *len = pty_items;
+ ltxt = (unsigned char *) malloc(*len);
}
else {
- if(XGetWindowProperty(m_display, m_window, xevent.xselection.property , 0L, 4096L, False, AnyPropertyType, &rtype, &bits, &len, &bytes, &data) == Success) {
- if (data) {
- if (bits == 8 && (rtype == compound_text || rtype == a_text || rtype == a_string)) {
- tmp_data = (unsigned char*) malloc(strlen((char*)data)+1);
- strcpy((char*)tmp_data, (char*)data);
- }
- else
- tmp_data= NULL;
-
- XFree(data);
- return (GHOST_TUns8*)tmp_data;
- }
- }
- return(NULL);
+ *len += pty_items;
+ ltxt = (unsigned char *) realloc(ltxt, *len);
}
- }
+
+ // add data to ltxt
+ memcpy(&ltxt[*len - pty_items], buffer, pty_items);
+
+ *txt = ltxt;
+ XFree(buffer);
+
+ // delete property to get the next item
+ XDeleteProperty(m_display, win, m_xclip_out);
+ XFlush(m_display);
+ return;
}
+ return;
}
- void
-GHOST_SystemX11::
-putClipboard(
-GHOST_TInt8 *buffer, bool selection) const
+GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
{
- static Atom Primary_atom;
- Window m_window, owner;
-
- if(!buffer) {return;}
-
- if(!selection) {
- Primary_atom = XInternAtom(m_display, "CLIPBOARD", False);
- if(txt_cut_buffer) { free((void*)txt_cut_buffer); }
+ Atom sseln;
+ Atom target= m_string;
+ Window owner;
+
+ // from xclip.c doOut() v0.11
+ unsigned char *sel_buf;
+ unsigned long sel_len= 0;
+ XEvent evt;
+ unsigned int context= XCLIB_XCOUT_NONE;
+
+ if (selection == True)
+ sseln= m_primary;
+ else
+ sseln= m_clipboard;
+
+ 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);
+ Window win = window->getXWindow();
+
+ /* check if we are the owner. */
+ owner= XGetSelectionOwner(m_display, sseln);
+ if (owner == win) {
+ if (sseln == m_clipboard) {
+ sel_buf= (unsigned char *)malloc(strlen(txt_cut_buffer)+1);
+ strcpy((char *)sel_buf, txt_cut_buffer);
+ return((GHOST_TUns8*)sel_buf);
+ }
+ else {
+ sel_buf= (unsigned char *)malloc(strlen(txt_select_buffer)+1);
+ strcpy((char *)sel_buf, txt_select_buffer);
+ return((GHOST_TUns8*)sel_buf);
+ }
+ }
+ else if (owner == None)
+ return(NULL);
+
+ while (1) {
+ /* only get an event if xcout() is doing something */
+ if (context != XCLIB_XCOUT_NONE)
+ XNextEvent(m_display, &evt);
+
+ /* fetch the selection, or part of it */
+ getClipboard_xcout(evt, sseln, target, &sel_buf, &sel_len, &context);
+
+ /* fallback is needed. set XA_STRING to target and restart the loop. */
+ if (context == XCLIB_XCOUT_FALLBACK) {
+ context= XCLIB_XCOUT_NONE;
+ target= m_string;
+ continue;
+ }
+ else if (context == XCLIB_XCOUT_FALLBACK_UTF8) {
+ /* utf8 fail, move to compouned text. */
+ context= XCLIB_XCOUT_NONE;
+ target= m_compound_text;
+ continue;
+ }
+ else if (context == XCLIB_XCOUT_FALLBACK_COMP) {
+ /* compouned text faile, move to text. */
+ context= XCLIB_XCOUT_NONE;
+ target= m_text;
+ continue;
+ }
+
+ /* only continue if xcout() is doing something */
+ if (context == XCLIB_XCOUT_NONE)
+ break;
+ }
+
+ if (sel_len) {
+ /* only print the buffer out, and free it, if it's not
+ * empty
+ */
+ unsigned char *tmp_data = (unsigned char*) malloc(sel_len+1);
+ memcpy((char*)tmp_data, (char*)sel_buf, sel_len);
+ tmp_data[sel_len] = '\0';
- txt_cut_buffer = (char*) malloc(strlen(buffer)+1);
- strcpy(txt_cut_buffer, buffer);
- } else {
- Primary_atom = XInternAtom(m_display, "PRIMARY", False);
- if(txt_select_buffer) { free((void*)txt_select_buffer); }
+ if (sseln == m_string)
+ XFree(sel_buf);
+ else
+ free(sel_buf);
- txt_select_buffer = (char*) malloc(strlen(buffer)+1);
- strcpy(txt_select_buffer, buffer);
+ return (GHOST_TUns8*)tmp_data;
}
-
- vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+ return(NULL);
+}
+
+void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
+{
+ Window m_window, owner;
+
+ 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)
- fprintf(stderr, "failed to own primary\n");
+ if (buffer) {
+ if (selection == False) {
+ XSetSelectionOwner(m_display, m_clipboard, m_window, CurrentTime);
+ owner= XGetSelectionOwner(m_display, m_clipboard);
+ if (txt_cut_buffer)
+ free((void*)txt_cut_buffer);
+
+ txt_cut_buffer = (char*) malloc(strlen(buffer)+1);
+ strcpy(txt_cut_buffer, buffer);
+ } else {
+ XSetSelectionOwner(m_display, m_primary, m_window, CurrentTime);
+ owner= XGetSelectionOwner(m_display, m_primary);
+ if (txt_select_buffer)
+ free((void*)txt_select_buffer);
+
+ txt_select_buffer = (char*) malloc(strlen(buffer)+1);
+ strcpy(txt_select_buffer, buffer);
+ }
- return;
+ if (owner != m_window)
+ fprintf(stderr, "failed to own primary\n");
+ }
}
-
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index 6eacd88b8c2..711a188ffe9 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -199,20 +199,25 @@ public:
prepareNdofInfo(
volatile GHOST_TEventNDOFData *current_values
);
-
+
+ /* Helped function for get data from the clipboard. */
+ void getClipboard_xcout(XEvent evt, Atom sel, Atom target,
+ unsigned char **txt, unsigned long *len,
+ unsigned int *context) const;
+
/**
* Returns unsinged char from CUT_BUFFER0
* @param selection Get selection, X11 only feature
* @return Returns the Clipboard indicated by Flag
*/
- GHOST_TUns8* getClipboard(bool selection) const;
+ GHOST_TUns8 *getClipboard(bool selection) const;
/**
* Puts buffer to system clipboard
* @param buffer The buffer to copy to the clipboard
* @param selection Set the selection into the clipboard, X11 only feature
*/
- virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
+ void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
/**
* Atom used for ICCCM, WM-spec and Motif.
@@ -231,6 +236,17 @@ public:
Atom m_wm_protocols;
Atom m_delete_window_atom;
+ /* Atoms for Selection, copy & paste. */
+ Atom m_targets;
+ Atom m_string;
+ Atom m_compound_text;
+ Atom m_text;
+ Atom m_clipboard;
+ Atom m_primary;
+ Atom m_xclip_out;
+ Atom m_incr;
+ Atom m_utf8_string;
+
private :
Display * m_display;