summaryrefslogtreecommitdiffstats
path: root/examples/opengl/overlay_x11
diff options
context:
space:
mode:
Diffstat (limited to 'examples/opengl/overlay_x11')
-rw-r--r--examples/opengl/overlay_x11/README74
-rw-r--r--examples/opengl/overlay_x11/README.X11-OVERLAYS92
-rw-r--r--examples/opengl/overlay_x11/gearwidget.cpp268
-rw-r--r--examples/opengl/overlay_x11/gearwidget.h29
-rw-r--r--examples/opengl/overlay_x11/main.cpp125
-rw-r--r--examples/opengl/overlay_x11/overlay_x11.doc82
-rw-r--r--examples/opengl/overlay_x11/overlayrubber.pro14
-rw-r--r--examples/opengl/overlay_x11/rubberbandwidget.cpp59
-rw-r--r--examples/opengl/overlay_x11/rubberbandwidget.h37
-rw-r--r--examples/opengl/overlay_x11/utilities/NOTICE11
-rw-r--r--examples/opengl/overlay_x11/utilities/README22
-rw-r--r--examples/opengl/overlay_x11/utilities/glxvisuals/glxvisuals.c147
-rw-r--r--examples/opengl/overlay_x11/utilities/sovinfo/sovLayerUtil.h54
-rw-r--r--examples/opengl/overlay_x11/utilities/sovinfo/sovinfo.c95
-rw-r--r--examples/opengl/overlay_x11/utilities/sovinfo/sovlayerutil.c150
15 files changed, 1259 insertions, 0 deletions
diff --git a/examples/opengl/overlay_x11/README b/examples/opengl/overlay_x11/README
new file mode 100644
index 000000000..eba728e67
--- /dev/null
+++ b/examples/opengl/overlay_x11/README
@@ -0,0 +1,74 @@
+
+-----------------------------------------------------------------------
+UPDATE: From version 5.0 onwards, the Qt OpenGL Extension includes
+direct support for use of OpenGL overlays. For many uses of overlays,
+this makes the technique described below redundant. See the 'overlay'
+example program. The following is a discussion on how to use non-QGL
+widgets in overlay planes.
+-----------------------------------------------------------------------
+
+Overlayrubber: An example program showing how to use Qt and Qt OpenGL
+Extension with X11 overlay visuals.
+
+(Background information for this example can be found in the file
+ README.X11-OVERLAYS)
+
+The example program has three main parts:
+
+GearWidget: A simple QGLWidget that renders the usual gears. Modified
+so that it will print a debug message every time it redraws (renders)
+itself. Thus, you can eaily confirm that drawing in the overlay plane
+does not cause redrawings in the main plane where the QGLWidget
+resides.
+
+RubberbandWidget: Very simple standard (non-GL) Qt widget that
+implements rubberband drawing. Designed for use in an overlay
+plane. It takes the planes' transparent color as a constructor
+argument and uses that for its background color. Thus, the widget
+itself will be invisible, only the rubberbands it draws will be
+visible.
+
+main.cpp: Creates a GearWidget and a Rubberbandwidget and puts the
+latter on top of the former. Contains a routine that checks that the
+default visual is in an overlay plane, and returns the transparent
+color of that plane.
+
+
+Running it:
+-----------
+
+Start the overlayrubber executable. Click and drag with the left mouse
+button to see rubberband drawing. Observe that the QGLWidget does
+not redraw itself (no redraw debug messages are output), and yet the
+image is not destroyed. Marvel at the coolness of X11 overlays!
+
+
+Using this technique in a real application
+------------------------------------------
+
+For clarity, this example program has been kept very simple. Here are
+some hints for real application use:
+
+All normal widgets can go in the overlay plane: This means that you
+can put all kinds of Qt widgets (your own or those provided with Qt)
+on top of the OpenGL image (widget), e.g. pushbuttons etc., and they
+can be moved, resized, or removed without destroying the OpenGL image.
+
+Using with geometry management: The QLayout classes will not allow you
+to put one widget (the overlay) on top of another (the OpenGL widget);
+that would defy the whole purpose of the automatic layout. The
+solution is to add just one of them to the QLayout object. Have it
+keep a pointer to the other (i.e. the QGLWidget knows about its
+overlay widget or vice versa). Implement the resizeEvent() method of
+the widget you put in the layout, and make it call setGeometry() on
+the other widget with its own geometry as parameters, thus keeping the
+two widgets' geometries synchronized.
+
+Using with QPalette and QColorGroup: Instead of the somewhat
+simplistic setBackgroundColor( transparentColor ), you can use Qt's
+QPalette system for having your overlay widgets use transparent color
+for what you want. This way, the normal Qt widgets can be used as
+overlays for fancy effects: just create a palette for them with the
+transparent color for the wanted color roles, e.g. Background and
+Base, in the Normal and/or Active modes. This way, you can create
+see-through QPushButtons etc.
diff --git a/examples/opengl/overlay_x11/README.X11-OVERLAYS b/examples/opengl/overlay_x11/README.X11-OVERLAYS
new file mode 100644
index 000000000..6029ca3eb
--- /dev/null
+++ b/examples/opengl/overlay_x11/README.X11-OVERLAYS
@@ -0,0 +1,92 @@
+
+ HOW TO USE X11 OVERLAYS WITH THE QT OPENGL EXTENSION
+
+X11 overlays is a powerful mechanism that allows one to draw
+annotations etc. on top of an image without destroying it, thus saving
+significant image rendering time. For more information, consult the
+highly recommended book "OpenGL Programming for the X Window System"
+(Mark Kilgard, Addison Wesley Developers Press 1996).
+
+-----------------------------------------------------------------------
+UPDATE: From version 5.0 onwards, the Qt OpenGL Extension includes
+direct support for use of OpenGL overlays. For many uses of overlays,
+this makes the technique described below redundant. See the 'overlay'
+example program. The following is a discussion on how to use non-QGL
+widgets in overlay planes.
+-----------------------------------------------------------------------
+
+In the typical case, X11 overlays can easily be used together with the
+current version of Qt and the Qt OpenGL Extension. The following
+retquirements apply:
+
+1) Your X server and graphics card/hardware must support overlays (of
+ course). For many X servers, overlay support can be turned on with
+ a configuration option; consult your X server installation
+ documentation.
+
+2) Your X server must (be configured to) use an overlay visual as the
+ default visual. Most modern X servers do this, since this has the
+ added advantage that pop-up menus, overlapping windows etc. will
+ not destroy underlying images in the main plane, saving expensive
+ redraws.
+
+3) The best (deepest) visual for OpenGL rendering is in the main
+ plane. This is the normal case. Typically, X servers that support
+ overlays provide a 24 bit deep TrueColor visuals in the main plane,
+ and an 8 bit PseudoColor (default) visual in the overlay plane.
+
+The provided example program "overlayrubber" will check for all this
+and tell you what is wrong, if anything. See "About X11 Visuals" below
+for more information.
+
+
+How it works:
+-------------
+
+Given the above, a QGLWidget will by default use the main plane
+visual, while all other widgets will use the overlay visual. Thus, one
+can place a normal widget on top of the QGLWidget, and do drawing in
+it, without destroying the image in the OpenGL window. In other words,
+one can use all the drawing capabilities of QPainter to draw the
+annotations, rubberbands, whatever. For the typical use of overlays,
+this is much easier than using OpenGL for rendering the annotations.
+
+An overlay plane has a specific color called the transparent
+color. Pixels drawn in this color will not be visible, instead the
+underlying OpenGL image will show through. In the example program
+"overlayrubber", the file main.cpp contains a routine that returns a
+QColor containing the transparent color. For the overlay widget, one
+will typically want to set the background color to the transparent
+color, so that the OpenGL image shows through except where explicitly
+overpainted.
+
+Note: To use this technique, you must not use the "ManyColor" or
+"TrueColor" ColorSpec for the QApplication, because this will force
+the normal Qt widgets to use a TrueColor visual, which will typically
+be in the main plane, not in the overlay plane as desired.
+
+
+
+About X11 visuals:
+------------------
+
+The utilities directory contains two small programs that can help you
+determine the capabilities of your X server. These programs are from
+the OpenGL book mentioned above, see utilities/NOTICE for copyright
+information. The full set of example programs from this book is
+available at ftp://ftp.sgi.com/pub/opengl/opengl_for_x/
+
+"glxvisuals" will list all the GL-capable visuals the X server provides,
+together with the depth and other GL-specific information for
+each. Note especially the column "lvl"; a number in this column means
+the visual is in an overlay plane.
+
+"sovinfo" will list all available visuals, and provides special
+transparency information for overlay visuals.
+
+The overlayrubber example program will output what visual is used for
+the normal Qt widgets, and what visual is used by the QGLWidget.
+
+
+
+Comments are welcome at info@trolltech.com.
diff --git a/examples/opengl/overlay_x11/gearwidget.cpp b/examples/opengl/overlay_x11/gearwidget.cpp
new file mode 100644
index 000000000..4d717f27e
--- /dev/null
+++ b/examples/opengl/overlay_x11/gearwidget.cpp
@@ -0,0 +1,268 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for TQt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+//
+// A TQt OpenGL widget that draws a gear.
+//
+// Portions of this code has been borrowed from Brian Paul's Mesa
+// distribution.
+//
+
+#include "gearwidget.h"
+#include <math.h>
+#if defined(Q_WS_X11)
+#include <X11/Xlib.h>
+#endif
+
+#if defined(Q_CC_MSVC)
+#pragma warning(disable:4305) // init: truncation from const double to float
+#endif
+
+/*
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * Input: inner_radius - radius of hole at center
+ * outer_radius - radius at center of teeth
+ * width - width of gear
+ * teeth - number of teeth
+ * tooth_depth - depth of tooth
+ */
+static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth )
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth/2.0;
+ r2 = outer_radius + tooth_depth/2.0;
+
+ const double pi = 3.14159264;
+ da = 2.0*pi / teeth / 4.0;
+
+ glShadeModel( GL_FLAT );
+
+ glNormal3f( 0.0, 0.0, 1.0 );
+
+ /* draw front face */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
+ glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin( GL_QUADS );
+ da = 2.0*pi / teeth / 4.0;
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+
+ glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
+ }
+ glEnd();
+
+
+ glNormal3f( 0.0, 0.0, -1.0 );
+
+ /* draw back face */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin( GL_QUADS );
+ da = 2.0*pi / teeth / 4.0;
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
+ glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
+ }
+ glEnd();
+
+
+ /* draw outward faces of teeth */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+
+ glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
+ glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
+ u = r2*cos(angle+da) - r1*cos(angle);
+ v = r2*sin(angle+da) - r1*sin(angle);
+ len = sqrt( u*u + v*v );
+ u /= len;
+ v /= len;
+ glNormal3f( v, -u, 0.0 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
+ glNormal3f( cos(angle), sin(angle), 0.0 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
+ u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
+ v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
+ glNormal3f( v, -u, 0.0 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
+ glNormal3f( cos(angle), sin(angle), 0.0 );
+ }
+
+ glVertex3f( r1*cos(0.0), r1*sin(0.0), width*0.5 );
+ glVertex3f( r1*cos(0.0), r1*sin(0.0), -width*0.5 );
+
+ glEnd();
+
+
+ glShadeModel( GL_SMOOTH );
+
+ /* draw inside radius cylinder */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glNormal3f( -cos(angle), -sin(angle), 0.0 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
+ }
+ glEnd();
+
+}
+
+
+static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+
+
+static void draw()
+{
+ angle += 2.0;
+ view_roty += 1.0;
+
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ glPushMatrix();
+ glRotatef( view_rotx, 1.0, 0.0, 0.0 );
+ glRotatef( view_roty, 0.0, 1.0, 0.0 );
+ glRotatef( view_rotz, 0.0, 0.0, 1.0 );
+
+ glPushMatrix();
+ glTranslatef( -3.0, -2.0, 0.0 );
+ glRotatef( angle, 0.0, 0.0, 1.0 );
+ glCallList(gear1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef( 3.1, -2.0, 0.0 );
+ glRotatef( -2.0*angle-9.0, 0.0, 0.0, 1.0 );
+ glCallList(gear2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef( -3.1, 2.2, -1.8 );
+ glRotatef( 90.0, 1.0, 0.0, 0.0 );
+ glRotatef( 2.0*angle-2.0, 0.0, 0.0, 1.0 );
+ glCallList(gear3);
+ glPopMatrix();
+
+ glPopMatrix();
+}
+
+
+
+GearWidget::GearWidget( TQWidget *parent, const char *name )
+ : TQGLWidget( parent, name )
+{
+}
+
+void GearWidget::initializeGL()
+{
+ static GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0 };
+ static GLfloat redgear[4] = {0.8, 0.1, 0.0, 1.0 };
+ static GLfloat greengear[4] = {0.0, 0.8, 0.2, 1.0 };
+ static GLfloat bluegear[4] = {0.2, 0.2, 1.0, 1.0 };
+
+ glLightfv( GL_LIGHT0, GL_POSITION, pos );
+ glEnable( GL_CULL_FACE );
+ glEnable( GL_LIGHTING );
+ glEnable( GL_LIGHT0 );
+ glEnable( GL_DEPTH_TEST );
+
+ /* make the gears */
+ gear1 = glGenLists(1);
+ glNewList(gear1, GL_COMPILE);
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, redgear );
+ gear( 1.0, 4.0, 1.0, 20, 0.7 );
+ glEndList();
+
+ gear2 = glGenLists(1);
+ glNewList(gear2, GL_COMPILE);
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, greengear );
+ gear( 0.5, 2.0, 2.0, 10, 0.7 );
+ glEndList();
+
+ gear3 = glGenLists(1);
+ glNewList(gear3, GL_COMPILE);
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bluegear );
+ gear( 1.3, 2.0, 0.5, 10, 0.7 );
+ glEndList();
+
+ glEnable( GL_NORMALIZE );
+}
+
+
+void GearWidget::resizeGL( int width, int height )
+{
+ GLfloat w = (float) width / (float) height;
+ GLfloat h = 1.0;
+
+ glViewport( 0, 0, width, height );
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum( -w, w, -h, h, 5.0, 60.0 );
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, -40.0 );
+}
+
+
+void GearWidget::paintGL()
+{
+ qDebug( "GearWidget: Doing GL rendering." );
+#if defined (Q_GLX)
+ static bool doneIt = FALSE;
+ if ( !doneIt ) {
+ doneIt = TRUE;
+ // Print out the Visual ID. Access to this will be made
+ // simpler in future versions of TQt!
+ XWindowAttributes a;
+ XGetWindowAttributes( x11Display(), winId(), &a );
+ qDebug( "TQGLWidget: using Visual ID: 0x%x.",
+ (int)XVisualIDFromVisual( a.visual ) );
+ }
+#endif
+ draw();
+}
+
diff --git a/examples/opengl/overlay_x11/gearwidget.h b/examples/opengl/overlay_x11/gearwidget.h
new file mode 100644
index 000000000..6154e36da
--- /dev/null
+++ b/examples/opengl/overlay_x11/gearwidget.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+**
+** Definition of a simple TQt OpenGL widget
+**
+** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for TQt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef GEAR_H
+#define GEAR_H
+
+#include <qgl.h>
+
+class GearWidget : public TQGLWidget
+{
+public:
+ GearWidget( TQWidget *parent=0, const char *name=0 );
+
+protected:
+ void initializeGL();
+ void resizeGL( int, int );
+ void paintGL();
+};
+
+
+#endif
diff --git a/examples/opengl/overlay_x11/main.cpp b/examples/opengl/overlay_x11/main.cpp
new file mode 100644
index 000000000..70a6f4362
--- /dev/null
+++ b/examples/opengl/overlay_x11/main.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Example application showing how to use TQt and TQt OpenGL Extension on an
+** X11 overlay visual
+**
+** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for TQt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include <qapplication.h>
+#include "gearwidget.h"
+#include "rubberbandwidget.h"
+
+#if defined(Q_WS_X11)
+#include <X11/Xlib.h>
+#endif
+
+TQColor findOverlayTransparentColor()
+{
+ TQColor invalidColor;
+
+#if defined(Q_WS_X11)
+
+ Display* appDisplay;
+ Visual* appVisual;
+
+ // The static methods are called 'App' in TQt 2.x
+#if QT_VERSION < 200
+ appDisplay = TQPaintDevice::x__Display();
+ appVisual = (Visual*)TQPaintDevice::x11Visual();
+#else
+ appDisplay = TQPaintDevice::x11AppDisplay();
+ appVisual = (Visual*)TQPaintDevice::x11AppVisual();
+#endif
+
+ qDebug( "Default Visual ID: 0x%x", (int)XVisualIDFromVisual(appVisual) );
+
+ typedef struct OverlayProp {
+ long visual;
+ long type;
+ long value;
+ long layer;
+ } OverlayProp;
+
+ TQWidget* rootWin = TQApplication::desktop();
+ if ( !rootWin )
+ return invalidColor; // Should not happen
+
+ Atom overlayVisualsAtom = XInternAtom( appDisplay,
+ "SERVER_OVERLAY_VISUALS", True );
+ if ( overlayVisualsAtom == None ) {
+ warning( "Server has no overlay visuals" );
+ return invalidColor;
+ }
+
+ Atom actualType;
+ int actualFormat;
+ ulong nItems;
+ ulong bytesAfter;
+ OverlayProp* overlayProp;
+ int res = XGetWindowProperty( appDisplay, TQApplication::desktop()->winId(),
+ overlayVisualsAtom, 0, 10000, False,
+ overlayVisualsAtom, &actualType,
+ &actualFormat, &nItems, &bytesAfter,
+ (uchar**)&overlayProp );
+
+ if ( res != Success || actualType != overlayVisualsAtom
+ || actualFormat != 32 || nItems < 4 ) {
+ warning( "Failed to get overlay visual property from server" );
+ return invalidColor;
+ }
+
+
+ for ( uint i = 0; i < nItems/4; i++ ) {
+ if ( (VisualID)overlayProp[i].visual == XVisualIDFromVisual(appVisual)
+ && overlayProp[i].type == 1 )
+ return TQColor( qRgb( 1, 2, 3 ), overlayProp[i].value );
+ }
+
+ qWarning( "Default visual is not in overlay plane" );
+ return invalidColor;
+
+#else // defined(Q_WS_X11)
+ qWarning( "Wrong window system - Only X11 has overlay support." );
+ return invalidColor;
+#endif
+}
+
+
+int main( int argc, char **argv )
+{
+ TQApplication::setColorSpec( TQApplication::CustomColor );
+ TQApplication a( argc, argv );
+
+ if ( !TQGLFormat::hasOpenGL() ) {
+ qWarning( "This system has no OpenGL support. Exiting." );
+ return -1;
+ }
+
+ TQColor transparentColor = findOverlayTransparentColor();
+ if ( !transparentColor.isValid() ) {
+ qWarning( "Failed to get transparent color for overlay. Exiting." );
+ return -1;
+ }
+
+ TQWidget top;
+ a.setMainWidget( &top );
+ top.setGeometry( 50, 50, 600, 400 );
+
+ // Make an OpenGL widget. It will use the deepest visual available
+ // (typically a TrueColor visual), which typically is in the normal layer.
+ GearWidget g( &top );
+ g.setGeometry( 20, 20, 560, 360 );
+
+ // Put the rubberband widget (which uses the default, i.e. overlay visual)
+ // on top of the OpenGL widget:
+ RubberbandWidget r( transparentColor, &top );
+ r.setGeometry( 20, 20, 560, 360 );
+
+ top.show();
+ return a.exec();
+}
diff --git a/examples/opengl/overlay_x11/overlay_x11.doc b/examples/opengl/overlay_x11/overlay_x11.doc
new file mode 100644
index 000000000..6dddc9b9b
--- /dev/null
+++ b/examples/opengl/overlay_x11/overlay_x11.doc
@@ -0,0 +1,82 @@
+/*! \page opengl-overlay-x11-example.html
+
+ \ingroup opengl-examples
+ \title OpenGL Overlay X11 Example
+
+\warning From version 5.0 onwards, the Qt OpenGL Extension includes
+direct support for use of OpenGL overlays. For many uses of overlays,
+this makes the technique described below redundant. See the \link
+opengl-overlay-example.html overlay\endlink example program. The
+following is a discussion on how to use non-QGL widgets in overlay
+planes.
+
+Overlayrubber: An example program showing how to use Qt and Qt OpenGL
+Extension with X11 overlay visuals.
+
+See \c{$QTDIR/examples/opengl/overlay_x11} for the source code.
+
+Background information for this example can be found in the
+information on \link opengl-x11-overlays.html overlays\endlink.
+
+The example program has three main parts:
+
+\list 1
+\i \e GearWidget - a normal, simple QGLWidget. This renders the usual
+gears. It has been modified to print a debug message every time it
+redraws (renders) itself. Thus, you can easily confirm that drawing in
+the overlay plane does not cause redrawings in the main plane where
+the QGLWidget resides.
+
+\i \e RubberbandWidget - Very simple standard (non-GL) Qt widget that
+implements rubberband drawing. Designed for use in an overlay plane.
+It takes the plane's transparent color as a constructor argument and
+uses that for its background color. Thus, the widget itself will be
+invisible, only the rubberbands it draws will be visible.
+
+\i \e{main.cpp} Creates a GearWidget and a Rubberbandwidget and puts the
+latter on top of the former. Contains a routine that checks that the
+default visual is in an overlay plane, and returns the transparent
+color of that plane.
+\endlist
+
+\section1 Running the Example
+
+Start the \c overlayrubber executable. Click and drag with the left
+mouse button to see rubberband drawing. Observe that the QGLWidget
+does not redraw itself (no redraw debug messages are output), and yet
+the image is not destroyed. Marvel at the coolness of X11 overlays!
+
+
+\section1 Using this technique in a real application
+
+For clarity, this example program has been kept very simple. Here are
+some hints for real application usage:
+
+\list
+
+\i \e{All normal widgets are in the overlay plane.} This means that you
+can put all kinds of Qt widgets (your own or standard Qt widgets) on
+top of the OpenGL image (widget), e.g. pushbuttons etc., and they can
+be moved, resized, or removed without destroying the OpenGL image.
+
+\i \e{Using with geometry management.} The QLayout classes don't permit
+putting one widget (the overlay) on top of another (the OpenGL
+widget); that would defy the whole purpose of the automatic layout.
+The solution is to add just one of them to the QLayout object. Have it
+keep a pointer to the other (i.e. the QGLWidget knows about its
+overlay widget or vice versa). Implement the resizeEvent() method of
+the widget you put in the layout, and make it call setGeometry() on
+the other widget with its own geometry as parameters, thus keeping the
+two widgets' geometries synchronized.
+
+\i \e{Using together with QPalette and QColorGroup.} Instead of the
+simplistic setBackgroundColor( transparentColor ), you can
+use Qt's QPalette system to make your overlay widgets use
+transparent color for what you want. This way, the normal Qt widgets
+can be used as overlays for fancy effects. Just create a palette for
+them with the transparent color for the relevant color roles, e.g.
+Background and Base, in the Normal and/or Active modes. This way, you
+can create see-through QPushButtons etc.
+\endlist
+
+*/
diff --git a/examples/opengl/overlay_x11/overlayrubber.pro b/examples/opengl/overlay_x11/overlayrubber.pro
new file mode 100644
index 000000000..5381ebb2e
--- /dev/null
+++ b/examples/opengl/overlay_x11/overlayrubber.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+TARGET = overlayrubber
+
+CONFIG += qt opengl warn_on release
+CONFIG -= dlopen_opengl
+DEPENDPATH = ../include
+
+REQUIRES = opengl full-config
+
+HEADERS = gearwidget.h \
+ rubberbandwidget.h
+SOURCES = gearwidget.cpp \
+ main.cpp \
+ rubberbandwidget.cpp
diff --git a/examples/opengl/overlay_x11/rubberbandwidget.cpp b/examples/opengl/overlay_x11/rubberbandwidget.cpp
new file mode 100644
index 000000000..5cd5c5654
--- /dev/null
+++ b/examples/opengl/overlay_x11/rubberbandwidget.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Implementation of a widget that draws a rubberband. Designed to be used
+** in an X11 overlay visual
+**
+** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for TQt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "rubberbandwidget.h"
+#include <qpainter.h>
+
+
+RubberbandWidget::RubberbandWidget( TQColor transparentColor, TQWidget *parent,
+ const char *name, WFlags f )
+ : TQWidget( parent, name, f )
+{
+ setBackgroundColor( transparentColor );
+ on = FALSE;
+}
+
+
+void RubberbandWidget::mousePressEvent( TQMouseEvent* e )
+{
+ p1 = e->pos();
+ p2 = p1;
+ p3 = p1;
+ on = TRUE;
+ setMouseTracking( TRUE );
+}
+
+
+void RubberbandWidget::mouseMoveEvent( TQMouseEvent* e )
+{
+ if ( on ) {
+ p2 = e->pos();
+ TQPainter p( this );
+ // Erase last drawn rubberband:
+ p.setPen( TQPen( backgroundColor(), 3 ) );
+ p.drawRect( TQRect( p1, p3 ) );
+ // Draw the new one:
+ p.setPen( TQPen( white, 3 ) );
+ p.drawRect( TQRect(p1, p2) );
+ p3 = p2;
+ }
+}
+
+void RubberbandWidget::mouseReleaseEvent( TQMouseEvent* )
+{
+ if ( on ) {
+ TQPainter p ( this );
+ p.eraseRect( rect() );
+ }
+ on = FALSE;
+ setMouseTracking( FALSE );
+}
diff --git a/examples/opengl/overlay_x11/rubberbandwidget.h b/examples/opengl/overlay_x11/rubberbandwidget.h
new file mode 100644
index 000000000..10513a6d6
--- /dev/null
+++ b/examples/opengl/overlay_x11/rubberbandwidget.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Definition of a widget that draws a rubberband. Designed to be used
+** in an X11 overlay visual
+**
+** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for TQt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef RUBBERBANDWIDGET_H
+#define RUBBERBANDWIDGET_H
+
+#include <qwidget.h>
+
+
+class RubberbandWidget : public TQWidget
+{
+public:
+ RubberbandWidget( TQColor transparentColor, TQWidget *parent=0,
+ const char *name=0, WFlags f=0 );
+
+protected:
+ void mousePressEvent( TQMouseEvent* e );
+ void mouseMoveEvent( TQMouseEvent* e );
+ void mouseReleaseEvent( TQMouseEvent* e );
+
+ TQColor c;
+ TQPoint p1;
+ TQPoint p2;
+ TQPoint p3;
+ bool on;
+};
+
+#endif
diff --git a/examples/opengl/overlay_x11/utilities/NOTICE b/examples/opengl/overlay_x11/utilities/NOTICE
new file mode 100644
index 000000000..4157392b3
--- /dev/null
+++ b/examples/opengl/overlay_x11/utilities/NOTICE
@@ -0,0 +1,11 @@
+
+NOTICE: This source code distribution contains source code contained
+in the book "Programming OpenGL for the X Window System" (ISBN:
+0-201-48359-9) published by Addison-Wesley. The programs and
+associated files contained in the distribution were developed by Mark
+J. Kilgard and are Copyright 1994, 1995, 1996 by Mark J. Kilgard
+(unless otherwise noted). The programs are not in the public domain,
+but they are freely distributable without licensing fees. These
+programs are provided without guarantee or warranty expressed or
+implied.
+
diff --git a/examples/opengl/overlay_x11/utilities/README b/examples/opengl/overlay_x11/utilities/README
new file mode 100644
index 000000000..d96f3437b
--- /dev/null
+++ b/examples/opengl/overlay_x11/utilities/README
@@ -0,0 +1,22 @@
+
+Welcome to the "Programming OpenGL for the X Window System" Xlib-based
+example source code. The following table names each example program
+directory and what section of the book discusses the example.
+
+Section Example directory
+---------- ------------------
+ 1.5 glxsimple
+ 2.1 glxdino
+ 2.2.2 glxvisuals
+ 2.6.1 pixmap2eps
+ 6.2.3.1 xdevices
+ 6.2.7 dials
+ 6.3.4 sovinfo
+ 6.3.5 layerdemo
+
+I've tried to make the Makefiles as simple and as portable as
+possible. If you find problems with these examples, please report bugs
+to mjk@sgi.com
+
+- Mark Kilgard
+
diff --git a/examples/opengl/overlay_x11/utilities/glxvisuals/glxvisuals.c b/examples/opengl/overlay_x11/utilities/glxvisuals/glxvisuals.c
new file mode 100644
index 000000000..3c1a21e68
--- /dev/null
+++ b/examples/opengl/overlay_x11/utilities/glxvisuals/glxvisuals.c
@@ -0,0 +1,147 @@
+
+/* Copyright (c) Mark J. Kilgard, 1996. */
+
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
+ implied. This program is -not- in the public domain. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+static char *ClassOf(int c);
+static char *Format(int n, int w);
+
+void
+main(int argc, char *argv[])
+{
+ Display *dpy;
+ XVisualInfo match, *visualList, *vi, *visualToTry;
+ int errorBase, eventBase, major, minor, found;
+ int glxCapable, bufferSize, level, renderType, doubleBuffer, stereo,
+ auxBuffers, redSize, greenSize, blueSize, alphaSize, depthSize,
+ stencilSize, acRedSize, acGreenSize, acBlueSize, acAlphaSize;
+
+ dpy = XOpenDisplay(NULL);
+ if (!dpy) {
+ fprintf(stderr, "Could not connect to %s.\n", XDisplayName(NULL));
+ exit(1);
+ }
+ if (glXQueryExtension(dpy, &errorBase, &eventBase) == False) {
+ fprintf(stderr, "OpenGL not supported by X server.\n");
+ exit(1);
+ }
+
+ glXQueryVersion(dpy, &major, &minor);
+ printf("display: %s\n", XDisplayName(NULL));
+ printf("using GLX version: %d.%d\n\n", major, minor);
+
+ match.screen = DefaultScreen(dpy);
+ visualList = XGetVisualInfo(dpy, VisualScreenMask, &match, &found);
+
+ printf(" visual bf lv rg d st r g b a ax dp st accum buffs\n");
+ printf(" id dep cl sz l ci b ro sz sz sz sz bf th cl r g b a\n");
+ printf("-------------------------------------------------------------\n");
+
+ visualToTry = NULL;
+ for(vi = visualList; found > 0; found--, vi++) {
+ glXGetConfig(dpy, vi, GLX_USE_GL, &glxCapable);
+ if (glxCapable) {
+ printf("0x%x %2d %s", vi->visualid, vi->depth, ClassOf(vi->class));
+ glXGetConfig(dpy, vi, GLX_BUFFER_SIZE, &bufferSize);
+ glXGetConfig(dpy, vi, GLX_LEVEL, &level);
+ glXGetConfig(dpy, vi, GLX_RGBA, &renderType);
+ glXGetConfig(dpy, vi, GLX_DOUBLEBUFFER, &doubleBuffer);
+ glXGetConfig(dpy, vi, GLX_STEREO, &stereo);
+ glXGetConfig(dpy, vi, GLX_AUX_BUFFERS, &auxBuffers);
+ glXGetConfig(dpy, vi, GLX_RED_SIZE, &redSize);
+ glXGetConfig(dpy, vi, GLX_GREEN_SIZE, &greenSize);
+ glXGetConfig(dpy, vi, GLX_BLUE_SIZE, &blueSize);
+ glXGetConfig(dpy, vi, GLX_ALPHA_SIZE, &alphaSize);
+ glXGetConfig(dpy, vi, GLX_DEPTH_SIZE, &depthSize);
+ glXGetConfig(dpy, vi, GLX_STENCIL_SIZE, &stencilSize);
+ glXGetConfig(dpy, vi, GLX_ACCUM_RED_SIZE, &acRedSize);
+ glXGetConfig(dpy, vi, GLX_ACCUM_GREEN_SIZE, &acGreenSize);
+ glXGetConfig(dpy, vi, GLX_ACCUM_BLUE_SIZE, &acBlueSize);
+ glXGetConfig(dpy, vi, GLX_ACCUM_ALPHA_SIZE, &acAlphaSize);
+ printf(" %2s %2s %1s %1s %1s ",
+ Format(bufferSize, 2), Format(level, 2),
+ renderType ? "r" : "c",
+ doubleBuffer ? "y" : ".",
+ stereo ? "y" : ".");
+ printf("%2s %2s %2s %2s ",
+ Format(redSize, 2), Format(greenSize, 2),
+ Format(blueSize, 2), Format(alphaSize, 2));
+ printf("%2s %2s %2s %2s %2s %2s %2s",
+ Format(auxBuffers, 2), Format(depthSize, 2), Format(stencilSize, 2),
+ Format(acRedSize, 2), Format(acGreenSize, 2),
+ Format(acBlueSize, 2), Format(acAlphaSize, 2));
+ printf("\n");
+ visualToTry = vi;
+ }
+ }
+
+ if (visualToTry) {
+ GLXContext context;
+ Window window;
+ Colormap colormap;
+ XSetWindowAttributes swa;
+
+ context = glXCreateContext(dpy, visualToTry, 0, GL_TRUE);
+ colormap = XCreateColormap(dpy,
+ RootWindow(dpy, visualToTry->screen),
+ visualToTry->visual, AllocNone);
+ swa.colormap = colormap;
+ swa.border_pixel = 0;
+ window = XCreateWindow(dpy, RootWindow(dpy, visualToTry->screen), 0, 0, 100, 100,
+ 0, visualToTry->depth, InputOutput, visualToTry->visual,
+ CWBorderPixel | CWColormap, &swa);
+ glXMakeCurrent(dpy, window, context);
+ printf("\n");
+ printf("OpenGL vendor string: %s\n", glGetString(GL_VENDOR));
+ printf("OpenGL renderer string: %s\n", glGetString(GL_RENDERER));
+ printf("OpenGL version string: %s\n", glGetString(GL_VERSION));
+ if (glXIsDirect(dpy, context))
+ printf("direct rendering: supported\n");
+ printf( "GL extensions: '%s'\n\n", glGetString(GL_EXTENSIONS) );
+#if defined(GLX_VERSION_1_1)
+ printf( "GLX extensions: '%s'\n\n", glXQueryExtensionsString( dpy, visualToTry->screen ) );
+#endif
+
+ } else
+ printf("No GLX-capable visuals!\n");
+ XFree(visualList);
+}
+
+static char *
+ClassOf(int c)
+{
+ switch (c) {
+ case StaticGray: return "sg";
+ case GrayScale: return "gs";
+ case StaticColor: return "sc";
+ case PseudoColor: return "pc";
+ case TrueColor: return "tc";
+ case DirectColor: return "dc";
+ default: return "??";
+ }
+}
+
+static char *
+Format(int n, int w)
+{
+ static char buffer[256];
+ static int bufptr;
+ char *buf;
+
+ if (bufptr >= sizeof(buffer) - w)
+ bufptr = 0;
+ buf = buffer + bufptr;
+ if (n == 0)
+ sprintf(buf, "%*s", w, ".");
+ else
+ sprintf(buf, "%*d", w, n);
+ bufptr += w + 1;
+ return buf;
+}
diff --git a/examples/opengl/overlay_x11/utilities/sovinfo/sovLayerUtil.h b/examples/opengl/overlay_x11/utilities/sovinfo/sovLayerUtil.h
new file mode 100644
index 000000000..f45423a8d
--- /dev/null
+++ b/examples/opengl/overlay_x11/utilities/sovinfo/sovLayerUtil.h
@@ -0,0 +1,54 @@
+#ifndef __sovLayerUtil_h__
+#define __sovLayerUtil_h__
+
+/* Copyright (c) Mark J. Kilgard, 1996. */
+
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
+ implied. This program is -not- in the public domain. */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xmd.h>
+
+/* Transparent type values */
+/* None 0 */
+#define TransparentPixel 1
+#define TransparentMask 2
+
+/* layered visual info template flags */
+#define VisualLayerMask 0x200
+#define VisualTransparentType 0x400
+#define VisualTransparentValue 0x800
+#define VisualAllLayerMask 0xFFF
+
+/* layered visual info structure */
+typedef struct _sovVisualInfo {
+ XVisualInfo vinfo;
+ int layer;
+ int type;
+ unsigned long value;
+} sovVisualInfo;
+
+/* SERVER_OVERLAY_VISUALS property element */
+typedef struct _sovOverlayInfo {
+ long overlay_visual;
+ long transparent_type;
+ long value;
+ long layer;
+} sovOverlayInfo;
+
+extern sovVisualInfo *sovGetVisualInfo(
+ Display *display,
+ long lvinfo_mask,
+ sovVisualInfo *lvinfo_template,
+ int *nitems_return);
+extern Status sovMatchVisualInfo(
+ Display *display,
+ int screen,
+ int depth,
+ int class,
+ int layer,
+ sovVisualInfo *lvinfo_return);
+
+#endif /* __sovLayerUtil_h__ */
diff --git a/examples/opengl/overlay_x11/utilities/sovinfo/sovinfo.c b/examples/opengl/overlay_x11/utilities/sovinfo/sovinfo.c
new file mode 100644
index 000000000..059050c2f
--- /dev/null
+++ b/examples/opengl/overlay_x11/utilities/sovinfo/sovinfo.c
@@ -0,0 +1,95 @@
+
+/* Copyright (c) Mark J. Kilgard, 1996. */
+
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
+ implied. This program is -not- in the public domain. */
+
+/* compile: cc -o sovinfo sovinfo.c sovLayerUtil.c -lX11 */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "sovLayerUtil.h"
+
+int
+main(int argc, char *argv[])
+{
+ Display *dpy;
+ char *display_name, *arg, *class;
+ sovVisualInfo template, *lvinfo;
+ int nVisuals, i, overlaysOnly = 0;
+
+ display_name = NULL;
+ for (i = 1; i < argc; i++) {
+ arg = argv[i];
+ if (!strcmp(arg, "-display")) {
+ if (++i >= argc) {
+ fprintf(stderr, "sovinfo: missing argument to -display\n");
+ exit(1);
+ }
+ display_name = argv[i];
+ } else if (!strcmp(arg, "-overlays_only")) {
+ overlaysOnly = 1;
+ } else {
+ fprintf(stderr,
+ "usage: sovinfo [-display dpy] [-overlays_only]\n");
+ exit(1);
+ }
+ }
+ dpy = XOpenDisplay(display_name);
+ if (dpy == NULL) {
+ fprintf(stderr, "sovinfo: cannot open display %s\n",
+ XDisplayName(NULL));
+ exit(1);
+ }
+ lvinfo = sovGetVisualInfo(dpy, 0L, &template, &nVisuals);
+ for (i = 0; i < nVisuals; i++) {
+ if (!overlaysOnly || lvinfo[i].layer > 0) {
+ printf(" Visual ID: 0x%x\n", lvinfo[i].vinfo.visualid);
+ printf(" screen: %d\n", lvinfo[i].vinfo.screen);
+ printf(" depth: %d\n", lvinfo[i].vinfo.depth);
+ switch (lvinfo[i].vinfo.class) {
+ case StaticGray:
+ class = "StaticGray";
+ break;
+ case GrayScale:
+ class = "GrayScale";
+ break;
+ case StaticColor:
+ class = "StaticColor";
+ break;
+ case PseudoColor:
+ class = "PseudoColor";
+ break;
+ case TrueColor:
+ class = "TrueColor";
+ break;
+ case DirectColor:
+ class = "DirectColor";
+ break;
+ default:
+ class = "Unknown";
+ break;
+ }
+ printf(" class: %s\n", class);
+ switch (lvinfo[i].type) {
+ case None:
+ printf(" transparent type: None\n");
+ break;
+ case TransparentPixel:
+ printf(" transparent type: TransparentPixel\n");
+ printf(" pixel value: %d\n", lvinfo[i].value);
+ break;
+ case TransparentMask:
+ printf(" transparent type: TransparentMask\n");
+ printf(" transparency mask: %0x%x\n", lvinfo[i].value);
+ break;
+ default:
+ printf(" transparent type: Unknown or invalid\n");
+ break;
+ }
+ printf(" layer: %d\n", lvinfo[i].layer);
+ }
+ }
+ return 0;
+}
diff --git a/examples/opengl/overlay_x11/utilities/sovinfo/sovlayerutil.c b/examples/opengl/overlay_x11/utilities/sovinfo/sovlayerutil.c
new file mode 100644
index 000000000..8837d06cf
--- /dev/null
+++ b/examples/opengl/overlay_x11/utilities/sovinfo/sovlayerutil.c
@@ -0,0 +1,150 @@
+
+/* Copyright (c) Mark J. Kilgard, 1996. */
+
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
+ implied. This program is -not- in the public domain. */
+
+#include <stdlib.h>
+#include "sovLayerUtil.h"
+
+static Bool layersRead;
+static Atom overlayVisualsAtom;
+static sovOverlayInfo **overlayInfoPerScreen;
+static int *numOverlaysPerScreen;
+
+sovVisualInfo *
+sovGetVisualInfo(Display *display, long lvinfo_mask,
+ sovVisualInfo *lvinfo_template, int *nitems_return)
+{
+ XVisualInfo *vinfo;
+ sovVisualInfo *layerInfo;
+ Window root;
+ Status status;
+ Atom actualType;
+ unsigned long sizeData, bytesLeft;
+ int actualFormat, numVisuals, numScreens, count, i, j;
+
+ vinfo = XGetVisualInfo(display, lvinfo_mask & VisualAllMask,
+ &lvinfo_template->vinfo, nitems_return);
+ if (vinfo == NULL)
+ return NULL;
+ numVisuals = *nitems_return;
+ if (layersRead == False) {
+ overlayVisualsAtom = XInternAtom(display,
+ "SERVER_OVERLAY_VISUALS", True);
+ if (overlayVisualsAtom != None) {
+ numScreens = ScreenCount(display);
+ overlayInfoPerScreen = (sovOverlayInfo **)
+ malloc(numScreens * sizeof(sovOverlayInfo *));
+ numOverlaysPerScreen = (int *) malloc(numScreens * sizeof(int));
+ if (overlayInfoPerScreen != NULL &&
+ numOverlaysPerScreen != NULL) {
+ for (i = 0; i < numScreens; i++) {
+ root = RootWindow(display, i);
+ status = XGetWindowProperty(display, root, overlayVisualsAtom,
+ 0L, (long) 10000, False, overlayVisualsAtom,
+ &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlayInfoPerScreen[i]);
+ if (status != Success ||
+ actualType != overlayVisualsAtom ||
+ actualFormat != 32 || sizeData < 4)
+ numOverlaysPerScreen[i] = 0;
+ else
+ numOverlaysPerScreen[i] = sizeData / 4;
+ }
+ layersRead = True;
+ } else {
+ if (overlayInfoPerScreen != NULL)
+ free(overlayInfoPerScreen);
+ if (numOverlaysPerScreen != NULL)
+ free(numOverlaysPerScreen);
+ }
+ }
+ }
+ layerInfo = (sovVisualInfo *)
+ malloc(numVisuals * sizeof(sovVisualInfo));
+ if (layerInfo == NULL) {
+ XFree(vinfo);
+ return NULL;
+ }
+ count = 0;
+ for (i = 0; i < numVisuals; i++) {
+ XVisualInfo *pVinfo;
+ int screen;
+ sovOverlayInfo *overlayInfo;
+
+ pVinfo = &vinfo[i];
+ screen = pVinfo->screen;
+ overlayInfo = NULL;
+ if (layersRead) {
+ for (j = 0; j < numOverlaysPerScreen[screen]; j++)
+ if (pVinfo->visualid ==
+ overlayInfoPerScreen[screen][j].overlay_visual) {
+ overlayInfo = &overlayInfoPerScreen[screen][j];
+ break;
+ }
+ }
+ if (lvinfo_mask & VisualLayerMask)
+ if (overlayInfo == NULL) {
+ if (lvinfo_template->layer != 0)
+ continue;
+ } else if (lvinfo_template->layer != overlayInfo->layer)
+ continue;
+ if (lvinfo_mask & VisualTransparentType)
+ if (overlayInfo == NULL) {
+ if (lvinfo_template->type != None)
+ continue;
+ } else if (lvinfo_template->type !=
+ overlayInfo->transparent_type)
+ continue;
+ if (lvinfo_mask & VisualTransparentValue)
+ if (overlayInfo == NULL)
+ /* non-overlay visuals have no sense of
+ TransparentValue */
+ continue;
+ else if (lvinfo_template->value != overlayInfo->value)
+ continue;
+ layerInfo[count].vinfo = *pVinfo;
+ if (overlayInfo == NULL) {
+ layerInfo[count].layer = 0;
+ layerInfo[count].type = None;
+ layerInfo[count].value = 0; /* meaningless */
+ } else {
+ layerInfo[count].layer = overlayInfo->layer;
+ layerInfo[count].type = overlayInfo->transparent_type;
+ layerInfo[count].value = overlayInfo->value;
+ }
+ count++;
+ }
+ XFree(vinfo);
+ *nitems_return = count;
+ if (count == 0) {
+ XFree(layerInfo);
+ return NULL;
+ } else
+ return layerInfo;
+}
+
+Status
+sovMatchVisualInfo(Display *display, int screen,
+ int depth, int class, int layer, sovVisualInfo *lvinfo_return)
+{
+ sovVisualInfo *lvinfo;
+ sovVisualInfo lvinfoTemplate;
+ int nitems;
+
+ lvinfoTemplate.vinfo.screen = screen;
+ lvinfoTemplate.vinfo.depth = depth;
+ lvinfoTemplate.vinfo.class = class;
+ lvinfoTemplate.layer = layer;
+ lvinfo = sovGetVisualInfo(display,
+ VisualScreenMask|VisualDepthMask|VisualClassMask|VisualLayerMask,
+ &lvinfoTemplate, &nitems);
+ if (lvinfo != NULL && nitems > 0) {
+ *lvinfo_return = *lvinfo;
+ return 1;
+ } else
+ return 0;
+}