Add more EWMH methods and helper methods.

Simplify dragging support code.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@25389 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2007-08-14 22:44:40 +00:00
parent 0dd2da6751
commit 32d116c7b2
3 changed files with 1198 additions and 783 deletions

View file

@ -1,3 +1,9 @@
2007-08-15 Fred Kiefer <FredKiefer@gmx.de>
* Source/x11/XGServerWindow.m: Add more EWMH methods and helper
methods for them.
* Tools/xpbs.m: Simplify dragging support code.
2007-08-13 Fred Kiefer <FredKiefer@gmx.de> 2007-08-13 Fred Kiefer <FredKiefer@gmx.de>
* Source/art/ftfont.m (-coveredCharacterSet): Correct code. * Source/art/ftfont.m (-coveredCharacterSet): Correct code.

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,7 @@
/* /*
* Non-predefined atoms that are used in the X selection mechanism * Non-predefined atoms that are used in the X selection mechanism
*/ */
static char* atom_names[] = { static char *atom_names[] = {
"CHARACTER_POSITION", "CHARACTER_POSITION",
"CLIENT_WINDOW", "CLIENT_WINDOW",
"HOST_NAME", "HOST_NAME",
@ -54,7 +54,17 @@ static char* atom_names[] = {
"UTF8_STRING", "UTF8_STRING",
"MULTIPLE", "MULTIPLE",
"COMPOUND_TEXT", "COMPOUND_TEXT",
"INCR" "INCR",
// MIME types
"text/plain",
"text/uri-list",
"application/postscript",
"text/tab-separated-values",
"text/richtext",
"image/tiff",
"application/octet-stream",
"application/x-rootwindow-drop"
}; };
static Atom atoms[sizeof(atom_names)/sizeof(char*)]; static Atom atoms[sizeof(atom_names)/sizeof(char*)];
@ -82,6 +92,8 @@ static Atom atoms[sizeof(atom_names)/sizeof(char*)];
#define XG_MULTIPLE atoms[17] #define XG_MULTIPLE atoms[17]
#define XG_COMPOUND_TEXT atoms[18] #define XG_COMPOUND_TEXT atoms[18]
#define XG_INCR atoms[19] #define XG_INCR atoms[19]
#define XG_MIME_PLAIN atoms[20]
#define XG_MIME_URI atoms[21]
@ -274,38 +286,38 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
while ((count = XPending(xDisplay)) > 0) while ((count = XPending(xDisplay)) > 0)
{ {
while (count-- > 0) while (count-- > 0)
{ {
XEvent xEvent; XEvent xEvent;
XNextEvent(xDisplay, &xEvent); XNextEvent(xDisplay, &xEvent);
switch (xEvent.type)
{
case PropertyNotify:
[self xPropertyNotify: (XPropertyEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"PropertyNotify.");
break;
case SelectionNotify:
[self xSelectionNotify: (XSelectionEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"SelectionNotify.");
break;
switch (xEvent.type) case SelectionClear:
{ [self xSelectionClear: (XSelectionClearEvent*)&xEvent];
case PropertyNotify: NSDebugLLog(@"Pbs", @"SelectionClear.");
[self xPropertyNotify: (XPropertyEvent*)&xEvent]; break;
NSDebugLLog(@"Pbs", @"PropertyNotify.");
break;
case SelectionNotify: case SelectionRequest:
[self xSelectionNotify: (XSelectionEvent*)&xEvent]; [self xSelectionRequest: (XSelectionRequestEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"SelectionNotify."); NSDebugLLog(@"Pbs", @"SelectionRequest.");
break; break;
case SelectionClear: default:
[self xSelectionClear: (XSelectionClearEvent*)&xEvent]; NSDebugLLog(@"Pbs", @"Unexpected X event.");
NSDebugLLog(@"Pbs", @"SelectionClear."); break;
break; }
}
case SelectionRequest:
[self xSelectionRequest: (XSelectionRequestEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"SelectionRequest.");
break;
default:
NSDebugLLog(@"Pbs", @"Unexpected X event.");
break;
}
}
} }
} }
@ -332,7 +344,7 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
char *name = XGetAtomName(xDisplay, xEvent->selection); char *name = XGetAtomName(xDisplay, xEvent->selection);
NSDebugLLog(@"Pbs", @"Selection clear for unknown selection - '%s'.", NSDebugLLog(@"Pbs", @"Selection clear for unknown selection - '%s'.",
name); name);
XFree(name); XFree(name);
return; return;
} }
@ -355,7 +367,7 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
{ {
char *name = XGetAtomName(xDisplay, xEvent->atom); char *name = XGetAtomName(xDisplay, xEvent->atom);
NSDebugLLog(@"Pbs", @"Property notify for unknown property - '%s'.", NSDebugLLog(@"Pbs", @"Property notify for unknown property - '%s'.",
name); name);
XFree(name); XFree(name);
return; return;
} }
@ -374,14 +386,14 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
+ (void) xSelectionNotify: (XSelectionEvent*)xEvent + (void) xSelectionNotify: (XSelectionEvent*)xEvent
{ {
XPbOwner *o; XPbOwner *o;
o = [self ownerByXPb: xEvent->selection]; o = [self ownerByXPb: xEvent->selection];
if (o == nil) if (o == nil)
{ {
char *name = XGetAtomName(xDisplay, xEvent->selection); char *name = XGetAtomName(xDisplay, xEvent->selection);
NSDebugLLog(@"Pbs", @"Selection notify for unknown selection - '%s'.", NSDebugLLog(@"Pbs", @"Selection notify for unknown selection - '%s'.",
name); name);
XFree(name); XFree(name);
return; return;
} }
@ -393,19 +405,19 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
} }
else else
{ {
char *sel_name = XGetAtomName(xDisplay, xEvent->selection); char *sel_name = XGetAtomName(xDisplay, xEvent->selection);
char *pro_name; char *pro_name;
if (xEvent->property == None)
pro_name = NULL;
else
pro_name = XGetAtomName(xDisplay, xEvent->property);
if (xEvent->property == None) NSDebugLLog(@"Pbs", @"Selection (%s) notify - '%s'.", sel_name,
pro_name = NULL; pro_name? pro_name : "None");
else XFree(sel_name);
pro_name = XGetAtomName(xDisplay, xEvent->property); if (pro_name)
XFree(pro_name);
NSDebugLLog(@"Pbs", @"Selection (%s) notify - '%s'.", sel_name,
pro_name? pro_name : "None");
XFree(sel_name);
if (pro_name)
XFree(pro_name);
} }
[o xSelectionNotify: xEvent]; [o xSelectionNotify: xEvent];
@ -420,7 +432,7 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
{ {
char *name = XGetAtomName(xDisplay, xEvent->selection); char *name = XGetAtomName(xDisplay, xEvent->selection);
NSDebugLLog(@"Pbs", @"Selection request for unknown selection - '%s'.", NSDebugLLog(@"Pbs", @"Selection request for unknown selection - '%s'.",
name); name);
XFree(name); XFree(name);
return; return;
} }
@ -505,7 +517,7 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
- (void) requestData: (Atom)xType - (void) requestData: (Atom)xType
{ {
Time whenRequested; Time whenRequested;
/* /*
* Do a nul append to a property to get a timestamp, if it returns the * Do a nul append to a property to get a timestamp, if it returns the
@ -514,7 +526,7 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
whenRequested = [self xTimeByAppending]; whenRequested = [self xTimeByAppending];
if (whenRequested != CurrentTime) if (whenRequested != CurrentTime)
{ {
NSDate *limit; NSDate *limit;
/* /*
* Ok - we got a timestamp, so we can ask the selection system for * Ok - we got a timestamp, so we can ask the selection system for
@ -523,7 +535,7 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
* appropriate property of our application root window. * appropriate property of our application root window.
*/ */
XConvertSelection(xDisplay, [self xPb], xType, XConvertSelection(xDisplay, [self xPb], xType,
[self xPb], xAppWin, whenRequested); [self xPb], xAppWin, whenRequested);
XFlush(xDisplay); XFlush(xDisplay);
/* /*
@ -534,19 +546,19 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
[self setWaitingForSelection: whenRequested]; [self setWaitingForSelection: whenRequested];
while ([self waitingForSelection] == whenRequested) while ([self waitingForSelection] == whenRequested)
{ {
[[NSRunLoop currentRunLoop] runMode: xWaitMode [[NSRunLoop currentRunLoop] runMode: xWaitMode
beforeDate: limit]; beforeDate: limit];
if ([limit timeIntervalSinceNow] <= 0.0) if ([limit timeIntervalSinceNow] <= 0.0)
break; /* Timeout */ break; /* Timeout */
} }
if ([self waitingForSelection] != 0) if ([self waitingForSelection] != 0)
{ {
char *name = XGetAtomName(xDisplay, xType); char *name = XGetAtomName(xDisplay, xType);
[self setWaitingForSelection: 0]; [self setWaitingForSelection: 0];
NSLog(@"Timed out waiting for X selection '%s'", name); NSLog(@"Timed out waiting for X selection '%s'", name);
XFree(name); XFree(name);
} }
} }
} }
@ -563,8 +575,13 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
{ {
[self requestData: XG_UTF8_STRING]; [self requestData: XG_UTF8_STRING];
if ([self data] == nil) if ([self data] == nil)
[self requestData: XA_STRING]; [self requestData: XA_STRING];
} }
else if ([type isEqual: NSFilenamesPboardType])
{
[self requestData: XG_FILE_NAME];
}
// FIXME: Support more types
else else
{ {
NSLog(@"Request for non-string info from X pasteboard: %@", type); NSLog(@"Request for non-string info from X pasteboard: %@", type);
@ -630,7 +647,7 @@ xErrorHandler(Display *d, XErrorEvent *e)
} }
- (NSMutableData*) getSelectionData: (XSelectionEvent*)xEvent - (NSMutableData*) getSelectionData: (XSelectionEvent*)xEvent
type: (Atom*)type type: (Atom*)type
{ {
int status; int status;
unsigned char *data; unsigned char *data;
@ -649,51 +666,51 @@ xErrorHandler(Display *d, XErrorEvent *e)
do do
{ {
status = XGetWindowProperty(xDisplay, status = XGetWindowProperty(xDisplay,
xEvent->requestor, xEvent->requestor,
xEvent->property, xEvent->property,
long_offset, // offset long_offset, // offset
long_length, long_length,
True, // Delete prop when read. True, // Delete prop when read.
req_type, req_type,
&actual_type, &actual_type,
&actual_format, &actual_format,
&number_items, &number_items,
&bytes_remaining, &bytes_remaining,
&data); &data);
if ((status == Success) && (number_items > 0)) if ((status == Success) && (number_items > 0))
{ {
long count = number_items * actual_format / 8; long count = number_items * actual_format / 8;
if (md == nil) if (md == nil)
{ {
md = [[NSMutableData alloc] initWithBytes: (void *)data md = [[NSMutableData alloc] initWithBytes: (void *)data
length: count]; length: count];
req_type = actual_type; req_type = actual_type;
} }
else else
{ {
if (req_type != actual_type) if (req_type != actual_type)
{ {
char *req_name = XGetAtomName(xDisplay, req_type); char *req_name = XGetAtomName(xDisplay, req_type);
char *act_name = XGetAtomName(xDisplay, actual_type); char *act_name = XGetAtomName(xDisplay, actual_type);
NSLog(@"Selection changed type from %s to %s.", NSLog(@"Selection changed type from %s to %s.",
req_name, act_name); req_name, act_name);
XFree(req_name); XFree(req_name);
XFree(act_name); XFree(act_name);
RELEASE(md); RELEASE(md);
return nil; return nil;
} }
[md appendBytes: (void *)data length: count]; [md appendBytes: (void *)data length: count];
} }
long_offset += count / 4; long_offset += count / 4;
if (data) if (data)
{ {
XFree(data); XFree(data);
} }
} }
} }
while ((status == Success) && (bytes_remaining > 0)); while ((status == Success) && (bytes_remaining > 0));
@ -733,79 +750,99 @@ xErrorHandler(Display *d, XErrorEvent *e)
if (md != nil) if (md != nil)
{ {
if (actual_type == XG_INCR) if (actual_type == XG_INCR)
{ {
XEvent event; XEvent event;
NSMutableData *imd = nil; NSMutableData *imd = nil;
BOOL wait = YES; BOOL wait = YES;
md = nil; md = nil;
while (wait) while (wait)
{ {
XNextEvent(xDisplay, &event); XNextEvent(xDisplay, &event);
if (event.type == PropertyNotify) if (event.type == PropertyNotify)
{ {
if (event.xproperty.state != PropertyNewValue) continue; if (event.xproperty.state != PropertyNewValue) continue;
imd = [self getSelectionData: xEvent type: &actual_type]; imd = [self getSelectionData: xEvent type: &actual_type];
if (imd != nil) if (imd != nil)
{ {
if (md == nil) if (md == nil)
{ {
md = imd; md = imd;
} }
else else
{ {
[md appendData: imd]; [md appendData: imd];
} }
} }
else else
{ {
wait = NO; wait = NO;
} }
} }
} }
} }
} }
if (md != nil) if (md != nil)
{ {
// Convert data to text string. // Convert data to text string.
if (actual_type == XG_UTF8_STRING) if (actual_type == XG_UTF8_STRING)
{ {
NSString *s; NSString *s;
NSData *d; NSData *d;
s = [[NSString alloc] initWithData: md s = [[NSString alloc] initWithData: md
encoding: NSUTF8StringEncoding]; encoding: NSUTF8StringEncoding];
if (s != nil) if (s != nil)
{ {
d = [NSSerializer serializePropertyList: s]; d = [NSSerializer serializePropertyList: s];
RELEASE(s); RELEASE(s);
[self setData: d]; [self setData: d];
} }
} }
else if (actual_type == XA_STRING) else if (actual_type == XA_STRING)
{ {
NSString *s; NSString *s;
NSData *d; NSData *d;
s = [[NSString alloc] initWithData: md
encoding: NSISOLatin1StringEncoding];
if (s != nil)
{
d = [NSSerializer serializePropertyList: s];
RELEASE(s);
[self setData: d];
}
}
else if (actual_type == XG_FILE_NAME)
{
NSArray *names;
NSData *d;
NSString *s;
NSURL *url;
s = [[NSString alloc] initWithData: md s = [[NSString alloc] initWithData: md
encoding: NSISOLatin1StringEncoding]; encoding: NSUTF8StringEncoding];
if (s != nil) url = [[NSURL alloc] initWithString: s];
{ RELEASE(s);
d = [NSSerializer serializePropertyList: s]; if ([url isFileURL])
RELEASE(s); {
[self setData: d]; s = [url path];
} names = [NSArray arrayWithObject: s];
} d = [NSSerializer serializePropertyList: names];
[self setData: d];
}
RELEASE(url);
}
else else
{ {
char *name = XGetAtomName(xDisplay, actual_type); char *name = XGetAtomName(xDisplay, actual_type);
NSLog(@"Unsupported data type '%s' from X selection.", name); NSLog(@"Unsupported data type '%s' from X selection.", name);
XFree(name); XFree(name);
} }
} }
} }
@ -873,16 +910,16 @@ xErrorHandler(Display *d, XErrorEvent *e)
if ([types containsObject: NSStringPboardType]) if ([types containsObject: NSStringPboardType])
{ {
xTypes[numTypes++] = XG_UTF8_STRING; xTypes[numTypes++] = XG_UTF8_STRING;
xTypes[numTypes++] = XG_COMPOUND_TEXT; xTypes[numTypes++] = XG_COMPOUND_TEXT;
xTypes[numTypes++] = XA_STRING; xTypes[numTypes++] = XA_STRING;
xTypes[numTypes++] = XG_TEXT; xTypes[numTypes++] = XG_TEXT;
} }
if ([types containsObject: NSFilenamesPboardType]) if ([types containsObject: NSFilenamesPboardType])
{ {
xTypes[numTypes++] = XG_FILE_NAME; xTypes[numTypes++] = XG_FILE_NAME;
} }
xType = XA_ATOM; xType = XA_ATOM;
format = 32; format = 32;
@ -906,59 +943,59 @@ xErrorHandler(Display *d, XErrorEvent *e)
*/ */
if ([types containsObject: NSStringPboardType]) if ([types containsObject: NSStringPboardType])
{ {
xEvent->target = XG_UTF8_STRING; xEvent->target = XG_UTF8_STRING;
[self xProvideSelection: xEvent]; [self xProvideSelection: xEvent];
} }
else if ([types containsObject: NSFilenamesPboardType]) else if ([types containsObject: NSFilenamesPboardType])
{ {
xEvent->target = XG_FILE_NAME; xEvent->target = XG_FILE_NAME;
[self xProvideSelection: xEvent]; [self xProvideSelection: xEvent];
} }
} }
else if (xEvent->target == XG_MULTIPLE) else if (xEvent->target == XG_MULTIPLE)
{ {
if (xEvent->property != None) if (xEvent->property != None)
{ {
Atom *multipleAtoms= NULL; Atom *multipleAtoms= NULL;
int actual_format; int actual_format;
Atom actual_type; Atom actual_type;
unsigned long number_items, bytes_remaining; unsigned long number_items, bytes_remaining;
int status; int status;
status = XGetWindowProperty(xDisplay, status = XGetWindowProperty(xDisplay,
xEvent->requestor, xEvent->requestor,
xEvent->property, xEvent->property,
0, 0,
100, 100,
False, False,
AnyPropertyType, AnyPropertyType,
&actual_type, &actual_type,
&actual_format, &actual_format,
&number_items, &number_items,
&bytes_remaining, &bytes_remaining,
(unsigned char **)&multipleAtoms); (unsigned char **)&multipleAtoms);
if ((status == Success) && (bytes_remaining == 0) && if ((status == Success) && (bytes_remaining == 0) &&
(actual_format == 32) && (actual_type == XA_ATOM)) (actual_format == 32) && (actual_type == XA_ATOM))
{ {
int i; int i;
XSelectionRequestEvent requestEvent; XSelectionRequestEvent requestEvent;
memcpy(&requestEvent, xEvent, sizeof(XSelectionRequestEvent)); memcpy(&requestEvent, xEvent, sizeof(XSelectionRequestEvent));
for (i = 0; i < number_items; i += 2) for (i = 0; i < number_items; i += 2)
{ {
requestEvent.target= multipleAtoms[i]; requestEvent.target= multipleAtoms[i];
requestEvent.property= multipleAtoms[i+1]; requestEvent.property= multipleAtoms[i+1];
if (requestEvent.target != None) if (requestEvent.target != None)
{ {
// Recursive call to this method for each pair. // Recursive call to this method for each pair.
if (![self xProvideSelection: &requestEvent]) if (![self xProvideSelection: &requestEvent])
{ {
multipleAtoms[i+1]= None; multipleAtoms[i+1]= None;
} }
} }
} }
// FIXME: Should we call XChangeProperty to set the invalid types? // FIXME: Should we call XChangeProperty to set the invalid types?
} }
} }
} }
else if ((xEvent->target == XG_COMPOUND_TEXT) && else if ((xEvent->target == XG_COMPOUND_TEXT) &&
@ -973,25 +1010,25 @@ xErrorHandler(Display *d, XErrorEvent *e)
d = [s cString]; d = [s cString];
if (d) if (d)
{ {
char *list[]= {(char *)d, NULL}; char *list[]= {(char *)d, NULL};
XTextProperty textProperty; XTextProperty textProperty;
status = XmbTextListToTextProperty(xEvent->display, list, 1, status = XmbTextListToTextProperty(xEvent->display, list, 1,
XCompoundTextStyle, &textProperty); XCompoundTextStyle, &textProperty);
if (status == Success) if (status == Success)
{ {
NSAssert(textProperty.format == 8, @"textProperty.format == 8"); NSAssert(textProperty.format == 8, @"textProperty.format == 8");
numItems = textProperty.nitems; numItems = textProperty.nitems;
data = malloc(numItems + 1); data = malloc(numItems + 1);
memcpy(data, textProperty.value, numItems + 1); memcpy(data, textProperty.value, numItems + 1);
XFree((void *)textProperty.value); XFree((void *)textProperty.value);
} }
} }
} }
else if (((xEvent->target == XG_UTF8_STRING) || else if (((xEvent->target == XG_UTF8_STRING) ||
(xEvent->target == XA_STRING) || (xEvent->target == XA_STRING) ||
(xEvent->target == XG_TEXT)) && (xEvent->target == XG_TEXT)) &&
[types containsObject: NSStringPboardType]) [types containsObject: NSStringPboardType])
{ {
NSString *s = [_pb stringForType: NSStringPboardType]; NSString *s = [_pb stringForType: NSStringPboardType];
NSData *d = nil; NSData *d = nil;
@ -1005,24 +1042,43 @@ xErrorHandler(Display *d, XErrorEvent *e)
*/ */
if (xType == XG_UTF8_STRING) if (xType == XG_UTF8_STRING)
{ {
d = [s dataUsingEncoding: NSUTF8StringEncoding]; d = [s dataUsingEncoding: NSUTF8StringEncoding];
} }
else if ((xType == XA_STRING) || (xType == XG_TEXT)) else if ((xType == XA_STRING) || (xType == XG_TEXT))
{ {
d = [s dataUsingEncoding: NSISOLatin1StringEncoding]; d = [s dataUsingEncoding: NSISOLatin1StringEncoding];
} }
if (d != nil) if (d != nil)
{ {
numItems = [d length]; numItems = [d length];
data = malloc(numItems + 1); data = malloc(numItems + 1);
if (data) if (data)
[d getBytes: data]; [d getBytes: data];
} }
} }
else if ((xEvent->target == XG_FILE_NAME) && else if ((xEvent->target == XG_FILE_NAME) &&
[types containsObject: NSFilenamesPboardType]) [types containsObject: NSFilenamesPboardType])
{ {
NSArray *names = [_pb propertyListForType: NSFilenamesPboardType];
NSString *file = [[names lastObject] stringByStandardizingPath];
NSURL *url = [[NSURL alloc] initWithScheme: NSURLFileScheme
host: @"localhost"
path: file];
NSString *s = [url absoluteString];
NSData *d;
xType = xEvent->target;
format = 8;
RELEASE(url);
d = [s dataUsingEncoding: NSISOLatin1StringEncoding];
if (d != nil)
{
numItems = [d length];
data = malloc(numItems + 1);
if (data)
[d getBytes: data];
}
} }
else else
{ {
@ -1034,12 +1090,12 @@ xErrorHandler(Display *d, XErrorEvent *e)
} }
return [self xSendData: data format: format items: numItems type: xType return [self xSendData: data format: format items: numItems type: xType
to: xEvent->requestor property: xEvent->property]; to: xEvent->requestor property: xEvent->property];
} }
- (BOOL) xSendData: (unsigned char*) data format: (int) format - (BOOL) xSendData: (unsigned char*) data format: (int) format
items: (int) numItems type: (Atom) xType items: (int) numItems type: (Atom) xType
to: (Window) window property: (Atom) property to: (Window) window property: (Atom) property
{ {
BOOL status = NO; BOOL status = NO;
@ -1061,23 +1117,23 @@ xErrorHandler(Display *d, XErrorEvent *e)
oldHandler = XSetErrorHandler(xErrorHandler); oldHandler = XSetErrorHandler(xErrorHandler);
while (appendFailure == NO && pos < numItems) while (appendFailure == NO && pos < numItems)
{ {
if (pos + maxItems > numItems) if (pos + maxItems > numItems)
{ {
maxItems = numItems - pos; maxItems = numItems - pos;
} }
XChangeProperty(xDisplay, window, property, XChangeProperty(xDisplay, window, property,
xType, format, mode, &data[pos*format/8], maxItems); xType, format, mode, &data[pos*format/8], maxItems);
mode = PropModeAppend; mode = PropModeAppend;
pos += maxItems; pos += maxItems;
XSync(xDisplay, False); XSync(xDisplay, False);
} }
free(data); free(data);
XSetErrorHandler(oldHandler); XSetErrorHandler(oldHandler);
if (appendFailure == NO) if (appendFailure == NO)
{ {
status = YES; status = YES;
} }
} }
return status; return status;
} }
@ -1125,7 +1181,7 @@ xErrorHandler(Display *d, XErrorEvent *e)
[[NSRunLoop currentRunLoop] runMode: xWaitMode [[NSRunLoop currentRunLoop] runMode: xWaitMode
beforeDate: limit]; beforeDate: limit];
if ([limit timeIntervalSinceNow] <= 0.0) if ([limit timeIntervalSinceNow] <= 0.0)
break; /* Timeout */ break; /* Timeout */
} }
if ((whenRequested = [self timeOfLastAppend]) == 0) if ((whenRequested = [self timeOfLastAppend]) == 0)
{ {
@ -1204,12 +1260,7 @@ static DndClass dnd;
NSArray *types; NSArray *types;
Atom *typelist; Atom *typelist;
// Some GNUstep application did grap the drag pasteboard. Report this to X. [super pasteboardChangedOwner: sender];
if (xdnd_set_selection_owner(&dnd, xAppWin, None))
{
NSLog(@"Failed to set X drag selection owner to the pasteboard server.");
}
[self setOwnedByOpenStep: YES];
// We also have to set the supported types for our window // We also have to set the supported types for our window
types = [_pb types]; types = [_pb types];
@ -1237,35 +1288,9 @@ static DndClass dnd;
{ {
NSString *mime = [NSPasteboard mimeTypeForPasteboardType: type]; NSString *mime = [NSPasteboard mimeTypeForPasteboardType: type];
Atom mType = XInternAtom(xDisplay, [mime cString], False); Atom mType = XInternAtom(xDisplay, [mime cString], False);
Window window;
Time whenRequested = CurrentTime;
NSDate *limit;
[self setData: nil]; [self setData: nil];
// How can we get the selection owner? [self requestData: mType];
window = XGetSelectionOwner(xDisplay, dnd.XdndSelection);
xdnd_convert_selection(&dnd, window, xAppWin, mType);
XFlush(xDisplay);
/*
* Run an event loop to read X events until we have aquired the
* pasteboard data we need.
*/
limit = [NSDate dateWithTimeIntervalSinceNow: 20.0];
[self setWaitingForSelection: whenRequested];
while ([self waitingForSelection] == whenRequested)
{
[[NSRunLoop currentRunLoop] runMode: xWaitMode
beforeDate: limit];
if ([limit timeIntervalSinceNow] <= 0.0)
break; /* Timeout */
}
if ([self waitingForSelection] != 0)
{
[self setWaitingForSelection: 0];
NSLog(@"Timed out waiting for X selection");
}
[pb setData: [self data] forType: type]; [pb setData: [self data] forType: type];
} }