forked from bartvdbraak/blender
Commit revision 20062 and 20109 from trunk, also fix a small memory
error on interface, was try to free an incorrect pointer.
This commit is contained in:
parent
4022380dc6
commit
96348bc772
@ -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();
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_SystemX11::
|
||||
putClipboard(
|
||||
GHOST_TInt8 *buffer, 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); }
|
||||
|
||||
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); }
|
||||
|
||||
txt_select_buffer = (char*) malloc(strlen(buffer)+1);
|
||||
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();
|
||||
// add data to ltxt
|
||||
memcpy(<xt[*len - pty_items], buffer, pty_items);
|
||||
|
||||
if(!Primary_atom) {
|
||||
return;
|
||||
*txt = ltxt;
|
||||
XFree(buffer);
|
||||
|
||||
// delete property to get the next item
|
||||
XDeleteProperty(m_display, win, m_xclip_out);
|
||||
XFlush(m_display);
|
||||
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");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
|
||||
{
|
||||
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';
|
||||
|
||||
if (sseln == m_string)
|
||||
XFree(sel_buf);
|
||||
else
|
||||
free(sel_buf);
|
||||
|
||||
return (GHOST_TUns8*)tmp_data;
|
||||
}
|
||||
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 (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);
|
||||
}
|
||||
|
||||
if (owner != m_window)
|
||||
fprintf(stderr, "failed to own primary\n");
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -651,7 +651,8 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
|
||||
|
||||
if(mode=='v') {
|
||||
/* extract first line from clipboard in case of multi-line copies */
|
||||
char *p = WM_clipboard_text_get(0);
|
||||
char *p, *pbuf= WM_clipboard_text_get(0);
|
||||
p= pbuf;
|
||||
if(p) {
|
||||
int i = 0;
|
||||
while (*p && *p!='\r' && *p!='\n' && i<UI_MAX_DRAW_STR) {
|
||||
@ -659,7 +660,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
|
||||
p++;
|
||||
}
|
||||
buf[i]= 0;
|
||||
MEM_freeN(p);
|
||||
MEM_freeN(pbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user