xserver: Branch 'xorg-server-1.5-apple' - 8 commits

Jeremy Huddleston jeremyhu at kemper.freedesktop.org
Tue Oct 28 22:02:51 PDT 2008


 hw/xquartz/GL/capabilities.c              |  437 +++++++++++++++++++++++++++---
 hw/xquartz/GL/capabilities.h              |   29 +
 hw/xquartz/GL/indirect.c                  |    2 
 hw/xquartz/GL/visualConfigs.c             |  165 +++++++----
 hw/xquartz/mach-startup/Makefile.am       |    4 
 hw/xquartz/mach-startup/bundle-main.c     |   29 -
 hw/xquartz/mach-startup/mach_startup.defs |    4 
 hw/xquartz/mach-startup/stub.c            |   26 +
 hw/xquartz/pbproxy/x-selection.h          |    1 
 hw/xquartz/pbproxy/x-selection.m          |  288 +++++++++++++------
 10 files changed, 758 insertions(+), 227 deletions(-)

New commits:
commit 953e0c2f595a2ce087ca066085fbc069b340e3f8
Author: Jeremy Huddleston <jeremyhu at freedesktop.org>
Date:   Tue Oct 28 12:38:05 2008 -0700

    XQuartz: Pass along SIGINT and SIGTERM from the stub to X11.app
    (cherry picked from commit 183ca5d68b4f34e248749f304ce140de11bd451b)

diff --git a/hw/xquartz/mach-startup/Makefile.am b/hw/xquartz/mach-startup/Makefile.am
index 97539e1..800fb0c 100644
--- a/hw/xquartz/mach-startup/Makefile.am
+++ b/hw/xquartz/mach-startup/Makefile.am
@@ -1,14 +1,12 @@
 AM_CPPFLAGS = \
 	-DBUILD_DATE=\"$(BUILD_DATE)\" \
-	-DXSERVER_VERSION=\"$(VERSION)\" \
-	-DMACHO_STARTUP
+	-DXSERVER_VERSION=\"$(VERSION)\"
 
 x11appdir = $(APPLE_APPLICATIONS_DIR)/X11.app/Contents/MacOS
 x11app_PROGRAMS = X11
 
 dist_X11_SOURCES = \
 	bundle-main.c 
-#	launchd_fd.c
 
 nodist_X11_SOURCES = \
 	mach_startupServer.c \
diff --git a/hw/xquartz/mach-startup/bundle-main.c b/hw/xquartz/mach-startup/bundle-main.c
index 576a370..9f03647 100644
--- a/hw/xquartz/mach-startup/bundle-main.c
+++ b/hw/xquartz/mach-startup/bundle-main.c
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 #include <pthread.h>
 #include <stdbool.h>
+#include <signal.h>
 
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -96,7 +97,6 @@ static pthread_t create_thread(void *func, void *arg) {
     return tid;
 }
 
-#ifdef MACHO_STARTUP
 /*** Mach-O IPC Stuffs ***/
 
 union MaxMsgSize {
@@ -303,6 +303,11 @@ kern_return_t do_request_fd_handoff_socket(mach_port_t port, string_t filename)
     return KERN_SUCCESS;
 }
 
+kern_return_t do_request_pid(mach_port_t port, int *my_pid) {
+    *my_pid = getpid();
+    return KERN_SUCCESS;
+}
+
 /*** Server Startup ***/
 kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
                                   mach_msg_type_number_t argvCnt,
