xserver: Branch 'xorg-server-1.4-apple'

George Peter Staplin gstaplin at kemper.freedesktop.org
Mon Oct 27 15:41:06 PDT 2008


 hw/xquartz/pbproxy/x-selection.h |    1 
 hw/xquartz/pbproxy/x-selection.m |  209 ++++++++++++++++++++++++++-------------
 2 files changed, 141 insertions(+), 69 deletions(-)

New commits:
commit 8d048cfa956f4a0860250cc836a6748912b37ad8
Author: George Peter Staplin <gps at Georges-Workstation.local>
Date:   Mon Oct 27 16:34:24 2008 -0600

    XQuartz: pbproxy: Add code to handle PICT conversion to PNG and JPEG.
    
    This may work, unfortunately I don't have test apps that fail.
    
    The way it works is by using an NSImage class initWithPasteboard:
    method, which we then get the TIFFRepresentation of, and convert
    to PNG or JPEG.
    
    The TIFFRepresentation uses NSTIFFCompressionNone; which should be
    lossless.

diff --git a/hw/xquartz/pbproxy/x-selection.h b/hw/xquartz/pbproxy/x-selection.h
index 7a26a21..67170ac 100644
--- a/hw/xquartz/pbproxy/x-selection.h
+++ b/hw/xquartz/pbproxy/x-selection.h
@@ -107,6 +107,7 @@ struct atom_list {
 
 - (void) reload_preferences;
 - (BOOL) is_active;
+- (void) send_none:(XSelectionRequestEvent *)e;
 @end
 
 /* main.m */
diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m
index f17970c..5290c8f 100644
--- a/hw/xquartz/pbproxy/x-selection.m
+++ b/hw/xquartz/pbproxy/x-selection.m
@@ -35,6 +35,8 @@
 #include <stdlib.h>
 #include <X11/Xatom.h>
 #include <X11/Xutil.h>
+#import <AppKit/NSGraphics.h>
+#import <AppKit/NSImage.h>
 #import <AppKit/NSBitmapImageRep.h>
 
 /*
@@ -58,15 +60,17 @@
 
 /*
  * TODO:
- * 1. handle  MULTIPLE - I need to study the ICCCM further.
- * 2. Handle PICT images properly.
- * 3. Handle NSPasteboard updates immediately, not on active/inactive
+ * 1. handle MULTIPLE - I need to study the ICCCM further, and find a test app.
+ * 2. Handle NSPasteboard updates immediately, not on active/inactive
  *    - Open xterm, run 'cat readme.txt | pbcopy'
  */
 
 static struct {
     BOOL active ;
-    BOOL primary_on_grab; // This is provided as an option for people who want it and has issues that won't ever be addressed to make it *always* work
+    BOOL primary_on_grab; /* This is provided as an option for people who
+			   * want it and has issues that won't ever be
+			   * addressed to make it *always* work.
+			   */
     BOOL clipboard_to_pasteboard;
     BOOL pasteboard_to_primary;
     BOOL pasteboard_to_clipboard;
@@ -410,7 +414,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 }
 
 /* Called when the Edit/Copy item on the main X11 menubar is selected
-   and no appkit window claims it. */
+ * and no appkit window claims it. */
 - (void) x_copy:(Time)timestamp
 {
     Window w;
@@ -620,7 +624,8 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 	 * functionality in send_image.
 	 */
 
-	if ([pbtypes containsObject:NSTIFFPboardType]) 
+	if ([pbtypes containsObject:NSPICTPboardType] 
+	    || [pbtypes containsObject:NSTIFFPboardType]) 
 	{
 	    /* We can convert a TIFF to a PNG or JPEG. */
 	    DB ("NSTIFFPboardType\n");
@@ -775,93 +780,159 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
     [self send_reply:&reply];
 }
 
+/* Return nil if an error occured. */
+/* DO NOT retain the encdata for longer than the length of an event response.  
+ * The autorelease pool will reuse/free it.
+ */ 
+- (NSData *) encode_image_data:(NSData *)data type:(NSBitmapImageFileType)enctype
+{
+    NSBitmapImageRep *bmimage = nil; 
+    NSData *encdata = nil;
+    NSDictionary *dict = nil;
 
-- (void) send_image:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb
+    bmimage = [[NSBitmapImageRep alloc] initWithData:data];
+
+    if (nil == bmimage)
+	return nil;
+
+    dict = [[NSDictionary alloc] init];
+    encdata = [bmimage representationUsingType:enctype properties:dict];
+
+    if (nil == encdata)
+    {
+	[dict autorelease];
+	[bmimage autorelease];
+	return nil;
+    }
+    
+    [dict autorelease];
+    [bmimage autorelease];
+
+    return encdata;
+}
+
+/* Return YES when an error has occured when trying to send the PICT. */
+/* The caller should send a default reponse with a property of None when an error occurs. */
+- (BOOL) send_image_pict_reply:(XSelectionRequestEvent *)e 
+		    pasteboard:(NSPasteboard *)pb 
+			  type:(NSBitmapImageFileType)imagetype
 {
     XEvent reply;
-    NSArray *pbtypes;
-    NSString *type = nil;
-    NSBitmapImageFileType imagetype = /*quiet warning*/ NSPNGFileType; 
-    NSData *data;
+    NSImage *img = nil;
+    NSData *data = nil, *encdata = nil;
+    NSUInteger length;
+    const void *bytes = NULL;
+    
+    img = [[NSImage alloc] initWithPasteboard:pb];
 
-    TRACE ();
+    if (nil == img) 
+    {
+	return YES;
+    }
+	    
+    data = [img TIFFRepresentation];
+
+    if (nil == data)
+    {
+	[img autorelease];
+	fprintf(stderr, "unable to convert PICT to TIFF!\n");
+	return YES;
+    }
+        
+    encdata = [self encode_image_data:data type:imagetype];
+    if(nil == encdata)
+    {
+	[img autorelease];
+	return YES;
+    }
 
     [self init_reply:&reply request:e];
 
-    pbtypes = [pb types];
+    length = [encdata length];
+    bytes = [encdata bytes];
+    
+    XChangeProperty (x_dpy, e->requestor, e->property, e->target,
+		     8, PropModeReplace, bytes, length);
+    reply.xselection.property = e->property;
 
-    if (pbtypes) 
-    {
-	if ([pbtypes containsObject:NSTIFFPboardType])
-	    type = NSTIFFPboardType;
+    [self send_reply:&reply];
 
-	/* PICT is not yet supported by pbproxy. 
-	 * The NSBitmapImageRep doesn't support it. 
-	else if ([pbtypes containsObject:NSPICTPboardType])
-	    type  = NSPICTPboardType;
-	*/
-    }
+    [img autorelease];
+
+    return NO; /*no error*/
+}
+
+/* Return YES if an error occured. */
+/* The caller should send a reply with a property of None when an error occurs. */
+- (BOOL) send_image_tiff_reply:(XSelectionRequestEvent *)e
+		    pasteboard:(NSPasteboard *)pb 
+			  type:(NSBitmapImageFileType)imagetype
+{
+    XEvent reply;
+    NSData *data = nil;
+    NSData *encdata = nil;
+    NSUInteger length;
+    const void *bytes = NULL;
+
+    data = [pb dataForType:NSTIFFPboardType];
+
+    if (nil == data)
+ 	return YES;
+  
+    encdata = [self encode_image_data:data type:imagetype];
+
+    if(nil == encdata)
+	return YES;
+
+    [self init_reply:&reply request:e];
+
+    length = [encdata length];
+    bytes = [encdata bytes];
+    
+    XChangeProperty (x_dpy, e->requestor, e->property, e->target,
+		     8, PropModeReplace, bytes, length);
+    reply.xselection.property = e->property;
+    
+    [self send_reply:&reply];
+
+    return NO; /*no error*/
+}
+
+- (void) send_image:(XSelectionRequestEvent *)e pasteboard:(NSPasteboard *)pb
+{
+    NSArray *pbtypes = nil;
+    NSBitmapImageFileType imagetype = NSPNGFileType;
+
+    TRACE ();
 
     if (e->target == atoms->image_png)
 	imagetype = NSPNGFileType;
     else if (e->target == atoms->image_jpeg)
 	imagetype = NSJPEGFileType;
-    
-    
-    if (nil == type) 
+    else 
     {
-	[self send_reply:&reply];
-	return;
+	fprintf(stderr, "internal failure in xpbproxy!  imagetype being sent isn't PNG or JPEG.\n");
     }
 
-    data = [pb dataForType:type];
+    pbtypes = [pb types];
 
-    if (nil == data)
-    {
-	[self send_reply:&reply];
-	return;
-    }
-	 
-    if (NSTIFFPboardType == type)
+    if (pbtypes) 
     {
-  	NSBitmapImageRep *bmimage = [[NSBitmapImageRep alloc] initWithData:data];
-	NSDictionary *dict;
-	NSData *encdata;
-
-	if (nil == bmimage)
+	if ([pbtypes containsObject:NSTIFFPboardType])
 	{
-	    [self send_reply:&reply];
-	    return;
-	}
-
-	DB ("bmimage retainCount after initWithData %u\n", [bmimage retainCount]);
-
-	dict = [[NSDictionary alloc] init];
-	encdata = [bmimage representationUsingType:imagetype properties:dict];
-	if (encdata)
+	    if (NO == [self send_image_tiff_reply:e pasteboard:pb type:imagetype]) 
+	  	return;
+	} 
+     	else if ([pbtypes containsObject:NSPICTPboardType])
 	{
-	    NSUInteger length;
-	    const void *bytes;
-	    
-	    length = [encdata length];
-	    bytes = [encdata bytes];
-	    
-	    XChangeProperty (x_dpy, e->requestor, e->property, e->target,
-			     8, PropModeReplace, bytes, length);
-	    reply.xselection.property = e->property;
-	    
-	    DB ("changed property for %s\n", XGetAtomName (x_dpy, e->target));
-	    DB ("encdata retainCount %u\n", [encdata retainCount]);
-	}
-	DB ("dict retainCount before release %u\n", [dict retainCount]);
-	[dict autorelease];
+	    if (NO == [self send_image_pict_reply:e pasteboard:pb type:imagetype]) 
+		return;
 
-	DB ("bmimage retainCount before release %u\n", [bmimage retainCount]);
-	
-	[bmimage autorelease];
+	    /* Fall through intentionally to the send_none: */
+	}
     }
 
-    [self send_reply:&reply];
+    [self send_none:e];
 }
 
 - (void)send_none:(XSelectionRequestEvent *)e


More information about the xorg-commit mailing list