summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralanh <alanh>2002-10-22 13:22:42 +0000
committeralanh <alanh>2002-10-22 13:22:42 +0000
commitd9adac36dc5c47304f8b98458bab48c0394dd5b2 (patch)
treeaf642c159aeabdbd8ac6e58ccc4bea054ef784dd
parenta10dd7bf6ed1ec9e9810710a71f9238061369e15 (diff)
Initial revision
-rw-r--r--xc/programs/Xserver/fb/fbtrap.c1382
-rw-r--r--xc/programs/Xserver/fb/module/Imakefile6
-rw-r--r--xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Credits.rtf139
-rw-r--r--xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Imakefile25
-rw-r--r--xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Localizable.stringsbin0 -> 1498 bytes
-rw-r--r--xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/classes.nib64
-rw-r--r--xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/objects.nibbin0 -> 20861 bytes
-rw-r--r--xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/XDarwinHelp.html.cpp216
-rw-r--r--xc/programs/Xserver/hw/darwin/darwinEvents.c418
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/Imakefile102
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/Preferences.h105
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/Preferences.m517
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XApplication.h47
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XApplication.m47
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.h41
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.m45
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XDarwin.pbproj/project.pbxproj1376
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.c165
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.man75
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XServer.h100
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XServer.m916
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XView.h42
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/XView.m76
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/aqua.h53
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/aquaCommon.h56
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/aquaPicture.c268
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/aquaWindow.c171
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/fakeBoxRec.h15
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/fullscreen.c444
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/fullscreen.h33
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.c420
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.h10
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartz.c288
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartz.h51
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzAudio.c342
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzAudio.h41
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzCocoa.m148
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzCommon.h92
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzCursor.c620
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzCursor.h43
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.c150
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.h45
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzShared.h57
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/quartzStartup.c139
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootless.h136
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessAqua.h15
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessAquaGlue.c242
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.h40
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.m427
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.c360
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.h228
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessGC.c1218
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessScreen.c419
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessValTree.c640
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c829
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.h36
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/Imakefile127
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/XDarwin.pbproj/project.pbxproj1372
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.h72
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.m832
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/XView.h50
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/XView.m330
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.h36
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.m104
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootless.h127
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAqua.h15
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaGlue.c226
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.h38
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.m237
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.c262
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.h214
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessGC.c1170
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessScreen.c426
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessValTree.c744
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.c674
-rw-r--r--xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.h32
-rw-r--r--xc/programs/Xserver/hw/kdrive/pcmcia/pcmciarotate.c332
-rw-r--r--xc/programs/Xserver/hw/xfree86/Domain.note159
-rw-r--r--xc/programs/Xserver/hw/xfree86/doc/README.Solaris222
-rw-r--r--xc/programs/Xserver/hw/xwin/X.icobin0 -> 4710 bytes
-rw-r--r--xc/programs/Xserver/hw/xwin/XWin.rc60
-rw-r--r--xc/programs/Xserver/hw/xwin/resource.h41
-rw-r--r--xc/programs/Xserver/hw/xwin/winconfig.c949
-rw-r--r--xc/programs/Xserver/hw/xwin/winconfig.h332
-rw-r--r--xc/programs/Xserver/hw/xwin/winmsg.c119
-rw-r--r--xc/programs/Xserver/hw/xwin/winmsg.h72
-rw-r--r--xc/programs/Xserver/hw/xwin/winregistry.c66
87 files changed, 23420 insertions, 0 deletions
diff --git a/xc/programs/Xserver/fb/fbtrap.c b/xc/programs/Xserver/fb/fbtrap.c
new file mode 100644
index 000000000..3a44d53ef
--- /dev/null
+++ b/xc/programs/Xserver/fb/fbtrap.c
@@ -0,0 +1,1382 @@
+/*
+ * $XFree86: xc/programs/Xserver/fb/fbtrap.c,v 1.10 2002/09/27 00:31:24 keithp Exp $
+ *
+ * Copyright © 2000 University of Southern California
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of University
+ * of Southern California not be used in advertising or publicity
+ * pertaining to distribution of the software without specific,
+ * written prior permission. University of Southern California makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * University of Southern California DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE BE LIABLE FOR
+ * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ * Author: Carl Worth, USC, Information Sciences Institute */
+
+#include "fb.h"
+
+#ifdef RENDER
+
+#include "picturestr.h"
+#include "mipict.h"
+#include "fbpict.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+#include <assert.h>
+
+#define ASSERT(e) assert(e)
+
+#endif
+
+#ifndef ASSERT
+#define ASSERT(e)
+#endif
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#define MAX_AREA 0x80000000
+
+/*
+ * A RationalPoint is an exact position along one of the trapezoid
+ * edges represented by an approximate position (x,y) and two error
+ * terms (ex_dy, ey_dx). The error in X is multiplied by the Y
+ * dimension of the line while the error in Y is multiplied by the
+ * X dimension of the line, allowing an exact measurement of the
+ * distance from (x,y) to the line.
+ *
+ * Generally, while walking an edge, one of ex_dy/ey_dx will be zero
+ * indicating that the position error is held in the other.
+ */
+typedef struct {
+ xFixed x;
+ xFixed ex_dy;
+ xFixed y;
+ xFixed ey_dx;
+} RationalPoint;
+
+/*
+ * Edges are walked both horizontally and vertically
+ * They are walked vertically to get to a particular row
+ * of pixels, and then walked horizontally within that row
+ * to compute pixel coverage.
+ *
+ * Edges are always walked from top to bottom and from
+ * left to right. This means that for lines moving leftwards
+ * from top to bottom, the left to right walking actually moves
+ * backwards along the line with respect to the top to bottom
+ * walking.
+ */
+
+/*
+ * A RationalRow represents the two positions where
+ * an edge intersects a row of pixels. This is used
+ * to walk an edge vertically
+ */
+
+typedef struct {
+ RationalPoint top; /* intersection at top of row */
+ RationalPoint bottom; /* intersection at bottom of row */
+ RationalPoint pixel_top; /* intersection at top of pixel */
+} RationalRow;
+
+/*
+ * A RationalCol represents the two positions where
+ * an edge intersects a column of pixels
+ */
+
+typedef struct {
+ RationalPoint left; /* intersection at left of column */
+ RationalPoint right; /* intersection at right of column */
+} RationalCol;
+
+/*
+ Here are some thoughts on line walking:
+
+ Conditions: c2.x - c1.x = 1
+ r2.y - r1.y = 1
+
+ A B C D E F G H
+ c1\ c1 c2 /c2
+r1 r1 |\ \ r1 r1 / r1/| r1 r1
+\-+---+ \-+---+ +-\-+ +\--+ +--/+ +-/-+ +---+-/ +---+-/
+ \| | `.c1 | |r1\| | \ | | / | |/ | | .' | |/
+c1\ | |`-.|c2 | \c2 | | | | | | c1/ | c1|,_/|c2 | /c2
+ |\ | | `. | |\ | \ | | / | /| | ./ | | /|
+ +-\-+ +---+-\ +---+-\ +--\+ +/--+ /-+---+ /-+---+ +-/-+
+ r2\| r2 r2 r2\ /r2 r2 r2 |/r2
+ \c2 c2 c1 c1/
+
+ Bottom Right Right Bottom Top Top Right Right
+
+State transitions:
+
+A -> C, D E -> E, F
+B -> A, B F -> G, H
+C -> A, B G -> G, H
+D -> C, D H -> E, F
+
+*/
+
+/*
+ * Values for PixelWalk.depart. Top and Bottom can have the same value
+ * as only one mode is possible given a line of either positive or
+ * negative slope. These mark the departure edge while walking
+ * rightwards across columns.
+ */
+
+typedef enum _departure {
+ DepartTop = 0, /* edge exits top of pixel */
+ DepartBottom = 0, /* edge exits bottom of pixel */
+ DepartRight = 1 /* edge exits right edge of pixel */
+} Departure;
+
+/*
+ * PixelWalk
+ *
+ * This structure holds state to walk a single edge down the trapezoid.
+ *
+ * The edge is walked twice -- once by rows and once by columns.
+ * The two intersections of the pixel by the edge are then set
+ * from either the row or column position, depending on which edge
+ * is intersected.
+ *
+ * Note that for lines moving left, walking by rows moves down the
+ * line (increasing y) while walking by columns moves up the line
+ * (decreasing y).
+ */
+typedef struct {
+ xFixed dx;
+ xFixed ey_thresh;
+ xFixed dy;
+ xFixed ex_thresh;
+
+ Departure depart;
+
+ /* slope */
+ xFixed m;
+ xFixed em_dx;
+ xFixed y_correct;
+ xFixed ey_correct;
+
+ /* Inverse slope. Does this have a standard symbol? */
+ xFixed p;
+ xFixed ep_dy;
+ xFixed x_correct;
+ xFixed ex_correct;
+
+ /* Trapezoid bottom, used to limit walking to the last row */
+ xFixed bottom;
+
+ /*
+ * Current edge positions along pixel rows and columns
+ */
+ RationalRow row;
+ RationalCol col;
+
+ /*
+ * The three pixel intersection points, copied from the appropriate
+ * row or column position above
+ */
+ RationalPoint p_pixel_top;
+ RationalPoint p_trap_top;
+ RationalPoint p_trap_bottom;
+} PixelWalk;
+
+#if 0
+#ifdef GCC
+#define INLINE inline
+#endif
+#endif
+
+#ifndef INLINE
+#define INLINE
+#endif
+
+/*
+ * Step 'pt' vertically to 'newy'.
+ */
+static INLINE void
+pixelWalkMovePointToRow (PixelWalk *pw, RationalPoint *pt, xFixed newy)
+{
+ xFixed_32_32 oex;
+ xFixed xoff;
+
+ /* X error of old X position and new Y position */
+ oex = (xFixed_32_32) pw->dx * (newy - pt->y) - pt->ey_dx + pt->ex_dy;
+
+ /* amount to step X by */
+ xoff = oex / pw->dy;
+
+ /* step X */
+ pt->x = pt->x + xoff;
+
+ /* set new X error value for new X position and new Y positition */
+ pt->ex_dy = oex - (xFixed_32_32) pw->dy * xoff;
+
+ /* set new Y position, set Y error to zero */
+ pt->y = newy;
+ pt->ey_dx = 0;
+}
+
+/*
+ * Step 'pt' horizontally to 'newx'
+ */
+static INLINE void
+pixelWalkMovePointToCol (PixelWalk *pw, RationalPoint *pt, xFixed newx)
+{
+ xFixed_32_32 oey;
+ xFixed yoff;
+
+ /* Special case vertical lines to arbitrary y */
+ if (pw->dx == 0)
+ {
+ pt->x = newx;
+ pt->ex_dy = 0;
+ pt->y = 0;
+ pt->ey_dx = 0;
+ }
+ else
+ {
+ /* Y error of old Y position and new X position */
+ oey = (xFixed_32_32) pw->dy * (newx - pt->x) - pt->ex_dy + pt->ey_dx;
+
+ /* amount to step Y by */
+ yoff = oey / pw->dx;
+
+ /* step Y */
+ pt->y = pt->y + yoff;
+
+ /* set new Y error value for new Y position and new X position */
+ pt->ey_dx = oey - (xFixed_32_32) pw->dx * yoff;
+
+ /* set new X position, set X error to zero */
+ pt->x = newx;
+ pt->ex_dy = 0;
+ }
+}
+
+/*
+ * Step the 'row' element of 'pw' vertically
+ * (increasing y) by one whole pixel
+ */
+static INLINE void
+pixelWalkStepRow (PixelWalk *pw)
+{
+ xFixed y_next = xFixedFloor (pw->row.bottom.y) + xFixed1;
+
+ if (y_next > pw->bottom)
+ y_next = pw->bottom;
+
+ /* pw.row.top.y < pw.row.bottom.y */
+ pw->row.top = pw->row.bottom;
+
+ if (y_next - pw->row.bottom.y == xFixed1)
+ {
+ pw->row.pixel_top = pw->row.bottom;
+ pw->row.bottom.y += xFixed1;
+ pw->row.bottom.x += pw->p;
+ pw->row.bottom.ex_dy += pw->ep_dy;
+ if (abs (pw->row.bottom.ex_dy) > pw->ex_thresh)
+ {
+ pw->row.bottom.x += pw->x_correct;
+ pw->row.bottom.ex_dy += pw->ex_correct;
+ }
+ }
+ else
+ {
+ pixelWalkMovePointToRow (pw, &pw->row.pixel_top,
+ xFixedCeil (y_next) - xFixed1);
+ pixelWalkMovePointToRow (pw, &pw->row.bottom, y_next);
+ }
+}
+
+/*
+ * Step the 'col' element of 'pw' horizontally
+ * (increasing x) by one whole pixel
+ */
+static INLINE void
+pixelWalkStepCol (PixelWalk *pw)
+{
+ /* pw.col.p1.x < pw.col.p2.x */
+ /*
+ * Copy the current right point into the left point
+ */
+ pw->col.left = pw->col.right;
+
+ /*
+ * Now incrementally walk across the pixel
+ */
+ pw->col.right.x += xFixed1;
+ pw->col.right.y += pw->m;
+ pw->col.right.ey_dx += pw->em_dx;
+ if (pw->col.right.ey_dx > pw->ey_thresh)
+ {
+ pw->col.right.y += pw->y_correct;
+ pw->col.right.ey_dx += pw->ey_correct;
+ }
+}
+/*
+ * Walk to the nearest edge of the next pixel, filling in both p1 and
+ * p2 as necessary from either the row or col intersections.
+ *
+ * The "next" pixel is defined to be the next pixel intersected by the
+ * line with pixels visited in raster scan order, (for the benefit of
+ * cache performance). For lines with positive slope it is easy to
+ * achieve raster scan order by simply calling StepCol for each pixel
+ * in a given scanline, then calling StepRow once at the end of each
+ * scanline.
+ *
+ * However, for lines of negative slope where the magnitude of dx is
+ * greater than dy, a little more work needs to be done. The pixels of
+ * a particular scanline will be visited by succesive calls to StepCol
+ * as before. This will effectively step "up" the line as we scan from
+ * left to right. But, the call to StepRow at the end of the scan line
+ * will step "down" the line and the column information will be
+ * invalid at that point.
+ *
+ * For now, I fix up the column of all negative slope lines by calling
+ * MovePointToCol at the end of each scanline. However, this is an
+ * extremely expensive operation since it involves a 64-bit multiply
+ * and a 64-bit divide. It would be much better, (at least as long as
+ * abs(dx) is not much greater than dy), to instead step the col
+ * backwards as many times as necessary. Or even better, we could
+ * simply restore col to the position it began at when we started the
+ * scanline, then simply step it backwards once. That would give a
+ * performance benefit for lines with slope of any magnitude.
+ */
+
+static INLINE void
+pixelWalkNextPixel (PixelWalk *pw)
+{
+ if (pw->dx < 0)
+ {
+ /*
+ * left moving lines
+ *
+ * Check which pixel edge we're departing from
+ *
+ * Remember that in this case (dx < 0), the 'row' element of 'pw'
+ * walks down the line while 'col' walks up
+ */
+ if (pw->depart == DepartTop)
+ {
+ /*
+ * The edge departs the row at this pixel, the
+ * next time it gets used will be for the next row
+ *
+ * Step down one row and then recompute the
+ * column values to start the next row of
+ * pixels
+ */
+ pixelWalkStepRow(pw);
+ /*
+ * Set column exit pixel
+ */
+ pixelWalkMovePointToCol(pw, &pw->col.right, xFixedFloor(pw->row.bottom.x));
+ /*
+ * This moves the exit pixel to the entry pixel
+ * and computes the next exit pixel
+ */
+ pixelWalkStepCol(pw);
+ /*
+ * The first pixel on the next row will always
+ * be entered from below, set the lower
+ * intersection of this edge with that pixel
+ */
+ pw->p_trap_bottom = pw->row.bottom;
+ }
+ else /* pw->depart == DepartRight */
+ {
+ /*
+ * easy case -- just move right one pixel
+ */
+ pixelWalkStepCol(pw);
+ /*
+ * Set the lower intersection of the edge with the
+ * pixel -- that's just where the edge entered
+ * the pixel from the left
+ */
+ pw->p_trap_bottom = pw->col.left;
+ }
+ /*
+ * Now compute which edge the pixel
+ * is departing from
+ */
+ if (pw->row.top.x <= pw->col.right.x)
+ {
+ /*
+ * row intersection is left of column intersection,
+ * that means the edge hits the top of the pixel
+ * before it hits the right edge
+ */
+ pw->p_trap_top = pw->row.top;
+ pw->depart = DepartTop;
+ /*
+ * Further check to see whether the edge
+ * leaves the right or top edge of the
+ * whole pixel
+ */
+ if (pw->row.pixel_top.x <= pw->col.right.x)
+ pw->p_pixel_top = pw->row.pixel_top;
+ else
+ pw->p_pixel_top = pw->col.right;
+ }
+ else
+ {
+ /*
+ * Row intersection is right of colum intersection,
+ * that means the edge hits the right edge of the
+ * pixel first
+ */
+ pw->p_trap_top = pw->col.right;
+ pw->p_pixel_top = pw->col.right;
+ pw->depart = DepartRight;
+ }
+ }
+ else
+ {
+ /*
+ * right moving lines
+ *
+ * Check which edge we're departing from
+ *
+ * In the dx >= 0 case, the row and col elements both
+ * walk downwards
+ */
+ if (pw->depart == DepartBottom)
+ {
+ /*
+ * The edge departs the row at this pixel,
+ * the next time it gets used will be for the
+ * next row
+ *
+ * Step down one row and (maybe) over one
+ * column to prepare for the next row
+ */
+ if (pw->row.bottom.x == pw->col.right.x)
+ {
+ /*
+ * right through the corner of the pixel,
+ * adjust the column
+ */
+ pixelWalkStepCol(pw);
+ }
+ pixelWalkStepRow(pw);
+ /*
+ * Set the upper intersection of the edge with
+ * the pixel, the first pixel on the next
+ * row is always entered from the top
+ */
+ pw->p_trap_top = pw->row.top;
+ pw->p_pixel_top = pw->row.pixel_top;
+ }
+ else /* pw->depart == DepartRight */
+ {
+ /*
+ * Easy case -- move right one
+ * pixel
+ */
+ pixelWalkStepCol(pw);
+ /*
+ * Set the upper intersection of the edge
+ * with the pixel, that's along the left
+ * edge of the pixel
+ */
+ pw->p_trap_top = pw->col.left;
+ pw->p_pixel_top = pw->col.left;
+ }
+ /*
+ * Now compute the exit edge and the
+ * lower intersection of the edge with the pixel
+ */
+ if (pw->row.bottom.x <= pw->col.right.x)
+ {
+ /*
+ * Hit the place where the edge leaves
+ * the pixel, the lower intersection is
+ * where the edge hits the bottom
+ */
+ pw->p_trap_bottom = pw->row.bottom;
+ pw->depart = DepartBottom;
+ }
+ else
+ {
+ /*
+ * The edge goes through the
+ * next pixel on the row,
+ * the lower intersection is where the
+ * edge hits the right side of the pixel
+ */
+ pw->p_trap_bottom = pw->col.right;
+ pw->depart = DepartRight;
+ }
+ }
+}
+
+/*
+ * Compute the first pixel intersection points
+ * and the departure type from that pixel
+ */
+static void
+pixelWalkFirstPixel (PixelWalk *pw)
+{
+ if (pw->dx < 0)
+ {
+ if (pw->row.top.x <= pw->col.right.x)
+ {
+ /*
+ * leaving through the top.
+ * upper position is the upper point of
+ * the 'row' element
+ */
+ pw->depart = DepartTop;
+ pw->p_trap_top = pw->row.top;
+ /*
+ * further check for pixel top
+ */
+ if (pw->row.pixel_top.x <= pw->col.right.x)
+ pw->p_pixel_top = pw->row.pixel_top;
+ else
+ pw->p_pixel_top = pw->col.right;
+ }
+ else
+ {
+ /*
+ * leaving through the right side
+ * upper position is the right point of
+ * the 'col' element
+ */
+ pw->depart = DepartRight;
+ pw->p_trap_top = pw->col.right;
+ pw->p_pixel_top = pw->col.right;
+ }
+ /*
+ * Now find the lower pixel intersection point
+ */
+ if (pw->row.bottom.x >= pw->col.left.x)
+ /*
+ * entering through bottom,
+ * lower position is the bottom point of
+ * the 'row' element
+ */
+ pw->p_trap_bottom = pw->row.bottom;
+ else
+ /*
+ * entering through left side,
+ * lower position is the left point of
+ * the 'col' element
+ */
+ pw->p_trap_bottom = pw->col.left;
+ }
+ else
+ {
+ if (pw->row.bottom.x <= pw->col.right.x)
+ {
+ /*
+ * leaving through the bottom (or corner).
+ * lower position is the lower point of
+ * the 'row' element
+ */
+ pw->depart = DepartBottom;
+ pw->p_trap_bottom = pw->row.bottom;
+ }
+ else
+ {
+ /*
+ * leaving through the right side
+ * lower position is the right point of
+ * the 'col' element
+ */
+ pw->depart = DepartRight;
+ pw->p_trap_bottom = pw->col.right;
+ }
+ /*
+ * Now find the upper pixel intersection point
+ */
+ if (pw->row.top.x >= pw->col.left.x)
+ {
+ /*
+ * entering through the top (or corner),
+ * upper position is the top point
+ * of the 'row' element
+ */
+ pw->p_trap_top = pw->row.top;
+ /*
+ * further check for pixel entry
+ */
+ if (pw->row.pixel_top.x >= pw->col.left.x)
+ pw->p_pixel_top = pw->row.pixel_top;
+ else
+ pw->p_pixel_top = pw->col.left;
+ }
+ else
+ {
+ /*
+ * entering through the left side,
+ * upper position is the left point of
+ * the 'col' element
+ */
+ pw->p_trap_top = pw->col.left;
+ pw->p_pixel_top = pw->col.left;
+ }
+ }
+}
+
+static void
+pixelWalkInit (PixelWalk *pw, xLineFixed *line, xFixed top_y, xFixed bottom_y)
+{
+ xFixed_32_32 dy_inc, dx_inc;
+ xFixed next_y;
+ xFixed left_x;
+ xPointFixed *top, *bot;
+
+ next_y = xFixedFloor (top_y) + xFixed1;
+ if (next_y > bottom_y)
+ next_y = bottom_y;
+
+ /*
+ * Orient lines top down
+ */
+ if (line->p1.y < line->p2.y)
+ {
+ top = &line->p1;
+ bot = &line->p2;
+ }
+ else
+ {
+ top = &line->p2;
+ bot = &line->p1;
+ }
+
+ pw->dx = bot->x - top->x;
+ pw->ey_thresh = abs(pw->dx >> 1);
+ pw->dy = bot->y - top->y;
+ pw->ex_thresh = pw->dy >> 1;
+
+ /*
+ * Set step values for walking lines
+ */
+ if (pw->dx < 0)
+ {
+ pw->x_correct = -1;
+ pw->ex_correct = pw->dy;
+ pw->y_correct = -1;
+ pw->ey_correct = pw->dx;
+ }
+ else
+ {
+ pw->x_correct = 1;
+ pw->ex_correct = -pw->dy;
+ pw->y_correct = 1;
+ pw->ey_correct = -pw->dx;
+ }
+
+ pw->bottom = bottom_y;
+
+ /*
+ * Compute Bresenham values for walking edges incrementally
+ */
+ dy_inc = (xFixed_32_32) xFixed1 * pw->dy; /* > 0 */
+ if (pw->dx != 0)
+ {
+ pw->m = dy_inc / pw->dx; /* sign(dx) */
+ pw->em_dx = dy_inc - (xFixed_32_32) pw->m * pw->dx; /* > 0 */
+ }
+ else
+ {
+ /* Vertical line. Setting these to zero prevents us from
+ having to put any conditions in pixelWalkStepCol. */
+ pw->m = 0;
+ pw->em_dx = 0;
+ }
+
+ dx_inc = (xFixed_32_32) xFixed1 * (xFixed_32_32) pw->dx; /* sign(dx) */
+ pw->p = dx_inc / pw->dy; /* sign(dx) */
+ pw->ep_dy = dx_inc - (xFixed_32_32) pw->p * pw->dy; /* sign(dx) */
+
+ /*
+ * Initialize 'row' for walking down rows
+ */
+ pw->row.bottom.x = top->x;
+ pw->row.bottom.ex_dy = 0;
+ pw->row.bottom.y = top->y;
+ pw->row.bottom.ey_dx = 0;
+
+ /*
+ * Initialize 'pixel_top' to be on the line for
+ * the first step
+ */
+ pw->row.pixel_top = pw->row.bottom;
+ /*
+ * Move to the pixel above the 'top_y' coordinate,
+ * first setting 'bottom' and then using StepRow
+ * which moves that to 'top' and computes the next 'bottom'
+ */
+ pixelWalkMovePointToRow(pw, &pw->row.bottom, top_y);
+ pixelWalkStepRow(pw);
+
+ /*
+ * Initialize 'col' for walking across columns
+ */
+ pw->col.right.x = top->x;
+ pw->col.right.ex_dy = 0;
+ pw->col.right.y = top->y;
+ pw->col.right.ey_dx = 0;
+
+ /*
+ * First set the column to the left most
+ * pixel hit by the row
+ */
+ if (pw->dx < 0)
+ left_x = pw->row.bottom.x;
+ else
+ left_x = pw->row.top.x;
+
+ pixelWalkMovePointToCol(pw, &pw->col.right, xFixedFloor (left_x));
+ pixelWalkStepCol(pw);
+
+ /*
+ * Compute first pixel intersections and the
+ * first departure state
+ */
+ pixelWalkFirstPixel (pw);
+}
+
+#define RoundShift(a,b) (((a) + (1 << ((b) - 1))) >> (b))
+#define MaxAlpha(depth) ((1 << (depth)) - 1)
+
+#define AreaAlpha(area, depth) (RoundShift (RoundShift (area, depth) * \
+ MaxAlpha (depth), \
+ (31 - depth)))
+
+/*
+ Pixel coverage from the upper-left corner bounded by one horizontal
+ bottom line (bottom) and one line defined by two points, (x1,y1) and
+ (x2,y2), which intersect the pixel. y1 must be less than y2. There
+ are 8 cases yielding the following area calculations:
+
+ A B C D E F G H
++---+ +---+ +-1-+ +1--+ +--1+ +-1-+ +---+ +---+
+| | 1 | | \| | \ | | / | |/ | | 1 | |
+1 | |`-.| | 2 | | | | | | 2 | |,_/| | 1
+|\ | | 2 | | | \ | | / | | | 2 | | /|
++-2-+ +---+ +---+ +--2+ +2--+ +---+ +---+ +-2-+
+
+A: (1/2 * x2 * (y2 - y1))
+B: (1/2 * x2 * (y2 - y1)) + (bottom - y2) * x2
+C: (1/2 * (x1 + x2) * y2 ) + (bottom - y2) * x2
+D: (1/2 * (x1 + x2) * y2 )
+E: (1/2 * (x1 + x2) * y2 )
+F: (1/2 * x1 * y2 )
+G: (1/2 * x1 * (y2 - y1)) + x1 * y1
+H: (1/2 * (x1 + x2) * (y2 - y1)) + x1 * y1
+
+The union of these calculations is valid for all cases. Namely:
+
+ (1/2 * (x1 + x2) * (y2 - y1)) + (bottom - y2) * x2 + x1 * y1
+
+An exercise for later would perhaps be to optimize the calculations
+for some of the cases above. Specifically, it's possible to eliminate
+multiplications by zero in several cases, leaving a maximum of two
+multiplies per pixel calculation. (This is even more promising now
+that the higher level code actually computes the exact same 8 cases
+as part of its pixel walking).
+
+But, for now, I just want to get something working correctly even if
+slower. So, we'll use the non-optimized general equation.
+
+*/
+
+/* 1.16 * 1.16 -> 1.31 */
+#define AREA_MULT(w, h) ( (xFixed_1_31) (((((xFixed_1_16)w)*((xFixed_1_16)h) + 1) >> 1) | (((xFixed_1_16)w)&((xFixed_1_16)h)&0x10000) << 15))
+
+/* (1.16 + 1.16) / 2 -> 1.16 */
+#define WIDTH_AVG(x1,x2) (((x1) + (x2) + 1) >> 1)
+
+#define SubPixelArea(x1, y1, x2, y2, bottom) \
+(xFixed_1_31) ( \
+ AREA_MULT((x1), (y1)) \
+ + AREA_MULT(WIDTH_AVG((x1), (x2)), (y2) - (y1))\
+ + AREA_MULT((x2), (bottom) - (y2)) \
+)
+
+/*
+static xFixed_1_31
+SubPixelArea (xFixed_1_16 x1,
+ xFixed_1_16 y1,
+ xFixed_1_16 x2,
+ xFixed_1_16 y2,
+ xFixed_1_16 bottom)
+{
+ xFixed_1_16 x_trap;
+ xFixed_1_16 h_top, h_trap, h_bot;
+ xFixed_1_31 area;
+
+ x_trap = WIDTH_AVG(x1,x2);
+ h_top = y1;
+ h_trap = (y2 - y1);
+ h_bot = (bottom - y2);
+
+ area = AREA_MULT(x1, h_top) +
+ AREA_MULT(x_trap, h_trap) +
+ AREA_MULT(x2, h_bot);
+
+ return area;
+}
+*/
+
+#define SubPixelAlpha(x1, y1, x2, y2, bottom, depth) \
+( \
+ AreaAlpha( \
+ SubPixelArea((x1), (y1), (x2), (y2), (bottom)), \
+ (depth) \
+ ) \
+)
+
+/*
+static int
+SubPixelAlpha (xFixed_1_16 x1,
+ xFixed_1_16 y1,
+ xFixed_1_16 x2,
+ xFixed_1_16 y2,
+ xFixed_1_16 bottom,
+ int depth)
+{
+ xFixed_1_31 area;
+
+ area = SubPixelArea(x1, y1, x2, y2, bottom);
+
+ return AreaAlpha(area, depth);
+}
+*/
+
+/* Alpha of a pixel above a given horizontal line */
+#define AlphaAbove(pixel_y, line_y, depth) \
+( \
+ AreaAlpha(AREA_MULT((line_y) - (pixel_y), xFixed1), depth) \
+)
+
+static int
+RectAlpha(xFixed pixel_y, xFixed top, xFixed bottom, int depth)
+{
+ if (depth == 1)
+ return top == pixel_y ? 1 : 0;
+ else
+ return (AlphaAbove (pixel_y, bottom, depth) -
+ AlphaAbove (pixel_y, top, depth));
+}
+
+
+/*
+ * Pixel coverage from the left edge bounded by one horizontal lines,
+ * (top and bottom), as well as one PixelWalk line.
+ */
+static int
+AlphaAboveLeft(RationalPoint *upper,
+ RationalPoint *lower,
+ xFixed bottom,
+ xFixed pixel_x,
+ xFixed pixel_y,
+ int depth)
+{
+ return SubPixelAlpha(upper->x - pixel_x,
+ upper->y - pixel_y,
+ lower->x - pixel_x,
+ lower->y - pixel_y,
+ bottom - pixel_y,
+ depth);
+}
+
+/*
+ Pixel coverage from the left edge bounded by two horizontal lines,
+ (top and bottom), as well as one line two points, p1 and p2, which
+ intersect the pixel. The following condition must be true:
+
+ p2.y > p1.y
+*/
+
+/*
+ lr
+ |\
+ +--|-\-------+
+ | a| b\ |
+ =======|===\========== top
+ | c| d \ |
+ =======|=====\======== bot
+ | | \ |
+ +--|-------\-+
+
+ alpha(d) = alpha(cd) - alpha(c) = alpha(abcd) - alpha(ab) - (alpha(ac) - alpha(c))
+
+ alpha(d) = pixelalpha(top, bot, right) - pixelalpha(top, bot, left)
+
+ pixelalpha(top, bot, line) = subpixelalpha(bot, line) - subpixelalpha(top, line)
+*/
+
+static int
+PixelAlpha(xFixed pixel_x,
+ xFixed pixel_y,
+ xFixed top,
+ xFixed bottom,
+ PixelWalk *pw,
+ int depth)
+{
+ int alpha;
+
+#ifdef DEBUG
+ fprintf(stderr, "alpha (%f, %f) - (%f, %f) = ",
+ (double) pw->p1.x / (1 << 16),
+ (double) pw->p1.y / (1 << 16),
+ (double) pw->p2.x / (1 << 16),
+ (double) pw->p2.y / (1 << 16));
+ fflush(stderr);
+#endif
+
+ /*
+ * Sharp polygons are different, alpha is 1 if the
+ * area includes the pixel origin, else zero, in
+ * the above figure, only 'a' has alpha 1
+ */
+ if (depth == 1)
+ {
+ alpha = 0;
+ if (top == pixel_y && pw->p_pixel_top.x != pixel_x)
+ alpha = 1;
+ }
+ else
+ {
+ alpha = (AlphaAboveLeft(&pw->p_pixel_top, &pw->p_trap_bottom,
+ bottom, pixel_x, pixel_y, depth)
+ - AlphaAboveLeft(&pw->p_pixel_top, &pw->p_trap_top,
+ top, pixel_x, pixel_y, depth));
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "0x%x => %f\n",
+ alpha,
+ (double) alpha / ((1 << depth) -1 ));
+ fflush(stderr);
+#endif
+
+ return alpha;
+}
+
+#define INCREMENT_X_AND_PIXEL \
+{ \
+ pixel_x += xFixed1; \
+ (*mask.over) (&mask); \
+}
+
+/* XXX: What do we really want this prototype to look like? Do we want
+ separate versions for 1, 4, 8, and 16-bit alpha? */
+
+#define saturateAdd(t, a, b) (((t) = (a) + (b)), \
+ ((CARD8) ((t) | (0 - ((t) >> 8)))))
+
+#define addAlpha(mask, depth, alpha, temp) (\
+ (*(mask)->store) ((mask), (alpha == (1 << depth) - 1) ? \
+ 0xff000000 : \
+ (saturateAdd (temp, \
+ alpha << (8 - depth), \
+ (*(mask)->fetch) (mask) >> 24) << 24)) \
+)
+
+void
+fbRasterizeTrapezoid (PicturePtr pMask,
+ xTrapezoid *pTrap,
+ int x_off,
+ int y_off)
+{
+ xTrapezoid trap = *pTrap;
+ int alpha, temp;
+
+ FbCompositeOperand mask;
+
+ int depth = pMask->pDrawable->depth;
+ int max_alpha = (1 << depth) - 1;
+ int buf_width = pMask->pDrawable->width;
+
+ xFixed x_off_fixed = IntToxFixed(x_off);
+ xFixed y_off_fixed = IntToxFixed(y_off);
+ xFixed buf_width_fixed = IntToxFixed(buf_width);
+
+ PixelWalk left, right;
+ xFixed pixel_x, pixel_y;
+ xFixed first_right_x;
+ xFixed y, y_next;
+
+ /* trap.left and trap.right must be non-horizontal */
+ if (trap.left.p1.y == trap.left.p2.y
+ || trap.right.p1.y == trap.right.p2.y) {
+ return;
+ }
+
+ trap.top += y_off_fixed;
+ trap.bottom += y_off_fixed;
+ trap.left.p1.x += x_off_fixed;
+ trap.left.p1.y += y_off_fixed;
+ trap.left.p2.x += x_off_fixed;
+ trap.left.p2.y += y_off_fixed;
+ trap.right.p1.x += x_off_fixed;
+ trap.right.p1.y += y_off_fixed;
+ trap.right.p2.x += x_off_fixed;
+ trap.right.p2.y += y_off_fixed;
+
+#ifdef DEBUG
+ fprintf(stderr, "(top, bottom) = (%f, %f)\n",
+ (double) trap.top / (1 << 16),
+ (double) trap.bottom / (1 << 16));
+#endif
+
+ pixelWalkInit(&left, &trap.left, trap.top, trap.bottom);
+ pixelWalkInit(&right, &trap.right, trap.top, trap.bottom);
+
+ /* XXX: I'd still like to optimize this loop for top and
+ bottom. Only the first row intersects top and only the last
+ row, (which could also be the first row), intersects bottom. So
+ we could eliminate some unnecessary calculations from all other
+ rows. Unfortunately, I haven't found an easy way to do it
+ without bloating the text, (eg. unrolling a couple iterations
+ of the loop). So, for sake of maintenance, I'm putting off this
+ optimization at least until this code is more stable.. */
+
+ if (!fbBuildCompositeOperand (pMask, &mask, 0, xFixedToInt (trap.top), FALSE, FALSE))
+ return;
+
+ for (y = trap.top; y < trap.bottom; y = y_next)
+ {
+ pixel_y = xFixedFloor (y);
+ y_next = pixel_y + xFixed1;
+ if (y_next > trap.bottom)
+ y_next = trap.bottom;
+
+ ASSERT (left.row.top.y == y);
+ ASSERT (left.row.bottom.y == y_next);
+ ASSERT (right.row.top.y == y);
+ ASSERT (right.row.bottom.y == y_next);
+
+ pixel_x = xFixedFloor(left.col.left.x);
+
+ /*
+ * Walk pixels on this row that are left of the
+ * first possibly lit pixel
+ *
+ * pixelWalkNextPixel will change .row.top.y
+ * when the last pixel covered by the edge
+ * is passed
+ */
+
+ first_right_x = xFixedFloor(right.col.left.x);
+ while (right.row.top.y == y && first_right_x < pixel_x)
+ {
+ /* these are empty */
+ pixelWalkNextPixel (&right);
+ /* step over */
+ first_right_x += xFixed1;
+ }
+
+ (*mask.set) (&mask, xFixedToInt (pixel_x), xFixedToInt (y));
+
+ /*
+ * Walk pixels on this row intersected by only trap.left
+ *
+ */
+ while (left.row.top.y == y && pixel_x < first_right_x)
+ {
+ alpha = (RectAlpha (pixel_y, y, y_next, depth)
+ - PixelAlpha(pixel_x, pixel_y, y, y_next, &left, depth));
+
+ if (alpha > 0)
+ {
+ if (0 <= pixel_x && pixel_x < buf_width_fixed)
+ addAlpha (&mask, depth, alpha, temp);
+ }
+
+ /*
+ * Step right
+ */
+ pixelWalkNextPixel(&left);
+ INCREMENT_X_AND_PIXEL;
+ }
+
+ /*
+ * Either pixels are covered by both edges or
+ * there are fully covered pixels on this row
+ */
+ if (pixel_x == first_right_x)
+ {
+ /*
+ * Now walk the pixels on this row intersected
+ * by both edges
+ */
+ while (left.row.top.y == y && right.row.top.y == y)
+ {
+ alpha = (PixelAlpha(pixel_x, pixel_y, y, y_next, &right, depth)
+ - PixelAlpha(pixel_x, pixel_y, y, y_next, &left, depth));
+ if (alpha > 0)
+ {
+ ASSERT (0 <= alpha && alpha <= max_alpha);
+ if (0 <= pixel_x && pixel_x < buf_width_fixed)
+ addAlpha (&mask, depth, alpha, temp);
+ }
+ pixelWalkNextPixel(&left);
+ pixelWalkNextPixel(&right);
+ INCREMENT_X_AND_PIXEL;
+ }
+ /*
+ * If the right edge is now left of the left edge,
+ * the left edge will end up only partially walked,
+ * walk it the rest of the way
+ */
+ while (left.row.top.y == y)
+ pixelWalkNextPixel(&left);
+ }
+ else
+ {
+ /*
+ * Fully covered pixels simply saturate
+ */
+ alpha = RectAlpha (pixel_y, y, y_next, depth);
+ if (alpha == max_alpha)
+ {
+ while (pixel_x < first_right_x)
+ {
+ if (0 <= pixel_x && pixel_x < buf_width_fixed)
+ (*mask.store) (&mask, 0xff000000);
+ INCREMENT_X_AND_PIXEL;
+ }
+ }
+ else
+ {
+ while (pixel_x < first_right_x)
+ {
+ ASSERT (0 <= alpha && alpha <= max_alpha);
+ if (0 <= pixel_x && pixel_x < buf_width_fixed)
+ addAlpha (&mask, depth, alpha, temp);
+ INCREMENT_X_AND_PIXEL;
+ }
+ }
+ }
+
+ /*
+ * Finally, pixels intersected only by trap.right
+ */
+ while (right.row.top.y == y)
+ {
+ alpha = PixelAlpha(pixel_x, pixel_y, y, y_next, &right, depth);
+ if (alpha > 0)
+ {
+ if (0 <= pixel_x && pixel_x < buf_width_fixed)
+ addAlpha (&mask, depth, alpha, temp);
+ }
+ pixelWalkNextPixel(&right);
+ INCREMENT_X_AND_PIXEL;
+ }
+ }
+}
+
+/* Some notes on walking while keeping track of errors in both dimensions:
+
+That's really pretty easy. Your bresenham should be walking sub-pixel
+coordinates rather than pixel coordinates. Now you can calculate the
+sub-pixel Y coordinate for any arbitrary sub-pixel X coordinate (or vice
+versa).
+
+ ey: y error term (distance from current Y sub-pixel to line) * dx
+ ex: x error term (distance from current X sub-pixel to line) * dy
+ dx: difference of X coordinates for line endpoints
+ dy: difference of Y coordinates for line endpoints
+ x: current fixed-point X coordinate
+ y: current fixed-point Y coordinate
+
+One of ey or ex will always be zero, depending on whether the distance to
+the line was measured horizontally or vertically.
+
+In moving from x, y to x1, y1:
+
+ (x1 + e1x/dy) - (x + ex/dy) dx
+ --------------------------- = --
+ (y1 + e1y/dx) - (y + ey/dx) dy
+
+ (x1dy + e1x) - (xdy + ex) = (y1dx + e1y) - (ydx + ey)
+
+ dy(x1 - x) + (e1x - ex) = dx(y1-y) + (e1y - ey)
+
+So, if you know y1 and want to know x1:
+
+ Set e1y to zero and compute the error from x:
+
+ oex = dx(y1 - y) - ey + ex
+
+ Compute the number of whole pixels to get close to the line:
+
+ wx = oex / dy
+
+ Set x1:
+
+ Now compute the e1x:
+
+ e1x = oex - wx * dy
+
+A similar operation moves to a known y1. Note that this computation (in
+general) requires 64 bit arithmetic. I suggest just using the available
+64 bit datatype for now, we can optimize the common cases with a few
+conditionals. There's some cpp code in fb/fb.h that selects a 64 bit type
+for machines that XFree86 builds on; there aren't any machines missing a
+64 bit datatype that I know of.
+*/
+
+/* Here's a large-step Bresenham for jogging my memory.
+
+void large_bresenham_x_major(x1, y1, x2, y2, x_inc)
+{
+ int x, y, dx, dy, m;
+ int em_dx, ey_dx;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+
+ m = (x_inc * dy) / dx;
+ em_dx = (x_inc * dy) - m * dx;
+
+ x = x1;
+ y = y1;
+ ey = 0;
+
+ set(x,y);
+
+ while (x < x2) {
+ x += x_inc;
+ y += m;
+ ey_dx += em_dx;
+ if (ey_dx > dx_2) {
+ y++;
+ ey_dx -= dx;
+ }
+ set(x,y);
+ }
+}
+
+*/
+
+/* Here are the latest, simplified equations for computing trapezoid
+ coverage of a pixel:
+
+ alpha_from_area(A) = round(2**depth-1 * A)
+
+ alpha(o) = 2**depth-1
+
+ alpha(a) = alpha_from_area(area(a))
+
+ alpha(ab) = alpha_from_area(area(ab))
+
+ alpha(b) = alpha(ab) - alpha (a)
+
+ alpha(abc) = alpha_from_area(area(abc))
+
+ alpha(c) = alpha(abc) - alpha(ab)
+
+ alpha(ad) = alpha_from_area(area(ad))
+
+ alpha (d) = alpha(ad) - alpha (a)
+
+ alpha (abde) = alpha_from_area(area(abde))
+
+ alpha (de) = alpha (abde) - alpha (ab)
+
+ alpha (e) = alpha (de) - alpha (d)
+
+ alpha (abcdef) = alpha_from_area(area(abcdef))
+
+ alpha (def) = alpha (abcdef) - alpha (abc)
+
+ alpha (f) = alpha (def) - alpha (de)
+
+ alpha (adg) = alpha_from_area(area(adg))
+
+ alpha (g) = alpha (adg) - alpha (ad)
+
+ alpha (abdegh) = alpha_from_area(area(abdegh))
+
+ alpha (gh) = alpha (abdegh) - alpha (abde)
+
+ alpha (h) = alpha (gh) - alpha (g)
+
+ alpha (abcdefghi) = alpha_from_area(area(abcdefghi)) =
+ alpha_from_area(area(o)) = alpha_from_area(1) = alpha(o)
+
+ alpha (ghi) = alpha (abcdefghi) - alpha (abcdef)
+
+ alpha (i) = alpha (ghi) - alpha (gh)
+*/
+
+/* Latest thoughts from Keith on implementing area/alpha computations:
+
+*** 1.16 * 1.16 -> 1.31 ***
+#define AREA_MULT(w,h) ((w)&(h) == 0x10000 ? 0x80000000 : (((w)*(h) + 1) >> 1)
+
+*** (1.16 + 1.16) / 2 -> 1.16 ***
+#define WIDTH_AVG(x1,x2) (((x1) + (x2) + 1) >> 1)
+
+xFixed_1_31
+SubpixelArea (xFixed_1_16 x1,
+ xFixed_1_16 x2,
+ xFixed_1_16 y1,
+ xFixed_1_16 y2,
+ xFixed_1_16 bottom)
+ {
+ xFixed_1_16 x_trap;
+ xFixed_1_16 h_top, h_trap, h_bot;
+ xFixed_1_31 area;
+
+ x_trap = WIDTH_AVG(x1,x2);
+ h_top = y1;
+ h_trap = (y2 - y1);
+ h_bot = (bottom - y2);
+
+ area = AREA_MULT(x1, h_top) +
+ AREA_MULT(x_trap, h_trap) +
+ AREA_MULT(x2, h_bot);
+
+ return area;
+ }
+
+To convert this xFixed_1_31 value to alpha using 32 bit arithmetic:
+
+int
+AreaAlpha (xFixed_1_31 area, int depth)
+ {
+ return ((area >> bits) * ((1 << depth) - 1)) >> (31 - depth);
+ }
+
+Avoiding the branch bubble in the AREA_MULT could be done with either:
+
+area = (w * h + 1) >> 1;
+area |= ((area - 1) & 0x80000000);
+
+or
+ #define AREA_MULT(w,h) ((((w)*(h) + 1) >> 1) | ((w)&(h)&0x10000) << 15)
+
+depending on your preference, the first takes one less operation but
+can't be expressed as a macro; the second takes a large constant which may
+require an additional instruction on some processors. The differences
+will be swamped by the cost of the multiply.
+
+*/
+
+#endif /* RENDER */
diff --git a/xc/programs/Xserver/fb/module/Imakefile b/xc/programs/Xserver/fb/module/Imakefile
new file mode 100644
index 000000000..8ad64ec73
--- /dev/null
+++ b/xc/programs/Xserver/fb/module/Imakefile
@@ -0,0 +1,6 @@
+XCOMM $XFree86: xc/programs/Xserver/fb/module/Imakefile,v 1.1 2002/05/31 16:12:17 dawes Exp $
+
+#define IHaveModules
+#define LinkDirectory ..
+
+#include "../Imakefile"
diff --git a/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Credits.rtf b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Credits.rtf
new file mode 100644
index 000000000..cbf13779f
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Credits.rtf
@@ -0,0 +1,139 @@
+{\rtf1\mac\ansicpg10000\cocoartf100
+{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;\f2\fswiss\fcharset77 Helvetica-Oblique;
+}
+{\colortbl;\red255\green255\blue255;}
+\vieww5340\viewh4520\viewkind0
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\qc
+
+\f0\b\fs24 \cf0 Contribuidores do XonX ao XFree86 4.2.99.x:
+\f1\b0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+\cf0 Fabr\'92cio Luis de Castro
+\f0\b \
+
+\f2\i\b0 Localiza\'8d\'8bo para o Portugu\'90s\
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+
+\f0\i0\b \cf0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\qc
+\cf0 Contribuidores do XonX ao XFree86 4.2:
+\f1\b0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+\cf0 Rob Braun\
+
+\f2\i Suporte para o Darwin x86\
+
+\f1\i0 Pablo Di Noto\
+
+\f2\i Localiza\'8d\'8bo para o Espanhol
+\f1\i0 \
+Paul Edens\
+
+\f2\i Localiza\'8d\'8bo para o Holand\'90s
+\f1\i0 \
+Kyunghwan Kim\
+
+\f2\i Localiza\'8d\'8bo para o Coreano
+\f1\i0 \
+Mario Klebsch\
+
+\f2\i Suporte para teclados Non-US
+\f1\i0 \
+Torrey T. Lyons\
+
+\f2\i L\'92der de Projeto
+\f1\i0 \
+Andreas Monitzer\
+
+\f2\i Localiza\'8d\'8bo para o Alem\'8bo
+\f1\i0 \
+Patrik Montgomery\
+
+\f2\i Localiza\'8d\'8bo para o Sueco
+\f1\i0 \
+Greg Parker\
+
+\f2\i Suporte ao modo Compartilhado (Rootless)
+\f1\i0 \
+Toshimitsu Tanaka\
+
+\f2\i Localiza\'8d\'8bo para o Japon\'90s
+\f1\i0 \
+Olivier Verdier\
+
+\f2\i Localiza\'8d\'8bo para o Fran\'8d\'90s
+\f1\i0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+
+\f0\b \cf0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\qc
+\cf0 Agradecimentos Especiais:
+\f1\b0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+\cf0 Devin Poolman and Zero G Software, Inc.\
+
+\f2\i Instalador
+\f1\i0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+
+\f0\b \cf0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\qc
+\cf0 Membros do Time XonX\
+Contribuindo com o XFree86 4.1:
+\f1\b0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+\cf0 Rob Braun\
+
+\f2\i Suporte ao Darwin x86\
+
+\f1\i0 Torrey T. Lyons\
+
+\f2\i L\'92der de Projeto
+\f1\i0 \
+Andreas Monitzer\
+
+\f2\i Vers\'8bo Cocoa da interface XDarwin
+\f1\i0 \
+Greg Parker\
+
+\f2\i Implementa\'8d\'8bo Original
+\f1\i0
+\f2\i ao Quartz \
+
+\f1\i0 Christoph Pfisterer\
+
+\f2\i Bibliotecas Din\'89micas Compartilhadas
+\f1\i0 \
+Toshimitsu Tanaka\
+
+\f2\i Localiza\'8d\'8bo para o Japon\'90s
+\f1\i0 \
+\
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\qc
+
+\f0\b \cf0 Agradecimento Especial:
+\f1\b0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+\cf0 Tiago Ribeiro\
+
+\f2\i \'eacone do XDarwin
+\f1\i0 \
+\
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\qc
+
+\f0\b \cf0 Hist\'97rico:
+\f1\b0 \
+\pard\tx1440\tx2880\tx4320\tx5760\tx7200\ql\qnatural
+\cf0 John Carmack\
+
+\f2\i Suporte Original do XFree86 no Mac OS X Server
+\f1\i0 \
+Dave Zarzycki\
+
+\f2\i Suporte ao
+\f1\i0
+\f2\i XFree86 4.0 no Darwin 1.0
+\f1\i0 \
+Torrey T. Lyons\
+
+\f2\i Integra\'8d\'8bo dentro do Projeto XFree86 na vers\'8bo 4.0.2} \ No newline at end of file
diff --git a/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Imakefile b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Imakefile
new file mode 100644
index 000000000..89a73d682
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Imakefile
@@ -0,0 +1,25 @@
+XCOMM $XFree86: xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Imakefile,v 1.2 2002/07/17 01:24:58 torrey Exp $
+
+#include <Server.tmpl>
+
+LinkSourceFile(InfoPlist.strings.cpp,../English.lproj)
+
+INCLUDES = -I$(SERVERSRC)/include
+
+VERS = XFree86VersionString
+DATE = XFree86DateString
+XF86_DEFS = $(INCLUDES) -DXF86_VERSION=$(VERS) -DXF86_REL_DATE=$(DATE)
+
+AllTarget(XDarwinHelp.html)
+CppFileTarget(XDarwinHelp.html,XDarwinHelp.html.cpp,$(XF86_DEFS), \
+ NullParameter)
+
+AllTarget(InfoPlist.strings)
+InfoPlist.strings: InfoPlist.strings.cpp
+ RemoveFile($@)
+ ClearmakeOSName \
+ $(CPP) CppNoLineInfoOption $(XF86_DEFS) <InfoPlist.strings.cpp | \
+ CppSedMagic | sed 's/__quote__/"/g' >$@
+
+clean::
+ RemoveFiles(InfoPlist.strings)
diff --git a/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Localizable.strings b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Localizable.strings
new file mode 100644
index 000000000..b3edbb41d
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/Localizable.strings
Binary files differ
diff --git a/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/classes.nib b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/classes.nib
new file mode 100644
index 000000000..ba1e3a206
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/classes.nib
@@ -0,0 +1,64 @@
+{
+ IBClasses = (
+ {
+ ACTIONS = {showHelp = id; };
+ CLASS = FirstResponder;
+ LANGUAGE = ObjC;
+ SUPERCLASS = NSObject;
+ },
+ {
+ ACTIONS = {close = id; pickFile = id; saveChanges = id; setKey = id; };
+ CLASS = Preferences;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ addToPathButton = id;
+ addToPathField = id;
+ button2ModifiersMatrix = id;
+ button3ModifiersMatrix = id;
+ depthButton = id;
+ displayField = id;
+ dockSwitchButton = id;
+ fakeButton = id;
+ keymapFileField = id;
+ modeMatrix = id;
+ modeWindowButton = id;
+ mouseAccelChangeButton = id;
+ startupHelpButton = id;
+ switchKeyButton = id;
+ systemBeepButton = id;
+ useDefaultShellMatrix = id;
+ useOtherShellField = id;
+ useXineramaButton = id;
+ window = id;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {
+ CLASS = XApplication;
+ LANGUAGE = ObjC;
+ OUTLETS = {preferences = id; xserver = id; };
+ SUPERCLASS = NSApplication;
+ },
+ {
+ ACTIONS = {
+ closeHelpAndShow = id;
+ showAction = id;
+ startFullScreen = id;
+ startRootless = id;
+ };
+ CLASS = XServer;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ helpWindow = NSWindow;
+ modeWindow = NSWindow;
+ startFullScreenButton = NSButton;
+ startRootlessButton = NSButton;
+ startupHelpButton = NSButton;
+ startupModeButton = NSButton;
+ switchWindow = NSPanel;
+ };
+ SUPERCLASS = NSObject;
+ }
+ );
+ IBVersion = 1;
+} \ No newline at end of file
diff --git a/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/objects.nib b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/objects.nib
new file mode 100644
index 000000000..4b7736a12
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/MainMenu.nib/objects.nib
Binary files differ
diff --git a/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/XDarwinHelp.html.cpp b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/XDarwinHelp.html.cpp
new file mode 100644
index 000000000..37502eac6
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/XDarwinHelp.html.cpp
@@ -0,0 +1,216 @@
+<!-- $XFree86: xc/programs/Xserver/hw/darwin/bundle/Portuguese.lproj/XDarwinHelp.html.cpp,v 1.1 2002/01/25 06:46:46 torrey Exp $ --><html><body>
+
+#include "xf86Version.h"
+#ifndef PRE_RELEASE
+#define PRE_RELEASE XF86_VERSION_SNAP
+#endif
+
+
+<head>
+<title>XFree86 para Mac OS X</title>
+</head>
+
+<center>
+
+ <h1>XFree86 para Darwin e Mac OS X</h1>
+ XFree86 XF86_VERSION<br>
+ Release Date: XF86_REL_DATE
+</center>
+<h2>&Iacute;ndice</h2>
+<ol>
+ <li><A HREF="#notice">Notas importantes</A></li>
+ <li><A HREF="#usage">Uso</A></li>
+ <li><A HREF="#path">Ajustando seu Path</A></li>
+
+ <li><A HREF="#prefs">Prefer&ecirc;ncias do usu&aacute;rio</A></li>
+ <li><A HREF="#license">Licen&ccedil;a</A></li>
+</ol>
+<center>
+ <h2><a NAME="notice">Notas importantes</a></h2>
+</center>
+<blockquote> #if PRE_RELEASE Essa &eacute; uma vers&atilde;o pr&eacute;-lancamento
+ do XFree86, e ela n&atilde;o &eacute; suportada de nenhuma forma. Bugs podem
+ ser reportados e corre&ccedil;&otilde;es podem ser enviadas para <A HREF="http://sourceforge.net/projects/xonx/">P&aacute;gina
+ do projeto XonX</A> no SourceForge. Antes de informar bugs em vers&otilde;es
+ pr&eacute;-lancamento, por favor verifique a þltima vers&atilde;o em <A HREF="http://sourceforge.net/projects/xonx/">XonX</A>
+ or no <A HREF="http://www.XFree86.Org/cvs">Reposit&oacute;rio CVS do XFree86</A>.
+ #else Se o servidor &eacute; mais velho que 6-12 semanas, ou seu hardware &eacute;
+ mais novo que a data acima, procure por uma nova vers&atilde;o antes de informar
+ problemas. Bugs podem ser reportados e corre&ccedil;&otilde;es podem ser enviadas
+ para a <A HREF="http://sourceforge.net/projects/xonx/">P&aacute;gina do projeto
+ XonX</A> na SourceForge. #endif </blockquote>
+<blockquote> Este software &eacute; distribu&iacute;do sob os termos da <a href="#license">licen&ccedil;a
+ MIT X11 / X Consortium</a> e &eacute; provido, sem nenhuma garantia. Por favor
+ leia a <a href="#license">Licen&ccedil;a</a> antes de come&ccedil;ar a usar
+ o programa.</blockquote>
+
+<h2><a NAME="usage">Uso</a></h2>
+<p>O XFree86 &eacute; uma aplica&ccedil;&atilde;o &quot;open-source&quot; livremente
+ redistribu&iacute;da do <a HREF
+="http://www.x.org/">Sistema X Window</a> produzido pelo <a HREF="http://www.XFree86.Org/">XFree86
+ Project, Inc.</a> O servidor X window para o Darwin e Mac OS X provido pelo
+ XFree86 &eacute; chamado XDarwin. XDarwin roda sobre Mac OS X no modo Tela Cheia
+ ou no modo Compartilhado.</p>
+<p>No modo Tela Cheia, quando o sistema X window est&aacute; ativo, ele ocupa
+ a tela toda. Voc&ecirc; pode voltar ao desktop do Mac OS X clicando Command-Option-A.
+ Essa combina&ccedil;&atilde;o de teclas pode ser mudada nas prefer&ecirc;ncias.
+ Pelo desktop Mac OS X, clique no &iacute;cone XDarwin no Dock para voltar ao
+ sistema X window. (Voc&ecirc; pode mudar esse comportamento nas prefer&ecirc;ncias
+ da&iacute; voc&ecirc; dever&aacute; clicar no &iacute;cone XDarwin na janela
+ flutuante que aparecer&aacute;.)</p>
+<p>No modo Compartilhado, o sistema X window e Aqua dividem a mesma tela. A janela
+ raiz da tela X11 est&aacute; do tamanho da tela (monitor) e cont&eacute;m todas
+ as outras janelas. A janela raiz do X11 no modo compartilhado n&atilde;o &eacute;
+ mostrada pois o Aqua controla o fundo de tela.</p>
+<h3>Emula&ccedil;&atilde;o de Mouse Multi-Bot&otilde;es</h3>
+<p>Muitas aplica&ccedil;&otilde;es X11 insistem em usar um mouse de 3 bot&otilde;es.
+ Voc&ecirc; pode emular um mouse de 3 bot&otilde;es com um simples bot&atilde;o,
+ mantendo pressionando teclas modificadoras enquanto voc&ecirc; clica no bot&atilde;o
+ do mouse. Isto &eacute; controlado pela configura&ccedil;&atilde;o da &quot;Emula&ccedil;&atilde;o
+ de Mouse Multi-Bot&otilde;es&quot; da prefer&ecirc;ncia &quot;Geral&quot;. Por
+ padr&atilde;o, a emula&ccedil;&atilde;o est&aacute; habilitada e mantendo pressionada
+ a tecla Command e clicando no bot&atilde;o do mouse ele simular&aacute; o clique
+ no segundo bot&atilde;o do mouse. Mantendo pressionada a tecla Option e clicando
+ no bot&atilde;o do mouse ele simular&aacute; o terceiro bot&atilde;o. Voc&ecirc;
+ pode mudar a combina&ccedil;&atilde;o de teclas modificadoras para emular os
+ bot&otilde;es dois e tr&ecirc;s nas prefer&ecirc;ncias. Nota, se a tecla modificadora
+ foi mapeada para alguma outra tecla no xmodmap, voc&ecirc; ainda ter&aacute;
+ que usar a tecla atual especificada nas prefer&ecirc;ncias para a emula&ccedil;&atilde;o
+ do mouse multi-bot&otilde;es.</p>
+<h2><a NAME="path">Ajustando seu Path</a></h2>
+<p>Seu path &eacute; a lista de diret&oacute;rios a serem procurados por arquivos
+ execut&aacute;veis. O comando X11 est&aacute; localizado em <code>/usr/X11R6/bin</code>,
+ que precisa ser adicionado ao seu path. XDarwin faz isso para voc&ecirc; por
+ padr&atilde;o e pode-se tamb&eacute;m adicionar diret&oacute;rios onde voc&ecirc;
+ instalou aplica&ccedil;&otilde;es de linha de comando.</p>
+<p>Usu&aacute;rios experientes j&aacute; ter&atilde;o configurado corretamente
+ seu path usando arquivos de inicializa&ccedil;&atilde;o de seu shell. Neste
+ caso, voc&ecirc; pode informar o XDarwin para n&atilde;o modificar seu path
+ nas prefer&ecirc;ncias. O XDarwin inicia o cliente inicial X11 no shell padr&atilde;o
+ do usu&aacute;rio corrente. (Um shell alternativo pode ser tamb&eacute;m expecificado
+ nas prefer&ecirc;ncias.) O modo para ajustar o path depende do shell que voc&ecirc;
+ est&aacute; usando. Isto &eacute; descrito na man page do seu shell.</p>
+<p>Voc&ecirc; pode tamb&eacute;m querer adicionar as man pages do XFree86 para
+ a lista de p&aacute;ginas a serem procuradas quando voc&ecirc; est&aacute; procurando
+ por documenta&ccedil;&atilde;o. As man pages do X11 est&atilde;o localizadas
+ em <code>/usr/X11R6/man</code> e a vari&aacute;vel de ambiente <code>MANPATH</code>
+ cont&eacute;m a lista de diret&oacute;rios a buscar.</p>
+<h2><a NAME="prefs">Prefer&ecirc;ncias do Usu&aacute;rio</a></h2>
+<p>V&aacute;rias op&ccedil;&otilde;es podem ser ajustadas nas prefer&ecirc;ncias
+ do usu&aacute;rio, acess&iacute;vel pelo item &quot;Prefer&ecirc;ncias...&quot;
+ no menu &quot;XDarwin&quot;. As op&ccedil;&otilde;es listadas como op&ccedil;&otilde;es
+ de inicializa&ccedil;&atilde;o, n&atilde;o ter&atilde;o efeito at&eacute; voc&ecirc;
+ reiniciar o XDarwin. Todas as outras op&ccedil;&otilde;es ter&atilde;o efeito
+ imediatamente. V&aacute;rias das op&ccedil;&otilde;es est&atilde;o descritas
+ abaixo:</p>
+<h3>Geral</h3>
+<ul>
+ <li><b>Usar o Beep do Sistema para o X11: </b>Quando habilitado som de alerta
+ padr&atilde;o do Mac OS X ser&aacute; usado como alerta no X11. Quando desabilitado
+ (padr&atilde;o) um tom simples ser&aacute; usado.</li>
+ <li><b>Permitir o X11 mudar a acelera&ccedil;&atilde;o do mouse: </b>Por implementa&ccedil;&atilde;o
+ padr&atilde;o no sistema X window, o gerenciador de janelas pode mudar a acelera&ccedil;&atilde;o
+ do mouse. Isso pode gerar uma confus&atilde;o pois a acelera&ccedil;&atilde;o
+ do mouse pode ser ajustada diferentemente nas prefer&ecirc;ncias do Mac OS
+ X e nas prefer&ecirc;ncias do X window. Por padr&atilde;o, o X11 n&atilde;o
+ est&aacute; habilitado a mudar a acelera&ccedil;&atilde;o do mouse para evitar
+ este problema.</li>
+ <li><b>Emula&ccedil;&atilde;o de Mouse de Multi-Bot&otilde;es: </b>Esta op&ccedil;&atilde;o
+ est&aacute; escrita acima em <a href="#usage">Uso</a>. Quando a emula&ccedil;&atilde;o
+ est&aacute; habilitada as teclas modificadoras selecionadas tem que estar
+ pressionadas quando o bot&atilde;o do mouse for pressionado, para emular o
+ segundo e terceiro bot&otilde;es.</li>
+</ul>
+<h3>Inicial</h3>
+<ul>
+ <li><b>Modo Padr&atilde;o: </b>Se o usu&aacute;rio n&atilde;o indicar qual modo
+ de exibi&ccedil;&atilde;o quer usar (Tela Cheia ou Compartilhado) o modo especificado
+ aqui ser&aacute; usado .</li>
+ <li><b>Mostrar o painel de escolha na inicializa&ccedil;&atilde;o: </b> Por
+ padr&atilde;o, uma painel &eacute; mostrado quando o XDarwin &eacute;
+ iniciado para permitir que o usu&aacute;rio escolha ente o modo tela cheia
+ ou modo compartilhado. Se esta op&ccedil;&atilde;o estiver desligada, o modo
+ padr&atilde;o ser&aacute; inicializado automaticamente.</li>
+ <li><b>N&uacute;mero do Monitor X11: </b>O X11 permite ser administrado em multiplos
+ monitores por servidores X separados num mesmo computador. O usu&aacute;rio
+ pode indicar o n&uacute;mero do monitor para o XDarwin usar se mais de um
+ servidor X se estiver rodando simultaneamente.</li>
+ <li><b>Habilitar suporte a m&uacute;ltiplos monitores pelo Xinerama: </b>o XDarwin
+ suporta m&uacute;ltiplos monitores com o Xinerama, que trata todos os monitores
+ como parte de uma grande e retangular tela. Voc&ecirc; pode desabilitar o
+ Xinerama com est&aacute; op&ccedil;&atilde;o, mas normalmente o XDarwin n&atilde;o
+ controla m&uacute;ltiplos monitores corretamente sem est&aacute; op&ccedil;&atilde;o.
+ Se voc&ecirc; s&oacute; tiver um monotor, Xinerama &eacute; automaticamente
+ desabilitado. </li>
+ <li><b>Arquivo de Mapa de Teclado: </b> O mapa de teclado &eacute; lido na inicializa&ccedil;&atilde;o
+ e traduzido para um mapa de teclado X11. Arquivos de mapa de teclado, est&atilde;o
+ dispon&iacute;veis numa grande variedade de l&iacute;nguas e s&atilde;o encontradas
+ em <code>/System/Library/Keyboards</code>.</li>
+ <li><b>Iniciando Clientes X11 primeiro: </b>Quando o XDrawin &eacute; inicializado
+ pelo Finder, ele ir&aacute; rodar o <code>xinit</code> para abrir o controlador
+ X window e outros clientes X. (Veja o manual "<code>man xinit</code>" para
+ mais informa&ccedil;&otilde;es.) Antes do XDarwin rodar o <code>xinit</code>
+ ele ir&aacute; adicionar espec&iacute;ficos diret&oacute;rios a seu path.
+ Por padr&atilde;o somente o <code>/usr/X11R6/bin</code> &eacute; adicionado.
+ separado por um ponto-e-v&iacute;rgula. Os clientes X s&atilde;o inicializados
+ no shell padr&atilde;o do usu&aacute;rio e os arquivos de inicializa&ccedil;&atilde;o
+ do shell ser&atilde;o lidos. Se desejado, um shell alternativo pode ser especificado.</li>
+</ul>
+<h3>Tela Cheia</h3>
+<ul>
+ <li><b>Bot&atilde;o de Combina&ccedil;&atilde;o de Teclas: </b> Clique no bot&atilde;o
+ e pressione qualquer quantidade de teclas modificadoras seguidas por uma tecla
+ padr&atilde;o para modificar a combina&ccedil;&atilde;o quando se quer mudar
+ entre o Aqua e X11.</li>
+ <li><b>Clique no &Iacute;cone no Dock para mudar para o X11: </b>Habilitando
+ esta op&ccedil;&atilde;o voc&ecirc; ir&aacute; ativar a mudan&ccedil;a para
+ o X11 clicando no &iacute;cone do XDarwin no Dock. Em algumas vers&otilde;es
+ do Mac OS X, mudando pelo clique no Dock pode causar o desaparecimento do
+ cursor quando retornar ao Aqua.</li>
+ <li><b>Mostrar a Ajuda na inicializa&ccedil;&atilde;o: </b>Isto ir&aacute; mostrar
+ uma tela introdut&oacute;ria quando o XDarwin for inicializado no modo Tela
+ Cheia. </li>
+ <li><b>Profundidade de Cores em bits: </b> No modo Tela Cheia, a tela do X11
+ pode usar uma profundiadde de cor diferente da usada no Aqua. Se a op&ccedil;&atilde;o
+ &quot;Atual&quot; est&aacute; especificada, a profundidade usada pelo Aqua
+ quando o XDarwin iniciar ser&aacute; a mesma. Al&eacute;m das op&ccedil;&otilde;es
+ 8, 15 ou 24 bits que podem ser especificadas.</li>
+</ul>
+
+<h2><a NAME="license">Licen&ccedil;a</a></h2>
+<p>O projeto XFree86 &eacute; designado a prover e a ser livremente redistribu&iacute;do
+ as vers&otilde;es bin&aacute;rias e souce (c&oacute;digo-fonte). A licen&ccedil;a
+ principal n&oacute;s usamos uma baseada na licen&ccedil;a tradicional MIT X11
+ / X Consortium, que n&atilde;o imp&otilde;e nenhuma condi&ccedil;&atilde;o sobre
+ modifica&ccedil;&otilde;es ou redistribui&ccedil;&atilde;o do c&oacute;digo-fonte
+ ou dos bin&aacute;rios desde que o copyright/licen&ccedil;a sejam mantidos intactos.
+ Para mais informa&ccedil;&otilde;es e not&iacute;cias adicionais de copyright/licensing
+ em algumas se&ccedil;&atilde;o do c&oacute;digo, por favor visite a <a href="http://www.xfree86.org/legal/licence.html">p&aacute;gina
+ de licen&ccedil;as do XFree86</a>.</p>
+<H3><A NAME="3"></A>Licen&ccedil;a do X Consortium</H3>
+<p>Copyright (C) 1996 X Consortium</p>
+<p>Permiss&otilde;es s&atilde;o em virtude garantidas, livre de mudan&ccedil;as,
+ para qualquer pessoa que possua uma c&oacute;pia deste software e aos arquivos
+ de documenta&ccedil;&atilde;o associada (o &quot;Software&quot;), para lidar
+ com o software sem restri&ccedil;&otilde;es, incluindo limita&ccedil;&otilde;es
+ dos direitos de uso, c&oacute;pia, modifica&ccedil;&atilde;o, inclus&atilde;o,
+ publica&ccedil;&atilde;o, distribui&ccedil;&atilde;o, sub licen&ccedil;a, e/ou
+ venda de c&oacute;pias deste Software, e permitir pessoas to whom o Software
+ &eacute; fornecido para ser desta forma, verifique as seguintes condi&ccedil;&otilde;es:</p>
+<p>O nota de copyright abaixo e a permiss&atilde;o dever&atilde;o ser inclu&iacute;das
+ em todas as c&oacute;pias ou substanciais por&ccedil;&otilde;es do Software.</p>
+<p>O SOFTWARE 'E PROVIDO &quot;COMO TAL&quot;, SEM GARANTIAS DE NENHUM TIPO, EXPLICITA
+ OU IMPLICITA, INCLUINDO MAS N&Atilde;O LIMITADO NOS AVISOS DE COM&Eacute;RCIO,
+ TAMANHO OU PARA PROPOSTAS PARTICULARES E N&Atilde;O INFRA&Ccedil;&Atilde;O.
+ EM NENHUM ACONTECIMENTO O X CONSORTIUM SER&Aacute; RESPONSAV&Eacute;L POR NENHUMA
+ RECLAMA&Ccedil;&Atilde;O, DANOS OU OUTRAS RESPONSABILIDADES, SE NUMA A&Ccedil;&Atilde;O
+ DE CONTRATO, OU OUTRA COISA, SURGINDO DE, FORA DE OU EM CONEX&Atilde;O COM O
+ SOFTWARE OU O USO OU OUTRO MODO DE LIDAR COM O SOFTWARE.</p>
+<p>Exceto o contido nesta nota, o nome do X Consortium n&atilde;o pode ser usado
+ em propagandas ou outra forma de promo&ccedil;&atilde;o de vendas, uso ou outro
+ modo de lidar com este Software sem ter recebido uma autoriza&ccedil;&atilde;o
+ escrita pelo X Consortium.</p>
+<p>O Sistema X Window &eacute; marca registrada do X Consortium, Inc.</p>
+</body>
+</html>
+
diff --git a/xc/programs/Xserver/hw/darwin/darwinEvents.c b/xc/programs/Xserver/hw/darwin/darwinEvents.c
new file mode 100644
index 000000000..d0cd7880b
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/darwinEvents.c
@@ -0,0 +1,418 @@
+/*
+ * Darwin event queue and event handling
+ */
+/*
+Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+
+This file is based on mieq.c by Keith Packard,
+which contains the following copyright:
+Copyright 1990, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ */
+
+#define NEED_EVENTS
+#include "X.h"
+#include "Xmd.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "inputstr.h"
+#include "mi.h"
+#include "scrnintstr.h"
+#include "mipointer.h"
+
+#include "darwin.h"
+#include "quartz/quartz.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <IOKit/hidsystem/IOLLEvent.h>
+
+/* Fake button press/release for scroll wheel move. */
+#define SCROLLWHEELUPFAKE 4
+#define SCROLLWHEELDOWNFAKE 5
+
+#define QUEUE_SIZE 256
+
+typedef struct _Event {
+ xEvent event;
+ ScreenPtr pScreen;
+} EventRec, *EventPtr;
+
+typedef struct _EventQueue {
+ HWEventQueueType head, tail; /* long for SetInputCheck */
+ CARD32 lastEventTime; /* to avoid time running backwards */
+ Bool lastMotion;
+ EventRec events[QUEUE_SIZE]; /* static allocation for signals */
+ DevicePtr pKbd, pPtr; /* device pointer, to get funcs */
+ ScreenPtr pEnqueueScreen; /* screen events are being delivered to */
+ ScreenPtr pDequeueScreen; /* screen events are being dispatched to */
+} EventQueueRec, *EventQueuePtr;
+
+static EventQueueRec darwinEventQueue;
+
+
+/*
+ * DarwinPressModifierMask
+ * Press or release the given modifier key, specified by its mask.
+ */
+static void DarwinPressModifierMask(
+ xEvent *xe, // must already have type, time and mouse location
+ int mask) // one of NX_*MASK constants
+{
+ int key = DarwinModifierNXMaskToNXKey(mask);
+
+ if (key != -1) {
+ int keycode = DarwinModifierNXKeyToNXKeycode(key, 0);
+ if (keycode != 0) {
+ xe->u.u.detail = keycode + MIN_KEYCODE;
+ (*darwinEventQueue.pKbd->processInputProc)(xe,
+ (DeviceIntPtr)darwinEventQueue.pKbd, 1);
+ }
+ }
+}
+
+
+/*
+ * DarwinUpdateModifiers
+ * Send events to update the modifier state.
+ */
+static void DarwinUpdateModifiers(
+ xEvent *xe, // event template with time and mouse position set
+ int pressed, // KeyPress or KeyRelease
+ int flags ) // modifier flags that have changed
+{
+ xe->u.u.type = pressed;
+ if (flags & NX_ALPHASHIFTMASK) {
+ DarwinPressModifierMask(xe, NX_ALPHASHIFTMASK);
+ }
+ if (flags & NX_COMMANDMASK) {
+ DarwinPressModifierMask(xe, NX_COMMANDMASK);
+ }
+ if (flags & NX_CONTROLMASK) {
+ DarwinPressModifierMask(xe, NX_CONTROLMASK);
+ }
+ if (flags & NX_ALTERNATEMASK) {
+ DarwinPressModifierMask(xe, NX_ALTERNATEMASK);
+ }
+ if (flags & NX_SHIFTMASK) {
+ DarwinPressModifierMask(xe, NX_SHIFTMASK);
+ }
+ if (flags & NX_SECONDARYFNMASK) {
+ DarwinPressModifierMask(xe, NX_SECONDARYFNMASK);
+ }
+}
+
+
+/*
+ * DarwinSimulateMouseClick
+ * Send a mouse click to X when multiple mouse buttons are simulated
+ * with modifier-clicks, such as command-click for button 2. The dix
+ * layer is told that the previously pressed modifier key(s) are
+ * released, the simulated click event is sent. After the mouse button
+ * is released, the modifier keys are reverted to their actual state,
+ * which may or may not be pressed at that point. This is usually
+ * closest to what the user wants. Ie. the user typically wants to
+ * simulate a button 2 press instead of Command-button 2.
+ */
+static void DarwinSimulateMouseClick(
+ xEvent *xe, // event template with time and
+ // mouse position filled in
+ int whichButton, // mouse button to be pressed
+ int modifierMask) // modifiers used for the fake click
+{
+ // first fool X into forgetting about the keys
+ DarwinUpdateModifiers(xe, KeyRelease, modifierMask);
+
+ // push the mouse button
+ xe->u.u.type = ButtonPress;
+ xe->u.u.detail = whichButton;
+ (*darwinEventQueue.pPtr->processInputProc)
+ (xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+}
+
+
+Bool
+DarwinEQInit(
+ DevicePtr pKbd,
+ DevicePtr pPtr)
+{
+ darwinEventQueue.head = darwinEventQueue.tail = 0;
+ darwinEventQueue.lastEventTime = GetTimeInMillis ();
+ darwinEventQueue.pKbd = pKbd;
+ darwinEventQueue.pPtr = pPtr;
+ darwinEventQueue.pEnqueueScreen = screenInfo.screens[0];
+ darwinEventQueue.pDequeueScreen = darwinEventQueue.pEnqueueScreen;
+ SetInputCheck (&darwinEventQueue.head, &darwinEventQueue.tail);
+ return TRUE;
+}
+
+
+/*
+ * DarwinEQEnqueue
+ * Must be thread safe with ProcessInputEvents.
+ * DarwinEQEnqueue - called from event gathering thread
+ * ProcessInputEvents - called from X server thread
+ * DarwinEQEnqueue should never be called from more than one thread.
+ */
+void
+DarwinEQEnqueue(
+ const xEvent *e)
+{
+ HWEventQueueType oldtail, newtail;
+
+ oldtail = darwinEventQueue.tail;
+
+ // mieqEnqueue() collapses successive motion events into one event.
+ // This is difficult to do in a thread-safe way and rarely useful.
+
+ newtail = oldtail + 1;
+ if (newtail == QUEUE_SIZE)
+ newtail = 0;
+ /* Toss events which come in late */
+ if (newtail == darwinEventQueue.head)
+ return;
+
+ darwinEventQueue.events[oldtail].event = *e;
+ /*
+ * Make sure that event times don't go backwards - this
+ * is "unnecessary", but very useful
+ */
+ if (e->u.keyButtonPointer.time < darwinEventQueue.lastEventTime &&
+ darwinEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
+ {
+ darwinEventQueue.events[oldtail].event.u.keyButtonPointer.time =
+ darwinEventQueue.lastEventTime;
+ }
+ darwinEventQueue.events[oldtail].pScreen = darwinEventQueue.pEnqueueScreen;
+
+ // Update the tail after the event is prepared
+ darwinEventQueue.tail = newtail;
+}
+
+
+void
+DarwinEQSwitchScreen(
+ ScreenPtr pScreen,
+ Bool fromDIX)
+{
+ darwinEventQueue.pEnqueueScreen = pScreen;
+ if (fromDIX)
+ darwinEventQueue.pDequeueScreen = pScreen;
+}
+
+
+/*
+ * ProcessInputEvents
+ * Read and process events from the event queue until it is empty.
+ */
+void ProcessInputEvents(void)
+{
+ EventRec *e;
+ int x, y;
+ xEvent xe;
+ static int old_flags = 0; // last known modifier state
+ // button number and modifier mask of currently pressed fake button
+ static int darwinFakeMouseButtonDown = 0;
+ static int darwinFakeMouseButtonMask = 0;
+
+ // Empty the signaling pipe
+ x = sizeof(xe);
+ while (x == sizeof(xe)) {
+ x = read(darwinEventFD, &xe, sizeof(xe));
+ }
+
+ while (darwinEventQueue.head != darwinEventQueue.tail)
+ {
+ if (screenIsSaved == SCREEN_SAVER_ON)
+ SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
+
+ e = &darwinEventQueue.events[darwinEventQueue.head];
+ xe = e->event;
+
+ // Shift from global screen coordinates to coordinates relative to
+ // the origin of the current screen.
+ xe.u.keyButtonPointer.rootX -= darwinMainScreenX +
+ dixScreenOrigins[miPointerCurrentScreen()->myNum].x;
+ xe.u.keyButtonPointer.rootY -= darwinMainScreenY +
+ dixScreenOrigins[miPointerCurrentScreen()->myNum].y;
+
+ /*
+ * Assumption - screen switching can only occur on motion events
+ */
+ if (e->pScreen != darwinEventQueue.pDequeueScreen)
+ {
+ darwinEventQueue.pDequeueScreen = e->pScreen;
+ x = xe.u.keyButtonPointer.rootX;
+ y = xe.u.keyButtonPointer.rootY;
+ if (darwinEventQueue.head == QUEUE_SIZE - 1)
+ darwinEventQueue.head = 0;
+ else
+ ++darwinEventQueue.head;
+ NewCurrentScreen (darwinEventQueue.pDequeueScreen, x, y);
+ }
+ else
+ {
+ if (darwinEventQueue.head == QUEUE_SIZE - 1)
+ darwinEventQueue.head = 0;
+ else
+ ++darwinEventQueue.head;
+ switch (xe.u.u.type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ xe.u.u.detail += MIN_KEYCODE;
+ (*darwinEventQueue.pKbd->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pKbd, 1);
+ break;
+
+ case ButtonPress:
+ if (darwinFakeButtons && xe.u.u.detail == 1) {
+ // Mimic multi-button mouse with modifier-clicks
+ // If both sets of modifiers are pressed,
+ // button 2 is clicked.
+ if ((old_flags & darwinFakeMouse2Mask) ==
+ darwinFakeMouse2Mask)
+ {
+ DarwinSimulateMouseClick(&xe, 2, darwinFakeMouse2Mask);
+ darwinFakeMouseButtonDown = 2;
+ darwinFakeMouseButtonMask = darwinFakeMouse2Mask;
+ break;
+ }
+ else if ((old_flags & darwinFakeMouse3Mask) ==
+ darwinFakeMouse3Mask)
+ {
+ DarwinSimulateMouseClick(&xe, 3, darwinFakeMouse3Mask);
+ darwinFakeMouseButtonDown = 3;
+ darwinFakeMouseButtonMask = darwinFakeMouse3Mask;
+ break;
+ }
+ }
+ (*darwinEventQueue.pPtr->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+ break;
+
+ case ButtonRelease:
+ if (darwinFakeButtons && xe.u.u.detail == 1 &&
+ darwinFakeMouseButtonDown)
+ {
+ // If last mousedown was a fake click, don't check for
+ // mouse modifiers here. The user may have released the
+ // modifiers before the mouse button.
+ xe.u.u.detail = darwinFakeMouseButtonDown;
+ darwinFakeMouseButtonDown = 0;
+ (*darwinEventQueue.pPtr->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+
+ // Bring modifiers back up to date
+ DarwinUpdateModifiers(&xe, KeyPress,
+ darwinFakeMouseButtonMask & old_flags);
+ darwinFakeMouseButtonMask = 0;
+ } else {
+ (*darwinEventQueue.pPtr->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+ }
+ break;
+
+ case MotionNotify:
+ (*darwinEventQueue.pPtr->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+ break;
+
+ case kXDarwinUpdateModifiers:
+ {
+ // Update modifier state.
+ // Any amount of modifiers may have changed.
+ int flags = xe.u.clientMessage.u.l.longs0;
+ DarwinUpdateModifiers(&xe, KeyRelease,
+ old_flags & ~flags);
+ DarwinUpdateModifiers(&xe, KeyPress,
+ ~old_flags & flags);
+ old_flags = flags;
+ break;
+ }
+
+ case kXDarwinUpdateButtons:
+ {
+ long hwDelta = xe.u.clientMessage.u.l.longs0;
+ long hwButtons = xe.u.clientMessage.u.l.longs1;
+ int i;
+
+ for (i = 1; i < 5; i++) {
+ if (hwDelta & (1 << i)) {
+ // IOKit and X have different numbering for the
+ // middle and right mouse buttons.
+ if (i == 1) {
+ xe.u.u.detail = 3;
+ } else if (i == 2) {
+ xe.u.u.detail = 2;
+ } else {
+ xe.u.u.detail = i + 1;
+ }
+ if (hwButtons & (1 << i)) {
+ xe.u.u.type = ButtonPress;
+ } else {
+ xe.u.u.type = ButtonRelease;
+ }
+ (*darwinEventQueue.pPtr->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+ }
+ }
+ break;
+ }
+
+ case kXDarwinScrollWheel:
+ {
+ short count = xe.u.clientMessage.u.s.shorts0;
+
+ if (count > 0) {
+ xe.u.u.detail = SCROLLWHEELUPFAKE;
+ } else {
+ xe.u.u.detail = SCROLLWHEELDOWNFAKE;
+ count = -count;
+ }
+
+ for (; count; --count) {
+ xe.u.u.type = ButtonPress;
+ (*darwinEventQueue.pPtr->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+ xe.u.u.type = ButtonRelease;
+ (*darwinEventQueue.pPtr->processInputProc)
+ (&xe, (DeviceIntPtr)darwinEventQueue.pPtr, 1);
+ }
+ break;
+ }
+
+ default:
+ if (quartz) {
+ QuartzProcessEvent(&xe);
+ } else {
+ ErrorF("Unknown X event caught: %d\n", xe.u.u.type);
+ }
+ }
+ }
+ }
+
+ miPointerUpdate();
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/Imakefile b/xc/programs/Xserver/hw/darwin/quartz/Imakefile
new file mode 100644
index 000000000..d547fe97c
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/Imakefile
@@ -0,0 +1,102 @@
+XCOMM $XFree86: xc/programs/Xserver/hw/darwin/quartz/Imakefile,v 1.4 2002/07/24 05:58:33 torrey Exp $
+
+#include <Server.tmpl>
+
+SRCS = Preferences.m \
+ XApplication.m \
+ XServer.m \
+ XView.m \
+ aquaPicture.c \
+ aquaWindow.c \
+ fullscreen.c \
+ quartz.c \
+ quartzAudio.c \
+ quartzCocoa.m \
+ quartzCursor.c \
+ quartzPasteboard.c \
+ rootlessAquaGlue.c \
+ rootlessAquaImp.m \
+ rootlessCommon.c \
+ rootlessGC.c \
+ rootlessScreen.c \
+ rootlessValTree.c \
+ rootlessWindow.c \
+ pseudoramiX.c
+
+OBJS = Preferences.o \
+ XApplication.o \
+ XServer.o \
+ XView.o \
+ aquaPicture.o \
+ aquaWindow.o \
+ fullscreen.o \
+ quartz.o \
+ quartzAudio.o \
+ quartzCocoa.o \
+ quartzCursor.o \
+ quartzPasteboard.o \
+ rootlessAquaGlue.o \
+ rootlessAquaImp.o \
+ rootlessCommon.o \
+ rootlessGC.o \
+ rootlessScreen.o \
+ rootlessValTree.o \
+ rootlessWindow.o \
+ pseudoramiX.o
+
+INCLUDES = -I. -I$(SERVERSRC)/fb -I$(SERVERSRC)/mi -I$(SERVERSRC)/include \
+ -I$(XINCLUDESRC) -I$(FONTINCSRC) -I$(SERVERSRC)/render \
+ -I$(EXTINCSRC) -I.. -I$(SERVERSRC)/Xext
+
+#if defined(XFree86CustomVersion)
+CUSTOMVERSION = XFree86CustomVersion
+CUSTOMVERDEF = -DXF86_CUSTOM_VERSION='$(CUSTOMVERSION)'
+#endif
+#if HasCGMachPort
+QUARTZDEFINES = -DHAS_CG_MACH_PORT
+#endif
+
+#if XFree86Devel
+PBXBUILDSTYLE = -buildstyle Development
+DEBUGDEFINES = -DROOTLESSDEBUG
+#else
+PBXBUILDSTYLE = -buildstyle Deployment
+#endif
+
+DEFINES = $(CUSTOMVERDEF) -DXBINDIR=$(BINDIR) -DXINITDIR=$(XINITDIR) \
+ $(QUARTZDEFINES) $(DEBUGDEFINES)
+EXTRAMANDEFS = -D__XBinDir__=$(BINDIR)
+#if NothingOutsideProjectRoot
+XDARWINROOT = $(BINDIR)
+#else
+XDARWINROOT = /Applications
+#endif
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(XQuartz,$(OBJS))
+
+AllTarget(quartzStartup.o)
+
+AllTarget(XDarwinStartup)
+NormalProgramTarget(XDarwinStartup,XDarwinStartup.o, \
+ NullParameter,NullParameter, \
+ -framework CoreFoundation -framework ApplicationServices)
+InstallProgram(XDarwinStartup,$(BINDIR))
+install::
+ -(cd $(DESTDIR)$(BINDIR); $(RM) X; $(LN) XDarwinStartup X)
+
+AllTarget(XDarwin)
+XDarwin:
+ pbxbuild -target XDarwin $(PBXBUILDSTYLE)
+
+install::
+ pbxbuild install -target XDarwin $(PBXBUILDSTYLE) \
+ DSTROOT=$(DESTDIR)$(XDARWINROOT)
+
+InstallManPage(XDarwinStartup,$(MANDIR))
+
+clean::
+ pbxbuild "clean" -target XDarwin $(PBXBUILDSTYLE)
+
+DependTarget()
+
diff --git a/xc/programs/Xserver/hw/darwin/quartz/Preferences.h b/xc/programs/Xserver/hw/darwin/quartz/Preferences.h
new file mode 100644
index 000000000..6a84bbd01
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/Preferences.h
@@ -0,0 +1,105 @@
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/Preferences.h,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface Preferences : NSObject
+{
+ IBOutlet NSPanel *window;
+ IBOutlet id displayField;
+ IBOutlet id dockSwitchButton;
+ IBOutlet id fakeButton;
+ IBOutlet id button2ModifiersMatrix;
+ IBOutlet id button3ModifiersMatrix;
+ IBOutlet id switchKeyButton;
+ IBOutlet id keymapFileField;
+ IBOutlet id modeMatrix;
+ IBOutlet id modeWindowButton;
+ IBOutlet id startupHelpButton;
+ IBOutlet id systemBeepButton;
+ IBOutlet id mouseAccelChangeButton;
+ IBOutlet id useXineramaButton;
+ IBOutlet id addToPathButton;
+ IBOutlet id addToPathField;
+ IBOutlet id useDefaultShellMatrix;
+ IBOutlet id useOtherShellField;
+ IBOutlet id depthButton;
+
+ BOOL isGettingKeyCode;
+ int keyCode;
+ int modifiers;
+ NSMutableString *switchString;
+}
+
+- (IBAction)close:(id)sender;
+- (IBAction)pickFile:(id)sender;
+- (IBAction)saveChanges:(id)sender;
+- (IBAction)setKey:(id)sender;
+
+- (BOOL)sendEvent:(NSEvent*)anEvent;
+
+- (void)awakeFromNib;
+- (void)windowWillClose:(NSNotification *)aNotification;
+
++ (void)setUseKeymapFile:(BOOL)newUseKeymapFile;
++ (void)setKeymapFile:(NSString*)newFile;
++ (void)setSwitchString:(NSString*)newString;
++ (void)setKeyCode:(int)newKeyCode;
++ (void)setModifiers:(int)newModifiers;
++ (void)setDisplay:(int)newDisplay;
++ (void)setDockSwitch:(BOOL)newDockSwitch;
++ (void)setFakeButtons:(BOOL)newFakeButtons;
++ (void)setButton2Mask:(int)newFakeMask;
++ (void)setButton3Mask:(int)newFakeMask;
++ (void)setMouseAccelChange:(BOOL)newMouseAccelChange;
++ (void)setUseQDCursor:(int)newUseQDCursor;
++ (void)setRootless:(BOOL)newRootless;
++ (void)setModeWindow:(BOOL)newModeWindow;
++ (void)setStartupHelp:(BOOL)newStartupHelp;
++ (void)setSystemBeep:(BOOL)newSystemBeep;
++ (void)setXinerama:(BOOL)newXinerama;
++ (void)setAddToPath:(BOOL)newAddToPath;
++ (void)setAddToPathString:(NSString*)newAddToPathString;
++ (void)setUseDefaultShell:(BOOL)newUseDefaultShell;
++ (void)setShellString:(NSString*)newShellString;
++ (void)setDepth:(int)newDepth;
++ (void)saveToDisk;
+
++ (BOOL)useKeymapFile;
++ (NSString*)keymapFile;
++ (NSString*)switchString;
++ (unsigned int)keyCode;
++ (unsigned int)modifiers;
++ (int)display;
++ (BOOL)dockSwitch;
++ (BOOL)fakeButtons;
++ (int)button2Mask;
++ (int)button3Mask;
++ (BOOL)mouseAccelChange;
++ (int)useQDCursor;
++ (BOOL)rootless;
++ (BOOL)modeWindow;
++ (BOOL)startupHelp;
++ (BOOL)systemBeep;
++ (BOOL)xinerama;
++ (BOOL)addToPath;
++ (NSString*)addToPathString;
++ (BOOL)useDefaultShell;
++ (NSString*)shellString;
++ (int)depth;
+
+@end
+
+// Possible settings for useQDCursor
+enum {
+ qdCursor_Never, // never use QuickDraw cursor
+ qdCursor_Not8Bit, // don't try to use QuickDraw with 8-bit depth
+ qdCursor_Always // always try to use QuickDraw cursor
+};
+
+// Possible settings for depth
+enum {
+ depth_Current,
+ depth_8Bit,
+ depth_15Bit,
+ depth_24Bit
+};
diff --git a/xc/programs/Xserver/hw/darwin/quartz/Preferences.m b/xc/programs/Xserver/hw/darwin/quartz/Preferences.m
new file mode 100644
index 000000000..c17c997ea
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/Preferences.m
@@ -0,0 +1,517 @@
+//
+// Preferences.m
+//
+// This class keeps track of the user preferences.
+//
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/Preferences.m,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#import "Preferences.h"
+#import "quartzCommon.h"
+#include <IOKit/hidsystem/IOLLEvent.h> // for modifier masks
+
+// Macros to build the path name
+#ifndef XBINDIR
+#define XBINDIR /usr/X11R6/bin
+#endif
+#define STR(s) #s
+#define XSTRPATH(s) STR(s)
+
+
+@implementation Preferences
+
++ (void)initialize
+{
+ // Provide user defaults if needed
+ NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt:0], @"Display",
+ @"YES", @"FakeButtons",
+ [NSNumber numberWithInt:NX_COMMANDMASK], @"Button2Mask",
+ [NSNumber numberWithInt:NX_ALTERNATEMASK], @"Button3Mask",
+ NSLocalizedString(@"USA.keymapping",@""), @"KeymappingFile",
+ @"YES", @"UseKeymappingFile",
+ NSLocalizedString(@"Cmd-Opt-a",@""), @"SwitchString",
+ @"NO", @"UseRootlessMode",
+ @"YES", @"ShowModePickWindow",
+ @"YES", @"ShowStartupHelp",
+ [NSNumber numberWithInt:0], @"SwitchKeyCode",
+ [NSNumber numberWithInt:(NSCommandKeyMask | NSAlternateKeyMask)],
+ @"SwitchModifiers", @"NO", @"UseSystemBeep",
+ @"YES", @"DockSwitch",
+ @"NO", @"AllowMouseAccelChange",
+ [NSNumber numberWithInt:qdCursor_Not8Bit], @"UseQDCursor",
+ @"YES", @"Xinerama",
+ @"YES", @"AddToPath",
+ [NSString stringWithCString:XSTRPATH(XBINDIR)], @"AddToPathString",
+ @"YES", @"UseDefaultShell",
+ @"/bin/tcsh", @"Shell",
+ [NSNumber numberWithInt:depth_Current], @"Depth", nil];
+
+ [super initialize];
+ [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
+}
+
+// Initialize internal state info of switch key button
+- (void)initSwitchKey
+{
+ keyCode = [Preferences keyCode];
+ modifiers = [Preferences modifiers];
+ [switchString setString:[Preferences switchString]];
+}
+
+- (id)init
+{
+ self = [super init];
+
+ isGettingKeyCode=NO;
+ switchString=[[NSMutableString alloc] init];
+ [self initSwitchKey];
+
+ return self;
+}
+
+// Set a modifiers checkbox matrix to match a modifier mask
+- (void)resetMatrix:(NSMatrix *)aMatrix withMask:(int)aMask
+{
+ [aMatrix setState:(aMask & NX_SHIFTMASK) atRow:0 column:0];
+ [aMatrix setState:(aMask & NX_CONTROLMASK) atRow:1 column:0];
+ [aMatrix setState:(aMask & NX_COMMANDMASK) atRow:2 column:0];
+ [aMatrix setState:(aMask & NX_ALTERNATEMASK) atRow:3 column:0];
+ [aMatrix setState:(aMask & NX_SECONDARYFNMASK) atRow:4 column:0];
+}
+
+// Generate a modifiers mask from a modifiers checkbox matrix
+- (int)getMaskFromMatrix:(NSMatrix *)aMatrix
+{
+ int theMask = 0;
+
+ if ([[aMatrix cellAtRow:0 column:0] state])
+ theMask |= NX_SHIFTMASK;
+ if ([[aMatrix cellAtRow:1 column:0] state])
+ theMask |= NX_CONTROLMASK;
+ if ([[aMatrix cellAtRow:2 column:0] state])
+ theMask |= NX_COMMANDMASK;
+ if ([[aMatrix cellAtRow:3 column:0] state])
+ theMask |= NX_ALTERNATEMASK;
+ if ([[aMatrix cellAtRow:4 column:0] state])
+ theMask |= NX_SECONDARYFNMASK;
+
+ return theMask;
+}
+
+// Set the window controls to the state in user defaults
+- (void)resetWindow
+{
+ if ([Preferences keymapFile] == nil)
+ [keymapFileField setStringValue:@" "];
+ else
+ [keymapFileField setStringValue:[Preferences keymapFile]];
+
+ if ([Preferences switchString] == nil)
+ [switchKeyButton setTitle:@"--"];
+ else
+ [switchKeyButton setTitle:[Preferences switchString]];
+
+ [displayField setIntValue:[Preferences display]];
+ [dockSwitchButton setIntValue:[Preferences dockSwitch]];
+ [fakeButton setIntValue:[Preferences fakeButtons]];
+ [self resetMatrix:button2ModifiersMatrix
+ withMask:[Preferences button2Mask]];
+ [self resetMatrix:button3ModifiersMatrix
+ withMask:[Preferences button3Mask]];
+ [modeMatrix setState:[Preferences rootless] atRow:0 column:1];
+ [startupHelpButton setIntValue:[Preferences startupHelp]];
+ [modeWindowButton setIntValue:[Preferences modeWindow]];
+ [systemBeepButton setIntValue:[Preferences systemBeep]];
+ [mouseAccelChangeButton setIntValue:[Preferences mouseAccelChange]];
+ [useXineramaButton setIntValue:[Preferences xinerama]];
+ [addToPathButton setIntValue:[Preferences addToPath]];
+ [addToPathField setStringValue:[Preferences addToPathString]];
+ [useDefaultShellMatrix setState:![Preferences useDefaultShell]
+ atRow:1 column:0];
+ [useOtherShellField setStringValue:[Preferences shellString]];
+ [depthButton selectItemAtIndex:[Preferences depth]];
+}
+
+- (void)awakeFromNib
+{
+ [self resetWindow];
+}
+
+// Preference window delegate
+- (void)windowWillClose:(NSNotification *)aNotification
+{
+ [self resetWindow];
+ [self initSwitchKey];
+}
+
+// User cancelled the changes
+- (IBAction)close:(id)sender
+{
+ [window orderOut:nil];
+ [self resetWindow]; // reset window controls
+ [self initSwitchKey]; // reset switch key state
+}
+
+// Pick keymapping file
+- (IBAction)pickFile:(id)sender
+{
+ int result;
+ NSArray *fileTypes = [NSArray arrayWithObject:@"keymapping"];
+ NSOpenPanel *oPanel = [NSOpenPanel openPanel];
+
+ [oPanel setAllowsMultipleSelection:NO];
+ result = [oPanel runModalForDirectory:@"/System/Library/Keyboards"
+ file:nil types:fileTypes];
+ if (result == NSOKButton) {
+ [keymapFileField setStringValue:[oPanel filename]];
+ }
+}
+
+// User saved changes
+- (IBAction)saveChanges:(id)sender
+{
+ [Preferences setKeyCode:keyCode];
+ [Preferences setModifiers:modifiers];
+ [Preferences setSwitchString:switchString];
+ [Preferences setKeymapFile:[keymapFileField stringValue]];
+ [Preferences setUseKeymapFile:YES];
+ [Preferences setDisplay:[displayField intValue]];
+ [Preferences setDockSwitch:[dockSwitchButton intValue]];
+ [Preferences setFakeButtons:[fakeButton intValue]];
+ [Preferences setButton2Mask:
+ [self getMaskFromMatrix:button2ModifiersMatrix]];
+ [Preferences setButton3Mask:
+ [self getMaskFromMatrix:button3ModifiersMatrix]];
+ [Preferences setRootless:[[modeMatrix cellAtRow:0 column:1] state]];
+ [Preferences setModeWindow:[modeWindowButton intValue]];
+ [Preferences setStartupHelp:[startupHelpButton intValue]];
+ [Preferences setSystemBeep:[systemBeepButton intValue]];
+ [Preferences setMouseAccelChange:[mouseAccelChangeButton intValue]];
+ [Preferences setXinerama:[useXineramaButton intValue]];
+ [Preferences setAddToPath:[addToPathButton intValue]];
+ [Preferences setAddToPathString:[addToPathField stringValue]];
+ [Preferences setUseDefaultShell:
+ [[useDefaultShellMatrix cellAtRow:0 column:0] state]];
+ [Preferences setShellString:[useOtherShellField stringValue]];
+ [Preferences setDepth:[depthButton indexOfSelectedItem]];
+ [Preferences saveToDisk];
+
+ [window orderOut:nil];
+}
+
+- (IBAction)setKey:(id)sender
+{
+ [switchKeyButton setTitle:NSLocalizedString(@"Press key",@"")];
+ isGettingKeyCode=YES;
+ [switchString setString:@""];
+}
+
+- (BOOL)sendEvent:(NSEvent*)anEvent
+{
+ if(isGettingKeyCode) {
+ if([anEvent type]==NSKeyDown) // wait for keyup
+ return YES;
+ if([anEvent type]!=NSKeyUp)
+ return NO;
+
+ if([anEvent modifierFlags] & NSCommandKeyMask)
+ [switchString appendString:@"Cmd-"];
+ if([anEvent modifierFlags] & NSControlKeyMask)
+ [switchString appendString:@"Ctrl-"];
+ if([anEvent modifierFlags] & NSAlternateKeyMask)
+ [switchString appendString:@"Opt-"];
+ if([anEvent modifierFlags] & NSNumericPadKeyMask) // doesn't work
+ [switchString appendString:@"Num-"];
+ if([anEvent modifierFlags] & NSHelpKeyMask)
+ [switchString appendString:@"Help-"];
+ if([anEvent modifierFlags] & NSFunctionKeyMask) // powerbooks only
+ [switchString appendString:@"Fn-"];
+
+ [switchString appendString:[anEvent charactersIgnoringModifiers]];
+ [switchKeyButton setTitle:switchString];
+
+ keyCode = [anEvent keyCode];
+ modifiers = [anEvent modifierFlags];
+ isGettingKeyCode=NO;
+
+ return YES;
+ }
+ return NO;
+}
+
++ (void)setKeymapFile:(NSString*)newFile
+{
+ [[NSUserDefaults standardUserDefaults] setObject:newFile
+ forKey:@"KeymappingFile"];
+}
+
++ (void)setUseKeymapFile:(BOOL)newUseKeymapFile
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newUseKeymapFile
+ forKey:@"UseKeymappingFile"];
+}
+
++ (void)setSwitchString:(NSString*)newString
+{
+ [[NSUserDefaults standardUserDefaults] setObject:newString
+ forKey:@"SwitchString"];
+}
+
++ (void)setKeyCode:(int)newKeyCode
+{
+ [[NSUserDefaults standardUserDefaults] setInteger:newKeyCode
+ forKey:@"SwitchKeyCode"];
+}
+
++ (void)setModifiers:(int)newModifiers
+{
+ [[NSUserDefaults standardUserDefaults] setInteger:newModifiers
+ forKey:@"SwitchModifiers"];
+}
+
++ (void)setDisplay:(int)newDisplay
+{
+ [[NSUserDefaults standardUserDefaults] setInteger:newDisplay
+ forKey:@"Display"];
+}
+
++ (void)setDockSwitch:(BOOL)newDockSwitch
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newDockSwitch
+ forKey:@"DockSwitch"];
+}
+
++ (void)setFakeButtons:(BOOL)newFakeButtons
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newFakeButtons
+ forKey:@"FakeButtons"];
+ // Update the setting used by the X server thread
+ darwinFakeButtons = newFakeButtons;
+}
+
++ (void)setButton2Mask:(int)newFakeMask
+{
+ [[NSUserDefaults standardUserDefaults] setInteger:newFakeMask
+ forKey:@"Button2Mask"];
+ // Update the setting used by the X server thread
+ darwinFakeMouse2Mask = newFakeMask;
+}
+
++ (void)setButton3Mask:(int)newFakeMask
+{
+ [[NSUserDefaults standardUserDefaults] setInteger:newFakeMask
+ forKey:@"Button3Mask"];
+ // Update the setting used by the X server thread
+ darwinFakeMouse3Mask = newFakeMask;
+}
+
++ (void)setMouseAccelChange:(BOOL)newMouseAccelChange
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newMouseAccelChange
+ forKey:@"AllowMouseAccelChange"];
+ // Update the setting used by the X server thread
+ quartzMouseAccelChange = newMouseAccelChange;
+}
+
++ (void)setUseQDCursor:(int)newUseQDCursor
+{
+ [[NSUserDefaults standardUserDefaults] setInteger:newUseQDCursor
+ forKey:@"UseQDCursor"];
+}
+
++ (void)setModeWindow:(BOOL)newModeWindow
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newModeWindow
+ forKey:@"ShowModePickWindow"];
+}
+
++ (void)setRootless:(BOOL)newRootless
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newRootless
+ forKey:@"UseRootlessMode"];
+}
+
++ (void)setStartupHelp:(BOOL)newStartupHelp
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newStartupHelp
+ forKey:@"ShowStartupHelp"];
+}
+
++ (void)setSystemBeep:(BOOL)newSystemBeep
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newSystemBeep
+ forKey:@"UseSystemBeep"];
+ // Update the setting used by the X server thread
+ quartzUseSysBeep = newSystemBeep;
+}
+
++ (void)setXinerama:(BOOL)newXinerama
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newXinerama
+ forKey:@"Xinerama"];
+}
+
++ (void)setAddToPath:(BOOL)newAddToPath
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newAddToPath
+ forKey:@"AddToPath"];
+}
+
++ (void)setAddToPathString:(NSString*)newAddToPathString
+{
+ [[NSUserDefaults standardUserDefaults] setObject:newAddToPathString
+ forKey:@"AddToPathString"];
+}
+
++ (void)setUseDefaultShell:(BOOL)newUseDefaultShell
+{
+ [[NSUserDefaults standardUserDefaults] setBool:newUseDefaultShell
+ forKey:@"UseDefaultShell"];
+}
+
++ (void)setShellString:(NSString*)newShellString
+{
+ [[NSUserDefaults standardUserDefaults] setObject:newShellString
+ forKey:@"Shell"];
+}
+
++ (void)setDepth:(int)newDepth
+{
+ [[NSUserDefaults standardUserDefaults] setInteger:newDepth
+ forKey:@"Depth"];
+}
+
++ (void)saveToDisk
+{
+ [[NSUserDefaults standardUserDefaults] synchronize];
+}
+
++ (BOOL)useKeymapFile
+{
+ return [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"UseKeymappingFile"];
+}
+
++ (NSString*)keymapFile
+{
+ return [[NSUserDefaults standardUserDefaults]
+ stringForKey:@"KeymappingFile"];
+}
+
++ (NSString*)switchString
+{
+ return [[NSUserDefaults standardUserDefaults]
+ stringForKey:@"SwitchString"];
+}
+
++ (unsigned int)keyCode
+{
+ return [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"SwitchKeyCode"];
+}
+
++ (unsigned int)modifiers
+{
+ return [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"SwitchModifiers"];
+}
+
++ (int)display
+{
+ return [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"Display"];
+}
+
++ (BOOL)dockSwitch
+{
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"DockSwitch"];
+}
+
++ (BOOL)fakeButtons
+{
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"FakeButtons"];
+}
+
++ (int)button2Mask
+{
+ return [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"Button2Mask"];
+}
+
++ (int)button3Mask
+{
+ return [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"Button3Mask"];
+}
+
++ (BOOL)mouseAccelChange
+{
+ return [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"AllowMouseAccelChange"];
+}
+
++ (int)useQDCursor
+{
+ return [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"UseQDCursor"];
+}
+
++ (BOOL)rootless
+{
+ return [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"UseRootlessMode"];
+}
+
++ (BOOL)modeWindow
+{
+ return [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"ShowModePickWindow"];
+}
+
++ (BOOL)startupHelp
+{
+ return [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"ShowStartupHelp"];
+}
+
++ (BOOL)systemBeep
+{
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"UseSystemBeep"];
+}
+
++ (BOOL)xinerama
+{
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"Xinerama"];
+}
+
++ (BOOL)addToPath
+{
+ return [[NSUserDefaults standardUserDefaults] boolForKey:@"AddToPath"];
+}
+
++ (NSString*)addToPathString
+{
+ return [[NSUserDefaults standardUserDefaults]
+ stringForKey:@"AddToPathString"];
+}
+
++ (BOOL)useDefaultShell
+{
+ return [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"UseDefaultShell"];
+}
+
++ (NSString*)shellString
+{
+ return [[NSUserDefaults standardUserDefaults]
+ stringForKey:@"Shell"];
+}
+
++ (int)depth
+{
+ return [[NSUserDefaults standardUserDefaults]
+ integerForKey:@"Depth"];
+}
+
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XApplication.h b/xc/programs/Xserver/hw/darwin/quartz/XApplication.h
new file mode 100644
index 000000000..3d3e96dab
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XApplication.h
@@ -0,0 +1,47 @@
+//
+// XApplication.h
+//
+// Created by Andreas Monitzer on January 6, 2001.
+//
+/*
+ * Copyright (c) 2001 Andreas Monitzer. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XApplication.h,v 1.2 2002/10/12 00:32:45 torrey Exp $ */
+
+#import <Cocoa/Cocoa.h>
+
+#import "XServer.h"
+#import "Preferences.h"
+
+@interface XApplication : NSApplication {
+ IBOutlet XServer *xserver;
+ IBOutlet Preferences *preferences;
+}
+
+- (void)sendEvent:(NSEvent *)anEvent;
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XApplication.m b/xc/programs/Xserver/hw/darwin/quartz/XApplication.m
new file mode 100644
index 000000000..9b81bbee0
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XApplication.m
@@ -0,0 +1,47 @@
+//
+// XApplication.m
+//
+// Created by Andreas Monitzer on January 6, 2001.
+//
+/*
+ * Copyright (c) 2001 Andreas Monitzer. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XApplication.m,v 1.2 2002/10/12 00:32:45 torrey Exp $ */
+
+#import "XApplication.h"
+
+
+@implementation XApplication
+
+- (void)sendEvent:(NSEvent *)anEvent {
+ if (![xserver translateEvent:anEvent]) {
+ if (![preferences sendEvent:anEvent])
+ [super sendEvent:anEvent];
+ }
+}
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.h b/xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.h
new file mode 100644
index 000000000..3ffc16c9c
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.h
@@ -0,0 +1,41 @@
+/*
+ * XCarbonWindow category for Mac OS X rootless X server
+ *
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.h,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#import <AppKit/NSWindow.h>
+
+@interface NSCarbonWindow : NSWindow
+
+@end
+
+
+@interface NSCarbonWindow(XCarbonWindow)
+
+- (void)display;
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.m b/xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.m
new file mode 100644
index 000000000..167297b2e
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.m
@@ -0,0 +1,45 @@
+/*
+ * XCarbonWindow category for Mac OS X rootless X server
+ *
+ * This category extends/replaces the functionality of NSCarbonWindow.
+ *
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XCarbonWindow.m,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#import "XCarbonWindow.h"
+
+
+@implementation NSCarbonWindow(XCarbonWindow)
+
+// Unfortunately, NSCarbonWindow does not always respect autoDisplay:NO.
+// NSCarbonWindow's display method erases the window content,
+// so we override it.
+- (void)display
+{
+ // Don't do anything here.
+}
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XDarwin.pbproj/project.pbxproj b/xc/programs/Xserver/hw/darwin/quartz/XDarwin.pbproj/project.pbxproj
new file mode 100644
index 000000000..30b591fd5
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XDarwin.pbproj/project.pbxproj
@@ -0,0 +1,1376 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 38;
+ objects = {
+ 01279092000747AA0A000002 = {
+ isa = PBXFileReference;
+ path = XServer.m;
+ refType = 4;
+ };
+ 0127909600074AF60A000002 = {
+ isa = PBXFileReference;
+ path = XApplication.m;
+ refType = 4;
+ };
+ 0127909800074B1A0A000002 = {
+ isa = PBXFileReference;
+ path = XApplication.h;
+ refType = 4;
+ };
+ 014C68ED00ED6A9D7F000001 = {
+ isa = PBXFileReference;
+ path = XView.h;
+ refType = 4;
+ };
+ 014C68EE00ED6A9D7F000001 = {
+ isa = PBXFileReference;
+ path = XView.m;
+ refType = 4;
+ };
+ 014C68F200ED7AD67F000001 = {
+ isa = PBXFileReference;
+ path = fakeBoxRec.h;
+ refType = 4;
+ };
+ 014C68F300EE5AB97F000001 = {
+ isa = PBXFileReference;
+ path = rootlessCommon.c;
+ refType = 4;
+ };
+ 014C68F400EE5AB97F000001 = {
+ isa = PBXFileReference;
+ path = rootlessCommon.h;
+ refType = 4;
+ };
+ 014C68F700EE678F7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessWindow.c;
+ refType = 4;
+ };
+ 014C68F800EE678F7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessWindow.h;
+ refType = 4;
+ };
+ 015698ED003DF345CE6F79C2 = {
+ isa = PBXFileReference;
+ path = XDarwin.icns;
+ refType = 4;
+ };
+ 0157A37D002CF6D7CE6F79C2 = {
+ children = (
+ F533214601A4B45401000001,
+ 0157A37E002CF6D7CE6F79C2,
+ F58D65DF018F79B101000001,
+ F533213D0193CBE001000001,
+ 43B962E200617B93416877C2,
+ F5ACD263C5BE031F01000001,
+ F51BF62E02026E3501000001,
+ F5ACD25CC5B5E96601000001,
+ F587E16401924C6901000001,
+ );
+ isa = PBXVariantGroup;
+ name = Credits.rtf;
+ path = "";
+ refType = 4;
+ };
+ 0157A37E002CF6D7CE6F79C2 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/Credits.rtf;
+ refType = 4;
+ };
+ 015EDCEA004203A8CE6F79C2 = {
+ isa = PBXFrameworkReference;
+ name = IOKit.framework;
+ path = /System/Library/Frameworks/IOKit.framework;
+ refType = 0;
+ };
+ 017D6F4400E861FB7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessGC.c;
+ refType = 4;
+ };
+ 017D6F4500E861FB7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessScreen.c;
+ refType = 4;
+ };
+ 018F40F2003E1902CE6F79C2 = {
+ children = (
+ 018F40F3003E1916CE6F79C2,
+ 021D6BA9003E1BACCE6F79C2,
+ 3E74E03600863F047F000001,
+ F5A94EF10314BAC70100011B,
+ 018F40F6003E1974CE6F79C2,
+ );
+ isa = PBXGroup;
+ name = "X Server";
+ path = ..;
+ refType = 4;
+ };
+ 018F40F3003E1916CE6F79C2 = {
+ isa = PBXFileReference;
+ path = darwin.c;
+ refType = 4;
+ };
+ 018F40F6003E1974CE6F79C2 = {
+ isa = PBXFileReference;
+ path = darwinKeyboard.c;
+ refType = 4;
+ };
+ 018F40F8003E1979CE6F79C2 = {
+ isa = PBXFileReference;
+ path = quartz.c;
+ refType = 4;
+ };
+ 018F40FA003E197ECE6F79C2 = {
+ isa = PBXFileReference;
+ path = quartz.h;
+ refType = 4;
+ };
+ 018F40FC003E1983CE6F79C2 = {
+ isa = PBXFileReference;
+ path = xfIOKit.c;
+ refType = 4;
+ };
+ 018F40FE003E1988CE6F79C2 = {
+ isa = PBXFileReference;
+ path = xfIOKit.h;
+ refType = 4;
+ };
+ 018F4100003E19E4CE6F79C2 = {
+ isa = PBXFileReference;
+ path = xfIOKitCursor.c;
+ refType = 4;
+ };
+//010
+//011
+//012
+//013
+//014
+//020
+//021
+//022
+//023
+//024
+ 021D6BA9003E1BACCE6F79C2 = {
+ isa = PBXFileReference;
+ path = darwin.h;
+ refType = 4;
+ };
+ 02A1FEA6006D34BE416877C2 = {
+ isa = PBXFileReference;
+ path = xfIOKitStartup.c;
+ refType = 4;
+ };
+ 02A1FEA8006D38F0416877C2 = {
+ isa = PBXFileReference;
+ path = quartzStartup.c;
+ refType = 4;
+ };
+ 02E03CA000348209CE6F79C2 = {
+ children = (
+ F533214701A4B48301000001,
+ 02E03CA100348209CE6F79C2,
+ F58D65E0018F79C001000001,
+ F533213E0193CBF401000001,
+ 43B962E300617B93416877C2,
+ F5ACD268C5BE046401000001,
+ F51BF62F02026E5C01000001,
+ F5ACD261C5B5EA2001000001,
+ F587E16501924C7401000001,
+ );
+ isa = PBXVariantGroup;
+ name = XDarwinHelp.html;
+ path = "";
+ refType = 4;
+ };
+ 02E03CA100348209CE6F79C2 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+//020
+//021
+//022
+//023
+//024
+//030
+//031
+//032
+//033
+//034
+ 0338412F0083BFE57F000001 = {
+ isa = PBXFileReference;
+ path = quartzCursor.h;
+ refType = 4;
+ };
+//030
+//031
+//032
+//033
+//034
+//040
+//041
+//042
+//043
+//044
+ 04329610000763920A000002 = {
+ isa = PBXFileReference;
+ path = Preferences.m;
+ refType = 4;
+ };
+ 04329611000763920A000002 = {
+ isa = PBXFileReference;
+ path = Preferences.h;
+ refType = 4;
+ };
+//040
+//041
+//042
+//043
+//044
+//060
+//061
+//062
+//063
+//064
+ 06EB6C3B004099E7CE6F79C2 = {
+ isa = PBXFileReference;
+ path = quartzShared.h;
+ refType = 4;
+ };
+//060
+//061
+//062
+//063
+//064
+//080
+//081
+//082
+//083
+//084
+ 080E96DDFE201D6D7F000001 = {
+ children = (
+ 04329610000763920A000002,
+ 04329611000763920A000002,
+ 0127909600074AF60A000002,
+ 0127909800074B1A0A000002,
+ 01279092000747AA0A000002,
+ 1C4A3109004D8F24CE6F79C2,
+ 014C68EE00ED6A9D7F000001,
+ 014C68ED00ED6A9D7F000001,
+ );
+ isa = PBXGroup;
+ name = Classes;
+ refType = 4;
+ };
+ 089C165CFE840E0CC02AAC07 = {
+ children = (
+ F533214301A4B3F001000001,
+ 089C165DFE840E0CC02AAC07,
+ F58D65DD018F798F01000001,
+ F533213A0193CBA201000001,
+ 43B962E100617B49416877C2,
+ F5ACD269C5BE049301000001,
+ F51BF62B02026DDA01000001,
+ F5ACD262C5B5EA4D01000001,
+ F587E16101924C2F01000001,
+ );
+ isa = PBXVariantGroup;
+ name = InfoPlist.strings;
+ refType = 4;
+ };
+ 089C165DFE840E0CC02AAC07 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+//080
+//081
+//082
+//083
+//084
+//0A0
+//0A1
+//0A2
+//0A3
+//0A4
+ 0A79E19E004499A1CE6F79C2 = {
+ isa = PBXApplicationReference;
+ path = XDarwin.app;
+ refType = 3;
+ };
+ 0A79E19F004499A1CE6F79C2 = {
+ buildPhases = (
+ 0A79E1A0004499A1CE6F79C2,
+ 0A79E1A1004499A1CE6F79C2,
+ 0A79E1A2004499A1CE6F79C2,
+ 0A79E1A3004499A1CE6F79C2,
+ 0A79E1A4004499A1CE6F79C2,
+ );
+ buildSettings = {
+ INSTALL_PATH = /;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = XDarwin;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = app;
+ };
+ dependencies = (
+ );
+ isa = PBXApplicationTarget;
+ name = XDarwin;
+ productInstallPath = /;
+ productName = XDarwin;
+ productReference = 0A79E19E004499A1CE6F79C2;
+ productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
+<plist version=\"1.0\">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>XDarwin</string>
+ <key>CFBundleGetInfoString</key>
+ <string>XDarwin 1.2a2, ©2001-2002 XFree86 Project, Inc.</string>
+ <key>CFBundleIconFile</key>
+ <string>XDarwin.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.xfree86.XDarwin</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>XDarwin</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>XDarwin 1.2a2</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string></string>
+ <key>NSHelpFile</key>
+ <string>XDarwinHelp.html</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>XApplication</string>
+</dict>
+</plist>
+";
+ shouldUseHeadermap = 0;
+ };
+ 0A79E1A0004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0A79E1A1004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ 0A79E1A600449EB2CE6F79C2,
+ 0A79E1A700449EB2CE6F79C2,
+ 0A79E1A800449EB2CE6F79C2,
+ 0A79E1A900449EB2CE6F79C2,
+ 0A79E1AA00449EB2CE6F79C2,
+ 1220774500712D2D416877C2,
+ F54BF6ED017D506E01000001,
+ );
+ isa = PBXResourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0A79E1A2004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0A79E1A3004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0A79E1A4004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 0A79E1A600449EB2CE6F79C2 = {
+ fileRef = 29B97318FDCFA39411CA2CEA;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1A700449EB2CE6F79C2 = {
+ fileRef = 089C165CFE840E0CC02AAC07;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1A800449EB2CE6F79C2 = {
+ fileRef = 0157A37D002CF6D7CE6F79C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1A900449EB2CE6F79C2 = {
+ fileRef = 02E03CA000348209CE6F79C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1AA00449EB2CE6F79C2 = {
+ fileRef = 015698ED003DF345CE6F79C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+//0A0
+//0A1
+//0A2
+//0A3
+//0A4
+//100
+//101
+//102
+//103
+//104
+ 1058C7A0FEA54F0111CA2CBB = {
+ children = (
+ F53321400193CCF001000001,
+ 1BE4F84D0006C9890A000002,
+ 1058C7A1FEA54F0111CA2CBB,
+ F53321410193CCF001000001,
+ 015EDCEA004203A8CE6F79C2,
+ );
+ isa = PBXGroup;
+ name = "Linked Frameworks";
+ refType = 4;
+ };
+ 1058C7A1FEA54F0111CA2CBB = {
+ isa = PBXFrameworkReference;
+ name = Cocoa.framework;
+ path = /System/Library/Frameworks/Cocoa.framework;
+ refType = 0;
+ };
+ 1058C7A2FEA54F0111CA2CBB = {
+ children = (
+ 29B97325FDCFA39411CA2CEA,
+ 29B97324FDCFA39411CA2CEA,
+ );
+ isa = PBXGroup;
+ name = "Other Frameworks";
+ refType = 4;
+ };
+//100
+//101
+//102
+//103
+//104
+//120
+//121
+//122
+//123
+//124
+ 1220774300712D2D416877C2 = {
+ children = (
+ F533214501A4B42501000001,
+ 1220774400712D2D416877C2,
+ F58D65DE018F79A001000001,
+ F533213C0193CBC901000001,
+ 1220774600712D75416877C2,
+ F5ACD266C5BE03C501000001,
+ F51BF62D02026E1C01000001,
+ F5ACD25FC5B5E9AA01000001,
+ F587E16301924C5E01000001,
+ );
+ isa = PBXVariantGroup;
+ name = Localizable.strings;
+ path = "";
+ refType = 4;
+ };
+ 1220774400712D2D416877C2 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/Localizable.strings;
+ refType = 4;
+ };
+ 1220774500712D2D416877C2 = {
+ fileRef = 1220774300712D2D416877C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1220774600712D75416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/Localizable.strings;
+ refType = 4;
+ };
+//120
+//121
+//122
+//123
+//124
+//170
+//171
+//172
+//173
+//174
+ 170DFAFF00729A35416877C2 = {
+ isa = PBXFileReference;
+ path = XDarwinStartup.c;
+ refType = 4;
+ };
+ 170DFB0000729C86416877C2 = {
+ children = (
+ 018F40FC003E1983CE6F79C2,
+ 018F40FE003E1988CE6F79C2,
+ 018F4100003E19E4CE6F79C2,
+ 02A1FEA6006D34BE416877C2,
+ );
+ isa = PBXGroup;
+ name = IOKit;
+ path = ..;
+ refType = 4;
+ };
+//170
+//171
+//172
+//173
+//174
+//190
+//191
+//192
+//193
+//194
+ 19C28FACFE9D520D11CA2CBB = {
+ children = (
+ 0A79E19E004499A1CE6F79C2,
+ );
+ isa = PBXGroup;
+ name = Products;
+ refType = 4;
+ };
+//190
+//191
+//192
+//193
+//194
+//1B0
+//1B1
+//1B2
+//1B3
+//1B4
+ 1BD8DE4200B8A3567F000001 = {
+ children = (
+ F533214401A4B40F01000001,
+ 1BD8DE4300B8A3567F000001,
+ F58D65DC018F794D01000001,
+ F533213B0193CBB401000001,
+ 1BD8DE4700B8A3C77F000001,
+ F5ACD264C5BE035B01000001,
+ F51BF62C02026E0601000001,
+ F5ACD25DC5B5E97701000001,
+ F587E16201924C5301000001,
+ );
+ isa = PBXVariantGroup;
+ name = InfoPlist.strings.cpp;
+ path = "";
+ refType = 4;
+ };
+ 1BD8DE4300B8A3567F000001 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ 1BD8DE4400B8A38E7F000001 = {
+ children = (
+ F533214801A4B4D701000001,
+ 1BD8DE4500B8A38E7F000001,
+ F58D65E1018F79E001000001,
+ F533213F0193CC2501000001,
+ 1BD8DE4800B8A4167F000001,
+ F5ACD267C5BE03FC01000001,
+ F51BF63002026E8D01000001,
+ F5ACD260C5B5E9DF01000001,
+ F587E16601924C9D01000001,
+ );
+ isa = PBXVariantGroup;
+ name = XDarwinHelp.html.cpp;
+ path = "";
+ refType = 4;
+ };
+ 1BD8DE4500B8A38E7F000001 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ 1BD8DE4700B8A3C77F000001 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ 1BD8DE4800B8A4167F000001 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ 1BE4F84D0006C9890A000002 = {
+ isa = PBXFrameworkReference;
+ name = Carbon.framework;
+ path = /System/Library/Frameworks/Carbon.framework;
+ refType = 0;
+ };
+//1B0
+//1B1
+//1B2
+//1B3
+//1B4
+//1C0
+//1C1
+//1C2
+//1C3
+//1C4
+ 1C4A3109004D8F24CE6F79C2 = {
+ isa = PBXFileReference;
+ path = XServer.h;
+ refType = 4;
+ };
+//1C0
+//1C1
+//1C2
+//1C3
+//1C4
+//230
+//231
+//232
+//233
+//234
+ 237A34C10076E37E7F000001 = {
+ isa = PBXFileReference;
+ path = quartzAudio.c;
+ refType = 4;
+ };
+ 237A34C20076E37E7F000001 = {
+ buildRules = (
+ );
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ OPTIMIZATION_CFLAGS = "-O0";
+ };
+ isa = PBXBuildStyle;
+ name = Development;
+ };
+ 237A34C30076E37E7F000001 = {
+ buildRules = (
+ );
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ };
+ isa = PBXBuildStyle;
+ name = Deployment;
+ };
+ 237A34C40076F4F07F000001 = {
+ isa = PBXFileReference;
+ path = quartzAudio.h;
+ refType = 4;
+ };
+//230
+//231
+//232
+//233
+//234
+//290
+//291
+//292
+//293
+//294
+ 29B97313FDCFA39411CA2CEA = {
+ buildStyles = (
+ 237A34C20076E37E7F000001,
+ 237A34C30076E37E7F000001,
+ );
+ isa = PBXProject;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ Swedish,
+ Dutch,
+ Spanish,
+ ko,
+ Portuguese,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA;
+ projectDirPath = "";
+ targets = (
+ 0A79E19F004499A1CE6F79C2,
+ );
+ };
+ 29B97314FDCFA39411CA2CEA = {
+ children = (
+ 080E96DDFE201D6D7F000001,
+ 018F40F2003E1902CE6F79C2,
+ 170DFB0000729C86416877C2,
+ 43B962CE00617089416877C2,
+ F5614B3D025112D901000114,
+ 32FEE13C00E07C3E7F000001,
+ 29B97315FDCFA39411CA2CEA,
+ 29B97317FDCFA39411CA2CEA,
+ 29B97323FDCFA39411CA2CEA,
+ 19C28FACFE9D520D11CA2CBB,
+ );
+ isa = PBXGroup;
+ name = "Xmaster-Cocoa";
+ path = "";
+ refType = 4;
+ };
+ 29B97315FDCFA39411CA2CEA = {
+ children = (
+ 170DFAFF00729A35416877C2,
+ );
+ isa = PBXGroup;
+ name = "Other Sources";
+ path = "";
+ refType = 2;
+ };
+ 29B97317FDCFA39411CA2CEA = {
+ children = (
+ 29B97318FDCFA39411CA2CEA,
+ 089C165CFE840E0CC02AAC07,
+ 1BD8DE4200B8A3567F000001,
+ 1220774300712D2D416877C2,
+ 0157A37D002CF6D7CE6F79C2,
+ 02E03CA000348209CE6F79C2,
+ 1BD8DE4400B8A38E7F000001,
+ 015698ED003DF345CE6F79C2,
+ F54BF6EA017D500901000001,
+ F54BF6EC017D506E01000001,
+ );
+ isa = PBXGroup;
+ name = Resources;
+ path = ../bundle;
+ refType = 4;
+ };
+ 29B97318FDCFA39411CA2CEA = {
+ children = (
+ F533214201A4B3CE01000001,
+ 29B97319FDCFA39411CA2CEA,
+ F58D65DB018F793801000001,
+ F53321390193CB6A01000001,
+ 43B962E000617B49416877C2,
+ F5ACD265C5BE038601000001,
+ F51BF62A02026DAF01000001,
+ F5ACD25EC5B5E98D01000001,
+ F587E16001924C1D01000001,
+ );
+ isa = PBXVariantGroup;
+ name = MainMenu.nib;
+ path = "";
+ refType = 4;
+ };
+ 29B97319FDCFA39411CA2CEA = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ 29B97323FDCFA39411CA2CEA = {
+ children = (
+ 1058C7A0FEA54F0111CA2CBB,
+ 1058C7A2FEA54F0111CA2CBB,
+ );
+ isa = PBXGroup;
+ name = Frameworks;
+ path = "";
+ refType = 4;
+ };
+ 29B97324FDCFA39411CA2CEA = {
+ isa = PBXFrameworkReference;
+ name = AppKit.framework;
+ path = /System/Library/Frameworks/AppKit.framework;
+ refType = 0;
+ };
+ 29B97325FDCFA39411CA2CEA = {
+ isa = PBXFrameworkReference;
+ name = Foundation.framework;
+ path = /System/Library/Frameworks/Foundation.framework;
+ refType = 0;
+ };
+//290
+//291
+//292
+//293
+//294
+//320
+//321
+//322
+//323
+//324
+ 32FEE13C00E07C3E7F000001 = {
+ children = (
+ F56CBD0D02EB84A801129B8A,
+ F56CBD0E02EB84A801129B8A,
+ F56CBD0F02EBDCFC01129B8A,
+ 014C68F200ED7AD67F000001,
+ F5269C2D01D5BC3501000001,
+ F5269C2E01D5BC3501000001,
+ 32FEE13E00E07CBE7F000001,
+ 32FEE13F00E07CBE7F000001,
+ 32FEE14000E07CBE7F000001,
+ 32FEE14100E07CBE7F000001,
+ 32FEE14200E07CBE7F000001,
+ 014C68F300EE5AB97F000001,
+ 014C68F400EE5AB97F000001,
+ 017D6F4400E861FB7F000001,
+ 017D6F4500E861FB7F000001,
+ 014C68F700EE678F7F000001,
+ 014C68F800EE678F7F000001,
+ 32FEE14900E07D317F000001,
+ );
+ isa = PBXGroup;
+ name = Rootless;
+ path = "";
+ refType = 4;
+ };
+ 32FEE13E00E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootless.h;
+ refType = 4;
+ };
+ 32FEE13F00E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAqua.h;
+ refType = 4;
+ };
+ 32FEE14000E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAquaGlue.c;
+ refType = 4;
+ };
+ 32FEE14100E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAquaImp.h;
+ refType = 4;
+ };
+ 32FEE14200E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAquaImp.m;
+ refType = 4;
+ };
+ 32FEE14900E07D317F000001 = {
+ isa = PBXFileReference;
+ path = rootlessValTree.c;
+ refType = 4;
+ };
+//320
+//321
+//322
+//323
+//324
+//350
+//351
+//352
+//353
+//354
+ 3576829A0077B8F17F000001 = {
+ isa = PBXFileReference;
+ path = quartzCursor.c;
+ refType = 4;
+ };
+//350
+//351
+//352
+//353
+//354
+//3E0
+//3E1
+//3E2
+//3E3
+//3E4
+ 3E74E03600863F047F000001 = {
+ isa = PBXFileReference;
+ path = darwinClut8.h;
+ refType = 4;
+ };
+//3E0
+//3E1
+//3E2
+//3E3
+//3E4
+//430
+//431
+//432
+//433
+//434
+ 43B962CE00617089416877C2 = {
+ children = (
+ 018F40F8003E1979CE6F79C2,
+ 018F40FA003E197ECE6F79C2,
+ 237A34C10076E37E7F000001,
+ 237A34C40076F4F07F000001,
+ 3576829A0077B8F17F000001,
+ 0338412F0083BFE57F000001,
+ 43B962D000617089416877C2,
+ 43B962D100617089416877C2,
+ 43B962CF00617089416877C2,
+ F5582948015DAD3B01000001,
+ 06EB6C3B004099E7CE6F79C2,
+ 02A1FEA8006D38F0416877C2,
+ );
+ isa = PBXGroup;
+ name = Quartz;
+ path = "";
+ refType = 4;
+ };
+ 43B962CF00617089416877C2 = {
+ isa = PBXFileReference;
+ path = quartzCocoa.m;
+ refType = 4;
+ };
+ 43B962D000617089416877C2 = {
+ isa = PBXFileReference;
+ path = quartzPasteboard.c;
+ refType = 4;
+ };
+ 43B962D100617089416877C2 = {
+ isa = PBXFileReference;
+ path = quartzPasteboard.h;
+ refType = 4;
+ };
+ 43B962E000617B49416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ 43B962E100617B49416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ 43B962E200617B93416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/Credits.rtf;
+ refType = 4;
+ };
+ 43B962E300617B93416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+//430
+//431
+//432
+//433
+//434
+//F50
+//F51
+//F52
+//F53
+//F54
+ F51BF62A02026DAF01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F51BF62B02026DDA01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F51BF62C02026E0601000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F51BF62D02026E1C01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F51BF62E02026E3501000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F51BF62F02026E5C01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F51BF63002026E8D01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5269C2D01D5BC3501000001 = {
+ isa = PBXFileReference;
+ path = pseudoramiX.c;
+ refType = 4;
+ };
+ F5269C2E01D5BC3501000001 = {
+ isa = PBXFileReference;
+ path = pseudoramiX.h;
+ refType = 4;
+ };
+ F53321390193CB6A01000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F533213A0193CBA201000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F533213B0193CBB401000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F533213C0193CBC901000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F533213D0193CBE001000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F533213E0193CBF401000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F533213F0193CC2501000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F53321400193CCF001000001 = {
+ isa = PBXFrameworkReference;
+ name = ApplicationServices.framework;
+ path = /System/Library/Frameworks/ApplicationServices.framework;
+ refType = 0;
+ };
+ F53321410193CCF001000001 = {
+ isa = PBXFrameworkReference;
+ name = CoreAudio.framework;
+ path = /System/Library/Frameworks/CoreAudio.framework;
+ refType = 0;
+ };
+ F533214201A4B3CE01000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F533214301A4B3F001000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F533214401A4B40F01000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F533214501A4B42501000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F533214601A4B45401000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F533214701A4B48301000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F533214801A4B4D701000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F54BF6EA017D500901000001 = {
+ isa = PBXFileReference;
+ path = startXClients.cpp;
+ refType = 4;
+ };
+ F54BF6EC017D506E01000001 = {
+ isa = PBXFileReference;
+ path = startXClients;
+ refType = 4;
+ };
+ F54BF6ED017D506E01000001 = {
+ fileRef = F54BF6EC017D506E01000001;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F5582948015DAD3B01000001 = {
+ isa = PBXFileReference;
+ path = quartzCommon.h;
+ refType = 4;
+ };
+ F5614B3B0251124C01000114 = {
+ isa = PBXFileReference;
+ path = fullscreen.c;
+ refType = 4;
+ };
+ F5614B3C0251124C01000114 = {
+ isa = PBXFileReference;
+ path = fullscreen.h;
+ refType = 4;
+ };
+ F5614B3D025112D901000114 = {
+ children = (
+ F5614B3B0251124C01000114,
+ F5614B3C0251124C01000114,
+ );
+ isa = PBXGroup;
+ name = "Full Screen";
+ path = "";
+ refType = 4;
+ };
+ F56CBD0D02EB84A801129B8A = {
+ isa = PBXFileReference;
+ path = aqua.h;
+ refType = 4;
+ };
+ F56CBD0E02EB84A801129B8A = {
+ isa = PBXFileReference;
+ path = aquaPicture.c;
+ refType = 4;
+ };
+ F56CBD0F02EBDCFC01129B8A = {
+ isa = PBXFileReference;
+ path = aquaWindow.c;
+ refType = 4;
+ };
+ F587E16001924C1D01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F587E16101924C2F01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F587E16201924C5301000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F587E16301924C5E01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F587E16401924C6901000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F587E16501924C7401000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F587E16601924C9D01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F58D65DB018F793801000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F58D65DC018F794D01000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F58D65DD018F798F01000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F58D65DE018F79A001000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F58D65DF018F79B101000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F58D65E0018F79C001000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F58D65E1018F79E001000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5A94EF10314BAC70100011B = {
+ isa = PBXFileReference;
+ path = darwinEvents.c;
+ refType = 4;
+ };
+ F5ACD25CC5B5E96601000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F5ACD25DC5B5E97701000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F5ACD25EC5B5E98D01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F5ACD25FC5B5E9AA01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F5ACD260C5B5E9DF01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5ACD261C5B5EA2001000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F5ACD262C5B5EA4D01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F5ACD263C5BE031F01000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F5ACD264C5BE035B01000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F5ACD265C5BE038601000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F5ACD266C5BE03C501000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F5ACD267C5BE03FC01000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5ACD268C5BE046401000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F5ACD269C5BE049301000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.c b/xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.c
new file mode 100644
index 000000000..53343aa1e
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.c
@@ -0,0 +1,165 @@
+/**************************************************************
+ *
+ * Startup program for Darwin X servers
+ *
+ * This program selects the appropriate X server to launch:
+ * XDarwin IOKit X server (default)
+ * XDarwinQuartz A soft link to the Quartz X server
+ * executable (-quartz etc. option)
+ *
+ * If told to idle, the program will simply pause and not
+ * launch any X server. This is to support startx being
+ * run by XDarwin.app.
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * TORREY T. LYONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Torrey T. Lyons shall not
+ * be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * Torrey T. Lyons.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/syslimits.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+extern int errno;
+
+// Macros to build the path name
+#ifndef XBINDIR
+#define XBINDIR /usr/X11R6/bin
+#endif
+#define STR(s) #s
+#define XSTRPATH(s) STR(s) "/"
+#define XPATH(file) XSTRPATH(XBINDIR) STR(file)
+
+int main(
+ int argc,
+ char *argv[] )
+{
+ int i, j, quartzMode = -1;
+ char **newargv;
+
+ // Check if we are going to run in Quartz mode or idle
+ // to support startx from the Quartz server. The last
+ // parameter in the list is the one used.
+ for (i = argc-1; i; i--) {
+ if (!strcmp(argv[i], "-idle")) {
+ pause();
+ return 0;
+
+ } else if (!strcmp(argv[i], "-quartz") ||
+ !strcmp(argv[i], "-rootless") ||
+ !strcmp(argv[i], "-fullscreen"))
+ {
+ quartzMode = 1;
+ break;
+
+ } else if (!strcmp(argv[i], "-iokit")) {
+ quartzMode = 0;
+ break;
+ }
+ }
+
+ if (quartzMode == -1) {
+#ifdef HAS_CG_MACH_PORT
+ // Check if the CoreGraphics window server is running.
+ // Mike Paquette says this is the fastest way to determine if it is running.
+ CFMachPortRef cgMachPortRef = CGWindowServerCFMachPort();
+ if (cgMachPortRef == NULL)
+ quartzMode = 0;
+ else
+ quartzMode = 1;
+#else
+ // On older systems we assume IOKit mode.
+ quartzMode = 0;
+#endif
+ }
+
+ if (quartzMode) {
+ // Launch the X server for the quartz modes
+
+ char quartzPath[PATH_MAX+1];
+ int pathLength;
+ OSStatus theStatus;
+ CFURLRef appURL;
+ CFStringRef appPath;
+ Boolean success;
+
+ // Build the new argument list
+ newargv = (char **) malloc((argc+2) * sizeof(char *));
+ for (j = argc; j; j--)
+ newargv[j] = argv[j];
+ newargv[argc] = "-nostartx";
+ newargv[argc+1] = NULL;
+
+ // Use the XDarwinQuartz soft link if it is valid
+ pathLength = readlink(XPATH(XDarwinQuartz), quartzPath, PATH_MAX);
+ if (pathLength != -1) {
+ quartzPath[pathLength] = '\0';
+ newargv[0] = quartzPath;
+ execv(newargv[0], newargv);
+ }
+
+ // Otherwise query LaunchServices for the location of the XDarwin application
+ theStatus = LSFindApplicationForInfo(kLSUnknownCreator,
+ CFSTR("org.xfree86.XDarwin"),
+ NULL, NULL, &appURL);
+ if (theStatus) {
+ fprintf(stderr, "Could not find the XDarwin application. (Error = 0x%lx)\n", theStatus);
+ fprintf(stderr, "Launch XDarwin once from the Finder.\n");
+ return theStatus;
+ }
+
+ appPath = CFURLCopyFileSystemPath (appURL, kCFURLPOSIXPathStyle);
+ success = CFStringGetCString(appPath, quartzPath, PATH_MAX, CFStringGetSystemEncoding());
+ if (! success) {
+ fprintf(stderr, "Could not find path to XDarwin application.\n");
+ return success;
+ }
+
+ // Launch the XDarwin application
+ strncat(quartzPath, "/Contents/MacOS/XDarwin", PATH_MAX);
+ newargv[0] = quartzPath;
+ execv(newargv[0], newargv);
+ fprintf(stderr, "Could not start XDarwin application at %s.\n", newargv[0]);
+ return errno;
+
+ } else {
+
+ // Build the new argument list
+ newargv = (char **) malloc((argc+1) * sizeof(char *));
+ for (j = argc; j; j--)
+ newargv[j] = argv[j];
+ newargv[0] = "XDarwin";
+ newargv[argc] = NULL;
+
+ // Launch the IOKit X server
+ execvp(newargv[0], newargv);
+ fprintf(stderr, "Could not start XDarwin IOKit X server.\n");
+ return errno;
+ }
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.man b/xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.man
new file mode 100644
index 000000000..312f4b88b
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.man
@@ -0,0 +1,75 @@
+.\" $XFree86: xc/programs/Xserver/hw/darwin/quartz/XDarwinStartup.man,v 1.1 2002/03/28 02:21:18 torrey Exp $
+.TH XDarwinStartup 1
+.SH NAME
+XDarwinStartup - Startup program for the XDarwin X window server
+.SH SYNOPSIS
+.B XDarwinStartup
+[\fI-iokit\fP]
+[\fI-fullscreen\fP]
+[\fI-rootless\fP]
+[\fI-quartz\fP]
+[\fI-idle\fP]
+[\fIoptions\fP]
+.SH DESCRIPTION
+The \fIXDarwin(1)\fP X window server can be run in a variety of different
+modes and is actually two different executables. The IOKit X server,
+XDarwin, is used when running from the console. It is most commonly
+located in __XBinDir__. The Quartz X server, for running in parallel with
+Aqua, is a full-fledged Mac OS X application that can be started from
+the Finder. Its application bundle is XDarwin.app, which is typically
+located in /Applications.
+.I XDarwinStartup
+allows easy switching between these X servers and auto-detection of the
+appropriate one to use when launching from the command line.
+When run without any arguments,
+.I XDarwinStartup
+will start the Quartz X server if the Core Graphics window server
+is currently running. Otherwise it will start the IOKit X server.
+.PP
+To locate the Quartz X server,
+.I XDarwinStartup
+will try to read the soft link at __XBinDir__/XDarwinQuartz.
+This is typically a soft link to the executable of the XDarwin.app
+application. If this fails,
+.I XDarwinStartup
+will call Launch Services to locate XDarwin.app.
+.PP
+To start the IOKit X server,
+.I XDarwinStartup
+will run the XDarwin execuatable, which should be present in the
+user's path.
+.SH OPTIONS
+.I XDarwinStartup
+accepts and passes on all options to the X server it
+launches. In addition the following options have specific effects:
+.TP 8
+.B \-iokit
+Launch the IOKit X server.
+.TP 8
+.B \-fullscreen
+Launch the Quartz X server to run in full screen mode.
+.TP 8
+.B \-rootless
+Launch the Quartz X server to run in rootless mode.
+.TP 8
+.B \-quartz
+Launch the Quartz X server.
+.TP 8
+.B \-idle
+Pause and do nothing. This option is used by XDarwin.app when it is
+started from the Finder.
+.SH FILES
+.TP 30
+__XBinDir__/XDarwin
+IOKit mode X server
+.TP 30
+/Applications/XDarwin.app
+Quartz mode X server
+.TP 30
+__XBinDir__/XDarwinQuartz
+Soft link to Quartz mode X server executable
+.SH SEE ALSO
+XDarwin(1)
+.SH BUGS
+The path to XDarwinQuartz should not be hard coded.
+
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XServer.h b/xc/programs/Xserver/hw/darwin/quartz/XServer.h
new file mode 100644
index 000000000..b9fe410b6
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XServer.h
@@ -0,0 +1,100 @@
+//
+// XServer.h
+//
+/*
+ * Copyright (c) 2001 Andreas Monitzer. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XServer.h,v 1.4 2002/10/12 00:32:45 torrey Exp $ */
+
+#define BOOL xBOOL
+#include "Xproto.h"
+#undef BOOL
+
+#import <Cocoa/Cocoa.h>
+
+@interface XServer : NSObject {
+ // server state
+ NSRecursiveLock *serverLock;
+ BOOL serverVisible;
+ BOOL rootlessMenuBarVisible;
+ BOOL appQuitting;
+ UInt32 mouseState;
+ Class windowClass;
+
+ // server event queue
+ BOOL sendServerEvents;
+ int eventWriteFD;
+
+ // Aqua interface
+ IBOutlet NSWindow *modeWindow;
+ IBOutlet NSButton *startupModeButton;
+ IBOutlet NSButton *startFullScreenButton;
+ IBOutlet NSButton *startRootlessButton;
+ IBOutlet NSWindow *helpWindow;
+ IBOutlet NSButton *startupHelpButton;
+ IBOutlet NSPanel *switchWindow;
+}
+
+- (id)init;
+
+- (BOOL)translateEvent:(NSEvent *)anEvent;
+- (BOOL)getMousePosition:(xEvent *)xe;
+
++ (void)append:(NSString *)value toEnv:(NSString *)name;
+
+- (void)startX;
+- (BOOL)startXClients;
+- (void)run;
+- (void)toggle;
+- (void)show;
+- (void)hide;
+- (void)killServer;
+- (void)readPasteboard;
+- (void)writePasteboard;
+- (void)sendXEvent:(xEvent *)xe;
+- (void)sendShowHide:(BOOL)show;
+- (void)clientProcessDone:(int)clientStatus;
+
+// Aqua interface actions
+- (IBAction)startFullScreen:(id)sender;
+- (IBAction)startRootless:(id)sender;
+- (IBAction)closeHelpAndShow:(id)sender;
+- (IBAction)showAction:(id)sender;
+
+// NSApplication delegate
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag;
+- (void)applicationWillResignActive:(NSNotification *)aNotification;
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification;
+
+// NSPort delegate
+- (void)handlePortMessage:(NSPortMessage *)portMessage;
+
+@end
+
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XServer.m b/xc/programs/Xserver/hw/darwin/quartz/XServer.m
new file mode 100644
index 000000000..4b7af53e6
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XServer.m
@@ -0,0 +1,916 @@
+//
+// XServer.m
+//
+// This class handles the interaction between the Cocoa front-end
+// and the Darwin X server thread.
+//
+// Created by Andreas Monitzer on January 6, 2001.
+//
+/*
+ * Copyright (c) 2001 Andreas Monitzer. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the
+ * sale, use or other dealings in this Software without prior written
+ * authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XServer.m,v 1.4 2002/10/12 00:32:45 torrey Exp $ */
+
+#include "quartzCommon.h"
+
+#define BOOL xBOOL
+#include "X.h"
+#include "Xproto.h"
+#include "os.h"
+#include "darwin.h"
+#undef BOOL
+
+#import "XServer.h"
+#import "Preferences.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/syslimits.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pwd.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#define ENQUEUE(xe) \
+{ \
+ char byte = 0; \
+ DarwinEQEnqueue(xe); \
+ /* signal there is an event ready to handle */ \
+ write(eventWriteFD, &byte, 1); \
+}
+
+// Types of shells
+enum {
+ shell_Unknown,
+ shell_Bourne,
+ shell_C
+};
+
+typedef struct {
+ char *name;
+ int type;
+} shellList_t;
+
+static shellList_t const shellList[] = {
+ { "csh", shell_C }, // standard C shell
+ { "tcsh", shell_C }, // ... needs no introduction
+ { "sh", shell_Bourne }, // standard Bourne shell
+ { "zsh", shell_Bourne }, // Z shell
+ { "bash", shell_Bourne }, // GNU Bourne again shell
+ { NULL, shell_Unknown }
+};
+
+extern int argcGlobal;
+extern char **argvGlobal;
+extern char **envpGlobal;
+extern int main(int argc, char *argv[], char *envp[]);
+extern void HideMenuBar(void);
+extern void ShowMenuBar(void);
+static void childDone(int sig);
+
+static NSPort *signalPort;
+static NSPort *returnPort;
+static NSPortMessage *signalMessage;
+static pid_t clientPID;
+static XServer *oneXServer;
+static NSRect aquaMenuBarBox;
+
+
+@implementation XServer
+
+- (id)init
+{
+ self = [super init];
+ oneXServer = self;
+
+ serverLock = [[NSRecursiveLock alloc] init];
+ clientPID = 0;
+ sendServerEvents = NO;
+ serverVisible = NO;
+ rootlessMenuBarVisible = YES;
+ appQuitting = NO;
+ mouseState = 0;
+ eventWriteFD = quartzEventWriteFD;
+ windowClass = [NSWindow class];
+
+ // set up a port to safely send messages to main thread from server thread
+ signalPort = [[NSPort port] retain];
+ returnPort = [[NSPort port] retain];
+ signalMessage = [[NSPortMessage alloc] initWithSendPort:signalPort
+ receivePort:returnPort components:nil];
+
+ // set up receiving end
+ [signalPort setDelegate:self];
+ [[NSRunLoop currentRunLoop] addPort:signalPort
+ forMode:NSDefaultRunLoopMode];
+ [[NSRunLoop currentRunLoop] addPort:signalPort
+ forMode:NSModalPanelRunLoopMode];
+
+ return self;
+}
+
+- (NSApplicationTerminateReply)
+ applicationShouldTerminate:(NSApplication *)sender
+{
+ // Quit if the X server is not running
+ if ([serverLock tryLock]) {
+ appQuitting = YES;
+ if (clientPID != 0)
+ kill(clientPID, SIGINT);
+ return NSTerminateNow;
+ }
+
+ if (clientPID != 0 || !quartzStartClients) {
+ int but;
+
+ // Hide the X server and stop sending it events
+ [self hide];
+ sendServerEvents = NO;
+
+ but = NSRunAlertPanel(NSLocalizedString(@"Quit X server?",@""),
+ NSLocalizedString(@"Quitting the X server will terminate any running X Window System programs.",@""),
+ NSLocalizedString(@"Quit",@""),
+ NSLocalizedString(@"Cancel",@""),
+ nil);
+
+ switch (but) {
+ case NSAlertDefaultReturn: // quit
+ break;
+ case NSAlertAlternateReturn: // cancel
+ sendServerEvents = YES;
+ return NSTerminateCancel;
+ }
+ }
+
+ appQuitting = YES;
+ if (clientPID != 0)
+ kill(clientPID, SIGINT);
+ [self killServer];
+ return NSTerminateNow;
+}
+
+// Ensure that everything has quit cleanly
+- (void)applicationWillTerminate:(NSNotification *)aNotification
+{
+ // Make sure the client process has finished
+ if (clientPID != 0) {
+ NSLog(@"Waiting on client process...");
+ sleep(2);
+
+ // If the client process hasn't finished yet, kill it off
+ if (clientPID != 0) {
+ int clientStatus;
+ NSLog(@"Killing client process...");
+ killpg(clientPID, SIGKILL);
+ waitpid(clientPID, &clientStatus, 0);
+ }
+ }
+
+ // Wait until the X server thread quits
+ [serverLock lock];
+}
+
+// returns YES when event was handled
+- (BOOL)translateEvent:(NSEvent *)anEvent
+{
+ xEvent xe;
+ static BOOL mouse1Pressed = NO;
+ BOOL onScreen;
+ NSEventType type;
+ unsigned int flags;
+
+ if (!sendServerEvents) {
+ return NO;
+ }
+
+ type = [anEvent type];
+ flags = [anEvent modifierFlags];
+
+ if (!quartzRootless) {
+ // Check for switch keypress
+ if ((type == NSKeyDown) && (![anEvent isARepeat]) &&
+ ([anEvent keyCode] == [Preferences keyCode]))
+ {
+ unsigned int switchFlags = [Preferences modifiers];
+
+ // Switch if all the switch modifiers are pressed, while none are
+ // pressed that should not be, except for caps lock.
+ if (((flags & switchFlags) == switchFlags) &&
+ ((flags & ~(switchFlags | NSAlphaShiftKeyMask)) == 0))
+ {
+ [self toggle];
+ return YES;
+ }
+ }
+
+ if (!serverVisible)
+ return NO;
+ }
+
+ memset(&xe, 0, sizeof(xe));
+
+ // If the mouse is not on the valid X display area,
+ // we don't send the X server key events.
+ onScreen = [self getMousePosition:&xe];
+
+ switch (type) {
+ case NSLeftMouseUp:
+ if (quartzRootless && !mouse1Pressed) {
+ // MouseUp after MouseDown in menu - ignore
+ return NO;
+ }
+ mouse1Pressed = NO;
+ xe.u.u.type = ButtonRelease;
+ xe.u.u.detail = 1;
+ break;
+ case NSLeftMouseDown:
+ if (quartzRootless &&
+ ! ([anEvent window] &&
+ [[anEvent window] isKindOfClass:windowClass])) {
+ // Click in non X window - ignore
+ return NO;
+ }
+ mouse1Pressed = YES;
+ xe.u.u.type = ButtonPress;
+ xe.u.u.detail = 1;
+ break;
+ case NSMouseMoved:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged:
+ xe.u.u.type = MotionNotify;
+ break;
+ case NSSystemDefined:
+ {
+ long hwButtons = [anEvent data2];
+
+ if (![anEvent subtype]==7)
+ return NO; // we only use multibutton mouse events
+ if (mouseState == hwButtons)
+ return NO; // ignore double events
+ mouseState = hwButtons;
+
+ xe.u.u.type = kXDarwinUpdateButtons;
+ xe.u.clientMessage.u.l.longs0 = [anEvent data1];
+ xe.u.clientMessage.u.l.longs1 =[anEvent data2];
+ break;
+ }
+ case NSScrollWheel:
+ xe.u.u.type = kXDarwinScrollWheel;
+ xe.u.clientMessage.u.s.shorts0 = [anEvent deltaY];
+ break;
+ case NSKeyDown:
+ case NSKeyUp:
+ if (!onScreen)
+ return NO;
+ if (type == NSKeyDown)
+ xe.u.u.type = KeyPress;
+ else
+ xe.u.u.type = KeyRelease;
+ xe.u.u.detail = [anEvent keyCode];
+ break;
+ case NSFlagsChanged:
+ xe.u.u.type = kXDarwinUpdateModifiers;
+ xe.u.clientMessage.u.l.longs0 = flags;
+ break;
+ case NSOtherMouseDown: // undocumented MouseDown
+ case NSOtherMouseUp: // undocumented MouseUp
+ // Hide these from AppKit to avoid its log messages
+ return YES;
+ default:
+ return NO;
+ }
+
+ [self sendXEvent:&xe];
+
+ // Rootless: Send first NSLeftMouseDown to windows and views so window
+ // ordering can be suppressed.
+ // Don't pass further events - they (incorrectly?) bring the window
+ // forward no matter what.
+ if (quartzRootless &&
+ (type == NSLeftMouseDown || type == NSLeftMouseUp) &&
+ [anEvent clickCount] == 1 &&
+ [[anEvent window] isKindOfClass:windowClass])
+ {
+ return NO;
+ }
+
+ return YES;
+}
+
+// Return mouse coordinates, inverting y coordinate.
+// For rootless mode, the menu bar is treated as not part of the usable
+// X display area and the cursor position is adjusted accordingly.
+// Returns YES if the cursor is not in the menu bar.
+- (BOOL)getMousePosition:(xEvent *)xe
+{
+ NSPoint pt = [NSEvent mouseLocation];
+
+ xe->u.keyButtonPointer.rootX = (int)(pt.x);
+
+ if (quartzRootless && NSMouseInRect(pt, aquaMenuBarBox, NO)) {
+ // mouse in menu bar - tell X11 that it's just below instead
+ xe->u.keyButtonPointer.rootY = aquaMenuBarHeight;
+ return NO;
+ } else {
+ xe->u.keyButtonPointer.rootY =
+ NSHeight([[NSScreen mainScreen] frame]) - (int)(pt.y);
+ return YES;
+ }
+}
+
+// Append a string to the given enviroment variable
++ (void)append:(NSString*)value toEnv:(NSString*)name
+{
+ setenv([name cString],
+ [[[NSString stringWithCString:getenv([name cString])]
+ stringByAppendingString:value] cString],1);
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+ // Block SIGPIPE
+ // SIGPIPE repeatably killed the (rootless) server when closing a
+ // dozen xterms in rapid succession. Those SIGPIPEs should have been
+ // sent to the X server thread, which ignores them, but somehow they
+ // ended up in this thread instead.
+ {
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ // pthread_sigmask not implemented yet
+ // pthread_sigmask(SIG_BLOCK, &set, NULL);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+ }
+
+ if (quartzRootless == -1) {
+ // The display mode was not set from the command line.
+ // Show mode pick panel?
+ if ([Preferences modeWindow]) {
+ if ([Preferences rootless])
+ [startRootlessButton setKeyEquivalent:@"\r"];
+ else
+ [startFullScreenButton setKeyEquivalent:@"\r"];
+ [modeWindow makeKeyAndOrderFront:nil];
+ } else {
+ // Otherwise use default mode
+ quartzRootless = [Preferences rootless];
+ [self startX];
+ }
+ } else {
+ [self startX];
+ }
+}
+
+// Start the X server thread and the client process
+- (void)startX
+{
+ NSDictionary *appDictionary;
+ NSString *appVersion;
+
+ [modeWindow close];
+
+ // Calculate the height of the menu bar so rootless mode can avoid it
+ if (quartzRootless) {
+ aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) -
+ NSMaxY([[NSScreen mainScreen] visibleFrame]) - 1;
+ aquaMenuBarBox =
+ NSMakeRect(0, NSMaxY([[NSScreen mainScreen] visibleFrame]) + 1,
+ NSWidth([[NSScreen mainScreen] frame]),
+ aquaMenuBarHeight);
+ }
+
+ // Write the XDarwin version to the console log
+ appDictionary = [[NSBundle mainBundle] infoDictionary];
+ appVersion = [appDictionary objectForKey:@"CFBundleShortVersionString"];
+ if (appVersion)
+ NSLog(@"\n%@", appVersion);
+ else
+ NSLog(@"No version");
+
+ // Start the X server thread
+ [NSThread detachNewThreadSelector:@selector(run) toTarget:self
+ withObject:nil];
+ sendServerEvents = YES;
+
+ // Start the X clients if started from GUI
+ if (quartzStartClients) {
+ [self startXClients];
+ }
+
+ if (quartzRootless) {
+ // There is no help window for rootless; just start
+ [helpWindow close];
+ helpWindow = nil;
+ if ([NSApp isActive])
+ [self sendShowHide:YES];
+ else
+ [self sendShowHide:NO];
+ } else {
+ // Show the X switch window if not using dock icon switching
+ if (![Preferences dockSwitch])
+ [switchWindow orderFront:nil];
+
+ if ([Preferences startupHelp]) {
+ // display the full screen mode help
+ [self sendShowHide:NO];
+ [helpWindow makeKeyAndOrderFront:nil];
+ } else {
+ // start running full screen and make sure X is visible
+ ShowMenuBar();
+ [self closeHelpAndShow:nil];
+ }
+ }
+}
+
+// Start the first X clients in a separate process
+- (BOOL)startXClients
+{
+ struct passwd *passwdUser;
+ NSString *shellPath, *dashShellName, *commandStr, *startXPath;
+ NSMutableString *safeStartXPath;
+ NSRange aRange;
+ NSBundle *thisBundle;
+ const char *shellPathStr, *newargv[3], *shellNameStr;
+ int fd[2], outFD, length, shellType, i;
+
+ // Register to catch the signal when the client processs finishes
+ signal(SIGCHLD, childDone);
+
+ // Get user's password database entry
+ passwdUser = getpwuid(getuid());
+
+ // Find the shell to use
+ if ([Preferences useDefaultShell])
+ shellPath = [NSString stringWithCString:passwdUser->pw_shell];
+ else
+ shellPath = [Preferences shellString];
+
+ dashShellName = [NSString stringWithFormat:@"-%@",
+ [shellPath lastPathComponent]];
+ shellPathStr = [shellPath cString];
+ shellNameStr = [[shellPath lastPathComponent] cString];
+
+ if (access(shellPathStr, X_OK)) {
+ NSLog(@"Shell %s is not valid!", shellPathStr);
+ return NO;
+ }
+
+ // Find the type of shell
+ for (i = 0; shellList[i].name; i++) {
+ if (!strcmp(shellNameStr, shellList[i].name))
+ break;
+ }
+ shellType = shellList[i].type;
+
+ newargv[0] = [dashShellName cString];
+ if (shellType == shell_Bourne) {
+ // Bourne shells need to be told they are interactive to make
+ // sure they read all their initialization files.
+ newargv[1] = "-i";
+ newargv[2] = NULL;
+ } else {
+ newargv[1] = NULL;
+ }
+
+ // Create a pipe to communicate with the X client process
+ NSAssert(pipe(fd) == 0, @"Could not create new pipe.");
+
+ // Open a file descriptor for writing to stdout and stderr
+ outFD = open("/dev/console", O_WRONLY, 0);
+ if (outFD == -1) {
+ outFD = open("/dev/null", O_WRONLY, 0);
+ NSAssert(outFD != -1, @"Could not open shell output.");
+ }
+
+ // Fork process to start X clients in user's default shell
+ // Sadly we can't use NSTask because we need to start a login shell.
+ // Login shells are started by passing "-" as the first character of
+ // argument 0. NSTask forces argument 0 to be the shell's name.
+ clientPID = vfork();
+ if (clientPID == 0) {
+
+ // Inside the new process:
+ if (fd[0] != STDIN_FILENO) {
+ dup2(fd[0], STDIN_FILENO); // Take stdin from pipe
+ close(fd[0]);
+ }
+ close(fd[1]); // Close write end of pipe
+ if (outFD == STDOUT_FILENO) { // Setup stdout and stderr
+ dup2(outFD, STDERR_FILENO);
+ } else if (outFD == STDERR_FILENO) {
+ dup2(outFD, STDOUT_FILENO);
+ } else {
+ dup2(outFD, STDERR_FILENO);
+ dup2(outFD, STDOUT_FILENO);
+ close(outFD);
+ }
+
+ // Setup environment
+ setenv("HOME", passwdUser->pw_dir, 1);
+ setenv("SHELL", shellPathStr, 1);
+ setenv("LOGNAME", passwdUser->pw_name, 1);
+ setenv("USER", passwdUser->pw_name, 1);
+ setenv("TERM", "unknown", 1);
+ if (chdir(passwdUser->pw_dir)) // Change to user's home dir
+ NSLog(@"Could not change to user's home directory.");
+
+ execv(shellPathStr, (char * const *)newargv); // Start user's shell
+
+ NSLog(@"Could not start X client process with errno = %i.", errno);
+ _exit(127);
+ }
+
+ // In parent process:
+ close(fd[0]); // Close read end of pipe
+ close(outFD); // Close output file descriptor
+
+ thisBundle = [NSBundle bundleForClass:[self class]];
+ startXPath = [thisBundle pathForResource:@"startXClients" ofType:nil];
+ if (!startXPath) {
+ NSLog(@"Could not find startXClients in application bundle!");
+ return NO;
+ }
+
+ // We will run the startXClients script with the path in single quotes
+ // in case there are problematic characters in the path. We still have
+ // to worry about there being single quotes in the path. So, replace
+ // all instances of the ' character in startXPath with '\''.
+ safeStartXPath = [NSMutableString stringWithString:startXPath];
+ aRange = NSMakeRange(0, [safeStartXPath length]);
+ while (aRange.length) {
+ aRange = [safeStartXPath rangeOfString:@"'" options:0 range:aRange];
+ if (!aRange.length)
+ break;
+ [safeStartXPath replaceCharactersInRange:aRange
+ withString:@"\'\\'\'"];
+ aRange.location += 4;
+ aRange.length = [safeStartXPath length] - aRange.location;
+ }
+
+ if ([Preferences addToPath]) {
+ commandStr = [NSString stringWithFormat:@"'%@' :%d %@\n",
+ safeStartXPath, [Preferences display],
+ [Preferences addToPathString]];
+ } else {
+ commandStr = [NSString stringWithFormat:@"'%@' :%d\n",
+ safeStartXPath, [Preferences display]];
+ }
+
+ length = [commandStr cStringLength];
+ if (write(fd[1], [commandStr cString], length) != length) {
+ NSLog(@"Write to X client process failed.");
+ return NO;
+ }
+
+ // Close the pipe so that shell will terminate when xinit quits
+ close(fd[1]);
+
+ return YES;
+}
+
+// Run the X server thread
+- (void)run
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [serverLock lock];
+ main(argcGlobal, argvGlobal, envpGlobal);
+ serverVisible = NO;
+ [pool release];
+ [serverLock unlock];
+ QuartzMessageMainThread(kQuartzServerDied, nil, 0);
+}
+
+// Full screen mode was picked in the mode pick panel
+- (IBAction)startFullScreen:(id)sender
+{
+ [Preferences setModeWindow:[startupModeButton intValue]];
+ [Preferences saveToDisk];
+ quartzRootless = FALSE;
+ [self startX];
+}
+
+// Rootless mode was picked in the mode pick panel
+- (IBAction)startRootless:(id)sender
+{
+ [Preferences setModeWindow:[startupModeButton intValue]];
+ [Preferences saveToDisk];
+ quartzRootless = TRUE;
+ [self startX];
+}
+
+// Close the help splash screen and show the X server
+- (IBAction)closeHelpAndShow:(id)sender
+{
+ if (sender) {
+ int helpVal = [startupHelpButton intValue];
+ [Preferences setStartupHelp:helpVal];
+ [Preferences saveToDisk];
+ }
+ [helpWindow close];
+ helpWindow = nil;
+
+ serverVisible = YES;
+ [self sendShowHide:YES];
+ [NSApp activateIgnoringOtherApps:YES];
+}
+
+// Show the X server when sent message from GUI
+- (IBAction)showAction:(id)sender
+{
+ if (sendServerEvents)
+ [self sendShowHide:YES];
+}
+
+// Show or hide the X server or menu bar in rootless mode
+- (void)toggle
+{
+ if (quartzRootless) {
+#if 0
+ // FIXME: Remove or add option to not dodge menubar
+ if (rootlessMenuBarVisible)
+ HideMenuBar();
+ else
+ ShowMenuBar();
+ rootlessMenuBarVisible = !rootlessMenuBarVisible;
+#endif
+ } else {
+ if (serverVisible)
+ [self hide];
+ else
+ [self show];
+ }
+}
+
+// Show the X server on screen
+- (void)show
+{
+ if (!serverVisible && sendServerEvents) {
+ [self sendShowHide:YES];
+ }
+}
+
+// Hide the X server from the screen
+- (void)hide
+{
+ if (serverVisible && sendServerEvents) {
+ [self sendShowHide:NO];
+ }
+}
+
+// Kill the X server thread
+- (void)killServer
+{
+ xEvent xe;
+
+ if (serverVisible)
+ [self hide];
+
+ xe.u.u.type = kXDarwinQuit;
+ [self sendXEvent:&xe];
+}
+
+// Tell the X server to show or hide itself.
+// This ignores the current X server visible state.
+//
+// In full screen mode, the order we do things is important and must be
+// preserved between the threads. X drawing operations have to be performed
+// in the X server thread. It appears that we have the additional
+// constraint that we must hide and show the menu bar in the main thread.
+//
+// To show the X server:
+// 1. Capture the displays. (Main thread)
+// 2. Hide the menu bar. (Must be in main thread)
+// 3. Send event to X server thread to redraw X screen.
+// 4. Redraw the X screen. (Must be in X server thread)
+//
+// To hide the X server:
+// 1. Send event to X server thread to stop drawing.
+// 2. Stop drawing to the X screen. (Must be in X server thread)
+// 3. Message main thread that drawing is stopped.
+// 4. If main thread still wants X server hidden:
+// a. Release the displays. (Main thread)
+// b. Unhide the menu bar. (Must be in main thread)
+// Otherwise we have already queued an event to start drawing again.
+//
+- (void)sendShowHide:(BOOL)show
+{
+ xEvent xe;
+
+ [self getMousePosition:&xe];
+
+ if (show) {
+ if (!quartzRootless) {
+ QuartzFSCapture();
+ HideMenuBar();
+ }
+ xe.u.u.type = kXDarwinShow;
+ [self sendXEvent:&xe];
+
+ // the mouse location will have moved; track it
+ xe.u.u.type = MotionNotify;
+ [self sendXEvent:&xe];
+
+ // inform the X server of the current modifier state
+ xe.u.u.type = kXDarwinUpdateModifiers;
+ xe.u.clientMessage.u.l.longs0 = [[NSApp currentEvent] modifierFlags];
+ [self sendXEvent:&xe];
+
+ // put the pasteboard into the X cut buffer
+ [self readPasteboard];
+ } else {
+ // put the X cut buffer on the pasteboard
+ [self writePasteboard];
+
+ xe.u.u.type = kXDarwinHide;
+ [self sendXEvent:&xe];
+ }
+
+ serverVisible = show;
+}
+
+// Tell the X server to read from the pasteboard into the X cut buffer
+- (void)readPasteboard
+{
+ xEvent xe;
+
+ xe.u.u.type = kXDarwinReadPasteboard;
+ [self sendXEvent:&xe];
+}
+
+// Tell the X server to write the X cut buffer into the pasteboard
+- (void)writePasteboard
+{
+ xEvent xe;
+
+ xe.u.u.type = kXDarwinWritePasteboard;
+ [self sendXEvent:&xe];
+}
+
+- (void)sendXEvent:(xEvent *)xe
+{
+ // This field should be filled in for every event
+ xe->u.keyButtonPointer.time = GetTimeInMillis();
+
+#if 0
+ // FIXME: Really?
+ if (quartzRootless &&
+ (ev->type == NSLeftMouseDown || ev->type == NSLeftMouseUp ||
+ (ev->type == NSSystemDefined && ev->data.compound.subType == 7)))
+ {
+ // mouse button event - send mouseMoved to this position too
+ // X gets confused if it gets a click that isn't at the last
+ // reported mouse position.
+ xEvent moveEvent = *ev;
+ xe.u.u.type = NSMouseMoved;
+ [self sendXEvent:&moveEvent];
+ }
+#endif
+
+ ENQUEUE(xe);
+}
+
+// Handle messages from the X server thread
+- (void)handlePortMessage:(NSPortMessage *)portMessage
+{
+ unsigned msg = [portMessage msgid];
+
+ switch(msg) {
+ case kQuartzServerHidden:
+ // Make sure the X server wasn't queued to be shown again while
+ // the hide was pending.
+ if (!quartzRootless && !serverVisible) {
+ QuartzFSRelease();
+ ShowMenuBar();
+ }
+
+ // FIXME: This hack is necessary (but not completely effective)
+ // since Mac OS X 10.0.2
+ [NSCursor unhide];
+ break;
+
+ case kQuartzServerDied:
+ sendServerEvents = NO;
+ if (!appQuitting) {
+ [NSApp terminate:nil]; // quit if we aren't already
+ }
+ break;
+
+ case kQuartzPostEvent:
+ {
+ const xEvent *xe = [[[portMessage components] lastObject] bytes];
+ ENQUEUE(xe);
+ break;
+ }
+
+ default:
+ NSLog(@"Unknown message from server thread.");
+ }
+}
+
+// Quit the X server when the X client process finishes
+- (void)clientProcessDone:(int)clientStatus
+{
+ if (WIFEXITED(clientStatus)) {
+ int exitStatus = WEXITSTATUS(clientStatus);
+ if (exitStatus != 0)
+ NSLog(@"X client process terminated with status %i.", exitStatus);
+ } else {
+ NSLog(@"X client process terminated abnormally.");
+ }
+
+ if (!appQuitting) {
+ [NSApp terminate:nil]; // quit if we aren't already
+ }
+}
+
+// Called when the user clicks the application icon,
+// but not when Cmd-Tab is used.
+// Rootless: Don't switch until applicationWillBecomeActive.
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication
+ hasVisibleWindows:(BOOL)flag
+{
+ if ([Preferences dockSwitch] && !quartzRootless) {
+ [self show];
+ }
+ return NO;
+}
+
+- (void)applicationWillResignActive:(NSNotification *)aNotification
+{
+ [self hide];
+}
+
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification
+{
+ if (quartzRootless)
+ [self show];
+}
+
+@end
+
+
+// Send a message to the main thread, which calls handlePortMessage in
+// response. Must only be called from the X server thread because
+// NSPort is not thread safe.
+void QuartzMessageMainThread(unsigned msg, void *data, unsigned length)
+{
+ if (msg == kQuartzPostEvent) {
+ NSData *eventData = [NSData dataWithBytes:data length:length];
+ NSArray *eventArray = [NSArray arrayWithObject:eventData];
+ NSPortMessage *newMessage =
+ [[NSPortMessage alloc]
+ initWithSendPort:signalPort
+ receivePort:returnPort components:eventArray];
+ [newMessage setMsgid:msg];
+ [newMessage sendBeforeDate:[NSDate distantPast]];
+ [newMessage release];
+ } else {
+ [signalMessage setMsgid:msg];
+ [signalMessage sendBeforeDate:[NSDate distantPast]];
+ }
+}
+
+// Handle SIGCHLD signals
+static void childDone(int sig)
+{
+ int clientStatus;
+
+ if (clientPID == 0)
+ return;
+
+ // Make sure it was the client task that finished
+ if (waitpid(clientPID, &clientStatus, WNOHANG) == clientPID) {
+ if (WIFSTOPPED(clientStatus))
+ return;
+ clientPID = 0;
+ [oneXServer clientProcessDone:clientStatus];
+ }
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XView.h b/xc/programs/Xserver/hw/darwin/quartz/XView.h
new file mode 100644
index 000000000..01f5b04b4
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XView.h
@@ -0,0 +1,42 @@
+/*
+ * NSView subclass for Mac OS X rootless X server
+ *
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XView.h,v 1.2 2002/07/15 19:58:31 torrey Exp $ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface XView : NSQuickDrawView
+
+- (BOOL)isFlipped;
+- (BOOL)isOpaque;
+- (BOOL)acceptsFirstResponder;
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;
+- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent;
+
+- (void)mouseDown:(NSEvent *)anEvent;
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz/XView.m b/xc/programs/Xserver/hw/darwin/quartz/XView.m
new file mode 100644
index 000000000..5146ff185
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/XView.m
@@ -0,0 +1,76 @@
+/*
+ * NSView subclass for Mac OS X rootless X server
+ *
+ * Each rootless window contains an instance of this class.
+ * This class handles events while drawing is handled by Carbon
+ * code in the rootless Aqua implementation.
+ *
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/XView.m,v 1.2 2002/07/15 19:58:31 torrey Exp $ */
+
+#import "XView.h"
+
+
+@implementation XView
+
+- (BOOL)isFlipped
+{
+ return NO;
+}
+
+- (BOOL)isOpaque
+{
+ return YES;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
+{
+ return YES;
+}
+
+- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent
+{
+ return YES;
+}
+
+- (void)mouseDown:(NSEvent *)anEvent
+{
+ // Only X is allowed to restack windows.
+ [NSApp preventWindowOrdering];
+ if (! [NSApp isActive]) {
+ [NSApp activateIgnoringOtherApps:YES];
+ // FIXME: Interleaving with other apps would be nice, but has issues.
+ [NSApp arrangeInFront:nil];
+ }
+ [[self nextResponder] mouseDown:anEvent];
+}
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz/aqua.h b/xc/programs/Xserver/hw/darwin/quartz/aqua.h
new file mode 100644
index 000000000..35adf2256
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/aqua.h
@@ -0,0 +1,53 @@
+/*
+ * Rootless implementation for the Mac OS X Aqua environment
+ */
+/*
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/aqua.h,v 1.2 2002/07/24 05:58:33 torrey Exp $ */
+
+#ifndef _AQUA_H
+#define _AQUA_H
+
+#include "picturestr.h"
+
+void AquaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
+
+#ifdef RENDER
+void
+AquaComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+#endif /* RENDER */
+
+
+/*
+ * AquaAlphaMask
+ * Bit mask for alpha channel with a particular number of bits per pixel (bpp)
+ */
+#define AquaAlphaMask(bpp) ((((Pixel) 1 << (bpp >> 2))-1) << \
+ (bpp - (bpp >> 2)))
+
+#endif /* _AQUA_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz/aquaCommon.h b/xc/programs/Xserver/hw/darwin/quartz/aquaCommon.h
new file mode 100644
index 000000000..a6618197a
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/aquaCommon.h
@@ -0,0 +1,56 @@
+/*
+ * Common internal definitions and code of the rootless implementation
+ * for the Mac OS X Aqua environment
+ */
+/*
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+
+#ifndef _AQUACOMMON_H
+#define _AQUACOMMON_H
+
+#include "quartzCommon.h"
+
+#ifdef __OBJC__
+#undef BOOL
+#import <Cocoa/Cocoa.h>
+#import "XView.h"
+#else
+typedef struct OpaqueNSWindow NSWindow;
+typedef struct OpaqueXView XView;
+#endif
+
+
+typedef struct {
+ NSWindow *window;
+ XView *view;
+ GrafPtr port;
+ CGContextRef context;
+ GWorldPtr rootGWorld;
+} AquaWindowRec;
+
+#define AQUA_WINREC(rw) ((AquaWindowRec *)rw)
+
+#endif /* _AQUACOMMON_H */ \ No newline at end of file
diff --git a/xc/programs/Xserver/hw/darwin/quartz/aquaPicture.c b/xc/programs/Xserver/hw/darwin/quartz/aquaPicture.c
new file mode 100644
index 000000000..1d5fa7d44
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/aquaPicture.c
@@ -0,0 +1,268 @@
+/*
+ * Support for RENDER extension with rootless Aqua
+ */
+/*
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* This file is largely based on fbcompose.c and fbpict.c, which contain
+ * the following copyright:
+ *
+ * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ */
+ /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/aquaPicture.c,v 1.3 2002/09/28 00:00:03 torrey Exp $ */
+
+#ifdef RENDER
+
+#include "fb.h"
+#include "picturestr.h"
+#include "mipict.h"
+#include "fbpict.h"
+#include "aqua.h"
+
+# define mod(a,b) ((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
+
+
+// Replacement for fbStore_x8r8g8b8 that sets the Aqua alpha channel
+void
+AquaStore_x8r8g8b8 (FbCompositeOperand *op, CARD32 value)
+{
+ FbBits *line = op->u.drawable.line; CARD32 offset = op->u.drawable.offset;
+ ((CARD32 *)line)[offset >> 5] = (value & 0xffffff) | 0xff000000;
+}
+
+
+// Defined in fbcompose.c
+extern FbCombineFunc fbCombineFuncU[];
+extern FbCombineFunc fbCombineFuncC[];
+
+void
+AquaCompositeGeneral(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ FbCompositeOperand src[4],msk[4],dst[4],*pmsk;
+ FbCompositeOperand *srcPict, *srcAlpha;
+ FbCompositeOperand *dstPict, *dstAlpha;
+ FbCompositeOperand *mskPict = 0, *mskAlpha = 0;
+ FbCombineFunc f;
+ int w;
+
+ if (!fbBuildCompositeOperand (pSrc, src, xSrc, ySrc, TRUE, TRUE))
+ return;
+ if (!fbBuildCompositeOperand (pDst, dst, xDst, yDst, FALSE, TRUE))
+ return;
+
+ // Use Aqua operands for on screen picture formats
+ if (pDst->format == PICT_x8r8g8b8) {
+ dst[0].store = AquaStore_x8r8g8b8;
+ }
+
+ if (pSrc->alphaMap)
+ {
+ srcPict = &src[1];
+ srcAlpha = &src[2];
+ }
+ else
+ {
+ srcPict = &src[0];
+ srcAlpha = 0;
+ }
+ if (pDst->alphaMap)
+ {
+ dstPict = &dst[1];
+ dstAlpha = &dst[2];
+ }
+ else
+ {
+ dstPict = &dst[0];
+ dstAlpha = 0;
+ }
+ f = fbCombineFuncU[op];
+ if (pMask)
+ {
+ if (!fbBuildCompositeOperand (pMask, msk, xMask, yMask, TRUE, TRUE))
+ return;
+ pmsk = msk;
+ if (pMask->componentAlpha)
+ f = fbCombineFuncC[op];
+ if (pMask->alphaMap)
+ {
+ mskPict = &msk[1];
+ mskAlpha = &msk[2];
+ }
+ else
+ {
+ mskPict = &msk[0];
+ mskAlpha = 0;
+ }
+ }
+ else
+ pmsk = 0;
+ while (height--)
+ {
+ w = width;
+
+ while (w--)
+ {
+ (*f) (src, pmsk, dst);
+ (*src->over) (src);
+ (*dst->over) (dst);
+ if (pmsk)
+ (*pmsk->over) (pmsk);
+ }
+ (*src->down) (src);
+ (*dst->down) (dst);
+ if (pmsk)
+ (*pmsk->down) (pmsk);
+ }
+}
+
+
+void
+AquaComposite(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ RegionRec region;
+ int n;
+ BoxPtr pbox;
+ CompositeFunc func;
+ Bool srcRepeat = pSrc->repeat;
+ Bool maskRepeat = FALSE;
+ Bool maskAlphaMap = FALSE;
+ int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
+ int w, h, w_this, h_this;
+
+ xDst += pDst->pDrawable->x;
+ yDst += pDst->pDrawable->y;
+ xSrc += pSrc->pDrawable->x;
+ ySrc += pSrc->pDrawable->y;
+ if (pMask)
+ {
+ xMask += pMask->pDrawable->x;
+ yMask += pMask->pDrawable->y;
+ maskRepeat = pMask->repeat;
+ maskAlphaMap = pMask->alphaMap != 0;
+ }
+
+ if (!miComputeCompositeRegion (&region,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height))
+ return;
+
+ // To preserve the alpha channel we only use a special,
+ // non-optimzied compositor.
+ func = AquaCompositeGeneral;
+
+ n = REGION_NUM_RECTS (&region);
+ pbox = REGION_RECTS (&region);
+ while (n--)
+ {
+ h = pbox->y2 - pbox->y1;
+ y_src = pbox->y1 - yDst + ySrc;
+ y_msk = pbox->y1 - yDst + yMask;
+ y_dst = pbox->y1;
+ while (h)
+ {
+ h_this = h;
+ w = pbox->x2 - pbox->x1;
+ x_src = pbox->x1 - xDst + xSrc;
+ x_msk = pbox->x1 - xDst + xMask;
+ x_dst = pbox->x1;
+ if (maskRepeat)
+ {
+ y_msk = mod (y_msk, pMask->pDrawable->height);
+ if (h_this > pMask->pDrawable->height - y_msk)
+ h_this = pMask->pDrawable->height - y_msk;
+ }
+ if (srcRepeat)
+ {
+ y_src = mod (y_src, pSrc->pDrawable->height);
+ if (h_this > pSrc->pDrawable->height - y_src)
+ h_this = pSrc->pDrawable->height - y_src;
+ }
+ while (w)
+ {
+ w_this = w;
+ if (maskRepeat)
+ {
+ x_msk = mod (x_msk, pMask->pDrawable->width);
+ if (w_this > pMask->pDrawable->width - x_msk)
+ w_this = pMask->pDrawable->width - x_msk;
+ }
+ if (srcRepeat)
+ {
+ x_src = mod (x_src, pSrc->pDrawable->width);
+ if (w_this > pSrc->pDrawable->width - x_src)
+ w_this = pSrc->pDrawable->width - x_src;
+ }
+ (*func) (op, pSrc, pMask, pDst,
+ x_src, y_src, x_msk, y_msk, x_dst, y_dst,
+ w_this, h_this);
+ w -= w_this;
+ x_src += w_this;
+ x_msk += w_this;
+ x_dst += w_this;
+ }
+ h -= h_this;
+ y_src += h_this;
+ y_msk += h_this;
+ y_dst += h_this;
+ }
+ pbox++;
+ }
+ REGION_UNINIT (pDst->pDrawable->pScreen, &region);
+}
+
+#endif /* RENDER */
diff --git a/xc/programs/Xserver/hw/darwin/quartz/aquaWindow.c b/xc/programs/Xserver/hw/darwin/quartz/aquaWindow.c
new file mode 100644
index 000000000..8addd5e1b
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/aquaWindow.c
@@ -0,0 +1,171 @@
+/*
+ * Specialized window functions for rootless Aqua
+ */
+/*
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* Portions of this file are based on fbwindow.c, which contains the
+ * following copyright:
+ *
+ * Copyright © 1998 Keith Packard
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/aquaWindow.c,v 1.1 2002/07/24 05:58:33 torrey Exp $ */
+
+#include "fb.h"
+#include "aqua.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+/*
+ * AquaFillRegionTiled
+ * Fill using a tile while leaving the alpha channel untouched.
+ * Based on fbfillRegionTiled.
+ */
+void
+AquaFillRegionTiled(
+ DrawablePtr pDrawable,
+ RegionPtr pRegion,
+ PixmapPtr pTile)
+{
+ FbBits *dst;
+ FbStride dstStride;
+ int dstBpp;
+ int dstXoff, dstYoff;
+ FbBits *tile;
+ FbStride tileStride;
+ int tileBpp;
+ int tileXoff, tileYoff; /* XXX assumed to be zero */
+ int tileWidth, tileHeight;
+ int n = REGION_NUM_RECTS(pRegion);
+ BoxPtr pbox = REGION_RECTS(pRegion);
+ int xRot = pDrawable->x;
+ int yRot = pDrawable->y;
+ FbBits planeMask;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ {
+ int index = pDrawable->pScreen->myNum;
+ if(&WindowTable[index]->drawable == pDrawable)
+ {
+ xRot -= panoramiXdataPtr[index].x;
+ yRot -= panoramiXdataPtr[index].y;
+ }
+ }
+#endif
+ fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
+ fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp,
+ tileXoff, tileYoff);
+ tileWidth = pTile->drawable.width;
+ tileHeight = pTile->drawable.height;
+ planeMask = FB_ALLONES & ~AquaAlphaMask(dstBpp);
+
+ while (n--)
+ {
+ fbTile (dst + (pbox->y1 + dstYoff) * dstStride,
+ dstStride,
+ (pbox->x1 + dstXoff) * dstBpp,
+ (pbox->x2 - pbox->x1) * dstBpp,
+ pbox->y2 - pbox->y1,
+ tile,
+ tileStride,
+ tileWidth * dstBpp,
+ tileHeight,
+ GXcopy,
+ planeMask,
+ dstBpp,
+ xRot * dstBpp,
+ yRot - pbox->y1);
+ pbox++;
+ }
+}
+
+
+/*
+ * AquaPaintWindow
+ * Paint the window while filling in the alpha channel with all on.
+ * We can't use fbPaintWindow because it zeros the alpha channel.
+ */
+void
+AquaPaintWindow(
+ WindowPtr pWin,
+ RegionPtr pRegion,
+ int what)
+{
+ switch (what) {
+ case PW_BACKGROUND:
+
+ switch (pWin->backgroundState) {
+ case None:
+ break;
+ case ParentRelative:
+ do {
+ pWin = pWin->parent;
+ } while (pWin->backgroundState == ParentRelative);
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
+ what);
+ break;
+ case BackgroundPixmap:
+ AquaFillRegionTiled (&pWin->drawable,
+ pRegion,
+ pWin->background.pixmap);
+ break;
+ case BackgroundPixel:
+ {
+ Pixel pixel = pWin->background.pixel |
+ AquaAlphaMask(pWin->drawable.bitsPerPixel);
+ fbFillRegionSolid (&pWin->drawable, pRegion, 0,
+ fbReplicatePixel (pixel,
+ pWin->drawable.bitsPerPixel));
+ break;
+ }
+ }
+ break;
+ case PW_BORDER:
+ if (pWin->borderIsPixel)
+ {
+ Pixel pixel = pWin->border.pixel |
+ AquaAlphaMask(pWin->drawable.bitsPerPixel);
+ fbFillRegionSolid (&pWin->drawable, pRegion, 0,
+ fbReplicatePixel (pixel,
+ pWin->drawable.bitsPerPixel));
+ }
+ else
+ {
+ WindowPtr pBgWin;
+ for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative;
+ pBgWin = pBgWin->parent);
+
+ AquaFillRegionTiled (&pBgWin->drawable,
+ pRegion,
+ pWin->border.pixmap);
+ }
+ break;
+ }
+ fbValidateDrawable (&pWin->drawable);
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/fakeBoxRec.h b/xc/programs/Xserver/hw/darwin/quartz/fakeBoxRec.h
new file mode 100644
index 000000000..1629cce4e
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/fakeBoxRec.h
@@ -0,0 +1,15 @@
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/fakeBoxRec.h,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#ifndef FAKEBOXREC_H
+#define FAKEBOXREC_H
+
+// This struct is byte-compatible with X11's BoxRec, for use in
+// code that can't include X headers.
+typedef struct _fakeBox {
+ short x1;
+ short y1;
+ short x2;
+ short y2;
+} fakeBoxRec;
+
+#endif
diff --git a/xc/programs/Xserver/hw/darwin/quartz/fullscreen.c b/xc/programs/Xserver/hw/darwin/quartz/fullscreen.c
new file mode 100644
index 000000000..46b562794
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/fullscreen.c
@@ -0,0 +1,444 @@
+/*
+ * Screen routines for full screen Quartz mode
+ *
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * TORREY T. LYONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Torrey T. Lyons shall not
+ * be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * Torrey T. Lyons.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/fullscreen.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#include "quartzCommon.h"
+#include "darwin.h"
+#include "colormapst.h"
+#include "scrnintstr.h"
+#include "micmap.h"
+
+// Full screen specific per screen storage structure
+typedef struct {
+ CGDirectDisplayID displayID;
+ CFDictionaryRef xDisplayMode;
+ CFDictionaryRef aquaDisplayMode;
+ CGDirectPaletteRef xPalette;
+ CGDirectPaletteRef aquaPalette;
+} QuartzFSScreenRec, *QuartzFSScreenPtr;
+
+#define FULLSCREEN_PRIV(pScreen) \
+ ((QuartzFSScreenPtr)pScreen->devPrivates[quartzFSScreenIndex].ptr)
+
+static int quartzFSScreenIndex;
+static CGDirectDisplayID *quartzDisplayList = NULL;
+static int quartzNumScreens = 0;
+static QuartzFSScreenPtr quartzScreens[MAXSCREENS];
+
+static int darwinCmapPrivateIndex = -1;
+static unsigned long darwinCmapGeneration = 0;
+
+#define CMAP_PRIV(pCmap) \
+ ((CGDirectPaletteRef) (pCmap)->devPrivates[darwinCmapPrivateIndex].ptr)
+
+/*
+ =============================================================================
+
+ Colormap handling
+
+ =============================================================================
+*/
+
+/*
+ * QuartzFSInitCmapPrivates
+ * Colormap privates may be allocated after the default colormap has
+ * already been created for some screens. This initialization procedure
+ * is called for each default colormap that is found.
+ */
+static Bool
+QuartzFSInitCmapPrivates(
+ ColormapPtr pCmap)
+{
+ return TRUE;
+}
+
+
+/*
+ * QuartzFSCreateColormap
+ * This is a callback from X after a new colormap is created.
+ * We allocate a new CoreGraphics pallete for each colormap.
+ */
+Bool
+QuartzFSCreateColormap(
+ ColormapPtr pCmap)
+{
+ CGDirectPaletteRef pallete;
+
+ // Allocate private storage for the hardware dependent colormap info.
+ if (darwinCmapGeneration != serverGeneration) {
+ if ((darwinCmapPrivateIndex =
+ AllocateColormapPrivateIndex(QuartzFSInitCmapPrivates)) < 0)
+ {
+ return FALSE;
+ }
+ darwinCmapGeneration = serverGeneration;
+ }
+
+ pallete = CGPaletteCreateDefaultColorPalette();
+ if (!pallete) return FALSE;
+
+ CMAP_PRIV(pCmap) = pallete;
+ return TRUE;
+}
+
+
+/*
+ * QuartzFSDestroyColormap
+ * This is called by DIX FreeColormap after it has uninstalled a colormap
+ * and notified all interested parties. We deallocated the corresponding
+ * CoreGraphics pallete.
+ */
+void
+QuartzFSDestroyColormap(
+ ColormapPtr pCmap)
+{
+ CGPaletteRelease( CMAP_PRIV(pCmap) );
+}
+
+
+/*
+ * QuartzFSInstallColormap
+ * Set the current CoreGraphics pallete to the pallete corresponding
+ * to the provided colormap.
+ */
+void
+QuartzFSInstallColormap(
+ ColormapPtr pCmap)
+{
+ CGDirectPaletteRef palette = CMAP_PRIV(pCmap);
+ ScreenPtr pScreen = pCmap->pScreen;
+ QuartzFSScreenPtr fsDisplayInfo = FULLSCREEN_PRIV(pScreen);
+
+ // Inform all interested parties that the map is being changed.
+ miInstallColormap(pCmap);
+
+ if (quartzServerVisible)
+ CGDisplaySetPalette(fsDisplayInfo->displayID, palette);
+
+ fsDisplayInfo->xPalette = palette;
+}
+
+
+/*
+ * QuartzFSStoreColors
+ * This is a callback from X to change the hardware colormap
+ * when using PsuedoColor in full screen mode.
+ */
+static void
+QuartzFSStoreColors(
+ ColormapPtr pCmap,
+ int numEntries,
+ xColorItem *pdefs)
+{
+ CGDirectPaletteRef palette = CMAP_PRIV(pCmap);
+ ScreenPtr pScreen = pCmap->pScreen;
+ QuartzFSScreenPtr fsDisplayInfo = FULLSCREEN_PRIV(pScreen);
+ CGDeviceColor color;
+ int i;
+
+ if (! palette)
+ return;
+
+ for (i = 0; i < numEntries; i++) {
+ color.red = pdefs[i].red / 65535.0;
+ color.green = pdefs[i].green / 65535.0;
+ color.blue = pdefs[i].blue / 65535.0;
+ CGPaletteSetColorAtIndex(palette, color, pdefs[i].pixel);
+ }
+
+ // Update hardware colormap
+ if (quartzServerVisible)
+ CGDisplaySetPalette(fsDisplayInfo->displayID, palette);
+}
+
+
+/*
+ =============================================================================
+
+ Screen initialization
+
+ =============================================================================
+*/
+
+/*
+ * QuartzFSDisplayInit
+ * Full screen specific initialization called from InitOutput.
+ */
+void QuartzFSDisplayInit(void)
+{
+ static unsigned long generation = 0;
+ CGDisplayCount quartzDisplayCount = 0;
+
+ // Allocate private storage for each screen's mode specific info
+ if (generation != serverGeneration) {
+ quartzFSScreenIndex = AllocateScreenPrivateIndex();
+ generation = serverGeneration;
+ }
+
+ // Find all the CoreGraphics displays
+ CGGetActiveDisplayList(0, NULL, &quartzDisplayCount);
+ quartzDisplayList = xalloc(quartzDisplayCount * sizeof(CGDirectDisplayID));
+ CGGetActiveDisplayList(quartzDisplayCount, quartzDisplayList,
+ &quartzDisplayCount);
+
+ darwinScreensFound = quartzDisplayCount;
+ atexit(QuartzFSRelease);
+}
+
+
+/*
+ * QuartzFSFindDisplayMode
+ * Find the appropriate display mode to use in full screen mode.
+ * If display mode is not the same as the current Aqua mode, switch
+ * to the new mode.
+ */
+static Bool QuartzFSFindDisplayMode(
+ QuartzFSScreenPtr fsDisplayInfo)
+{
+ CGDirectDisplayID cgID = fsDisplayInfo->displayID;
+ size_t height, width, bpp;
+ boolean_t exactMatch;
+
+ fsDisplayInfo->aquaDisplayMode = CGDisplayCurrentMode(cgID);
+
+ // If no user options, use current display mode
+ if (darwinDesiredWidth == 0 && darwinDesiredDepth == -1 &&
+ darwinDesiredRefresh == -1)
+ {
+ fsDisplayInfo->xDisplayMode = fsDisplayInfo->aquaDisplayMode;
+ return TRUE;
+ }
+
+ // If the user has no choice for size, use current
+ if (darwinDesiredWidth == 0) {
+ width = CGDisplayPixelsWide(cgID);
+ height = CGDisplayPixelsHigh(cgID);
+ } else {
+ width = darwinDesiredWidth;
+ height = darwinDesiredHeight;
+ }
+
+ switch (darwinDesiredDepth) {
+ case 0:
+ bpp = 8;
+ break;
+ case 1:
+ bpp = 16;
+ break;
+ case 2:
+ bpp = 32;
+ break;
+ default:
+ bpp = CGDisplayBitsPerPixel(cgID);
+ }
+
+ if (darwinDesiredRefresh == -1) {
+ fsDisplayInfo->xDisplayMode =
+ CGDisplayBestModeForParameters(cgID, bpp, width, height,
+ &exactMatch);
+ } else {
+ fsDisplayInfo->xDisplayMode =
+ CGDisplayBestModeForParametersAndRefreshRate(cgID, bpp,
+ width, height, darwinDesiredRefresh, &exactMatch);
+ }
+ if (!exactMatch) {
+ fsDisplayInfo->xDisplayMode = fsDisplayInfo->aquaDisplayMode;
+ return FALSE;
+ }
+
+ // Switch to the new display mode
+ CGDisplaySwitchToMode(cgID, fsDisplayInfo->xDisplayMode);
+ return TRUE;
+}
+
+
+/*
+ * QuartzFSAddScreen
+ * Do initialization of each screen for Quartz in full screen mode.
+ */
+Bool QuartzFSAddScreen(
+ int index,
+ ScreenPtr pScreen)
+{
+ DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
+ QuartzScreenPtr displayInfo = QUARTZ_PRIV(pScreen);
+ CGDirectDisplayID cgID = quartzDisplayList[index];
+ CGRect bounds;
+ QuartzFSScreenPtr fsDisplayInfo;
+
+ // Allocate space for private per screen fullscreen specific storage.
+ fsDisplayInfo = xalloc(sizeof(QuartzFSScreenRec));
+ FULLSCREEN_PRIV(pScreen) = fsDisplayInfo;
+
+ displayInfo->displayCount = 1;
+ displayInfo->displayIDs = xrealloc(displayInfo->displayIDs,
+ 1 * sizeof(CGDirectDisplayID));
+ displayInfo->displayIDs[0] = cgID;
+
+ fsDisplayInfo->displayID = cgID;
+ fsDisplayInfo->xDisplayMode = 0;
+ fsDisplayInfo->aquaDisplayMode = 0;
+ fsDisplayInfo->xPalette = 0;
+ fsDisplayInfo->aquaPalette = 0;
+
+ // Capture full screen because X doesn't like read-only framebuffer.
+ // We need to do this before we (potentially) switch the display mode.
+ CGDisplayCapture(cgID);
+
+ if (! QuartzFSFindDisplayMode(fsDisplayInfo)) {
+ ErrorF("Could not support specified display mode on screen %i.\n",
+ index);
+ xfree(fsDisplayInfo);
+ return FALSE;
+ }
+
+ // Don't need to flip y-coordinate as CoreGraphics treats (0, 0)
+ // as the top left of main screen.
+ bounds = CGDisplayBounds(cgID);
+ dfb->x = bounds.origin.x;
+ dfb->y = bounds.origin.y;
+ dfb->width = bounds.size.width;
+ dfb->height = bounds.size.height;
+ dfb->pitch = CGDisplayBytesPerRow(cgID);
+ dfb->bitsPerPixel = CGDisplayBitsPerPixel(cgID);
+ dfb->pixelInfo.componentCount = CGDisplaySamplesPerPixel(cgID);
+
+ if (dfb->bitsPerPixel == 8) {
+ if (CGDisplayCanSetPalette(cgID)) {
+ dfb->pixelInfo.pixelType = kIOCLUTPixels;
+ } else {
+ dfb->pixelInfo.pixelType = kIOFixedCLUTPixels;
+ }
+ dfb->pixelInfo.bitsPerComponent = 8;
+ dfb->colorBitsPerPixel = 8;
+ } else {
+ dfb->pixelInfo.pixelType = kIORGBDirectPixels;
+ dfb->pixelInfo.bitsPerComponent = CGDisplayBitsPerSample(cgID);
+ dfb->colorBitsPerPixel = (dfb->pixelInfo.componentCount *
+ dfb->pixelInfo.bitsPerComponent);
+ }
+
+ dfb->framebuffer = CGDisplayBaseAddress(cgID);
+
+ return TRUE;
+}
+
+
+/*
+ * QuartzFSSetupScreen
+ * Finalize full screen specific setup of each screen.
+ */
+Bool QuartzFSSetupScreen(
+ int index,
+ ScreenPtr pScreen)
+{
+ DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
+ QuartzFSScreenPtr fsDisplayInfo = FULLSCREEN_PRIV(pScreen);
+ CGDirectDisplayID cgID = fsDisplayInfo->displayID;
+
+ if (dfb->pixelInfo.pixelType == kIOCLUTPixels) {
+ // Initialize colormap handling
+ size_t aquaBpp;
+
+ // If Aqua is using 8 bits we need to keep track of its pallete.
+ CFNumberGetValue(CFDictionaryGetValue(fsDisplayInfo->aquaDisplayMode,
+ kCGDisplayBitsPerPixel), kCFNumberLongType, &aquaBpp);
+ if (aquaBpp <= 8)
+ fsDisplayInfo->aquaPalette = CGPaletteCreateWithDisplay(cgID);
+
+ pScreen->CreateColormap = QuartzFSCreateColormap;
+ pScreen->DestroyColormap = QuartzFSDestroyColormap;
+ pScreen->InstallColormap = QuartzFSInstallColormap;
+ pScreen->StoreColors = QuartzFSStoreColors;
+
+ }
+
+ quartzScreens[quartzNumScreens++] = fsDisplayInfo;
+ return TRUE;
+}
+
+
+/*
+ =============================================================================
+
+ Switching between Aqua and X
+
+ =============================================================================
+*/
+
+/*
+ * QuartzFSCapture
+ * Capture the screen so we can draw. Called directly from the main thread
+ * to synchronize with hiding the menubar.
+ */
+void QuartzFSCapture(void)
+{
+ int i;
+
+ if (quartzRootless) return;
+
+ for (i = 0; i < quartzNumScreens; i++) {
+ QuartzFSScreenPtr fsDisplayInfo = quartzScreens[i];
+ CGDirectDisplayID cgID = fsDisplayInfo->displayID;
+
+ if (!CGDisplayIsCaptured(cgID)) {
+ CGDisplayCapture(cgID);
+ fsDisplayInfo->aquaDisplayMode = CGDisplayCurrentMode(cgID);
+ if (fsDisplayInfo->xDisplayMode != fsDisplayInfo->aquaDisplayMode)
+ CGDisplaySwitchToMode(cgID, fsDisplayInfo->xDisplayMode);
+ if (fsDisplayInfo->xPalette)
+ CGDisplaySetPalette(cgID, fsDisplayInfo->xPalette);
+ }
+ }
+}
+
+
+/*
+ * QuartzFSRelease
+ * Release the screen so others can draw.
+ */
+void QuartzFSRelease(void)
+{
+ int i;
+
+ if (quartzRootless) return;
+
+ for (i = 0; i < quartzNumScreens; i++) {
+ QuartzFSScreenPtr fsDisplayInfo = quartzScreens[i];
+ CGDirectDisplayID cgID = fsDisplayInfo->displayID;
+
+ if (CGDisplayIsCaptured(cgID)) {
+ if (fsDisplayInfo->xDisplayMode != fsDisplayInfo->aquaDisplayMode)
+ CGDisplaySwitchToMode(cgID, fsDisplayInfo->aquaDisplayMode);
+ if (fsDisplayInfo->aquaPalette)
+ CGDisplaySetPalette(cgID, fsDisplayInfo->aquaPalette);
+ CGDisplayRelease(cgID);
+ }
+ }
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/fullscreen.h b/xc/programs/Xserver/hw/darwin/quartz/fullscreen.h
new file mode 100644
index 000000000..7cfacbae3
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/fullscreen.h
@@ -0,0 +1,33 @@
+/*
+ * External interface for full screen Quartz mode
+ *
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * TORREY T. LYONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Torrey T. Lyons shall not
+ * be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from
+ * Torrey T. Lyons.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/fullscreen.h,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+void QuartzFSDisplayInit(void);
+Bool QuartzFSAddScreen(int index, ScreenPtr pScreen);
+Bool QuartzFSSetupScreen(int index, ScreenPtr pScreen);
diff --git a/xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.c b/xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.c
new file mode 100644
index 000000000..e55aabd6f
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.c
@@ -0,0 +1,420 @@
+/*
+ * Minimal implementation of PanoramiX/Xinerama
+ *
+ * This is used in rootless mode where the underlying window server
+ * already provides an abstracted view of multiple screens as one
+ * large screen area.
+ *
+ * This code is largely based on panoramiX.c, which contains the
+ * following copyright notice:
+ */
+/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.c,v 1.2 2002/10/16 21:13:33 dawes Exp $ */
+
+#include "pseudoramiX.h"
+
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "window.h"
+#include "panoramiXproto.h"
+#include "globals.h"
+
+extern int ProcPanoramiXQueryVersion (ClientPtr client);
+
+static void PseudoramiXResetProc(ExtensionEntry *extEntry);
+
+static int ProcPseudoramiXQueryVersion(ClientPtr client);
+static int ProcPseudoramiXGetState(ClientPtr client);
+static int ProcPseudoramiXGetScreenCount(ClientPtr client);
+static int ProcPseudoramiXGetScreenSize(ClientPtr client);
+static int ProcPseudoramiXIsActive(ClientPtr client);
+static int ProcPseudoramiXQueryScreens(ClientPtr client);
+static int ProcPseudoramiXDispatch(ClientPtr client);
+
+static int SProcPseudoramiXQueryVersion(ClientPtr client);
+static int SProcPseudoramiXGetState(ClientPtr client);
+static int SProcPseudoramiXGetScreenCount(ClientPtr client);
+static int SProcPseudoramiXGetScreenSize(ClientPtr client);
+static int SProcPseudoramiXIsActive(ClientPtr client);
+static int SProcPseudoramiXQueryScreens(ClientPtr client);
+static int SProcPseudoramiXDispatch(ClientPtr client);
+
+
+typedef struct {
+ int x;
+ int y;
+ int w;
+ int h;
+} PseudoramiXScreenRec;
+
+static PseudoramiXScreenRec *pseudoramiXScreens = NULL;
+static int pseudoramiXScreensAllocated = 0;
+static int pseudoramiXNumScreens = 0;
+static unsigned long pseudoramiXGeneration = 0;
+
+
+// Add a PseudoramiX screen.
+// The rest of the X server will know nothing about this screen.
+// Can be called before or after extension init.
+// Screens must be re-added once per generation.
+void
+PseudoramiXAddScreen(int x, int y, int w, int h)
+{
+ PseudoramiXScreenRec *s;
+
+ if (noPseudoramiXExtension) return;
+
+ if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) {
+ pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1;
+ pseudoramiXScreens = xrealloc(pseudoramiXScreens,
+ pseudoramiXScreensAllocated *
+ sizeof(PseudoramiXScreenRec));
+ }
+
+ s = &pseudoramiXScreens[pseudoramiXNumScreens++];
+ s->x = x;
+ s->y = y;
+ s->w = w;
+ s->h = h;
+}
+
+
+// Initialize PseudoramiX.
+// Copied from PanoramiXExtensionInit
+void PseudoramiXExtensionInit(int argc, char *argv[])
+{
+ Bool success = FALSE;
+ ExtensionEntry *extEntry;
+
+ if (noPseudoramiXExtension) return;
+
+ if (pseudoramiXNumScreens == 1 || aquaNumScreens == 1) {
+ // Only one screen - disable Xinerama extension.
+ noPseudoramiXExtension = TRUE;
+ return;
+ }
+
+ // The server must not run the PanoramiX operations.
+ noPanoramiXExtension = TRUE;
+
+ if (pseudoramiXGeneration != serverGeneration) {
+ extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
+ ProcPseudoramiXDispatch,
+ SProcPseudoramiXDispatch,
+ PseudoramiXResetProc,
+ StandardMinorOpcode);
+ if (!extEntry) {
+ ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n");
+ } else {
+ pseudoramiXGeneration = serverGeneration;
+ success = TRUE;
+ }
+ }
+
+ if (!success) {
+ ErrorF("%s Extension (PseudoramiX) failed to initialize\n",
+ PANORAMIX_PROTOCOL_NAME);
+ return;
+ }
+}
+
+
+static void PseudoramiXResetProc(ExtensionEntry *extEntry)
+{
+ pseudoramiXNumScreens = 0;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXQueryVersion(ClientPtr client)
+{
+ return ProcPanoramiXQueryVersion(client);
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ WindowPtr pWin;
+ xPanoramiXGetStateReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPseudoramiXExtension;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
+ return client->noClientException;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.ScreenCount = pseudoramiXNumScreens;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.ScreenCount, n);
+ }
+ WriteToClient (client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
+ return client->noClientException;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ /* screen dimensions */
+ rep.width = pseudoramiXScreens[stuff->screen].w;
+ // was panoramiXdataPtr[stuff->screen].width;
+ rep.height = pseudoramiXScreens[stuff->screen].h;
+ // was panoramiXdataPtr[stuff->screen].height;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.width, n);
+ swaps (&rep.height, n);
+ }
+ WriteToClient (client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
+ return client->noClientException;
+}
+
+
+// was Xinerama
+static int ProcPseudoramiXIsActive(ClientPtr client)
+{
+ /* REQUEST(xXineramaIsActiveReq); */
+ xXineramaIsActiveReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPseudoramiXExtension;
+ if (client->swapped) {
+ register int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
+ return client->noClientException;
+}
+
+
+// was Xinerama
+static int ProcPseudoramiXQueryScreens(ClientPtr client)
+{
+ /* REQUEST(xXineramaQueryScreensReq); */
+ xXineramaQueryScreensReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens;
+ rep.length = rep.number * sz_XineramaScreenInfo >> 2;
+ if (client->swapped) {
+ register int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.number, n);
+ }
+ WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep);
+
+ if (!noPseudoramiXExtension) {
+ xXineramaScreenInfo scratch;
+ int i;
+
+ for(i = 0; i < pseudoramiXNumScreens; i++) {
+ scratch.x_org = pseudoramiXScreens[i].x;
+ scratch.y_org = pseudoramiXScreens[i].y;
+ scratch.width = pseudoramiXScreens[i].w;
+ scratch.height = pseudoramiXScreens[i].h;
+
+ if(client->swapped) {
+ register int n;
+ swaps (&scratch.x_org, n);
+ swaps (&scratch.y_org, n);
+ swaps (&scratch.width, n);
+ swaps (&scratch.height, n);
+ }
+ WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch);
+ }
+ }
+
+ return client->noClientException;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXDispatch (ClientPtr client)
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return ProcPseudoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return ProcPseudoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return ProcPseudoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return ProcPseudoramiXGetScreenSize(client);
+ case X_XineramaIsActive:
+ return ProcPseudoramiXIsActive(client);
+ case X_XineramaQueryScreens:
+ return ProcPseudoramiXQueryScreens(client);
+ }
+ return BadRequest;
+}
+
+
+
+static int
+SProcPseudoramiXQueryVersion (ClientPtr client)
+{
+ REQUEST(xPanoramiXQueryVersionReq);
+ register int n;
+
+ swaps(&stuff->length,n);
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ return ProcPseudoramiXQueryVersion(client);
+}
+
+static int
+SProcPseudoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ return ProcPseudoramiXGetState(client);
+}
+
+static int
+SProcPseudoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ return ProcPseudoramiXGetScreenCount(client);
+}
+
+static int
+SProcPseudoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ return ProcPseudoramiXGetScreenSize(client);
+}
+
+
+static int
+SProcPseudoramiXIsActive(ClientPtr client)
+{
+ REQUEST(xXineramaIsActiveReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+ return ProcPseudoramiXIsActive(client);
+}
+
+
+static int
+SProcPseudoramiXQueryScreens(ClientPtr client)
+{
+ REQUEST(xXineramaQueryScreensReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+ return ProcPseudoramiXQueryScreens(client);
+}
+
+
+static int
+SProcPseudoramiXDispatch (ClientPtr client)
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return SProcPseudoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return SProcPseudoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return SProcPseudoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return SProcPseudoramiXGetScreenSize(client);
+ case X_XineramaIsActive:
+ return SProcPseudoramiXIsActive(client);
+ case X_XineramaQueryScreens:
+ return SProcPseudoramiXQueryScreens(client);
+ }
+ return BadRequest;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.h b/xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.h
new file mode 100644
index 000000000..d0d596686
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.h
@@ -0,0 +1,10 @@
+/*
+ * Minimal implementation of PanoramiX/Xinerama
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/pseudoramiX.h,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+extern int noPseudoramiXExtension;
+extern int aquaNumScreens;
+
+void PseudoramiXAddScreen(int x, int y, int w, int h);
+void PseudoramiXExtensionInit(int argc, char *argv[]);
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartz.c b/xc/programs/Xserver/hw/darwin/quartz/quartz.c
new file mode 100644
index 000000000..5f24ad93c
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartz.c
@@ -0,0 +1,288 @@
+/**************************************************************
+ *
+ * Quartz-specific support for the Darwin X Server
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001 Greg Parker and Torrey T. Lyons.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartz.c,v 1.2 2002/10/12 00:32:45 torrey Exp $ */
+
+#include "quartzCommon.h"
+#include "quartz.h"
+#include "darwin.h"
+#include "quartzAudio.h"
+#include "quartzCursor.h"
+#include "fullscreen.h"
+#include "rootlessAqua.h"
+#include "pseudoramiX.h"
+
+// X headers
+#include "scrnintstr.h"
+#include "colormapst.h"
+
+// System headers
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
+
+// Shared global variables for Quartz modes
+int quartzEventWriteFD = -1;
+int quartzStartClients = 1;
+int quartzRootless = -1;
+int quartzUseSysBeep = 0;
+int quartzServerVisible = TRUE;
+int quartzScreenIndex = 0;
+int aquaMenuBarHeight = 0;
+int noPseudoramiXExtension = TRUE;
+int aquaNumScreens = 0;
+
+
+/*
+===========================================================================
+
+ Screen functions
+
+===========================================================================
+*/
+
+/*
+ * QuartzPMThread
+ * Handle power state notifications, FIXME
+ */
+#if 0
+static void *QuartzPMThread(void *arg)
+{
+ for (;;) {
+ mach_msg_return_t kr;
+ mach_msg_empty_rcv_t msg;
+
+ kr = mach_msg((mach_msg_header_t*) &msg, MACH_RCV_MSG, 0,
+ sizeof(msg), pmNotificationPort, 0, MACH_PORT_NULL);
+ kern_assert(kr);
+
+ // computer just woke up
+ if (msg.header.msgh_id == 1) {
+ if (quartzServerVisible) {
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (screenInfo.screens[i])
+ xf86SetRootClip(screenInfo.screens[i], true);
+ }
+ }
+ }
+ }
+ return NULL;
+}
+#endif
+
+
+/*
+ * QuartzAddScreen
+ * Do mode dependent initialization of each screen for Quartz.
+ */
+Bool QuartzAddScreen(
+ int index,
+ ScreenPtr pScreen)
+{
+ // allocate space for private per screen Quartz specific storage
+ QuartzScreenPtr displayInfo = xcalloc(sizeof(QuartzScreenRec), 1);
+ QUARTZ_PRIV(pScreen) = displayInfo;
+
+ // do full screen or rootless specific initialization
+ if (quartzRootless) {
+ return AquaAddScreen(index, pScreen);
+ } else {
+ return QuartzFSAddScreen(index, pScreen);
+ }
+}
+
+
+/*
+ * QuartzSetupScreen
+ * Finalize mode specific setup of each screen.
+ */
+Bool QuartzSetupScreen(
+ int index,
+ ScreenPtr pScreen)
+{
+ // do full screen or rootless specific setup
+ if (quartzRootless) {
+ if (! AquaSetupScreen(index, pScreen))
+ return FALSE;
+ } else {
+ if (! QuartzFSSetupScreen(index, pScreen))
+ return FALSE;
+ }
+
+ // setup cursor support
+ if (! QuartzInitCursor(pScreen))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * QuartzInitOutput
+ * Quartz display initialization.
+ */
+void QuartzInitOutput(
+ int argc,
+ char **argv )
+{
+ static unsigned long generation = 0;
+
+ // Allocate private storage for each screen's Quartz specific info
+ if (generation != serverGeneration) {
+ quartzScreenIndex = AllocateScreenPrivateIndex();
+ generation = serverGeneration;
+ }
+
+ if (serverGeneration == 0) {
+ QuartzAudioInit();
+ }
+
+ if (quartzRootless) {
+ ErrorF("Display mode: Rootless Quartz\n");
+ AquaDisplayInit();
+ } else {
+ ErrorF("Display mode: Full screen Quartz\n");
+ QuartzFSDisplayInit();
+ }
+
+ // Init PseudoramiX implementation of Xinerama.
+ // This should be in InitExtensions, but that causes link errors
+ // for servers that don't link in pseudoramiX.c.
+ if (!noPseudoramiXExtension) {
+ PseudoramiXExtensionInit(argc, argv);
+ }
+}
+
+
+/*
+ * QuartzShow
+ * Show the X server on screen. Does nothing if already shown.
+ * Restore the X clip regions the X server cursor state.
+ */
+void QuartzShow(
+ int x, // cursor location
+ int y )
+{
+ int i;
+
+ if (!quartzServerVisible) {
+ quartzServerVisible = TRUE;
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (screenInfo.screens[i]) {
+ QuartzResumeXCursor(screenInfo.screens[i], x, y);
+ if (!quartzRootless)
+ xf86SetRootClip(screenInfo.screens[i], TRUE);
+ }
+ }
+ }
+}
+
+
+/*
+ * QuartzHide
+ * Remove the X server display from the screen. Does nothing if already
+ * hidden. Set X clip regions to prevent drawing, and restore the Aqua
+ * cursor.
+ */
+void QuartzHide(void)
+{
+ int i;
+
+ if (quartzServerVisible) {
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (screenInfo.screens[i]) {
+ QuartzSuspendXCursor(screenInfo.screens[i]);
+ if (!quartzRootless)
+ xf86SetRootClip(screenInfo.screens[i], FALSE);
+ }
+ }
+ }
+ quartzServerVisible = FALSE;
+ QuartzMessageMainThread(kQuartzServerHidden, NULL, 0);
+}
+
+
+/*
+ * QuartzProcessEvent
+ * Process Quartz specific events.
+ */
+void QuartzProcessEvent(
+ xEvent *xe)
+{
+ switch (xe->u.u.type) {
+
+ case kXDarwinShow:
+ QuartzShow(xe->u.keyButtonPointer.rootX,
+ xe->u.keyButtonPointer.rootY);
+ break;
+
+ case kXDarwinHide:
+ QuartzHide();
+ break;
+
+ case kXDarwinQuit:
+ GiveUp(0);
+ break;
+
+ case kXDarwinReadPasteboard:
+ QuartzReadPasteboard();
+ break;
+
+ case kXDarwinWritePasteboard:
+ QuartzWritePasteboard();
+ break;
+
+ default:
+ ErrorF("Unknown application defined event.\n");
+ }
+}
+
+
+/*
+ * QuartzGiveUp
+ * Cleanup before X server shutdown
+ * Release the screen and restore the Aqua cursor.
+ */
+void QuartzGiveUp(void)
+{
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (screenInfo.screens[i]) {
+ QuartzSuspendXCursor(screenInfo.screens[i]);
+ }
+ }
+ if (!quartzRootless)
+ QuartzFSRelease();
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartz.h b/xc/programs/Xserver/hw/darwin/quartz/quartz.h
new file mode 100644
index 000000000..e304591a4
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartz.h
@@ -0,0 +1,51 @@
+/*
+ * quartz.h
+ *
+ * External interface of the Quartz modes seen by the generic, mode
+ * independent parts of the Darwin X server.
+ */
+/*
+ * Copyright (c) 2001 Greg Parker and Torrey T. Lyons.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartz.h,v 1.2 2002/10/12 00:32:45 torrey Exp $ */
+
+#ifndef _QUARTZ_H
+#define _QUARTZ_H
+
+#include "screenint.h"
+#include "Xproto.h"
+#include "quartzPasteboard.h"
+
+int QuartzProcessArgument(int argc, char *argv[], int i);
+void QuartzInitOutput(int argc, char **argv);
+Bool QuartzAddScreen(int index, ScreenPtr pScreen);
+Bool QuartzSetupScreen(int index, ScreenPtr pScreen);
+void QuartzGiveUp(void);
+void QuartzHide(void);
+void QuartzShow(int x, int y);
+void QuartzProcessEvent(xEvent *xe);
+
+#endif
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzAudio.c b/xc/programs/Xserver/hw/darwin/quartz/quartzAudio.c
new file mode 100644
index 000000000..2dfb313b7
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzAudio.c
@@ -0,0 +1,342 @@
+//
+// QuartzAudio.m
+//
+// X Window bell support using CoreAudio or AppKit.
+// Greg Parker gparker@cs.stanford.edu 19 Feb 2001
+//
+// Info about sine wave sound playback:
+// CoreAudio code derived from macosx-dev posting by Tim Wood
+// http://www.omnigroup.com/mailman/archive/macosx-dev/2000-May/002004.html
+// Smoothing transitions between sounds
+// http://www.wam.umd.edu/~mphoenix/dss/dss.html
+//
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzAudio.c,v 1.1 2002/03/28 02:21:18 torrey Exp $ */
+
+#include "quartzCommon.h"
+#include "quartzAudio.h"
+
+#include <CoreAudio/CoreAudio.h>
+#include <pthread.h>
+
+#include "inputstr.h"
+#include "extensions/XI.h"
+
+void NSBeep();
+
+typedef struct QuartzAudioRec {
+ double frequency;
+ double amplitude;
+
+ UInt32 curFrame;
+ UInt32 remainingFrames;
+ UInt32 totalFrames;
+ UInt32 bytesPerFrame;
+ double sampleRate;
+ UInt32 fadeLength;
+
+ UInt32 bufferByteCount;
+ Boolean playing;
+ pthread_mutex_t lock;
+
+ // used to fade out interrupted sound and avoid 'pop'
+ double prevFrequency;
+ double prevAmplitude;
+ UInt32 prevFrame;
+} QuartzAudioRec;
+
+static AudioDeviceID quartzAudioDevice = kAudioDeviceUnknown;
+static QuartzAudioRec data;
+
+
+/*
+ * QuartzAudioEnvelope
+ * Fade sound in and out to avoid pop.
+ * Sounds with shorter duration will never reach full amplitude. Deal.
+ */
+static double QuartzAudioEnvelope(
+ UInt32 curFrame,
+ UInt32 totalFrames,
+ UInt32 fadeLength )
+{
+ double fadeFrames = min(fadeLength, totalFrames / 2);
+ if (fadeFrames < 1) return 0;
+
+ if (curFrame < fadeFrames) {
+ return curFrame / fadeFrames;
+ } else if (curFrame > totalFrames - fadeFrames) {
+ return (totalFrames-curFrame) / fadeFrames;
+ } else {
+ return 1.0;
+ }
+}
+
+
+/*
+ * QuartzFillBuffer
+ * Fill this buffer with data and update the data position.
+ * FIXME: this is ugly
+ */
+static void QuartzFillBuffer(
+ AudioBuffer *audiobuffer,
+ QuartzAudioRec *data )
+{
+ float *buffer, *b;
+ unsigned int frame, frameCount;
+ unsigned int bufferFrameCount;
+ float multiplier, v;
+ int i;
+
+ buffer = (float *)audiobuffer->mData;
+ bufferFrameCount = audiobuffer->mDataByteSize / data->bytesPerFrame;
+
+ frameCount = min(bufferFrameCount, data->remainingFrames);
+
+ // Fade out previous sine wave, if any.
+ b = buffer;
+ if (data->prevFrame) {
+ multiplier = 2*M_PI*(data->prevFrequency/data->sampleRate);
+ for (frame = 0; frame < data->fadeLength; frame++) {
+ v = data->prevAmplitude *
+ QuartzAudioEnvelope(frame+data->fadeLength,
+ 2*data->fadeLength,
+ data->fadeLength) *
+ sin(multiplier * (data->prevFrame+frame));
+ for (i = 0; i < audiobuffer->mNumberChannels; i++) {
+ *b++ = v;
+ }
+ }
+ // no more prev fade
+ data->prevFrame = 0;
+
+ // adjust for space eaten by prev fade
+ buffer += audiobuffer->mNumberChannels*frame;
+ bufferFrameCount -= frame;
+ frameCount = min(bufferFrameCount, data->remainingFrames);
+ }
+
+ // Write a sine wave with the specified frequency and amplitude
+ multiplier = 2*M_PI*(data->frequency/data->sampleRate);
+ for (frame = 0; frame < frameCount; frame++) {
+ v = data->amplitude *
+ QuartzAudioEnvelope(data->curFrame+frame, data->totalFrames,
+ data->fadeLength) *
+ sin(multiplier * (data->curFrame+frame));
+ for (i = 0; i < audiobuffer->mNumberChannels; i++) {
+ *b++ = v;
+ }
+ }
+
+ // Zero out the rest of the buffer, if any
+ memset(b, 0, sizeof(float) * audiobuffer->mNumberChannels *
+ (bufferFrameCount-frame));
+
+ data->curFrame += frameCount;
+ data->remainingFrames -= frameCount;
+ if (data->remainingFrames == 0) {
+ data->playing = FALSE;
+ data->curFrame = 0;
+ }
+}
+
+
+/*
+ * QuartzAudioIOProc
+ * Callback function for audio playback.
+ * FIXME: use inOutputTime to correct for skipping
+ */
+static OSStatus
+QuartzAudioIOProc(
+ AudioDeviceID inDevice,
+ const AudioTimeStamp *inNow,
+ const AudioBufferList *inInputData,
+ const AudioTimeStamp *inInputTime,
+ AudioBufferList *outOutputData,
+ const AudioTimeStamp *inOutputTime,
+ void *inClientData )
+{
+ QuartzAudioRec *data = (QuartzAudioRec *)inClientData;
+ int i;
+ Boolean wasPlaying;
+
+ pthread_mutex_lock(&data->lock);
+ wasPlaying = data->playing;
+ for (i = 0; i < outOutputData->mNumberBuffers; i++) {
+ if (data->playing) {
+ QuartzFillBuffer(outOutputData->mBuffers+i, data);
+ }
+ else {
+ memset(outOutputData->mBuffers[i].mData, 0,
+ outOutputData->mBuffers[i].mDataByteSize);
+ }
+ }
+ if (wasPlaying && !data->playing) {
+ OSStatus err;
+ err = AudioDeviceStop(inDevice, QuartzAudioIOProc);
+ }
+ pthread_mutex_unlock(&data->lock);
+ return 0;
+}
+
+
+/*
+ * QuartzCoreAudioBell
+ * Play a tone using the CoreAudio API
+ */
+static void QuartzCoreAudioBell(
+ int volume, // volume is % of max
+ int pitch, // pitch is Hz
+ int duration ) // duration is milliseconds
+{
+ if (quartzAudioDevice == kAudioDeviceUnknown) return;
+
+ pthread_mutex_lock(&data.lock);
+
+ // fade previous sound, if any
+ data.prevFrequency = data.frequency;
+ data.prevAmplitude = data.amplitude;
+ data.prevFrame = data.curFrame;
+
+ // set new sound
+ data.frequency = pitch;
+ data.amplitude = volume / 100.0;
+ data.curFrame = 0;
+ data.totalFrames = (int)(data.sampleRate * duration / 1000.0);
+ data.remainingFrames = data.totalFrames;
+
+ if (! data.playing) {
+ OSStatus status;
+ status = AudioDeviceStart(quartzAudioDevice, QuartzAudioIOProc);
+ if (status) {
+ ErrorF("QuartzAudioBell: AudioDeviceStart returned %d\n", status);
+ } else {
+ data.playing = TRUE;
+ }
+ }
+ pthread_mutex_unlock(&data.lock);
+}
+
+
+/*
+ * QuartzBell
+ * Ring the bell
+ */
+void QuartzBell(
+ int volume, // volume in percent of max
+ DeviceIntPtr pDevice,
+ pointer ctrl,
+ int class )
+{
+ int pitch; // pitch in Hz
+ int duration; // duration in milliseconds
+
+ if (class == BellFeedbackClass) {
+ pitch = ((BellCtrl*)ctrl)->pitch;
+ duration = ((BellCtrl*)ctrl)->duration;
+ } else if (class == KbdFeedbackClass) {
+ pitch = ((KeybdCtrl*)ctrl)->bell_pitch;
+ duration = ((KeybdCtrl*)ctrl)->bell_duration;
+ } else {
+ ErrorF("QuartzBell: bad bell class %d\n", class);
+ return;
+ }
+
+ if (quartzUseSysBeep) {
+ if (volume)
+ NSBeep();
+ } else {
+ QuartzCoreAudioBell(volume, pitch, duration);
+ }
+}
+
+
+/*
+ * QuartzAudioInit
+ * Prepare to play the bell with the CoreAudio API
+ */
+void QuartzAudioInit(void)
+{
+ UInt32 propertySize;
+ OSStatus status;
+ AudioDeviceID outputDevice;
+ AudioStreamBasicDescription outputStreamDescription;
+ double sampleRate;
+
+ // Get the default output device
+ propertySize = sizeof(outputDevice);
+ status = AudioHardwareGetProperty(
+ kAudioHardwarePropertyDefaultOutputDevice,
+ &propertySize, &outputDevice);
+ if (status) {
+ ErrorF("QuartzAudioInit: AudioHardwareGetProperty returned %d\n",
+ status);
+ return;
+ }
+ if (outputDevice == kAudioDeviceUnknown) {
+ ErrorF("QuartzAudioInit: No audio output devices available.\n");
+ return;
+ }
+
+ // Get the basic device description
+ propertySize = sizeof(outputStreamDescription);
+ status = AudioDeviceGetProperty(outputDevice, 0, FALSE,
+ kAudioDevicePropertyStreamFormat,
+ &propertySize, &outputStreamDescription);
+ if (status) {
+ ErrorF("QuartzAudioInit: GetProperty(stream format) returned %d\n",
+ status);
+ return;
+ }
+ sampleRate = outputStreamDescription.mSampleRate;
+
+ // Fill in the playback data
+ data.frequency = 0;
+ data.amplitude = 0;
+ data.curFrame = 0;
+ data.remainingFrames = 0;
+ data.bytesPerFrame = outputStreamDescription.mBytesPerFrame;
+ data.sampleRate = sampleRate;
+ // data.bufferByteCount = bufferByteCount;
+ data.playing = FALSE;
+ data.prevAmplitude = 0;
+ data.prevFrame = 0;
+ data.prevFrequency = 0;
+ data.fadeLength = data.sampleRate / 200;
+ pthread_mutex_init(&data.lock, NULL); // fixme error check
+
+ // fixme assert fadeLength<framesPerBuffer
+
+ // Prepare for playback
+ status = AudioDeviceAddIOProc(outputDevice, QuartzAudioIOProc, &data);
+ if (status) {
+ ErrorF("QuartzAudioInit: AddIOProc returned %d\n", status);
+ return;
+ }
+
+ // success!
+ quartzAudioDevice = outputDevice;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzAudio.h b/xc/programs/Xserver/hw/darwin/quartz/quartzAudio.h
new file mode 100644
index 000000000..1d213e36a
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzAudio.h
@@ -0,0 +1,41 @@
+//
+// QuartzAudio.h
+//
+// X Window bell support using CoreAudio or AppKit.
+// Greg Parker gparker@cs.stanford.edu 19 Feb 2001
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzAudio.h,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#ifndef _QUARTZAUDIO_H
+#define _QUARTZAUDIO_H
+
+#include "input.h"
+
+void QuartzAudioInit(void);
+void QuartzBell(int volume, DeviceIntPtr pDevice, pointer ctrl, int class);
+
+#endif
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzCocoa.m b/xc/programs/Xserver/hw/darwin/quartz/quartzCocoa.m
new file mode 100644
index 000000000..b24739184
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzCocoa.m
@@ -0,0 +1,148 @@
+/**************************************************************
+ *
+ * Quartz-specific support for the Darwin X Server
+ * that requires Cocoa and Objective-C.
+ *
+ * This file is separate from the parts of Quartz support
+ * that use X include files to avoid symbol collisions.
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001 Torrey T. Lyons and Greg Parker.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzCocoa.m,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#include <Cocoa/Cocoa.h>
+
+#import "Preferences.h"
+#include "quartzCommon.h"
+#include "pseudoramiX.h"
+
+extern void FatalError(const char *, ...);
+extern char *display;
+extern int noPanoramiXExtension;
+
+// Read the user preferences from the Cocoa front end
+void QuartzReadPreferences(void)
+{
+ char *fileString;
+
+ darwinFakeButtons = [Preferences fakeButtons];
+ darwinFakeMouse2Mask = [Preferences button2Mask];
+ darwinFakeMouse3Mask = [Preferences button3Mask];
+ quartzMouseAccelChange = [Preferences mouseAccelChange];
+ quartzUseSysBeep = [Preferences systemBeep];
+
+ // Rootless: use PseudoramiX not Xinerama (quartzRootless already set)
+ if (quartzRootless) {
+ noPanoramiXExtension = TRUE;
+ noPseudoramiXExtension = ![Preferences xinerama];
+ } else {
+ noPanoramiXExtension = ![Preferences xinerama];
+ noPseudoramiXExtension = TRUE;
+ }
+
+ if ([Preferences useKeymapFile]) {
+ fileString = (char *) [[Preferences keymapFile] lossyCString];
+ darwinKeymapFile = (char *) malloc(strlen(fileString)+1);
+ if (! darwinKeymapFile)
+ FatalError("malloc failed in QuartzReadPreferences()!\n");
+ strcpy(darwinKeymapFile, fileString);
+ }
+
+ display = (char *) malloc(8);
+ if (! display)
+ FatalError("malloc failed in QuartzReadPreferences()!\n");
+ snprintf(display, 8, "%i", [Preferences display]);
+
+ darwinDesiredDepth = [Preferences depth] - 1;
+}
+
+// Write text to the Mac OS X pasteboard.
+void QuartzWriteCocoaPasteboard(
+ char *text)
+{
+ NSPasteboard *pasteboard;
+ NSArray *pasteboardTypes;
+ NSString *string;
+
+ if (! text) return;
+ pasteboard = [NSPasteboard generalPasteboard];
+ if (! pasteboard) return;
+ string = [NSString stringWithCString:text];
+ if (! string) return;
+ pasteboardTypes = [NSArray arrayWithObject:NSStringPboardType];
+
+ // nil owner because we don't provide type translations
+ [pasteboard declareTypes:pasteboardTypes owner:nil];
+ [pasteboard setString:string forType:NSStringPboardType];
+}
+
+// Read text from the Mac OS X pasteboard and return it as a heap string.
+// The caller must free the string.
+char *QuartzReadCocoaPasteboard(void)
+{
+ NSPasteboard *pasteboard;
+ NSArray *pasteboardTypes;
+ NSString *existingType;
+ char *text = NULL;
+
+ pasteboardTypes = [NSArray arrayWithObject:NSStringPboardType];
+ pasteboard = [NSPasteboard generalPasteboard];
+ if (! pasteboard) return NULL;
+
+ existingType = [pasteboard availableTypeFromArray:pasteboardTypes];
+ if (existingType) {
+ NSString *string = [pasteboard stringForType:existingType];
+ char *buffer;
+
+ if (! string) return NULL;
+ buffer = (char *) [string lossyCString];
+ text = (char *) malloc(strlen(buffer)+1);
+ if (text)
+ strcpy(text, buffer);
+ }
+
+ return text;
+}
+
+// Return whether the screen should use a QuickDraw cursor
+int QuartzFSUseQDCursor(
+ int depth) // screen depth
+{
+ switch ([Preferences useQDCursor]) {
+ case qdCursor_Always:
+ return TRUE;
+ case qdCursor_Never:
+ return FALSE;
+ case qdCursor_Not8Bit:
+ if (depth > 8)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzCommon.h b/xc/programs/Xserver/hw/darwin/quartz/quartzCommon.h
new file mode 100644
index 000000000..dce37e001
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzCommon.h
@@ -0,0 +1,92 @@
+/*
+ * quartzCommon.h
+ *
+ * Common definitions used internally by all Quartz modes
+ *
+ * This file should be included before any X11 or IOKit headers
+ * so that it can avoid symbol conflicts.
+ *
+ * Copyright (c) 2001 Torrey T. Lyons and Greg Parker.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzCommon.h,v 1.4 2002/10/12 00:32:45 torrey Exp $ */
+
+#ifndef _QUARTZCOMMON_H
+#define _QUARTZCOMMON_H
+
+// QuickDraw in ApplicationServices has the following conflicts with
+// the basic X server headers. Use QD_<name> to use the QuickDraw
+// definition of any of these symbols, or the normal name for the
+// X11 definition.
+#define Cursor QD_Cursor
+#define WindowPtr QD_WindowPtr
+#define Picture QD_Picture
+#include <ApplicationServices/ApplicationServices.h>
+#undef Cursor
+#undef WindowPtr
+#undef Picture
+
+#include "quartzShared.h"
+
+// Quartz specific per screen storage structure
+typedef struct {
+ // List of CoreGraphics displays that this X11 screen covers.
+ // This is more than one CG display for video mirroring and
+ // rootless PseudoramiX mode.
+ // No CG display will be covered by more than one X11 screen.
+ int displayCount;
+ CGDirectDisplayID *displayIDs;
+} QuartzScreenRec, *QuartzScreenPtr;
+
+#define QUARTZ_PRIV(pScreen) \
+ ((QuartzScreenPtr)pScreen->devPrivates[quartzScreenIndex].ptr)
+
+// Data stored at startup for Cocoa front end
+extern int quartzEventWriteFD;
+extern int quartzStartClients;
+
+// User preferences used by Quartz modes
+extern int quartzRootless;
+extern int quartzUseSysBeep;
+
+// Other shared data
+extern int quartzServerVisible;
+extern int quartzScreenIndex;
+extern int aquaMenuBarHeight;
+
+void QuartzReadPreferences(void);
+void QuartzMessageMainThread(unsigned msg, void *data, unsigned length);
+void QuartzFSCapture(void);
+void QuartzFSRelease(void);
+int QuartzFSUseQDCursor(int depth);
+
+// Messages that can be sent to the main thread.
+enum {
+ kQuartzServerHidden,
+ kQuartzServerDied,
+ kQuartzPostEvent
+};
+
+#endif /* _QUARTZCOMMON_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzCursor.c b/xc/programs/Xserver/hw/darwin/quartz/quartzCursor.c
new file mode 100644
index 000000000..ddc2fb0ef
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzCursor.c
@@ -0,0 +1,620 @@
+/**************************************************************
+ *
+ * Support for using the Quartz Window Manager cursor
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001-2002 Torrey T. Lyons and Greg Parker.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzCursor.c,v 1.3 2002/10/16 17:39:18 torrey Exp $ */
+
+#include "quartzCommon.h"
+#include "quartzCursor.h"
+#include "darwin.h"
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "cursorstr.h"
+#include "mipointrst.h"
+#include "globals.h"
+
+// Size of the QuickDraw cursor
+#define CURSORWIDTH 16
+#define CURSORHEIGHT 16
+
+typedef struct {
+ int qdCursorMode;
+ int qdCursorVisible;
+ int useQDCursor;
+ QueryBestSizeProcPtr QueryBestSize;
+ miPointerSpriteFuncPtr spriteFuncs;
+} QuartzCursorScreenRec, *QuartzCursorScreenPtr;
+
+static int darwinCursorScreenIndex = -1;
+static unsigned long darwinCursorGeneration = 0;
+static CursorPtr quartzLatentCursor = NULL;
+static QD_Cursor gQDArrow; // QuickDraw arrow cursor
+
+#define CURSOR_PRIV(pScreen) \
+ ((QuartzCursorScreenPtr)pScreen->devPrivates[darwinCursorScreenIndex].ptr)
+
+#define HIDE_QD_CURSOR(pScreen, visible) \
+ if (visible) { \
+ int ix; \
+ for (ix = 0; ix < QUARTZ_PRIV(pScreen)->displayCount; ix++) { \
+ CGDisplayHideCursor(QUARTZ_PRIV(pScreen)->displayIDs[ix]); \
+ } \
+ visible = FALSE; \
+ } ((void)0)
+
+#define SHOW_QD_CURSOR(pScreen, visible) \
+ { \
+ int ix; \
+ for (ix = 0; ix < QUARTZ_PRIV(pScreen)->displayCount; ix++) { \
+ CGDisplayShowCursor(QUARTZ_PRIV(pScreen)->displayIDs[ix]); \
+ } \
+ visible = TRUE; \
+ } ((void)0)
+
+
+/*
+ * MakeQDCursor helpers: CTAB_ENTER, interleave
+ */
+
+// Add a color entry to a ctab
+#define CTAB_ENTER(ctab, index, r, g, b) \
+ ctab->ctTable[index].value = index; \
+ ctab->ctTable[index].rgb.red = r; \
+ ctab->ctTable[index].rgb.green = g; \
+ ctab->ctTable[index].rgb.blue = b
+
+// Make an unsigned short by interleaving the bits of bytes c1 and c2.
+// High bit of c1 is first; low bit of c2 is last.
+// Interleave is a built-in INTERCAL operator.
+static unsigned short
+interleave(
+ unsigned char c1,
+ unsigned char c2 )
+{
+ return
+ ((c1 & 0x80) << 8) | ((c2 & 0x80) << 7) |
+ ((c1 & 0x40) << 7) | ((c2 & 0x40) << 6) |
+ ((c1 & 0x20) << 6) | ((c2 & 0x20) << 5) |
+ ((c1 & 0x10) << 5) | ((c2 & 0x10) << 4) |
+ ((c1 & 0x08) << 4) | ((c2 & 0x08) << 3) |
+ ((c1 & 0x04) << 3) | ((c2 & 0x04) << 2) |
+ ((c1 & 0x02) << 2) | ((c2 & 0x02) << 1) |
+ ((c1 & 0x01) << 1) | ((c2 & 0x01) << 0) ;
+}
+
+/*
+ * MakeQDCursor
+ * Make a QuickDraw color cursor from the given X11 cursor.
+ * Warning: This code is nasty. Color cursors were meant to be read
+ * from resources; constructing the structures programmatically is messy.
+ */
+/*
+ QuickDraw cursor representation:
+ Our color cursor is a 2 bit per pixel pixmap.
+ Each pixel's bits are (source<<1 | mask) from the original X cursor pixel.
+ The cursor's color table maps the colors like this:
+ (2-bit value | X result | colortable | Mac result)
+ 00 | transparent | white | transparent (white outside mask)
+ 01 | back color | back color | back color
+ 10 | undefined | black | invert background (just for fun)
+ 11 | fore color | fore color | fore color
+*/
+static CCrsrHandle
+MakeQDCursor(
+ CursorPtr pCursor )
+{
+ CCrsrHandle result;
+ CCrsrPtr curs;
+ int i, w, h;
+ unsigned short rowMask;
+ PixMap *pix;
+ ColorTable *ctab;
+ unsigned short *image;
+
+ result = (CCrsrHandle) NewHandleClear(sizeof(CCrsr));
+ if (!result) return NULL;
+ HLock((Handle)result);
+ curs = *result;
+
+ // Initialize CCrsr
+ curs->crsrType = 0x8001; // 0x8000 = b&w, 0x8001 = color
+ curs->crsrMap = (PixMapHandle) NewHandleClear(sizeof(PixMap));
+ if (!curs->crsrMap) goto pixAllocFailed;
+ HLock((Handle)curs->crsrMap);
+ pix = *curs->crsrMap;
+ curs->crsrData = NULL; // raw cursor image data (set below)
+ curs->crsrXData = NULL; // QD's processed data
+ curs->crsrXValid = 0; // zero means QD must re-process cursor data
+ curs->crsrXHandle = NULL; // reserved
+ memset(curs->crsr1Data, 0, CURSORWIDTH*CURSORHEIGHT/8); // b&w data
+ memset(curs->crsrMask, 0, CURSORWIDTH*CURSORHEIGHT/8); // b&w & color mask
+ curs->crsrHotSpot.h = min(CURSORWIDTH, pCursor->bits->xhot); // hot spot
+ curs->crsrHotSpot.v = min(CURSORHEIGHT, pCursor->bits->yhot); // hot spot
+ curs->crsrXTable = 0; // reserved
+ curs->crsrID = GetCTSeed(); // unique ID from Color Manager
+
+ // Set the b&w data and mask
+ w = min(pCursor->bits->width, CURSORWIDTH);
+ h = min(pCursor->bits->height, CURSORHEIGHT);
+ rowMask = ~((1 << (CURSORWIDTH - w)) - 1);
+ for (i = 0; i < h; i++) {
+ curs->crsr1Data[i] = rowMask &
+ ((pCursor->bits->source[i*4]<<8) | pCursor->bits->source[i*4+1]);
+ curs->crsrMask[i] = rowMask &
+ ((pCursor->bits->mask[i*4]<<8) | pCursor->bits->mask[i*4+1]);
+ }
+
+ // Set the color data and mask
+ // crsrMap: defines bit depth and size and colortable only
+ pix->rowBytes = (CURSORWIDTH * 2 / 8) | 0x8000; // last bit on means PixMap
+ SetRect(&pix->bounds, 0, 0, CURSORWIDTH, CURSORHEIGHT); // see TN 1020
+ pix->pixelSize = 2;
+ pix->cmpCount = 1;
+ pix->cmpSize = 2;
+ // pix->pmTable set below
+
+ // crsrData is the pixel data. crsrMap's baseAddr is not used.
+ curs->crsrData = NewHandleClear(CURSORWIDTH*CURSORHEIGHT * 2 / 8);
+ if (!curs->crsrData) goto imageAllocFailed;
+ HLock((Handle)curs->crsrData);
+ image = (unsigned short *) *curs->crsrData;
+ // Pixel data is just 1-bit data and mask interleaved (see above)
+ for (i = 0; i < h; i++) {
+ unsigned char s, m;
+ s = pCursor->bits->source[i*4] & (rowMask >> 8);
+ m = pCursor->bits->mask[i*4] & (rowMask >> 8);
+ image[2*i] = interleave(s, m);
+ s = pCursor->bits->source[i*4+1] & (rowMask & 0x00ff);
+ m = pCursor->bits->mask[i*4+1] & (rowMask & 0x00ff);
+ image[2*i+1] = interleave(s, m);
+ }
+
+ // Build the color table (entries described above)
+ // NewPixMap allocates a color table handle.
+ pix->pmTable = (CTabHandle) NewHandleClear(sizeof(ColorTable) + 3
+ * sizeof(ColorSpec));
+ if (!pix->pmTable) goto ctabAllocFailed;
+ HLock((Handle)pix->pmTable);
+ ctab = *pix->pmTable;
+ ctab->ctSeed = GetCTSeed();
+ ctab->ctFlags = 0;
+ ctab->ctSize = 3; // color count - 1
+ CTAB_ENTER(ctab, 0, 0xffff, 0xffff, 0xffff);
+ CTAB_ENTER(ctab, 1, pCursor->backRed, pCursor->backGreen,
+ pCursor->backBlue);
+ CTAB_ENTER(ctab, 2, 0x0000, 0x0000, 0x0000);
+ CTAB_ENTER(ctab, 3, pCursor->foreRed, pCursor->foreGreen,
+ pCursor->foreBlue);
+
+ HUnlock((Handle)pix->pmTable); // ctab
+ HUnlock((Handle)curs->crsrData); // image data
+ HUnlock((Handle)curs->crsrMap); // pix
+ HUnlock((Handle)result); // cursor
+
+ return result;
+
+ // "What we have here is a failure to allocate"
+ctabAllocFailed:
+ HUnlock((Handle)curs->crsrData);
+ DisposeHandle((Handle)curs->crsrData);
+imageAllocFailed:
+ HUnlock((Handle)curs->crsrMap);
+ DisposeHandle((Handle)curs->crsrMap);
+pixAllocFailed:
+ HUnlock((Handle)result);
+ DisposeHandle((Handle)result);
+ return NULL;
+}
+
+
+/*
+ * FreeQDCursor
+ * Destroy a QuickDraw color cursor created with MakeQDCursor().
+ * The cursor must not currently be on screen.
+ */
+static void FreeQDCursor(CCrsrHandle cursHandle)
+{
+ CCrsrPtr curs;
+ PixMap *pix;
+
+ HLock((Handle)cursHandle);
+ curs = *cursHandle;
+ HLock((Handle)curs->crsrMap);
+ pix = *curs->crsrMap;
+ DisposeHandle((Handle)pix->pmTable);
+ HUnlock((Handle)curs->crsrMap);
+ DisposeHandle((Handle)curs->crsrMap);
+ DisposeHandle((Handle)curs->crsrData);
+ HUnlock((Handle)cursHandle);
+ DisposeHandle((Handle)cursHandle);
+}
+
+
+/*
+===========================================================================
+
+ Pointer sprite functions
+
+===========================================================================
+*/
+
+/*
+ * QuartzRealizeCursor
+ * Convert the X cursor representation to QuickDraw format if possible.
+ */
+Bool
+QuartzRealizeCursor(
+ ScreenPtr pScreen,
+ CursorPtr pCursor )
+{
+ CCrsrHandle qdCursor;
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ if(!pCursor || !pCursor->bits)
+ return FALSE;
+
+ // if the cursor is too big we use a software cursor
+ if ((pCursor->bits->height > CURSORHEIGHT) ||
+ (pCursor->bits->width > CURSORWIDTH) || !ScreenPriv->useQDCursor)
+ {
+ if (quartzRootless) {
+ // rootless can't use a software cursor
+ return TRUE;
+ } else {
+ return (*ScreenPriv->spriteFuncs->RealizeCursor)
+ (pScreen, pCursor);
+ }
+ }
+
+ // make new cursor image
+ qdCursor = MakeQDCursor(pCursor);
+ if (!qdCursor) return FALSE;
+
+ // save the result
+ pCursor->devPriv[pScreen->myNum] = (pointer) qdCursor;
+
+ return TRUE;
+}
+
+
+/*
+ * QuartzUnrealizeCursor
+ * Free the storage space associated with a realized cursor.
+ */
+Bool
+QuartzUnrealizeCursor(
+ ScreenPtr pScreen,
+ CursorPtr pCursor )
+{
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ if ((pCursor->bits->height > CURSORHEIGHT) ||
+ (pCursor->bits->width > CURSORWIDTH) || !ScreenPriv->useQDCursor)
+ {
+ if (quartzRootless) {
+ return TRUE;
+ } else {
+ return (*ScreenPriv->spriteFuncs->UnrealizeCursor)
+ (pScreen, pCursor);
+ }
+ } else {
+ FreeQDCursor((CCrsrHandle) pCursor->devPriv[pScreen->myNum]);
+ pCursor->devPriv[pScreen->myNum] = NULL;
+ return TRUE;
+ }
+}
+
+
+/*
+ * QuartzSetCursor
+ * Set the cursor sprite and position.
+ * Use QuickDraw cursor if possible.
+ */
+static void
+QuartzSetCursor(
+ ScreenPtr pScreen,
+ CursorPtr pCursor,
+ int x,
+ int y)
+{
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ quartzLatentCursor = pCursor;
+
+ // Don't touch Mac OS cursor if X is hidden!
+ if (!quartzServerVisible)
+ return;
+
+ if (!pCursor) {
+ // Remove the cursor completely.
+ HIDE_QD_CURSOR(pScreen, ScreenPriv->qdCursorVisible);
+ if (! ScreenPriv->qdCursorMode)
+ (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, 0, x, y);
+ }
+ else if ((pCursor->bits->height <= CURSORHEIGHT) &&
+ (pCursor->bits->width <= CURSORWIDTH) && ScreenPriv->useQDCursor)
+ {
+ // Cursor is small enough to use QuickDraw directly.
+ CCrsrHandle curs;
+
+ if (! ScreenPriv->qdCursorMode) // remove the X cursor
+ (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, 0, x, y);
+ ScreenPriv->qdCursorMode = TRUE;
+
+ curs = (CCrsrHandle) pCursor->devPriv[pScreen->myNum];
+ SetCCursor(curs);
+ SHOW_QD_CURSOR(pScreen, ScreenPriv->qdCursorVisible);
+ }
+ else if (quartzRootless) {
+ // Rootless can't use a software cursor, so we just use Mac OS arrow.
+ SetCursor(&gQDArrow);
+ SHOW_QD_CURSOR(pScreen, ScreenPriv->qdCursorVisible);
+ }
+ else {
+ // Cursor is too big for QuickDraw. Use X software cursor.
+ HIDE_QD_CURSOR(pScreen, ScreenPriv->qdCursorVisible);
+ ScreenPriv->qdCursorMode = FALSE;
+ (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, pCursor, x, y);
+ }
+}
+
+
+/*
+ * QuartzMoveCursor
+ * Move the cursor. This is a noop for QuickDraw.
+ */
+static void
+QuartzMoveCursor(
+ ScreenPtr pScreen,
+ int x,
+ int y)
+{
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ // only the X cursor needs to be explicitly moved
+ if (!ScreenPriv->qdCursorMode)
+ (*ScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y);
+}
+
+
+static miPointerSpriteFuncRec quartzSpriteFuncsRec = {
+ QuartzRealizeCursor,
+ QuartzUnrealizeCursor,
+ QuartzSetCursor,
+ QuartzMoveCursor
+};
+
+/*
+===========================================================================
+
+ Pointer screen functions
+
+===========================================================================
+*/
+
+/*
+ * QuartzCursorOffScreen
+ */
+static Bool QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
+{
+ return FALSE;
+}
+
+
+/*
+ * QuartzCrossScreen
+ */
+static void QuartzCrossScreen(ScreenPtr pScreen, Bool entering)
+{
+ return;
+}
+
+
+/*
+ * QuartzWarpCursor
+ * Change the cursor position without generating an event or motion history.
+ * The input coordinates (x,y) are in pScreen-local X11 coordinates.
+ *
+ */
+static void
+QuartzWarpCursor(
+ ScreenPtr pScreen,
+ int x,
+ int y)
+{
+ static int neverMoved = TRUE;
+
+ if (neverMoved) {
+ // Don't move the cursor the first time. This is the jump-to-center
+ // initialization, and it's annoying because we may still be in MacOS.
+ neverMoved = FALSE;
+ return;
+ }
+
+ if (quartzServerVisible) {
+ CGDisplayErr cgErr;
+ CGPoint cgPoint;
+ // Only need to do this for one display. Any display will do.
+ CGDirectDisplayID cgID = QUARTZ_PRIV(pScreen)->displayIDs[0];
+ CGRect cgRect = CGDisplayBounds(cgID);
+
+ // Convert (x,y) to CoreGraphics screen-local CG coordinates.
+ // This is necessary because the X11 screen and CG screen may not
+ // coincide. (e.g. X11 screen may be moved to dodge the menu bar)
+
+ // Make point in X11 global coordinates
+ cgPoint = CGPointMake(x + dixScreenOrigins[pScreen->myNum].x,
+ y + dixScreenOrigins[pScreen->myNum].y);
+ // Shift to CoreGraphics global screen coordinates
+ cgPoint.x += darwinMainScreenX;
+ cgPoint.y += darwinMainScreenY;
+ // Shift to CoreGraphics screen-local coordinates
+ cgPoint.x -= cgRect.origin.x;
+ cgPoint.y -= cgRect.origin.y;
+
+ cgErr = CGDisplayMoveCursorToPoint(cgID, cgPoint);
+ if (cgErr != CGDisplayNoErr) {
+ ErrorF("Could not set cursor position with error code 0x%x.\n",
+ cgErr);
+ }
+ }
+
+ miPointerWarpCursor(pScreen, x, y);
+}
+
+
+/*
+ * QuartzEnqueueEvent
+ * Enqueue an event from the X server thread. Most events are posted with
+ * DarwinEQEnqueue() by the main thread, but any events generated by the
+ * X server thread must be posted with this routine.
+ */
+static void QuartzEnqueueEvent(
+ xEvent *xe)
+{
+ // Convert back to global screen coordinates
+ xe->u.keyButtonPointer.rootX += darwinMainScreenX +
+ dixScreenOrigins[miPointerCurrentScreen()->myNum].x;
+ xe->u.keyButtonPointer.rootY += darwinMainScreenY +
+ dixScreenOrigins[miPointerCurrentScreen()->myNum].y;
+
+ QuartzMessageMainThread(kQuartzPostEvent, xe, sizeof(xEvent));
+}
+
+
+static miPointerScreenFuncRec quartzScreenFuncsRec = {
+ QuartzCursorOffScreen,
+ QuartzCrossScreen,
+ QuartzWarpCursor,
+ QuartzEnqueueEvent,
+ DarwinEQSwitchScreen
+};
+
+/*
+===========================================================================
+
+ Other screen functions
+
+===========================================================================
+*/
+
+/*
+ * QuartzCursorQueryBestSize
+ * Handle queries for best cursor size
+ */
+static void
+QuartzCursorQueryBestSize(
+ int class,
+ unsigned short *width,
+ unsigned short *height,
+ ScreenPtr pScreen)
+{
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ if (class == CursorShape) {
+ *width = CURSORWIDTH;
+ *height = CURSORHEIGHT;
+ } else {
+ (*ScreenPriv->QueryBestSize)(class, width, height, pScreen);
+ }
+}
+
+
+/*
+ * QuartzInitCursor
+ * Initialize cursor support
+ */
+Bool
+QuartzInitCursor(
+ ScreenPtr pScreen )
+{
+ QuartzCursorScreenPtr ScreenPriv;
+ miPointerScreenPtr PointPriv;
+ DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
+
+ // initialize software cursor handling (always needed as backup)
+ if (!miDCInitialize(pScreen, &quartzScreenFuncsRec)) {
+ return FALSE;
+ }
+
+ // allocate private storage for this screen's QuickDraw cursor info
+ if (darwinCursorGeneration != serverGeneration) {
+ if ((darwinCursorScreenIndex = AllocateScreenPrivateIndex()) < 0)
+ return FALSE;
+ darwinCursorGeneration = serverGeneration;
+ }
+
+ ScreenPriv = xcalloc( 1, sizeof(QuartzCursorScreenRec) );
+ if (!ScreenPriv) return FALSE;
+
+ CURSOR_PRIV(pScreen) = ScreenPriv;
+
+ // override some screen procedures
+ ScreenPriv->QueryBestSize = pScreen->QueryBestSize;
+ pScreen->QueryBestSize = QuartzCursorQueryBestSize;
+
+ // initialize QuickDraw cursor handling
+ GetQDGlobalsArrow(&gQDArrow);
+ PointPriv = (miPointerScreenPtr)
+ pScreen->devPrivates[miPointerScreenIndex].ptr;
+
+ ScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
+ PointPriv->spriteFuncs = &quartzSpriteFuncsRec;
+
+ if (!quartzRootless)
+ ScreenPriv->useQDCursor = QuartzFSUseQDCursor(dfb->colorBitsPerPixel);
+ else
+ ScreenPriv->useQDCursor = TRUE;
+ ScreenPriv->qdCursorMode = TRUE;
+ ScreenPriv->qdCursorVisible = TRUE;
+ return TRUE;
+}
+
+
+// X server is hiding. Restore the Aqua cursor.
+void QuartzSuspendXCursor(
+ ScreenPtr pScreen )
+{
+ QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen);
+
+ SetCursor(&gQDArrow);
+ SHOW_QD_CURSOR(pScreen, ScreenPriv->qdCursorVisible);
+}
+
+
+// X server is showing. Restore the X cursor.
+void QuartzResumeXCursor(
+ ScreenPtr pScreen,
+ int x,
+ int y )
+{
+ QuartzSetCursor(pScreen, quartzLatentCursor, x, y);
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzCursor.h b/xc/programs/Xserver/hw/darwin/quartz/quartzCursor.h
new file mode 100644
index 000000000..9710d4be2
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzCursor.h
@@ -0,0 +1,43 @@
+/*
+ * quartzCursor.h
+ *
+ * External interface for Quartz hardware cursor
+ */
+/*
+ * Copyright (c) 2001 Torrey T. Lyons and Greg Parker.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzCursor.h,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#ifndef QUARTZCURSOR_H
+#define QUARTZCURSOR_H
+
+#include "screenint.h"
+
+Bool QuartzInitCursor(ScreenPtr pScreen);
+void QuartzSuspendXCursor(ScreenPtr pScreen);
+void QuartzResumeXCursor(ScreenPtr pScreen, int x, int y);
+
+#endif
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.c b/xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.c
new file mode 100644
index 000000000..658832aa1
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.c
@@ -0,0 +1,150 @@
+/**************************************************************
+ * quartzPasteboard.c
+ *
+ * Aqua pasteboard <-> X cut buffer
+ * Greg Parker gparker@cs.stanford.edu March 8, 2001
+ **************************************************************/
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.c,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#include "quartzPasteboard.h"
+
+#include "Xatom.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "scrnintstr.h"
+#include "selection.h"
+#include "globals.h"
+
+extern Selection *CurrentSelections;
+extern int NumCurrentSelections;
+
+
+// Helper function to read the X11 cut buffer
+// FIXME: What about multiple screens? Currently, this reads the first
+// CUT_BUFFER0 from the first screen where the buffer content is a string.
+// Returns a string on the heap that the caller must free.
+// Returns NULL if there is no cut text or there is not enough memory.
+static char * QuartzReadCutBuffer(void)
+{
+ int i;
+ char *text = NULL;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ PropertyPtr pProp;
+
+ pProp = wUserProps (WindowTable[pScreen->myNum]);
+ while (pProp && pProp->propertyName != XA_CUT_BUFFER0) {
+ pProp = pProp->next;
+ }
+ if (! pProp) continue;
+ if (pProp->type != XA_STRING) continue;
+ if (pProp->format != 8) continue;
+
+ text = xalloc(1 + pProp->size);
+ if (! text) continue;
+ memcpy(text, pProp->data, pProp->size);
+ text[pProp->size] = '\0';
+ return text;
+ }
+
+ // didn't find any text
+ return NULL;
+}
+
+// Write X cut buffer to Mac OS X pasteboard
+// Called by ProcessInputEvents() in response to request from X server thread.
+void QuartzWritePasteboard(void)
+{
+ char *text;
+ text = QuartzReadCutBuffer();
+ if (text) {
+ QuartzWriteCocoaPasteboard(text);
+ free(text);
+ }
+}
+
+#define strequal(a, b) (0 == strcmp((a), (b)))
+
+// Read Mac OS X pasteboard into X cut buffer
+// Called by ProcessInputEvents() in response to request from X server thread.
+void QuartzReadPasteboard(void)
+{
+ char *oldText = QuartzReadCutBuffer();
+ char *text = QuartzReadCocoaPasteboard();
+
+ // Compare text with current cut buffer contents.
+ // Change the buffer if both exist and are different
+ // OR if there is new text but no old text.
+ // Otherwise, don't clear the selection unnecessarily.
+
+ if ((text && oldText && !strequal(text, oldText)) ||
+ (text && !oldText)) {
+ int scrn, sel;
+
+ for (scrn = 0; scrn < screenInfo.numScreens; scrn++) {
+ ScreenPtr pScreen = screenInfo.screens[scrn];
+ // Set the cut buffers on each screen
+ // fixme really on each screen?
+ ChangeWindowProperty(WindowTable[pScreen->myNum], XA_CUT_BUFFER0,
+ XA_STRING, 8, PropModeReplace,
+ strlen(text), (pointer)text, TRUE);
+ }
+
+ // Undo any current X selection (similar to code in dispatch.c)
+ // FIXME: what about secondary selection?
+ // FIXME: only touch first XA_PRIMARY selection?
+ sel = 0;
+ while ((sel < NumCurrentSelections) &&
+ CurrentSelections[sel].selection != XA_PRIMARY)
+ sel++;
+ if (sel < NumCurrentSelections) {
+ // Notify client if necessary
+ if (CurrentSelections[sel].client) {
+ xEvent event;
+
+ event.u.u.type = SelectionClear;
+ event.u.selectionClear.time = GetTimeInMillis();
+ event.u.selectionClear.window = CurrentSelections[sel].window;
+ event.u.selectionClear.atom = CurrentSelections[sel].selection;
+ TryClientEvents(CurrentSelections[sel].client, &event, 1,
+ NoEventMask, NoEventMask /*CantBeFiltered*/,
+ NullGrab);
+ }
+
+ // Erase it
+ // FIXME: need to erase .selection too? dispatch.c doesn't
+ CurrentSelections[sel].pWin = NullWindow;
+ CurrentSelections[sel].window = None;
+ CurrentSelections[sel].client = NullClient;
+ }
+ }
+
+ if (text) free(text);
+ if (oldText) free(oldText);
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.h b/xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.h
new file mode 100644
index 000000000..fef375493
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.h
@@ -0,0 +1,45 @@
+/*
+ QuartzPasteboard.h
+
+ Mac OS X pasteboard <-> X cut buffer
+ Greg Parker gparker@cs.stanford.edu March 8, 2001
+*/
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzPasteboard.h,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#ifndef _QUARTZPASTEBOARD_H
+#define _QUARTZPASTEBOARD_H
+
+// Aqua->X
+void QuartzReadPasteboard();
+char * QuartzReadCocoaPasteboard(void); // caller must free string
+
+// X->Aqua
+void QuartzWritePasteboard();
+void QuartzWriteCocoaPasteboard(char *text);
+
+#endif /* _QUARTZPASTEBOARD_H */ \ No newline at end of file
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzShared.h b/xc/programs/Xserver/hw/darwin/quartz/quartzShared.h
new file mode 100644
index 000000000..94c7417ee
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzShared.h
@@ -0,0 +1,57 @@
+/*
+ * quartzShared.h
+ *
+ * Shared definitions between the Darwin X Server and the Cocoa front end
+ *
+ * This file is included in all parts of the Darwin X Server and must not
+ * include any types defined in X11 or Mac OS X specific headers.
+ * Definitions that are internal to the Quartz modes or use Mac OS X
+ * specific types should be in quartzCommon.h instead of here.
+ */
+/*
+ * Copyright (c) 2001 Torrey T. Lyons and Greg Parker.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzShared.h,v 1.2 2002/10/12 00:32:45 torrey Exp $ */
+
+#ifndef _QUARTZSHARED_H
+#define _QUARTZSHARED_H
+
+// User preferences used by generic Darwin X server code
+extern int quartzMouseAccelChange;
+extern int darwinFakeButtons;
+extern int darwinFakeMouse2Mask;
+extern int darwinFakeMouse3Mask;
+extern char *darwinKeymapFile;
+extern unsigned int darwinDesiredWidth, darwinDesiredHeight;
+extern int darwinDesiredDepth;
+extern int darwinDesiredRefresh;
+
+// location of X11's (0,0) point in global screen coordinates
+extern int darwinMainScreenX;
+extern int darwinMainScreenY;
+
+#endif /* _QUARTZSHARED_H */
+
diff --git a/xc/programs/Xserver/hw/darwin/quartz/quartzStartup.c b/xc/programs/Xserver/hw/darwin/quartz/quartzStartup.c
new file mode 100644
index 000000000..9b210ac6e
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/quartzStartup.c
@@ -0,0 +1,139 @@
+/**************************************************************
+ *
+ * Startup code for the Quartz Darwin X Server
+ *
+ **************************************************************/
+/*
+ * Copyright (c) 2001 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/quartzStartup.c,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#include <fcntl.h>
+#include "quartzCommon.h"
+#include "darwin.h"
+#include "opaque.h"
+
+int NSApplicationMain(int argc, char *argv[]);
+
+char **envpGlobal; // argcGlobal and argvGlobal
+ // are from dix/globals.c
+
+/*
+ * DarwinHandleGUI
+ * This function is called first from main(). The first time
+ * it is called we start the Mac OS X front end. The front end
+ * will call main() again from another thread to run the X
+ * server. On the second call this function loads the user
+ * preferences set by the Mac OS X front end.
+ */
+void DarwinHandleGUI(
+ int argc,
+ char *argv[],
+ char *envp[] )
+{
+ static Bool been_here = FALSE;
+ int main_exit, i;
+ int fd[2];
+
+ if (been_here) {
+ QuartzReadPreferences();
+ return;
+ }
+ been_here = TRUE;
+
+ // Make a pipe to pass events
+ assert( pipe(fd) == 0 );
+ darwinEventFD = fd[0];
+ quartzEventWriteFD = fd[1];
+ fcntl(darwinEventFD, F_SETFL, O_NONBLOCK);
+
+ // Store command line arguments to pass back to main()
+ argcGlobal = argc;
+ argvGlobal = argv;
+ envpGlobal = envp;
+
+ // Determine if we need to start X clients
+ // and what display mode to use
+ quartzStartClients = 1;
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-nostartx")) {
+ quartzStartClients = 0;
+ } else if (!strcmp( argv[i], "-fullscreen")) {
+ quartzRootless = 0;
+ } else if (!strcmp( argv[i], "-rootless")) {
+ quartzRootless = 1;
+ }
+ }
+
+ quartz = TRUE;
+ main_exit = NSApplicationMain(argc, argv);
+ exit(main_exit);
+}
+
+int QuartzProcessArgument( int argc, char *argv[], int i )
+{
+ // fullscreen: CoreGraphics full-screen mode
+ // rootless: Cocoa rootless mode
+ // quartz: Default, either fullscreen or rootless
+
+ if ( !strcmp( argv[i], "-fullscreen" ) ) {
+ ErrorF( "Running full screen in parallel with Mac OS X Quartz window server.\n" );
+#ifdef QUARTZ_SAFETY_DELAY
+ ErrorF( "Quitting in %d seconds if no controller is found.\n",
+ QUARTZ_SAFETY_DELAY );
+#endif
+ return 1;
+ }
+
+ if ( !strcmp( argv[i], "-rootless" ) ) {
+ ErrorF( "Running rootless inside Mac OS X window server.\n" );
+#ifdef QUARTZ_SAFETY_DELAY
+ ErrorF( "Quitting in %d seconds if no controller is found.\n",
+ QUARTZ_SAFETY_DELAY );
+#endif
+ return 1;
+ }
+
+ if ( !strcmp( argv[i], "-quartz" ) ) {
+ ErrorF( "Running in parallel with Mac OS X Quartz window server.\n" );
+#ifdef QUARTZ_SAFETY_DELAY
+ ErrorF( "Quitting in %d seconds if no controller is found.\n",
+ QUARTZ_SAFETY_DELAY );
+#endif
+ return 1;
+ }
+
+ // The Mac OS X front end uses this argument, which we just ignore here.
+ if ( !strcmp( argv[i], "-nostartx" ) ) {
+ return 1;
+ }
+
+ // This command line arg is passed when launched from the Aqua GUI.
+ if ( !strncmp( argv[i], "-psn_", 5 ) ) {
+ return 1;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootless.h b/xc/programs/Xserver/hw/darwin/quartz/rootless.h
new file mode 100644
index 000000000..e2aad5a4c
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootless.h
@@ -0,0 +1,136 @@
+/*
+ * External interface to generic rootless mode
+ *
+ * Greg Parker gparker@cs.stanford.edu March 3, 2001
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootless.h,v 1.2 2002/08/28 06:41:26 torrey Exp $ */
+
+#ifndef _ROOTLESS_H
+#define _ROOTLESS_H
+
+#include "mi.h"
+#include "gcstruct.h"
+
+// RootlessFrameRec
+// Describes a single rootless window (aka frame).
+// The rootless mode keeps track of window position, and the
+// rootless implementation is responsible for the pixmap.
+// Multiple screens: all coordinates are SCREEN-LOCAL, not global.
+
+
+typedef struct RootlessFrameRec {
+ /* Data maintained by rootless mode */
+ /* position and size, including window border, in screen coordinates */
+ int x;
+ int y;
+ unsigned int w;
+ unsigned int h;
+ WindowPtr win; /* the top-level window drawn in this frame */
+ int isRoot; /* TRUE if this is the root window */
+
+ /* Data maintained by rootless implementation */
+ char *pixelData;
+ int depth; // color bits per pixel; depth <= bitsPerPixel
+ int bitsPerPixel;
+ int bytesPerRow;
+
+ void *devPrivate; /* for caller's use */
+} RootlessFrameRec, *RootlessFramePtr;
+
+
+// Create a new frame.
+// pUpper is the window above the new frame, or NULL if the new
+// frame will be on top.
+// pFrame is completely initialized. devPrivate is NULL
+// The pixmap must be valid when this is done.
+typedef void (*RootlessCreateFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, RootlessFramePtr pUpper);
+
+// Destroy a frame. Caller must free any private data and the pixmap.
+// All drawing is stopped and all updates are flushed before this is called.
+typedef void (*RootlessDestroyFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame);
+
+// Move a frame on screen.
+// The frame changes position and nothing else.
+// pFrame and pFrame->win already contain the information about the
+// new position. oldX and oldY are the old position.
+// All updates are flushed before this is called.
+// The pixmap may change during this function.
+typedef void (*RootlessMoveFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, int oldX, int oldY);
+
+// Change frame ordering (aka stacking, layering)
+// pFrame->win already has its new siblings.
+// pOldNext is the window that was below this one, or NULL if this was
+// at the bottom.
+// pNewNext is the window that is now below this one, or NULL if this is
+// now at the bottom.
+typedef void (*RootlessRestackFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RootlessFramePtr pOldNext, RootlessFramePtr pNewNext);
+
+// Change the frame's shape.
+// pNewShape is in frame-local coordinates.
+// Everything outside pNewShape is no longer part of the frame.
+// pNewShape is {0, 0, width, height} for a plain-shaped frame.
+typedef void (*RootlessReshapeFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, RegionPtr pNewShape);
+
+// Flush drawing updates to the screen.
+// pDamage contains all changed pixels.
+// pDamage is in frame-local coordinates.
+// pDamage is clipped to the frame bounds and the frame shape.
+typedef void (*RootlessUpdateRegionProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, RegionPtr pDamage);
+
+// Prepare a window for direct access to its backing buffer.
+typedef void (*RootlessStartDrawingProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame);
+
+// Stop access to a window's backing buffer.
+typedef void (*RootlessStopDrawingProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame);
+
+// Frame is about to resize.
+// The frame has its new position and size already.
+// postconditions:
+// The pixmap MUST point to a pixmap with the new size.
+// The pixmap data is undefined.
+// The old pixmap may be destroyed here.
+typedef void (*RootlessStartResizeFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY, unsigned int oldW, unsigned int oldH);
+
+// Frame is done resizing.
+// Destroy the old pixmap if you haven't already.
+typedef void (*RootlessFinishResizeFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY, unsigned int oldW, unsigned int oldH);
+
+
+// The callback function list.
+// Any of these may be NULL.
+typedef struct RootlessFrameProcs {
+ RootlessCreateFrameProc CreateFrame;
+ RootlessDestroyFrameProc DestroyFrame;
+
+ RootlessMoveFrameProc MoveFrame;
+ RootlessStartResizeFrameProc StartResizeFrame;
+ RootlessFinishResizeFrameProc FinishResizeFrame;
+ RootlessRestackFrameProc RestackFrame;
+ RootlessReshapeFrameProc ReshapeFrame;
+
+ RootlessUpdateRegionProc UpdateRegion;
+
+ RootlessStartDrawingProc StartDrawing;
+ RootlessStopDrawingProc StopDrawing;
+} RootlessFrameProcs;
+
+// Initialize rootless mode on the given screen.
+Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcs *procs);
+
+// Return the rootless frame for the given window or NULL if it's not framed
+RootlessFramePtr RootlessFrameForWindow(WindowPtr pWin);
+
+#endif /* _ROOTLESS_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessAqua.h b/xc/programs/Xserver/hw/darwin/quartz/rootlessAqua.h
new file mode 100644
index 000000000..c64005325
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessAqua.h
@@ -0,0 +1,15 @@
+/*
+ * Rootless setup for Aqua
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessAqua.h,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#ifndef _ROOTLESSAQUA_H
+#define _ROOTLESSAQUA_H
+
+Bool AquaAddScreen(int index, ScreenPtr pScreen);
+Bool AquaSetupScreen(int index, ScreenPtr pScreen);
+void AquaDisplayInit(void);
+
+#endif /* _ROOTLESSAQUA_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaGlue.c b/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaGlue.c
new file mode 100644
index 000000000..bebfb411b
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaGlue.c
@@ -0,0 +1,242 @@
+/*
+ * Generic rootless to Aqua specific glue code
+ *
+ * This code acts as a glue between the generic rootless X server code
+ * and the Aqua specific implementation, which includes definitions that
+ * conflict with stardard X types.
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessAquaGlue.c,v 1.4 2002/07/24 05:58:33 torrey Exp $ */
+
+#include "quartzCommon.h"
+#include "darwin.h"
+#include "rootlessAqua.h"
+#include "rootlessAquaImp.h"
+#include "rootless.h"
+#include "aqua.h"
+
+#include "regionstr.h"
+#include "scrnintstr.h"
+#include "picturestr.h"
+#include "globals.h" // dixScreenOrigins[]
+
+
+/////////////////////////////////////////
+// Rootless mode callback glue
+
+static void
+AquaGlueCreateFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RootlessFramePtr pUpper)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ pFrame->devPrivate = AquaNewWindow(pUpper ? pUpper->devPrivate : NULL,
+ pFrame->x + sx, pFrame->y + sy,
+ pFrame->w, pFrame->h,
+ pFrame->isRoot);
+}
+
+
+static void
+AquaGlueDestroyFrame(ScreenPtr pScreen, RootlessFramePtr pFrame)
+{
+ AquaDestroyWindow(pFrame->devPrivate);
+}
+
+
+static void
+AquaGlueMoveFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ AquaMoveWindow(pFrame->devPrivate, pFrame->x + sx, pFrame->y + sy);
+}
+
+
+static void
+AquaGlueStartResizeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ AquaStartResizeWindow(pFrame->devPrivate,
+ pFrame->x + sx, pFrame->y + sy, pFrame->w, pFrame->h);
+}
+
+static void
+AquaGlueFinishResizeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ AquaFinishResizeWindow(pFrame->devPrivate,
+ pFrame->x + sx, pFrame->y + sy,
+ pFrame->w, pFrame->h);
+}
+
+
+static void
+AquaGlueRestackFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RootlessFramePtr pOldPrev,
+ RootlessFramePtr pNewPrev)
+{
+ AquaRestackWindow(pFrame->devPrivate,
+ pNewPrev ? pNewPrev->devPrivate : NULL);
+}
+
+
+static void
+AquaGlueReshapeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RegionPtr pNewShape)
+{
+ BoxRec shapeBox = {0, 0, pFrame->w, pFrame->h};
+
+ // Don't correct for dixScreenOrigins here.
+ // pNewShape is in window-local coordinates.
+
+ if (pFrame->isRoot) return; // shouldn't happen; mi or dix covers this
+
+ REGION_INVERSE(pScreen, pNewShape, pNewShape, &shapeBox);
+ AquaReshapeWindow(pFrame->devPrivate,
+ (fakeBoxRec *) REGION_RECTS(pNewShape),
+ REGION_NUM_RECTS(pNewShape));
+}
+
+
+static void
+AquaGlueUpdateRegion(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RegionPtr pDamage)
+{
+ AquaUpdateRects(pFrame->devPrivate,
+ (fakeBoxRec *) REGION_RECTS(pDamage),
+ REGION_NUM_RECTS(pDamage));
+}
+
+
+static void
+AquaGlueStartDrawing(ScreenPtr pScreen, RootlessFramePtr pFrame)
+{
+ AquaStartDrawing(pFrame->devPrivate, &pFrame->pixelData,
+ &pFrame->bytesPerRow, &pFrame->depth,
+ &pFrame->bitsPerPixel);
+}
+
+static void
+AquaGlueStopDrawing(ScreenPtr pScreen, RootlessFramePtr pFrame)
+{
+ AquaStopDrawing(pFrame->devPrivate);
+}
+
+
+static RootlessFrameProcs aquaRootlessProcs = {
+ AquaGlueCreateFrame,
+ AquaGlueDestroyFrame,
+ AquaGlueMoveFrame,
+ AquaGlueStartResizeFrame,
+ AquaGlueFinishResizeFrame,
+ AquaGlueRestackFrame,
+ AquaGlueReshapeFrame,
+ AquaGlueUpdateRegion,
+ AquaGlueStartDrawing,
+ AquaGlueStopDrawing
+};
+
+
+///////////////////////////////////////
+// Rootless mode initialization.
+// Exported by rootlessAqua.h
+
+/*
+ * AquaDisplayInit
+ * Find all Aqua screens.
+ */
+void
+AquaDisplayInit(void)
+{
+ darwinScreensFound = AquaDisplayCount();
+}
+
+
+/*
+ * AquaAddScreen
+ * Init the framebuffer and record pixmap parameters for the screen.
+ */
+Bool
+AquaAddScreen(int index, ScreenPtr pScreen)
+{
+ DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
+ QuartzScreenPtr displayInfo = QUARTZ_PRIV(pScreen);
+ CGRect cgRect;
+ CGDisplayCount numDisplays;
+ CGDisplayCount allocatedDisplays = 0;
+ CGDirectDisplayID *displays = NULL;
+ CGDisplayErr cgErr;
+
+ dfb->pixelInfo.pixelType = kIORGBDirectPixels;
+ AquaScreenInit(index, &dfb->x, &dfb->y, &dfb->width, &dfb->height,
+ &dfb->pitch, &dfb->pixelInfo.bitsPerComponent,
+ &dfb->pixelInfo.componentCount, &dfb->bitsPerPixel);
+ dfb->colorBitsPerPixel = dfb->pixelInfo.bitsPerComponent *
+ dfb->pixelInfo.componentCount;
+
+ // No frame buffer - it's all in window pixmaps.
+ dfb->framebuffer = NULL; // malloc(dfb.pitch * dfb.height);
+
+ // Get all CoreGraphics displays covered by this X11 display.
+ cgRect = CGRectMake(dfb->x, dfb->y, dfb->width, dfb->height);
+ do {
+ cgErr = CGGetDisplaysWithRect(cgRect, 0, NULL, &numDisplays);
+ if (cgErr) break;
+ allocatedDisplays = numDisplays;
+ displays = xrealloc(displays,
+ numDisplays * sizeof(CGDirectDisplayID));
+ cgErr = CGGetDisplaysWithRect(cgRect, allocatedDisplays, displays,
+ &numDisplays);
+ if (cgErr != CGDisplayNoErr) break;
+ } while (numDisplays > allocatedDisplays);
+
+ if (cgErr != CGDisplayNoErr || numDisplays == 0) {
+ ErrorF("Could not find CGDirectDisplayID(s) for X11 screen %d: %dx%d @ %d,%d.\n",
+ index, dfb->width, dfb->height, dfb->x, dfb->y);
+ return FALSE;
+ }
+
+ // This X11 screen covers all CoreGraphics displays we just found.
+ // If there's more than one CG display, then video mirroring is on
+ // or PseudoramiX is on.
+ displayInfo->displayCount = allocatedDisplays;
+ displayInfo->displayIDs = displays;
+
+ return TRUE;
+}
+
+
+/*
+ * AquaSetupScreen
+ * Setup the screen for rootless access.
+ */
+Bool
+AquaSetupScreen(int index, ScreenPtr pScreen)
+{
+ // Add Aqua specific replacements for fb screen functions
+ pScreen->PaintWindowBackground = AquaPaintWindow;
+ pScreen->PaintWindowBorder = AquaPaintWindow;
+
+#ifdef RENDER
+ {
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ ps->Composite = AquaComposite;
+ }
+#endif /* RENDER */
+
+ // Initialize generic rootless code
+ return RootlessInit(pScreen, &aquaRootlessProcs);
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.h b/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.h
new file mode 100644
index 000000000..ded22d40b
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.h
@@ -0,0 +1,40 @@
+/*
+ * Rootless implementation for Mac OS X Aqua environment
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.h,v 1.1 2002/03/28 02:21:19 torrey Exp $ */
+
+#ifndef _ROOTLESSAQUAIMP_H
+#define _ROOTLESSAQUAIMP_H
+
+#include "fakeBoxRec.h"
+
+int AquaDisplayCount();
+
+void AquaScreenInit(int index, int *x, int *y, int *width, int *height,
+ int *rowBytes, unsigned long *bps, unsigned long *spp,
+ int *bpp);
+
+void *AquaNewWindow(void *upperw, int x, int y, int w, int h, int isRoot);
+
+void AquaDestroyWindow(void *rw);
+
+void AquaMoveWindow(void *rw, int x, int y);
+
+void AquaStartResizeWindow(void *rw, int x, int y, int w, int h);
+
+void AquaFinishResizeWindow(void *rw, int x, int y, int w, int h);
+
+void AquaUpdateRects(void *rw, fakeBoxRec *rects, int count);
+
+void AquaRestackWindow(void *rw, void *lowerw);
+
+void AquaReshapeWindow(void *rw, fakeBoxRec *rects, int count);
+
+void AquaStartDrawing(void *rw, char **bits,
+ int *rowBytes, int *depth, int *bpp);
+
+void AquaStopDrawing(void *rw);
+
+#endif /* _ROOTLESSAQUAIMP_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.m b/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.m
new file mode 100644
index 000000000..3a67b3693
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.m
@@ -0,0 +1,427 @@
+/*
+ * Rootless implementation for Mac OS X Aqua environment
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessAquaImp.m,v 1.3 2002/08/28 06:41:26 torrey Exp $ */
+
+#include "rootlessAquaImp.h"
+#include "fakeBoxRec.h"
+#include "quartzCommon.h"
+#include "aquaCommon.h"
+#include "pseudoramiX.h"
+#import <Cocoa/Cocoa.h>
+#include <ApplicationServices/ApplicationServices.h>
+#import "XView.h"
+
+extern void ErrorF(const char *, ...);
+
+
+/*
+ * AquaDisplayCount
+ * Return the number of displays.
+ * Multihead note: When rootless mode uses PseudoramiX, the
+ * X server only sees one screen; only PseudoramiX itself knows
+ * about all of the screens.
+ */
+int AquaDisplayCount()
+{
+ aquaNumScreens = [[NSScreen screens] count];
+
+ if (noPseudoramiXExtension) {
+ return aquaNumScreens;
+ } else {
+ return 1; // only PseudoramiX knows about the rest
+ }
+}
+
+
+void AquaScreenInit(int index, int *x, int *y, int *width, int *height,
+ int *rowBytes, unsigned long *bps, unsigned long *spp,
+ int *bpp)
+{
+ *bps = 8;
+ *spp = 3;
+ *bpp = 32;
+
+ if (noPseudoramiXExtension) {
+ NSScreen *screen = [[NSScreen screens] objectAtIndex:index];
+ NSRect frame = [screen frame];
+
+ // set x, y so (0,0) is top left of main screen
+ *x = NSMinX(frame);
+ *y = NSHeight([[NSScreen mainScreen] frame]) - NSHeight(frame) -
+ NSMinY(frame);
+
+ *width = NSWidth(frame);
+ *height = NSHeight(frame);
+ *rowBytes = (*width) * (*bpp) / 8;
+
+ // Shift the usable part of main screen down to avoid the menu bar.
+ if (NSEqualRects(frame, [[NSScreen mainScreen] frame])) {
+ *y += aquaMenuBarHeight;
+ *height -= aquaMenuBarHeight;
+ }
+
+ } else {
+ int i;
+ NSRect unionRect = NSMakeRect(0, 0, 0, 0);
+ NSArray *screens = [NSScreen screens];
+
+ // Get the union of all screens (minus the menu bar on main screen)
+ for (i = 0; i < [screens count]; i++) {
+ NSScreen *screen = [screens objectAtIndex:i];
+ NSRect frame = [screen frame];
+ frame.origin.y = [[NSScreen mainScreen] frame].size.height -
+ frame.size.height - frame.origin.y;
+ if (NSEqualRects([screen frame], [[NSScreen mainScreen] frame])) {
+ frame.origin.y += aquaMenuBarHeight;
+ frame.size.height -= aquaMenuBarHeight;
+ }
+ unionRect = NSUnionRect(unionRect, frame);
+ }
+
+ // Use unionRect as the screen size for the X server.
+ *x = unionRect.origin.x;
+ *y = unionRect.origin.y;
+ *width = unionRect.size.width;
+ *height = unionRect.size.height;
+ *rowBytes = (*width) * (*bpp) / 8;
+
+ // Tell PseudoramiX about the real screens.
+ // InitOutput() will move the big screen to (0,0),
+ // so compensate for that here.
+ for (i = 0; i < [screens count]; i++) {
+ NSScreen *screen = [screens objectAtIndex:i];
+ NSRect frame = [screen frame];
+ int j;
+
+ // Skip this screen if it's a mirrored copy of an earlier screen.
+ for (j = 0; j < i; j++) {
+ if (NSEqualRects(frame, [[screens objectAtIndex:j] frame])) {
+ ErrorF("PseudoramiX screen %d is a mirror of screen %d.\n",
+ i, j);
+ break;
+ }
+ }
+ if (j < i) continue; // this screen is a mirrored copy
+
+ frame.origin.y = [[NSScreen mainScreen] frame].size.height -
+ frame.size.height - frame.origin.y;
+
+ if (NSEqualRects([screen frame], [[NSScreen mainScreen] frame])) {
+ frame.origin.y += aquaMenuBarHeight;
+ frame.size.height -= aquaMenuBarHeight;
+ }
+
+ ErrorF("PseudoramiX screen %d added: %dx%d @ (%d,%d).\n", i,
+ (int)frame.size.width, (int)frame.size.height,
+ (int)frame.origin.x, (int)frame.origin.y);
+
+ frame.origin.x -= unionRect.origin.x;
+ frame.origin.y -= unionRect.origin.y;
+
+ ErrorF("PseudoramiX screen %d placed at X11 coordinate (%d,%d).\n",
+ i, (int)frame.origin.x, (int)frame.origin.y);
+
+ PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
+ frame.size.width, frame.size.height);
+ }
+ }
+}
+
+
+/*
+ * AquaNewWindow
+ * Create a new on-screen window.
+ * Rootless windows must not autodisplay! Autodisplay can cause a deadlock.
+ * Event thread - autodisplay: locks view hierarchy, then window
+ * X Server thread - window resize: locks window, then view hierarchy
+ * Deadlock occurs if each thread gets one lock and waits for the other.
+ * Autodisplay can also cause NSCarbonWindows to lose their contents.
+*/
+void *AquaNewWindow(void *upperw, int x, int y, int w, int h, int isRoot)
+{
+ AquaWindowRec *winRec = (AquaWindowRec *)malloc(sizeof(AquaWindowRec));
+ NSRect frame = NSMakeRect(x, NSHeight([[NSScreen mainScreen] frame]) -
+ y - h, w, h);
+ NSWindow *theWindow;
+ XView *theView;
+
+ // Create an NSWindow for the new X11 window
+ theWindow = [[NSWindow alloc] initWithContentRect:frame
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
+ if (!theWindow) return NULL;
+
+ [theWindow setBackgroundColor:[NSColor clearColor]]; // erase transparent
+ [theWindow setAlphaValue:1.0]; // draw opaque
+ [theWindow setOpaque:YES]; // changed when window is shaped
+
+ [theWindow useOptimizedDrawing:YES]; // Has no overlapping sub-views
+ [theWindow setAutodisplay:NO]; // See comment above
+ [theWindow disableFlushWindow]; // We do all the flushing manually
+ [theWindow setHasShadow:!isRoot]; // All windows have shadows except root
+ [theWindow setReleasedWhenClosed:YES]; // Default, but we want to be sure
+
+ theView = [[XView alloc] initWithFrame:frame];
+ [theWindow setContentView:theView];
+ [theWindow setInitialFirstResponder:theView];
+
+ if (upperw) {
+ AquaWindowRec *upperRec = AQUA_WINREC(upperw);
+ int uppernum = [upperRec->window windowNumber];
+ [theWindow orderWindow:NSWindowBelow relativeTo:uppernum];
+ } else {
+ if (!isRoot) {
+ [theWindow orderFront:nil];
+ winRec->port = NULL;
+ }
+ }
+
+ [theWindow setAcceptsMouseMovedEvents:YES];
+
+ winRec->window = theWindow;
+ winRec->view = theView;
+
+ if (!isRoot) {
+ winRec->rootGWorld = NULL;
+ [theView lockFocus];
+ // Fill the window with white to make sure alpha channel is set
+ NSEraseRect(frame);
+ winRec->port = [theView qdPort];
+ winRec->context = [[NSGraphicsContext currentContext] graphicsPort];
+ // CreateCGContextForPort(winRec->port, &winRec->context);
+ [theView unlockFocus];
+ } else {
+ // Allocate the offscreen graphics world for root window drawing
+ GWorldPtr rootGWorld;
+ Rect globalRect;
+
+ SetRect(&globalRect, x, y, x+w, y+h);
+ if (NewGWorld(&rootGWorld, 0, &globalRect, NULL, NULL, 0))
+ return NULL;
+ winRec->rootGWorld = rootGWorld;
+ }
+
+ return winRec;
+}
+
+
+void AquaDestroyWindow(void *rw)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+
+ [winRec->window orderOut:nil];
+ [winRec->window close];
+ [winRec->view release];
+ if (winRec->rootGWorld) {
+ DisposeGWorld(winRec->rootGWorld);
+ }
+ free(rw);
+}
+
+
+void AquaMoveWindow(void *rw, int x, int y)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+ NSPoint topLeft = NSMakePoint(x, NSHeight([[NSScreen mainScreen] frame]) -
+ y);
+
+ [winRec->window setFrameTopLeftPoint:topLeft];
+}
+
+
+/*
+ * AquaStartResizeWindow
+ * Undo any shape and resize the on screen window.
+ */
+void AquaStartResizeWindow(void *rw, int x, int y, int w, int h)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+ NSRect frame = NSMakeRect(x, NSHeight([[NSScreen mainScreen] frame]) -
+ y - h, w, h);
+
+ [winRec->window setFrame:frame display:NO];
+}
+
+
+void AquaFinishResizeWindow(void *rw, int x, int y, int w, int h)
+{
+ // refresh everything? fixme yes for testing
+ fakeBoxRec box = {0, 0, w, h};
+ AquaUpdateRects(rw, &box, 1);
+}
+
+
+/*
+ * AquaUpdateRects
+ * Flush rectangular regions from a window's backing buffer
+ * (or PixMap for the root window) to the screen.
+ */
+void AquaUpdateRects(void *rw, fakeBoxRec *fakeRects, int count)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+ fakeBoxRec *rects, *end;
+ static RgnHandle rgn = NULL;
+ static RgnHandle box = NULL;
+
+ if (!rgn) rgn = NewRgn();
+ if (!box) box = NewRgn();
+
+ if (winRec->rootGWorld) {
+ // FIXME: Draw from the root PixMap to the normally
+ // invisible root window.
+ } else {
+ for (rects = fakeRects, end = fakeRects+count; rects < end; rects++) {
+ Rect qdrect;
+ qdrect.left = rects->x1;
+ qdrect.top = rects->y1;
+ qdrect.right = rects->x2;
+ qdrect.bottom = rects->y2;
+
+ RectRgn(box, &qdrect);
+ UnionRgn(rgn, box, rgn);
+ }
+
+ QDFlushPortBuffer(winRec->port, rgn);
+ }
+
+ SetEmptyRgn(rgn);
+ SetEmptyRgn(box);
+}
+
+
+/*
+ * AquaRestackWindow
+ * Change the window order. Put the window behind upperw or on top if
+ * upperw is NULL.
+ */
+void AquaRestackWindow(void *rw, void *upperw)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+
+ if (upperw) {
+ AquaWindowRec *upperRec = AQUA_WINREC(upperw);
+ int uppernum = [upperRec->window windowNumber];
+ [winRec->window orderWindow:NSWindowBelow relativeTo:uppernum];
+ } else {
+ [winRec->window makeKeyAndOrderFront:nil];
+ }
+}
+
+
+/*
+ * AquaReshapeWindow
+ * Set the shape of a window. The rectangles are the areas that are
+ * not part of the new shape.
+ */
+void AquaReshapeWindow(void *rw, fakeBoxRec *fakeRects, int count)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+ NSRect frame = [winRec->view frame];
+ int winHeight = NSHeight(frame);
+
+ if (count > 0) {
+ fakeBoxRec *rects, *end;
+
+ // Make transparent if window is now shaped.
+ [winRec->window setOpaque:NO];
+
+ // Clear the areas outside the window shape
+ [winRec->view lockFocus];
+ [[NSColor clearColor] set];
+ for (rects = fakeRects, end = fakeRects+count; rects < end; rects++) {
+ int rectHeight = rects->y2 - rects->y1;
+ NSRectFill( NSMakeRect(rects->x1,
+ winHeight - rects->y1 - rectHeight,
+ rects->x2 - rects->x1, rectHeight) );
+ }
+ [[NSGraphicsContext currentContext] flushGraphics];
+ [winRec->view unlockFocus];
+
+ // force update of window shadow
+ [winRec->window setHasShadow:NO];
+ [winRec->window setHasShadow:YES];
+
+ } else {
+ fakeBoxRec bounds = {0, 0, NSWidth(frame), winHeight};
+
+ [winRec->window setOpaque:YES];
+ AquaUpdateRects(rw, &bounds, 1);
+ }
+}
+
+
+/* AquaStartDrawing
+ * When a window's buffer is not being drawn to, the CoreGraphics
+ * window server may compress or move it. Call this routine
+ * to lock down the buffer during direct drawing. It returns
+ * a pointer to the backing buffer and its depth, etc.
+ */
+void AquaStartDrawing(void *rw, char **bits,
+ int *rowBytes, int *depth, int *bpp)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+ PixMapHandle pix;
+
+ if (! winRec->rootGWorld) {
+ [winRec->view lockFocus];
+ winRec->port = [winRec->view qdPort];
+ LockPortBits(winRec->port);
+ [winRec->view unlockFocus];
+ pix = GetPortPixMap(winRec->port);
+ } else {
+ pix = GetGWorldPixMap(winRec->rootGWorld);
+ LockPixels(pix);
+ }
+
+ *bits = GetPixBaseAddr(pix);
+ *rowBytes = GetPixRowBytes(pix) & 0x3fff; // fixme is mask needed?
+ *depth = (**pix).cmpCount * (**pix).cmpSize; // fixme use GetPixDepth(pix)?
+ *bpp = (**pix).pixelSize;
+}
+
+
+/*
+ * AquaStopDrawing
+ * When direct access to a window's buffer is no longer needed, this
+ * routine should be called to allow CoreGraphics to compress or
+ * move it.
+ */
+void AquaStopDrawing(void *rw)
+{
+ AquaWindowRec *winRec = AQUA_WINREC(rw);
+
+ if (! winRec->rootGWorld) {
+ UnlockPortBits(winRec->port);
+ } else {
+ PixMapHandle pix = GetGWorldPixMap(winRec->rootGWorld);
+ UnlockPixels(pix);
+ }
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.c b/xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.c
new file mode 100644
index 000000000..2018fa84f
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.c
@@ -0,0 +1,360 @@
+/*
+ * Common rootless definitions and code
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.c,v 1.6 2002/07/15 19:58:31 torrey Exp $ */
+
+#include "rootlessCommon.h"
+
+
+RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
+
+
+/*
+ * TopLevelParent
+ * Returns the top-level parent of pWindow.
+ * The root is the top-level parent of itself, even though the root is
+ * not otherwise considered to be a top-level window.
+ */
+WindowPtr TopLevelParent(WindowPtr pWindow)
+{
+ WindowPtr top = pWindow;
+
+ if (IsRoot(pWindow)) return pWindow; // root is top-level parent of itself
+ while (top && ! IsTopLevel(top)) top = top->parent;
+ return top;
+}
+
+
+/*
+ * IsFramedWindow
+ * Returns TRUE if this window is visible inside a frame
+ * (e.g. it is visible and has a top-level or root parent)
+ */
+Bool IsFramedWindow(WindowPtr pWin)
+{
+ WindowPtr top;
+
+ if (! pWin->realized) return FALSE;
+ top = TopLevelParent(pWin);
+ return (top && WINREC(top));
+}
+
+
+/*
+ * RootlessStartDrawing
+ * Prepare a window for direct access to its backing buffer.
+ * Each top-level parent has a Pixmap representing its backing buffer,
+ * which all of its children inherit.
+ */
+void RootlessStartDrawing(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ WindowPtr top = TopLevelParent(pWindow);
+ RootlessWindowRec *winRec;
+
+ if (!top) return;
+ winRec = WINREC(top);
+ if (!winRec) return;
+
+ // Make sure the window's top-level parent is prepared for drawing.
+ if (!winRec->drawing) {
+ int bw = wBorderWidth(top);
+
+ CallFrameProc(pScreen, StartDrawing, (pScreen, &winRec->frame));
+ winRec->pixmap =
+ GetScratchPixmapHeader(pScreen, winRec->frame.w, winRec->frame.h,
+ winRec->frame.depth,
+ winRec->frame.bitsPerPixel,
+ winRec->frame.bytesPerRow,
+ winRec->frame.pixelData);
+ SetPixmapBaseToScreen(winRec->pixmap,
+ top->drawable.x - bw, top->drawable.y - bw);
+ winRec->drawing = TRUE;
+ }
+
+ winRec->oldPixmap = pScreen->GetWindowPixmap(pWindow);
+ pScreen->SetWindowPixmap(pWindow, winRec->pixmap);
+}
+
+
+/*
+ * RootlessStopDrawing
+ * Stop drawing to a window's backing buffer.
+ */
+void RootlessStopDrawing(WindowPtr pWindow)
+{
+ WindowPtr top = TopLevelParent(pWindow);
+ RootlessWindowRec *winRec;
+
+ if (!top) return;
+ winRec = WINREC(top);
+ if (!winRec) return;
+
+ if (winRec->drawing) {
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ CallFrameProc(pScreen, StopDrawing, (pScreen, &winRec->frame));
+ FreeScratchPixmapHeader(winRec->pixmap);
+ pScreen->SetWindowPixmap(pWindow, winRec->oldPixmap);
+ winRec->pixmap = NULL;
+ winRec->drawing = FALSE;
+ }
+}
+
+#if 0
+// NSCarbonWindow Note: Windows no longer need a backing pixmap
+// other than the one provided by the implementation.
+// This routine is obsolete.
+
+// Update pWindow's pixmap.
+// This needs to be called every time a window moves relative to
+// its top-level parent, or the parent's pixmap data is reallocated.
+// Three cases:
+// * window is top-level with no existing pixmap: make one
+// * window is top-level with existing pixmap: update it in place
+// * window is descendant of top-level: point to top-level's pixmap
+void UpdatePixmap(WindowPtr pWindow)
+{
+ WindowPtr top = TopLevelParent(pWindow);
+ RootlessWindowRec *winRec;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ PixmapPtr pix;
+
+ RL_DEBUG_MSG("update pixmap (win 0x%x)", pWindow);
+
+ // Don't use IsFramedWindow(); window is unrealized during RealizeWindow().
+
+ if (! top) {
+ RL_DEBUG_MSG("no parent\n");
+ return;
+ }
+ winRec = WINREC(top);
+ if (!winRec) {
+ RL_DEBUG_MSG("not framed\n");
+ return;
+ }
+
+ if (pWindow == top) {
+ // This is the top window. Update its pixmap.
+ int bw = wBorderWidth(pWindow);
+
+ if (winRec->pixmap == NULL) {
+ // Allocate a new pixmap.
+ pix = GetScratchPixmapHeader(pScreen,
+ winRec->frame.w, winRec->frame.h,
+ winRec->frame.depth,
+ winRec->frame.bitsPerPixel,
+ winRec->frame.bytesPerRow,
+ winRec->frame.pixelData);
+ SetPixmapBaseToScreen(pix, pWindow->drawable.x - bw,
+ pWindow->drawable.y - bw);
+ pScreen->SetWindowPixmap(pWindow, pix);
+ winRec->pixmap = pix;
+ } else {
+ // Update existing pixmap. Update in place so we don't have to
+ // change the children's pixmaps.
+ int bw = wBorderWidth(top);
+
+ pix = winRec->pixmap;
+ pScreen->ModifyPixmapHeader(pix,
+ winRec->frame.w, winRec->frame.h,
+ winRec->frame.depth,
+ winRec->frame.bitsPerPixel,
+ winRec->frame.bytesPerRow,
+ winRec->frame.pixelData);
+ SetPixmapBaseToScreen(pix, top->drawable.x - bw,
+ top->drawable.y - bw);
+ }
+ } else {
+ // This is not the top window. Point to the parent's pixmap.
+ pix = winRec->pixmap;
+ pScreen->SetWindowPixmap(pWindow, pix);
+ }
+
+ RL_DEBUG_MSG("done\n");
+}
+#endif
+
+#ifdef SHAPE
+
+// boundingShape = outside border (like borderClip)
+// clipShape = inside border (like clipList)
+// Both are in window-local coordinates
+// We only care about boundingShape (fixme true?)
+
+// RootlessReallySetShape is used in several places other than SetShape.
+// Most importantly, SetShape is often called on unmapped windows, so we
+// have to wait until the window is mapped to reshape the frame.
+static void RootlessReallySetShape(WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RegionRec newShape;
+
+ if (IsRoot(pWin)) return;
+ if (!IsTopLevel(pWin)) return;
+ if (!winRec) return;
+
+ RootlessStopDrawing(pWin);
+
+ if (wBoundingShape(pWin)) {
+ // wBoundingShape is relative to *inner* origin of window.
+ // Translate by borderWidth to get the outside-relative position.
+ REGION_INIT(pScreen, &newShape, NullBox, 0);
+ REGION_COPY(pScreen, &newShape, wBoundingShape(pWin));
+ REGION_TRANSLATE(pScreen, &newShape, pWin->borderWidth,
+ pWin->borderWidth);
+ } else {
+ newShape.data = NULL;
+ newShape.extents.x1 = 0;
+ newShape.extents.y1 = 0;
+ newShape.extents.x2 = winRec->frame.w;
+ newShape.extents.y2 = winRec->frame.h;
+ }
+ RL_DEBUG_MSG("reshaping...");
+ RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
+ REGION_NUM_RECTS(&newShape),
+ newShape.extents.x1, newShape.extents.y1,
+ newShape.extents.x2, newShape.extents.y2);
+ CallFrameProc(pScreen, ReshapeFrame, (pScreen, &winRec->frame, &newShape));
+ REGION_UNINIT(pScreen, &newShape);
+}
+
+#endif // SHAPE
+
+
+// pRegion is GLOBAL
+void
+RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion)
+{
+ RL_DEBUG_MSG("Damaged win 0x%x ", pWindow);
+ pWindow = TopLevelParent(pWindow);
+ RL_DEBUG_MSG("parent 0x%x:\n", pWindow);
+ if (!pWindow) {
+ RL_DEBUG_MSG("RootlessDamageRegion: window is not framed\n");
+ } else if (!WINREC(pWindow)) {
+ RL_DEBUG_MSG("RootlessDamageRegion: top-level window not a frame\n");
+ } else {
+ REGION_UNION((pWindow)->drawable.pScreen, &WINREC(pWindow)->damage,
+ &WINREC(pWindow)->damage, (pRegion));
+ }
+
+#ifdef ROOTLESSDEBUG
+ {
+ BoxRec *box = REGION_RECTS(pRegion), *end;
+ int numBox = REGION_NUM_RECTS(pRegion);
+
+ for (end = box+numBox; box < end; box++) {
+ RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
+ box->x1, box->x2, box->y1, box->y2);
+ }
+ }
+#endif
+}
+
+
+// pBox is GLOBAL
+void
+RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox)
+{
+ RegionRec region;
+
+ REGION_INIT(pWindow->drawable.pScreen, &region, pBox, 1);
+ RootlessDamageRegion(pWindow, &region);
+}
+
+
+// (x, y, w, h) is in window-local coordinates.
+void
+RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
+{
+ BoxRec box;
+ RegionRec region;
+
+ x += pWindow->drawable.x;
+ y += pWindow->drawable.y;
+ box.x1 = x;
+ box.x2 = x + w;
+ box.y1 = y;
+ box.y2 = y + h;
+ REGION_INIT(pWindow->drawable.pScreen, &region, &box, 1);
+ RootlessDamageRegion(pWindow, &region);
+}
+
+#ifdef SHAPE
+
+void
+RootlessDamageShape(WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ // We only care about the shape of top-level framed windows.
+ if (IsRoot(pWin)) return;
+ if (!IsTopLevel(pWin)) return;
+ if (!winRec) return;
+
+ winRec->shapeDamage = TRUE;
+}
+
+#endif // SHAPE
+
+/*
+ * RootlessRedisplay
+ * Stop drawing and redisplay the damaged region of a window.
+ */
+void
+RootlessRedisplay(WindowPtr pWindow)
+{
+ RootlessWindowRec *winRec = WINREC(pWindow);
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+#ifdef SHAPE
+ if (winRec->shapeDamage) {
+ // Reshape the window. This will also update the entire window.
+ RootlessReallySetShape(pWindow);
+ REGION_EMPTY(pScreen, &winRec->damage);
+ winRec->shapeDamage = FALSE;
+ } else
+#endif // SHAPE
+ {
+ RootlessStopDrawing(pWindow);
+ if (REGION_NOTEMPTY(pScreen, &winRec->damage)) {
+ RL_DEBUG_MSG("Redisplay Win 0x%x, %i x %i @ (%i, %i)\n",
+ pWindow, winRec->frame.w, winRec->frame.h,
+ winRec->frame.x, winRec->frame.y);
+
+ REGION_INTERSECT(pScreen, &winRec->damage, &winRec->damage,
+ &pWindow->borderSize);
+
+ // move region to window local coords
+ REGION_TRANSLATE(pScreen, &winRec->damage,
+ -winRec->frame.x, -winRec->frame.y);
+ CallFrameProc(pScreen, UpdateRegion,
+ (pScreen, &winRec->frame, &winRec->damage));
+ REGION_EMPTY(pScreen, &winRec->damage);
+ }
+ }
+}
+
+
+/*
+ * RootlessRedisplayScreen
+ * Walk every window on a screen and redisplay the damaged regions.
+ */
+void
+RootlessRedisplayScreen(ScreenPtr pScreen)
+{
+ WindowPtr root = WindowTable[pScreen->myNum];
+
+ if (root) {
+ WindowPtr win;
+
+ RootlessRedisplay(root);
+ for (win = root->firstChild; win; win = win->nextSib) {
+ if (WINREC(win)) {
+ RootlessRedisplay(win);
+ }
+ }
+ }
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.h b/xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.h
new file mode 100644
index 000000000..43a74e106
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.h
@@ -0,0 +1,228 @@
+/*
+ * Common internal rootless definitions and code
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessCommon.h,v 1.6 2002/07/24 05:58:33 torrey Exp $ */
+
+#ifndef _ROOTLESSCOMMON_H
+#define _ROOTLESSCOMMON_H
+
+#include "rootless.h"
+
+#include "pixmapstr.h"
+#include "windowstr.h"
+
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+
+// Debug output, or not.
+#ifdef ROOTLESSDEBUG
+#define RL_DEBUG_MSG ErrorF
+#else
+#define RL_DEBUG_MSG(a, ...)
+#endif
+
+
+// Global variables
+extern int rootlessGCPrivateIndex;
+extern int rootlessScreenPrivateIndex;
+extern int rootlessWindowPrivateIndex;
+
+
+// RootlessGCRec: private per-gc data
+typedef struct {
+ GCFuncs *originalFuncs;
+ GCOps *originalOps;
+} RootlessGCRec;
+
+
+// RootlessWindowRec: private per-window data
+typedef struct RootlessWindowRec {
+ RootlessFrameRec frame;
+ RegionRec damage;
+ unsigned int borderWidth; // needed for MoveWindow(VTOther) (%$#@!!!)
+ PixmapPtr pixmap;
+ PixmapPtr oldPixmap;
+ BOOL drawing; // TRUE if currently drawing
+#ifdef SHAPE
+ BOOL shapeDamage; // TRUE if shape has changed
+#endif
+} RootlessWindowRec;
+
+
+// RootlessScreenRec: per-screen private data
+typedef struct {
+ ScreenPtr pScreen;
+ RootlessFrameProcs frameProcs;
+
+ CloseScreenProcPtr CloseScreen;
+
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ MoveWindowProcPtr MoveWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ RestackWindowProcPtr RestackWindow;
+ ChangeBorderWidthProcPtr ChangeBorderWidth;
+ PositionWindowProcPtr PositionWindow;
+ ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+
+ CreateGCProcPtr CreateGC;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ GetImageProcPtr GetImage;
+ SourceValidateProcPtr SourceValidate;
+
+ MarkOverlappedWindowsProcPtr MarkOverlappedWindows;
+ ValidateTreeProcPtr ValidateTree;
+
+#ifdef SHAPE
+ SetShapeProcPtr SetShape;
+#endif
+
+#ifdef RENDER
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+#endif
+
+} RootlessScreenRec;
+
+
+// "Definition of the Porting Layer for the X11 Sample Server" says
+// unwrap and rewrap of screen functions is unnecessary, but
+// screen->CreateGC changes after a call to cfbCreateGC.
+
+#define SCREEN_UNWRAP(screen, fn) \
+ screen->fn = SCREENREC(screen)->fn;
+
+#define SCREEN_WRAP(screen, fn) \
+ SCREENREC(screen)->fn = screen->fn; \
+ screen->fn = Rootless##fn
+
+
+// Accessors for screen and window privates
+
+#define SCREENREC(pScreen) \
+ ((RootlessScreenRec*)(pScreen)->devPrivates[rootlessScreenPrivateIndex].ptr)
+
+#define WINREC(pWin) \
+ ((RootlessWindowRec *)(pWin)->devPrivates[rootlessWindowPrivateIndex].ptr)
+
+
+// Call a rootless implementation function.
+// Many rootless implementation functions are allowed to be NULL.
+#define CallFrameProc(pScreen, proc, params) \
+ if (SCREENREC(pScreen)->frameProcs.proc) { \
+ RL_DEBUG_MSG("calling frame proc " #proc " "); \
+ SCREENREC(pScreen)->frameProcs.proc params; \
+ }
+
+
+// BoxRec manipulators
+// Copied from shadowfb
+
+#define TRIM_BOX(box, pGC) { \
+ BoxPtr extents = &pGC->pCompositeClip->extents;\
+ if(box.x1 < extents->x1) box.x1 = extents->x1; \
+ if(box.x2 > extents->x2) box.x2 = extents->x2; \
+ if(box.y1 < extents->y1) box.y1 = extents->y1; \
+ if(box.y2 > extents->y2) box.y2 = extents->y2; \
+}
+
+#define TRANSLATE_BOX(box, pDraw) { \
+ box.x1 += pDraw->x; \
+ box.x2 += pDraw->x; \
+ box.y1 += pDraw->y; \
+ box.y2 += pDraw->y; \
+}
+
+#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
+ TRANSLATE_BOX(box, pDraw); \
+ TRIM_BOX(box, pGC); \
+}
+
+#define BOX_NOT_EMPTY(box) \
+ (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+
+
+// HUGE_ROOT and NORMAL_ROOT
+// We don't want to clip windows to the edge of the screen.
+// HUGE_ROOT temporarily makes the root window really big.
+// This is needed as a wrapper around any function that calls
+// SetWinSize or SetBorderSize which clip a window against its
+// parents, including the root.
+
+extern RegionRec rootlessHugeRoot;
+
+#define HUGE_ROOT(pWin) \
+ { \
+ WindowPtr w = pWin; \
+ while (w->parent) w = w->parent; \
+ saveRoot = w->winSize; \
+ w->winSize = rootlessHugeRoot; \
+ }
+
+#define NORMAL_ROOT(pWin) \
+ { \
+ WindowPtr w = pWin; \
+ while (w->parent) w = w->parent; \
+ w->winSize = saveRoot; \
+ }
+
+
+// Returns TRUE if this window is a top-level window (i.e. child of the root)
+// The root is not a top-level window.
+#define IsTopLevel(pWin) \
+ ((pWin) && (pWin)->parent && !(pWin)->parent->parent)
+
+// Returns TRUE if this window is a root window
+#define IsRoot(pWin) \
+ ((pWin) == WindowTable[(pWin)->drawable.pScreen->myNum])
+
+
+/*
+ * SetPixmapBaseToScreen
+ * Move the given pixmap's base address to where pixel (0, 0)
+ * would be if the pixmap's actual data started at (x, y).
+ */
+#define SetPixmapBaseToScreen(pix, x, y) { \
+ PixmapPtr _pPix = (PixmapPtr) (pix); \
+ _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \
+ ((int)(x) * _pPix->drawable.bitsPerPixel/8 + \
+ (int)(y) * _pPix->devKind); \
+}
+
+
+// Returns the top-level parent of pWindow.
+// The root is the top-level parent of itself, even though the root is
+// not otherwise considered to be a top-level window.
+WindowPtr TopLevelParent(WindowPtr pWindow);
+
+// Returns TRUE if this window is visible inside a frame
+// (e.g. it is visible and has a top-level or root parent)
+Bool IsFramedWindow(WindowPtr pWin);
+
+// Prepare a window for direct access to its backing buffer.
+void RootlessStartDrawing(WindowPtr pWindow);
+
+// Finish drawing to a window's backing buffer.
+void RootlessStopDrawing(WindowPtr pWindow);
+
+// Routines that cause regions to get redrawn.
+// DamageRegion and DamageRect are in global coordinates.
+// DamageBox is in window-local coordinates.
+void RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion);
+void RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h);
+void RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox);
+void RootlessRedisplay(WindowPtr pWindow);
+void RootlessRedisplayScreen(ScreenPtr pScreen);
+
+// Window reshape needs to be updated. The reshape also forces complete redraw.
+void RootlessDamageShape(WindowPtr pWin);
+
+#endif // _ROOTLESSCOMMON_H
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessGC.c b/xc/programs/Xserver/hw/darwin/quartz/rootlessGC.c
new file mode 100644
index 000000000..1542d2c00
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessGC.c
@@ -0,0 +1,1218 @@
+/*
+ * Graphics Context support for Mac OS X rootless X server
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessGC.c,v 1.3 2002/07/24 05:58:33 torrey Exp $ */
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "dixfontstr.h"
+#include "mivalidate.h"
+#include "fb.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rootlessCommon.h"
+#include "aqua.h"
+
+
+// GC functions
+static void RootlessValidateGC(GCPtr pGC, unsigned long changes,
+ DrawablePtr pDrawable);
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask);
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void RootlessDestroyGC(GCPtr pGC);
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue,
+ int nrects);
+static void RootlessDestroyClip(GCPtr pGC);
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+
+GCFuncs rootlessGCFuncs = {
+ RootlessValidateGC,
+ RootlessChangeGC,
+ RootlessCopyGC,
+ RootlessDestroyGC,
+ RootlessChangeClip,
+ RootlessDestroyClip,
+ RootlessCopyClip,
+};
+
+// GC operations
+static void RootlessFillSpans();
+static void RootlessSetSpans();
+static void RootlessPutImage();
+static RegionPtr RootlessCopyArea();
+static RegionPtr RootlessCopyPlane();
+static void RootlessPolyPoint();
+static void RootlessPolylines();
+static void RootlessPolySegment();
+static void RootlessPolyRectangle();
+static void RootlessPolyArc();
+static void RootlessFillPolygon();
+static void RootlessPolyFillRect();
+static void RootlessPolyFillArc();
+static int RootlessPolyText8();
+static int RootlessPolyText16();
+static void RootlessImageText8();
+static void RootlessImageText16();
+static void RootlessImageGlyphBlt();
+static void RootlessPolyGlyphBlt();
+static void RootlessPushPixels();
+
+static GCOps rootlessGCOps = {
+ RootlessFillSpans,
+ RootlessSetSpans,
+ RootlessPutImage,
+ RootlessCopyArea,
+ RootlessCopyPlane,
+ RootlessPolyPoint,
+ RootlessPolylines,
+ RootlessPolySegment,
+ RootlessPolyRectangle,
+ RootlessPolyArc,
+ RootlessFillPolygon,
+ RootlessPolyFillRect,
+ RootlessPolyFillArc,
+ RootlessPolyText8,
+ RootlessPolyText16,
+ RootlessImageText8,
+ RootlessImageText16,
+ RootlessImageGlyphBlt,
+ RootlessPolyGlyphBlt,
+ RootlessPushPixels
+#ifdef NEED_LINEHELPER
+ , NULL
+#endif
+};
+
+
+Bool
+RootlessCreateGC(GCPtr pGC)
+{
+ RootlessGCRec *gcrec;
+ RootlessScreenRec *s;
+ Bool result;
+
+ SCREEN_UNWRAP(pGC->pScreen, CreateGC);
+ s = (RootlessScreenRec *) pGC->pScreen->
+ devPrivates[rootlessScreenPrivateIndex].ptr;
+ result = s->CreateGC(pGC);
+ gcrec = (RootlessGCRec *) pGC->devPrivates[rootlessGCPrivateIndex].ptr;
+ gcrec->originalOps = NULL; // don't wrap ops yet
+ gcrec->originalFuncs = pGC->funcs;
+ pGC->funcs = &rootlessGCFuncs;
+
+ SCREEN_WRAP(pGC->pScreen, CreateGC);
+ return result;
+}
+
+
+// GC func wrapping
+// ValidateGC wraps gcOps iff dest is viewable. All others just unwrap&call.
+
+// GCFUN_UNRAP assumes funcs have been wrapped and
+// does not assume ops have been wrapped
+#define GCFUNC_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ if (gcrec->originalOps) { \
+ (pGC)->ops = gcrec->originalOps; \
+}
+
+#define GCFUNC_WRAP(pGC) \
+ gcrec->originalFuncs = (pGC)->funcs; \
+ (pGC)->funcs = &rootlessGCFuncs; \
+ if (gcrec->originalOps) { \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->ops = &rootlessGCOps; \
+}
+
+
+static void
+RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+
+ GCFUNC_UNWRAP(pGC);
+
+ gcrec->originalOps = NULL;
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ // We force a planemask so fb doesn't overwrite the alpha channel.
+ // Left to its own devices, fb will optimize away the planemask.
+ int depth = pDrawable->depth;
+ pDrawable->depth = pDrawable->bitsPerPixel;
+ pGC->planemask &= ~AquaAlphaMask(pDrawable->bitsPerPixel);
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable);
+ pDrawable->depth = depth;
+
+ if (((WindowPtr) pDrawable)->viewable) {
+ gcrec->originalOps = pGC->ops;
+ }
+ } else {
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable);
+ }
+
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeGC(pGC, mask);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
+{
+ GCFUNC_UNWRAP(pGCDst);
+ pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst);
+ GCFUNC_WRAP(pGCDst);
+}
+
+static void RootlessDestroyGC(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyGC(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessDestroyClip(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyClip(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ GCFUNC_UNWRAP(pgcDst);
+ pgcDst->funcs->CopyClip(pgcDst, pgcSrc);
+ GCFUNC_WRAP(pgcDst);
+}
+
+
+// GC ops
+// We can't use shadowfb because shadowfb assumes one pixmap
+// and our root window is a special case.
+// So much of this code is copied from shadowfb.
+
+// assumes both funcs and ops are wrapped
+#define GCOP_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \
+ GCFuncs *saveFuncs = pGC->funcs; \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ (pGC)->ops = gcrec->originalOps;
+
+#define GCOP_WRAP(pGC) \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->funcs = saveFuncs; \
+ (pGC)->ops = &rootlessGCOps;
+
+
+static void
+RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit, int sorted)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill spans start ");
+
+ if (nInit <= 0) {
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nInit;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidthInit++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill spans end\n");
+}
+
+static void
+RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int nspans, int sorted)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("set spans start ");
+
+ if (nspans <= 0) {
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nspans;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidth++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("set spans end\n");
+}
+
+static void
+RootlessPutImage(DrawablePtr dst, GCPtr pGC,
+ int depth, int x, int y, int w, int h,
+ int leftPad, int format, char *pBits)
+{
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("put image start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits);
+
+ box.x1 = x + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = y + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("put image end\n");
+}
+
+/* changed area is *dest* rect */
+static RegionPtr
+RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty)
+{
+ RegionPtr result;
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst);
+
+ if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
+ RootlessStartDrawing((WindowPtr) pSrc);
+ }
+ RootlessStartDrawing((WindowPtr) dst);
+ result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy area end\n");
+ return result;
+}
+
+/* changed area is *dest* rect */
+static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
+ GCPtr pGC, int srcx, int srcy,
+ int w, int h, int dstx, int dsty,
+ unsigned long plane)
+{
+ RegionPtr result;
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("copy plane start ");
+
+ if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
+ RootlessStartDrawing((WindowPtr) pSrc);
+ }
+ RootlessStartDrawing((WindowPtr) dst);
+ result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
+ dstx, dsty, plane);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy plane end\n");
+ return result;
+}
+
+// Options for size of changed area:
+// 0 = box per point
+// 1 = big box around all points
+// 2 = accumulate point in 20 pixel radius
+#define ROOTLESS_CHANGED_AREA 1
+#define abs(a) ((a) > 0 ? (a) : -(a))
+
+/* changed area is box around all points */
+static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("polypoint start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+#if ROOTLESS_CHANGED_AREA==0
+ // box per point
+ BoxRec box;
+
+ while (npt) {
+ box.x1 = pptInit->x;
+ box.y1 = pptInit->y;
+ box.x2 = box.x1 + 1;
+ box.y2 = box.y1 + 1;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ npt--;
+ pptInit++;
+ }
+
+#elif ROOTLESS_CHANGED_AREA==1
+ // one big box
+ BoxRec box;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+#elif ROOTLESS_CHANGED_AREA==2
+ // clever(?) method: accumulate point in 20-pixel radius
+ BoxRec box;
+ int firstx, firsty;
+
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ while(--npt) {
+ pptInit++;
+ if (abs(pptInit->x - firstx) > 20 ||
+ abs(pptInit->y - firsty) > 20) {
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ } else {
+ if (box.x1 > pptInit->x) box.x1 = pptInit->x;
+ else if (box.x2 < pptInit->x) box.x2 = pptInit->x;
+ if (box.y1 > pptInit->y) box.y1 = pptInit->y;
+ else if (box.y2 < pptInit->y) box.y2 = pptInit->y;
+ }
+ }
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+#endif /* ROOTLESS_CHANGED_AREA */
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polypoint end\n");
+}
+
+#undef ROOTLESS_CHANGED_AREA
+
+/* changed area is box around each line */
+static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly lines start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth >> 1;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+
+ if(npt > 1) {
+ if(pGC->joinStyle == JoinMiter)
+ extra = 6 * pGC->lineWidth;
+ else if(pGC->capStyle == CapProjecting)
+ extra = pGC->lineWidth;
+ }
+
+ if(mode == CoordModePrevious) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while(--npt) {
+ pptInit++;
+ x += pptInit->x;
+ y += pptInit->y;
+ if(box.x1 > x)
+ box.x1 = x;
+ else if(box.x2 < x)
+ box.x2 = x;
+ if(box.y1 > y)
+ box.y1 = y;
+ else if(box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly lines end\n");
+}
+
+/* changed area is box around each line segment */
+static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
+ int nseg, xSegment *pSeg)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly segment start (win 0x%x)", dst);
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolySegment(dst, pGC, nseg, pSeg);
+
+ if (nseg > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth;
+
+ if(pGC->capStyle != CapProjecting)
+ extra >>= 1;
+
+ if(pSeg->x2 > pSeg->x1) {
+ box.x1 = pSeg->x1;
+ box.x2 = pSeg->x2;
+ } else {
+ box.x2 = pSeg->x1;
+ box.x1 = pSeg->x2;
+ }
+
+ if(pSeg->y2 > pSeg->y1) {
+ box.y1 = pSeg->y1;
+ box.y2 = pSeg->y2;
+ } else {
+ box.y2 = pSeg->y1;
+ box.y1 = pSeg->y2;
+ }
+
+ while(--nseg) {
+ pSeg++;
+ if(pSeg->x2 > pSeg->x1) {
+ if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
+ if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
+ } else {
+ if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
+ if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
+ }
+ if(pSeg->y2 > pSeg->y1) {
+ if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
+ if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
+ } else {
+ if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
+ if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly segment end\n");
+}
+
+/* changed area is box around each line (not entire rects) */
+static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
+ int nRects, xRectangle *pRects)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly rectangle start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyRectangle(dst, pGC, nRects, pRects);
+
+ if (nRects > 0) {
+ BoxRec box;
+ int offset1, offset2, offset3;
+
+ offset2 = pGC->lineWidth;
+ if(!offset2) offset2 = 1;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+
+ while(nRects--) {
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x + pRects->width - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + pRects->height - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ pRects++;
+ }
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly rectangle end\n");
+}
+
+
+/* changed area is box around each arc (assumes all arcs are 360 degrees) */
+static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly arc start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyArc(dst, pGC, narcs, parcs);
+
+ if (narcs > 0) {
+ int extra = pGC->lineWidth >> 1;
+ BoxRec box;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while(--narcs) {
+ parcs++;
+ if(box.x1 > parcs->x)
+ box.x1 = parcs->x;
+ if(box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if(box.y1 > parcs->y)
+ box.y1 = parcs->y;
+ if(box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly arc end\n");
+}
+
+
+/* changed area is box around each poly */
+static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst,
+ pGC->fillStyle);
+
+ if (count <= 2) {
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int i = count;
+ BoxRec box;
+
+ box.x2 = box.x1 = ppt->x;
+ box.y2 = box.y1 = ppt->y;
+
+ if(mode != CoordModeOrigin) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while(--i) {
+ ppt++;
+ x += ppt->x;
+ y += ppt->y;
+ if(box.x1 > x)
+ box.x1 = x;
+ else if(box.x2 < x)
+ box.x2 = x;
+ if(box.y1 > y)
+ box.y1 = y;
+ else if(box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while(--i) {
+ ppt++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ else if(box.x2 < ppt->x)
+ box.x2 = ppt->x;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill poly end\n");
+}
+
+/* changed area is the rects */
+static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
+ int nRectsInit, xRectangle *pRectsInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst,
+ pGC->fillStyle);
+
+ if (nRectsInit <= 0) {
+ pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
+ } else {
+ BoxRec box;
+ xRectangle *pRects = pRectsInit;
+ int nRects = nRectsInit;
+
+ box.x1 = pRects->x;
+ box.x2 = box.x1 + pRects->width;
+ box.y1 = pRects->y;
+ box.y2 = box.y1 + pRects->height;
+
+ while(--nRects) {
+ pRects++;
+ if(box.x1 > pRects->x)
+ box.x1 = pRects->x;
+ if(box.x2 < (pRects->x + pRects->width))
+ box.x2 = pRects->x + pRects->width;
+ if(box.y1 > pRects->y)
+ box.y1 = pRects->y;
+ if(box.y2 < (pRects->y + pRects->height))
+ box.y2 = pRects->y + pRects->height;
+ }
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill rect end\n");
+}
+
+
+/* changed area is box around each arc (assuming arcs are all 360 degrees) */
+static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
+ int narcs, xArc *parcs)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("fill arc start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyFillArc(dst, pGC, narcs, parcs);
+
+ if (narcs > 0) {
+ BoxRec box;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while(--narcs) {
+ parcs++;
+ if(box.x1 > parcs->x)
+ box.x1 = parcs->x;
+ if(box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if(box.y1 > parcs->y)
+ box.y1 = parcs->y;
+ if(box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill arc end\n");
+}
+
+
+static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 end\n");
+}
+
+static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ int width; // the result, sorta
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polytext8 start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if(width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext8 end\n");
+ return (width + x);
+}
+
+static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 end\n");
+}
+
+static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ int width; // the result, sorta
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polytext16 start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if (width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext16 end\n");
+ return width + x;
+}
+
+static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer unused)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imageglyph start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyph, ppci, unused);
+
+ if (nglyph > 0) {
+ int top, bot, width = 0;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ box.x1 = ppci[0]->metrics.leftSideBearing;
+ if(box.x1 > 0) box.x1 = 0;
+ box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
+ ppci[nglyph - 1]->metrics.characterWidth;
+ if(box.x2 < 0) box.x2 = 0;
+
+ box.x2 += dst->x + x;
+ box.x1 += dst->x + x;
+
+ while(nglyph--) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0)
+ box.x2 += width;
+ else
+ box.x1 += width;
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imageglyph end\n");
+}
+
+static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polyglyph start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ if (nglyph > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing;
+ box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
+
+ if(nglyph > 1) {
+ int width = 0;
+
+ while(--nglyph) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polyglyph end\n");
+}
+
+
+/* changed area is in dest */
+static void
+RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
+ int dx, int dy, int xOrg, int yOrg)
+{
+ BoxRec box;
+ GCOP_UNWRAP(pGC);
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg);
+
+ box.x1 = xOrg + dst->x;
+ box.x2 = box.x1 + dx;
+ box.y1 = yOrg + dst->y;
+ box.y2 = box.y1 + dy;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("push pixels end\n");
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessScreen.c b/xc/programs/Xserver/hw/darwin/quartz/rootlessScreen.c
new file mode 100644
index 000000000..50428cc4d
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessScreen.c
@@ -0,0 +1,419 @@
+/*
+ * Screen routines for Mac OS X rootless X server
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ *
+ * February 2001 Created
+ * March 3, 2001 Restructured as generic rootless mode
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessScreen.c,v 1.3 2002/10/16 21:13:33 dawes Exp $ */
+
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "mivalidate.h"
+#include "picturestr.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rootlessCommon.h"
+#include "rootlessWindow.h"
+
+extern int
+RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, VTKind kind);
+extern Bool
+RootlessCreateGC(GCPtr pGC);
+
+// Initialize globals
+int rootlessGCPrivateIndex = -1;
+int rootlessScreenPrivateIndex = -1;
+int rootlessWindowPrivateIndex = -1;
+
+
+static Bool
+RootlessCloseScreen(int i, ScreenPtr pScreen)
+{
+ RootlessScreenRec *s;
+
+ s = SCREENREC(pScreen);
+
+ // fixme unwrap everything that was wrapped?
+ pScreen->CloseScreen = s->CloseScreen;
+
+ xfree(s);
+ return pScreen->CloseScreen(i, pScreen);
+}
+
+
+static void
+RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
+ unsigned int format, unsigned long planeMask, char *pdstLine)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ SCREEN_UNWRAP(pScreen, GetImage);
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ // Many apps use GetImage to sync with the visible frame buffer
+ // FIXME: entire screen or just window or all screens?
+ RootlessRedisplayScreen(pScreen);
+
+ // RedisplayScreen stops drawing, so we need to start it again
+ RootlessStartDrawing((WindowPtr)pDrawable);
+ }
+
+ pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
+
+ SCREEN_WRAP(pScreen, GetImage);
+}
+
+
+/*
+ * RootlessSourceValidate
+ * CopyArea and CopyPlane use a GC tied to the destination drawable.
+ * StartDrawing/StopDrawing wrappers won't be called if source is
+ * a visible window but the destination isn't. So, we call StartDrawing
+ * here and leave StopDrawing for the block handler.
+ */
+static void
+RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h)
+{
+ SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr)pDrawable;
+ RootlessStartDrawing(pWin);
+ }
+ if (pDrawable->pScreen->SourceValidate) {
+ pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h);
+ }
+ SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
+}
+
+#ifdef RENDER
+
+static void
+RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ WindowPtr srcWin, dstWin, maskWin = NULL;
+
+ if (pMask) { // pMask can be NULL
+ maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pMask->pDrawable : NULL;
+ }
+ srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pSrc->pDrawable : NULL;
+ dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pDst->pDrawable : NULL;
+
+ // SCREEN_UNWRAP(ps, Composite);
+ ps->Composite = SCREENREC(pScreen)->Composite;
+
+ if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
+ if (maskWin && IsFramedWindow(maskWin)) RootlessStartDrawing(maskWin);
+ if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
+
+ ps->Composite(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+
+ if (dstWin && IsFramedWindow(dstWin)) {
+ RootlessDamageRect(dstWin, xDst, yDst, width, height);
+ }
+
+ ps->Composite = RootlessComposite;
+ // SCREEN_WRAP(ps, Composite);
+}
+
+
+static void
+RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int nlist, GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ int x, y;
+ int n;
+ GlyphPtr glyph;
+ WindowPtr srcWin, dstWin;
+
+ srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pSrc->pDrawable : NULL;
+ dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pDst->pDrawable : NULL;
+
+ if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
+ if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
+
+ //SCREEN_UNWRAP(ps, Glyphs);
+ ps->Glyphs = SCREENREC(pScreen)->Glyphs;
+ ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+ ps->Glyphs = RootlessGlyphs;
+ //SCREEN_WRAP(ps, Glyphs);
+
+ if (dstWin && IsFramedWindow(dstWin)) {
+ x = xSrc;
+ y = ySrc;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ glyph = *glyphs++;
+ RootlessDamageRect(dstWin,
+ x - glyph->info.x, y - glyph->info.y,
+ glyph->info.width, glyph->info.height);
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+ }
+}
+
+#endif // RENDER
+
+
+// RootlessValidateTree
+// ValidateTree is modified in two ways:
+// * top-level windows don't clip each other
+// * windows aren't clipped against root.
+// These only matter when validating from the root.
+static int
+RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
+{
+ int result;
+ RegionRec saveRoot;
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+
+ SCREEN_UNWRAP(pScreen, ValidateTree);
+ RL_DEBUG_MSG("VALIDATETREE start ");
+
+ // Use our custom version to validate from root
+ if (IsRoot(pParent)) {
+ RL_DEBUG_MSG("custom ");
+ result = RootlessMiValidateTree(pParent, pChild, kind);
+ } else {
+ HUGE_ROOT(pParent);
+ result = pScreen->ValidateTree(pParent, pChild, kind);
+ NORMAL_ROOT(pParent);
+ }
+
+ SCREEN_WRAP(pScreen, ValidateTree);
+ RL_DEBUG_MSG("VALIDATETREE end\n");
+
+ return result;
+}
+
+
+// RootlessMarkOverlappedWindows
+// MarkOverlappedWindows is modified to ignore overlapping
+// top-level windows.
+static Bool
+RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
+ WindowPtr *ppLayerWin)
+{
+ RegionRec saveRoot;
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
+ RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
+
+ HUGE_ROOT(pWin);
+ if (IsRoot(pWin)) {
+ // root - mark nothing
+ RL_DEBUG_MSG("is root not marking ");
+ result = FALSE;
+ }
+ else if (! IsTopLevel(pWin)) {
+ // not top-level window - mark normally
+ result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
+ }
+ else {
+ //top-level window - mark children ONLY - NO overlaps with sibs (?)
+ // This code copied from miMarkOverlappedWindows()
+
+ register WindowPtr pChild;
+ Bool anyMarked = FALSE;
+ void (* MarkWindow)() = pScreen->MarkWindow;
+
+ RL_DEBUG_MSG("is top level! ");
+ /* single layered systems are easy */
+ if (ppLayerWin) *ppLayerWin = pWin;
+
+ if (pWin == pFirst) {
+ /* Blindly mark pWin and all of its inferiors. This is a slight
+ * overkill if there are mapped windows that outside pWin's border,
+ * but it's better than wasting time on RectIn checks.
+ */
+ pChild = pWin;
+ while (1) {
+ if (pChild->viewable) {
+ if (REGION_BROKEN (pScreen, &pChild->winSize))
+ SetWinSize (pChild);
+ if (REGION_BROKEN (pScreen, &pChild->borderSize))
+ SetBorderSize (pChild);
+ (* MarkWindow)(pChild);
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+ anyMarked = TRUE;
+ pFirst = pFirst->nextSib;
+ }
+ if (anyMarked)
+ (* MarkWindow)(pWin->parent);
+ result = anyMarked;
+ }
+ NORMAL_ROOT(pWin);
+ SCREEN_WRAP(pScreen, MarkOverlappedWindows);
+ RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
+ return result;
+}
+
+
+// Flush drawing before blocking on select().
+static void
+RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask)
+{
+ RootlessRedisplayScreen((ScreenPtr) pbdata);
+}
+
+
+static void
+RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask)
+{
+ // nothing here
+}
+
+
+static Bool
+RootlessAllocatePrivates(ScreenPtr pScreen)
+{
+ RootlessScreenRec *s;
+ static unsigned long rootlessGeneration = 0;
+
+ if (rootlessGeneration != serverGeneration) {
+ rootlessScreenPrivateIndex = AllocateScreenPrivateIndex();
+ if (rootlessScreenPrivateIndex == -1) return FALSE;
+ rootlessGCPrivateIndex = AllocateGCPrivateIndex();
+ if (rootlessGCPrivateIndex == -1) return FALSE;
+ rootlessWindowPrivateIndex = AllocateWindowPrivateIndex();
+ if (rootlessWindowPrivateIndex == -1) return FALSE;
+ rootlessGeneration = serverGeneration;
+ }
+
+ // no allocation needed for screen privates
+ if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex,
+ sizeof(RootlessGCRec)))
+ return FALSE;
+ if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0))
+ return FALSE;
+
+ s = xalloc(sizeof(RootlessScreenRec));
+ if (! s) return FALSE;
+ SCREENREC(pScreen) = s;
+
+ return TRUE;
+}
+
+
+static void
+RootlessWrap(ScreenPtr pScreen)
+{
+ RootlessScreenRec *s = (RootlessScreenRec*)
+ pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
+
+#define WRAP(a) \
+ if (pScreen->a) { \
+ s->a = pScreen->a; \
+ } else { \
+ RL_DEBUG_MSG("null screen fn " #a "\n"); \
+ s->a = NULL; \
+ } \
+ pScreen->a = Rootless##a
+
+ WRAP(CloseScreen);
+ WRAP(CreateGC);
+ WRAP(PaintWindowBackground);
+ WRAP(PaintWindowBorder);
+ WRAP(CopyWindow);
+ WRAP(GetImage);
+ WRAP(SourceValidate);
+ WRAP(CreateWindow);
+ WRAP(DestroyWindow);
+ WRAP(RealizeWindow);
+ WRAP(UnrealizeWindow);
+ WRAP(MoveWindow);
+ WRAP(PositionWindow);
+ WRAP(ResizeWindow);
+ WRAP(RestackWindow);
+ WRAP(ChangeBorderWidth);
+ WRAP(MarkOverlappedWindows);
+ WRAP(ValidateTree);
+ WRAP(ChangeWindowAttributes);
+
+#ifdef SHAPE
+ WRAP(SetShape);
+#endif
+
+#ifdef RENDER
+ {
+ // Composite and Glyphs don't use normal screen wrapping
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ s->Composite = ps->Composite;
+ ps->Composite = RootlessComposite;
+ s->Glyphs = ps->Glyphs;
+ ps->Glyphs = RootlessGlyphs;
+ }
+#endif
+
+ // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
+ // WRAP(RestoreAreas); fixme put this back?
+
+#undef WRAP
+}
+
+
+/*
+ * RootlessInit
+ * Rootless wraps lots of stuff and needs a bunch of devPrivates.
+ */
+Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcs *procs)
+{
+ RootlessScreenRec *s;
+
+ if (! RootlessAllocatePrivates(pScreen)) return FALSE;
+ s = (RootlessScreenRec*)
+ pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
+
+ s->pScreen = pScreen;
+ s->frameProcs = *procs;
+
+ RootlessWrap(pScreen);
+
+ if (!RegisterBlockAndWakeupHandlers (RootlessBlockHandler,
+ RootlessWakeupHandler,
+ (pointer) pScreen))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessValTree.c b/xc/programs/Xserver/hw/darwin/quartz/rootlessValTree.c
new file mode 100644
index 000000000..c8e5ad0a0
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessValTree.c
@@ -0,0 +1,640 @@
+/*
+ * Calculate window clip lists for rootless mode
+ *
+ * This file is very closely based on mivaltree.c.
+ */
+ /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessValTree.c,v 1.2 2002/06/18 19:43:04 torrey Exp $ */
+
+/*
+ * mivaltree.c --
+ * Functions for recalculating window clip lists. Main function
+ * is miValidateTree.
+ *
+
+Copyright 1987, 1988, 1989, 1998 The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+ *
+ * Copyright 1987, 1988, 1989 by
+ * Digital Equipment Corporation, Maynard, Massachusetts,
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Digital not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ ******************************************************************/
+
+/* The panoramix components contained the following notice */
+/****************************************************************
+* *
+* Copyright (c) Digital Equipment Corporation, 1991, 1997 *
+* *
+* All Rights Reserved. Unpublished rights reserved under *
+* the copyright laws of the United States. *
+* *
+* The software contained on this media is proprietary to *
+* and embodies the confidential technology of Digital *
+* Equipment Corporation. Possession, use, duplication or *
+* dissemination of the software and media is authorized only *
+* pursuant to a valid written license from Digital Equipment *
+* Corporation. *
+* *
+* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure *
+* by the U.S. Government is subject to restrictions as set *
+* forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, *
+* or in FAR 52.227-19, as applicable. *
+* *
+*****************************************************************/
+
+ /*
+ * Aug '86: Susan Angebranndt -- original code
+ * July '87: Adam de Boor -- substantially modified and commented
+ * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
+ * In particular, much improved code for window mapping and
+ * circulating.
+ * Bob Scheifler -- avoid miComputeClips for unmapped windows,
+ * valdata changes
+ */
+#include "X.h"
+#include "scrnintstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "regionstr.h"
+#include "mivalidate.h"
+
+#include "globals.h"
+
+#ifdef SHAPE
+/*
+ * Compute the visibility of a shaped window
+ */
+int
+RootlessShapedWindowIn (pScreen, universe, bounding, rect, x, y)
+ ScreenPtr pScreen;
+ RegionPtr universe, bounding;
+ BoxPtr rect;
+ register int x, y;
+{
+ BoxRec box;
+ register BoxPtr boundBox;
+ int nbox;
+ Bool someIn, someOut;
+ register int t, x1, y1, x2, y2;
+
+ nbox = REGION_NUM_RECTS (bounding);
+ boundBox = REGION_RECTS (bounding);
+ someIn = someOut = FALSE;
+ x1 = rect->x1;
+ y1 = rect->y1;
+ x2 = rect->x2;
+ y2 = rect->y2;
+ while (nbox--)
+ {
+ if ((t = boundBox->x1 + x) < x1)
+ t = x1;
+ box.x1 = t;
+ if ((t = boundBox->y1 + y) < y1)
+ t = y1;
+ box.y1 = t;
+ if ((t = boundBox->x2 + x) > x2)
+ t = x2;
+ box.x2 = t;
+ if ((t = boundBox->y2 + y) > y2)
+ t = y2;
+ box.y2 = t;
+ if (box.x1 > box.x2)
+ box.x2 = box.x1;
+ if (box.y1 > box.y2)
+ box.y2 = box.y1;
+ switch (RECT_IN_REGION(pScreen, universe, &box))
+ {
+ case rgnIN:
+ if (someOut)
+ return rgnPART;
+ someIn = TRUE;
+ break;
+ case rgnOUT:
+ if (someIn)
+ return rgnPART;
+ someOut = TRUE;
+ break;
+ default:
+ return rgnPART;
+ }
+ boundBox++;
+ }
+ if (someIn)
+ return rgnIN;
+ return rgnOUT;
+}
+#endif
+
+#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
+ HasBorder(w) && \
+ (w)->backgroundState == ParentRelative)
+
+
+/*
+ *-----------------------------------------------------------------------
+ * RootlessComputeClips --
+ * Recompute the clipList, borderClip, exposed and borderExposed
+ * regions for pParent and its children. Only viewable windows are
+ * taken into account.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * clipList, borderClip, exposed and borderExposed are altered.
+ * A VisibilityNotify event may be generated on the parent window.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+RootlessComputeClips (pParent, pScreen, universe, kind, exposed)
+ register WindowPtr pParent;
+ register ScreenPtr pScreen;
+ register RegionPtr universe;
+ VTKind kind;
+ RegionPtr exposed; /* for intermediate calculations */
+{
+ int dx,
+ dy;
+ RegionRec childUniverse;
+ register WindowPtr pChild;
+ int oldVis, newVis;
+ BoxRec borderSize;
+ RegionRec childUnion;
+ Bool overlap;
+ RegionPtr borderVisible;
+ Bool resized;
+ /*
+ * Figure out the new visibility of this window.
+ * The extent of the universe should be the same as the extent of
+ * the borderSize region. If the window is unobscured, this rectangle
+ * will be completely inside the universe (the universe will cover it
+ * completely). If the window is completely obscured, none of the
+ * universe will cover the rectangle.
+ */
+ borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
+ borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
+ dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
+ if (dx > 32767)
+ dx = 32767;
+ borderSize.x2 = dx;
+ dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
+ if (dy > 32767)
+ dy = 32767;
+ borderSize.y2 = dy;
+
+ oldVis = pParent->visibility;
+ switch (RECT_IN_REGION( pScreen, universe, &borderSize))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnPART:
+ newVis = VisibilityPartiallyObscured;
+#ifdef SHAPE
+ {
+ RegionPtr pBounding;
+
+ if ((pBounding = wBoundingShape (pParent)))
+ {
+ switch (RootlessShapedWindowIn (pScreen, universe,
+ pBounding, &borderSize,
+ pParent->drawable.x,
+ pParent->drawable.y))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnOUT:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+ }
+ }
+#endif
+ break;
+ default:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+
+ pParent->visibility = newVis;
+ if (oldVis != newVis &&
+ ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
+ SendVisibilityNotify(pParent);
+
+ dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
+ dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
+
+ /*
+ * avoid computations when dealing with simple operations
+ */
+
+ switch (kind) {
+ case VTMap:
+ case VTStack:
+ case VTUnmap:
+ break;
+ case VTMove:
+ if ((oldVis == newVis) &&
+ ((oldVis == VisibilityFullyObscured) ||
+ (oldVis == VisibilityUnobscured)))
+ {
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ if (pChild->visibility != VisibilityFullyObscured)
+ {
+ REGION_TRANSLATE( pScreen, &pChild->borderClip,
+ dx, dy);
+ REGION_TRANSLATE( pScreen, &pChild->clipList,
+ dx, dy);
+ pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pChild, dx, dy);
+
+ }
+ if (pChild->valdata)
+ {
+ REGION_INIT(pScreen,
+ &pChild->valdata->after.borderExposed,
+ NullBox, 0);
+ if (HasParentRelativeBorder(pChild))
+ {
+ REGION_SUBTRACT(pScreen,
+ &pChild->valdata->after.borderExposed,
+ &pChild->borderClip,
+ &pChild->winSize);
+ }
+ REGION_INIT( pScreen, &pChild->valdata->after.exposed,
+ NullBox, 0);
+ }
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+ return;
+ }
+ /* fall through */
+ default:
+ /*
+ * To calculate exposures correctly, we have to translate the old
+ * borderClip and clipList regions to the window's new location so there
+ * is a correspondence between pieces of the new and old clipping regions.
+ */
+ if (dx || dy)
+ {
+ /*
+ * We translate the old clipList because that will be exposed or copied
+ * if gravity is right.
+ */
+ REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
+ REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
+ }
+ break;
+ case VTBroken:
+ REGION_EMPTY (pScreen, &pParent->borderClip);
+ REGION_EMPTY (pScreen, &pParent->clipList);
+ break;
+ }
+
+ borderVisible = pParent->valdata->before.borderVisible;
+ resized = pParent->valdata->before.resized;
+ REGION_INIT( pScreen, &pParent->valdata->after.borderExposed, NullBox, 0);
+ REGION_INIT( pScreen, &pParent->valdata->after.exposed, NullBox, 0);
+
+ /*
+ * Since the borderClip must not be clipped by the children, we do
+ * the border exposure first...
+ *
+ * 'universe' is the window's borderClip. To figure the exposures, remove
+ * the area that used to be exposed from the new.
+ * This leaves a region of pieces that weren't exposed before.
+ */
+
+ if (HasBorder (pParent))
+ {
+ if (borderVisible)
+ {
+ /*
+ * when the border changes shape, the old visible portions
+ * of the border will be saved by DIX in borderVisible --
+ * use that region and destroy it
+ */
+ REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
+ REGION_DESTROY( pScreen, borderVisible);
+ }
+ else
+ {
+ REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
+ }
+ if (HasParentRelativeBorder(pParent) && (dx || dy)) {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
+ universe,
+ &pParent->winSize);
+ } else {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
+ exposed, &pParent->winSize);
+ }
+
+ REGION_COPY( pScreen, &pParent->borderClip, universe);
+
+ /*
+ * To get the right clipList for the parent, and to make doubly sure
+ * that no child overlaps the parent's border, we remove the parent's
+ * border from the universe before proceeding.
+ */
+
+ REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
+ }
+ else
+ REGION_COPY( pScreen, &pParent->borderClip, universe);
+
+ if ((pChild = pParent->firstChild) && pParent->mapped)
+ {
+ REGION_INIT(pScreen, &childUniverse, NullBox, 0);
+ REGION_INIT(pScreen, &childUnion, NullBox, 0);
+ if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
+ ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
+ (pChild->drawable.x < pParent->lastChild->drawable.x)))
+ {
+ for (; pChild; pChild = pChild->nextSib)
+ {
+ if (pChild->viewable)
+ REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
+ }
+ }
+ else
+ {
+ for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
+ {
+ if (pChild->viewable)
+ REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
+ }
+ }
+ REGION_VALIDATE( pScreen, &childUnion, &overlap);
+
+ for (pChild = pParent->firstChild;
+ pChild;
+ pChild = pChild->nextSib)
+ {
+ if (pChild->viewable) {
+ /*
+ * If the child is viewable, we want to remove its extents
+ * from the current universe, but we only re-clip it if
+ * it's been marked.
+ */
+ if (pChild->valdata) {
+ /*
+ * Figure out the new universe from the child's
+ * perspective and recurse.
+ */
+ REGION_INTERSECT( pScreen, &childUniverse,
+ universe,
+ &pChild->borderSize);
+ RootlessComputeClips (pChild, pScreen, &childUniverse,
+ kind, exposed);
+ }
+ /*
+ * Once the child has been processed, we remove its extents
+ * from the current universe, thus denying its space to any
+ * other sibling.
+ */
+ if (overlap)
+ REGION_SUBTRACT( pScreen, universe, universe,
+ &pChild->borderSize);
+ }
+ }
+ if (!overlap)
+ REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
+ REGION_UNINIT( pScreen, &childUnion);
+ REGION_UNINIT( pScreen, &childUniverse);
+ } /* if any children */
+
+ /*
+ * 'universe' now contains the new clipList for the parent window.
+ *
+ * To figure the exposure of the window we subtract the old clip from the
+ * new, just as for the border.
+ */
+
+ if (oldVis == VisibilityFullyObscured ||
+ oldVis == VisibilityNotViewable)
+ {
+ REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
+ }
+ else if (newVis != VisibilityFullyObscured &&
+ newVis != VisibilityNotViewable)
+ {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
+ universe, &pParent->clipList);
+ }
+
+ /*
+ * One last thing: backing storage. We have to try to save what parts of
+ * the window are about to be obscured. We can just subtract the universe
+ * from the old clipList and get the areas that were in the old but aren't
+ * in the new and, hence, are about to be obscured.
+ */
+ if (pParent->backStorage && !resized)
+ {
+ REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe);
+ (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
+ }
+
+ /* HACK ALERT - copying contents of regions, instead of regions */
+ {
+ RegionRec tmp;
+
+ tmp = pParent->clipList;
+ pParent->clipList = *universe;
+ *universe = tmp;
+ }
+
+#ifdef NOTDEF
+ REGION_COPY( pScreen, &pParent->clipList, universe);
+#endif
+
+ pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pParent, dx, dy);
+}
+
+static void
+RootlessTreeObscured(pParent)
+ register WindowPtr pParent;
+{
+ register WindowPtr pChild;
+ register int oldVis;
+
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ oldVis = pChild->visibility;
+ if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
+ ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
+ SendVisibilityNotify(pChild);
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------
+ * RootlessMiValidateTree --
+ * Recomputes the clip list for pParent and all its inferiors.
+ *
+ * Results:
+ * Always returns 1.
+ *
+ * Side Effects:
+ * The clipList, borderClip, exposed, and borderExposed regions for
+ * each marked window are altered.
+ *
+ * Notes:
+ * This routine assumes that all affected windows have been marked
+ * (valdata created) and their winSize and borderSize regions
+ * adjusted to correspond to their new positions. The borderClip and
+ * clipList regions should not have been touched.
+ *
+ * The top-most level is treated differently from all lower levels
+ * because pParent is unchanged. For the top level, we merge the
+ * regions taken up by the marked children back into the clipList
+ * for pParent, thus forming a region from which the marked children
+ * can claim their areas. For lower levels, where the old clipList
+ * and borderClip are invalid, we can't do this and have to do the
+ * extra operations done in miComputeClips, but this is much faster
+ * e.g. when only one child has moved...
+ *
+ *-----------------------------------------------------------------------
+ */
+/*
+ Quartz version: used for validate from root in rootless mode.
+ We need to make sure top-level windows don't clip each other,
+ and that top-level windows aren't clipped to the root window.
+*/
+/*ARGSUSED*/
+// fixme this is ugly
+// Xprint/ValTree.c doesn't work, but maybe that method can?
+int
+RootlessMiValidateTree (pRoot, pChild, kind)
+ WindowPtr pRoot; /* Parent to validate */
+ WindowPtr pChild; /* First child of pRoot that was
+ * affected */
+ VTKind kind; /* What kind of configuration caused call */
+{
+ RegionRec childClip; /* The new borderClip for the current
+ * child */
+ RegionRec exposed; /* For intermediate calculations */
+ register ScreenPtr pScreen;
+ register WindowPtr pWin;
+
+ pScreen = pRoot->drawable.pScreen;
+ if (pChild == NullWindow)
+ pChild = pRoot->firstChild;
+
+ REGION_INIT(pScreen, &childClip, NullBox, 0);
+ REGION_INIT(pScreen, &exposed, NullBox, 0);
+
+ if (REGION_BROKEN (pScreen, &pRoot->clipList) &&
+ !REGION_BROKEN (pScreen, &pRoot->borderClip))
+ {
+ // fixme this might not work, but hopefully doesn't happen anyway.
+ kind = VTBroken;
+ REGION_EMPTY (pScreen, &pRoot->clipList);
+ ErrorF("ValidateTree: BUSTED!\n");
+ }
+
+ /*
+ * Recursively compute the clips for all children of the root.
+ * They don't clip against each other or the root itself, so
+ * childClip is always reset to that child's size.
+ */
+
+ for (pWin = pChild;
+ pWin != NullWindow;
+ pWin = pWin->nextSib)
+ {
+ if (pWin->viewable) {
+ if (pWin->valdata) {
+ REGION_COPY( pScreen, &childClip, &pWin->borderSize);
+ RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
+ } else if (pWin->visibility == VisibilityNotViewable) {
+ RootlessTreeObscured(pWin);
+ }
+ } else {
+ if (pWin->valdata) {
+ REGION_EMPTY( pScreen, &pWin->clipList);
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pWin, 0, 0);
+ REGION_EMPTY( pScreen, &pWin->borderClip);
+ pWin->valdata = (ValidatePtr)NULL;
+ }
+ }
+ }
+
+ REGION_UNINIT( pScreen, &childClip);
+
+ /* The root is never clipped by its children, so nothing on the root
+ is ever exposed by moving or mapping its children. */
+ REGION_INIT( pScreen, &pRoot->valdata->after.exposed, NullBox, 0);
+ REGION_INIT( pScreen, &pRoot->valdata->after.borderExposed, NullBox, 0);
+
+ return 1;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c b/xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c
new file mode 100644
index 000000000..d283b4181
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c
@@ -0,0 +1,829 @@
+/*
+ * Rootless window management
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c,v 1.11 2002/09/28 00:43:39 torrey Exp $ */
+
+#include "rootlessCommon.h"
+#include "rootlessWindow.h"
+
+#include "fb.h"
+
+
+/*
+ * RootlessFrameForWindow
+ * Returns the rootless frame for the given window, or
+ * NULL if the the window is not inside a frame.
+ * Unrealized windows never have a frame.
+ */
+RootlessFramePtr
+RootlessFrameForWindow(WindowPtr pWin)
+{
+ WindowPtr top = TopLevelParent(pWin);
+ RootlessWindowRec *winRec;
+
+ if (!top) return NULL;
+ winRec = WINREC(top);
+ if (!winRec) return NULL;
+ return &winRec->frame;
+}
+
+
+// RootlessCreateWindow
+// For now, don't create a frame until the window is realized.
+// Do reset the window size so it's not clipped by the root window.
+Bool
+RootlessCreateWindow(WindowPtr pWin)
+{
+ Bool result;
+ RegionRec saveRoot;
+
+ WINREC(pWin) = NULL;
+ SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
+ if (!IsRoot(pWin)) {
+ // win/border size set by DIX, not by wrapped CreateWindow, so
+ // correct it here.
+ // Don't HUGE_ROOT when pWin is the root!
+ HUGE_ROOT(pWin);
+ SetWinSize(pWin);
+ SetBorderSize(pWin);
+ }
+ result = pWin->drawable.pScreen->CreateWindow(pWin);
+ if (pWin->parent) {
+ NORMAL_ROOT(pWin);
+ }
+ SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
+ return result;
+}
+
+
+// RootlessDestroyWindow
+// For now, all window destruction takes place in UnrealizeWindow
+Bool
+RootlessDestroyWindow(WindowPtr pWin)
+{
+ Bool result;
+
+ SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
+ result = pWin->drawable.pScreen->DestroyWindow(pWin);
+ SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
+ return result;
+}
+
+
+#ifdef SHAPE
+
+// RootlessSetShape
+// Shape is usually set before the window is mapped, but (for now) we
+// don't keep track of frames before they're mapped. So we just record
+// that the shape needs to updated later.
+void
+RootlessSetShape(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RootlessDamageShape(pWin);
+ SCREEN_UNWRAP(pScreen, SetShape);
+ pScreen->SetShape(pWin);
+ SCREEN_WRAP(pScreen, SetShape);
+}
+
+#endif // SHAPE
+
+
+// Disallow ParentRelative background on top-level windows
+// because the root window doesn't really have the right background
+// and fb will try to draw on the root instead of on the window.
+// ParentRelative prevention is also in PaintWindowBackground/Border()
+// so it is no longer really needed here.
+Bool
+RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("change window attributes start ");
+
+ SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
+ result = pScreen->ChangeWindowAttributes(pWin, vmask);
+ SCREEN_WRAP(pScreen, ChangeWindowAttributes);
+
+ if (WINREC(pWin)) {
+ // disallow ParentRelative background state
+ if (pWin->backgroundState == ParentRelative) {
+ XID pixel = 0;
+ ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
+ }
+ }
+
+ RL_DEBUG_MSG("change window attributes end\n");
+ return result;
+}
+
+
+/* RootlessPositionWindow
+ * This is a hook for when DIX moves or resizes a window.
+ * Update the frame position now. (x, y) are *inside* position.
+ * After this, mi and fb are expecting the pixmap to be at the new location.
+ */
+Bool
+RootlessPositionWindow(WindowPtr pWin, int x, int y)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ Bool result;
+
+ RL_DEBUG_MSG("positionwindow start (win 0x%x)\n", pWin);
+
+ if (winRec) {
+ if (winRec->drawing) {
+ // Reset frame's pixmap and move it to the new position.
+ int bw = wBorderWidth(pWin);
+
+ winRec->pixmap->devPrivate.ptr = winRec->frame.pixelData;
+ SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw);
+
+ // Move damaged region to correspond to new window position
+ if (REGION_NOTEMPTY(pScreen, &winRec->damage)) {
+ REGION_TRANSLATE(pScreen, &winRec->damage,
+ x - bw - winRec->frame.x,
+ y - bw - winRec->frame.y);
+ }
+ }
+ }
+
+ SCREEN_UNWRAP(pScreen, PositionWindow);
+ result = pScreen->PositionWindow(pWin, x, y);
+ SCREEN_WRAP(pScreen, PositionWindow);
+
+ RL_DEBUG_MSG("positionwindow end\n");
+ return result;
+}
+
+
+// RootlessRealizeWindow
+// The frame is created here and not in CreateWindow so that windows do
+// not eat memory until they are realized.
+Bool
+RootlessRealizeWindow(WindowPtr pWin)
+{
+ Bool result = FALSE;
+ RegionRec saveRoot;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin);
+
+ if (IsTopLevel(pWin) || IsRoot(pWin)) {
+ DrawablePtr d = &pWin->drawable;
+ RootlessWindowRec *winRec = xalloc(sizeof(RootlessWindowRec));
+ int bw = wBorderWidth(pWin);
+
+ RL_DEBUG_MSG("Top level window ");
+ if (! winRec) goto windowcreatebad;
+
+ winRec->frame.isRoot = (pWin == WindowTable[pScreen->myNum]);
+ winRec->frame.x = d->x - bw;
+ winRec->frame.y = d->y - bw;
+ winRec->frame.w = d->width + 2*bw;
+ winRec->frame.h = d->height + 2*bw;
+ winRec->frame.win = pWin;
+ winRec->frame.devPrivate = NULL;
+
+ REGION_INIT(pScreen, &winRec->damage, NullBox, 0);
+ winRec->borderWidth = bw;
+ winRec->drawing = FALSE;
+
+ winRec->pixmap = NULL;
+
+ WINREC(pWin) = winRec;
+
+ RL_DEBUG_MSG("creating frame ");
+ CallFrameProc(pScreen, CreateFrame,
+ (pScreen, &WINREC(pWin)->frame,
+ pWin->prevSib ? &WINREC(pWin->prevSib)->frame : NULL));
+ if (!winRec->frame.devPrivate) goto windowcreatebad;
+
+ // Disallow ParentRelative background state on top-level windows.
+ // This might have been set before the window was mapped.
+ if (pWin->backgroundState == ParentRelative) {
+ XID pixel = 0;
+ ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
+ }
+
+#ifdef SHAPE
+ // Shape is usually set before the window is mapped, but
+ // (for now) we don't keep track of frames before they're mapped.
+ winRec->shapeDamage = TRUE;
+#endif
+ }
+
+ if (!IsRoot(pWin)) HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, RealizeWindow);
+ result = pScreen->RealizeWindow(pWin);
+ SCREEN_WRAP(pScreen, RealizeWindow);
+ if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
+
+ RL_DEBUG_MSG("realizewindow end\n");
+ return result;
+
+windowcreatebad:
+ RL_DEBUG_MSG("window create bad! ");
+ RL_DEBUG_MSG("realizewindow end\n");
+ return NULL;
+}
+
+
+Bool
+RootlessUnrealizeWindow(WindowPtr pWin)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("unrealizewindow start ");
+
+ if (IsTopLevel(pWin) || IsRoot(pWin)) {
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ RootlessRedisplay(pWin);
+ CallFrameProc(pScreen, DestroyFrame, (pScreen, &winRec->frame));
+
+ REGION_UNINIT(pScreen, &winRec->damage);
+
+ xfree(winRec);
+ WINREC(pWin) = NULL;
+ }
+
+ SCREEN_UNWRAP(pScreen, UnrealizeWindow);
+ result = pScreen->UnrealizeWindow(pWin);
+ SCREEN_WRAP(pScreen, UnrealizeWindow);
+ RL_DEBUG_MSG("unrealizewindow end\n");
+ return result;
+}
+
+
+void
+RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
+{
+ RegionRec saveRoot;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("restackwindow start ");
+ if (winRec) RL_DEBUG_MSG("restack top level \n");
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, RestackWindow);
+ if (pScreen->RestackWindow) pScreen->RestackWindow(pWin, pOldNextSib);
+ SCREEN_WRAP(pScreen, RestackWindow);
+ NORMAL_ROOT(pWin);
+
+ if (winRec) {
+ // fixme simplify the following
+
+ WindowPtr oldNextW, newNextW, oldPrevW, newPrevW;
+ RootlessFramePtr oldNext, newNext, oldPrev, newPrev;
+
+ oldNextW = pOldNextSib;
+ while (oldNextW && ! WINREC(oldNextW)) oldNextW = oldNextW->nextSib;
+ oldNext = oldNextW ? &WINREC(oldNextW)->frame : NULL;
+
+ newNextW = pWin->nextSib;
+ while (newNextW && ! WINREC(newNextW)) newNextW = newNextW->nextSib;
+ newNext = newNextW ? &WINREC(newNextW)->frame : NULL;
+
+ oldPrevW= pOldNextSib ? pOldNextSib->prevSib : pWin->parent->lastChild;
+ while (oldPrevW && ! WINREC(oldPrevW)) oldPrevW = oldPrevW->prevSib;
+ oldPrev = oldPrevW ? &WINREC(oldPrevW)->frame : NULL;
+
+ newPrevW = pWin->prevSib;
+ while (newPrevW && ! WINREC(newPrevW)) newPrevW = newPrevW->prevSib;
+ newPrev = newPrevW ? &WINREC(newPrevW)->frame : NULL;
+
+ if (pWin->prevSib) {
+ WindowPtr w = pWin->prevSib;
+ while (w) {
+ RL_DEBUG_MSG("w 0x%x\n", w);
+ w = w->parent;
+ }
+ }
+
+ CallFrameProc(pScreen, RestackFrame,
+ (pScreen, &winRec->frame, oldPrev, newPrev));
+ }
+
+ RL_DEBUG_MSG("restackwindow end\n");
+}
+
+
+/*
+ * Specialized window copy procedures
+ */
+
+// Globals needed during window resize and move.
+static PixmapPtr gResizeDeathPix = NULL;
+static pointer gResizeDeathBits = NULL;
+static PixmapPtr gResizeCopyWindowSource = NULL;
+static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
+
+// CopyWindow() that doesn't do anything.
+// For MoveWindow() of top-level windows.
+static void
+RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ // some code expects the region to be translated
+ int dx = ptOldOrg.x - pWin->drawable.x;
+ int dy = ptOldOrg.y - pWin->drawable.y;
+ RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
+
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+}
+
+
+// CopyWindow used during ResizeWindow for gravity moves.
+// Cloned from fbCopyWindow
+// The original always draws on the root pixmap (which we don't have).
+// Instead, draw on the parent window's pixmap.
+// Resize version: the old location's pixels are in gResizeCopyWindowSource
+static void
+RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ // Don't unwrap pScreen->CopyWindow.
+ // The bogus rewrap with RootlessCopyWindow causes a crash if
+ // CopyWindow is called again during the same resize.
+ RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
+
+ {
+ RegionRec rgnDst;
+ int dx, dy;
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
+ REGION_INIT(pScreen, &rgnDst, NullBox, 0);
+ REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ RootlessStartDrawing(pWin);
+ fbCopyRegion (&gResizeCopyWindowSource->drawable,
+ &pScreen->GetWindowPixmap(pWin)->drawable,
+ 0,
+ &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
+
+ // don't update - resize will update everything
+ REGION_UNINIT(pScreen, &rgnDst);
+ fbValidateDrawable (&pWin->drawable);
+ }
+
+ RL_DEBUG_MSG("resizecopywindowFB end\n");
+}
+
+
+/* Update *new* location of window. Old location is redrawn with
+ * PaintWindowBackground/Border.
+ * Cloned from fbCopyWindow
+ * The original always draws on the root pixmap (which we don't have).
+ * Instead, draw on the parent window's pixmap.
+ */
+void
+RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ SCREEN_UNWRAP(pScreen, CopyWindow);
+ RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
+
+ {
+ RegionRec rgnDst;
+ int dx, dy;
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT(pScreen, &rgnDst, NullBox, 0);
+ REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ RootlessStartDrawing(pWin);
+ fbCopyRegion ((DrawablePtr)pWin, (DrawablePtr)pWin,
+ 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
+
+ // prgnSrc has been translated to dst position
+ RootlessDamageRegion(pWin, prgnSrc);
+ REGION_UNINIT(pScreen, &rgnDst);
+ fbValidateDrawable (&pWin->drawable);
+ }
+
+ SCREEN_WRAP(pScreen, CopyWindow);
+ RL_DEBUG_MSG("copywindowFB end\n");
+}
+
+
+/*
+ * Window resize procedures
+ */
+
+// Prepare to resize a top-level window.
+// The old window's pixels are saved and the implementation is told
+// to change the window size.
+// (x,y,w,h) is outer frame of window (outside border)
+static void
+StartFrameResize(WindowPtr pWin, Bool gravity,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH, unsigned int oldBW,
+ int newX, int newY,
+ unsigned int newW, unsigned int newH, unsigned int newBW)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
+ RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d ",
+ oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+
+ RootlessRedisplay(pWin);
+
+ // Make a copy of the current pixmap and all its data.
+ // The original will go away when we ask the frame manager to
+ // allocate the new pixmap.
+ RootlessStartDrawing(pWin);
+ gResizeDeathBits = xalloc(winRec->frame.bytesPerRow * winRec->frame.h);
+ memcpy(gResizeDeathBits, winRec->frame.pixelData,
+ winRec->frame.bytesPerRow * winRec->frame.h);
+ gResizeDeathPix =
+ GetScratchPixmapHeader(pScreen, winRec->frame.w, winRec->frame.h,
+ winRec->frame.depth, winRec->frame.bitsPerPixel,
+ winRec->frame.bytesPerRow, gResizeDeathBits);
+ SetPixmapBaseToScreen(gResizeDeathPix, oldX, oldY);
+ RootlessStopDrawing(pWin);
+
+ winRec->frame.x = newX;
+ winRec->frame.y = newY;
+ winRec->frame.w = newW;
+ winRec->frame.h = newH;
+ winRec->borderWidth = newBW;
+
+ CallFrameProc(pScreen, StartResizeFrame,
+ (pScreen, &winRec->frame, oldX, oldY, oldW, oldH));
+ RootlessStartDrawing(pWin);
+
+ // Use custom CopyWindow when moving gravity bits around
+ // ResizeWindow assumes the old window contents are in the same
+ // pixmap, but here they're in deathPix instead.
+ if (gravity) {
+ gResizeCopyWindowSource = gResizeDeathPix;
+ gResizeOldCopyWindowProc = pScreen->CopyWindow;
+ pScreen->CopyWindow = RootlessResizeCopyWindow;
+ }
+
+ // Copy pixels in intersection from src to dst.
+ // ResizeWindow assumes these pixels are already present when
+ // making gravity adjustments.
+ // pWin currently has new-sized pixmap but is in old position.
+ // fixme border width change!
+ {
+ BoxRec rect;
+ DrawablePtr src = &gResizeDeathPix->drawable;
+ DrawablePtr dst = &pScreen->GetWindowPixmap(pWin)->drawable;
+ // These vars are needed because implicit unsigned->signed fails
+ int oldX2 = (int)(oldX + oldW), newX2 = (int)(newX + newW);
+ int oldY2 = (int)(oldY + oldH), newY2 = (int)(newY + newH);
+
+ rect.x1 = max(oldX, newX);
+ rect.y1 = max(oldY, newY);
+ rect.x2 = min(oldX2, newX2);
+ rect.y2 = min(oldY2, newY2);
+
+ RL_DEBUG_MSG("Resize copy rect %d %d %d %d ",
+ rect.x1, rect.y1, rect.x2, rect.y2);
+
+ // rect is the intersection of the old location and new location
+ if (BOX_NOT_EMPTY(rect)) {
+ fbCopyWindowProc(src, dst, NULL, &rect, 1, 0, 0,
+ FALSE, FALSE, 0, 0);
+ }
+ }
+}
+
+
+static void
+FinishFrameResize(WindowPtr pWin, Bool gravity,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH, unsigned int oldBW,
+ int newX, int newY,
+ unsigned int newW, unsigned int newH, unsigned int newBW)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ CallFrameProc(pScreen, FinishResizeFrame,
+ (pScreen, &winRec->frame, oldX, oldY, oldW, oldH));
+ if (wBoundingShape(pWin)) {
+ RootlessDamageShape(pWin);
+ }
+
+ // Destroy temp pixmap
+ FreeScratchPixmapHeader(gResizeDeathPix);
+ xfree(gResizeDeathBits);
+ gResizeDeathPix = gResizeDeathBits = NULL;
+
+ if (gravity) {
+ pScreen->CopyWindow = gResizeOldCopyWindowProc;
+ gResizeCopyWindowSource = NULL;
+ }
+}
+
+
+// If kind==VTOther, window border is resizing (and borderWidth is
+// already changed!!@#$) This case works like window resize, not move.
+void
+RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
+{
+ CopyWindowProcPtr oldCopyWindowProc = NULL;
+ RegionRec saveRoot;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ int oldX = 0, oldY = 0, newX = 0, newY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
+
+ RL_DEBUG_MSG("movewindow start \n");
+
+ if (winRec) {
+ if (kind == VTMove) {
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ RootlessRedisplay(pWin);
+ RootlessStartDrawing(pWin);
+ } else {
+ RL_DEBUG_MSG("movewindow border resizing ");
+ oldBW = winRec->borderWidth;
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ oldW = winRec->frame.w;
+ oldH = winRec->frame.h;
+ newBW = wBorderWidth(pWin);
+ newX = x;
+ newY = y;
+ newW = pWin->drawable.width + 2*newBW;
+ newH = pWin->drawable.height + 2*newBW;
+ StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+ }
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, MoveWindow);
+ if (winRec) {
+ oldCopyWindowProc = pScreen->CopyWindow;
+ pScreen->CopyWindow = RootlessNoCopyWindow;
+ }
+ pScreen->MoveWindow(pWin, x, y, pSib, kind);
+ if (winRec) {
+ pScreen->CopyWindow = oldCopyWindowProc;
+ }
+ NORMAL_ROOT(pWin);
+ SCREEN_WRAP(pScreen, MoveWindow);
+
+ if (winRec) {
+ if (kind == VTMove) {
+ winRec->frame.x = x;
+ winRec->frame.y = y;
+ RootlessStopDrawing(pWin);
+ CallFrameProc(pScreen, MoveFrame,
+ (pScreen, &winRec->frame, oldX, oldY));
+ } else {
+ FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+ }
+
+ RL_DEBUG_MSG("movewindow end\n");
+}
+
+
+// Note: (x, y, w, h) as passed to this procedure don't match
+// the frame definition.
+// (x,y) is corner of very outer edge, *outside* border
+// w,h is width and height *inside* border, *ignoring* border width
+// The rect (x, y, w, h) doesn't mean anything.
+// (x, y, w+2*bw, h+2*bw) is total rect
+// (x+bw, y+bw, w, h) is inner rect
+
+void
+RootlessResizeWindow(WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib)
+{
+ RegionRec saveRoot;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ int oldX = 0, oldY = 0, newX = 0, newY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
+
+ RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
+
+ if (winRec) {
+ oldBW = winRec->borderWidth;
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ oldW = winRec->frame.w;
+ oldH = winRec->frame.h;
+
+ newBW = oldBW;
+ newX = x;
+ newY = y;
+ newW = w + 2*newBW;
+ newH = h + 2*newBW;
+
+ StartFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, ResizeWindow);
+ pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
+ SCREEN_WRAP(pScreen, ResizeWindow);
+ NORMAL_ROOT(pWin);
+
+ if (winRec) {
+ FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ RL_DEBUG_MSG("resizewindow end\n");
+}
+
+
+/*
+ * SetPixmapOfAncestors
+ * Set the Pixmaps on all ParentRelative windows up the ancestor chain.
+ */
+static void
+SetPixmapOfAncestors(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ WindowPtr topWin = TopLevelParent(pWin);
+ RootlessWindowRec *topWinRec = WINREC(topWin);
+
+ while (pWin->backgroundState == ParentRelative) {
+ if (pWin == topWin) {
+ // disallow ParentRelative background state on top level
+ XID pixel = 0;
+ ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
+ RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
+ break;
+ }
+
+ pWin = pWin->parent;
+ pScreen->SetWindowPixmap(pWin, topWinRec->pixmap);
+ }
+}
+
+
+/*
+ * RootlessPaintWindowBackground
+ * Paint the window background while filling in the alpha channel with all on.
+ */
+void
+RootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ int oldBackgroundState = 0;
+ PixUnion oldBackground;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ SCREEN_UNWRAP(pScreen, PaintWindowBackground);
+ RL_DEBUG_MSG("paintwindowbackground start (win 0x%x, framed %i) ",
+ pWin, IsFramedWindow(pWin));
+
+ if (IsFramedWindow(pWin)) {
+ if (IsRoot(pWin)) {
+ // set root background to magic transparent color
+ oldBackgroundState = pWin->backgroundState;
+ oldBackground = pWin->background;
+ pWin->backgroundState = BackgroundPixel;
+ pWin->background.pixel = 0x00fffffe;
+ }
+ RootlessStartDrawing(pWin);
+ RootlessDamageRegion(pWin, pRegion);
+
+ // For ParentRelative windows, we have to make sure the window
+ // pixmap is set correctly all the way up the ancestor chain.
+ if (pWin->backgroundState == ParentRelative) {
+ SetPixmapOfAncestors(pWin);
+ }
+ }
+
+ pScreen->PaintWindowBackground(pWin, pRegion, what);
+
+ if (IsRoot(pWin)) {
+ pWin->backgroundState = oldBackgroundState;
+ pWin->background = oldBackground;
+ }
+
+ SCREEN_WRAP(pScreen, PaintWindowBackground);
+ RL_DEBUG_MSG("paintwindowbackground end\n");
+}
+
+
+/*
+ * RootlessPaintWindowBorder
+ * Paint the window border while filling in the alpha channel with all on.
+ */
+void
+RootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder);
+ RL_DEBUG_MSG("paintwindowborder start (win 0x%x) ", pWin);
+
+ if (IsFramedWindow(pWin)) {
+ RootlessStartDrawing(pWin);
+ RootlessDamageRegion(pWin, pRegion);
+
+ // For ParentRelative windows with tiled borders, we have to make
+ // sure the window pixmap is set correctly all the way up the
+ // ancestor chain.
+ if (!pWin->borderIsPixel &&
+ pWin->backgroundState == ParentRelative)
+ {
+ SetPixmapOfAncestors(pWin);
+ }
+ }
+
+ pWin->drawable.pScreen->PaintWindowBorder(pWin, pRegion, what);
+
+ SCREEN_WRAP(pWin->drawable.pScreen, PaintWindowBorder);
+ RL_DEBUG_MSG("paintwindowborder end\n");
+}
+
+
+// fixme untested!
+// pWin inside corner stays the same
+// pWin->drawable.[xy] stays the same
+// frame moves and resizes
+void
+RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
+{
+ RegionRec saveRoot;
+
+ RL_DEBUG_MSG("change border width ");
+ if (width != wBorderWidth(pWin)) {
+ RootlessWindowRec *winRec = WINREC(pWin);
+ int oldX = 0, oldY = 0, newX = 0, newY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0;
+ unsigned int newW = 0, newH = 0, newBW = 0;
+
+ if (winRec) {
+ oldBW = winRec->borderWidth;
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ oldW = winRec->frame.w;
+ oldH = winRec->frame.h;
+
+ newBW = width;
+ newX = pWin->drawable.x - newBW;
+ newY = pWin->drawable.y - newBW;
+ newW = pWin->drawable.width + 2*newBW;
+ newH = pWin->drawable.height + 2*newBW;
+
+ StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
+ pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
+ SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
+ NORMAL_ROOT(pWin);
+
+ if (winRec) {
+ FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+ }
+ RL_DEBUG_MSG("change border width end\n");
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.h b/xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.h
new file mode 100644
index 000000000..ef3852d93
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.h
@@ -0,0 +1,36 @@
+/*
+ * Rootless window management
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.h,v 1.2 2002/04/03 00:06:32 torrey Exp $ */
+
+#ifndef _ROOTLESSWINDOW_H
+#define _ROOTLESSWINDOW_H
+
+#include "rootlessCommon.h"
+
+
+Bool RootlessCreateWindow(WindowPtr pWin);
+Bool RootlessDestroyWindow(WindowPtr pWin);
+
+#ifdef SHAPE
+void RootlessSetShape(WindowPtr pWin);
+#endif // SHAPE
+
+Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask);
+Bool RootlessPositionWindow(WindowPtr pWin, int x, int y);
+Bool RootlessRealizeWindow(WindowPtr pWin);
+Bool RootlessUnrealizeWindow(WindowPtr pWin);
+void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
+void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc);
+void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind);
+void RootlessResizeWindow(WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib);
+void RootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
+ int what);
+void RootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
+ int what);
+void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
+
+#endif
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/Imakefile b/xc/programs/Xserver/hw/darwin/quartz_1.3/Imakefile
new file mode 100644
index 000000000..c4299239a
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/Imakefile
@@ -0,0 +1,127 @@
+XCOMM $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/Imakefile,v 1.1 2002/03/28 02:21:20 torrey Exp $
+
+#include <Server.tmpl>
+
+LinkSourceFile(Preferences.m,../quartz)
+LinkSourceFile(Preferences.h,../quartz)
+LinkSourceFile(XApplication.m,../quartz)
+LinkSourceFile(XApplication.h,../quartz)
+LinkSourceFile(fakeBoxRec.h,../quartz)
+LinkSourceFile(fullscreen.c,../quartz)
+LinkSourceFile(fullscreen.h,../quartz)
+LinkSourceFile(quartz.c,../quartz)
+LinkSourceFile(quartz.h,../quartz)
+LinkSourceFile(quartzAudio.c,../quartz)
+LinkSourceFile(quartzAudio.h,../quartz)
+LinkSourceFile(quartzCocoa.m,../quartz)
+LinkSourceFile(quartzCommon.h,../quartz)
+LinkSourceFile(quartzCursor.c,../quartz)
+LinkSourceFile(quartzCursor.h,../quartz)
+LinkSourceFile(quartzPasteboard.c,../quartz)
+LinkSourceFile(quartzPasteboard.h,../quartz)
+LinkSourceFile(quartzShared.h,../quartz)
+LinkSourceFile(pseudoramiX.c,../quartz)
+LinkSourceFile(pseudoramiX.h,../quartz)
+LinkSourceFile(quartzStartup.c,../quartz)
+LinkSourceFile(XDarwinStartup.c,../quartz)
+LinkSourceFile(XDarwinStartup.man,../quartz)
+
+SRCS = Preferences.m \
+ XApplication.m \
+ XServer.m \
+ XView.m \
+ XWindow.m \
+ fullscreen.c \
+ quartz.c \
+ quartzAudio.c \
+ quartzCocoa.m \
+ quartzCursor.c \
+ quartzPasteboard.c \
+ rootlessAquaGlue.c \
+ rootlessAquaImp.m \
+ rootlessCommon.c \
+ rootlessGC.c \
+ rootlessScreen.c \
+ rootlessValTree.c \
+ rootlessWindow.c \
+ pseudoramiX.c
+
+OBJS = Preferences.o \
+ XApplication.o \
+ XServer.o \
+ XView.o \
+ XWindow.o \
+ fullscreen.o \
+ quartz.o \
+ quartzAudio.o \
+ quartzCocoa.o \
+ quartzCursor.o \
+ quartzPasteboard.o \
+ rootlessAquaGlue.o \
+ rootlessAquaImp.o \
+ rootlessCommon.o \
+ rootlessGC.o \
+ rootlessScreen.o \
+ rootlessValTree.o \
+ rootlessWindow.o \
+ pseudoramiX.o
+
+INCLUDES = -I. -I$(SERVERSRC)/fb -I$(SERVERSRC)/mi -I$(SERVERSRC)/include \
+ -I$(XINCLUDESRC) -I$(FONTINCSRC) -I$(SERVERSRC)/render \
+ -I$(EXTINCSRC) -I.. -I$(SERVERSRC)/Xext
+
+#if defined(XFree86CustomVersion)
+CUSTOMVERSION = XFree86CustomVersion
+CUSTOMVERDEF = -DXF86_CUSTOM_VERSION='$(CUSTOMVERSION)'
+#endif
+#if HasCGMachPort
+QUARTZDEFINES = -DHAS_CG_MACH_PORT
+#endif
+
+#if XFree86Devel
+PBXBUILDSTYLE = -buildstyle Development
+DEBUGDEFINES = -DROOTLESSDEBUG
+#else
+PBXBUILDSTYLE = -buildstyle Deployment
+#endif
+
+DEFINES = $(CUSTOMVERDEF) -DXBINDIR=$(BINDIR) -DXINITDIR=$(XINITDIR) \
+ $(QUARTZDEFINES) $(DEBUGDEFINES)
+EXTRAMANDEFS = -D__XBinDir__=$(BINDIR)
+#if NothingOutsideProjectRoot
+XDARWINROOT = $(BINDIR)
+#else
+XDARWINROOT = /Applications
+#endif
+
+MakeSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(XQuartz,$(OBJS))
+
+AllTarget(quartzStartup.o)
+
+AllTarget(XDarwinStartup)
+NormalProgramTarget(XDarwinStartup,XDarwinStartup.o, \
+ NullParameter,NullParameter, \
+ -framework CoreFoundation -framework ApplicationServices)
+InstallProgram(XDarwinStartup,$(BINDIR))
+install::
+ -(cd $(DESTDIR)$(BINDIR); $(RM) X; $(LN) XDarwinStartup X)
+
+AllTarget(XDarwin)
+XDarwin:
+ pbxbuild -target XDarwin $(PBXBUILDSTYLE)
+
+install::
+ pbxbuild install -target XDarwin $(PBXBUILDSTYLE) \
+ DSTROOT=$(DESTDIR)$(XDARWINROOT)
+
+InstallManPage(XDarwinStartup,$(MANDIR))
+
+clean::
+ pbxbuild "clean" -target XDarwin $(PBXBUILDSTYLE)
+
+DependTarget()
+
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/XDarwin.pbproj/project.pbxproj b/xc/programs/Xserver/hw/darwin/quartz_1.3/XDarwin.pbproj/project.pbxproj
new file mode 100644
index 000000000..af700a442
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/XDarwin.pbproj/project.pbxproj
@@ -0,0 +1,1372 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 32;
+ objects = {
+ 01279092000747AA0A000002 = {
+ isa = PBXFileReference;
+ path = XServer.m;
+ refType = 4;
+ };
+ 0127909600074AF60A000002 = {
+ isa = PBXFileReference;
+ name = XApplication.m;
+ path = ../quartz/XApplication.m;
+ refType = 4;
+ };
+ 0127909800074B1A0A000002 = {
+ isa = PBXFileReference;
+ name = XApplication.h;
+ path = ../quartz/XApplication.h;
+ refType = 4;
+ };
+ 014C68ED00ED6A9D7F000001 = {
+ isa = PBXFileReference;
+ path = XView.h;
+ refType = 4;
+ };
+ 014C68EE00ED6A9D7F000001 = {
+ isa = PBXFileReference;
+ path = XView.m;
+ refType = 4;
+ };
+ 014C68EF00ED6A9D7F000001 = {
+ isa = PBXFileReference;
+ path = XWindow.h;
+ refType = 4;
+ };
+ 014C68F000ED6A9D7F000001 = {
+ isa = PBXFileReference;
+ path = XWindow.m;
+ refType = 4;
+ };
+ 014C68F200ED7AD67F000001 = {
+ isa = PBXFileReference;
+ name = fakeBoxRec.h;
+ path = ../quartz/fakeBoxRec.h;
+ refType = 4;
+ };
+ 014C68F300EE5AB97F000001 = {
+ isa = PBXFileReference;
+ path = rootlessCommon.c;
+ refType = 4;
+ };
+ 014C68F400EE5AB97F000001 = {
+ isa = PBXFileReference;
+ path = rootlessCommon.h;
+ refType = 4;
+ };
+ 014C68F700EE678F7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessWindow.c;
+ refType = 4;
+ };
+ 014C68F800EE678F7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessWindow.h;
+ refType = 4;
+ };
+ 015698ED003DF345CE6F79C2 = {
+ isa = PBXFileReference;
+ path = XDarwin.icns;
+ refType = 4;
+ };
+ 0157A37D002CF6D7CE6F79C2 = {
+ children = (
+ F533214601A4B45401000001,
+ 0157A37E002CF6D7CE6F79C2,
+ F58D65DF018F79B101000001,
+ F533213D0193CBE001000001,
+ 43B962E200617B93416877C2,
+ F5ACD263C5BE031F01000001,
+ F51BF62E02026E3501000001,
+ F5ACD25CC5B5E96601000001,
+ F587E16401924C6901000001,
+ );
+ isa = PBXVariantGroup;
+ name = Credits.rtf;
+ path = "";
+ refType = 4;
+ };
+ 0157A37E002CF6D7CE6F79C2 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/Credits.rtf;
+ refType = 4;
+ };
+ 015EDCEA004203A8CE6F79C2 = {
+ isa = PBXFrameworkReference;
+ name = IOKit.framework;
+ path = /System/Library/Frameworks/IOKit.framework;
+ refType = 0;
+ };
+ 017D6F4400E861FB7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessGC.c;
+ refType = 4;
+ };
+ 017D6F4500E861FB7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessScreen.c;
+ refType = 4;
+ };
+ 018F40F2003E1902CE6F79C2 = {
+ children = (
+ 018F40F3003E1916CE6F79C2,
+ 021D6BA9003E1BACCE6F79C2,
+ 3E74E03600863F047F000001,
+ 018F40F6003E1974CE6F79C2,
+ );
+ isa = PBXGroup;
+ name = "X Server";
+ path = ..;
+ refType = 4;
+ };
+ 018F40F3003E1916CE6F79C2 = {
+ isa = PBXFileReference;
+ path = darwin.c;
+ refType = 4;
+ };
+ 018F40F6003E1974CE6F79C2 = {
+ isa = PBXFileReference;
+ path = darwinKeyboard.c;
+ refType = 4;
+ };
+ 018F40F8003E1979CE6F79C2 = {
+ isa = PBXFileReference;
+ path = quartz.c;
+ refType = 4;
+ };
+ 018F40FA003E197ECE6F79C2 = {
+ isa = PBXFileReference;
+ path = quartz.h;
+ refType = 4;
+ };
+ 018F40FC003E1983CE6F79C2 = {
+ isa = PBXFileReference;
+ path = xfIOKit.c;
+ refType = 4;
+ };
+ 018F40FE003E1988CE6F79C2 = {
+ isa = PBXFileReference;
+ path = xfIOKit.h;
+ refType = 4;
+ };
+ 018F4100003E19E4CE6F79C2 = {
+ isa = PBXFileReference;
+ path = xfIOKitCursor.c;
+ refType = 4;
+ };
+//010
+//011
+//012
+//013
+//014
+//020
+//021
+//022
+//023
+//024
+ 021D6BA9003E1BACCE6F79C2 = {
+ isa = PBXFileReference;
+ path = darwin.h;
+ refType = 4;
+ };
+ 02A1FEA6006D34BE416877C2 = {
+ isa = PBXFileReference;
+ path = xfIOKitStartup.c;
+ refType = 4;
+ };
+ 02A1FEA8006D38F0416877C2 = {
+ isa = PBXFileReference;
+ path = quartzStartup.c;
+ refType = 4;
+ };
+ 02E03CA000348209CE6F79C2 = {
+ children = (
+ F533214701A4B48301000001,
+ 02E03CA100348209CE6F79C2,
+ F58D65E0018F79C001000001,
+ F533213E0193CBF401000001,
+ 43B962E300617B93416877C2,
+ F5ACD268C5BE046401000001,
+ F51BF62F02026E5C01000001,
+ F5ACD261C5B5EA2001000001,
+ F587E16501924C7401000001,
+ );
+ isa = PBXVariantGroup;
+ name = XDarwinHelp.html;
+ path = "";
+ refType = 4;
+ };
+ 02E03CA100348209CE6F79C2 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+//020
+//021
+//022
+//023
+//024
+//030
+//031
+//032
+//033
+//034
+ 0338412F0083BFE57F000001 = {
+ isa = PBXFileReference;
+ path = quartzCursor.h;
+ refType = 4;
+ };
+//030
+//031
+//032
+//033
+//034
+//040
+//041
+//042
+//043
+//044
+ 04329610000763920A000002 = {
+ isa = PBXFileReference;
+ name = Preferences.m;
+ path = ../quartz/Preferences.m;
+ refType = 4;
+ };
+ 04329611000763920A000002 = {
+ isa = PBXFileReference;
+ name = Preferences.h;
+ path = ../quartz/Preferences.h;
+ refType = 4;
+ };
+//040
+//041
+//042
+//043
+//044
+//060
+//061
+//062
+//063
+//064
+ 06EB6C3B004099E7CE6F79C2 = {
+ isa = PBXFileReference;
+ path = quartzShared.h;
+ refType = 4;
+ };
+//060
+//061
+//062
+//063
+//064
+//080
+//081
+//082
+//083
+//084
+ 080E96DDFE201D6D7F000001 = {
+ children = (
+ 04329610000763920A000002,
+ 04329611000763920A000002,
+ 0127909600074AF60A000002,
+ 0127909800074B1A0A000002,
+ 01279092000747AA0A000002,
+ 1C4A3109004D8F24CE6F79C2,
+ 014C68EE00ED6A9D7F000001,
+ 014C68ED00ED6A9D7F000001,
+ 014C68F000ED6A9D7F000001,
+ 014C68EF00ED6A9D7F000001,
+ );
+ isa = PBXGroup;
+ name = Classes;
+ refType = 4;
+ };
+ 089C165CFE840E0CC02AAC07 = {
+ children = (
+ F533214301A4B3F001000001,
+ 089C165DFE840E0CC02AAC07,
+ F58D65DD018F798F01000001,
+ F533213A0193CBA201000001,
+ 43B962E100617B49416877C2,
+ F5ACD269C5BE049301000001,
+ F51BF62B02026DDA01000001,
+ F5ACD262C5B5EA4D01000001,
+ F587E16101924C2F01000001,
+ );
+ isa = PBXVariantGroup;
+ name = InfoPlist.strings;
+ refType = 4;
+ };
+ 089C165DFE840E0CC02AAC07 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+//080
+//081
+//082
+//083
+//084
+//0A0
+//0A1
+//0A2
+//0A3
+//0A4
+ 0A79E19E004499A1CE6F79C2 = {
+ isa = PBXApplicationReference;
+ path = XDarwin.app;
+ refType = 3;
+ };
+ 0A79E19F004499A1CE6F79C2 = {
+ buildPhases = (
+ 0A79E1A0004499A1CE6F79C2,
+ 0A79E1A1004499A1CE6F79C2,
+ 0A79E1A2004499A1CE6F79C2,
+ 0A79E1A3004499A1CE6F79C2,
+ 0A79E1A4004499A1CE6F79C2,
+ );
+ buildSettings = {
+ INSTALL_PATH = "";
+ OPTIMIZATION_CFLAGS = "";
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = XDarwin;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ WRAPPER_EXTENSION = app;
+ };
+ dependencies = (
+ );
+ isa = PBXApplicationTarget;
+ name = XDarwin;
+ productInstallPath = "";
+ productName = XDarwin;
+ productReference = 0A79E19E004499A1CE6F79C2;
+ productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
+<!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">
+<plist version=\"0.9\">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>XDarwin</string>
+ <key>CFBundleGetInfoString</key>
+ <string>XDarwin 1.1, ©2001-2002 XFree86 Project, Inc.</string>
+ <key>CFBundleIconFile</key>
+ <string>XDarwin.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.xfree86.XDarwin</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>XDarwin</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>XDarwin 1.1</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string></string>
+ <key>NSHelpFile</key>
+ <string>XDarwinHelp.html</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>XApplication</string>
+</dict>
+</plist>
+";
+ shouldUseHeadermap = 0;
+ };
+ 0A79E1A0004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXHeadersBuildPhase;
+ name = Headers;
+ };
+ 0A79E1A1004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ 0A79E1A600449EB2CE6F79C2,
+ 0A79E1A700449EB2CE6F79C2,
+ 0A79E1A800449EB2CE6F79C2,
+ 0A79E1A900449EB2CE6F79C2,
+ 0A79E1AA00449EB2CE6F79C2,
+ 1220774500712D2D416877C2,
+ F54BF6ED017D506E01000001,
+ );
+ isa = PBXResourcesBuildPhase;
+ name = "Bundle Resources";
+ };
+ 0A79E1A2004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXSourcesBuildPhase;
+ name = Sources;
+ };
+ 0A79E1A3004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ name = "Frameworks & Libraries";
+ };
+ 0A79E1A4004499A1CE6F79C2 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXRezBuildPhase;
+ name = "ResourceManager Resources";
+ };
+ 0A79E1A600449EB2CE6F79C2 = {
+ fileRef = 29B97318FDCFA39411CA2CEA;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1A700449EB2CE6F79C2 = {
+ fileRef = 089C165CFE840E0CC02AAC07;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1A800449EB2CE6F79C2 = {
+ fileRef = 0157A37D002CF6D7CE6F79C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1A900449EB2CE6F79C2 = {
+ fileRef = 02E03CA000348209CE6F79C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 0A79E1AA00449EB2CE6F79C2 = {
+ fileRef = 015698ED003DF345CE6F79C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+//0A0
+//0A1
+//0A2
+//0A3
+//0A4
+//100
+//101
+//102
+//103
+//104
+ 1058C7A0FEA54F0111CA2CBB = {
+ children = (
+ F53321400193CCF001000001,
+ 1BE4F84D0006C9890A000002,
+ 1058C7A1FEA54F0111CA2CBB,
+ F53321410193CCF001000001,
+ 015EDCEA004203A8CE6F79C2,
+ );
+ isa = PBXGroup;
+ name = "Linked Frameworks";
+ refType = 4;
+ };
+ 1058C7A1FEA54F0111CA2CBB = {
+ isa = PBXFrameworkReference;
+ name = Cocoa.framework;
+ path = /System/Library/Frameworks/Cocoa.framework;
+ refType = 0;
+ };
+ 1058C7A2FEA54F0111CA2CBB = {
+ children = (
+ 29B97325FDCFA39411CA2CEA,
+ 29B97324FDCFA39411CA2CEA,
+ );
+ isa = PBXGroup;
+ name = "Other Frameworks";
+ refType = 4;
+ };
+//100
+//101
+//102
+//103
+//104
+//120
+//121
+//122
+//123
+//124
+ 1220774300712D2D416877C2 = {
+ children = (
+ F533214501A4B42501000001,
+ 1220774400712D2D416877C2,
+ F58D65DE018F79A001000001,
+ F533213C0193CBC901000001,
+ 1220774600712D75416877C2,
+ F5ACD266C5BE03C501000001,
+ F51BF62D02026E1C01000001,
+ F5ACD25FC5B5E9AA01000001,
+ F587E16301924C5E01000001,
+ );
+ isa = PBXVariantGroup;
+ name = Localizable.strings;
+ path = "";
+ refType = 4;
+ };
+ 1220774400712D2D416877C2 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/Localizable.strings;
+ refType = 4;
+ };
+ 1220774500712D2D416877C2 = {
+ fileRef = 1220774300712D2D416877C2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 1220774600712D75416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/Localizable.strings;
+ refType = 4;
+ };
+//120
+//121
+//122
+//123
+//124
+//170
+//171
+//172
+//173
+//174
+ 170DFAFF00729A35416877C2 = {
+ isa = PBXFileReference;
+ name = XDarwinStartup.c;
+ path = ../quartz/XDarwinStartup.c;
+ refType = 4;
+ };
+ 170DFB0000729C86416877C2 = {
+ children = (
+ 018F40FC003E1983CE6F79C2,
+ 018F40FE003E1988CE6F79C2,
+ 018F4100003E19E4CE6F79C2,
+ 02A1FEA6006D34BE416877C2,
+ );
+ isa = PBXGroup;
+ name = IOKit;
+ path = ..;
+ refType = 4;
+ };
+//170
+//171
+//172
+//173
+//174
+//190
+//191
+//192
+//193
+//194
+ 19C28FACFE9D520D11CA2CBB = {
+ children = (
+ 0A79E19E004499A1CE6F79C2,
+ );
+ isa = PBXGroup;
+ name = Products;
+ refType = 4;
+ };
+//190
+//191
+//192
+//193
+//194
+//1B0
+//1B1
+//1B2
+//1B3
+//1B4
+ 1BD8DE4200B8A3567F000001 = {
+ children = (
+ F533214401A4B40F01000001,
+ 1BD8DE4300B8A3567F000001,
+ F58D65DC018F794D01000001,
+ F533213B0193CBB401000001,
+ 1BD8DE4700B8A3C77F000001,
+ F5ACD264C5BE035B01000001,
+ F51BF62C02026E0601000001,
+ F5ACD25DC5B5E97701000001,
+ F587E16201924C5301000001,
+ );
+ isa = PBXVariantGroup;
+ name = InfoPlist.strings.cpp;
+ path = "";
+ refType = 4;
+ };
+ 1BD8DE4300B8A3567F000001 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ 1BD8DE4400B8A38E7F000001 = {
+ children = (
+ F533214801A4B4D701000001,
+ 1BD8DE4500B8A38E7F000001,
+ F58D65E1018F79E001000001,
+ F533213F0193CC2501000001,
+ 1BD8DE4800B8A4167F000001,
+ F5ACD267C5BE03FC01000001,
+ F51BF63002026E8D01000001,
+ F5ACD260C5B5E9DF01000001,
+ F587E16601924C9D01000001,
+ );
+ isa = PBXVariantGroup;
+ name = XDarwinHelp.html.cpp;
+ path = "";
+ refType = 4;
+ };
+ 1BD8DE4500B8A38E7F000001 = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ 1BD8DE4700B8A3C77F000001 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ 1BD8DE4800B8A4167F000001 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ 1BE4F84D0006C9890A000002 = {
+ isa = PBXFrameworkReference;
+ name = Carbon.framework;
+ path = /System/Library/Frameworks/Carbon.framework;
+ refType = 0;
+ };
+//1B0
+//1B1
+//1B2
+//1B3
+//1B4
+//1C0
+//1C1
+//1C2
+//1C3
+//1C4
+ 1C4A3109004D8F24CE6F79C2 = {
+ isa = PBXFileReference;
+ path = XServer.h;
+ refType = 4;
+ };
+//1C0
+//1C1
+//1C2
+//1C3
+//1C4
+//230
+//231
+//232
+//233
+//234
+ 237A34C10076E37E7F000001 = {
+ isa = PBXFileReference;
+ path = quartzAudio.c;
+ refType = 4;
+ };
+ 237A34C20076E37E7F000001 = {
+ buildRules = (
+ );
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ };
+ isa = PBXBuildStyle;
+ name = Development;
+ };
+ 237A34C30076E37E7F000001 = {
+ buildRules = (
+ );
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ };
+ isa = PBXBuildStyle;
+ name = Deployment;
+ };
+ 237A34C40076F4F07F000001 = {
+ isa = PBXFileReference;
+ path = quartzAudio.h;
+ refType = 4;
+ };
+//230
+//231
+//232
+//233
+//234
+//290
+//291
+//292
+//293
+//294
+ 29B97313FDCFA39411CA2CEA = {
+ buildStyles = (
+ 237A34C20076E37E7F000001,
+ 237A34C30076E37E7F000001,
+ );
+ isa = PBXProject;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ Swedish,
+ Dutch,
+ Spanish,
+ ko,
+ Portuguese,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA;
+ projectDirPath = "";
+ targets = (
+ 0A79E19F004499A1CE6F79C2,
+ );
+ };
+ 29B97314FDCFA39411CA2CEA = {
+ children = (
+ 080E96DDFE201D6D7F000001,
+ 018F40F2003E1902CE6F79C2,
+ 170DFB0000729C86416877C2,
+ 43B962CE00617089416877C2,
+ F51B53260253F84B01000001,
+ 32FEE13C00E07C3E7F000001,
+ 29B97315FDCFA39411CA2CEA,
+ 29B97317FDCFA39411CA2CEA,
+ 29B97323FDCFA39411CA2CEA,
+ 19C28FACFE9D520D11CA2CBB,
+ );
+ isa = PBXGroup;
+ name = "Xmaster-Cocoa";
+ path = "";
+ refType = 4;
+ };
+ 29B97315FDCFA39411CA2CEA = {
+ children = (
+ 170DFAFF00729A35416877C2,
+ );
+ isa = PBXGroup;
+ name = "Other Sources";
+ path = "";
+ refType = 2;
+ };
+ 29B97317FDCFA39411CA2CEA = {
+ children = (
+ 29B97318FDCFA39411CA2CEA,
+ 089C165CFE840E0CC02AAC07,
+ 1BD8DE4200B8A3567F000001,
+ 1220774300712D2D416877C2,
+ 0157A37D002CF6D7CE6F79C2,
+ 02E03CA000348209CE6F79C2,
+ 1BD8DE4400B8A38E7F000001,
+ 015698ED003DF345CE6F79C2,
+ F54BF6EA017D500901000001,
+ F54BF6EC017D506E01000001,
+ );
+ isa = PBXGroup;
+ name = Resources;
+ path = ../bundle;
+ refType = 4;
+ };
+ 29B97318FDCFA39411CA2CEA = {
+ children = (
+ F533214201A4B3CE01000001,
+ 29B97319FDCFA39411CA2CEA,
+ F58D65DB018F793801000001,
+ F53321390193CB6A01000001,
+ 43B962E000617B49416877C2,
+ F5ACD265C5BE038601000001,
+ F51BF62A02026DAF01000001,
+ F5ACD25EC5B5E98D01000001,
+ F587E16001924C1D01000001,
+ );
+ isa = PBXVariantGroup;
+ name = MainMenu.nib;
+ path = "";
+ refType = 4;
+ };
+ 29B97319FDCFA39411CA2CEA = {
+ isa = PBXFileReference;
+ name = English;
+ path = English.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ 29B97323FDCFA39411CA2CEA = {
+ children = (
+ 1058C7A0FEA54F0111CA2CBB,
+ 1058C7A2FEA54F0111CA2CBB,
+ );
+ isa = PBXGroup;
+ name = Frameworks;
+ path = "";
+ refType = 4;
+ };
+ 29B97324FDCFA39411CA2CEA = {
+ isa = PBXFrameworkReference;
+ name = AppKit.framework;
+ path = /System/Library/Frameworks/AppKit.framework;
+ refType = 0;
+ };
+ 29B97325FDCFA39411CA2CEA = {
+ isa = PBXFrameworkReference;
+ name = Foundation.framework;
+ path = /System/Library/Frameworks/Foundation.framework;
+ refType = 0;
+ };
+//290
+//291
+//292
+//293
+//294
+//320
+//321
+//322
+//323
+//324
+ 32FEE13C00E07C3E7F000001 = {
+ children = (
+ 014C68F200ED7AD67F000001,
+ F5269C2D01D5BC3501000001,
+ F5269C2E01D5BC3501000001,
+ 32FEE13E00E07CBE7F000001,
+ 32FEE13F00E07CBE7F000001,
+ 32FEE14000E07CBE7F000001,
+ 32FEE14100E07CBE7F000001,
+ 32FEE14200E07CBE7F000001,
+ 014C68F300EE5AB97F000001,
+ 014C68F400EE5AB97F000001,
+ 017D6F4400E861FB7F000001,
+ 017D6F4500E861FB7F000001,
+ 014C68F700EE678F7F000001,
+ 014C68F800EE678F7F000001,
+ 32FEE14900E07D317F000001,
+ );
+ isa = PBXGroup;
+ name = Rootless;
+ path = "";
+ refType = 4;
+ };
+ 32FEE13E00E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootless.h;
+ refType = 4;
+ };
+ 32FEE13F00E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAqua.h;
+ refType = 4;
+ };
+ 32FEE14000E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAquaGlue.c;
+ refType = 4;
+ };
+ 32FEE14100E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAquaImp.h;
+ refType = 4;
+ };
+ 32FEE14200E07CBE7F000001 = {
+ isa = PBXFileReference;
+ path = rootlessAquaImp.m;
+ refType = 4;
+ };
+ 32FEE14900E07D317F000001 = {
+ isa = PBXFileReference;
+ path = rootlessValTree.c;
+ refType = 4;
+ };
+//320
+//321
+//322
+//323
+//324
+//350
+//351
+//352
+//353
+//354
+ 3576829A0077B8F17F000001 = {
+ isa = PBXFileReference;
+ path = quartzCursor.c;
+ refType = 4;
+ };
+//350
+//351
+//352
+//353
+//354
+//3E0
+//3E1
+//3E2
+//3E3
+//3E4
+ 3E74E03600863F047F000001 = {
+ isa = PBXFileReference;
+ path = darwinClut8.h;
+ refType = 4;
+ };
+//3E0
+//3E1
+//3E2
+//3E3
+//3E4
+//430
+//431
+//432
+//433
+//434
+ 43B962CE00617089416877C2 = {
+ children = (
+ 018F40F8003E1979CE6F79C2,
+ 018F40FA003E197ECE6F79C2,
+ 237A34C10076E37E7F000001,
+ 237A34C40076F4F07F000001,
+ 3576829A0077B8F17F000001,
+ 0338412F0083BFE57F000001,
+ 43B962D000617089416877C2,
+ 43B962D100617089416877C2,
+ 43B962CF00617089416877C2,
+ F5582948015DAD3B01000001,
+ 06EB6C3B004099E7CE6F79C2,
+ 02A1FEA8006D38F0416877C2,
+ );
+ isa = PBXGroup;
+ name = Quartz;
+ path = ../quartz;
+ refType = 4;
+ };
+ 43B962CF00617089416877C2 = {
+ isa = PBXFileReference;
+ path = quartzCocoa.m;
+ refType = 4;
+ };
+ 43B962D000617089416877C2 = {
+ isa = PBXFileReference;
+ path = quartzPasteboard.c;
+ refType = 4;
+ };
+ 43B962D100617089416877C2 = {
+ isa = PBXFileReference;
+ path = quartzPasteboard.h;
+ refType = 4;
+ };
+ 43B962E000617B49416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ 43B962E100617B49416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ 43B962E200617B93416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/Credits.rtf;
+ refType = 4;
+ };
+ 43B962E300617B93416877C2 = {
+ isa = PBXFileReference;
+ name = Japanese;
+ path = Japanese.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+//430
+//431
+//432
+//433
+//434
+//F50
+//F51
+//F52
+//F53
+//F54
+ F51B53260253F84B01000001 = {
+ children = (
+ F51B53270253F8B701000001,
+ F51B53280253F8B701000001,
+ );
+ isa = PBXGroup;
+ name = "Full Screen";
+ path = ../quartz;
+ refType = 4;
+ };
+ F51B53270253F8B701000001 = {
+ isa = PBXFileReference;
+ path = fullscreen.c;
+ refType = 4;
+ };
+ F51B53280253F8B701000001 = {
+ isa = PBXFileReference;
+ path = fullscreen.h;
+ refType = 4;
+ };
+ F51BF62A02026DAF01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F51BF62B02026DDA01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F51BF62C02026E0601000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F51BF62D02026E1C01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F51BF62E02026E3501000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F51BF62F02026E5C01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F51BF63002026E8D01000001 = {
+ isa = PBXFileReference;
+ name = Portuguese;
+ path = Portuguese.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5269C2D01D5BC3501000001 = {
+ isa = PBXFileReference;
+ name = pseudoramiX.c;
+ path = ../quartz/pseudoramiX.c;
+ refType = 4;
+ };
+ F5269C2E01D5BC3501000001 = {
+ isa = PBXFileReference;
+ name = pseudoramiX.h;
+ path = ../quartz/pseudoramiX.h;
+ refType = 4;
+ };
+ F53321390193CB6A01000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F533213A0193CBA201000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F533213B0193CBB401000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F533213C0193CBC901000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F533213D0193CBE001000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F533213E0193CBF401000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F533213F0193CC2501000001 = {
+ isa = PBXFileReference;
+ name = German;
+ path = German.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F53321400193CCF001000001 = {
+ isa = PBXFrameworkReference;
+ name = ApplicationServices.framework;
+ path = /System/Library/Frameworks/ApplicationServices.framework;
+ refType = 0;
+ };
+ F53321410193CCF001000001 = {
+ isa = PBXFrameworkReference;
+ name = CoreAudio.framework;
+ path = /System/Library/Frameworks/CoreAudio.framework;
+ refType = 0;
+ };
+ F533214201A4B3CE01000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F533214301A4B3F001000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F533214401A4B40F01000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F533214501A4B42501000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F533214601A4B45401000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F533214701A4B48301000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F533214801A4B4D701000001 = {
+ isa = PBXFileReference;
+ name = Dutch;
+ path = Dutch.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F54BF6EA017D500901000001 = {
+ isa = PBXFileReference;
+ path = startXClients.cpp;
+ refType = 4;
+ };
+ F54BF6EC017D506E01000001 = {
+ isa = PBXFileReference;
+ path = startXClients;
+ refType = 4;
+ };
+ F54BF6ED017D506E01000001 = {
+ fileRef = F54BF6EC017D506E01000001;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F5582948015DAD3B01000001 = {
+ isa = PBXFileReference;
+ path = quartzCommon.h;
+ refType = 4;
+ };
+ F587E16001924C1D01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F587E16101924C2F01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F587E16201924C5301000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F587E16301924C5E01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F587E16401924C6901000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F587E16501924C7401000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F587E16601924C9D01000001 = {
+ isa = PBXFileReference;
+ name = Swedish;
+ path = Swedish.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F58D65DB018F793801000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F58D65DC018F794D01000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F58D65DD018F798F01000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F58D65DE018F79A001000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F58D65DF018F79B101000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F58D65E0018F79C001000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F58D65E1018F79E001000001 = {
+ isa = PBXFileReference;
+ name = French;
+ path = French.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5ACD25CC5B5E96601000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F5ACD25DC5B5E97701000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F5ACD25EC5B5E98D01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F5ACD25FC5B5E9AA01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F5ACD260C5B5E9DF01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5ACD261C5B5EA2001000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F5ACD262C5B5EA4D01000001 = {
+ isa = PBXFileReference;
+ name = Spanish;
+ path = Spanish.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ F5ACD263C5BE031F01000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/Credits.rtf;
+ refType = 4;
+ };
+ F5ACD264C5BE035B01000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/InfoPlist.strings.cpp;
+ refType = 4;
+ };
+ F5ACD265C5BE038601000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/MainMenu.nib;
+ refType = 4;
+ };
+ F5ACD266C5BE03C501000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/Localizable.strings;
+ refType = 4;
+ };
+ F5ACD267C5BE03FC01000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/XDarwinHelp.html.cpp;
+ refType = 4;
+ };
+ F5ACD268C5BE046401000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/XDarwinHelp.html;
+ refType = 4;
+ };
+ F5ACD269C5BE049301000001 = {
+ isa = PBXFileReference;
+ name = ko;
+ path = ko.lproj/InfoPlist.strings;
+ refType = 4;
+ };
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.h
new file mode 100644
index 000000000..87932fc67
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.h
@@ -0,0 +1,72 @@
+//
+// XServer.h
+//
+// Created by Andreas Monitzer on January 6, 2001.
+//
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.h,v 1.2 2002/06/19 18:12:02 torrey Exp $ */
+
+#import <Cocoa/Cocoa.h>
+
+#include <drivers/event_status_driver.h> // for NXEvent
+
+@interface XServer : NSObject {
+ // server state
+ NSRecursiveLock *serverLock;
+ NSPort *signalPort;
+ BOOL serverVisible;
+ BOOL rootlessMenuBarVisible;
+ BOOL appQuitting;
+ UInt32 mouseState;
+ Class windowClass;
+
+ // server event queue
+ BOOL sendServerEvents;
+ int eventWriteFD;
+
+ // Aqua interface
+ IBOutlet NSWindow *modeWindow;
+ IBOutlet NSButton *startupModeButton;
+ IBOutlet NSButton *startFullScreenButton;
+ IBOutlet NSButton *startRootlessButton;
+ IBOutlet NSWindow *helpWindow;
+ IBOutlet NSButton *startupHelpButton;
+ IBOutlet NSPanel *switchWindow;
+}
+
+- (id)init;
+
+- (BOOL)translateEvent:(NSEvent *)anEvent;
+- (BOOL)getNXMouse:(NXEvent*)ev;
+
++ (void)append:(NSString*)value toEnv:(NSString*)name;
+
+- (void)startX;
+- (BOOL)startXClients;
+- (void)run;
+- (void)toggle;
+- (void)show;
+- (void)hide;
+- (void)killServer;
+- (void)readPasteboard;
+- (void)writePasteboard;
+- (void)sendNXEvent:(NXEvent*)ev;
+- (void)sendShowHide:(BOOL)show;
+
+// Aqua interface actions
+- (IBAction)startFullScreen:(id)sender;
+- (IBAction)startRootless:(id)sender;
+- (IBAction)closeHelpAndShow:(id)sender;
+- (IBAction)showAction:(id)sender;
+
+// NSApplication delegate
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag;
+- (void)applicationWillResignActive:(NSNotification *)aNotification;
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification;
+
+// NSPort delegate
+- (void)handlePortMessage:(NSPortMessage *)portMessage;
+
+@end
+
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.m b/xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.m
new file mode 100644
index 000000000..4cd5ab846
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.m
@@ -0,0 +1,832 @@
+//
+// XServer.m
+//
+// This class handles the interaction between the Cocoa front-end
+// and the Darwin X server thread.
+//
+// Created by Andreas Monitzer on January 6, 2001.
+//
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/XServer.m,v 1.2 2002/06/19 18:12:02 torrey Exp $ */
+
+#import "XServer.h"
+#import "Preferences.h"
+#import "XWindow.h"
+#include "quartzCommon.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/syslimits.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pwd.h>
+#include <signal.h>
+#include <fcntl.h>
+
+// Types of shells
+enum {
+ shell_Unknown,
+ shell_Bourne,
+ shell_C
+};
+
+typedef struct {
+ char *name;
+ int type;
+} shellList_t;
+
+static shellList_t const shellList[] = {
+ { "csh", shell_C }, // standard C shell
+ { "tcsh", shell_C }, // ... needs no introduction
+ { "sh", shell_Bourne }, // standard Bourne shell
+ { "zsh", shell_Bourne }, // Z shell
+ { "bash", shell_Bourne }, // GNU Bourne again shell
+ { NULL, shell_Unknown }
+};
+
+extern int argcGlobal;
+extern char **argvGlobal;
+extern char **envpGlobal;
+extern int main(int argc, char *argv[], char *envp[]);
+extern void HideMenuBar(void);
+extern void ShowMenuBar(void);
+static void childDone(int sig);
+
+static NSPortMessage *signalMessage;
+static pid_t clientPID;
+static XServer *oneXServer;
+static NSRect aquaMenuBarBox;
+
+
+@implementation XServer
+
+- (id)init
+{
+ self = [super init];
+ oneXServer = self;
+
+ serverLock = [[NSRecursiveLock alloc] init];
+ clientPID = 0;
+ sendServerEvents = NO;
+ serverVisible = NO;
+ rootlessMenuBarVisible = YES;
+ appQuitting = NO;
+ mouseState = 0;
+ eventWriteFD = quartzEventWriteFD;
+ windowClass = [XWindow class];
+
+ // set up a port to safely send messages to main thread from server thread
+ signalPort = [[NSPort port] retain];
+ signalMessage = [[NSPortMessage alloc] initWithSendPort:signalPort
+ receivePort:signalPort components:nil];
+
+ // set up receiving end
+ [signalPort setDelegate:self];
+ [[NSRunLoop currentRunLoop] addPort:signalPort
+ forMode:NSDefaultRunLoopMode];
+ [[NSRunLoop currentRunLoop] addPort:signalPort
+ forMode:NSModalPanelRunLoopMode];
+
+ return self;
+}
+
+- (NSApplicationTerminateReply)
+ applicationShouldTerminate:(NSApplication *)sender
+{
+ // Quit if the X server is not running
+ if ([serverLock tryLock]) {
+ appQuitting = YES;
+ if (clientPID != 0)
+ kill(clientPID, SIGINT);
+ return NSTerminateNow;
+ }
+
+ if (clientPID != 0 || !quartzStartClients) {
+ int but;
+
+ // Hide the X server and stop sending it events
+ [self hide];
+ sendServerEvents = NO;
+
+ but = NSRunAlertPanel(NSLocalizedString(@"Quit X server?",@""),
+ NSLocalizedString(@"Quitting the X server will terminate any running X Window System programs.",@""),
+ NSLocalizedString(@"Quit",@""),
+ NSLocalizedString(@"Cancel",@""),
+ nil);
+
+ switch (but) {
+ case NSAlertDefaultReturn: // quit
+ break;
+ case NSAlertAlternateReturn: // cancel
+ sendServerEvents = YES;
+ return NSTerminateCancel;
+ }
+ }
+
+ appQuitting = YES;
+ if (clientPID != 0)
+ kill(clientPID, SIGINT);
+ [self killServer];
+ return NSTerminateNow;
+}
+
+// Ensure that everything has quit cleanly
+- (void)applicationWillTerminate:(NSNotification *)aNotification
+{
+ // Make sure the client process has finished
+ if (clientPID != 0) {
+ NSLog(@"Waiting on client process...");
+ sleep(2);
+
+ // If the client process hasn't finished yet, kill it off
+ if (clientPID != 0) {
+ int clientStatus;
+ NSLog(@"Killing client process...");
+ killpg(clientPID, SIGKILL);
+ waitpid(clientPID, &clientStatus, 0);
+ }
+ }
+
+ // Wait until the X server thread quits
+ [serverLock lock];
+}
+
+// returns YES when event was handled
+- (BOOL)translateEvent:(NSEvent *)anEvent
+{
+ NXEvent ev;
+ static BOOL mouse1Pressed = NO;
+ BOOL onScreen;
+
+ if (!sendServerEvents) {
+ return NO;
+ }
+
+ ev.type = [anEvent type];
+ ev.flags = [anEvent modifierFlags];
+
+ if (!quartzRootless) {
+ // Check for switch keypress
+ if ((ev.type == NSKeyDown) && (![anEvent isARepeat]) &&
+ ([anEvent keyCode] == [Preferences keyCode]))
+ {
+ unsigned int switchFlags = [Preferences modifiers];
+
+ // Switch if all the switch modifiers are pressed, while none are
+ // pressed that should not be, except for caps lock.
+ if (((ev.flags & switchFlags) == switchFlags) &&
+ ((ev.flags & ~(switchFlags | NSAlphaShiftKeyMask)) == 0))
+ {
+ [self toggle];
+ return YES;
+ }
+ }
+
+ if (!serverVisible)
+ return NO;
+ }
+
+ // If the mouse is not on the valid X display area,
+ // we don't send the X server key events.
+ onScreen = [self getNXMouse:&ev];
+
+ switch (ev.type) {
+ case NSLeftMouseUp:
+ if (quartzRootless && !mouse1Pressed) {
+ // MouseUp after MouseDown in menu - ignore
+ return NO;
+ }
+ mouse1Pressed = NO;
+ break;
+ case NSLeftMouseDown:
+ if (quartzRootless &&
+ ! ([anEvent window] &&
+ [[anEvent window] isKindOfClass:windowClass])) {
+ // Click in non X window - ignore
+ return NO;
+ }
+ mouse1Pressed = YES;
+ case NSMouseMoved:
+ break;
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case 27: // undocumented high button MouseDragged event
+ ev.type=NSMouseMoved;
+ break;
+ case NSSystemDefined:
+ if (![anEvent subtype]==7)
+ return NO; // we only use multibutton mouse events
+ if ([anEvent data1] & 1)
+ return NO; // skip mouse button 1 events
+ if (mouseState==[anEvent data2])
+ return NO; // ignore double events
+ ev.data.compound.subType=[anEvent subtype];
+ ev.data.compound.misc.L[0]=[anEvent data1];
+ ev.data.compound.misc.L[1]=mouseState=[anEvent data2];
+ break;
+ case NSScrollWheel:
+ ev.data.scrollWheel.deltaAxis1=[anEvent deltaY];
+ break;
+ case NSKeyDown:
+ case NSKeyUp:
+ if (!onScreen)
+ return NO;
+ ev.data.key.keyCode = [anEvent keyCode];
+ ev.data.key.repeat = [anEvent isARepeat];
+ break;
+ case NSFlagsChanged:
+ ev.data.key.keyCode = [anEvent keyCode];
+ break;
+ case 25: // undocumented MouseDown
+ case 26: // undocumented MouseUp
+ // Hide these from AppKit to avoid its log messages
+ return YES;
+ default:
+ return NO;
+ }
+
+ [self sendNXEvent:&ev];
+
+ // Rootless: Send first NSLeftMouseDown to windows and views so window
+ // ordering can be suppressed.
+ // Don't pass further events - they (incorrectly?) bring the window
+ // forward no matter what.
+ if (quartzRootless &&
+ (ev.type == NSLeftMouseDown || ev.type == NSLeftMouseUp) &&
+ [anEvent clickCount] == 1 &&
+ [[anEvent window] isKindOfClass:windowClass])
+ {
+ return NO;
+ }
+
+ return YES;
+}
+
+// Fill in NXEvent with mouse coordinates, inverting y coordinate.
+// For rootless mode, the menu bar is treated as not part of the usable
+// X display area and the cursor position is adjusted accordingly.
+// Returns YES if the cursor is not in the menu bar.
+- (BOOL)getNXMouse:(NXEvent*)ev
+{
+ NSPoint pt = [NSEvent mouseLocation];
+
+ ev->location.x = (int)(pt.x);
+
+ if (quartzRootless && NSMouseInRect(pt, aquaMenuBarBox, NO)) {
+ // mouse in menu bar - tell X11 that it's just below instead
+ ev->location.y = aquaMenuBarHeight;
+ return NO;
+ } else {
+ ev->location.y = NSHeight([[NSScreen mainScreen] frame]) - (int)(pt.y);
+ return YES;
+ }
+}
+
+// Append a string to the given enviroment variable
++ (void)append:(NSString*)value toEnv:(NSString*)name
+{
+ setenv([name cString],
+ [[[NSString stringWithCString:getenv([name cString])]
+ stringByAppendingString:value] cString],1);
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+ // Block SIGPIPE
+ // SIGPIPE repeatably killed the (rootless) server when closing a
+ // dozen xterms in rapid succession. Those SIGPIPEs should have been
+ // sent to the X server thread, which ignores them, but somehow they
+ // ended up in this thread instead.
+ {
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ // pthread_sigmask not implemented yet
+ // pthread_sigmask(SIG_BLOCK, &set, NULL);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+ }
+
+ if (quartzRootless == -1) {
+ // The display mode was not set from the command line.
+ // Show mode pick panel?
+ if ([Preferences modeWindow]) {
+ if ([Preferences rootless])
+ [startRootlessButton setKeyEquivalent:@"\r"];
+ else
+ [startFullScreenButton setKeyEquivalent:@"\r"];
+ [modeWindow makeKeyAndOrderFront:nil];
+ } else {
+ // Otherwise use default mode
+ quartzRootless = [Preferences rootless];
+ [self startX];
+ }
+ } else {
+ [self startX];
+ }
+}
+
+// Start the X server thread and the client process
+- (void)startX
+{
+ NSDictionary *appDictionary;
+ NSString *appVersion;
+
+ [modeWindow close];
+
+ // Calculate the height of the menu bar so rootless mode can avoid it
+ if (quartzRootless) {
+ aquaMenuBarHeight = NSHeight([[NSScreen mainScreen] frame]) -
+ NSMaxY([[NSScreen mainScreen] visibleFrame]) - 1;
+ aquaMenuBarBox =
+ NSMakeRect(0, NSMaxY([[NSScreen mainScreen] visibleFrame]) + 1,
+ NSWidth([[NSScreen mainScreen] frame]),
+ aquaMenuBarHeight);
+ }
+
+ // Write the XDarwin version to the console log
+ appDictionary = [[NSBundle mainBundle] infoDictionary];
+ appVersion = [appDictionary objectForKey:@"CFBundleShortVersionString"];
+ if (appVersion)
+ NSLog(@"\n%@", appVersion);
+ else
+ NSLog(@"No version");
+
+ // Start the X server thread
+ [NSThread detachNewThreadSelector:@selector(run) toTarget:self
+ withObject:nil];
+ sendServerEvents = YES;
+
+ // Start the X clients if started from GUI
+ if (quartzStartClients) {
+ [self startXClients];
+ }
+
+ if (quartzRootless) {
+ // There is no help window for rootless; just start
+ [helpWindow close];
+ helpWindow = nil;
+ if ([NSApp isActive])
+ [self sendShowHide:YES];
+ else
+ [self sendShowHide:NO];
+ } else {
+ // Show the X switch window if not using dock icon switching
+ if (![Preferences dockSwitch])
+ [switchWindow orderFront:nil];
+
+ if ([Preferences startupHelp]) {
+ // display the full screen mode help
+ [self sendShowHide:NO];
+ [helpWindow makeKeyAndOrderFront:nil];
+ } else {
+ // start running full screen and make sure X is visible
+ ShowMenuBar();
+ [self closeHelpAndShow:nil];
+ }
+ }
+}
+
+// Start the first X clients in a separate process
+- (BOOL)startXClients
+{
+ struct passwd *passwdUser;
+ NSString *shellPath, *dashShellName, *commandStr, *startXPath;
+ NSMutableString *safeStartXPath;
+ NSRange aRange;
+ NSBundle *thisBundle;
+ const char *shellPathStr, *newargv[3], *shellNameStr;
+ int fd[2], outFD, length, shellType, i;
+
+ // Register to catch the signal when the client processs finishes
+ signal(SIGCHLD, childDone);
+
+ // Get user's password database entry
+ passwdUser = getpwuid(getuid());
+
+ // Find the shell to use
+ if ([Preferences useDefaultShell])
+ shellPath = [NSString stringWithCString:passwdUser->pw_shell];
+ else
+ shellPath = [Preferences shellString];
+
+ dashShellName = [NSString stringWithFormat:@"-%@",
+ [shellPath lastPathComponent]];
+ shellPathStr = [shellPath cString];
+ shellNameStr = [[shellPath lastPathComponent] cString];
+
+ if (access(shellPathStr, X_OK)) {
+ NSLog(@"Shell %s is not valid!", shellPathStr);
+ return NO;
+ }
+
+ // Find the type of shell
+ for (i = 0; shellList[i].name; i++) {
+ if (!strcmp(shellNameStr, shellList[i].name))
+ break;
+ }
+ shellType = shellList[i].type;
+
+ newargv[0] = [dashShellName cString];
+ if (shellType == shell_Bourne) {
+ // Bourne shells need to be told they are interactive to make
+ // sure they read all their initialization files.
+ newargv[1] = "-i";
+ newargv[2] = NULL;
+ } else {
+ newargv[1] = NULL;
+ }
+
+ // Create a pipe to communicate with the X client process
+ NSAssert(pipe(fd) == 0, @"Could not create new pipe.");
+
+ // Open a file descriptor for writing to stdout and stderr
+ outFD = open("/dev/console", O_WRONLY, 0);
+ if (outFD == -1) {
+ outFD = open("/dev/null", O_WRONLY, 0);
+ NSAssert(outFD != -1, @"Could not open shell output.");
+ }
+
+ // Fork process to start X clients in user's default shell
+ // Sadly we can't use NSTask because we need to start a login shell.
+ // Login shells are started by passing "-" as the first character of
+ // argument 0. NSTask forces argument 0 to be the shell's name.
+ clientPID = vfork();
+ if (clientPID == 0) {
+
+ // Inside the new process:
+ if (fd[0] != STDIN_FILENO) {
+ dup2(fd[0], STDIN_FILENO); // Take stdin from pipe
+ close(fd[0]);
+ }
+ close(fd[1]); // Close write end of pipe
+ if (outFD == STDOUT_FILENO) { // Setup stdout and stderr
+ dup2(outFD, STDERR_FILENO);
+ } else if (outFD == STDERR_FILENO) {
+ dup2(outFD, STDOUT_FILENO);
+ } else {
+ dup2(outFD, STDERR_FILENO);
+ dup2(outFD, STDOUT_FILENO);
+ close(outFD);
+ }
+
+ // Setup environment
+ setenv("HOME", passwdUser->pw_dir, 1);
+ setenv("SHELL", shellPathStr, 1);
+ setenv("LOGNAME", passwdUser->pw_name, 1);
+ setenv("USER", passwdUser->pw_name, 1);
+ setenv("TERM", "unknown", 1);
+ if (chdir(passwdUser->pw_dir)) // Change to user's home dir
+ NSLog(@"Could not change to user's home directory.");
+
+ execv(shellPathStr, newargv); // Start user's shell
+
+ NSLog(@"Could not start X client process with errno = %i.", errno);
+ _exit(127);
+ }
+
+ // In parent process:
+ close(fd[0]); // Close read end of pipe
+ close(outFD); // Close output file descriptor
+
+ thisBundle = [NSBundle bundleForClass:[self class]];
+ startXPath = [thisBundle pathForResource:@"startXClients" ofType:nil];
+ if (!startXPath) {
+ NSLog(@"Could not find startXClients in application bundle!");
+ return NO;
+ }
+
+ // We will run the startXClients script with the path in single quotes
+ // in case there are problematic characters in the path. We still have
+ // to worry about there being single quotes in the path. So, replace
+ // all instances of the ' character in startXPath with '\''.
+ safeStartXPath = [NSMutableString stringWithString:startXPath];
+ aRange = NSMakeRange(0, [safeStartXPath length]);
+ while (aRange.length) {
+ aRange = [safeStartXPath rangeOfString:@"'" options:0 range:aRange];
+ if (!aRange.length)
+ break;
+ [safeStartXPath replaceCharactersInRange:aRange
+ withString:@"\'\\'\'"];
+ aRange.location += 4;
+ aRange.length = [safeStartXPath length] - aRange.location;
+ }
+
+ if ([Preferences addToPath]) {
+ commandStr = [NSString stringWithFormat:@"'%@' :%d %@\n",
+ safeStartXPath, [Preferences display],
+ [Preferences addToPathString]];
+ } else {
+ commandStr = [NSString stringWithFormat:@"'%@' :%d\n",
+ safeStartXPath, [Preferences display]];
+ }
+
+ length = [commandStr cStringLength];
+ if (write(fd[1], [commandStr cString], length) != length) {
+ NSLog(@"Write to X client process failed.");
+ return NO;
+ }
+
+ // Close the pipe so that shell will terminate when xinit quits
+ close(fd[1]);
+
+ return YES;
+}
+
+// Run the X server thread
+- (void)run
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [serverLock lock];
+ main(argcGlobal, argvGlobal, envpGlobal);
+ serverVisible = NO;
+ [pool release];
+ [serverLock unlock];
+ QuartzMessageMainThread(kQuartzServerDied);
+}
+
+// Full screen mode was picked in the mode pick panel
+- (IBAction)startFullScreen:(id)sender
+{
+ [Preferences setModeWindow:[startupModeButton intValue]];
+ [Preferences saveToDisk];
+ quartzRootless = FALSE;
+ [self startX];
+}
+
+// Rootless mode was picked in the mode pick panel
+- (IBAction)startRootless:(id)sender
+{
+ [Preferences setModeWindow:[startupModeButton intValue]];
+ [Preferences saveToDisk];
+ quartzRootless = TRUE;
+ [self startX];
+}
+
+// Close the help splash screen and show the X server
+- (IBAction)closeHelpAndShow:(id)sender
+{
+ if (sender) {
+ int helpVal = [startupHelpButton intValue];
+ [Preferences setStartupHelp:helpVal];
+ [Preferences saveToDisk];
+ }
+ [helpWindow close];
+ helpWindow = nil;
+
+ serverVisible = YES;
+ [self sendShowHide:YES];
+ [NSApp activateIgnoringOtherApps:YES];
+}
+
+// Show the X server when sent message from GUI
+- (IBAction)showAction:(id)sender
+{
+ if (sendServerEvents)
+ [self sendShowHide:YES];
+}
+
+// Show or hide the X server or menu bar in rootless mode
+- (void)toggle
+{
+ if (quartzRootless) {
+#if 0
+ // FIXME: Remove or add option to not dodge menubar
+ if (rootlessMenuBarVisible)
+ HideMenuBar();
+ else
+ ShowMenuBar();
+ rootlessMenuBarVisible = !rootlessMenuBarVisible;
+#endif
+ } else {
+ if (serverVisible)
+ [self hide];
+ else
+ [self show];
+ }
+}
+
+// Show the X server on screen
+- (void)show
+{
+ if (!serverVisible && sendServerEvents) {
+ [self sendShowHide:YES];
+ }
+}
+
+// Hide the X server from the screen
+- (void)hide
+{
+ if (serverVisible && sendServerEvents) {
+ [self sendShowHide:NO];
+ }
+}
+
+// Kill the X server thread
+- (void)killServer
+{
+ NXEvent ev;
+
+ if (serverVisible)
+ [self hide];
+
+ ev.type = NX_APPDEFINED;
+ ev.data.compound.subType = kXDarwinQuit;
+ [self sendNXEvent:&ev];
+}
+
+// Tell the X server to show or hide itself.
+// This ignores the current X server visible state.
+//
+// In full screen mode, the order we do things is important and must be
+// preserved between the threads. X drawing operations have to be performed
+// in the X server thread. It appears that we have the additional
+// constraint that we must hide and show the menu bar in the main thread.
+//
+// To show the X server:
+// 1. Capture the displays. (Main thread)
+// 2. Hide the menu bar. (Must be in main thread)
+// 3. Send event to X server thread to redraw X screen.
+// 4. Redraw the X screen. (Must be in X server thread)
+//
+// To hide the X server:
+// 1. Send event to X server thread to stop drawing.
+// 2. Stop drawing to the X screen. (Must be in X server thread)
+// 3. Message main thread that drawing is stopped.
+// 4. If main thread still wants X server hidden:
+// a. Release the displays. (Main thread)
+// b. Unhide the menu bar. (Must be in main thread)
+// Otherwise we have already queued an event to start drawing again.
+//
+- (void)sendShowHide:(BOOL)show
+{
+ NXEvent ev;
+
+ [self getNXMouse:&ev];
+ ev.type = NX_APPDEFINED;
+
+ if (show) {
+ if (!quartzRootless) {
+ QuartzFSCapture();
+ HideMenuBar();
+ }
+ ev.data.compound.subType = kXDarwinShow;
+ [self sendNXEvent:&ev];
+
+ // inform the X server of the current modifier state
+ ev.flags = [[NSApp currentEvent] modifierFlags];
+ ev.data.compound.subType = kXDarwinUpdateModifiers;
+ [self sendNXEvent:&ev];
+
+ // put the pasteboard into the X cut buffer
+ [self readPasteboard];
+ } else {
+ // put the X cut buffer on the pasteboard
+ [self writePasteboard];
+
+ ev.data.compound.subType = kXDarwinHide;
+ [self sendNXEvent:&ev];
+ }
+
+ serverVisible = show;
+}
+
+// Tell the X server to read from the pasteboard into the X cut buffer
+- (void)readPasteboard
+{
+ NXEvent ev;
+
+ ev.type = NX_APPDEFINED;
+ ev.data.compound.subType = kXDarwinReadPasteboard;
+ [self sendNXEvent:&ev];
+}
+
+// Tell the X server to write the X cut buffer into the pasteboard
+- (void)writePasteboard
+{
+ NXEvent ev;
+
+ ev.type = NX_APPDEFINED;
+ ev.data.compound.subType = kXDarwinWritePasteboard;
+ [self sendNXEvent:&ev];
+}
+
+- (void)sendNXEvent:(NXEvent*)ev
+{
+ int bytesWritten;
+
+ if (quartzRootless &&
+ (ev->type == NSLeftMouseDown || ev->type == NSLeftMouseUp ||
+ (ev->type == NSSystemDefined && ev->data.compound.subType == 7)))
+ {
+ // mouse button event - send mouseMoved to this position too
+ // X gets confused if it gets a click that isn't at the last
+ // reported mouse position.
+ NXEvent moveEvent = *ev;
+ moveEvent.type = NSMouseMoved;
+ [self sendNXEvent:&moveEvent];
+ }
+
+ bytesWritten = write(eventWriteFD, ev, sizeof(*ev));
+ if (bytesWritten == sizeof(*ev))
+ return;
+ NSLog(@"Bad write to event pipe.");
+ // FIXME: handle bad writes better?
+}
+
+// Handle messages from the X server thread
+- (void)handlePortMessage:(NSPortMessage *)portMessage
+{
+ unsigned msg = [portMessage msgid];
+
+ switch(msg) {
+ case kQuartzServerHidden:
+ // Make sure the X server wasn't queued to be shown again while
+ // the hide was pending.
+ if (!quartzRootless && !serverVisible) {
+ QuartzFSRelease();
+ ShowMenuBar();
+ }
+
+ // FIXME: This hack is necessary (but not completely effective)
+ // since Mac OS X 10.0.2
+ [NSCursor unhide];
+ break;
+
+ case kQuartzServerDied:
+ sendServerEvents = NO;
+ if (!appQuitting) {
+ [NSApp terminate:nil]; // quit if we aren't already
+ }
+ break;
+
+ default:
+ NSLog(@"Unknown message from server thread.");
+ }
+}
+
+// Quit the X server when the X client process finishes
+- (void)clientProcessDone:(int)clientStatus
+{
+ if (WIFEXITED(clientStatus)) {
+ int exitStatus = WEXITSTATUS(clientStatus);
+ if (exitStatus != 0)
+ NSLog(@"X client process terminated with status %i.", exitStatus);
+ } else {
+ NSLog(@"X client process terminated abnormally.");
+ }
+
+ if (!appQuitting) {
+ [NSApp terminate:nil]; // quit if we aren't already
+ }
+}
+
+// Called when the user clicks the application icon,
+// but not when Cmd-Tab is used.
+// Rootless: Don't switch until applicationWillBecomeActive.
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication
+ hasVisibleWindows:(BOOL)flag
+{
+ if ([Preferences dockSwitch] && !quartzRootless) {
+ [self show];
+ }
+ return NO;
+}
+
+- (void)applicationWillResignActive:(NSNotification *)aNotification
+{
+ [self hide];
+}
+
+- (void)applicationWillBecomeActive:(NSNotification *)aNotification
+{
+ if (quartzRootless)
+ [self show];
+}
+
+@end
+
+// Send a message to the main thread, which calls handlePortMessage in
+// response. Must only be called from the X server thread because
+// NSPort is not thread safe.
+void QuartzMessageMainThread(unsigned msg)
+{
+ [signalMessage setMsgid:msg];
+ [signalMessage sendBeforeDate:[NSDate distantPast]];
+}
+
+// Handle SIGCHLD signals
+static void childDone(int sig)
+{
+ int clientStatus;
+
+ if (clientPID == 0)
+ return;
+
+ // Make sure it was the client task that finished
+ if (waitpid(clientPID, &clientStatus, WNOHANG) == clientPID) {
+ if (WIFSTOPPED(clientStatus))
+ return;
+ clientPID = 0;
+ [oneXServer clientProcessDone:clientStatus];
+ }
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/XView.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/XView.h
new file mode 100644
index 000000000..14a8dc917
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/XView.h
@@ -0,0 +1,50 @@
+/*
+ * NSView subclass for Mac OS X rootless X server
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/XView.h,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#import <Cocoa/Cocoa.h>
+
+#include <drivers/event_status_driver.h>
+#include "fakeBoxRec.h"
+
+@interface XView : NSView
+{
+ char *mBits;
+ int mBytesPerRow;
+ int mBitsPerSample;
+ int mSamplesPerPixel;
+ int mBitsPerPixel;
+ int mDepth;
+ BOOL mShaped;
+}
+
+- (id)initWithFrame:(NSRect)aRect;
+- (void)dealloc;
+
+- (void)drawRect:(NSRect)aRect;
+- (BOOL)isFlipped;
+- (BOOL)acceptsFirstResponder;
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;
+- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent;
+
+- (void)mouseDown:(NSEvent *)anEvent;
+
+- (void)setFrameSize:(NSSize)newSize;
+
+- (void)allocBitsForSize:(NSSize)newSize;
+- (char *)bits;
+- (void)getBits:(char **)bits
+ rowBytes:(int *)rowBytes
+ depth:(int *)depth
+ bitsPerPixel:(int *)bpp;
+
+- (void)refreshRects:(fakeBoxRec *)rectList count:(int)count;
+- (void)reshapeRects:(fakeBoxRec *)eraseRects count:(int)count;
+
+- (void)copyToScreen:(fakeBoxRec *)rectList count:(int)count
+ fromTemp:(BOOL)copyFromTemp;
+- (void)copyToShapeBits:(fakeBoxRec *)rectList count:(int)count;
+- (void)eraseFromShapeBits:(fakeBoxRec *)rectList count:(int)count;
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/XView.m b/xc/programs/Xserver/hw/darwin/quartz_1.3/XView.m
new file mode 100644
index 000000000..56b8ecf97
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/XView.m
@@ -0,0 +1,330 @@
+/*
+ * NSView subclass for Mac OS X rootless X server
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/XView.m,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#import "XView.h"
+#include "fakeBoxRec.h"
+
+static const void *infobytes(void *info)
+{
+ return info;
+}
+
+
+static unsigned long *shapeBits = NULL;
+static int shapeWidth = 0;
+static int shapeHeight = 0;
+
+static void reallocShapeBits(NSSize minSize)
+{
+ if (shapeWidth < minSize.width || shapeHeight < minSize.height) {
+ shapeWidth = minSize.width;
+ shapeHeight = minSize.height;
+ if (shapeBits) free(shapeBits);
+ shapeBits = (unsigned long *) malloc(4 * shapeWidth * shapeHeight);
+ }
+}
+
+
+@implementation XView
+
+- (id)initWithFrame:(NSRect)aRect
+{
+ self = [super initWithFrame:aRect];
+ if (!self) return nil;
+
+ mShaped = NO;
+ mBitsPerSample = 8;
+ mSamplesPerPixel = 3;
+ mDepth = mBitsPerSample * mSamplesPerPixel;
+ mBitsPerPixel = 32;
+ mBits = nil;
+ [self allocBitsForSize:aRect.size];
+
+ return self;
+}
+
+- (void)dealloc
+{
+ if (mBits) free(mBits);
+ [super dealloc];
+}
+
+- (void)drawRect:(NSRect)aRect
+{
+ // Never draw here.
+}
+
+- (BOOL)isFlipped
+{
+ return NO;
+}
+
+- (BOOL)isOpaque
+{
+ return !mShaped;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
+{
+ return YES;
+}
+
+- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent
+{
+ return YES;
+}
+
+
+- (void)mouseDown:(NSEvent *)anEvent
+{
+ // Only X is allowed to restack windows.
+ [NSApp preventWindowOrdering];
+ [[self nextResponder] mouseDown:anEvent];
+}
+
+- (void)mouseUp:(NSEvent *)anEvent
+{
+ // Bring app to front if necessary
+ // Don't bring app to front in mouseDown; mousedown-mouseup is too
+ // long and X gets what looks like a mouse drag.
+ if (! [NSApp isActive]) {
+ [NSApp activateIgnoringOtherApps:YES];
+ [NSApp arrangeInFront:nil]; // fixme only bring some windows forward?
+ }
+
+ [[self nextResponder] mouseDown:anEvent];
+}
+
+
+// Reallocate bits.
+// setFrame goes through here too.
+- (void)setFrameSize:(NSSize)newSize
+{
+ [self allocBitsForSize:newSize];
+ [super setFrameSize:newSize];
+}
+
+- (void)allocBitsForSize:(NSSize)newSize
+{
+ if (mBits) free(mBits);
+ mBytesPerRow = newSize.width * mBitsPerPixel / 8;
+ mBits = calloc(mBytesPerRow * newSize.height, 1);
+}
+
+- (char *)bits
+{
+ return mBits;
+}
+
+- (void)getBits:(char **)bits
+ rowBytes:(int *)rowBytes
+ depth:(int *)depth
+ bitsPerPixel:(int *)bpp
+{
+ *bits = mBits;
+ *rowBytes = mBytesPerRow;
+ *depth = mDepth;
+ *bpp = mBitsPerPixel;
+}
+
+- (void)refreshRects:(fakeBoxRec *)rectList count:(int)count
+{
+ if (!mShaped) {
+ [self lockFocus];
+ [self copyToScreen:rectList count:count fromTemp:NO];
+ } else {
+ [self copyToShapeBits:rectList count:count];
+ [self lockFocus];
+ [self copyToScreen:rectList count:count fromTemp:YES];
+ }
+ [[NSGraphicsContext currentContext] flushGraphics];
+ [self unlockFocus];
+}
+
+// eraseRects are OUTSIDE the new shape
+- (void)reshapeRects:(fakeBoxRec *)eraseRects count:(int)count
+{
+ fakeBoxRec bounds = {0, 0, [self frame].size.width,
+ [self frame].size.height};
+
+ if (count == 0 && !mShaped) {
+ [self refreshRects:&bounds count:1];
+ } else {
+ // View is shaped, or used to be shaped.
+ // Shaped windows never become unshaped.
+ // (Mac OS X 10.0.4 does not allow transparent windows
+ // to become opaque.)
+
+ mShaped = YES;
+
+ // Magic. 10.0.4 and 10.1 both require the alpha channel to be
+ // cleared explicitly. 10.0.4 additionally requires the view to
+ // be unlocked between this and the drawing code below.
+ [self lockFocus];
+ [[NSColor clearColor] set];
+ NSRectFill([self frame]);
+ [self unlockFocus];
+
+ // copy everything from X11 to temp
+ // erase eraseRects from temp
+ // copy everything from temp to screen
+ [self lockFocus];
+ [self copyToShapeBits:&bounds count:1];
+ [self eraseFromShapeBits:eraseRects count:count];
+ [self copyToScreen:&bounds count:1 fromTemp:YES];
+ [[NSGraphicsContext currentContext] flushGraphics];
+ [self unlockFocus];
+ }
+}
+
+
+- (void)eraseFromShapeBits:(fakeBoxRec *)rectList count:(int)count
+{
+ unsigned long *dst = NULL; // don't assign yet
+ int dstWidth = 0; // don't assign yet
+ fakeBoxRec *r;
+ fakeBoxRec *end;
+
+ assert(mBitsPerPixel == 32);
+ reallocShapeBits([self frame].size);
+ dst = shapeBits;
+ dstWidth = shapeWidth;
+
+ for (r = rectList, end = rectList + count; r < end; r++) {
+ unsigned long *dstline = dst + dstWidth*r->y1 + r->x1;
+ int h = r->y2 - r->y1;
+
+ while (h--) {
+ unsigned long *dstp = dstline;
+ int w = r->x2 - r->x1;
+
+ while (w--) {
+ *dstp++ = 0x00000000;
+ }
+ dstline += dstWidth;
+ }
+ }
+}
+
+// assumes X11 bits and temp bits are 32-bit
+- (void)copyToShapeBits:(fakeBoxRec *)rectList count:(int)count
+{
+ unsigned long *src = (unsigned long *) mBits;
+ unsigned long *dst = NULL; // don't assign yet
+ int srcWidth = mBytesPerRow / 4;
+ int dstWidth = 0; // don't assign yet
+ fakeBoxRec *r;
+ fakeBoxRec *end;
+
+ assert(mBitsPerPixel == 32);
+ reallocShapeBits([self frame].size);
+ dst = shapeBits;
+ dstWidth = shapeWidth;
+
+ for (r = rectList, end = rectList + count; r < end; r++) {
+ unsigned long *srcline = src + srcWidth*r->y1 + r->x1;
+ unsigned long *dstline = dst + dstWidth*r->y1 + r->x1;
+ int h = r->y2 - r->y1;
+
+ while (h--) {
+ unsigned long *srcp = srcline;
+ unsigned long *dstp = dstline;
+ int w = r->x2 - r->x1;
+
+ while (w--) {
+ *dstp++ = *srcp++ | 0xff000000;
+ }
+ srcline += srcWidth;
+ dstline += dstWidth;
+ }
+ }
+}
+
+
+// Copy boxes to the screen from the per-window pixmaps where X draws.
+// rectList is in local, X-flipped coordinates.
+- (void)copyToScreen:(fakeBoxRec *)rectList count:(int)count
+ fromTemp:(BOOL)copyFromTemp
+{
+ unsigned char *offsetbits;
+ fakeBoxRec *r;
+ fakeBoxRec *end;
+ NSRect bounds;
+ char *srcBits;
+ int bytesPerRow;
+ int bitsPerPixel;
+ int bitsPerSample;
+ CGImageAlphaInfo alpha;
+ CGContextRef destCtx = (CGContextRef)[[NSGraphicsContext currentContext]
+ graphicsPort];
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ // fixme colorspace leaks?
+ const CGDataProviderDirectAccessCallbacks cb = {
+ infobytes, NULL, NULL, NULL
+ };
+
+ if (copyFromTemp) {
+ // shapeBits assumed to be 32-bit
+ srcBits = (char *)shapeBits;
+ bytesPerRow = 4 * shapeWidth;
+ bitsPerPixel = 32;
+ bitsPerSample = 8;
+ alpha = kCGImageAlphaPremultipliedFirst; // premultiplied ARGB
+ } else {
+ srcBits = mBits;
+ bytesPerRow = mBytesPerRow;
+ bitsPerPixel = mBitsPerPixel;
+ bitsPerSample = mBitsPerSample;
+ alpha = kCGImageAlphaNoneSkipFirst; // xRGB
+ }
+
+ bounds = [self frame];
+ bounds.origin.x = bounds.origin.y = 0;
+
+ for (r = rectList, end = rectList + count; r < end; r++) {
+ NSRect nsr = {{r->x1, r->y1}, {r->x2-r->x1, r->y2-r->y1}};
+ CGRect destRect;
+ CGDataProviderRef dataProviderRef;
+ CGImageRef imageRef;
+
+ // Clip to window
+ // (bounds origin is (0,0) so it can be used in either flip)
+ // fixme is this necessary with pixmap-per-window?
+ nsr = NSIntersectionRect(nsr, bounds);
+
+ // Disallow empty rects
+ if (nsr.size.width <= 0 || nsr.size.height <= 0) continue;
+
+ offsetbits = srcBits + (int)(nsr.origin.y * bytesPerRow +
+ nsr.origin.x * bitsPerPixel/8);
+
+ // Flip r to Cocoa-flipped
+ nsr.origin.y = bounds.size.height - nsr.origin.y - nsr.size.height;
+ destRect = CGRectMake(nsr.origin.x, nsr.origin.y,
+ nsr.size.width, nsr.size.height);
+
+ dataProviderRef = CGDataProviderCreateDirectAccess(offsetbits,
+ destRect.size.height * bytesPerRow, &cb);
+
+ imageRef = CGImageCreate(destRect.size.width, destRect.size.height,
+ bitsPerSample, bitsPerPixel, bytesPerRow,
+ colorSpace, alpha, dataProviderRef, NULL,
+ 1, kCGRenderingIntentDefault);
+
+ CGContextDrawImage(destCtx, destRect, imageRef);
+ CGImageRelease(imageRef);
+ CGDataProviderRelease(dataProviderRef);
+ }
+}
+
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.h
new file mode 100644
index 000000000..4f7d1ec78
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.h
@@ -0,0 +1,36 @@
+/*
+ * NSWindow subclass for Mac OS X rootless X server
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.h,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#import <Cocoa/Cocoa.h>
+#import "XView.h"
+
+#include "fakeBoxRec.h"
+
+@interface XWindow : NSWindow
+{
+ XView *mView;
+}
+
+- (id)initWithContentRect:(NSRect)aRect
+ isRoot:(BOOL)isRoot;
+- (void)dealloc;
+
+- (char *)bits;
+- (void)getBits:(char **)bits
+ rowBytes:(int *)rowBytes
+ depth:(int *)depth
+ bitsPerPixel:(int *)bpp;
+
+- (void)refreshRects:(fakeBoxRec *)rectList
+ count:(int)count;
+
+- (void)orderWindow:(NSWindowOrderingMode)place
+ relativeTo:(int)otherWindowNumber;
+
+- (void)sendEvent:(NSEvent *)anEvent;
+- (BOOL)canBecomeMainWindow;
+- (BOOL)canBecomeKeyWindow;
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.m b/xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.m
new file mode 100644
index 000000000..02d030819
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.m
@@ -0,0 +1,104 @@
+/*
+ * NSWindow subclass for Mac OS X rootless X server
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/XWindow.m,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#import "XWindow.h"
+
+
+@implementation XWindow
+
+// XWindow MUST NOT autodisplay! Autodisplay can cause a deadlock.
+// event thread - autodisplay: locks view hierarchy, then window
+// X Server thread - window resize: locks window, then view hierarchy
+// Deadlock occurs if each thread gets one lock and waits for the other.
+
+// XWindow MUST defer! Otherwise an assertion fails in
+// NSViewHierarchyLock sometimes.
+
+- (id)initWithContentRect:(NSRect)aRect
+ isRoot:(BOOL)isRoot
+{
+ int style;
+ NSRect viewRect = {{0, 0}, {aRect.size.width, aRect.size.height}};
+ style = NSBorderlessWindowMask;
+
+ self = [super initWithContentRect: aRect
+ styleMask: style
+ backing: NSBackingStoreBuffered
+ defer: YES];
+ if (! self) return NULL;
+
+ [self setBackgroundColor:[NSColor clearColor]]; // erase transparent
+ [self setAlphaValue:1.0]; // draw opaque
+ [self setOpaque:YES]; // changed when window is shaped
+
+ [self useOptimizedDrawing:YES]; // Has no overlapping sub-views
+ [self setAutodisplay:NO]; // MUST NOT autodisplay! See comment above
+ [self disableFlushWindow]; // We do all the flushing manually
+ [self setHasShadow: !isRoot]; // All windows have shadows except root
+
+ // [self setAcceptsMouseMovedEvents:YES]; // MUST be AFTER orderFront?
+
+ mView = [[XView alloc] initWithFrame: viewRect];
+ [self setContentView:mView];
+ [self setInitialFirstResponder:mView];
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [mView release];
+ [super dealloc];
+}
+
+- (char *)bits
+{
+ return [mView bits];
+}
+
+- (void)getBits:(char **)bits
+ rowBytes:(int *)rowBytes
+ depth:(int *)depth
+ bitsPerPixel:(int *)bpp
+{
+ [mView getBits:bits rowBytes:rowBytes depth:depth bitsPerPixel:bpp];
+}
+
+
+// rects are X-flip and LOCAL coords
+- (void)refreshRects:(fakeBoxRec *)rectList count:(int)count;
+{
+ [mView refreshRects:rectList count:count];
+}
+
+
+// Deferred windows don't handle mouse moved events very well.
+- (void)orderWindow:(NSWindowOrderingMode)place
+ relativeTo:(int)otherWindowNumber
+{
+ [super orderWindow:place relativeTo:otherWindowNumber];
+ [self setAcceptsMouseMovedEvents:YES];
+}
+
+- (void)sendEvent:(NSEvent *)anEvent
+{
+ [super sendEvent:anEvent];
+ [self setAcceptsMouseMovedEvents:YES];
+}
+
+// XWindow may be frameless, and frameless windows default to
+// NO key and NO main.
+// update: we *don't* want main or key status after all
+- (BOOL)canBecomeMainWindow
+{
+ return NO;
+}
+
+- (BOOL)canBecomeKeyWindow
+{
+ return NO;
+}
+
+@end
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootless.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootless.h
new file mode 100644
index 000000000..716d8564a
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootless.h
@@ -0,0 +1,127 @@
+/*
+ * External interface to generic rootless mode
+ *
+ * Greg Parker gparker@cs.stanford.edu March 3, 2001
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootless.h,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#ifndef _ROOTLESS_H
+#define _ROOTLESS_H
+
+#include "mi.h"
+#include "gcstruct.h"
+
+// RootlessFrameRec
+// Describes a single rootless window (aka frame).
+// The rootless mode keeps track of window position, and the
+// rootless implementation is responsible for the pixmap.
+// Multiple screens: all coordinates are SCREEN-LOCAL, not global.
+
+
+typedef struct RootlessFrameRec {
+ /* Data maintained by rootless mode */
+ /* position and size, including window border, in screen coordinates */
+ int x;
+ int y;
+ unsigned int w;
+ unsigned int h;
+ WindowPtr win; /* the top-level window drawn in this frame */
+ int isRoot; /* TRUE if this is the root window */
+
+ /* Data maintained by rootless implementation */
+ char *pixelData;
+ int depth; // color bits per pixel; depth <= bitsPerPixel
+ int bitsPerPixel;
+ int bytesPerRow;
+
+ void *devPrivate; /* for caller's use */
+} RootlessFrameRec, *RootlessFramePtr;
+
+
+// Create a new frame.
+// pUpper is the window above the new frame, or NULL if the new
+// frame will be on top.
+// pFrame is completely initialized. devPrivate is NULL
+// The pixmap must be valid when this is done.
+typedef void (*RootlessCreateFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, RootlessFramePtr pUpper);
+
+// Destroy a frame. Caller must free any private data and the pixmap.
+// All drawing is stopped and all updates are flushed before this is called.
+typedef void (*RootlessDestroyFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame);
+
+// Move a frame on screen.
+// The frame changes position and nothing else.
+// pFrame and pFrame->win already contain the information about the
+// new position. oldX and oldY are the old position.
+// All updates are flushed before this is called.
+// The pixmap may change during this function.
+typedef void (*RootlessMoveFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, int oldX, int oldY);
+
+// Change frame ordering (aka stacking, layering)
+// pFrame->win already has its new siblings.
+// pOldNext is the window that was below this one, or NULL if this was
+// at the bottom.
+// pNewNext is the window that is now below this one, or NULL if this is
+// now at the bottom.
+typedef void (*RootlessRestackFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RootlessFramePtr pOldNext, RootlessFramePtr pNewNext);
+
+// Flush drawing updates to the screen.
+// pDamage contains all changed pixels.
+// pDamage is in frame-local coordinates.
+// pDamage is clipped to the frame bounds and the frame shape.
+typedef void (*RootlessUpdateRegionProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, RegionPtr pDamage);
+
+// Change the frame's shape.
+// pNewShape is in frame-local coordinates.
+// Everything outside pNewShape is no longer part of the frame.
+// pNewShape is {0, 0, width, height} for a plain-shaped frame.
+// fixme can the pixmap change here?
+// fixme reimplement shape
+typedef void (*RootlessReshapeFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame, RegionPtr pNewShape);
+
+// Frame is about to resize.
+// The frame has its new position and size already.
+// postconditions:
+// The pixmap MUST point to a pixmap with the new size.
+// The pixmap data is undefined.
+// The old pixmap may be destroyed here.
+typedef void (*RootlessStartResizeFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY, unsigned int oldW, unsigned int oldH);
+
+// Frame is done resizing.
+// Destroy the old pixmap if you haven't already.
+typedef void (*RootlessFinishResizeFrameProc)
+ (ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY, unsigned int oldW, unsigned int oldH);
+
+
+// The callback function list.
+// Any of these may be NULL.
+typedef struct RootlessFrameProcs {
+ RootlessCreateFrameProc CreateFrame;
+ RootlessDestroyFrameProc DestroyFrame;
+
+ RootlessMoveFrameProc MoveFrame;
+ RootlessStartResizeFrameProc StartResizeFrame;
+ RootlessFinishResizeFrameProc FinishResizeFrame;
+ RootlessRestackFrameProc RestackFrame;
+ RootlessReshapeFrameProc ReshapeFrame;
+
+ RootlessUpdateRegionProc UpdateRegion;
+
+ // RootlessStartDrawingProc StartDrawing;
+ // RootlessStopDrawingProc StopDrawing;
+} RootlessFrameProcs;
+
+// Initialize rootless mode on the given screen.
+Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcs *procs);
+
+#endif /* _ROOTLESS_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAqua.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAqua.h
new file mode 100644
index 000000000..b89a879e9
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAqua.h
@@ -0,0 +1,15 @@
+/*
+ * Rootless setup for Aqua
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAqua.h,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#ifndef _ROOTLESSAQUA_H
+#define _ROOTLESSAQUA_H
+
+Bool AquaAddScreen(int index, ScreenPtr pScreen);
+Bool AquaSetupScreen(int index, ScreenPtr pScreen);
+void AquaDisplayInit(void);
+
+#endif /* _ROOTLESSAQUA_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaGlue.c b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaGlue.c
new file mode 100644
index 000000000..29cbd6e10
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaGlue.c
@@ -0,0 +1,226 @@
+/*
+ * Generic rootless to Aqua specific glue code
+ *
+ * This code acts as a glue between the generic rootless X server code
+ * and the Aqua specific implementation, which includes definitions that
+ * conflict with stardard X types.
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaGlue.c,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#include "quartzCommon.h"
+#include "darwin.h"
+#include "rootlessAqua.h"
+#include "rootlessAquaImp.h"
+#include "rootless.h"
+
+#include "regionstr.h"
+#include "scrnintstr.h"
+#include "globals.h" // dixScreenOrigins[]
+
+
+/////////////////////////////////////////
+// Rootless mode callback glue
+
+static void
+AquaGlueCreateFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RootlessFramePtr pUpper)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ pFrame->devPrivate = AquaNewWindow(pUpper ? pUpper->devPrivate : NULL,
+ pFrame->x + sx, pFrame->y + sy,
+ pFrame->w, pFrame->h,
+ pFrame->isRoot);
+ AquaGetPixmap(pFrame->devPrivate, &pFrame->pixelData,
+ &pFrame->bytesPerRow, &pFrame->depth,
+ &pFrame->bitsPerPixel);
+}
+
+
+static void
+AquaGlueDestroyFrame(ScreenPtr pScreen, RootlessFramePtr pFrame)
+{
+ AquaDestroyWindow(pFrame->devPrivate);
+}
+
+static void
+AquaGlueMoveFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ AquaMoveWindow(pFrame->devPrivate, pFrame->x + sx, pFrame->y + sy);
+}
+
+
+static void
+AquaGlueStartResizeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ AquaStartResizeWindow(pFrame->devPrivate,
+ pFrame->x + sx, pFrame->y + sy, pFrame->w, pFrame->h);
+ AquaGetPixmap(pFrame->devPrivate, &pFrame->pixelData,
+ &pFrame->bytesPerRow, &pFrame->depth,
+ &pFrame->bitsPerPixel);
+}
+
+static void
+AquaGlueFinishResizeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH)
+{
+ int sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
+ int sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
+
+ AquaFinishResizeWindow(pFrame->devPrivate,
+ pFrame->x + sx, pFrame->y + sy,
+ pFrame->w, pFrame->h);
+}
+
+
+static void
+AquaGlueRestackFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RootlessFramePtr pOldPrev,
+ RootlessFramePtr pNewPrev)
+{
+ AquaRestackWindow(pFrame->devPrivate,
+ pNewPrev ? pNewPrev->devPrivate : NULL);
+}
+
+static void
+AquaGlueReshapeFrame(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RegionPtr pNewShape)
+{
+ // Don't correct for dixScreenOrigins here.
+ // pNewShape is in window-local coordinates.
+ BoxRec shapeBox = {0, 0, pFrame->w, pFrame->h};
+ if (pFrame->isRoot) return; // shouldn't happen; mi or dix covers this
+
+ REGION_INVERSE(pScreen, pNewShape, pNewShape, &shapeBox);
+ AquaReshapeWindow(pFrame->devPrivate,
+ (fakeBoxRec *) REGION_RECTS(pNewShape),
+ REGION_NUM_RECTS(pNewShape));
+}
+
+static void
+AquaGlueUpdateRegion(ScreenPtr pScreen, RootlessFramePtr pFrame,
+ RegionPtr pDamage)
+{
+ AquaUpdateRects(pFrame->devPrivate,
+ (fakeBoxRec *) REGION_RECTS(pDamage),
+ REGION_NUM_RECTS(pDamage));
+}
+
+#if 0
+static void
+AquaGlueStartDrawing(ScreenPtr pScreen, RootlessFramePtr pFrame)
+{
+ AquaStartDrawing(pFrame->devPrivate, &pFrame->pixelData,
+ &pFrame->bytesPerRow, &pFrame->depth,
+ &pFrame->bitsPerPixel);
+}
+
+static void
+AquaGlueStopDrawing(ScreenPtr pScreen, RootlessFramePtr pFrame)
+{
+ AquaStopDrawing(pFrame->devPrivate);
+}
+#endif
+
+static RootlessFrameProcs aquaRootlessProcs = {
+ AquaGlueCreateFrame,
+ AquaGlueDestroyFrame,
+ AquaGlueMoveFrame,
+ AquaGlueStartResizeFrame,
+ AquaGlueFinishResizeFrame,
+ AquaGlueRestackFrame,
+ AquaGlueReshapeFrame,
+ AquaGlueUpdateRegion
+};
+
+
+///////////////////////////////////////
+// Rootless mode initialization.
+// Exported by rootlessAqua.h
+
+/*
+ * AquaDisplayInit
+ * Find all Aqua screens.
+ */
+void
+AquaDisplayInit(void)
+{
+ darwinScreensFound = AquaDisplayCount();
+}
+
+
+/*
+ * AquaAddScreen
+ * Init the framebuffer and record pixmap parameters for the screen.
+ */
+Bool
+AquaAddScreen(int index, ScreenPtr pScreen)
+{
+ DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
+ QuartzScreenPtr displayInfo = QUARTZ_PRIV(pScreen);
+ CGRect cgRect;
+ CGDisplayCount numDisplays;
+ CGDisplayCount allocatedDisplays = 0;
+ CGDirectDisplayID *displays = NULL;
+ CGDisplayErr cgErr;
+
+ dfb->pixelInfo.pixelType = kIORGBDirectPixels;
+ AquaScreenInit(index, &dfb->x, &dfb->y, &dfb->width, &dfb->height,
+ &dfb->pitch, &dfb->pixelInfo.bitsPerComponent,
+ &dfb->pixelInfo.componentCount, &dfb->bitsPerPixel);
+ dfb->colorBitsPerPixel = dfb->pixelInfo.bitsPerComponent *
+ dfb->pixelInfo.componentCount;
+
+ // No frame buffer - it's all in window pixmaps.
+ dfb->framebuffer = NULL; // malloc(dfb.pitch * dfb.height);
+
+ // Get all CoreGraphics displays covered by this X11 display.
+ cgRect = CGRectMake(dfb->x, dfb->y, dfb->width, dfb->height);
+ do {
+ cgErr = CGGetDisplaysWithRect(cgRect, 0, NULL, &numDisplays);
+ if (cgErr) break;
+ allocatedDisplays = numDisplays;
+ displays = xrealloc(displays,
+ numDisplays * sizeof(CGDirectDisplayID));
+ cgErr = CGGetDisplaysWithRect(cgRect, allocatedDisplays, displays,
+ &numDisplays);
+ if (cgErr != CGDisplayNoErr) break;
+ } while (numDisplays > allocatedDisplays);
+
+ if (cgErr != CGDisplayNoErr || numDisplays == 0) {
+ ErrorF("Could not find CGDirectDisplayID(s) for X11 screen %d: %dx%d @ %d,%d.\n",
+ index, dfb->width, dfb->height, dfb->x, dfb->y);
+ return FALSE;
+ }
+
+ // This X11 screen covers all CoreGraphics displays we just found.
+ // If there's more than one CG display, then video mirroring is on
+ // or PseudoramiX is on.
+ displayInfo->displayCount = allocatedDisplays;
+ displayInfo->displayIDs = displays;
+
+ return TRUE;
+}
+
+/*
+ * AquaSetupScreen
+ * Setup the screen for rootless access.
+ */
+Bool
+AquaSetupScreen(int index, ScreenPtr pScreen)
+{
+ return RootlessInit(pScreen, &aquaRootlessProcs);
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.h
new file mode 100644
index 000000000..9ec56dca8
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.h
@@ -0,0 +1,38 @@
+/*
+ * Rootless implementation for Mac OS X Aqua environment
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.h,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#ifndef _ROOTLESSAQUAIMP_H
+#define _ROOTLESSAQUAIMP_H
+
+#include "fakeBoxRec.h"
+
+int AquaDisplayCount();
+
+void AquaScreenInit(int index, int *x, int *y, int *width, int *height,
+ int *rowBytes, unsigned long *bps, unsigned long *spp,
+ int *bpp);
+
+void *AquaNewWindow(void *upperw, int x, int y, int w, int h, int isRoot);
+
+void AquaDestroyWindow(void *rw);
+
+void AquaMoveWindow(void *rw, int x, int y);
+
+void AquaStartResizeWindow(void *rw, int x, int y, int w, int h);
+
+void AquaFinishResizeWindow(void *rw, int x, int y, int w, int h);
+
+void AquaUpdateRects(void *rw, fakeBoxRec *rects, int count);
+
+void AquaRestackWindow(void *rw, void *lowerw);
+
+void AquaReshapeWindow(void *rw, fakeBoxRec *rects, int count);
+
+void AquaGetPixmap(void *rw, char **bits,
+ int *rowBytes, int *depth, int *bpp);
+
+#endif /* _ROOTLESSAQUAIMP_H */
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.m b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.m
new file mode 100644
index 000000000..b3d9ae374
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.m
@@ -0,0 +1,237 @@
+/*
+ * Rootless implementation for Mac OS X Aqua environment
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.m,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#include "rootlessAquaImp.h"
+#include "XWindow.h"
+#include "fakeBoxRec.h"
+#include "quartzCommon.h"
+#include "pseudoramiX.h"
+
+extern void ErrorF(const char *, ...);
+
+typedef struct {
+ XWindow *window;
+} AquaWindowRec;
+
+
+#define WINREC(rw) ((AquaWindowRec *)rw)
+
+
+// Multihead note: When rootless mode uses PseudoramiX, the
+// X server only sees one screen; only PseudoramiX itself knows
+// about all of the screens.
+
+int AquaDisplayCount()
+{
+ aquaNumScreens = [[NSScreen screens] count];
+
+ if (noPseudoramiXExtension) {
+ return aquaNumScreens;
+ } else {
+ return 1; // only PseudoramiX knows about the rest
+ }
+}
+
+void AquaScreenInit(int index, int *x, int *y, int *width, int *height,
+ int *rowBytes, unsigned long *bps, unsigned long *spp,
+ int *bpp)
+{
+ *bps = 8;
+ *spp = 3;
+ *bpp = 32;
+
+ if (noPseudoramiXExtension) {
+ NSScreen *screen = [[NSScreen screens] objectAtIndex:index];
+ NSRect frame = [screen frame];
+
+ // set x, y so (0,0) is top left of main screen
+ *x = NSMinX(frame);
+ *y = NSHeight([[NSScreen mainScreen] frame]) - NSHeight(frame) -
+ NSMinY(frame);
+
+ *width = NSWidth(frame);
+ *height = NSHeight(frame);
+ *rowBytes = (*width) * (*bpp) / 8;
+
+ // Shift the usable part of main screen down to avoid the menu bar.
+ if (NSEqualRects(frame, [[NSScreen mainScreen] frame])) {
+ *y += aquaMenuBarHeight;
+ *height -= aquaMenuBarHeight;
+ }
+
+ } else {
+ int i;
+ NSRect unionRect = NSMakeRect(0, 0, 0, 0);
+ NSArray *screens = [NSScreen screens];
+
+ // Get the union of all screens (minus the menu bar on main screen)
+ for (i = 0; i < [screens count]; i++) {
+ NSScreen *screen = [screens objectAtIndex:i];
+ NSRect frame = [screen frame];
+ frame.origin.y = [[NSScreen mainScreen] frame].size.height -
+ frame.size.height - frame.origin.y;
+ if (NSEqualRects([screen frame], [[NSScreen mainScreen] frame])) {
+ frame.origin.y += aquaMenuBarHeight;
+ frame.size.height -= aquaMenuBarHeight;
+ }
+ unionRect = NSUnionRect(unionRect, frame);
+ }
+
+ // Use unionRect as the screen size for the X server.
+ *x = unionRect.origin.x;
+ *y = unionRect.origin.y;
+ *width = unionRect.size.width;
+ *height = unionRect.size.height;
+ *rowBytes = (*width) * (*bpp) / 8;
+
+ // Tell PseudoramiX about the real screens.
+ // InitOutput() will move the big screen to (0,0),
+ // so compensate for that here.
+ for (i = 0; i < [screens count]; i++) {
+ NSScreen *screen = [screens objectAtIndex:i];
+ NSRect frame = [screen frame];
+ int j;
+
+ // Skip this screen if it's a mirrored copy of an earlier screen.
+ for (j = 0; j < i; j++) {
+ if (NSEqualRects(frame, [[screens objectAtIndex:j] frame])) {
+ ErrorF("PseudoramiX screen %d is a mirror of screen %d.\n",
+ i, j);
+ break;
+ }
+ }
+ if (j < i) continue; // this screen is a mirrored copy
+
+ frame.origin.y = [[NSScreen mainScreen] frame].size.height -
+ frame.size.height - frame.origin.y;
+
+ if (NSEqualRects([screen frame], [[NSScreen mainScreen] frame])) {
+ frame.origin.y += aquaMenuBarHeight;
+ frame.size.height -= aquaMenuBarHeight;
+ }
+
+ ErrorF("PseudoramiX screen %d added: %dx%d @ (%d,%d).\n", i,
+ (int)frame.size.width, (int)frame.size.height,
+ (int)frame.origin.x, (int)frame.origin.y);
+
+ frame.origin.x -= unionRect.origin.x;
+ frame.origin.y -= unionRect.origin.y;
+
+ ErrorF("PseudoramiX screen %d placed at X11 coordinate (%d,%d).\n",
+ i, (int)frame.origin.x, (int)frame.origin.y);
+
+ PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
+ frame.size.width, frame.size.height);
+ }
+ }
+}
+
+void *AquaNewWindow(void *upperw, int x, int y, int w, int h, int isRoot)
+{
+ AquaWindowRec *winRec = (AquaWindowRec *)malloc(sizeof(AquaWindowRec));
+ NSRect frame = NSMakeRect(x, NSHeight([[NSScreen mainScreen] frame]) -
+ y - h, w, h);
+
+ winRec->window = [[XWindow alloc] initWithContentRect:frame isRoot:isRoot];
+
+ if (upperw) {
+ AquaWindowRec *upperRec = WINREC(upperw);
+ int uppernum = [upperRec->window windowNumber];
+ [winRec->window orderWindow:NSWindowBelow relativeTo:uppernum];
+ } else {
+ [winRec->window orderFront:nil];
+ }
+
+ // fixme hide root for now
+ if (isRoot) [winRec->window orderOut:nil];
+
+ return winRec;
+}
+
+void AquaDestroyWindow(void *rw)
+{
+ AquaWindowRec *winRec = WINREC(rw);
+
+ [winRec->window release];
+}
+
+void AquaMoveWindow(void *rw, int x, int y)
+{
+ AquaWindowRec *winRec = WINREC(rw);
+ NSPoint topLeft = NSMakePoint(x, NSHeight([[NSScreen mainScreen] frame]) -
+ y);
+
+ [winRec->window setFrameTopLeftPoint:topLeft];
+}
+
+void AquaStartResizeWindow(void *rw, int x, int y, int w, int h)
+{
+ AquaWindowRec *winRec = WINREC(rw);
+ NSRect frame = NSMakeRect(x, NSHeight([[NSScreen mainScreen] frame]) -
+ y - h, w, h);
+
+ [winRec->window setFrame:frame display:NO];
+}
+
+void AquaFinishResizeWindow(void *rw, int x, int y, int w, int h)
+{
+ // refresh everything? fixme yes for testing
+ fakeBoxRec box = {0, 0, w, h};
+ AquaWindowRec *winRec = WINREC(rw);
+
+ [winRec->window refreshRects:&box count:1];
+}
+
+void AquaUpdateRects(void *rw, fakeBoxRec *rects, int count)
+{
+ AquaWindowRec *winRec = WINREC(rw);
+
+ [winRec->window refreshRects:rects count:count];
+}
+
+// fixme is this upperw or lowerw?
+void AquaRestackWindow(void *rw, void *upperw)
+{
+ AquaWindowRec *winRec = WINREC(rw);
+
+ if (upperw) {
+ AquaWindowRec *upperRec = WINREC(upperw);
+ int uppernum = [upperRec->window windowNumber];
+ [winRec->window orderWindow:NSWindowBelow relativeTo:uppernum];
+ } else {
+ [winRec->window orderFront:nil];
+ }
+ // [winRec->window setAcceptsMouseMovedEvents:YES];
+ // fixme prefer to orderFront whenever possible - pass upperw, not lowerw
+}
+
+// rects are the areas not part of the new shape
+void AquaReshapeWindow(void *rw, fakeBoxRec *rects, int count)
+{
+ AquaWindowRec *winRec = WINREC(rw);
+
+ // make transparent if window is now shaped
+ // transparent windows never go back to opaque
+ if (count > 0) {
+ [winRec->window setOpaque:NO];
+ }
+
+ [[winRec->window contentView] reshapeRects:rects count:count];
+
+ if (! [winRec->window isOpaque]) {
+ // force update of window shadow
+ [winRec->window setHasShadow:NO];
+ [winRec->window setHasShadow:YES];
+ }
+}
+
+void AquaGetPixmap(void *rw, char **bits,
+ int *rowBytes, int *depth, int *bpp)
+{
+ AquaWindowRec *winRec = WINREC(rw);
+
+ [winRec->window getBits:bits rowBytes:rowBytes depth:depth
+ bitsPerPixel:bpp];
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.c b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.c
new file mode 100644
index 000000000..9fb51f203
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.c
@@ -0,0 +1,262 @@
+/*
+ * Common rootless definitions and code
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.c,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#include "rootlessCommon.h"
+
+
+RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
+
+
+// Returns the top-level parent of pWindow.
+// The root is the top-level parent of itself, even though the root is
+// not otherwise considered to be a top-level window.
+WindowPtr TopLevelParent(WindowPtr pWindow)
+{
+ WindowPtr top = pWindow;
+
+ if (IsRoot(pWindow)) return pWindow; // root is top-level parent of itself
+ while (top && ! IsTopLevel(top)) top = top->parent;
+ return top;
+}
+
+
+// Returns TRUE if this window is visible inside a frame
+// (e.g. it is visible and has a top-level or root parent)
+Bool IsFramedWindow(WindowPtr pWin)
+{
+ WindowPtr top;
+
+ if (! pWin->realized) return FALSE;
+ top = TopLevelParent(pWin);
+ return (top && WINREC(top));
+}
+
+
+// Move the given pixmap's base address to where pixel (0, 0)
+// would be if the pixmap's actual data started at (x, y)
+void SetPixmapBaseToScreen(PixmapPtr pix, int x, int y)
+{
+ pix->devPrivate.ptr = (char *)(pix->devPrivate.ptr) -
+ (pix->drawable.bitsPerPixel/8 * x + y*pix->devKind);
+}
+
+
+// Update pWindow's pixmap.
+// This needs to be called every time a window moves relative to
+// its top-level parent, or the parent's pixmap data is reallocated.
+// Three cases:
+// * window is top-level with no existing pixmap: make one
+// * window is top-level with existing pixmap: update it in place
+// * window is descendant of top-level: point to top-level's pixmap
+void UpdatePixmap(WindowPtr pWindow)
+{
+ WindowPtr top = TopLevelParent(pWindow);
+ RootlessWindowRec *winRec;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ PixmapPtr pix;
+
+ RL_DEBUG_MSG("update pixmap (win 0x%x)", pWindow);
+
+ // Don't use IsFramedWindow(); window is unrealized during RealizeWindow().
+
+ if (! top) {
+ RL_DEBUG_MSG("no parent\n");
+ return;
+ }
+ winRec = WINREC(top);
+ if (!winRec) {
+ RL_DEBUG_MSG("not framed\n");
+ return;
+ }
+
+ if (pWindow == top) {
+ // This is the top window. Update its pixmap.
+ if (winRec->pixmap == NULL) {
+ // Allocate a new pixmap.
+ pix = GetScratchPixmapHeader(pScreen,
+ winRec->frame.w, winRec->frame.h,
+ winRec->frame.depth,
+ winRec->frame.bitsPerPixel,
+ winRec->frame.bytesPerRow,
+ winRec->frame.pixelData);
+ SetPixmapBaseToScreen(pix, winRec->frame.x, winRec->frame.y);
+ pScreen->SetWindowPixmap(pWindow, pix);
+ winRec->pixmap = pix;
+ } else {
+ // Update existing pixmap. Update in place so we don't have to
+ // change the children's pixmaps.
+ pix = winRec->pixmap;
+ pScreen->ModifyPixmapHeader(pix,
+ winRec->frame.w, winRec->frame.h,
+ winRec->frame.depth,
+ winRec->frame.bitsPerPixel,
+ winRec->frame.bytesPerRow,
+ winRec->frame.pixelData);
+ SetPixmapBaseToScreen(pix, winRec->frame.x, winRec->frame.y);
+ }
+ } else {
+ // This is not the top window. Point to the parent's pixmap.
+ pix = winRec->pixmap;
+ pScreen->SetWindowPixmap(pWindow, pix);
+ }
+
+ RL_DEBUG_MSG("done\n");
+}
+
+
+#ifdef SHAPE
+
+// boundingShape = outside border (like borderClip)
+// clipShape = inside border (like clipList)
+// Both are in window-local coordinates
+// We only care about boundingShape (fixme true?)
+
+// RootlessReallySetShape is used in several places other than SetShape.
+// Most importantly, SetShape is often called on unmapped windows, so we
+// have to wait until the window is mapped to reshape the frame.
+static void RootlessReallySetShape(WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RegionRec newShape;
+
+ if (IsRoot(pWin)) return;
+ if (!IsTopLevel(pWin)) return;
+ if (!winRec) return;
+
+ if (wBoundingShape(pWin)) {
+ // wBoundingShape is relative to *inner* origin of window.
+ // Translate by borderWidth to get the outside-relative position.
+ REGION_INIT(pScreen, &newShape, NullBox, 0);
+ REGION_COPY(pScreen, &newShape, wBoundingShape(pWin));
+ REGION_TRANSLATE(pScreen, &newShape, pWin->borderWidth,
+ pWin->borderWidth);
+ } else {
+ newShape.data = NULL;
+ newShape.extents.x1 = 0;
+ newShape.extents.y1 = 0;
+ newShape.extents.x2 = winRec->frame.w;
+ newShape.extents.y2 = winRec->frame.h;
+ }
+ RL_DEBUG_MSG("reshaping...");
+ RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
+ REGION_NUM_RECTS(&newShape),
+ newShape.extents.x1, newShape.extents.y1,
+ newShape.extents.x2, newShape.extents.y2);
+ CallFrameProc(pScreen, ReshapeFrame,(pScreen, &winRec->frame, &newShape));
+ REGION_UNINIT(pScreen, &newShape);
+}
+
+#endif // SHAPE
+
+
+// pRegion is GLOBAL
+void
+RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion)
+{
+ pWindow = TopLevelParent(pWindow);
+ if (!pWindow) {
+ RL_DEBUG_MSG("RootlessDamageRegion: window is not framed\n");
+ } else if (!WINREC(pWindow)) {
+ RL_DEBUG_MSG("RootlessDamageRegion: top-level window not a frame\n");
+ } else {
+ REGION_UNION((pWindow)->drawable.pScreen, &WINREC(pWindow)->damage,
+ &WINREC(pWindow)->damage, (pRegion));
+ }
+}
+
+
+// pBox is GLOBAL
+void
+RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox)
+{
+ RegionRec region;
+
+ REGION_INIT(pWindow->drawable.pScreen, &region, pBox, 1);
+ RootlessDamageRegion(pWindow, &region);
+}
+
+
+// (x, y, w, h) is in window-local coordinates.
+void
+RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
+{
+ BoxRec box;
+ RegionRec region;
+
+ x += pWindow->drawable.x;
+ y += pWindow->drawable.y;
+ box.x1 = x;
+ box.x2 = x + w;
+ box.y1 = y;
+ box.y2 = y + h;
+ REGION_INIT(pWindow->drawable.pScreen, &region, &box, 1);
+ RootlessDamageRegion(pWindow, &region);
+}
+
+#ifdef SHAPE
+
+void
+RootlessDamageShape(WindowPtr pWin)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ // We only care about the shape of top-level framed windows.
+ if (IsRoot(pWin)) return;
+ if (!IsTopLevel(pWin)) return;
+ if (!winRec) return;
+
+ winRec->shapeDamage = TRUE;
+}
+
+#endif // SHAPE
+
+void
+RootlessRedisplay(WindowPtr pWindow)
+{
+ RootlessWindowRec *winRec = WINREC(pWindow);
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+#ifdef SHAPE
+ if (winRec->shapeDamage) {
+ // Reshape the window. This will also update the entire window.
+ RootlessReallySetShape(pWindow);
+ REGION_EMPTY(pScreen, &winRec->damage);
+ winRec->shapeDamage = FALSE;
+ }
+ else
+#endif // SHAPE
+ if (REGION_NOTEMPTY(pScreen, &winRec->damage)) {
+ REGION_INTERSECT(pScreen, &winRec->damage, &winRec->damage,
+ &pWindow->borderSize);
+
+ // move region to window local coords
+ REGION_TRANSLATE(pScreen, &winRec->damage,
+ -winRec->frame.x, -winRec->frame.y);
+ CallFrameProc(pScreen, UpdateRegion,
+ (pScreen, &winRec->frame, &winRec->damage));
+ REGION_EMPTY(pScreen, &winRec->damage);
+ }
+}
+
+
+void
+RootlessRedisplayScreen(ScreenPtr pScreen)
+{
+ WindowPtr root = WindowTable[pScreen->myNum];
+
+ if (root) {
+ WindowPtr win;
+
+ RootlessRedisplay(root);
+ for (win = root->firstChild; win; win = win->nextSib) {
+ if (WINREC(win)) {
+ RootlessRedisplay(win);
+ }
+ }
+ }
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.h
new file mode 100644
index 000000000..a34a28592
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.h
@@ -0,0 +1,214 @@
+/*
+ * Common internal rootless definitions and code
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessCommon.h,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#ifndef _ROOTLESSCOMMON_H
+#define _ROOTLESSCOMMON_H
+
+#include "rootless.h"
+
+#include "pixmapstr.h"
+#include "windowstr.h"
+
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+
+// Debug output, or not.
+#ifdef ROOTLESSDEBUG
+#define RL_DEBUG_MSG ErrorF
+#else
+#define RL_DEBUG_MSG(a, ...)
+#endif
+
+
+// Global variables
+extern int rootlessGCPrivateIndex;
+extern int rootlessScreenPrivateIndex;
+extern int rootlessWindowPrivateIndex;
+
+
+// RootlessGCRec: private per-gc data
+typedef struct {
+ GCFuncs *originalFuncs;
+ GCOps *originalOps;
+} RootlessGCRec;
+
+
+// RootlessWindowRec: private per-window data
+typedef struct RootlessWindowRec {
+ RootlessFrameRec frame;
+ RegionRec damage;
+ unsigned int borderWidth; // needed for MoveWindow(VTOther) (%$#@!!!)
+ PixmapPtr pixmap;
+#ifdef SHAPE
+ BOOL shapeDamage; // TRUE if shape has changed
+#endif
+} RootlessWindowRec;
+
+
+// RootlessScreenRec: per-screen private data
+typedef struct {
+ ScreenPtr pScreen;
+ RootlessFrameProcs frameProcs;
+
+ CloseScreenProcPtr CloseScreen;
+
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ MoveWindowProcPtr MoveWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ RestackWindowProcPtr RestackWindow;
+ ChangeBorderWidthProcPtr ChangeBorderWidth;
+ PositionWindowProcPtr PositionWindow;
+ ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+
+ CreateGCProcPtr CreateGC;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ GetImageProcPtr GetImage;
+
+ MarkOverlappedWindowsProcPtr MarkOverlappedWindows;
+ ValidateTreeProcPtr ValidateTree;
+
+#ifdef SHAPE
+ SetShapeProcPtr SetShape;
+#endif
+
+#ifdef RENDER
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+#endif
+
+} RootlessScreenRec;
+
+
+// "Definition of the Porting Layer for the X11 Sample Server" says
+// unwrap and rewrap of screen functions is unnecessary, but
+// screen->CreateGC changes after a call to cfbCreateGC.
+
+#define SCREEN_UNWRAP(screen, fn) \
+ screen->fn = SCREENREC(screen)->fn;
+
+#define SCREEN_WRAP(screen, fn) \
+ SCREENREC(screen)->fn = screen->fn; \
+ screen->fn = Rootless##fn
+
+
+// Accessors for screen and window privates
+
+#define SCREENREC(pScreen) \
+ ((RootlessScreenRec*)(pScreen)->devPrivates[rootlessScreenPrivateIndex].ptr)
+
+#define WINREC(pWin) \
+ ((RootlessWindowRec *)(pWin)->devPrivates[rootlessWindowPrivateIndex].ptr)
+
+
+// Call a rootless implementation function.
+// Many rootless implementation functions are allowed to be NULL.
+#define CallFrameProc(pScreen, proc, params) \
+ if (SCREENREC(pScreen)->frameProcs.proc) { \
+ RL_DEBUG_MSG("calling frame proc " #proc " "); \
+ SCREENREC(pScreen)->frameProcs.proc params; \
+ }
+
+
+// BoxRec manipulators
+// Copied from shadowfb
+
+#define TRIM_BOX(box, pGC) { \
+ BoxPtr extents = &pGC->pCompositeClip->extents;\
+ if(box.x1 < extents->x1) box.x1 = extents->x1; \
+ if(box.x2 > extents->x2) box.x2 = extents->x2; \
+ if(box.y1 < extents->y1) box.y1 = extents->y1; \
+ if(box.y2 > extents->y2) box.y2 = extents->y2; \
+}
+
+#define TRANSLATE_BOX(box, pDraw) { \
+ box.x1 += pDraw->x; \
+ box.x2 += pDraw->x; \
+ box.y1 += pDraw->y; \
+ box.y2 += pDraw->y; \
+}
+
+#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
+ TRANSLATE_BOX(box, pDraw); \
+ TRIM_BOX(box, pGC); \
+}
+
+#define BOX_NOT_EMPTY(box) \
+ (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+
+
+// HUGE_ROOT and NORMAL_ROOT
+// We don't want to clip windows to the edge of the screen.
+// HUGE_ROOT temporarily makes the root window really big.
+// This is needed as a wrapper around any function that calls
+// SetWinSize or SetBorderSize which clip a window against its
+// parents, including the root.
+
+extern RegionRec rootlessHugeRoot;
+
+#define HUGE_ROOT(pWin) \
+ { \
+ WindowPtr w = pWin; \
+ while (w->parent) w = w->parent; \
+ saveRoot = w->winSize; \
+ w->winSize = rootlessHugeRoot; \
+ }
+
+#define NORMAL_ROOT(pWin) \
+ { \
+ WindowPtr w = pWin; \
+ while (w->parent) w = w->parent; \
+ w->winSize = saveRoot; \
+ }
+
+
+// Returns TRUE if this window is a top-level window (i.e. child of the root)
+// The root is not a top-level window.
+#define IsTopLevel(pWin) \
+ ((pWin) && (pWin)->parent && !(pWin)->parent->parent)
+
+// Returns TRUE if this window is a root window
+#define IsRoot(pWin) \
+ ((pWin) == WindowTable[(pWin)->drawable.pScreen->myNum])
+
+// Returns the top-level parent of pWindow.
+// The root is the top-level parent of itself, even though the root is
+// not otherwise considered to be a top-level window.
+WindowPtr TopLevelParent(WindowPtr pWindow);
+
+// Returns TRUE if this window is visible inside a frame
+// (e.g. it is visible and has a top-level or root parent)
+Bool IsFramedWindow(WindowPtr pWin);
+
+// Move the given pixmap's base address to where pixel (0, 0)
+// would be if the pixmap's actual data started at (x, y).
+void SetPixmapBaseToScreen(PixmapPtr pix, int x, int y);
+
+// Update pWindow's pixmap.
+// This needs to be called every time a window moves relative to
+// its top-level parent, or the parent's pixmap data is reallocated.
+void UpdatePixmap(WindowPtr pWindow);
+
+// Routines that cause regions to get redrawn.
+// DamageRegion and DamageRect are in global coordinates.
+// DamageBox is in window-local coordinates.
+void RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion);
+void RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h);
+void RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox);
+void RootlessRedisplay(WindowPtr pWindow);
+void RootlessRedisplayScreen(ScreenPtr pScreen);
+
+// Window reshape needs to be updated. The reshape also forces complete redraw.
+void RootlessDamageShape(WindowPtr pWin);
+
+#endif // _ROOTLESSCOMMON_H
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessGC.c b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessGC.c
new file mode 100644
index 000000000..6d8eb9318
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessGC.c
@@ -0,0 +1,1170 @@
+/*
+ * Graphics Context support for Mac OS X rootless X server
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ *
+ * February 2001 Created
+ * March 3, 2001 Restructured as generic rootless mode
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessGC.c,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "dixfontstr.h"
+#include "mivalidate.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rootlessCommon.h"
+
+
+// GC functions
+static void RootlessValidateGC(GCPtr pGC, unsigned long changes,
+ DrawablePtr pDrawable);
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask);
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void RootlessDestroyGC(GCPtr pGC);
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue,
+ int nrects);
+static void RootlessDestroyClip(GCPtr pGC);
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+
+GCFuncs rootlessGCFuncs = {
+ RootlessValidateGC,
+ RootlessChangeGC,
+ RootlessCopyGC,
+ RootlessDestroyGC,
+ RootlessChangeClip,
+ RootlessDestroyClip,
+ RootlessCopyClip,
+};
+
+// GC operations
+static void RootlessFillSpans();
+static void RootlessSetSpans();
+static void RootlessPutImage();
+static RegionPtr RootlessCopyArea();
+static RegionPtr RootlessCopyPlane();
+static void RootlessPolyPoint();
+static void RootlessPolylines();
+static void RootlessPolySegment();
+static void RootlessPolyRectangle();
+static void RootlessPolyArc();
+static void RootlessFillPolygon();
+static void RootlessPolyFillRect();
+static void RootlessPolyFillArc();
+static int RootlessPolyText8();
+static int RootlessPolyText16();
+static void RootlessImageText8();
+static void RootlessImageText16();
+static void RootlessImageGlyphBlt();
+static void RootlessPolyGlyphBlt();
+static void RootlessPushPixels();
+
+static GCOps rootlessGCOps = {
+ RootlessFillSpans,
+ RootlessSetSpans,
+ RootlessPutImage,
+ RootlessCopyArea,
+ RootlessCopyPlane,
+ RootlessPolyPoint,
+ RootlessPolylines,
+ RootlessPolySegment,
+ RootlessPolyRectangle,
+ RootlessPolyArc,
+ RootlessFillPolygon,
+ RootlessPolyFillRect,
+ RootlessPolyFillArc,
+ RootlessPolyText8,
+ RootlessPolyText16,
+ RootlessImageText8,
+ RootlessImageText16,
+ RootlessImageGlyphBlt,
+ RootlessPolyGlyphBlt,
+ RootlessPushPixels
+#ifdef NEED_LINEHELPER
+ , NULL
+#endif
+};
+
+
+Bool
+RootlessCreateGC(GCPtr pGC)
+{
+ RootlessGCRec *gcrec;
+ RootlessScreenRec *s;
+ Bool result;
+
+ SCREEN_UNWRAP(pGC->pScreen, CreateGC);
+ s = (RootlessScreenRec *) pGC->pScreen->
+ devPrivates[rootlessScreenPrivateIndex].ptr;
+ result = s->CreateGC(pGC);
+ gcrec = (RootlessGCRec *) pGC->devPrivates[rootlessGCPrivateIndex].ptr;
+ gcrec->originalOps = NULL; // don't wrap ops yet
+ gcrec->originalFuncs = pGC->funcs;
+ pGC->funcs = &rootlessGCFuncs;
+
+ SCREEN_WRAP(pGC->pScreen, CreateGC);
+ return result;
+}
+
+
+// GC func wrapping
+// ValidateGC wraps gcOps iff dest is viewable. All others just unwrap&call.
+
+// GCFUN_UNRAP assumes funcs have been wrapped and
+// does not assume ops have been wrapped
+#define GCFUNC_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ if (gcrec->originalOps) { \
+ (pGC)->ops = gcrec->originalOps; \
+}
+
+#define GCFUNC_WRAP(pGC) \
+ gcrec->originalFuncs = (pGC)->funcs; \
+ (pGC)->funcs = &rootlessGCFuncs; \
+ if (gcrec->originalOps) { \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->ops = &rootlessGCOps; \
+}
+
+
+static void
+RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ GCFUNC_UNWRAP(pGC);
+
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable);
+
+ gcrec->originalOps = NULL;
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr) pDrawable;
+
+ if (pWin->viewable) {
+ gcrec->originalOps = pGC->ops;
+ }
+ }
+
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeGC(pGC, mask);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
+{
+ GCFUNC_UNWRAP(pGCDst);
+ pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst);
+ GCFUNC_WRAP(pGCDst);
+}
+
+static void RootlessDestroyGC(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyGC(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessDestroyClip(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyClip(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ GCFUNC_UNWRAP(pgcDst);
+ pgcDst->funcs->CopyClip(pgcDst, pgcSrc);
+ GCFUNC_WRAP(pgcDst);
+}
+
+
+// GC ops
+// We can't use shadowfb because shadowfb assumes one pixmap
+// and our root window is a special case.
+// So much of this code is copied from shadowfb.
+
+// assumes both funcs and ops are wrapped
+#define GCOP_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ (pGC)->devPrivates[rootlessGCPrivateIndex].ptr; \
+ GCFuncs *saveFuncs = pGC->funcs; \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ (pGC)->ops = gcrec->originalOps;
+
+#define GCOP_WRAP(pGC) \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->funcs = saveFuncs; \
+ (pGC)->ops = &rootlessGCOps;
+
+
+static void
+RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit, int sorted)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill spans start ");
+
+ if (nInit <= 0) {
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nInit;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidthInit++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill spans end\n");
+}
+
+static void
+RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int nspans, int sorted)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("set spans start ");
+
+ if (nspans <= 0) {
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nspans;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidth++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("set spans end\n");
+}
+
+static void
+RootlessPutImage(DrawablePtr dst, GCPtr pGC,
+ int depth, int x, int y, int w, int h,
+ int leftPad, int format, char *pBits)
+{
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("put image start ");
+
+ pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits);
+
+ box.x1 = x + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = y + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("put image end\n");
+}
+
+/* changed area is *dest* rect */
+/* If this code ever goes back go StartDrawing/StopDrawing:
+ * start and stop dst always
+ * start and stop src if src->type is DRAWABLE_WINDOW and src is framed
+ */
+static RegionPtr
+RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty)
+{
+ RegionPtr result;
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst);
+
+ result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy area end\n");
+ return result;
+}
+
+/* changed area is *dest* rect */
+/* If this code ever goes back go StartDrawing/StopDrawing:
+ * start and stop dst always
+ * start and stop src if src->type is DRAWABLE_WINDOW and src is framed
+ */
+static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
+ GCPtr pGC, int srcx, int srcy,
+ int w, int h, int dstx, int dsty,
+ unsigned long plane)
+{
+ RegionPtr result;
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("copy plane start ");
+
+ result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
+ dstx, dsty, plane);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy plane end\n");
+ return result;
+}
+
+// Options for size of changed area:
+// 0 = box per point
+// 1 = big box around all points
+// 2 = accumulate point in 20 pixel radius
+#define ROOTLESS_CHANGED_AREA 1
+#define abs(a) ((a) > 0 ? (a) : -(a))
+
+/* changed area is box around all points */
+static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("polypoint start ");
+
+ pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+#if ROOTLESS_CHANGED_AREA==0
+ // box per point
+ BoxRec box;
+
+ while (npt) {
+ box.x1 = pptInit->x;
+ box.y1 = pptInit->y;
+ box.x2 = box.x1 + 1;
+ box.y2 = box.y1 + 1;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ npt--;
+ pptInit++;
+ }
+
+#elif ROOTLESS_CHANGED_AREA==1
+ // one big box
+ BoxRec box;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+#elif ROOTLESS_CHANGED_AREA==2
+ // clever(?) method: accumulate point in 20-pixel radius
+ BoxRec box;
+ int firstx, firsty;
+
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ while(--npt) {
+ pptInit++;
+ if (abs(pptInit->x - firstx) > 20 ||
+ abs(pptInit->y - firsty) > 20) {
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ } else {
+ if (box.x1 > pptInit->x) box.x1 = pptInit->x;
+ else if (box.x2 < pptInit->x) box.x2 = pptInit->x;
+ if (box.y1 > pptInit->y) box.y1 = pptInit->y;
+ else if (box.y2 < pptInit->y) box.y2 = pptInit->y;
+ }
+ }
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+#endif /* ROOTLESS_CHANGED_AREA */
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polypoint end\n");
+}
+
+#undef ROOTLESS_CHANGED_AREA
+
+/* changed area is box around each line */
+static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly lines start ");
+
+ pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth >> 1;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+
+ if(npt > 1) {
+ if(pGC->joinStyle == JoinMiter)
+ extra = 6 * pGC->lineWidth;
+ else if(pGC->capStyle == CapProjecting)
+ extra = pGC->lineWidth;
+ }
+
+ if(mode == CoordModePrevious) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while(--npt) {
+ pptInit++;
+ x += pptInit->x;
+ y += pptInit->y;
+ if(box.x1 > x)
+ box.x1 = x;
+ else if(box.x2 < x)
+ box.x2 = x;
+ if(box.y1 > y)
+ box.y1 = y;
+ else if(box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly lines end\n");
+}
+
+/* changed area is box around each line segment */
+static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
+ int nseg, xSegment *pSeg)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly segment start (win 0x%x)", dst);
+
+ pGC->ops->PolySegment(dst, pGC, nseg, pSeg);
+
+ if (nseg > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth;
+
+ if(pGC->capStyle != CapProjecting)
+ extra >>= 1;
+
+ if(pSeg->x2 > pSeg->x1) {
+ box.x1 = pSeg->x1;
+ box.x2 = pSeg->x2;
+ } else {
+ box.x2 = pSeg->x1;
+ box.x1 = pSeg->x2;
+ }
+
+ if(pSeg->y2 > pSeg->y1) {
+ box.y1 = pSeg->y1;
+ box.y2 = pSeg->y2;
+ } else {
+ box.y2 = pSeg->y1;
+ box.y1 = pSeg->y2;
+ }
+
+ while(--nseg) {
+ pSeg++;
+ if(pSeg->x2 > pSeg->x1) {
+ if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
+ if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
+ } else {
+ if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
+ if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
+ }
+ if(pSeg->y2 > pSeg->y1) {
+ if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
+ if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
+ } else {
+ if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
+ if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly segment end\n");
+}
+
+/* changed area is box around each line (not entire rects) */
+static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
+ int nRects, xRectangle *pRects)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly rectangle start ");
+
+ pGC->ops->PolyRectangle(dst, pGC, nRects, pRects);
+
+ if (nRects > 0) {
+ BoxRec box;
+ int offset1, offset2, offset3;
+
+ offset2 = pGC->lineWidth;
+ if(!offset2) offset2 = 1;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+
+ while(nRects--) {
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x + pRects->width - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + pRects->height - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ pRects++;
+ }
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly rectangle end\n");
+}
+
+
+/* changed area is box around each arc (assumes all arcs are 360 degrees) */
+static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("poly arc start ");
+
+ pGC->ops->PolyArc(dst, pGC, narcs, parcs);
+
+ if (narcs > 0) {
+ int extra = pGC->lineWidth >> 1;
+ BoxRec box;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while(--narcs) {
+ parcs++;
+ if(box.x1 > parcs->x)
+ box.x1 = parcs->x;
+ if(box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if(box.y1 > parcs->y)
+ box.y1 = parcs->y;
+ if(box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly arc end\n");
+}
+
+
+/* changed area is box around each poly */
+static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("fill poly start ");
+
+ if (count <= 2) {
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int i = count;
+ BoxRec box;
+
+ box.x2 = box.x1 = ppt->x;
+ box.y2 = box.y1 = ppt->y;
+
+ if(mode != CoordModeOrigin) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while(--i) {
+ ppt++;
+ x += ppt->x;
+ y += ppt->y;
+ if(box.x1 > x)
+ box.x1 = x;
+ else if(box.x2 < x)
+ box.x2 = x;
+ if(box.y1 > y)
+ box.y1 = y;
+ else if(box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while(--i) {
+ ppt++;
+ if(box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ else if(box.x2 < ppt->x)
+ box.x2 = ppt->x;
+ if(box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if(box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill poly end\n");
+}
+
+/* changed area is the rects */
+static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
+ int nRectsInit, xRectangle *pRectsInit)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("fill rect start (win 0x%x)", dst);
+
+ if (nRectsInit <= 0) {
+ pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
+ } else {
+ BoxRec box;
+ xRectangle *pRects = pRectsInit;
+ int nRects = nRectsInit;
+
+ box.x1 = pRects->x;
+ box.x2 = box.x1 + pRects->width;
+ box.y1 = pRects->y;
+ box.y2 = box.y1 + pRects->height;
+
+ while(--nRects) {
+ pRects++;
+ if(box.x1 > pRects->x)
+ box.x1 = pRects->x;
+ if(box.x2 < (pRects->x + pRects->width))
+ box.x2 = pRects->x + pRects->width;
+ if(box.y1 > pRects->y)
+ box.y1 = pRects->y;
+ if(box.y2 < (pRects->y + pRects->height))
+ box.y2 = pRects->y + pRects->height;
+ }
+
+ /* cfb messes with the pRectsInit so we have to do our
+ calculations first */
+
+ pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill rect end\n");
+}
+
+
+/* changed area is box around each arc (assuming arcs are all 360 degrees) */
+static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
+ int narcs, xArc *parcs)
+{
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("fill arc start ");
+
+ pGC->ops->PolyFillArc(dst, pGC, narcs, parcs);
+
+ if (narcs > 0) {
+ BoxRec box;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while(--narcs) {
+ parcs++;
+ if(box.x1 > parcs->x)
+ box.x1 = parcs->x;
+ if(box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if(box.y1 > parcs->y)
+ box.y1 = parcs->y;
+ if(box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill arc end");
+}
+
+
+static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 start ");
+
+ pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 end\n");
+}
+
+static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ int width; // the result, sorta
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polytext8 start ");
+
+ width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if(width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext8 end\n");
+ return (width + x);
+}
+
+static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 start ");
+
+ pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 end\n");
+}
+
+static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ int width; // the result, sorta
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polytext16 start ");
+
+ width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if (width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext16 end\n");
+ return width + x;
+}
+
+static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer unused)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imageglyph start ");
+
+ pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyph, ppci, unused);
+
+ if (nglyph > 0) {
+ int top, bot, width = 0;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ box.x1 = ppci[0]->metrics.leftSideBearing;
+ if(box.x1 > 0) box.x1 = 0;
+ box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
+ ppci[nglyph - 1]->metrics.characterWidth;
+ if(box.x2 < 0) box.x2 = 0;
+
+ box.x2 += dst->x + x;
+ box.x1 += dst->x + x;
+
+ while(nglyph--) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0)
+ box.x2 += width;
+ else
+ box.x1 += width;
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imageglyph end\n");
+}
+
+static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polyglyph start ");
+
+ pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ if (nglyph > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing;
+ box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
+
+ if(nglyph > 1) {
+ int width = 0;
+
+ while(--nglyph) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polyglyph end\n");
+}
+
+
+/* changed area is in dest */
+static void
+RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
+ int dx, int dy, int xOrg, int yOrg)
+{
+ BoxRec box;
+ GCOP_UNWRAP(pGC);
+
+ pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg);
+
+ box.x1 = xOrg + dst->x;
+ box.x2 = box.x1 + dx;
+ box.y1 = yOrg + dst->y;
+ box.y2 = box.y1 + dy;
+
+ TRIM_BOX(box, pGC);
+ if(BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("push pixels end\n");
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessScreen.c b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessScreen.c
new file mode 100644
index 000000000..c864e118a
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessScreen.c
@@ -0,0 +1,426 @@
+/*
+ * Screen routines for Mac OS X rootless X server
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ *
+ * February 2001 Created
+ * March 3, 2001 Restructured as generic rootless mode
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessScreen.c,v 1.2 2002/10/16 21:13:33 dawes Exp $ */
+
+
+#include "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "mivalidate.h"
+#include "picturestr.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rootlessCommon.h"
+#include "rootlessWindow.h"
+
+extern int
+rootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, VTKind kind);
+extern Bool
+RootlessCreateGC(GCPtr pGC);
+
+// Initialize globals
+int rootlessGCPrivateIndex = -1;
+int rootlessScreenPrivateIndex = -1;
+int rootlessWindowPrivateIndex = -1;
+
+
+static Bool
+RootlessCloseScreen(int i, ScreenPtr pScreen)
+{
+ RootlessScreenRec *s;
+
+ s = SCREENREC(pScreen);
+
+ // fixme unwrap everything that was wrapped?
+ pScreen->CloseScreen = s->CloseScreen;
+
+ xfree(s);
+ return pScreen->CloseScreen(i, pScreen);
+}
+
+
+static void
+RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
+ unsigned int format, unsigned long planeMask, char *pdstLine)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ SCREEN_UNWRAP(pScreen, GetImage);
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ /* Many apps use GetImage to sync with the visible frame buffer */
+ // fixme entire screen or just window or all screens?
+ RootlessRedisplayScreen(pScreen);
+ }
+
+ pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
+
+ SCREEN_WRAP(pScreen, GetImage);
+}
+
+
+#ifdef RENDER
+
+static void
+RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ WindowPtr dstWin;
+
+ dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pDst->pDrawable : NULL;
+
+ // SCREEN_UNWRAP(ps, Composite);
+ ps->Composite = SCREENREC(pScreen)->Composite;
+
+ ps->Composite(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+
+ if (dstWin && IsFramedWindow(dstWin)) {
+ RootlessDamageRect(dstWin, xDst, yDst, width, height);
+ }
+
+ ps->Composite = RootlessComposite;
+ // SCREEN_WRAP(ps, Composite);
+}
+
+
+static void
+RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int nlist, GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ int x, y;
+ int n;
+ GlyphPtr glyph;
+ WindowPtr dstWin;
+
+ dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
+ (WindowPtr)pDst->pDrawable : NULL;
+
+ //SCREEN_UNWRAP(ps, Glyphs);
+ ps->Glyphs = SCREENREC(pScreen)->Glyphs;
+ ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+ ps->Glyphs = RootlessGlyphs;
+ //SCREEN_WRAP(ps, Glyphs);
+
+ if (dstWin && IsFramedWindow(dstWin)) {
+ x = xSrc;
+ y = ySrc;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ glyph = *glyphs++;
+ RootlessDamageRect(dstWin,
+ x - glyph->info.x, y - glyph->info.y,
+ glyph->info.width, glyph->info.height);
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+ }
+}
+
+#endif // RENDER
+
+
+// RootlessValidateTree
+// ValidateTree is modified in two ways:
+// * top-level windows don't clip each other
+// * windows aren't clipped against root.
+// These only matter when validating from the root.
+static int
+RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
+{
+ int result;
+ RegionRec saveRoot;
+ ScreenPtr pScreen = pParent->drawable.pScreen;
+
+ SCREEN_UNWRAP(pScreen, ValidateTree);
+ RL_DEBUG_MSG("VALIDATETREE start ");
+
+ // Use our custom version to validate from root
+ if (IsRoot(pParent)) {
+ RL_DEBUG_MSG("custom ");
+ result = rootlessMiValidateTree(pParent, pChild, kind);
+ } else {
+ HUGE_ROOT(pParent);
+ result = pScreen->ValidateTree(pParent, pChild, kind);
+ NORMAL_ROOT(pParent);
+ }
+
+ SCREEN_WRAP(pScreen, ValidateTree);
+ RL_DEBUG_MSG("VALIDATETREE end\n");
+
+ return result;
+}
+
+
+// RootlessMarkOverlappedWindows
+// MarkOverlappedWindows is modified to ignore overlapping
+// top-level windows.
+static Bool
+RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
+ WindowPtr *ppLayerWin)
+{
+ RegionRec saveRoot;
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
+ RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
+
+ HUGE_ROOT(pWin);
+ if (IsRoot(pWin)) {
+ // root - mark nothing
+ RL_DEBUG_MSG("is root not marking ");
+ result = FALSE;
+ }
+ else if (! IsTopLevel(pWin)) {
+ // not top-level window - mark normally
+ result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
+ }
+ else {
+ //top-level window - mark children ONLY - NO overlaps with sibs (?)
+ // This code copied from miMarkOverlappedWindows()
+
+ register WindowPtr pChild;
+ Bool anyMarked = FALSE;
+ void (* MarkWindow)() = pScreen->MarkWindow;
+
+ RL_DEBUG_MSG("is top level! ");
+ /* single layered systems are easy */
+ if (ppLayerWin) *ppLayerWin = pWin;
+
+ if (pWin == pFirst) {
+ /* Blindly mark pWin and all of its inferiors. This is a slight
+ * overkill if there are mapped windows that outside pWin's border,
+ * but it's better than wasting time on RectIn checks.
+ */
+ pChild = pWin;
+ while (1) {
+ if (pChild->viewable) {
+ if (REGION_BROKEN (pScreen, &pChild->winSize))
+ SetWinSize (pChild);
+ if (REGION_BROKEN (pScreen, &pChild->borderSize))
+ SetBorderSize (pChild);
+ (* MarkWindow)(pChild);
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pWin))
+ pChild = pChild->parent;
+ if (pChild == pWin)
+ break;
+ pChild = pChild->nextSib;
+ }
+ anyMarked = TRUE;
+ pFirst = pFirst->nextSib;
+ }
+ if (anyMarked)
+ (* MarkWindow)(pWin->parent);
+ result = anyMarked;
+ }
+ NORMAL_ROOT(pWin);
+ SCREEN_WRAP(pScreen, MarkOverlappedWindows);
+ RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
+ return result;
+}
+
+
+static void
+RootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ int oldBackgroundState = 0;
+ PixUnion oldBackground;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ SCREEN_UNWRAP(pScreen, PaintWindowBackground);
+ RL_DEBUG_MSG("paintwindowbackground start (win 0x%x) ", pWin);
+ if (IsFramedWindow(pWin)) {
+ if (IsRoot(pWin)) {
+ // set root background to magic transparent color
+ oldBackgroundState = pWin->backgroundState;
+ oldBackground = pWin->background;
+ pWin->backgroundState = BackgroundPixel;
+ pWin->background.pixel = 0x00fffffe;
+ }
+ }
+
+ pScreen->PaintWindowBackground(pWin, pRegion, what);
+
+ if (IsFramedWindow(pWin)) {
+ RootlessDamageRegion(pWin, pRegion);
+ if (IsRoot(pWin)) {
+ pWin->backgroundState = oldBackgroundState;
+ pWin->background = oldBackground;
+ }
+ }
+ SCREEN_WRAP(pScreen, PaintWindowBackground);
+ RL_DEBUG_MSG("paintwindowbackground end\n");
+}
+
+
+static void
+RootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder);
+ RL_DEBUG_MSG("paintwindowborder start (win 0x%x) ", pWin);
+ pWin->drawable.pScreen->PaintWindowBorder(pWin, pRegion, what);
+ if (IsFramedWindow(pWin)) {
+ RootlessDamageRegion(pWin, pRegion);
+ }
+ SCREEN_WRAP(pWin->drawable.pScreen, PaintWindowBorder);
+ RL_DEBUG_MSG("paintwindowborder end\n");
+}
+
+
+// Flush drawing before blocking on select().
+static void
+RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask)
+{
+ RootlessRedisplayScreen((ScreenPtr) pbdata);
+}
+
+
+static void
+RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask)
+{
+ // nothing here
+}
+
+
+static Bool
+RootlessAllocatePrivates(ScreenPtr pScreen)
+{
+ RootlessScreenRec *s;
+ static unsigned long rootlessGeneration = 0;
+
+ if (rootlessGeneration != serverGeneration) {
+ rootlessScreenPrivateIndex = AllocateScreenPrivateIndex();
+ if (rootlessScreenPrivateIndex == -1) return FALSE;
+ rootlessGCPrivateIndex = AllocateGCPrivateIndex();
+ if (rootlessGCPrivateIndex == -1) return FALSE;
+ rootlessWindowPrivateIndex = AllocateWindowPrivateIndex();
+ if (rootlessWindowPrivateIndex == -1) return FALSE;
+ rootlessGeneration = serverGeneration;
+ }
+
+ // no allocation needed for screen privates
+ if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex,
+ sizeof(RootlessGCRec)))
+ return FALSE;
+ if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0))
+ return FALSE;
+
+ s = xalloc(sizeof(RootlessScreenRec));
+ if (! s) return FALSE;
+ SCREENREC(pScreen) = s;
+
+ return TRUE;
+}
+
+
+static void
+RootlessWrap(ScreenPtr pScreen)
+{
+ RootlessScreenRec *s = (RootlessScreenRec*)
+ pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
+
+#define WRAP(a) \
+ if (pScreen->a) { \
+ s->a = pScreen->a; \
+ } else { \
+ RL_DEBUG_MSG("null screen fn " #a "\n"); \
+ s->a = NULL; \
+ } \
+ pScreen->a = Rootless##a
+
+ WRAP(CloseScreen);
+ WRAP(CreateGC);
+ WRAP(PaintWindowBackground);
+ WRAP(PaintWindowBorder);
+ WRAP(CopyWindow);
+ WRAP(GetImage);
+ WRAP(CreateWindow);
+ WRAP(DestroyWindow);
+ WRAP(RealizeWindow);
+ WRAP(UnrealizeWindow);
+ WRAP(MoveWindow);
+ WRAP(PositionWindow);
+ WRAP(ResizeWindow);
+ WRAP(RestackWindow);
+ WRAP(ChangeBorderWidth);
+ WRAP(MarkOverlappedWindows);
+ WRAP(ValidateTree);
+ WRAP(ChangeWindowAttributes);
+
+#ifdef SHAPE
+ WRAP(SetShape);
+#endif
+
+#ifdef RENDER
+ {
+ // Composite and Glyphs don't use normal screen wrapping
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ s->Composite = ps->Composite;
+ ps->Composite = RootlessComposite;
+ s->Glyphs = ps->Glyphs;
+ ps->Glyphs = RootlessGlyphs;
+ }
+#endif
+
+ // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
+ // WRAP(RestoreAreas); fixme put this back?
+
+#undef WRAP
+}
+
+
+/*
+ * RootlessInit
+ * Rootless wraps lots of stuff and needs a bunch of devPrivates.
+ */
+Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcs *procs)
+{
+ RootlessScreenRec *s;
+
+ if (! RootlessAllocatePrivates(pScreen)) return FALSE;
+ s = (RootlessScreenRec*)
+ pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
+
+ s->pScreen = pScreen;
+ s->frameProcs = *procs;
+
+ RootlessWrap(pScreen);
+
+ if (!RegisterBlockAndWakeupHandlers (RootlessBlockHandler,
+ RootlessWakeupHandler,
+ (pointer) pScreen))
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessValTree.c b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessValTree.c
new file mode 100644
index 000000000..abcb152c7
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessValTree.c
@@ -0,0 +1,744 @@
+/*
+ * Calculate window clip lists for rootless mode
+ *
+ * This file is very closely based on mivaltree.c.
+ */
+ /* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessValTree.c,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+/*
+ * mivaltree.c --
+ * Functions for recalculating window clip lists. Main function
+ * is miValidateTree.
+ *
+
+Copyright 1987, 1988, 1989, 1998 The Open Group
+
+All Rights Reserved.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+ *
+ * Copyright 1987, 1988, 1989 by
+ * Digital Equipment Corporation, Maynard, Massachusetts,
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Digital not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ ******************************************************************/
+
+/* The panoramix components contained the following notice */
+/****************************************************************
+* *
+* Copyright (c) Digital Equipment Corporation, 1991, 1997 *
+* *
+* All Rights Reserved. Unpublished rights reserved under *
+* the copyright laws of the United States. *
+* *
+* The software contained on this media is proprietary to *
+* and embodies the confidential technology of Digital *
+* Equipment Corporation. Possession, use, duplication or *
+* dissemination of the software and media is authorized only *
+* pursuant to a valid written license from Digital Equipment *
+* Corporation. *
+* *
+* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure *
+* by the U.S. Government is subject to restrictions as set *
+* forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, *
+* or in FAR 52.227-19, as applicable. *
+* *
+*****************************************************************/
+
+ /*
+ * Aug '86: Susan Angebranndt -- original code
+ * July '87: Adam de Boor -- substantially modified and commented
+ * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
+ * In particular, much improved code for window mapping and
+ * circulating.
+ * Bob Scheifler -- avoid miComputeClips for unmapped windows,
+ * valdata changes
+ */
+#include "X.h"
+#include "scrnintstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "regionstr.h"
+#include "mivalidate.h"
+
+#include "globals.h"
+
+#ifdef SHAPE
+/*
+ * Compute the visibility of a shaped window
+ */
+int
+rootlessShapedWindowIn (pScreen, universe, bounding, rect, x, y)
+ ScreenPtr pScreen;
+ RegionPtr universe, bounding;
+ BoxPtr rect;
+ register int x, y;
+{
+ BoxRec box;
+ register BoxPtr boundBox;
+ int nbox;
+ Bool someIn, someOut;
+ register int t, x1, y1, x2, y2;
+
+ nbox = REGION_NUM_RECTS (bounding);
+ boundBox = REGION_RECTS (bounding);
+ someIn = someOut = FALSE;
+ x1 = rect->x1;
+ y1 = rect->y1;
+ x2 = rect->x2;
+ y2 = rect->y2;
+ while (nbox--)
+ {
+ if ((t = boundBox->x1 + x) < x1)
+ t = x1;
+ box.x1 = t;
+ if ((t = boundBox->y1 + y) < y1)
+ t = y1;
+ box.y1 = t;
+ if ((t = boundBox->x2 + x) > x2)
+ t = x2;
+ box.x2 = t;
+ if ((t = boundBox->y2 + y) > y2)
+ t = y2;
+ box.y2 = t;
+ if (box.x1 > box.x2)
+ box.x2 = box.x1;
+ if (box.y1 > box.y2)
+ box.y2 = box.y1;
+ switch (RECT_IN_REGION(pScreen, universe, &box))
+ {
+ case rgnIN:
+ if (someOut)
+ return rgnPART;
+ someIn = TRUE;
+ break;
+ case rgnOUT:
+ if (someIn)
+ return rgnPART;
+ someOut = TRUE;
+ break;
+ default:
+ return rgnPART;
+ }
+ boundBox++;
+ }
+ if (someIn)
+ return rgnIN;
+ return rgnOUT;
+}
+#endif
+
+#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
+ HasBorder(w) && \
+ (w)->backgroundState == ParentRelative)
+
+
+/*
+ *-----------------------------------------------------------------------
+ * miComputeClips --
+ * Recompute the clipList, borderClip, exposed and borderExposed
+ * regions for pParent and its children. Only viewable windows are
+ * taken into account.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * clipList, borderClip, exposed and borderExposed are altered.
+ * A VisibilityNotify event may be generated on the parent window.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+rootlessComputeClips (pParent, pScreen, universe, kind, exposed)
+ register WindowPtr pParent;
+ register ScreenPtr pScreen;
+ register RegionPtr universe;
+ VTKind kind;
+ RegionPtr exposed; /* for intermediate calculations */
+{
+ int dx,
+ dy;
+ RegionRec childUniverse;
+ register WindowPtr pChild;
+ int oldVis, newVis;
+ BoxRec borderSize;
+ RegionRec childUnion;
+ Bool overlap;
+ RegionPtr borderVisible;
+ Bool resized;
+ /*
+ * Figure out the new visibility of this window.
+ * The extent of the universe should be the same as the extent of
+ * the borderSize region. If the window is unobscured, this rectangle
+ * will be completely inside the universe (the universe will cover it
+ * completely). If the window is completely obscured, none of the
+ * universe will cover the rectangle.
+ */
+ borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
+ borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
+ dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
+ if (dx > 32767)
+ dx = 32767;
+ borderSize.x2 = dx;
+ dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
+ if (dy > 32767)
+ dy = 32767;
+ borderSize.y2 = dy;
+
+ oldVis = pParent->visibility;
+ switch (RECT_IN_REGION( pScreen, universe, &borderSize))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnPART:
+ newVis = VisibilityPartiallyObscured;
+#ifdef SHAPE
+ {
+ RegionPtr pBounding;
+
+ if ((pBounding = wBoundingShape (pParent)))
+ {
+ switch (rootlessShapedWindowIn (pScreen, universe,
+ pBounding, &borderSize,
+ pParent->drawable.x,
+ pParent->drawable.y))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnOUT:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+ }
+ }
+#endif
+ break;
+ default:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+
+ pParent->visibility = newVis;
+ if (oldVis != newVis &&
+ ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
+ SendVisibilityNotify(pParent);
+
+ dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
+ dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
+
+ /*
+ * avoid computations when dealing with simple operations
+ */
+
+ switch (kind) {
+ case VTMap:
+ case VTStack:
+ case VTUnmap:
+ break;
+ case VTMove:
+ if ((oldVis == newVis) &&
+ ((oldVis == VisibilityFullyObscured) ||
+ (oldVis == VisibilityUnobscured)))
+ {
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ if (pChild->visibility != VisibilityFullyObscured)
+ {
+ REGION_TRANSLATE( pScreen, &pChild->borderClip,
+ dx, dy);
+ REGION_TRANSLATE( pScreen, &pChild->clipList,
+ dx, dy);
+ pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pChild, dx, dy);
+
+ }
+ if (pChild->valdata)
+ {
+ REGION_INIT(pScreen,
+ &pChild->valdata->after.borderExposed,
+ NullBox, 0);
+ if (HasParentRelativeBorder(pChild))
+ {
+ REGION_SUBTRACT(pScreen,
+ &pChild->valdata->after.borderExposed,
+ &pChild->borderClip,
+ &pChild->winSize);
+ }
+ REGION_INIT( pScreen, &pChild->valdata->after.exposed,
+ NullBox, 0);
+ }
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+ return;
+ }
+ /* fall through */
+ default:
+ /*
+ * To calculate exposures correctly, we have to translate the old
+ * borderClip and clipList regions to the window's new location so there
+ * is a correspondence between pieces of the new and old clipping regions.
+ */
+ if (dx || dy)
+ {
+ /*
+ * We translate the old clipList because that will be exposed or copied
+ * if gravity is right.
+ */
+ REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
+ REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
+ }
+ break;
+ case VTBroken:
+ REGION_EMPTY (pScreen, &pParent->borderClip);
+ REGION_EMPTY (pScreen, &pParent->clipList);
+ break;
+ }
+
+ borderVisible = pParent->valdata->before.borderVisible;
+ resized = pParent->valdata->before.resized;
+ REGION_INIT( pScreen, &pParent->valdata->after.borderExposed, NullBox, 0);
+ REGION_INIT( pScreen, &pParent->valdata->after.exposed, NullBox, 0);
+
+ /*
+ * Since the borderClip must not be clipped by the children, we do
+ * the border exposure first...
+ *
+ * 'universe' is the window's borderClip. To figure the exposures, remove
+ * the area that used to be exposed from the new.
+ * This leaves a region of pieces that weren't exposed before.
+ */
+
+ if (HasBorder (pParent))
+ {
+ if (borderVisible)
+ {
+ /*
+ * when the border changes shape, the old visible portions
+ * of the border will be saved by DIX in borderVisible --
+ * use that region and destroy it
+ */
+ REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
+ REGION_DESTROY( pScreen, borderVisible);
+ }
+ else
+ {
+ REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
+ }
+ if (HasParentRelativeBorder(pParent) && (dx || dy)) {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
+ universe,
+ &pParent->winSize);
+ } else {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
+ exposed, &pParent->winSize);
+ }
+
+ REGION_COPY( pScreen, &pParent->borderClip, universe);
+
+ /*
+ * To get the right clipList for the parent, and to make doubly sure
+ * that no child overlaps the parent's border, we remove the parent's
+ * border from the universe before proceeding.
+ */
+
+ REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
+ }
+ else
+ REGION_COPY( pScreen, &pParent->borderClip, universe);
+
+ if ((pChild = pParent->firstChild) && pParent->mapped)
+ {
+ REGION_INIT(pScreen, &childUniverse, NullBox, 0);
+ REGION_INIT(pScreen, &childUnion, NullBox, 0);
+ if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
+ ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
+ (pChild->drawable.x < pParent->lastChild->drawable.x)))
+ {
+ for (; pChild; pChild = pChild->nextSib)
+ {
+ if (pChild->viewable)
+ REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
+ }
+ }
+ else
+ {
+ for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
+ {
+ if (pChild->viewable)
+ REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
+ }
+ }
+ REGION_VALIDATE( pScreen, &childUnion, &overlap);
+
+ for (pChild = pParent->firstChild;
+ pChild;
+ pChild = pChild->nextSib)
+ {
+ if (pChild->viewable) {
+ /*
+ * If the child is viewable, we want to remove its extents
+ * from the current universe, but we only re-clip it if
+ * it's been marked.
+ */
+ if (pChild->valdata) {
+ /*
+ * Figure out the new universe from the child's
+ * perspective and recurse.
+ */
+ REGION_INTERSECT( pScreen, &childUniverse,
+ universe,
+ &pChild->borderSize);
+ rootlessComputeClips (pChild, pScreen, &childUniverse,
+ kind, exposed);
+ }
+ /*
+ * Once the child has been processed, we remove its extents
+ * from the current universe, thus denying its space to any
+ * other sibling.
+ */
+ if (overlap)
+ REGION_SUBTRACT( pScreen, universe, universe,
+ &pChild->borderSize);
+ }
+ }
+ if (!overlap)
+ REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
+ REGION_UNINIT( pScreen, &childUnion);
+ REGION_UNINIT( pScreen, &childUniverse);
+ } /* if any children */
+
+ /*
+ * 'universe' now contains the new clipList for the parent window.
+ *
+ * To figure the exposure of the window we subtract the old clip from the
+ * new, just as for the border.
+ */
+
+ if (oldVis == VisibilityFullyObscured ||
+ oldVis == VisibilityNotViewable)
+ {
+ REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
+ }
+ else if (newVis != VisibilityFullyObscured &&
+ newVis != VisibilityNotViewable)
+ {
+ REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
+ universe, &pParent->clipList);
+ }
+
+ /*
+ * One last thing: backing storage. We have to try to save what parts of
+ * the window are about to be obscured. We can just subtract the universe
+ * from the old clipList and get the areas that were in the old but aren't
+ * in the new and, hence, are about to be obscured.
+ */
+ if (pParent->backStorage && !resized)
+ {
+ REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe);
+ (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
+ }
+
+ /* HACK ALERT - copying contents of regions, instead of regions */
+ {
+ RegionRec tmp;
+
+ tmp = pParent->clipList;
+ pParent->clipList = *universe;
+ *universe = tmp;
+ }
+
+#ifdef NOTDEF
+ REGION_COPY( pScreen, &pParent->clipList, universe);
+#endif
+
+ pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pParent, dx, dy);
+}
+
+static void
+rootlessTreeObscured(pParent)
+ register WindowPtr pParent;
+{
+ register WindowPtr pChild;
+ register int oldVis;
+
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ oldVis = pChild->visibility;
+ if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
+ ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
+ SendVisibilityNotify(pChild);
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------
+ * miValidateTree --
+ * Recomputes the clip list for pParent and all its inferiors.
+ *
+ * Results:
+ * Always returns 1.
+ *
+ * Side Effects:
+ * The clipList, borderClip, exposed, and borderExposed regions for
+ * each marked window are altered.
+ *
+ * Notes:
+ * This routine assumes that all affected windows have been marked
+ * (valdata created) and their winSize and borderSize regions
+ * adjusted to correspond to their new positions. The borderClip and
+ * clipList regions should not have been touched.
+ *
+ * The top-most level is treated differently from all lower levels
+ * because pParent is unchanged. For the top level, we merge the
+ * regions taken up by the marked children back into the clipList
+ * for pParent, thus forming a region from which the marked children
+ * can claim their areas. For lower levels, where the old clipList
+ * and borderClip are invalid, we can't do this and have to do the
+ * extra operations done in miComputeClips, but this is much faster
+ * e.g. when only one child has moved...
+ *
+ *-----------------------------------------------------------------------
+ */
+/*
+ Quartz version: used for validate from root in rootless mode.
+ We need to make sure top-level windows don't clip each other,
+ and that top-level windows aren't clipped to the root window.
+*/
+/*ARGSUSED*/
+// fixme this is ugly
+// Xprint/ValTree.c doesn't work, but maybe that method can?
+int
+rootlessMiValidateTree (pRoot, pChild, kind)
+ WindowPtr pRoot; /* Parent to validate */
+ WindowPtr pChild; /* First child of pRoot that was
+ * affected */
+ VTKind kind; /* What kind of configuration caused call */
+{
+ RegionRec totalClip; /* Total clipping region available to
+ * the marked children. pRoot's clipList
+ * merged with the borderClips of all
+ * the marked children. */
+ RegionRec childClip; /* The new borderClip for the current
+ * child */
+ RegionRec childUnion; /* the space covered by borderSize for
+ * all marked children */
+ RegionRec exposed; /* For intermediate calculations */
+ register ScreenPtr pScreen;
+ register WindowPtr pWin;
+ Bool overlap;
+ int viewvals;
+ Bool forward;
+
+ pScreen = pRoot->drawable.pScreen;
+ if (pChild == NullWindow)
+ pChild = pRoot->firstChild;
+
+ REGION_INIT(pScreen, &childClip, NullBox, 0);
+ REGION_INIT(pScreen, &exposed, NullBox, 0);
+
+ /*
+ * compute the area of the parent window occupied
+ * by the marked children + the parent itself. This
+ * is the area which can be divied up among the marked
+ * children in their new configuration.
+ */
+ REGION_INIT(pScreen, &totalClip, NullBox, 0);
+ viewvals = 0;
+ if (REGION_BROKEN (pScreen, &pRoot->clipList) &&
+ !REGION_BROKEN (pScreen, &pRoot->borderClip))
+ {
+ kind = VTBroken;
+ /*
+ * When rebuilding clip lists after out of memory,
+ * assume everything is busted.
+ */
+ forward = TRUE;
+ REGION_COPY (pScreen, &totalClip, &pRoot->borderClip);
+ REGION_INTERSECT (pScreen, &totalClip, &totalClip, &pRoot->winSize);
+
+ for (pWin = pRoot->firstChild; pWin != pChild; pWin = pWin->nextSib)
+ {
+ if (pWin->viewable)
+ REGION_SUBTRACT (pScreen, &totalClip, &totalClip, &pWin->borderSize);
+ }
+ for (pWin = pChild; pWin; pWin = pWin->nextSib)
+ if (pWin->valdata && pWin->viewable)
+ viewvals++;
+
+ REGION_EMPTY (pScreen, &pRoot->clipList);
+ ErrorF("ValidateTree: BUSTED!\n");
+ }
+ else
+ {
+ if ((pChild->drawable.y < pRoot->lastChild->drawable.y) ||
+ ((pChild->drawable.y == pRoot->lastChild->drawable.y) &&
+ (pChild->drawable.x < pRoot->lastChild->drawable.x)))
+ {
+ forward = TRUE;
+ for (pWin = pChild; pWin; pWin = pWin->nextSib)
+ {
+ if (pWin->valdata)
+ {
+ REGION_APPEND( pScreen, &totalClip, &pWin->borderClip);
+ if (pWin->viewable)
+ viewvals++;
+ }
+ }
+ }
+ else
+ {
+ forward = FALSE;
+ pWin = pRoot->lastChild;
+ while (1)
+ {
+ if (pWin->valdata)
+ {
+ REGION_APPEND( pScreen, &totalClip, &pWin->borderClip);
+ if (pWin->viewable)
+ viewvals++;
+ }
+ if (pWin == pChild)
+ break;
+ pWin = pWin->prevSib;
+ }
+ }
+ REGION_VALIDATE( pScreen, &totalClip, &overlap);
+ }
+
+
+ // calculate childUnion so we can subtract it from totalClip later
+ REGION_INIT(pScreen, &childUnion, NullBox, 0);
+ if (kind != VTStack) {
+ if (forward)
+ {
+ for (pWin = pChild; pWin; pWin = pWin->nextSib)
+ if (pWin->valdata && pWin->viewable)
+ REGION_APPEND( pScreen, &childUnion,
+ &pWin->borderSize);
+ }
+ else
+ {
+ pWin = pRoot->lastChild;
+ while (1)
+ {
+ if (pWin->valdata && pWin->viewable)
+ REGION_APPEND( pScreen, &childUnion,
+ &pWin->borderSize);
+ if (pWin == pChild)
+ break;
+ pWin = pWin->prevSib;
+ }
+ }
+ REGION_VALIDATE(pScreen, &childUnion, &overlap);
+ }
+
+
+ /*
+ * Now go through the children of the root and figure their new
+ * borderClips from the totalClip, passing that off to miComputeClips
+ * to handle recursively. Once that's done, we remove the child
+ * from the totalClip to clip any siblings below it.
+ */
+
+ for (pWin = pChild;
+ pWin != NullWindow;
+ pWin = pWin->nextSib)
+ {
+ if (pWin->viewable) {
+ if (pWin->valdata) {
+ REGION_COPY( pScreen, &childClip, &pWin->borderSize);
+ rootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
+ } else if (pWin->visibility == VisibilityNotViewable) {
+ rootlessTreeObscured(pWin);
+ }
+ } else {
+ if (pWin->valdata) {
+ REGION_EMPTY( pScreen, &pWin->clipList);
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pWin, 0, 0);
+ REGION_EMPTY( pScreen, &pWin->borderClip);
+ pWin->valdata = (ValidatePtr)NULL;
+ }
+ }
+ }
+
+ REGION_UNINIT( pScreen, &childClip);
+
+ // REGION_SUBTRACT(pScreen, &totalClip, &totalClip, &childUnion);
+ REGION_UNINIT(pScreen, &childUnion);
+
+ REGION_INIT( pScreen, &pRoot->valdata->after.exposed, NullBox, 0);
+ REGION_INIT( pScreen, &pRoot->valdata->after.borderExposed, NullBox, 0);
+
+
+ REGION_UNINIT( pScreen, &totalClip);
+ REGION_UNINIT( pScreen, &exposed);
+ //if (pScreen->ClipNotify)
+ //(*pScreen->ClipNotify) (pRoot, 0, 0);
+ return (1);
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.c b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.c
new file mode 100644
index 000000000..15bdc4563
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.c
@@ -0,0 +1,674 @@
+/*
+ * Rootless window management
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.c,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#include "rootlessCommon.h"
+#include "rootlessWindow.h"
+
+#include "fb.h"
+
+
+// RootlessCreateWindow
+// For now, don't create a frame until the window is realized.
+// Do reset the window size so it's not clipped by the root window.
+Bool
+RootlessCreateWindow(WindowPtr pWin)
+{
+ Bool result;
+ RegionRec saveRoot;
+
+ WINREC(pWin) = NULL;
+ SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
+ if (!IsRoot(pWin)) {
+ // win/border size set by DIX, not by wrapped CreateWindow, so
+ // correct it here.
+ // Don't HUGE_ROOT when pWin is the root!
+ HUGE_ROOT(pWin);
+ SetWinSize(pWin);
+ SetBorderSize(pWin);
+ }
+ result = pWin->drawable.pScreen->CreateWindow(pWin);
+ if (pWin->parent) {
+ NORMAL_ROOT(pWin);
+ }
+ SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
+ return result;
+}
+
+
+// RootlessDestroyWindow
+// For now, all window destruction takes place in UnrealizeWindow
+Bool
+RootlessDestroyWindow(WindowPtr pWin)
+{
+ Bool result;
+
+ SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
+ result = pWin->drawable.pScreen->DestroyWindow(pWin);
+ SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
+ return result;
+}
+
+
+#ifdef SHAPE
+
+// RootlessSetShape
+// Shape is usually set before the window is mapped, but (for now) we
+// don't keep track of frames before they're mapped. So we just record
+// that the shape needs to updated later.
+void
+RootlessSetShape(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RootlessDamageShape(pWin);
+ SCREEN_UNWRAP(pScreen, SetShape);
+ pScreen->SetShape(pWin);
+ SCREEN_WRAP(pScreen, SetShape);
+}
+
+#endif // SHAPE
+
+
+// Disallow ParentRelative background on top-level windows
+// because the root window doesn't really have the right background
+// and cfb will try to draw on the root instead of on the window.
+// fixme what about fb?
+// fixme implement ParentRelative with real transparency?
+// ParentRelative prevention is also in RealizeWindow()
+Bool
+RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("change window attributes start ");
+
+ SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
+ result = pScreen->ChangeWindowAttributes(pWin, vmask);
+ SCREEN_WRAP(pScreen, ChangeWindowAttributes);
+
+ if (WINREC(pWin)) {
+ // disallow ParentRelative background state
+ if (pWin->backgroundState == ParentRelative) {
+ XID pixel = 0;
+ ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
+ }
+ }
+
+ RL_DEBUG_MSG("change window attributes end\n");
+ return result;
+}
+
+
+// Update the frame position now.
+// (x, y) are *inside* position!
+// After this, mi and fb are expecting the pixmap to be at the new location.
+Bool
+RootlessPositionWindow(WindowPtr pWin, int x, int y)
+{
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ Bool result;
+
+ RL_DEBUG_MSG("positionwindow start\n");
+ if (winRec) {
+ winRec->frame.x = x - pWin->borderWidth;
+ winRec->frame.y = y - pWin->borderWidth;
+ }
+
+ UpdatePixmap(pWin);
+
+ SCREEN_UNWRAP(pScreen, PositionWindow);
+ result = pScreen->PositionWindow(pWin, x, y);
+ SCREEN_WRAP(pScreen, PositionWindow);
+
+ RL_DEBUG_MSG("positionwindow end\n");
+ return result;
+}
+
+
+// RootlessRealizeWindow
+// The frame is created here and not in CreateWindow.
+// fixme change this? probably not - would be faster, but eat more memory
+Bool
+RootlessRealizeWindow(WindowPtr pWin)
+{
+ Bool result = FALSE;
+ RegionRec saveRoot;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("realizewindow start ");
+
+ if (IsTopLevel(pWin) || IsRoot(pWin)) {
+ DrawablePtr d = &pWin->drawable;
+ RootlessWindowRec *winRec = xalloc(sizeof(RootlessWindowRec));
+
+ if (! winRec) goto windowcreatebad;
+
+ winRec->frame.isRoot = (pWin == WindowTable[pScreen->myNum]);
+ winRec->frame.x = d->x - pWin->borderWidth;
+ winRec->frame.y = d->y - pWin->borderWidth;
+ winRec->frame.w = d->width + 2*pWin->borderWidth;
+ winRec->frame.h = d->height + 2*pWin->borderWidth;
+ winRec->frame.win = pWin;
+ winRec->frame.devPrivate = NULL;
+
+ REGION_INIT(pScreen, &winRec->damage, NullBox, 0);
+ winRec->borderWidth = pWin->borderWidth;
+
+ winRec->pixmap = NULL;
+ // UpdatePixmap() called below
+
+ WINREC(pWin) = winRec;
+
+ RL_DEBUG_MSG("creating frame ");
+ CallFrameProc(pScreen, CreateFrame,
+ (pScreen, &WINREC(pWin)->frame,
+ pWin->prevSib ? &WINREC(pWin->prevSib)->frame : NULL));
+
+ // fixme implement ParentRelative with transparency?
+ // need non-interfering fb first
+ // Disallow ParentRelative background state
+ // This might have been set before the window was mapped
+ if (pWin->backgroundState == ParentRelative) {
+ XID pixel = 0;
+ ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
+ }
+
+#ifdef SHAPE
+ // Shape is usually set before the window is mapped, but
+ // (for now) we don't keep track of frames before they're mapped.
+ winRec->shapeDamage = TRUE;
+#endif
+ }
+
+ UpdatePixmap(pWin);
+
+ if (!IsRoot(pWin)) HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, RealizeWindow);
+ result = pScreen->RealizeWindow(pWin);
+ SCREEN_WRAP(pScreen, RealizeWindow);
+ if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
+
+ RL_DEBUG_MSG("realizewindow end\n");
+ return result;
+
+windowcreatebad:
+ RL_DEBUG_MSG("window create bad! ");
+ RL_DEBUG_MSG("realizewindow end\n");
+ return NULL;
+}
+
+
+Bool
+RootlessUnrealizeWindow(WindowPtr pWin)
+{
+ Bool result;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("unrealizewindow start ");
+
+ if (IsTopLevel(pWin) || IsRoot(pWin)) {
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ RootlessRedisplay(pWin);
+ CallFrameProc(pScreen, DestroyFrame, (pScreen, &winRec->frame));
+
+ REGION_UNINIT(pScreen, &winRec->damage);
+
+ xfree(winRec);
+ WINREC(pWin) = NULL;
+ }
+
+ SCREEN_UNWRAP(pScreen, UnrealizeWindow);
+ result = pScreen->UnrealizeWindow(pWin);
+ SCREEN_WRAP(pScreen, UnrealizeWindow);
+ RL_DEBUG_MSG("unrealizewindow end\n");
+ return result;
+}
+
+
+void
+RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
+{
+ RegionRec saveRoot;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ RL_DEBUG_MSG("restackwindow start ");
+ if (winRec) RL_DEBUG_MSG("restack top level \n");
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, RestackWindow);
+ if (pScreen->RestackWindow) pScreen->RestackWindow(pWin, pOldNextSib);
+ SCREEN_WRAP(pScreen, RestackWindow);
+ NORMAL_ROOT(pWin);
+
+ if (winRec) {
+ // fixme simplify the following
+
+ WindowPtr oldNextW, newNextW, oldPrevW, newPrevW;
+ RootlessFramePtr oldNext, newNext, oldPrev, newPrev;
+
+ oldNextW = pOldNextSib;
+ while (oldNextW && ! WINREC(oldNextW)) oldNextW = oldNextW->nextSib;
+ oldNext = oldNextW ? &WINREC(oldNextW)->frame : NULL;
+
+ newNextW = pWin->nextSib;
+ while (newNextW && ! WINREC(newNextW)) newNextW = newNextW->nextSib;
+ newNext = newNextW ? &WINREC(newNextW)->frame : NULL;
+
+ oldPrevW= pOldNextSib ? pOldNextSib->prevSib : pWin->parent->lastChild;
+ while (oldPrevW && ! WINREC(oldPrevW)) oldPrevW = oldPrevW->prevSib;
+ oldPrev = oldPrevW ? &WINREC(oldPrevW)->frame : NULL;
+
+ newPrevW = pWin->prevSib;
+ while (newPrevW && ! WINREC(newPrevW)) newPrevW = newPrevW->prevSib;
+ newPrev = newPrevW ? &WINREC(newPrevW)->frame : NULL;
+
+ if (pWin->prevSib) {
+ WindowPtr w = pWin->prevSib;
+ while (w) {
+ RL_DEBUG_MSG("w 0x%x\n", w);
+ w = w->parent;
+ }
+ }
+
+ CallFrameProc(pScreen, RestackFrame,
+ (pScreen, &winRec->frame, oldPrev, newPrev));
+ }
+
+ RL_DEBUG_MSG("restackwindow end\n");
+}
+
+
+/*
+ * Specialized window copy procedures
+ */
+
+// Globals needed during window resize and move.
+static PixmapPtr gResizeDeathPix = NULL;
+static pointer gResizeDeathBits = NULL;
+static PixmapPtr gResizeCopyWindowSource = NULL;
+static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
+
+// CopyWindow() that doesn't do anything.
+// For MoveWindow() of top-level windows.
+static void
+RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ // some code expects the region to be translated
+ int dx = ptOldOrg.x - pWin->drawable.x;
+ int dy = ptOldOrg.y - pWin->drawable.y;
+ RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
+
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+}
+
+
+// CopyWindow used during ResizeWindow for gravity moves.
+// Cloned from fbCopyWindow
+// The original always draws on the root pixmap (which we don't have).
+// Instead, draw on the parent window's pixmap.
+// Resize version: the old location's pixels are in gResizeCopyWindowSource
+static void
+RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ SCREEN_UNWRAP(pScreen, CopyWindow);
+ RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
+
+ {
+ RegionRec rgnDst;
+ int dx, dy;
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
+ REGION_INIT (pScreen, &rgnDst, NullBox, 0);
+ REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ fbCopyRegion (&gResizeCopyWindowSource->drawable,
+ &pScreen->GetWindowPixmap(pWin)->drawable,
+ 0,
+ &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
+
+ // don't update - resize will update everything
+ // fixme DO update?
+ REGION_UNINIT(pScreen, &rgnDst);
+ fbValidateDrawable (&pWin->drawable);
+ }
+
+ SCREEN_WRAP(pScreen, CopyWindow);
+ RL_DEBUG_MSG("resizecopywindowFB end\n");
+}
+
+
+/* Update *new* location of window. Old location is redrawn with
+ * PaintWindowBackground/Border.
+ * Cloned from fbCopyWindow
+ * The original always draws on the root pixmap (which we don't have).
+ * Instead, draw on the parent window's pixmap.
+ */
+void
+RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ SCREEN_UNWRAP(pScreen, CopyWindow);
+ RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
+
+ {
+ RegionRec rgnDst;
+ int dx, dy;
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT(pScreen, &rgnDst, NullBox, 0);
+ REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+
+ fbCopyRegion ((DrawablePtr)pWin, (DrawablePtr)pWin,
+ 0,
+ &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
+
+ // prgnSrc has been translated to dst position
+ RootlessDamageRegion(pWin, prgnSrc);
+ REGION_UNINIT(pScreen, &rgnDst);
+ fbValidateDrawable (&pWin->drawable);
+ }
+
+ SCREEN_WRAP(pScreen, CopyWindow);
+ RL_DEBUG_MSG("copywindowFB end\n");
+}
+
+
+/*
+ * Window resize procedures
+ */
+
+// Prepare to resize a window.
+// The old window's pixels are saved and the implementation is told
+// to change the window size.
+// (x,y,w,h) is outer frame of window (outside border)
+static void
+StartFrameResize(WindowPtr pWin, Bool gravity,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH, unsigned int oldBW,
+ int newX, int newY,
+ unsigned int newW, unsigned int newH, unsigned int newBW)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW ");
+ RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d ",
+ oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+
+ RootlessRedisplay(pWin);
+
+ // Make a copy of the current pixmap and all its data.
+ // The original will go away when we ask the frame manager to
+ // allocate the new pixmap.
+
+ gResizeDeathBits = xalloc(winRec->frame.bytesPerRow * winRec->frame.h);
+ memcpy(gResizeDeathBits, winRec->frame.pixelData,
+ winRec->frame.bytesPerRow * winRec->frame.h);
+ gResizeDeathPix =
+ GetScratchPixmapHeader(pScreen, winRec->frame.w, winRec->frame.h,
+ winRec->frame.depth, winRec->frame.bitsPerPixel,
+ winRec->frame.bytesPerRow, gResizeDeathBits);
+ SetPixmapBaseToScreen(gResizeDeathPix, winRec->frame.x, winRec->frame.y);
+
+ winRec->frame.x = newX;
+ winRec->frame.y = newY;
+ winRec->frame.w = newW;
+ winRec->frame.h = newH;
+ winRec->borderWidth = newBW;
+
+ CallFrameProc(pScreen, StartResizeFrame,
+ (pScreen, &winRec->frame, oldX, oldY, oldW, oldH));
+ UpdatePixmap(pWin);
+
+ // Use custom CopyWindow when moving gravity bits around
+ // ResizeWindow assumes the old window contents are in the same
+ // pixmap, but here they're in deathPix instead.
+ if (gravity) {
+ gResizeCopyWindowSource = gResizeDeathPix;
+ gResizeOldCopyWindowProc = pScreen->CopyWindow;
+ pScreen->CopyWindow = RootlessResizeCopyWindow;
+ }
+
+ // Copy pixels in intersection from src to dst.
+ // ResizeWindow assumes these pixels are already present when
+ // making gravity adjustments.
+ // pWin currently has new-sized pixmap but is in old position
+ // fixme border width change!
+ {
+ RegionRec r;
+ DrawablePtr src = &gResizeDeathPix->drawable;
+ DrawablePtr dst = &pScreen->GetWindowPixmap(pWin)->drawable;
+ // These vars are needed because implicit unsigned->signed fails
+ int oldX2 = (int)(oldX + oldW), newX2 = (int)(newX + newW);
+ int oldY2 = (int)(oldY + oldH), newY2 = (int)(newY + newH);
+
+ r.data = NULL;
+ r.extents.x1 = max(oldX, newX);
+ r.extents.y1 = max(oldY, newY);
+ r.extents.x2 = min(oldX2, newX2);
+ r.extents.y2 = min(oldY2, newY2);
+
+ // r is now intersection of of old location and new location
+ if (r.extents.x2 > r.extents.x1 && r.extents.y2 > r.extents.y1) {
+#if 0
+ DDXPointRec srcPt = {r.extents.x1, r.extents.y1};
+ // Correct for border width change
+ // fixme need to correct for border width change
+ int dx = newX - oldX;
+ int dy = newY - oldY;
+ REGION_TRANSLATE(pScreen, &r, dx, dy);
+#endif
+ fbCopyRegion(src, dst, NULL, &r, 0, 0, fbCopyWindowProc, 0, 0);
+ }
+ REGION_UNINIT(pScreen, &r);
+ }
+}
+
+
+static void
+FinishFrameResize(WindowPtr pWin, Bool gravity,
+ int oldX, int oldY,
+ unsigned int oldW, unsigned int oldH, unsigned int oldBW,
+ int newX, int newY,
+ unsigned int newW, unsigned int newH, unsigned int newBW)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ CallFrameProc(pScreen, FinishResizeFrame,
+ (pScreen, &winRec->frame, oldX, oldY, oldW, oldH));
+ if (wBoundingShape(pWin)) {
+ RootlessDamageShape(pWin);
+ }
+
+ // Destroy temp pixmap
+ FreeScratchPixmapHeader(gResizeDeathPix);
+ xfree(gResizeDeathBits);
+ gResizeDeathPix = gResizeDeathBits = NULL;
+
+ if (gravity) {
+ pScreen->CopyWindow = gResizeOldCopyWindowProc;
+ gResizeCopyWindowSource = NULL;
+ }
+}
+
+
+// If kind==VTOther, window border is resizing (and borderWidth is
+// already changed!!@#$) This case works like window resize, not move.
+void
+RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
+{
+ CopyWindowProcPtr oldCopyWindowProc = NULL;
+ RegionRec saveRoot;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ int oldX = 0, oldY = 0, newX = 0, newY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
+
+ RL_DEBUG_MSG("movewindow start \n");
+
+ if (winRec) {
+ if (kind == VTMove) {
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ RootlessRedisplay(pWin);
+ } else {
+ RL_DEBUG_MSG("movewindow border resizing ");
+ oldBW = winRec->borderWidth;
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ oldW = winRec->frame.w;
+ oldH = winRec->frame.h;
+ newBW = pWin->borderWidth;
+ newX = x;
+ newY = y;
+ newW = pWin->drawable.width + 2*newBW;
+ newH = pWin->drawable.height + 2*newBW;
+ StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+ }
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, MoveWindow);
+ if (winRec) {
+ oldCopyWindowProc = pScreen->CopyWindow;
+ pScreen->CopyWindow = RootlessNoCopyWindow;
+ }
+ pScreen->MoveWindow(pWin, x, y, pSib, kind);
+ if (winRec) {
+ pScreen->CopyWindow = oldCopyWindowProc;
+ }
+ NORMAL_ROOT(pWin);
+ SCREEN_WRAP(pScreen, MoveWindow);
+
+ if (winRec) {
+ if (kind == VTMove) {
+ // PositionWindow has already set the new frame position.
+ CallFrameProc(pScreen, MoveFrame,
+ (pScreen, &winRec->frame, oldX, oldY));
+ } else {
+ FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+ }
+
+ RL_DEBUG_MSG("movewindow end\n");
+}
+
+
+// Note: (x, y, w, h) as passed to this procedure don't match
+// the frame definition.
+// (x,y) is corner of very outer edge, *outside* border
+// w,h is width and height *inside8 border, *ignoring* border width
+// The rect (x, y, w, h) doesn't mean anything.
+// (x, y, w+2*bw, h+2*bw) is total rect
+// (x+bw, y+bw, w, h) is inner rect
+
+void
+RootlessResizeWindow(WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib)
+{
+ RegionRec saveRoot;
+ RootlessWindowRec *winRec = WINREC(pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ int oldX = 0, oldY = 0, newX = 0, newY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
+
+ RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
+
+ if (winRec) {
+ oldBW = winRec->borderWidth;
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ oldW = winRec->frame.w;
+ oldH = winRec->frame.h;
+
+ newBW = oldBW;
+ newX = x;
+ newY = y;
+ newW = w + 2*newBW;
+ newH = h + 2*newBW;
+
+ StartFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pScreen, ResizeWindow);
+ pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
+ SCREEN_WRAP(pScreen, ResizeWindow);
+ NORMAL_ROOT(pWin);
+
+ if (winRec) {
+ FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ RL_DEBUG_MSG("resizewindow end\n");
+}
+
+
+// fixme untested!
+// pWin inside corner stays the same
+// pWin->drawable.[xy] stays the same
+// frame moves and resizes
+void
+RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
+{
+ RegionRec saveRoot;
+
+ RL_DEBUG_MSG("change border width ");
+ if (width != pWin->borderWidth) {
+ RootlessWindowRec *winRec = WINREC(pWin);
+ int oldX = 0, oldY = 0, newX = 0, newY = 0;
+ unsigned int oldW = 0, oldH = 0, oldBW = 0;
+ unsigned int newW = 0, newH = 0, newBW = 0;
+
+ if (winRec) {
+ oldBW = winRec->borderWidth;
+ oldX = winRec->frame.x;
+ oldY = winRec->frame.y;
+ oldW = winRec->frame.w;
+ oldH = winRec->frame.h;
+
+ newBW = width;
+ newX = pWin->drawable.x - newBW;
+ newY = pWin->drawable.y - newBW;
+ newW = pWin->drawable.width + 2*newBW;
+ newH = pWin->drawable.height + 2*newBW;
+
+ StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+
+ HUGE_ROOT(pWin);
+ SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
+ pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
+ SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
+ NORMAL_ROOT(pWin);
+
+ if (winRec) {
+ FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
+ newX, newY, newW, newH, newBW);
+ }
+ }
+ RL_DEBUG_MSG("change border width end\n");
+}
diff --git a/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.h b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.h
new file mode 100644
index 000000000..0c752e012
--- /dev/null
+++ b/xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.h
@@ -0,0 +1,32 @@
+/*
+ * Rootless window management
+ *
+ * Greg Parker gparker@cs.stanford.edu
+ */
+/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessWindow.h,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
+
+#ifndef _ROOTLESSWINDOW_H
+#define _ROOTLESSWINDOW_H
+
+#include "rootlessCommon.h"
+
+
+Bool RootlessCreateWindow(WindowPtr pWin);
+Bool RootlessDestroyWindow(WindowPtr pWin);
+
+#ifdef SHAPE
+void RootlessSetShape(WindowPtr pWin);
+#endif // SHAPE
+
+Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask);
+Bool RootlessPositionWindow(WindowPtr pWin, int x, int y);
+Bool RootlessRealizeWindow(WindowPtr pWin);
+Bool RootlessUnrealizeWindow(WindowPtr pWin);
+void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
+void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc);
+void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind);
+void RootlessResizeWindow(WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib);
+void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
+
+#endif
diff --git a/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciarotate.c b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciarotate.c
new file mode 100644
index 000000000..a8eb72d55
--- /dev/null
+++ b/xc/programs/Xserver/hw/kdrive/pcmcia/pcmciarotate.c
@@ -0,0 +1,332 @@
+/*
+ * $XFree86: xc/programs/Xserver/hw/kdrive/pcmcia/pcmciarotate.c,v 1.1 2002/10/13 19:35:56 keithp Exp $
+ *
+ * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "X.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "font.h"
+#include "dixfontstr.h"
+#include "fontstruct.h"
+#include "mi.h"
+#include "regionstr.h"
+#include "globals.h"
+#include "gcstruct.h"
+#include "shadow.h"
+#include "fb.h"
+
+/*
+ * These indicate which way the source (shadow) is scanned when
+ * walking the screen in a particular direction
+ */
+
+#define LEFT_TO_RIGHT 1
+#define RIGHT_TO_LEFT -1
+#define TOP_TO_BOTTOM 2
+#define BOTTOM_TO_TOP -2
+
+typedef CARD16 PcBits;
+typedef INT32 PcStride;
+
+#define PC_SHIFT 4
+#define PC_UNIT (1 << PC_SHIFT)
+#define PC_HALFUNIT (1 << (PC_SHIFT-1))
+#define PC_MASK (PC_UNIT - 1)
+#define PC_ALLONES ((PcBits) -1)
+
+#define PcScrRight(x,b) FbScrRight(x,b)
+#define PcScrLeft(x,b) FbScrLeft(x,b)
+#define PcBitsMask(x,w) (PcScrRight(PC_ALLONES,(x) & PC_MASK) & \
+ PcScrLeft(PC_ALLONES,(PC_UNIT - ((x) + (w))) & PC_MASK))
+
+#define pcGetDrawable(pDrawable, pointer, stride, bpp, xoff, yoff) { \
+ PixmapPtr _pPix; \
+ if ((pDrawable)->type != DRAWABLE_PIXMAP) \
+ _pPix = fbGetWindowPixmap(pDrawable); \
+ else \
+ _pPix = (PixmapPtr) (pDrawable); \
+ (pointer) = (PcBits *) _pPix->devPrivate.ptr; \
+ (stride) = ((int) _pPix->devKind) / sizeof (PcBits); \
+ (bpp) = _pPix->drawable.bitsPerPixel; \
+ (xoff) = 0; \
+ (yoff) = 0; \
+}
+
+void
+pcmciaUpdateRotatePacked (ScreenPtr pScreen,
+ shadowBufPtr pBuf)
+{
+ RegionPtr damage = &pBuf->damage;
+ PixmapPtr pShadow = pBuf->pPixmap;
+ int nbox = REGION_NUM_RECTS (damage);
+ BoxPtr pbox = REGION_RECTS (damage);
+ PcBits *shaBits;
+ PcStride shaStride;
+ int shaBpp;
+ int shaXoff, shaYoff;
+ int box_x1, box_x2, box_y1, box_y2;
+ int sha_x1, sha_y1;
+ int scr_x1, scr_x2, scr_y1, scr_y2, scr_w, scr_h;
+ int scr_x, scr_y;
+ int w;
+ int pixelsPerBits;
+ int pixelsMask;
+ PcStride shaStepOverY, shaStepDownY, shaStepOverX, shaStepDownX;
+ PcBits *shaLine, *sha;
+ int shaHeight = pShadow->drawable.height;
+ int shaWidth = pShadow->drawable.width;
+ PcBits shaMask;
+ int shaFirstShift, shaShift;
+ int o_x_dir;
+ int o_y_dir;
+ int x_dir;
+ int y_dir;
+
+ pcGetDrawable (&pShadow->drawable, shaBits, shaStride, shaBpp, shaXoff, shaYoff);
+ pixelsPerBits = (sizeof (PcBits) * 8) / shaBpp;
+ pixelsMask = ~(pixelsPerBits - 1);
+ shaMask = PcBitsMask (PC_UNIT-shaBpp, shaBpp);
+ /*
+ * Compute rotation related constants to walk the shadow
+ */
+ o_x_dir = LEFT_TO_RIGHT;
+ o_y_dir = TOP_TO_BOTTOM;
+ if (pBuf->randr & SHADOW_REFLECT_X)
+ o_x_dir = -o_x_dir;
+ if (pBuf->randr & SHADOW_REFLECT_Y)
+ o_y_dir = -o_y_dir;
+ switch (pBuf->randr & (SHADOW_ROTATE_ALL)) {
+ case SHADOW_ROTATE_0: /* upper left shadow -> upper left screen */
+ default:
+ x_dir = o_x_dir;
+ y_dir = o_y_dir;
+ break;
+ case SHADOW_ROTATE_90: /* upper right shadow -> upper left screen */
+ x_dir = o_y_dir;
+ y_dir = -o_x_dir;
+ break;
+ case SHADOW_ROTATE_180: /* lower right shadow -> upper left screen */
+ x_dir = -o_x_dir;
+ y_dir = -o_y_dir;
+ break;
+ case SHADOW_ROTATE_270: /* lower left shadow -> upper left screen */
+ x_dir = -o_y_dir;
+ y_dir = o_x_dir;
+ break;
+ }
+ switch (x_dir) {
+ case LEFT_TO_RIGHT:
+ shaStepOverX = shaBpp;
+ shaStepOverY = 0;
+ break;
+ case TOP_TO_BOTTOM:
+ shaStepOverX = 0;
+ shaStepOverY = shaStride;
+ break;
+ case RIGHT_TO_LEFT:
+ shaStepOverX = -shaBpp;
+ shaStepOverY = 0;
+ break;
+ case BOTTOM_TO_TOP:
+ shaStepOverX = 0;
+ shaStepOverY = -shaStride;
+ break;
+ }
+ switch (y_dir) {
+ case TOP_TO_BOTTOM:
+ shaStepDownX = 0;
+ shaStepDownY = shaStride;
+ break;
+ case RIGHT_TO_LEFT:
+ shaStepDownX = -shaBpp;
+ shaStepDownY = 0;
+ break;
+ case BOTTOM_TO_TOP:
+ shaStepDownX = 0;
+ shaStepDownY = -shaStride;
+ break;
+ case LEFT_TO_RIGHT:
+ shaStepDownX = shaBpp;
+ shaStepDownY = 0;
+ break;
+ }
+
+ while (nbox--)
+ {
+ box_x1 = pbox->x1;
+ box_y1 = pbox->y1;
+ box_x2 = pbox->x2;
+ box_y2 = pbox->y2;
+ pbox++;
+
+ /*
+ * Compute screen and shadow locations for this box
+ */
+ switch (x_dir) {
+ case LEFT_TO_RIGHT:
+ scr_x1 = box_x1 & pixelsMask;
+ scr_x2 = (box_x2 + pixelsPerBits - 1) & pixelsMask;
+
+ sha_x1 = scr_x1;
+ break;
+ case TOP_TO_BOTTOM:
+ scr_x1 = box_y1 & pixelsMask;
+ scr_x2 = (box_y2 + pixelsPerBits - 1) & pixelsMask;
+
+ sha_y1 = scr_x1;
+ break;
+ case RIGHT_TO_LEFT:
+ scr_x1 = (shaWidth - box_x2) & pixelsMask;
+ scr_x2 = (shaWidth - box_x1 + pixelsPerBits - 1) & pixelsMask;
+
+ sha_x1 = (shaWidth - scr_x1 - 1);
+ break;
+ case BOTTOM_TO_TOP:
+ scr_x1 = (shaHeight - box_y2) & pixelsMask;
+ scr_x2 = (shaHeight - box_y1 + pixelsPerBits - 1) & pixelsMask;
+
+ sha_y1 = (shaHeight - scr_x1 - 1);
+ break;
+ }
+ switch (y_dir) {
+ case TOP_TO_BOTTOM:
+ scr_y1 = box_y1;
+ scr_y2 = box_y2;
+
+ sha_y1 = scr_y1;
+ break;
+ case RIGHT_TO_LEFT:
+ scr_y1 = (shaWidth - box_x2);
+ scr_y2 = (shaWidth - box_x1);
+
+ sha_x1 = box_x2 - 1;
+ break;
+ case BOTTOM_TO_TOP:
+ scr_y1 = shaHeight - box_y2;
+ scr_y2 = shaHeight - box_y1;
+
+ sha_y1 = box_y2 - 1;
+ break;
+ case LEFT_TO_RIGHT:
+ scr_y1 = box_x1;
+ scr_y2 = box_x2;
+
+ sha_x1 = box_x1;
+ break;
+ }
+ scr_w = ((scr_x2 - scr_x1) * shaBpp) >> PC_SHIFT;
+ scr_h = scr_y2 - scr_y1;
+ scr_y = scr_y1;
+
+ /* shift amount for first pixel on screen */
+ shaFirstShift = PC_UNIT - ((sha_x1 * shaBpp) & PC_MASK) - shaBpp;
+
+ /* pointer to shadow data first placed on screen */
+ shaLine = (shaBits +
+ sha_y1 * shaStride +
+ ((sha_x1 * shaBpp) >> PC_SHIFT));
+
+ /*
+ * Copy the bits, always write across the physical frame buffer
+ * to take advantage of write combining.
+ */
+ while (scr_h--)
+ {
+ int p;
+ PcBits bits;
+ PcBits *win;
+ int i;
+ CARD32 winSize;
+
+ sha = shaLine;
+ shaShift = shaFirstShift;
+ w = scr_w;
+ scr_x = scr_x1 * shaBpp >> PC_SHIFT;
+
+ while (w)
+ {
+ /*
+ * Map some of this line
+ */
+ win = (PcBits *) (*pBuf->window) (pScreen,
+ scr_y,
+ scr_x << 1,
+ SHADOW_WINDOW_WRITE,
+ &winSize,
+ pBuf->closure);
+ i = (winSize >> 1);
+ if (i > w)
+ i = w;
+ w -= i;
+ scr_x += i;
+ /*
+ * Copy the portion of the line mapped
+ */
+ while (i--)
+ {
+ bits = 0;
+ p = pixelsPerBits;
+ /*
+ * Build one word of output from multiple inputs
+ *
+ * Note that for 90/270 rotations, this will walk
+ * down the shadow hitting each scanline once.
+ * This is probably not very efficient.
+ */
+ while (p--)
+ {
+ bits = PcScrLeft(bits, shaBpp);
+ bits |= PcScrRight (*sha, shaShift) & shaMask;
+
+ shaShift -= shaStepOverX;
+ if (shaShift >= PC_UNIT)
+ {
+ shaShift -= PC_UNIT;
+ sha--;
+ }
+ else if (shaShift < 0)
+ {
+ shaShift += PC_UNIT;
+ sha++;
+ }
+ sha += shaStepOverY;
+ }
+ *win++ = bits;
+ }
+ }
+ scr_y++;
+ shaFirstShift -= shaStepDownX;
+ if (shaFirstShift >= PC_UNIT)
+ {
+ shaFirstShift -= PC_UNIT;
+ shaLine--;
+ }
+ else if (shaFirstShift < 0)
+ {
+ shaFirstShift += PC_UNIT;
+ shaLine++;
+ }
+ shaLine += shaStepDownY;
+ }
+ }
+}
diff --git a/xc/programs/Xserver/hw/xfree86/Domain.note b/xc/programs/Xserver/hw/xfree86/Domain.note
new file mode 100644
index 000000000..3db2aefae
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/Domain.note
@@ -0,0 +1,159 @@
+The purpose of the changes described here is to implement a more general
+framework for multi-head on systems with more than one host-to-PCI bridge.
+The changes also implement a basic port of XFree86 to SPARC Solaris.
+
+These changes are derived from David S. Miller's submission #4653 to the
+patch list. David Andrew of Sun Microsystems was also kind enough to
+arrange for a hardware loan for development of these changes.
+
+These changes are known to work on several SPARC SunOS and UltraSPARC
+Linux configurations. Linux kernel work is in progress to port these
+changes to Linux/PowerPC.
+
+Several loose ends still need to be addressed before these changes can be
+considered stable. The bulk of this note is devoted to enumerating what
+remains to be done, along with other notes, broken down into various broad
+categories.
+
+SPARC SunOS (aka Solaris)
+-------------------------
+- An overview of this XFree86 port is available in README.Solaris.
+- The keyboard map code in hw/xfree86/os-support/sunos/sun_kbdEv.c needs
+ to be extended to handle more than only the sun5 keyboard I targeted it
+ for. Even for the sun5, the map is incomplete as several keys are not
+ mapped. What is there is just barely usable.
+- On exit, the server will zero out /dev/fb, but that might not be the
+ right thing to do for all primary adapters. This does however
+ appear to emulate the behaviour of Sun's commercial servers. It also
+ eliminates the need for output drivers to save and restore video memory
+ contents. (They still need to save/restore the mode timing however.)
+ This also chimes into a long-standing XFree86 policy to not save/restore
+ video memory contents if the mode on entry is found to be non-VGA, a
+ policy several existing drivers comply with.
+- The SBUS drivers (sunbw2, suncg14, suncg3, suncg6, sunffb, sunleo and
+ suntcx), the common layer's SBUS code and the fbdev driver have all
+ only been compile tested. There are likely to be Linux'isms within
+ them that remain to be dealt with.
+- It still needs to be verified whether or not this work adversely
+ affected support for ix86 Solaris.
+
+UltraSPARC Linux
+----------------
+- Although this code can be compiled using any Linux/SPARC64 kernel, it
+ can only run successfully using 2.4.12 or later.
+- I haven't had time to sufficiently dig into XKB to properly configure it
+ for sun5 keyboards. Given XFree86 on Linux/SPARC has been around for a
+ while, it's likely someone has already done this, and I'd appreciate
+ receiving a copy of a working XF86Config input section.
+
+PowerPC Linux
+-------------
+- As mentioned above, kernel work is in progress to port this PCI scheme
+ to Linux/PowerPC.
+- Aside from kernel work, the inX() and outX() definitions in compiler.h
+ will need to be changed to do something akin to their SPARC definitions,
+ i.e. consider their port argument to be a virtual address.
+
+Other Linux ports to multi-domain architectures
+-----------------------------------------------
+- Comments in os-support/bus/linuxPci.c document the kernel interface
+ required to port these changes. In short, Linux ports, such as Alpha
+ and mips, should follow SPARC and PowerPC's lead in providing support to
+ mmap() PCI devices through their /proc/bus/pci pseudo-files and to treat
+ such requests for host bridges as requests to mmap() space provided by
+ these bridges.
+
+Other OS's
+----------
+- In the right hands, either linuxPci.c or sparcPci.c can be used as a
+ guide for what would need to be done to port this scheme to other OS's.
+ Perhaps the largest difference between the two (in terms of interface to
+ the common layer) is that the SunOS port includes internally generated
+ domain numbers in PCITAG's, whereas the Linux port doesn't need to. The
+ remainder of the PCI code (which is OS-independent) can handle either
+ scheme.
+- Required entry points are xf86GetPciDomain(), xf86MapDomainMemory(),
+ xf86MapDomainIO() and xf86ReadDomainMemory(). Replacements for
+ xf86BusAccWindowsFromOS(), xf86PciBusAccWindowsFromOS() and
+ xf86AccResFromOS() might also be required.
+- Development of these changes has detected the fact that the XFree86 port
+ to the PowerMax OS is broken, and has been for some time, i.e. since
+ shortly after its introduction, back in the 3.9* days.
+
+SPARC PCI (OS-independent)
+--------------------------
+- The "Simba" PCI-to-PCI bridge used in SPARC's does not implement VGA
+ routing, as defined in the PCI specs. Fortunately, OpenPROM seems to
+ always route VGA resources to the bus with PCI connectors, but this also
+ causes the common layer to not mark any PCI adapter as primary.
+
+Multiple PCI domains (architecture- and OS-independent)
+-------------------------------------------------------
+- This implementation assumes every host-to-PCI bridge provides access to
+ a separate PCI domain. Each such domain provides three different
+ "address" spaces: PCI configuration, I/O and memory. The
+ implementation can also deal with situations where more than one PCI
+ domain share (different subsets of) the same PCI configuration space. I
+ have unconfirmed information that suggests it might be necessary to also
+ allow the sharing of PCI memory spaces.
+- This implementation also assumes the CPU's physical address space
+ includes the entirety of each domain's I/O and memory spaces. I know
+ this'll need to be changed to deal with the so-called UniNorth bridge,
+ found on PowerPC's, which allows access to only a subset of the memory
+ space behind it.
+- Ideally, the common layer should mark as primary up to one PCI adapter
+ per domain. This has yet to be done.
+- Something needs to be done about PCI master aborts on primary buses.
+ For details on this, see my long-winded diatribe in sparcPci.c, and
+ related comments in linuxPci.c. Suffice it to say here that I see the
+ eventual implementation of host bridge drivers within XFree86 as
+ unavoidable at this point.
+- DGA is broken on multi-domain platforms. The information passed to the
+ client to locate the framebuffer still needs to be revised. The best way
+ to deal with this is to change all drivers' OpenFramebuffer() function to
+ call a common layer routine to set the device name and displacements to be
+ returned to the DGA client.
+
+Output drivers
+--------------
+Most drivers currently used on ix86 need(ed) source code changes.
+- Calls to xf86ReadBIOS() and xf86MapVidMem() were replaced with calls to
+ xf86ReadDomainMemory() and xf86MapDomainMemory() respectively. Except
+ for the "ati" and "atimisc" modules, this has already been done.
+- All ix86-style I/O port numbers need to be declared as an IOADDRESS, a
+ type defined in xf86Pci.h as "unsigned long". Such port numbers also
+ need to be offset by a displacement which is also defined as an
+ IOADDRESS. Before a driver's PreInit() is called, the common layer
+ makes this displacement available in ScrnInfoRec.domainIOBase. For
+ single-domain architectures, such as ix86, domainIOBase will always be
+ zero. Current use of vgaHWRec.PIOOffset has also been adjusted
+ accordingly. Some drivers have been changed to keep a copy of this
+ displacement in their private structure. Internally, an IOADDRESS is
+ actually a pointer that has been recasted to an unsigned long, but the
+ common layer "hides" this fact from the driver ABI, which means that I/O
+ port numbers, as seen by drivers, remain as integers rather than
+ addresses. Aside from the ati and atimisc modules, s3, sis and tseng
+ are the only modules left whose I/O still needs to be converted (I've
+ temporarily run out of steam).
+- Note that these conversions are not necessarily sufficient to produce
+ drivers that will work on any given multi-domain architecture. A driver
+ that, for example, had endianness problems, still does. But, at least,
+ these conversions, along with the supporting common layer changes, make
+ PCI drivers more widely amenable to porting.
+- rdinx(), wrinx(), modinx(), testrg(), testinx() and testinx2() are not
+ given enough information to allow for the relocation of their I/O. They
+ are consequently being deleted. The apm and ark drivers, the only
+ remaining callers of the first three, have been changed to use local
+ definitions instead. The last three (test*()) were already unused.
+- As a temporary measure, these changes completely disable ISA-style
+ probing on SPARC's and PowerPC's. This means that driver calls to
+ xf86MatchIsaInstances(), while still valid, will always return detection
+ failure on SPARC's and PowerPC's. This will be dealt with when a more
+ general master abort handling scheme is implemented.
+- I need to make a decision about the master abort issues mentionned above
+ before I can convert the "ati" and "atimisc" modules. Consequently,
+ these modules still need to be compiled with -DAVOID_CPIO on
+ multi-domain architectures, and support for Mach64 variants as
+ non-primary heads is not yet available.
+
+$XFree86: xc/programs/Xserver/hw/xfree86/Domain.note,v 1.2 2002/01/25 21:55:49 tsi Exp $
diff --git a/xc/programs/Xserver/hw/xfree86/doc/README.Solaris b/xc/programs/Xserver/hw/xfree86/doc/README.Solaris
new file mode 100644
index 000000000..eccf3615c
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/doc/README.Solaris
@@ -0,0 +1,222 @@
+ Information for Solaris
+
+ David Holland, modified by Marc Aurele La France
+
+ 2001 October 01
+
+1. What is XFree86
+
+XFree86 is a port of X11R6.5.1 that supports several versions of Unix. It is
+derived from X386 1.2 which was the X server distributed with X11R5. This
+release consists of many new features and performance improvements as well as
+many bug fixes. The release is available as a source code distribution, as
+well as binary distributions for many architectures.
+
+The sources for XFree86 are available by anonymous ftp from:
+
+ ftp://ftp.XFree86.org/pub/XFree86/current
+
+Solaris binaries for XFree86 are available for anonymous ftp at the same
+address. Currently, two binary distributions are available: one for Solaris
+8 x86, the other for previous Solaris x86 releases. They are not inter-
+changeable. No binary distribution is available for Solaris/SPARC as it is
+still under development.
+
+2. The VT-switching sub-system in Solaris x86
+
+The virtual terminal sub-system is a undocumented, and unsupported feature of
+Solaris x86. Therefore if you use virtual terminals, you do so at YOUR OWN
+RISK.
+
+Virtual terminals are not available in Solaris SPARC, and their availability
+has been removed in Solaris8 x86.
+
+When available, the virtual terminals of Solaris work basically the same way
+as most other SVR4 VT sub-systems. However, there are a number of limita-
+tions documented below.
+
+First, if you are running a Solaris 2.4 x86 system, and you want VT's, you
+will have to create the necessary devices first, so become root.
+
+Verify the chanmux device driver's major number is 100:
+
+ # grep -i chanmux /etc/name_to_major
+ chanmux 100
+ #
+
+If the number after 'chanmux' is anything but 100, I would suggest you imme-
+diately abort your attempt to create virtual terminals, and learn to live
+without them.
+
+However, if it is 100, then as root type the following commands to create the
+maximum allowable number of virtual terminals.
+
+ # cd /dev
+ # mknod vt01 c 100 1
+ # mknod vt02 c 100 2
+ # mknod vt03 c 100 3
+ # mknod vt04 c 100 4
+ # mknod vt05 c 100 5
+ # mknod vt06 c 100 6
+ # mknod vt07 c 100 7
+
+There is no need for a reconfiguration boot.
+
+Secondly, for both 2.1, and 2.4 x86 systems, add a few lines to the inittab
+to enable logins on them.
+
+(Note, do NOT make a mistake here, you could lock yourself out of the system)
+
+ --------------------->Snip Snip<-----------------------------------------------
+ v1:234:respawn:/usr/lib/saf/ttymon -g -h -p "`uname -n` VT01 login: " -T AT386 -d /dev/vt01 -l console
+ v2:234:respawn:/usr/lib/saf/ttymon -g -h -p "`uname -n` VT02 login: " -T AT386 -d /dev/vt02 -l console
+ v3:234:respawn:/usr/lib/saf/ttymon -g -h -p "`uname -n` VT03 login: " -T AT386 -d /dev/vt03 -l console
+ v4:234:respawn:/usr/lib/saf/ttymon -g -h -p "`uname -n` VT04 login: " -T AT386 -d /dev/vt04 -l console
+ ---------------------->End Here<-----------------------------------------------
+
+These four lines enable four VT's on Alt-SysReq-F1 through Alt-SysReq-F4.
+
+Then execute the command 'init q' to immediately enable the virtual termi-
+nals.
+
+The keys used for VT switching are as follows:
+
+ Alt-SysReq-F1 through Alt-SysReq-F7 enable VT screens 1-7 respec-
+ tively (if the VT is active).
+
+ Alt-SysReq-n enables the next active VT screen.
+
+ Alt-SysReq-p enables the previous active VT screen.
+
+ Alt-SysReq-h returns to the console.
+
+If you are using virtual terminals, you must leave at least one free for use
+by the Xserver.
+
+Limitations of the virtual terminal sub-system under Solaris x86:
+
+There are only a total of 8 available VT's (7 normal VT's + 1 console) not
+the usual 15. If you have all 8 allocated, and you attempt to allocate a
+additional VT you will panic the system. (This bug is worked around in the
+Solaris XFree86 Xserver.)
+
+From a programming stand point, they work pretty much as documented in the
+AT&T Unix System V/386 Release 4 Integrated Software Development Guide, how-
+ever a number of ioctl() calls are broken.
+
+3. Notes for building XFree86 on Solaris
+
+ 1. Both GCC, and ProWorks are supported by XFree86. The minimum recom-
+ mended GCC release is 2.7.2. Some earlier GCC's are known to not work
+ and should be avoided.
+
+ You should also make certain your version of GCC predefines `sun'. If
+ needed edit /usr/local/lib/gcc-lib/*/*/specs, and modify the *prede-
+ fines: line.
+
+ On SPARCs, regardless of the compiler you use, ensure it generates
+ 32-bit binaries. At this time, 64-bit binaries will probably not work.
+
+ 2. Also on SPARCs, you will need to set BuildXFree86OnSparcSunOS to YES in
+ ~xc/config/cf/host.def. Otherwise, you can only build the old depre-
+ cated Xsun* servers.
+
+ 3. A Threaded Xlib compiled with GCC has subtle problems. It'll work 98%
+ of the time, however clients will occasionally exhibit strange hangs.
+ Most notably image viewers such as xv-3.10 exhibit this problem.
+
+ It is recommended that you set ThreadedX in ~xc/config/cf/host.def to
+ NO, if you are using GCC. ProWorks does not have this problem.
+ Whether this behaviour still exists with newer GCC's has not been veri-
+ fied.
+
+ 4. To build XFree86 with GCC you need gcc and (optionally) c++filt from
+ GNU binutils. Don't install gas or ld from GNU binutils, use the one
+ provided by Sun.
+
+ You might need to setup a /opt/SUNWspro/bin directory containing sym-
+ bolic links named cc, CC, and c++filt pointing respectively to the
+ actual gcc, g++ and c++filt commands.
+
+ 5. If you are using ProWorks to compile the XFree86 distribution, you need
+ to modify your PATH appropriately so the ProWorks tools are available.
+ Normally, they should be in /opt/SUNWspro/bin
+
+ 6. You MUST put /usr/ccs/bin at the front of your PATH. There are known
+ problems with some GNU replacements for the utilities found there. So
+ the /usr/ccs/bin versions of these programs must be found before any
+ possible GNU versions. (Most notably GNU 'ar' does not work during the
+ build).
+
+4. Notes for running XFree86 on Solaris
+
+ 1. Depending on the release or architecture of Solaris you are running,
+ you might need to install an OS driver for an aperture device.
+
+ Under Solaris x86 2.5 and later, there's a system driver (/dev/xsvc)
+ that provides this functionality. It will be detected automatically by
+ the server, so you don't need to install the aperture driver.
+
+ For older Solaris x86 and for Solaris SPARC releases, the source for
+ this driver is included in xc/programs/Xserver/hw/xfree86/etc/apSo-
+ laris.shar of the source distribution. This file can usually also be
+ found in the /usr/X11R6/lib/X11/etc directory when XFree86 is
+ installed. Building, and installing the driver is relatively straight
+ forward. Please read its accompanying README file.
+
+ 2. If you have not made the Virtual Terminal devices, you will need to
+ specify the terminal device to run the Xserver on. The correct device
+ is vt00 so your xinit command would look like so:
+
+ xinit -- vt00
+
+ If you have made the virtual terminal devices you do not need to spec-
+ ify the VT to run the Xserver on.
+
+ 3. For Solaris you will probably want to set your LD_LIBRARY_PATH to
+ /usr/X11R6/lib:/usr/openwin/lib:/usr/dt/lib. Including /usr/X11R6/lib
+ in your LD_LIBRARY_PATH is probably not necessary, however it doesn't
+ hurt. :)
+
+ Including /usr/openwin/lib in the LD_LIBRARY_PATH is recommended
+ because some Sun supplied binaries were not compiled with LD_RUN_PATH
+ set properly at compile time.
+
+ Motif and CDE applications may require /usr/dt/lib in your
+ LD_LIBRARY_PATH too.
+
+ 4. Xqueue is NOT supported under Solaris. The includes necessary for
+ Xqueue are available, however the driver does not seem to be in the
+ kernel. (Go figure)
+
+ 5. If you want to use xdm with Solaris, extract the files from the shar
+ file in /usr/X11R6/lib/X11/etc/XdmConf.svr4 into a temporary directory.
+ The README file tells where the individual files need to be installed.
+ Be sure to read through each file and make any site-specific changes
+ that you need.
+
+5. Known bugs, and work arounds with Solaris
+
+ 1. The Solaris 2.1 for x86 OpenWindows filemgr does not work against a
+ X11R5 Xserver, it probably will also not work against a X11R6 Xserver.
+ Attempting to 'Drag and Drop' a file causes the filemgr to abort with
+ an 'X error'
+
+ Solaris x86 2.4 does not have this problem.
+
+ There is no known work around.
+
+ 2. The SPARC port is still quite new, so instability is to be expected
+ (and reported!). It might even have broken some aspects of the x86
+ port.
+
+6. Bug Notification
+
+Bug reports should be sent to one of the XFree86@XFree86.org,
+Xpert@XFree86.org, or Newbie@XFree86.org (depending on your level of com-
+fort).
+
+ Generated from XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/Solaris.sgml,v 1.3 2002/01/25 21:55:53 tsi Exp $
+
+
+$XFree86: xc/programs/Xserver/hw/xfree86/doc/README.Solaris,v 1.3 2002/01/28 22:24:17 tsi Exp $
diff --git a/xc/programs/Xserver/hw/xwin/X.ico b/xc/programs/Xserver/hw/xwin/X.ico
new file mode 100644
index 000000000..26e2cf947
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/X.ico
Binary files differ
diff --git a/xc/programs/Xserver/hw/xwin/XWin.rc b/xc/programs/Xserver/hw/xwin/XWin.rc
new file mode 100644
index 000000000..73533ba4e
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/XWin.rc
@@ -0,0 +1,60 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+/* $XFree86: xc/programs/Xserver/hw/xwin/XWin.rc,v 1.1 2002/10/17 08:18:21 alanh Exp $ */
+
+#include "resource.h"
+
+
+/*
+ * Dialogs
+ */
+
+DEPTH_CHANGE_BOX DIALOG DISCARDABLE 32, 32, 180, 100
+STYLE WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE
+FONT 8, "MS Sans Serif"
+CAPTION "Cygwin/XFree86"
+BEGIN
+ DEFPUSHBUTTON "Dismiss", IDOK, 66, 80, 50, 14
+ CTEXT "Cygwin/XFree86", IDC_STATIC, 40, 12, 100, 8
+ CTEXT "Disruptive screen configuration change.", IDC_STATIC, 7, 40, 166, 8
+ CTEXT "Restore previous resolution to use Cygwin/XFree86.", IDC_STATIC, 7, 52, 166, 8
+END
+
+
+/*
+ * Menus
+ */
+
+
+/*
+ * Icons
+ */
+
+IDI_XWIN ICON DISCARDABLE "X.ico"
diff --git a/xc/programs/Xserver/hw/xwin/resource.h b/xc/programs/Xserver/hw/xwin/resource.h
new file mode 100644
index 000000000..b0b4b23c9
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/resource.h
@@ -0,0 +1,41 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+/* $XFree86: xc/programs/Xserver/hw/xwin/resource.h,v 1.1 2002/10/17 08:18:21 alanh Exp $ */
+
+#include "winms.h"
+
+
+/*
+ * Local defines
+ */
+
+#define IDM_APP_ABOUT 40001
+#define IDC_STATIC -1
+#define IDI_XWIN 101
diff --git a/xc/programs/Xserver/hw/xwin/winconfig.c b/xc/programs/Xserver/hw/xwin/winconfig.c
new file mode 100644
index 000000000..bc336527c
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/winconfig.c
@@ -0,0 +1,949 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Alexander Gottwald
+ */
+/* $XFree86: xc/programs/Xserver/hw/xwin/winconfig.c,v 1.1 2002/10/17 08:18:22 alanh Exp $ */
+
+#include "win.h"
+#include "winconfig.h"
+#include "winmsg.h"
+#include "globals.h"
+
+#ifdef XKB
+#define XKB_IN_SERVER
+#include "XKBsrv.h"
+#endif
+
+#ifndef CONFIGPATH
+#define CONFIGPATH "%A," "%R," \
+ "/etc/X11/%R," "%P/etc/X11/%R," \
+ "%E," "%F," \
+ "/etc/X11/%F," "%P/etc/X11/%F," \
+ "%D/%X," \
+ "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \
+ "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \
+ "%P/etc/X11/%X," \
+ "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \
+ "%P/lib/X11/%X"
+#endif
+
+XF86ConfigPtr g_xf86configptr = NULL;
+WinCmdlineRec g_cmdline = {
+ NULL, /* configFile */
+ NULL, /* fontPath */
+ NULL, /* rgbPath */
+ NULL, /* keyboard */
+#ifdef XKB
+ FALSE, /* noXkbExtension */
+ NULL, /* xkbMap */
+#endif
+ NULL, /* screenname */
+ NULL, /* mousename */
+ FALSE, /* emulate3Buttons */
+ 0 /* emulate3Timeout */
+};
+
+winInfoRec g_winInfo = {
+ { /* keyboard */
+ 0, /* leds */
+ 500, /* delay */
+ 30 /* rate */
+#ifdef XKB
+ }
+ ,
+ { /* xkb */
+ FALSE, /* disable */
+ NULL, /* rules */
+ NULL, /* model */
+ NULL, /* layout */
+ NULL, /* variant */
+ NULL, /* options */
+ NULL, /* initialMap */
+ NULL, /* keymap */
+ NULL, /* types */
+ NULL, /* compat */
+ NULL, /* keycodes */
+ NULL, /* symbols */
+ NULL /* geometry */
+#endif
+ }
+ ,
+ {
+ FALSE,
+ 50}
+};
+
+serverLayoutRec g_winConfigLayout;
+
+static Bool ParseOptionValue (int scrnIndex, pointer options,
+ OptionInfoPtr p);
+static Bool configLayout (serverLayoutPtr, XF86ConfLayoutPtr, char *);
+static Bool configImpliedLayout (serverLayoutPtr, XF86ConfScreenPtr);
+static Bool GetBoolValue (OptionInfoPtr p, const char *s);
+
+#define NULL_IF_EMPTY(x) (winNameCompare(x,"")?x:NULL)
+
+
+Bool
+winReadConfigfile ()
+{
+ Bool retval = TRUE;
+ const char *filename;
+
+ MessageType from = X_DEFAULT;
+ char *xf86ConfigFile = NULL;
+
+ if (g_cmdline.configFile)
+ {
+ from = X_CMDLINE;
+ xf86ConfigFile = g_cmdline.configFile;
+ }
+
+ /* Parse config file into data structure */
+
+ filename = xf86openConfigFile (CONFIGPATH, xf86ConfigFile, PROJECTROOT);
+ if (filename)
+ {
+ winMsg (from, "Using config file: \"%s\"\n", filename);
+ }
+ else
+ {
+ winMsg (X_ERROR, "Unable to locate/open config file");
+ if (xf86ConfigFile)
+ ErrorF (": \"%s\"", xf86ConfigFile);
+ ErrorF ("\n");
+ return FALSE;
+ }
+ if ((g_xf86configptr = xf86readConfigFile ()) == NULL)
+ {
+ winMsg (X_ERROR, "Problem parsing the config file\n");
+ return FALSE;
+ }
+ xf86closeConfigFile ();
+
+ winMsg (X_NONE, "Markers: ");
+ winMsg (X_PROBED, "probed, ");
+ winMsg (X_CONFIG, "from config file, ");
+ winMsg (X_DEFAULT, "default setting,\n ");
+ winMsg (X_CMDLINE, "from command line, ");
+ winMsg (X_NOTICE, "notice, ");
+ winMsg (X_INFO, "informational,\n ");
+ winMsg (X_WARNING, "warning, ");
+ winMsg (X_ERROR, "error, ");
+ winMsg (X_UNKNOWN, "unknown.\n");
+
+ /* set options from data structure */
+
+ if (g_xf86configptr->conf_layout_lst == NULL || g_cmdline.screenname != NULL)
+ {
+ if (g_cmdline.screenname == NULL)
+ {
+ winMsg (X_WARNING,
+ "No Layout section. Using the first Screen section.\n");
+ }
+ if (!configImpliedLayout (&g_winConfigLayout,
+ g_xf86configptr->conf_screen_lst))
+ {
+ winMsg (X_ERROR, "Unable to determine the screen layout\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Check if layout is given in the config file */
+ if (g_xf86configptr->conf_flags != NULL)
+ {
+ char *dfltlayout = NULL;
+ pointer optlist = g_xf86configptr->conf_flags->flg_option_lst;
+
+ if (optlist && winFindOption (optlist, "defaultserverlayout"))
+ dfltlayout =
+ winSetStrOption (optlist, "defaultserverlayout", NULL);
+
+ if (!configLayout (&g_winConfigLayout,
+ g_xf86configptr->conf_layout_lst,
+ dfltlayout))
+ {
+ winMsg (X_ERROR, "Unable to determine the screen layout\n");
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!configLayout (&g_winConfigLayout,
+ g_xf86configptr->conf_layout_lst,
+ NULL))
+ {
+ winMsg (X_ERROR, "Unable to determin the screen layout\n");
+ return FALSE;
+ }
+ }
+ }
+
+ /* setup special config files */
+ winConfigFiles ();
+ return retval;
+}
+
+
+/* Set the keyboard configuration */
+
+Bool
+winConfigKeyboard (DeviceIntPtr pDevice)
+{
+ XF86ConfInputPtr kbd = NULL;
+ XF86ConfInputPtr input_list = NULL;
+ MessageType from = X_DEFAULT;
+ MessageType kbdfrom = X_CONFIG;
+
+ /* Setup defaults */
+#ifdef XKB
+ g_winInfo.xkb.disable = FALSE;
+# ifdef PC98 /* japanese */ /* not implemented */
+ g_winInfo.xkb.rules = "xfree98";
+ g_winInfo.xkb.model = "pc98";
+ g_winInfo.xkb.layout = "nex/jp";
+ g_winInfo.xkb.variant = NULL;
+ g_winInfo.xkb.options = NULL;
+# else
+ g_winInfo.xkb.rules = "xfree86";
+ g_winInfo.xkb.model = "pc101";
+ g_winInfo.xkb.layout = "us";
+ g_winInfo.xkb.variant = NULL;
+ g_winInfo.xkb.options = NULL;
+# endif /* PC98 */
+ g_winInfo.xkb.initialMap = NULL;
+ g_winInfo.xkb.keymap = NULL;
+ g_winInfo.xkb.types = NULL;
+ g_winInfo.xkb.compat = NULL;
+ g_winInfo.xkb.keycodes = NULL;
+ g_winInfo.xkb.symbols = NULL;
+ g_winInfo.xkb.geometry = NULL;
+#endif /* XKB */
+
+ /* parse the configuration */
+
+ if (g_cmdline.keyboard)
+ kbdfrom = X_CMDLINE;
+
+ /*
+ * Until the layout code is finished, I search for the keyboard
+ * device and configure the server with it.
+ */
+
+ if (g_xf86configptr != NULL)
+ input_list = g_xf86configptr->conf_input_lst;
+
+ while (input_list != NULL)
+ {
+ if (winNameCompare (input_list->inp_driver, "keyboard") == 0)
+ {
+ /* Check if device name matches requested name */
+ if (g_cmdline.keyboard && winNameCompare (input_list->inp_identifier,
+ g_cmdline.keyboard))
+ continue;
+ kbd = input_list;
+ }
+ input_list = input_list->list.next;
+ }
+
+ if (kbd != NULL)
+ {
+ if (kbd->inp_identifier)
+ winMsg (kbdfrom, "Using keyboard \"%s\" as primary keyboard\n",
+ kbd->inp_identifier);
+
+#ifdef XKB
+ from = X_DEFAULT;
+ if (g_cmdline.noXkbExtension)
+ {
+ from = X_CMDLINE;
+ g_winInfo.xkb.disable = TRUE;
+ }
+ else if (kbd->inp_option_lst)
+ {
+ int b = winSetBoolOption (kbd->inp_option_lst, "XkbDisable", FALSE);
+ if (b)
+ {
+ from = X_CONFIG;
+ g_winInfo.xkb.disable = TRUE;
+ }
+ }
+ if (g_winInfo.xkb.disable)
+ {
+ winMsg (from, "XkbExtension disabled\n");
+ }
+ else
+ {
+ char *s;
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbRules", NULL)))
+ {
+ g_winInfo.xkb.rules = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: rules: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbModel", NULL)))
+ {
+ g_winInfo.xkb.model = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: model: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbLayout", NULL)))
+ {
+ g_winInfo.xkb.layout = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: layout: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbVariant", NULL)))
+ {
+ g_winInfo.xkb.variant = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: variant: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbOptions", NULL)))
+ {
+ g_winInfo.xkb.options = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: options: \"%s\"\n", s);
+ }
+
+ from = X_CMDLINE;
+ if (!XkbInitialMap)
+ {
+ s =
+ winSetStrOption (kbd->inp_option_lst, "XkbInitialMap", NULL);
+ if (s)
+ {
+ XkbInitialMap = NULL_IF_EMPTY (s);
+ from = X_CONFIG;
+ }
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbKeymap", NULL)))
+ {
+ g_winInfo.xkb.keymap = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: keymap: \"%s\" "
+ " (overrides other XKB settings)\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbCompat", NULL)))
+ {
+ g_winInfo.xkb.compat = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: compat: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbTypes", NULL)))
+ {
+ g_winInfo.xkb.types = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: types: \"%s\"\n", s);
+ }
+
+ if (
+ (s =
+ winSetStrOption (kbd->inp_option_lst, "XkbKeycodes", NULL)))
+ {
+ g_winInfo.xkb.keycodes = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: keycodes: \"%s\"\n", s);
+ }
+
+ if (
+ (s =
+ winSetStrOption (kbd->inp_option_lst, "XkbGeometry", NULL)))
+ {
+ g_winInfo.xkb.geometry = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: geometry: \"%s\"\n", s);
+ }
+
+ if ((s = winSetStrOption (kbd->inp_option_lst, "XkbSymbols", NULL)))
+ {
+ g_winInfo.xkb.symbols = NULL_IF_EMPTY (s);
+ winMsg (X_CONFIG, "XKB: symbols: \"%s\"\n", s);
+ }
+ }
+#endif
+ }
+ else
+ {
+ winMsg (X_ERROR, "No primary keyboard configured\n");
+ winMsg (X_DEFAULT, "Using compiletime defaults for keyboard\n");
+ }
+
+ return TRUE;
+}
+
+
+Bool
+winConfigMouse (DeviceIntPtr pDevice)
+{
+ MessageType mousefrom = X_CONFIG;
+ XF86ConfInputPtr mouse = NULL;
+ XF86ConfInputPtr input_list = NULL;
+
+ if (g_cmdline.mouse)
+ mousefrom = X_CMDLINE;
+
+ if (g_xf86configptr != NULL)
+ input_list = g_xf86configptr->conf_input_lst;
+
+ while (input_list != NULL)
+ {
+ if (winNameCompare (input_list->inp_driver, "mouse") == 0)
+ {
+ /* Check if device name matches requested name */
+ if (g_cmdline.mouse && winNameCompare (input_list->inp_identifier,
+ g_cmdline.mouse))
+ continue;
+ mouse = input_list;
+ }
+ input_list = input_list->list.next;
+ }
+
+ if (mouse != NULL)
+ {
+ if (mouse->inp_identifier)
+ winMsg (mousefrom, "Using pointer \"%s\" as primary pointer\n",
+ mouse->inp_identifier);
+
+ g_winInfo.pointer.emulate3Buttons =
+ winSetBoolOption (mouse->inp_option_lst, "Emulate3Buttons", FALSE);
+ if (g_cmdline.emulate3buttons)
+ g_winInfo.pointer.emulate3Buttons = g_cmdline.emulate3buttons;
+
+ g_winInfo.pointer.emulate3Timeout =
+ winSetIntOption (mouse->inp_option_lst, "Emulate3Timeout", 50);
+ if (g_cmdline.emulate3timeout)
+ g_winInfo.pointer.emulate3Timeout = g_cmdline.emulate3timeout;
+ }
+ else
+ {
+ winMsg (X_ERROR, "No primary pointer configured\n");
+ winMsg (X_DEFAULT, "Using compiletime defaults for pointer\n");
+ }
+
+ return TRUE;
+}
+
+
+Bool
+winConfigFiles ()
+{
+ MessageType from;
+ XF86ConfFilesPtr filesptr = NULL;
+
+ /* set some shortcuts */
+ if (g_xf86configptr != NULL)
+ {
+ filesptr = g_xf86configptr->conf_files;
+ }
+
+
+ /* Fontpath */
+ from = X_DEFAULT;
+
+ if (g_cmdline.fontPath)
+ {
+ from = X_CMDLINE;
+ defaultFontPath = g_cmdline.fontPath;
+ }
+ else if (filesptr != NULL && filesptr->file_fontpath)
+ {
+ from = X_CONFIG;
+ defaultFontPath = xstrdup (filesptr->file_fontpath);
+ }
+ winMsg (from, "FontPath set to \"%s\"\n", defaultFontPath);
+
+ /* RGBPath */
+ from = X_DEFAULT;
+ if (g_cmdline.rgbPath)
+ {
+ from = X_CMDLINE;
+ rgbPath = g_cmdline.rgbPath;
+ }
+ else if (filesptr != NULL && filesptr->file_rgbpath)
+ {
+ from = X_CONFIG;
+ rgbPath = xstrdup (filesptr->file_rgbpath);
+ }
+ winMsg (from, "RgbPath set to \"%s\"\n", rgbPath);
+
+ return TRUE;
+}
+
+
+Bool
+winConfigOptions ()
+{
+ return TRUE;
+}
+
+
+Bool
+winConfigScreens ()
+{
+ return TRUE;
+}
+
+
+char *
+winSetStrOption (pointer optlist, const char *name, char *deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_STRING;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.str;
+ if (deflt)
+ return xstrdup (deflt);
+ else
+ return NULL;
+}
+
+
+int
+winSetBoolOption (pointer optlist, const char *name, int deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_BOOLEAN;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.bool;
+ return deflt;
+}
+
+
+int
+winSetIntOption (pointer optlist, const char *name, int deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_INTEGER;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.num;
+ return deflt;
+}
+
+
+double
+winSetRealOption (pointer optlist, const char *name, double deflt)
+{
+ OptionInfoRec o;
+
+ o.name = name;
+ o.type = OPTV_REAL;
+ if (ParseOptionValue (-1, optlist, &o))
+ deflt = o.value.realnum;
+ return deflt;
+}
+
+
+/*
+ * Compare two strings for equality. This is caseinsensitive and
+ * The characters '_', ' ' (space) and '\t' (tab) are treated as
+ * not existing.
+ */
+
+int
+winNameCompare (const char *s1, const char *s2)
+{
+ char c1, c2;
+
+ if (!s1 || *s1 == 0)
+ {
+ if (!s2 || *s2 == 0)
+ return 0;
+ else
+ return 1;
+ }
+
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+
+ c1 = (isupper (*s1) ? tolower (*s1) : *s1);
+ c2 = (isupper (*s2) ? tolower (*s2) : *s2);
+
+ while (c1 == c2)
+ {
+ if (c1 == 0)
+ return 0;
+ s1++;
+ s2++;
+
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+
+ c1 = (isupper (*s1) ? tolower (*s1) : *s1);
+ c2 = (isupper (*s2) ? tolower (*s2) : *s2);
+ }
+ return (c1 - c2);
+}
+
+
+/*
+ * Find the named option in the list.
+ * @return the pointer to the option record, or NULL if not found.
+ */
+
+XF86OptionPtr
+winFindOption (XF86OptionPtr list, const char *name)
+{
+ while (list)
+ {
+ if (winNameCompare (list->opt_name, name) == 0)
+ return list;
+ list = list->list.next;
+ }
+ return NULL;
+}
+
+
+/*
+ * Find the Value of an named option.
+ * @return The option value or NULL if not found.
+ */
+
+char *
+winFindOptionValue (XF86OptionPtr list, const char *name)
+{
+ list = winFindOption (list, name);
+ if (list)
+ {
+ if (list->opt_val)
+ return (list->opt_val);
+ else
+ return "";
+ }
+ return (NULL);
+}
+
+
+/*
+ * Parse the option.
+ */
+
+static Bool
+ParseOptionValue (int scrnIndex, pointer options, OptionInfoPtr p)
+{
+ char *s, *end;
+
+ if ((s = winFindOptionValue (options, p->name)) != NULL)
+ {
+ switch (p->type)
+ {
+ case OPTV_INTEGER:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires an integer value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ p->value.num = strtoul (s, &end, 0);
+ if (*end == '\0')
+ {
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires an integer value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ }
+ break;
+ case OPTV_STRING:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires an string value\n", p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ p->value.str = s;
+ p->found = TRUE;
+ }
+ break;
+ case OPTV_ANYSTR:
+ p->value.str = s;
+ p->found = TRUE;
+ break;
+ case OPTV_REAL:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a floating point value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ p->value.realnum = strtod (s, &end);
+ if (*end == '\0')
+ {
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a floating point value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ }
+ break;
+ case OPTV_BOOLEAN:
+ if (GetBoolValue (p, s))
+ {
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a boolean value\n", p->name);
+ p->found = FALSE;
+ }
+ break;
+ case OPTV_FREQ:
+ if (*s == '\0')
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ else
+ {
+ double freq = strtod (s, &end);
+ int units = 0;
+
+ if (end != s)
+ {
+ p->found = TRUE;
+ if (!winNameCompare (end, "Hz"))
+ units = 1;
+ else if (!winNameCompare (end, "kHz") ||
+ !winNameCompare (end, "k"))
+ units = 1000;
+ else if (!winNameCompare (end, "MHz") ||
+ !winNameCompare (end, "M"))
+ units = 1000000;
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ if (p->found)
+ freq *= (double) units;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a frequency value\n",
+ p->name);
+ p->found = FALSE;
+ }
+ if (p->found)
+ {
+ p->value.freq.freq = freq;
+ p->value.freq.units = units;
+ }
+ }
+ break;
+ case OPTV_NONE:
+ /* Should never get here */
+ p->found = FALSE;
+ break;
+ }
+ if (p->found)
+ {
+ winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", p->name);
+ if (!(p->type == OPTV_BOOLEAN && *s == 0))
+ {
+ winErrorFVerb (2, " \"%s\"", s);
+ }
+ winErrorFVerb (2, "\n");
+ }
+ }
+ else if (p->type == OPTV_BOOLEAN)
+ {
+ /* Look for matches with options with or without a "No" prefix. */
+ char *n, *newn;
+ OptionInfoRec opt;
+
+ n = winNormalizeName (p->name);
+ if (!n)
+ {
+ p->found = FALSE;
+ return FALSE;
+ }
+ if (strncmp (n, "no", 2) == 0)
+ {
+ newn = n + 2;
+ }
+ else
+ {
+ free (n);
+ n = malloc (strlen (p->name) + 2 + 1);
+ if (!n)
+ {
+ p->found = FALSE;
+ return FALSE;
+ }
+ strcpy (n, "No");
+ strcat (n, p->name);
+ newn = n;
+ }
+ if ((s = winFindOptionValue (options, newn)) != NULL)
+ {
+ if (GetBoolValue (&opt, s))
+ {
+ p->value.bool = !opt.value.bool;
+ p->found = TRUE;
+ }
+ else
+ {
+ winDrvMsg (scrnIndex, X_WARNING,
+ "Option \"%s\" requires a boolean value\n", newn);
+ p->found = FALSE;
+ }
+ }
+ else
+ {
+ p->found = FALSE;
+ }
+ if (p->found)
+ {
+ winDrvMsgVerb (scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn);
+ if (*s != 0)
+ {
+ winErrorFVerb (2, " \"%s\"", s);
+ }
+ winErrorFVerb (2, "\n");
+ }
+ free (n);
+ }
+ else
+ {
+ p->found = FALSE;
+ }
+ return p->found;
+}
+
+
+static Bool
+configLayout (serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout,
+ char *default_layout)
+{
+#if 0
+#pragma warn UNIMPLEMENTED
+#endif
+ return TRUE;
+}
+
+
+static Bool
+configImpliedLayout (serverLayoutPtr servlayoutp,
+ XF86ConfScreenPtr conf_screen)
+{
+#if 0
+#pragma warn UNIMPLEMENTED
+#endif
+ return TRUE;
+}
+
+
+static Bool
+GetBoolValue (OptionInfoPtr p, const char *s)
+{
+ if (*s == 0)
+ {
+ p->value.bool = TRUE;
+ }
+ else
+ {
+ if (winNameCompare (s, "1") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "on") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "true") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "yes") == 0)
+ p->value.bool = TRUE;
+ else if (winNameCompare (s, "0") == 0)
+ p->value.bool = FALSE;
+ else if (winNameCompare (s, "off") == 0)
+ p->value.bool = FALSE;
+ else if (winNameCompare (s, "false") == 0)
+ p->value.bool = FALSE;
+ else if (winNameCompare (s, "no") == 0)
+ p->value.bool = FALSE;
+ }
+ return TRUE;
+}
+
+
+char *
+winNormalizeName (const char *s)
+{
+ char *ret, *q;
+ const char *p;
+
+ if (s == NULL)
+ return NULL;
+
+ ret = malloc (strlen (s) + 1);
+ for (p = s, q = ret; *p != 0; p++)
+ {
+ switch (*p)
+ {
+ case '_':
+ case ' ':
+ case '\t':
+ continue;
+ default:
+ if (isupper (*p))
+ *q++ = tolower (*p);
+ else
+ *q++ = *p;
+ }
+ }
+ *q = '\0';
+ return ret;
+}
diff --git a/xc/programs/Xserver/hw/xwin/winconfig.h b/xc/programs/Xserver/hw/xwin/winconfig.h
new file mode 100644
index 000000000..d3099b373
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/winconfig.h
@@ -0,0 +1,332 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Alexander Gottwald
+ */
+/* $XFree86: xc/programs/Xserver/hw/xwin/winconfig.h,v 1.1 2002/10/17 08:18:22 alanh Exp $ */
+#ifndef __WIN_CONFIG_H__
+#define __WIN_CONFIG_H__
+
+#include "win.h"
+#include "../xfree86/parser/xf86Parser.h"
+
+
+/* These are taken from hw/xfree86/common/xf86str.h */
+
+typedef struct
+{
+ CARD32 red, green, blue;
+}
+rgb;
+
+
+typedef struct
+{
+ float red, green, blue;
+}
+Gamma;
+
+
+typedef struct
+{
+ char *identifier;
+ char *vendor;
+ char *board;
+ char *chipset;
+ char *ramdac;
+ char *driver;
+ struct _confscreenrec *myScreenSection;
+ Bool claimed;
+ Bool active;
+ Bool inUse;
+ int videoRam;
+ int textClockFreq;
+ pointer options;
+ int screen; /* For multi-CRTC cards */
+}
+GDevRec, *GDevPtr;
+
+
+typedef struct
+{
+ char *identifier;
+ char *driver;
+ pointer commonOptions;
+ pointer extraOptions;
+}
+IDevRec, *IDevPtr;
+
+
+typedef struct
+{
+ int frameX0;
+ int frameY0;
+ int virtualX;
+ int virtualY;
+ int depth;
+ int fbbpp;
+ rgb weight;
+ rgb blackColour;
+ rgb whiteColour;
+ int defaultVisual;
+ char **modes;
+ pointer options;
+}
+DispRec, *DispPtr;
+
+
+typedef struct _confxvportrec
+{
+ char *identifier;
+ pointer options;
+}
+confXvPortRec, *confXvPortPtr;
+
+
+typedef struct _confxvadaptrec
+{
+ char *identifier;
+ int numports;
+ confXvPortPtr ports;
+ pointer options;
+}
+confXvAdaptorRec, *confXvAdaptorPtr;
+
+
+typedef struct _confscreenrec
+{
+ char *id;
+ int screennum;
+ int defaultdepth;
+ int defaultbpp;
+ int defaultfbbpp;
+ GDevPtr device;
+ int numdisplays;
+ DispPtr displays;
+ int numxvadaptors;
+ confXvAdaptorPtr xvadaptors;
+ pointer options;
+}
+confScreenRec, *confScreenPtr;
+
+
+typedef enum
+{
+ PosObsolete = -1,
+ PosAbsolute = 0,
+ PosRightOf,
+ PosLeftOf,
+ PosAbove,
+ PosBelow,
+ PosRelative
+}
+PositionType;
+
+
+typedef struct _screenlayoutrec
+{
+ confScreenPtr screen;
+ char *topname;
+ confScreenPtr top;
+ char *bottomname;
+ confScreenPtr bottom;
+ char *leftname;
+ confScreenPtr left;
+ char *rightname;
+ confScreenPtr right;
+ PositionType where;
+ int x;
+ int y;
+ char *refname;
+ confScreenPtr refscreen;
+}
+screenLayoutRec, *screenLayoutPtr;
+
+
+typedef struct _serverlayoutrec
+{
+ char *id;
+ screenLayoutPtr screens;
+ GDevPtr inactives;
+ IDevPtr inputs;
+ pointer options;
+}
+serverLayoutRec, *serverLayoutPtr;
+
+
+/*
+ * winconfig.c
+ */
+
+typedef struct
+{
+ /* Files */
+ char *configFile;
+ char *fontPath;
+ char *rgbPath;
+ /* input devices - keyboard */
+ char *keyboard;
+#ifdef XKB
+ Bool noXkbExtension;
+ char *xkbMap;
+#endif
+ /* layout */
+ char *screenname;
+ /* mouse settings */
+ char *mouse;
+ Bool emulate3buttons;
+ long emulate3timeout;
+}
+WinCmdlineRec, *WinCmdlinePtr;
+
+
+extern WinCmdlineRec g_cmdline;
+
+extern XF86ConfigPtr g_xf86configptr;
+extern serverLayoutRec g_winConfigLayout;
+
+
+/*
+ * Function prototypes
+ */
+
+Bool winReadConfigfile (void);
+Bool winConfigFiles (void);
+Bool winConfigOptions (void);
+Bool winConfigScreens (void);
+Bool winConfigKeyboard (DeviceIntPtr pDevice);
+Bool winConfigMouse (DeviceIntPtr pDevice);
+
+
+typedef struct
+{
+ double freq;
+ int units;
+}
+OptFrequency;
+
+
+typedef union
+{
+ unsigned long num;
+ char *str;
+ double realnum;
+ Bool bool;
+ OptFrequency freq;
+}
+ValueUnion;
+
+
+typedef enum
+{
+ OPTV_NONE = 0,
+ OPTV_INTEGER,
+ OPTV_STRING, /* a non-empty string */
+ OPTV_ANYSTR, /* Any string, including an empty one */
+ OPTV_REAL,
+ OPTV_BOOLEAN,
+ OPTV_FREQ
+}
+OptionValueType;
+
+
+typedef enum
+{
+ OPTUNITS_HZ = 1,
+ OPTUNITS_KHZ,
+ OPTUNITS_MHZ
+}
+OptFreqUnits;
+
+
+typedef struct
+{
+ int token;
+ const char *name;
+ OptionValueType type;
+ ValueUnion value;
+ Bool found;
+}
+OptionInfoRec, *OptionInfoPtr;
+
+
+/*
+ * Function prototypes
+ */
+
+char *winSetStrOption (pointer optlist, const char *name, char *deflt);
+int winSetBoolOption (pointer optlist, const char *name, int deflt);
+int winSetIntOption (pointer optlist, const char *name, int deflt);
+double winSetRealOption (pointer optlist, const char *name, double deflt);
+
+XF86OptionPtr winFindOption (XF86OptionPtr list, const char *name);
+char *winFindOptionValue (XF86OptionPtr list, const char *name);
+int winNameCompare (const char *s1, const char *s2);
+char *winNormalizeName (const char *s);
+
+
+typedef struct
+{
+ struct
+ {
+ long leds;
+ long delay;
+ long rate;
+ }
+ keyboard;
+#ifdef XKB
+ struct
+ {
+ Bool disable;
+ char *rules;
+ char *model;
+ char *layout;
+ char *variant;
+ char *options;
+ char *initialMap;
+ char *keymap;
+ char *types;
+ char *compat;
+ char *keycodes;
+ char *symbols;
+ char *geometry;
+ }
+ xkb;
+#endif
+ struct
+ {
+ Bool emulate3Buttons;
+ long emulate3Timeout;
+ }
+ pointer;
+}
+winInfoRec, *winInfoPtr;
+
+
+extern winInfoRec g_winInfo;
+
+#endif
diff --git a/xc/programs/Xserver/hw/xwin/winmsg.c b/xc/programs/Xserver/hw/xwin/winmsg.c
new file mode 100644
index 000000000..35342c359
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/winmsg.c
@@ -0,0 +1,119 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Alexander Gottwald
+ */
+/* $XFree86: xc/programs/Xserver/hw/xwin/winmsg.c,v 1.1 2002/10/17 08:18:22 alanh Exp $ */
+
+#include "win.h"
+#include "winmsg.h"
+#include <stdarg.h>
+
+#ifndef VERBOSE_LEVEL
+#define VERBOSE_LEVEL 4
+#endif
+
+
+void winVMsg (int, MessageType, int verb, const char *, va_list);
+
+
+void
+winVMsg (int scrnIndex, MessageType type, int verb, const char *format,
+ va_list ap)
+{
+ const char *prefix = NULL;
+
+ if (verb && verb > VERBOSE_LEVEL)
+ return;
+
+#undef __msg
+#define __msg(name,string) case name: prefix = string; break;
+#undef _msg
+#define _msg(name,string) __msg(name,string)
+ switch (type)
+ {
+ MESSAGE_STRINGS default:prefix = NULL;
+ break;
+ }
+#undef __msg
+#undef _msg
+
+ if (prefix != NULL)
+ ErrorF ("%s ", prefix);
+ VErrorF (format, ap);
+}
+
+
+void
+winDrvMsg (int scrnIndex, MessageType type, const char *format, ...)
+{
+ va_list ap;
+ va_start (ap, format);
+ winVMsg (scrnIndex, type, 0, format, ap);
+ va_end (ap);
+}
+
+
+void
+winMsg (MessageType type, const char *format, ...)
+{
+ va_list ap;
+ va_start (ap, format);
+ winVMsg (0, type, 0, format, ap);
+ va_end (ap);
+}
+
+
+void
+winDrvMsgVerb (int scrnIndex, MessageType type, int verb, const char *format,
+ ...)
+{
+ va_list ap;
+ va_start (ap, format);
+ winVMsg (scrnIndex, type, verb, format, ap);
+ va_end (ap);
+}
+
+
+void
+winMsgVerb (MessageType type, int verb, const char *format, ...)
+{
+ va_list ap;
+ va_start (ap, format);
+ winVMsg (0, type, verb, format, ap);
+ va_end (ap);
+}
+
+
+void
+winErrorFVerb (int verb, const char *format, ...)
+{
+ va_list ap;
+ va_start (ap, format);
+ winVMsg (0, X_NONE, verb, format, ap);
+ va_end (ap);
+}
diff --git a/xc/programs/Xserver/hw/xwin/winmsg.h b/xc/programs/Xserver/hw/xwin/winmsg.h
new file mode 100644
index 000000000..c873d4beb
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/winmsg.h
@@ -0,0 +1,72 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Alexander Gottwald
+ */
+/* $XFree86: xc/programs/Xserver/hw/xwin/winmsg.h,v 1.1 2002/10/17 08:18:22 alanh Exp $ */
+
+#ifndef __WIN_MSG_H__
+#define __WIN_MSG_H__
+
+
+#define __msg_name(name,string) name
+#define __msg(name,string) __msg_name(name,string)
+#define _msg(name,string) __msg(name,string),
+
+#define MESSAGE_STRINGS \
+ _msg(X_PROBED,"(--)" /* Value was probed */)\
+ _msg(X_CONFIG,"(**)" /* Value was given in the config file */)\
+ _msg(X_DEFAULT,"(==)" /* Value is a default */)\
+ _msg(X_CMDLINE,"(++)" /* Value was given on the command line */)\
+ _msg(X_NOTICE,"(!!)" /* Notice */) \
+ _msg(X_ERROR,"(EE)" /* Error message */) \
+ _msg(X_WARNING,"(WW)" /* Warning message */) \
+ _msg(X_INFO,"(II)" /* Informational message */) \
+ _msg(X_UNKNOWN,"(?""?)" /* Unknown, trigraph fix */) \
+ _msg(X_NONE,NULL /* No prefix */) \
+ __msg(X_NOT_IMPLEMENTED,"(NI)" /* Not implemented */)
+
+typedef enum
+{
+ MESSAGE_STRINGS
+}
+MessageType;
+
+
+/*
+ * Function prototypes
+ */
+
+void winDrvMsgVerb (int scrnIndex,
+ MessageType type, int verb, const char *format, ...);
+void winDrvMsg (int scrnIndex, MessageType type, const char *format, ...);
+void winMsgVerb (MessageType type, int verb, const char *format, ...);
+void winMsg (MessageType type, const char *format, ...);
+
+void winErrorFVerb (int verb, const char *format, ...);
+
+#endif
diff --git a/xc/programs/Xserver/hw/xwin/winregistry.c b/xc/programs/Xserver/hw/xwin/winregistry.c
new file mode 100644
index 000000000..b31fcf641
--- /dev/null
+++ b/xc/programs/Xserver/hw/xwin/winregistry.c
@@ -0,0 +1,66 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the XFree86 Project
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from the XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+/* $XFree86: xc/programs/Xserver/hw/xwin/winregistry.c,v 1.1 2002/07/05 09:19:26 alanh Exp $ */
+
+#include "win.h"
+
+
+DWORD
+winGetRegistryDWORD (HKEY hkey, char *pszRegistryKey)
+{
+ HKEY hkResult;
+ DWORD dwDisposition;
+
+ RegCreateKeyEx (hkey,
+ pszRegistryKey,
+ 0,
+ '\0',
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ,
+ NULL,
+ &hkResult,
+ &dwDisposition);
+
+ if (dwDisposition == REG_CREATED_NEW_KEY)
+ {
+ ErrorF ("winGetRegistryDWORD - Created new key: %s\n", pszRegistryKey);
+ }
+ else if (dwDisposition == REG_OPENED_EXISTING_KEY)
+ {
+ ErrorF ("winGetRegistryDWORD - Opened existing key: %s\n",
+ pszRegistryKey);
+ }
+
+ /* Free the registry key handle */
+ RegCloseKey (hkResult);
+ hkResult = NULL;
+
+ return 0;
+}