@@ -336,17 +341,11 @@ kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
 }
 
 int startup_trigger(int argc, char **argv, char **envp) {
-#else
-void *add_launchd_display_thread(void *data);
-
-int main(int argc, char **argv, char **envp) {
-#endif
     Display *display;
     const char *s;
     
     /* Take care of the case where we're called like a normal DDX */
     if(argc > 1 && argv[1][0] == ':') {
-#ifdef MACHO_STARTUP
         size_t i;
         kern_return_t kr;
         mach_port_t mp;
@@ -387,10 +386,6 @@ int main(int argc, char **argv, char **envp) {
             exit(EXIT_FAILURE);
         }
         exit(EXIT_SUCCESS);
-#else
-        create_thread(add_launchd_display_thread, NULL);
-        return server_main(argc, argv, envp);
-#endif
     }
 
     /* If we have a process serial number and it's our only arg, act as if
@@ -424,7 +419,6 @@ int main(int argc, char **argv, char **envp) {
     return execute(command_from_prefs("startx_script", DEFAULT_STARTX));
 }
 
-#ifdef MACHO_STARTUP
 /*** Main ***/
 int main(int argc, char **argv, char **envp) {
     Bool listenOnly = FALSE;
@@ -472,17 +466,6 @@ int main(int argc, char **argv, char **envp) {
     
     return EXIT_SUCCESS;
 }
-#else
-
-void *add_launchd_display_thread(void *data) {
-    /* Start listening on the launchd fd */
-    int launchd_fd = launchd_display_fd();
-    if(launchd_fd != -1) {
-        DarwinListenOnOpenFD(launchd_fd);
-    }
-    return NULL;
-}
-#endif
     
 static int execute(const char *command) {
     const char *newargv[7];
diff --git a/hw/xquartz/mach-startup/mach_startup.defs b/hw/xquartz/mach-startup/mach_startup.defs
index 76c8edf..e47f49c 100644
--- a/hw/xquartz/mach-startup/mach_startup.defs
+++ b/hw/xquartz/mach-startup/mach_startup.defs
@@ -44,3 +44,7 @@ routine start_x11_server(
 routine request_fd_handoff_socket (
         port             : mach_port_t;
     out socket_filename  : string_t);
+
+routine request_pid (
+        port    : mach_port_t;
+    out pid     : int);
diff --git a/hw/xquartz/mach-startup/stub.c b/hw/xquartz/mach-startup/stub.c
index 192a432..8bbd4d9 100644
--- a/hw/xquartz/mach-startup/stub.c
+++ b/hw/xquartz/mach-startup/stub.c
@@ -48,6 +48,8 @@
 #include <servers/bootstrap.h>
 #include "mach_startup.h"
 
+#include <signal.h>
+
 #include "launchd_fd.h"
 
 #ifndef BUILD_DATE
@@ -61,6 +63,8 @@
 
 static char x11_path[PATH_MAX + 1];
 
+static pid_t x11app_pid = 0;
+
 static void set_x11_path() {
     CFURLRef appURL = NULL;
     CFBundleRef bundle = NULL;
@@ -115,7 +119,6 @@ static void set_x11_path() {
     }
 }
 
-#ifdef MACHO_STARTUP
 static int connect_to_socket(const char *filename) {
     struct sockaddr_un servaddr_un;
     struct sockaddr *servaddr;
@@ -189,10 +192,13 @@ static void send_fd_handoff(int connected_fd, int launchd_fd) {
     close(connected_fd);
 }
 
-#endif
+static void signal_handler(int sig) {
+    if(x11app_pid)
+        kill(x11app_pid, sig);
+    _exit(0);
+}
 
 int main(int argc, char **argv, char **envp) {
-#ifdef MACHO_STARTUP
     int envpc;
     kern_return_t kr;
     mach_port_t mp;
@@ -201,7 +207,6 @@ int main(int argc, char **argv, char **envp) {
     size_t i;
     int launchd_fd;
     string_t handoff_socket_filename;
-#endif
     sig_t handler;
 
     if(argc == 2 && !strcmp(argv[1], "-version")) {
@@ -220,7 +225,10 @@ int main(int argc, char **argv, char **envp) {
         kill(getppid(), SIGUSR1);
     signal(SIGUSR1, handler);
 
-#ifdef MACHO_STARTUP
+    /* Pass on SIGs to X11.app */
+    signal(SIGINT, signal_handler);
+    signal(SIGTERM, signal_handler);
+    
     /* Get the $DISPLAY FD */
     launchd_fd = launchd_display_fd();
 
@@ -258,6 +266,9 @@ int main(int argc, char **argv, char **envp) {
         }
     }
     
+    /* Get X11.app's pid */
+    request_pid(mp, &x11app_pid);
+
     /* Handoff the $DISPLAY FD */
     if(launchd_fd != -1) {
         size_t try, try_max;
@@ -308,9 +319,4 @@ int main(int argc, char **argv, char **envp) {
         return EXIT_FAILURE;
     }
     return EXIT_SUCCESS;
-#else
-    set_x11_path();
-    argv[0] = x11_path;
-    return execvp(x11_path, argv);
-#endif
 }
commit c1cd92dc2fbbbd32f439ea5e3286d2ff40f2f962
Author: George Peter Staplin <gps at Georges-Workstation.local>
Date:   Mon Oct 27 22:07:00 2008 -0600

    XQuartz: pbproxy: Fix a bug that prevented nedit CLIPBOARD from being proxied.
    
    It seems that we were calling copy_completed: too soon.  Now we return instead
    of falling through to the free_propdata, and copy_completed:.
    (cherry picked from commit 5797d5b662817a3369a74a673f4a7c995cde75cf)

diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m
index 59b38bd..490fcec 100644
--- a/hw/xquartz/pbproxy/x-selection.m
+++ b/hw/xquartz/pbproxy/x-selection.m
@@ -236,7 +236,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 
     for (i = 0; i < pdata->length; i += sizeof (a))
     {
-	a = 0;
+	a = None;
 	memcpy (&a, pdata->data + i, sizeof (a));
 
 	if (a == atoms->image_png)
@@ -1095,6 +1095,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
     
     if (None != e->atom) 
     {
+#ifdef DEBUG
 	char *name = XGetAtomName (x_dpy, e->atom);
 
 	if (name) 
@@ -1102,6 +1103,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 	    DB ("e->atom %s\n", name);
 	    XFree(name);
 	}
+#endif
     }
 
     if (None != pending.requestor && PropertyNewValue == e->state) 
@@ -1157,6 +1159,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 {
     /* Find a type we can handle and prefer from the list of ATOMs. */
     Atom preferred;
+    char *name;
 
     TRACE ();
 
@@ -1171,7 +1174,15 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 	preferred = atoms->string;
     }
 
-    DB ("requesting %s\n", XGetAtomName (x_dpy, preferred));
+    (void)name; /* Avoid a warning with non-debug compiles. */
+#ifdef DEBUG
+    name = XGetAtomName (x_dpy, preferred);
+
+    if (name)
+    {
+	DB ("requesting %s\n", name);
+    }
+#endif
     request_atom = preferred;
     XConvertSelection (x_dpy, selection, preferred, selection,
 		       _selection_window, CurrentTime);    
@@ -1272,7 +1283,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
     [pb declareTypes:pbtypes owner:nil];
     
     if (YES != [pb setString:string forType:NSStringPboardType]) {
-	DB ("pasteboard setString:forType: failed!\n");
+	fprintf(stderr, "pasteboard setString:forType: failed!\n");
     }
     [string autorelease];
     DB ("done handling utf8 string\n");
@@ -1300,7 +1311,9 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
     }
 
     [pb declareTypes:pbtypes owner:nil];
-    [pb setString:string forType:NSStringPboardType];
+    if (YES != [pb setString:string forType:NSStringPboardType]) {
+	fprintf(stderr, "pasteboard setString:forType failed in handle_string!\n");
+    }
     [string autorelease];
 }
 
@@ -1321,21 +1334,16 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 	return;
     }
 
-#if 0
-    if (None != request_atom)
-	printf ("request_atom %s\n", XGetAtomName (x_dpy, request_atom));
-	       
-    printf ("type %s\n", XGetAtomName (x_dpy, type));
-#endif
-
     /*
      * Some apps it seems set the type to TARGETS instead of ATOM, such as Eterm.
      * These aren't ICCCM compliant apps, but we need these to work... 
      */
-    if (request_atom == atoms->targets 
+    if (request_atom == atoms->targets
 	&& (type == atoms->atom || type == atoms->targets))
     {
 	[self handle_targets:selection propdata:pdata];
+	free_propdata(pdata);
+	return;
     } 
     else if (type == atoms->image_png)
     {
@@ -1353,7 +1361,7 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
     {
 	[self handle_string:pdata pasteboard:pb];
     } 
-    
+   
     free_propdata(pdata);
 
     [self copy_completed:selection];
commit 7f096c8c174815c9a0344b74655bef7732d2aa59
Author: George Peter Staplin <gps at Georges-Workstation.local>
Date:   Mon Oct 27 20:44:02 2008 -0600

    XQuartz: pbproxy: Work around bugs in some apps that aren't ICCCM compliant.
    
    Eterm ends up setting the type of the property to TARGETS, instead of ATOM.
    That's why it wasn't working.
    (cherry picked from commit 9be5998ede7427f14dd9597e117b3d6b427ba4e5)

diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m
index 5290c8f..59b38bd 100644
--- a/hw/xquartz/pbproxy/x-selection.m
+++ b/hw/xquartz/pbproxy/x-selection.m
@@ -236,12 +236,13 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 
     for (i = 0; i < pdata->length; i += sizeof (a))
     {
+	a = 0;
 	memcpy (&a, pdata->data + i, sizeof (a));
-	
+
 	if (a == atoms->image_png)
 	{
 	    png = True;
-	} 
+	}
 	else if (a == atoms->image_jpeg)
 	{
 	    jpeg = True;
@@ -257,8 +258,11 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 	else
 	{
 	    char *type = XGetAtomName(x_dpy, a);
-	    DB("Unhandled X11 mime type: %s", type);
-	    XFree(type);
+	    if (type)
+	    {
+		DB("Unhandled X11 mime type: %s", type);
+		XFree(type);
+	    }
 	}
     }
 
@@ -482,8 +486,10 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
  */
 - (void) clear_event:(XSelectionClearEvent *)e
 {
-    TRACE ();
     
+
+    TRACE ();
+        
     DB ("e->selection %s\n", XGetAtomName (x_dpy, e->selection));
     
     if(e->selection == atoms->clipboard) {
@@ -1087,9 +1093,16 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 
     TRACE ();
     
-    if (None != e->atom)
-	DB ("e->atom %s\n", XGetAtomName (x_dpy, e->atom));
+    if (None != e->atom) 
+    {
+	char *name = XGetAtomName (x_dpy, e->atom);
 
+	if (name) 
+	{
+	    DB ("e->atom %s\n", name);
+	    XFree(name);
+	}
+    }
 
     if (None != pending.requestor && PropertyNewValue == e->state) 
     {
@@ -1315,7 +1328,12 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
     printf ("type %s\n", XGetAtomName (x_dpy, type));
 #endif
 
-    if (request_atom == atoms->targets && type == atoms->atom)
+    /*
+     * Some apps it seems set the type to TARGETS instead of ATOM, such as Eterm.
+     * These aren't ICCCM compliant apps, but we need these to work... 
+     */
+    if (request_atom == atoms->targets 
+	&& (type == atoms->atom || type == atoms->targets))
     {
 	[self handle_targets:selection propdata:pdata];
     } 
@@ -1345,8 +1363,17 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 - (void) copy_completed:(Atom)selection
 {
     TRACE ();
-    
-    DB ("copy_completed: %s\n", XGetAtomName (x_dpy, selection));
+    char *name;
+
+    (void)name; /* Avoid warning with non-debug compiles. */
+#ifdef DEBUG
+    name = XGetAtomName (x_dpy, selection);
+    if (name)
+    {
+	DB ("copy_completed: %s\n", name);
+	XFree (name);
+    }
+#endif
 
     if (selection == atoms->primary && pending_copy > 0)
     {
commit 7cf23e472c88cda8312c9603ec0a66925d348f24
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.
    (cherry picked from commit 8d048cfa956f4a0860250cc836a6748912b37ad8)

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
commit d79c5811357db6d1b586a9d395cac535fd8c2c58
Author: Jeremy Huddleston <jeremyhu at freedesktop.org>
Date:   Sun Oct 26 13:17:49 2008 -0700

    XQuartz: pbproxy: fixed blocking
    (cherry picked from commit bb330a1b1c480e89727fb75ff5aeb71f4afc5ee3)

diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m
index b95dfbf..f17970c 100644
--- a/hw/xquartz/pbproxy/x-selection.m
+++ b/hw/xquartz/pbproxy/x-selection.m
@@ -250,11 +250,12 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 	{
 	    string = True;
 	}
-    else
-    {
-        const char *type = XGetAtomName(x_dpy, a);
-        DB("Unhandled X11 mime type: %s", type);
-        Xfree(type);
+	else
+	{
+	    char *type = XGetAtomName(x_dpy, a);
+	    DB("Unhandled X11 mime type: %s", type);
+	    XFree(type);
+	}
     }
 
     /*We prefer PNG over strings, and UTF8 over a Latin-1 string.*/
commit f7b9ceea1ec26d216fe25292772d6f89e46edfc3
Author: Jeremy Huddleston <jeremyhu at freedesktop.org>
Date:   Sun Oct 26 10:22:12 2008 -0700

    Xquartz: pbproxy: Some debugging about unhandled mime types... this will spam up quick, but will be useful for a while...
    (cherry picked from commit 3647215310f5a52126661b9ec473dcfeed25b40f)

diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m
index 3cc1201..b95dfbf 100644
--- a/hw/xquartz/pbproxy/x-selection.m
+++ b/hw/xquartz/pbproxy/x-selection.m
@@ -250,6 +250,11 @@ get_property(Window win, Atom property, struct propdata *pdata, Bool delete, Ato
 	{
 	    string = True;
 	}
+    else
+    {
+        const char *type = XGetAtomName(x_dpy, a);
+        DB("Unhandled X11 mime type: %s", type);
+        Xfree(type);
     }
 
     /*We prefer PNG over strings, and UTF8 over a Latin-1 string.*/
commit a269d54c32d9be11ecb8fed291391759b7093490
Author: George Peter Staplin <gps at Georges-Workstation.local>
Date:   Fri Oct 24 19:12:05 2008 -0600

    XQuartz: GL: Fix several error handling mistakes in handleRenderDescriptions, that were leftover before the final code evolved.
    (cherry picked from commit fe35a3639081dc78ac6cc4123cde37770f6a39fd)

diff --git a/hw/xquartz/GL/capabilities.c b/hw/xquartz/GL/capabilities.c
index 8101e49..b38dba8 100644
--- a/hw/xquartz/GL/capabilities.c
+++ b/hw/xquartz/GL/capabilities.c
@@ -285,7 +285,7 @@ static void handleAccumulationModes(struct glCapabilitiesConfig *c, GLint cmodes
     assert(c->total_accum_buffers < GLCAPS_COLOR_BUFFERS);
 }
 
-/* Return true if an error occured. */
+/* Return non-zero if an error occured. */
 static CGLError handleRendererDescriptions(CGLRendererInfoObj info, GLint r, 
 					   struct glCapabilitiesConfig *c) {
     CGLError err;
@@ -328,14 +328,14 @@ static CGLError handleRendererDescriptions(CGLRendererInfoObj info, GLint r,
     err = CGLDescribeRenderer(info, r, kCGLRPColorModes, &flags);
 
     if(err)
-	return true;
+	return err;
     
     handleColorModes(c, flags);
 
     err = CGLDescribeRenderer(info, r, kCGLRPAccumModes, &flags);
 
     if(err)
-	return true;
+	return err;
 
     handleAccumulationModes(c, flags);
     
commit 73566cef7c43b55d4b0d001dcdbf5115b1a1f16c
Author: George Peter Staplin <gps at Georges-Workstation.local>
Date:   Fri Oct 24 18:11:46 2008 -0600

    XQuartz: GL: Add feature detection of color sizes, and accum sizes.
    
    This gives us a *lot* more visuals, and they should be more accurate.
    Some of the visuals may have been wrong before.  This may enable more
    OpenGL programs to behave correctly.
    
    I also suspect libGL needs a little work to handle some of these correctly.
    (cherry picked from commit 98a084ce9c455260ecdb5f8eecb67f33dbb53b69)

diff --git a/hw/xquartz/GL/capabilities.c b/hw/xquartz/GL/capabilities.c
index 479fc93..8101e49 100644
--- a/hw/xquartz/GL/capabilities.c
+++ b/hw/xquartz/GL/capabilities.c
@@ -22,6 +22,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <assert.h>
 #include <OpenGL/OpenGL.h>
 #include <OpenGL/gl.h>
 #include <OpenGL/glu.h>
@@ -30,27 +31,371 @@
 
 #include "capabilities.h"
 
-//#define DIAGNOSTIC 0
-
-static void handleBufferModes(struct glCapabilities *cap, GLint bufferModes) {
+static void handleBufferModes(struct glCapabilitiesConfig *c, GLint bufferModes) {
     if(bufferModes & kCGLStereoscopicBit) {
-	cap->stereo = true;
+	c->stereo = true;
     }
 
     if(bufferModes & kCGLDoubleBufferBit) {
-	cap->buffers = 2;
+	c->buffers = 2;
     } else {
-	cap->buffers = 1;
+	c->buffers = 1;
+    }
+}
+
+static void handleStencilModes(struct glCapabilitiesConfig *c, GLint smodes) {
+    int offset = 0;
+    
+    if(kCGL0Bit & smodes)
+	c->stencil_bit_depths[offset++] = 0;
+
+    if(kCGL1Bit & smodes)
+	c->stencil_bit_depths[offset++] = 1;
+
+    if(kCGL2Bit & smodes)
+	c->stencil_bit_depths[offset++] = 2;
+    
+    if(kCGL3Bit & smodes)
+	c->stencil_bit_depths[offset++] = 3;
+
+    if(kCGL4Bit & smodes)
+	c->stencil_bit_depths[offset++] = 4;
+
+    if(kCGL5Bit & smodes)
+	c->stencil_bit_depths[offset++] = 5;
+    
+    if(kCGL6Bit & smodes)
+	c->stencil_bit_depths[offset++] = 6;
+
+    if(kCGL8Bit & smodes)
+	c->stencil_bit_depths[offset++] = 8;
+
+    if(kCGL10Bit & smodes)
+	c->stencil_bit_depths[offset++] = 10;
+
+    if(kCGL12Bit & smodes)
+	c->stencil_bit_depths[offset++] = 12;
+
+    if(kCGL16Bit & smodes)
+	c->stencil_bit_depths[offset++] = 16;
+
+    if(kCGL24Bit & smodes)
+	c->stencil_bit_depths[offset++] = 24;
+
+    if(kCGL32Bit & smodes)
+	c->stencil_bit_depths[offset++] = 32;
+    
+    if(kCGL48Bit & smodes)
+	c->stencil_bit_depths[offset++] = 48;
+    
+    if(kCGL64Bit & smodes)
+	c->stencil_bit_depths[offset++] = 64;
+    
+    if(kCGL96Bit & smodes)
+	c->stencil_bit_depths[offset++] = 96;
+    
+    if(kCGL128Bit & smodes)
+	c->stencil_bit_depths[offset++] = 128;
+
+    assert(offset < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS);
+
+    c->total_stencil_bit_depths = offset;
+}
+
+static int handleColorAndAccumulation(struct glColorBufCapabilities *c, 
+				       GLint cmodes) {
+    int offset = 0;
+        
+    /*1*/
+    if(kCGLRGB444Bit & cmodes) {
+	c[offset].r = 4;
+	c[offset].g = 4; 
+	c[offset].b = 4;
+	++offset;
+    }
+    
+    /*2*/
+    if(kCGLARGB4444Bit & cmodes) {
+	c[offset].a = 4;
+	c[offset].r = 4;
+	c[offset].g = 4;
+	c[offset].b = 4;
+	c[offset].is_argb = true;
+	++offset;
+    }
+    
+    /*3*/
+    if(kCGLRGB444A8Bit & cmodes) {
+	c[offset].r = 4;
+	c[offset].g = 4;
+	c[offset].b = 4;
+	c[offset].a = 8;
+	++offset;
+    }
+
+    /*4*/
+    if(kCGLRGB555Bit & cmodes) {
+	c[offset].r = 5;
+	c[offset].g = 5;
+	c[offset].b = 5;
+	++offset;
+    }
+
+    /*5*/
+    if(kCGLARGB1555Bit & cmodes) {
+	c[offset].a = 1;
+	c[offset].r = 5;
+	c[offset].g = 5;
+	c[offset].b = 5;
+	c[offset].is_argb = true;
+	++offset;
+    }
+
+    /*6*/
+    if(kCGLRGB555A8Bit & cmodes) {
+	c[offset].r = 5;
+	c[offset].g = 5; 
+	c[offset].b = 5;
+	c[offset].a = 8;
+	++offset;
+    }
+
+    /*7*/
+    if(kCGLRGB565Bit & cmodes) {
+	c[offset].r = 5;
+	c[offset].g = 6;
+	c[offset].b = 5;
+	++offset;
+    }
+
+    /*8*/
+    if(kCGLRGB565A8Bit & cmodes) {
+	c[offset].r = 5;
+	c[offset].g = 6;
+	c[offset].b = 5;
+	c[offset].a = 8;
+	++offset;
+    }
+
+    /*9*/
+    if(kCGLRGB888Bit & cmodes) {
+	c[offset].r = 8;
+	c[offset].g = 8;
+	c[offset].b = 8;
+	++offset;
+    }
+
+    /*10*/
+    if(kCGLARGB8888Bit & cmodes) {
+	c[offset].a = 8;
+	c[offset].r = 8;
+	c[offset].g = 8;
+	c[offset].b = 8;
+	c[offset].is_argb = true;
+	++offset;
+    }
+
+    /*11*/
+    if(kCGLRGB888A8Bit & cmodes) {
+	c[offset].r = 8;
+	c[offset].g = 8;
+	c[offset].b = 8;
+	c[offset].a = 8;
+	++offset;
+    }
+
+    /*12*/
+    if(kCGLRGB101010Bit & cmodes) {
+	c[offset].r = 10;
+	c[offset].g = 10;
+	c[offset].b = 10;
+	++offset;
+    }
+
+    /*13*/
+    if(kCGLARGB2101010Bit & cmodes) {
+	c[offset].a = 2;
+	c[offset].r = 10;
+	c[offset].g = 10;
+	c[offset].b = 10;
+	c[offset].is_argb = true;
+	++offset;
+    }
+
+    /*14*/
+    if(kCGLRGB101010_A8Bit & cmodes) {
+	c[offset].r = 10;
+	c[offset].g = 10;
+	c[offset].b = 10;
+	c[offset].a = 8;
+	++offset;
+    }
+
+    /*15*/
+    if(kCGLRGB121212Bit & cmodes) {
+	c[offset].r = 12;
+	c[offset].g = 12;
+	c[offset].b = 12;
+	++offset;	
+    }
+
+    /*16*/
+    if(kCGLARGB12121212Bit & cmodes) {
+	c[offset].a = 12;
+	c[offset].r = 12;
+	c[offset].g = 12;
+	c[offset].b = 12;
+	c[offset].is_argb = true;
+	++offset;
+    }
+
+    /*17*/
+    if(kCGLRGB161616Bit & cmodes) {
+	c[offset].r = 16;
+	c[offset].g = 16;
+	c[offset].b = 16;
+	++offset;
+    }
+
+    /*18*/
+    if(kCGLRGBA16161616Bit & cmodes) {
+	c[offset].r = 16;
+	c[offset].g = 16;
+	c[offset].b = 16;
+	c[offset].a = 16;
+	++offset;
     }
+
+    /* FIXME should we handle the floating point color modes, and if so, how? */
+      
+    return offset;
+}
+
+
+static void handleColorModes(struct glCapabilitiesConfig *c, GLint cmodes) {
+    c->total_color_buffers = handleColorAndAccumulation(c->color_buffers,
+							cmodes);
+    
+    assert(c->total_color_buffers < GLCAPS_COLOR_BUFFERS);
+}
+
+static void handleAccumulationModes(struct glCapabilitiesConfig *c, GLint cmodes) {
+    c->total_accum_buffers = handleColorAndAccumulation(c->accum_buffers,
+							cmodes);
+    assert(c->total_accum_buffers < GLCAPS_COLOR_BUFFERS);
+}
+
+/* Return true if an error occured. */
+static CGLError handleRendererDescriptions(CGLRendererInfoObj info, GLint r, 
+					   struct glCapabilitiesConfig *c) {
+    CGLError err;
+    GLint accelerated = 0, flags = 0, aux = 0;
+
+    err = CGLDescribeRenderer (info, r, kCGLRPAccelerated, &accelerated);
+
+    if(err)
+	return err;
+    
+    c->accelerated = accelerated;
+
+    /* Buffering modes: single/double, stereo */
+    err = CGLDescribeRenderer(info, r, kCGLRPBufferModes, &flags);
+
+    if(err)
+	return err;
+    
+    handleBufferModes(c, flags);
+    
+    /* AUX buffers */
+    err = CGLDescribeRenderer(info, r, kCGLRPMaxAuxBuffers, &aux);
+
+    if(err)
+	return err;
+    
+    c->aux_buffers = aux;
+    
+
+    /* Stencil bit depths */
+    err = CGLDescribeRenderer(info, r, kCGLRPStencilModes, &flags);
+
+    if(err)
+	return err;
+
+    handleStencilModes(c, flags);   
+
+
+    /* Color modes (RGB/RGBA depths supported */
+    err = CGLDescribeRenderer(info, r, kCGLRPColorModes, &flags);
+
+    if(err)
+	return true;
+    
+    handleColorModes(c, flags);
+
+    err = CGLDescribeRenderer(info, r, kCGLRPAccumModes, &flags);
+
+    if(err)
+	return true;
+
+    handleAccumulationModes(c, flags);
+    
+    return 0;
 }
 
 static void initCapabilities(struct glCapabilities *cap) {
-    cap->stereo = cap->buffers = cap->aux_buffers = 0;
+    cap->configurations = NULL;
+    cap->total_configurations = 0;
 }
 
-enum {
-    MAX_DISPLAYS = 32
-};
+static void initConfig(struct glCapabilitiesConfig *c) {
+    int i;
+
+    c->accelerated = false;
+    c->stereo = false;
+    c->buffers = 0;
+    c->aux_buffers = 0;
+    c->total_stencil_bit_depths = 0;
+
+    for(i = 0; i < GLCAPS_STENCIL_BIT_DEPTH_BUFFERS; ++i) {
+	c->stencil_bit_depths[i] = GLCAPS_INVALID_STENCIL_DEPTH;
+    }
+   
+    c->total_color_buffers = 0;
+
+    for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) {
+	c->color_buffers[i].r =	c->color_buffers[i].g =
+	    c->color_buffers[i].b = c->color_buffers[i].a = 
+	    GLCAPS_COLOR_BUF_INVALID_VALUE;
+	c->color_buffers[i].is_argb = false;
+     }
+
+    c->total_accum_buffers = 0;
+
+    for(i = 0; i < GLCAPS_COLOR_BUFFERS; ++i) {
+	c->accum_buffers[i].r = c->accum_buffers[i].g =
+	    c->accum_buffers[i].b = c->accum_buffers[i].a =
+	    GLCAPS_COLOR_BUF_INVALID_VALUE;
+	c->accum_buffers[i].is_argb = false;
+    }
+
+    c->next = NULL;
+}
+
+void freeGlCapabilities(struct glCapabilities *cap) {
+    struct glCapabilitiesConfig *conf, *next;
+    
+    conf = cap->configurations;
+
+    while(conf) {
+	next = conf->next;
+	free(conf);
+	conf = next;
+    }
+
+    cap->configurations = NULL;    
+}
+
+enum { MAX_DISPLAYS = 3 };
 
 /*Return true if an error occured. */
 bool getGlCapabilities(struct glCapabilities *cap) {
@@ -63,9 +408,7 @@ bool getGlCapabilities(struct glCapabilities *cap) {
     
     err = CGGetActiveDisplayList(MAX_DISPLAYS, dspys, &displayCount);
     if(err) {
-#ifdef DIAGNOSTIC
-	fprintf(stderr, "CGGetActiveDisplayList %s\n", CGLErrorString (err));
-#endif
+	fprintf(stderr, "CGGetActiveDisplayList error: %s\n", CGLErrorString(err));
 	return true;
     }
  
@@ -73,36 +416,48 @@ bool getGlCapabilities(struct glCapabilities *cap) {
         displayMask = CGDisplayIDToOpenGLDisplayMask(dspys[i]);
        
 	CGLRendererInfoObj info;
-	GLint numRenderers = 0, r, accelerated = 0, flags = 0, aux = 0;
-    
-	err = CGLQueryRendererInfo (displayMask, &info, &numRenderers);
-        if(!err) {
-            CGLDescribeRenderer (info, 0, kCGLRPRendererCount, &numRenderers);
-            for(r = 0; r < numRenderers; ++r) {
-                // find accelerated renderer (assume only one)
-                CGLDescribeRenderer (info, r, kCGLRPAccelerated, &accelerated);
-                if(accelerated) {
-                    err = CGLDescribeRenderer(info, r, kCGLRPBufferModes, &flags);
-		    if(err) {
-			CGLDestroyRendererInfo(info);
-			return true;
-		    }
-
-		    handleBufferModes(cap, flags);
-
-		    err = CGLDescribeRenderer(info, r, kCGLRPMaxAuxBuffers, &aux);
-		    if(err) {
-			CGLDestroyRendererInfo(info);
-			return true;
-		    }
-
-		    cap->aux_buffers = aux;
-                }
-            }
-	    CGLDestroyRendererInfo(info);
+	GLint numRenderers = 0, r, renderCount = 0;
+	    
+	err = CGLQueryRendererInfo(displayMask, &info, &numRenderers);
+
+        if(err) {
+	    fprintf(stderr, "CGLQueryRendererInfo error: %s\n", CGLErrorString(err));
+	    fprintf(stderr, "trying to continue...\n");
+	    continue;
 	}
-    }
+			
+	CGLDescribeRenderer(info, 0, kCGLRPRendererCount, &renderCount);
+
+	for(r = 0; r < renderCount; ++r) {
+	    CGLError derr;
+	    struct glCapabilitiesConfig tmpconf, *conf;
+
+	    initConfig(&tmpconf);
 
+	    derr = handleRendererDescriptions(info, r, &tmpconf);
+	    if(derr) {
+		fprintf(stderr, "error: %s\n", CGLErrorString(derr));
+		fprintf(stderr, "trying to continue...\n");
+		continue;
+	    }
+
+	    conf = malloc(sizeof(*conf));
+	    if(NULL == conf) {
+		perror("malloc");
+		abort();
+	    }
+
+	    /* Copy the struct. */
+	    *conf = tmpconf;
+
+	    /* Now link the configuration into the list. */
+	    conf->next = cap->configurations;
+	    cap->configurations = conf;
+	}
+
+    	CGLDestroyRendererInfo(info);
+    }
+    
     /* No error occured.  We are done. */
     return false;
 }
diff --git a/hw/xquartz/GL/capabilities.h b/hw/xquartz/GL/capabilities.h
index 6a026cf..20be30d 100644
--- a/hw/xquartz/GL/capabilities.h
+++ b/hw/xquartz/GL/capabilities.h
@@ -25,13 +25,36 @@
 
 #include <stdbool.h>
 
-struct glCapabilities {
-    int stereo;
+enum { GLCAPS_INVALID_STENCIL_DEPTH = -1 };
+enum { GLCAPS_COLOR_BUF_INVALID_VALUE = -1 };
+enum { GLCAPS_COLOR_BUFFERS = 20 };
+enum { GLCAPS_STENCIL_BIT_DEPTH_BUFFERS = 20 };
+
+struct glColorBufCapabilities {
+    char r, g, b, a;
+    bool is_argb;
+};
+
+struct glCapabilitiesConfig {
+    bool accelerated;
+    bool stereo;
     int aux_buffers;
     int buffers;
-    /*TODO handle STENCIL and ACCUM*/
+    int total_stencil_bit_depths;
+    char stencil_bit_depths[GLCAPS_STENCIL_BIT_DEPTH_BUFFERS];
+    int total_color_buffers;
+    struct glColorBufCapabilities color_buffers[GLCAPS_COLOR_BUFFERS];
+    int total_accum_buffers;
+    struct glColorBufCapabilities accum_buffers[GLCAPS_COLOR_BUFFERS];
+    struct glCapabilitiesConfig *next;
+};
+
+struct glCapabilities  {
+    struct glCapabilitiesConfig *configurations;
+    int total_configurations;
 };
 
 bool getGlCapabilities(struct glCapabilities *cap);
+void freeGlCapabilities(struct glCapabilities *cap);
 
 #endif
diff --git a/hw/xquartz/GL/indirect.c b/hw/xquartz/GL/indirect.c
index 3e22f88..5cf12cc 100644
--- a/hw/xquartz/GL/indirect.c
+++ b/hw/xquartz/GL/indirect.c
@@ -1158,7 +1158,7 @@ static __GLXscreen * __glXAquaScreenProbe(ScreenPtr pScreen) {
 
   init_screen_visuals(screen);
     
-  glAquaInitVisualConfigs();
+  //glAquaInitVisualConfigs();
 
   return &screen->base;
 }
diff --git a/hw/xquartz/GL/visualConfigs.c b/hw/xquartz/GL/visualConfigs.c
index a287542..196989a 100644
--- a/hw/xquartz/GL/visualConfigs.c
+++ b/hw/xquartz/GL/visualConfigs.c
@@ -61,37 +61,56 @@ void setVisualConfigs(void) {
     int numConfigs = 0;
     __GLXvisualConfig *visualConfigs = NULL;
     void **visualPrivates = NULL;
-    struct glCapabilities caps[1];
-    int stereo, depth, aux, buffers, stencil, accum;
+    struct glCapabilities caps;
+    struct glCapabilitiesConfig *conf = NULL;
+    int stereo, depth, aux, buffers, stencil, accum, color;
     int i = 0; 
-
-    if(getGlCapabilities(caps)) {
+   
+    if(getGlCapabilities(&caps)) {
 	ErrorF("error from getGlCapabilities()!\n");
 	return;
     }
     
     /*
-      caps->stereo is 0 or 1, but we need at least 1 iteration of the loop, so we treat
-      a true caps->stereo as 2.
+      conf->stereo is 0 or 1, but we need at least 1 iteration of the loop, 
+      so we treat a true conf->stereo as 2.
 
       The depth size is 0 or 24.  Thus we do 2 iterations for that.
 
-      caps->aux_buffers (when available/non-zero) result in 2 iterations instead of 1.
+      conf->aux_buffers (when available/non-zero) result in 2 iterations instead of 1.
 
-      caps->buffers indicates whether we have single or double buffering.
+      conf->buffers indicates whether we have single or double buffering.
+     
+      conf->total_stencil_bit_depths
+       
+      conf->total_color_buffers indicates the RGB/RGBA color depths.
       
-      2 iterations for stencil (on and off (with a stencil size of 8)).
-
-      2 iterations for accum (on and off (with an accum color size of 16)).
+      conf->total_accum_buffers iterations for accum (with at least 1 if equal to 0) 
      */
 
-    numConfigs = (caps->stereo ? 2 : 1) * 2 * 
-	(caps->aux_buffers ? 2 : 1) * (caps->buffers) * 2 * 2;
+    assert(NULL != caps.configurations);
+    conf = caps.configurations;
+  
+    numConfigs = 0;
+
+    for(conf = caps.configurations; conf; conf = conf->next) {
+	if(conf->total_color_buffers <= 0)
+	    continue;
+
+	numConfigs += (conf->stereo ? 2 : 1) 
+	    * 2 /*depth*/ 
+	    * (conf->aux_buffers ? 2 : 1) 
+	    * conf->buffers
+	    * ((conf->total_stencil_bit_depths > 0) ? conf->total_stencil_bit_depths : 1)
+	    * conf->total_color_buffers
+	    * ((conf->total_accum_buffers > 0) ? conf->total_accum_buffers : 1);
+    }
 
     visualConfigs = xcalloc(sizeof(*visualConfigs), numConfigs);
 
     if(NULL == visualConfigs) {
 	ErrorF("xcalloc failure when allocating visualConfigs\n");
+	freeGlCapabilities(&caps);
 	return;
     }
     
@@ -99,55 +118,83 @@ void setVisualConfigs(void) {
 
     if(NULL == visualPrivates) {
 	ErrorF("xcalloc failure when allocating visualPrivates");
+	freeGlCapabilities(&caps);
 	xfree(visualConfigs);
 	return;
     }
-
- 
+    
     i = 0; /* current buffer */
-    for (stereo = 0; stereo < (caps->stereo ? 2 : 1); ++stereo) {
-	for (depth = 0; depth < 2; ++depth) {
-	    for (aux = 0; aux < (caps->aux_buffers ? 2 : 1); ++aux) {
-		for (buffers = 0; buffers < caps->buffers; ++buffers) {
-		    for (stencil = 0; stencil < 2; ++stencil) {
-			for (accum = 0; accum < 2; ++accum) {
-			    visualConfigs[i].vid = -1;
-			    visualConfigs[i].class = -1;
-			    visualConfigs[i].rgba = TRUE;
-			    visualConfigs[i].redSize = -1;
-			    visualConfigs[i].greenSize = -1;
-			    visualConfigs[i].blueSize = -1;
-			    visualConfigs[i].redMask = -1;
-			    visualConfigs[i].greenMask = -1;
-			    visualConfigs[i].blueMask = -1;
-			    visualConfigs[i].alphaMask = 0;
-			    if (accum) {
-				visualConfigs[i].accumRedSize = 16;
-				visualConfigs[i].accumGreenSize = 16;
-				visualConfigs[i].accumBlueSize = 16;
-				visualConfigs[i].accumAlphaSize = 16;
-			    } else {
-				visualConfigs[i].accumRedSize = 0;
-				visualConfigs[i].accumGreenSize = 0;
-				visualConfigs[i].accumBlueSize = 0;
-				visualConfigs[i].accumAlphaSize = 0;
+    for(conf = caps.configurations; conf; conf = conf->next) {
+	for(stereo = 0; stereo < (conf->stereo ? 2 : 1); ++stereo) {
+	    for(depth = 0; depth < 2; ++depth) {
+		for(aux = 0; aux < (conf->aux_buffers ? 2 : 1); ++aux) {
+		    for(buffers = 0; buffers < conf->buffers; ++buffers) {
+			for(stencil = 0; stencil < ((conf->total_stencil_bit_depths > 0) ? 
+						    conf->total_stencil_bit_depths : 1); ++stencil) {
+			    for(color = 0; color < conf->total_color_buffers; ++color) {
+				for(accum = 0; accum < ((conf->total_accum_buffers > 0) ?
+							conf->total_accum_buffers : 1); ++accum) {
+				    visualConfigs[i].vid = -1;
+				    visualConfigs[i].class = -1;
+		     
+				    visualConfigs[i].rgba = true;
+				    visualConfigs[i].redSize = conf->color_buffers[color].r;
+				    visualConfigs[i].greenSize = conf->color_buffers[color].g;
+				    visualConfigs[i].blueSize = conf->color_buffers[color].b;
+				    visualConfigs[i].alphaSize = conf->color_buffers[color].a;
+				
+				    visualConfigs[i].redMask = -1;
+				    visualConfigs[i].greenMask = -1;
+				    visualConfigs[i].blueMask = -1;
+				    visualConfigs[i].alphaMask = -1;
+
+				    if(conf->total_accum_buffers > 0) {
+					visualConfigs[i].accumRedSize = conf->accum_buffers[accum].r;
+					visualConfigs[i].accumGreenSize = conf->accum_buffers[accum].g;
+					visualConfigs[i].accumBlueSize = conf->accum_buffers[accum].b;
+					if(GLCAPS_COLOR_BUF_INVALID_VALUE != conf->accum_buffers[accum].a) {
+					    visualConfigs[i].accumAlphaSize = conf->accum_buffers[accum].a;
+					} else {
+					    visualConfigs[i].accumAlphaSize = 0;
+					}
+				    } else {
+					visualConfigs[i].accumRedSize = 0;
+					visualConfigs[i].accumGreenSize = 0;
+					visualConfigs[i].accumBlueSize = 0;
+					visualConfigs[i].accumAlphaSize = 0;
+				    }
+
+				    visualConfigs[i].doubleBuffer = buffers ? TRUE : FALSE;
+				    visualConfigs[i].stereo = stereo ? TRUE : FALSE;
+				    visualConfigs[i].bufferSize = -1;
+				    
+				    visualConfigs[i].depthSize = depth ? 24 : 0;
+				    
+				    if(conf->total_stencil_bit_depths > 0) {
+					visualConfigs[i].stencilSize = conf->stencil_bit_depths[stencil];
+				    } else {
+					visualConfigs[i].stencilSize = 0;
+				    }
+				    visualConfigs[i].auxBuffers = aux ? conf->aux_buffers : 0;
+				    visualConfigs[i].level = 0;
+				    visualConfigs[i].visualRating = GLX_NONE;
+				    visualConfigs[i].transparentPixel = GLX_NONE;
+				    visualConfigs[i].transparentRed = GLX_NONE;
+				    visualConfigs[i].transparentGreen = GLX_NONE;
+				    visualConfigs[i].transparentBlue = GLX_NONE;
+				    visualConfigs[i].transparentAlpha = GLX_NONE;
+				    visualConfigs[i].transparentIndex = GLX_NONE;
+
+				    /*
+				      TODO possibly handle:
+				      multiSampleSize;
+				      nMultiSampleBuffers;
+				      visualSelectGroup;
+				    */
+
+				    ++i;
+				}
 			    }
-			    visualConfigs[i].doubleBuffer = buffers ? TRUE : FALSE;
-			    visualConfigs[i].stereo = stereo ? TRUE : FALSE;
-			    visualConfigs[i].bufferSize = -1;
-			    
-			    visualConfigs[i].depthSize = depth ? 24 : 0;
-			    visualConfigs[i].stencilSize = stencil ? 8 : 0;
-			    visualConfigs[i].auxBuffers = aux ? caps->aux_buffers : 0;
-			    visualConfigs[i].level = 0;
-			    visualConfigs[i].visualRating = GLX_NONE_EXT;
-			    visualConfigs[i].transparentPixel = 0;
-			    visualConfigs[i].transparentRed = 0;
-			    visualConfigs[i].transparentGreen = 0;
-			    visualConfigs[i].transparentBlue = 0;
-			    visualConfigs[i].transparentAlpha = 0;
-			    visualConfigs[i].transparentIndex = 0;
-			    ++i;
 			}
 		    }
 		}
@@ -156,9 +203,11 @@ void setVisualConfigs(void) {
     }
 
     if (i != numConfigs) {
-	ErrorF("numConfigs calculation error in setVisualConfigs!\n");
+	ErrorF("numConfigs calculation error in setVisualConfigs!  numConfigs is %d  i is %d\n", numConfigs, i);
 	abort();
     }
 
+    freeGlCapabilities(&caps);
+
     GlxSetVisualConfigs(numConfigs, visualConfigs, visualPrivates);
 }


More information about the xorg-commit mailing list