First import
[xorg_rtime.git] / xorg-server-1.4 / hw / darwin / quartz / cr / crFrame.m
blob2b8e57d0ada12b12cf54bd7e55b8f13c33efbdac
1 /*
2  * Cocoa rootless implementation frame functions
3  */
4 /*
5  * Copyright (c) 2001 Greg Parker. All Rights Reserved.
6  * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  * Except as contained in this notice, the name(s) of the above copyright
27  * holders shall not be used in advertising or otherwise to promote the sale,
28  * use or other dealings in this Software without prior written authorization.
29  */
30 /* $XdotOrg: xc/programs/Xserver/hw/darwin/quartz/cr/crFrame.m,v 1.2 2004/04/23 19:15:51 eich Exp $ */
31 /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/cr/crFrame.m,v 1.9 2004/03/19 02:05:29 torrey Exp $ */
32 #ifdef HAVE_XORG_CONFIG_H
33 #include <xorg-config.h>
34 #endif
35 #include "quartz/quartzCommon.h"
36 #include "quartz/cr/cr.h"
38 #undef BOOL
39 #define BOOL xBOOL
40 #include "rootless.h"
41 #include "quartz/applewmExt.h"
42 #include "windowstr.h"
43 #undef BOOL
45 WindowPtr nextWindowToFrame = NULL;
46 unsigned int nextWindowStyle = 0;
48 static void CRReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
52  * CRCreateFrame
53  *  Create a new physical window.
54  *  Rootless windows must not autodisplay! Autodisplay can cause a deadlock.
55  *    Event thread - autodisplay: locks view hierarchy, then window
56  *    X Server thread - window resize: locks window, then view hierarchy
57  *  Deadlock occurs if each thread gets one lock and waits for the other.
58  */
59 static Bool
60 CRCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
61               int newX, int newY, RegionPtr pShape)
63     CRWindowPtr crWinPtr;
64     NSRect bounds;
65     NSWindow *theWindow;
66     XView *theView;
67     unsigned int theStyleMask = NSBorderlessWindowMask;
69     crWinPtr = (CRWindowPtr) xalloc(sizeof(CRWindowRec));
71     bounds = NSMakeRect(newX,
72                         NSHeight([[NSScreen mainScreen] frame]) -
73                         newY - pFrame->height,
74                         pFrame->width, pFrame->height);
76     // Check if AppleWM has specified a style for this window
77     if (pFrame->win == nextWindowToFrame) {
78         theStyleMask = nextWindowStyle;
79     }
80     nextWindowToFrame = NULL;
82     // Create an NSWindow for the new X11 window
83     theWindow = [[NSWindow alloc] initWithContentRect:bounds
84                                   styleMask:theStyleMask
85                                   backing:NSBackingStoreBuffered
86 #ifdef DEFER_NSWINDOW
87                                   defer:YES];
88 #else
89                                   defer:NO];
90 #endif
92     if (!theWindow) return FALSE;
94     [theWindow setBackgroundColor:[NSColor clearColor]];  // erase transparent
95     [theWindow setAlphaValue:1.0];       // draw opaque
96     [theWindow setOpaque:YES];           // changed when window is shaped
98     [theWindow useOptimizedDrawing:YES]; // Has no overlapping sub-views
99     [theWindow setAutodisplay:NO];       // See comment above
100     [theWindow disableFlushWindow];      // We do all the flushing manually
101     [theWindow setHasShadow:YES];        // All windows have shadows
102     [theWindow setReleasedWhenClosed:YES]; // Default, but we want to be sure
104     theView = [[XView alloc] initWithFrame:bounds];
105     [theWindow setContentView:theView];
106     [theWindow setInitialFirstResponder:theView];
108 #ifdef DEFER_NSWINDOW
109     // We need the NSWindow to actually be created now.
110     // If we had to defer creating it, we have to order it
111     // onto the screen to force it to be created.
113     if (pFrame->win->prevSib) {
114         CRWindowPtr crWinPtr = (CRWindowPtr) RootlessFrameForWindow(
115                                                 pFrame->win->prevSib, FALSE);
116         int upperNum = [crWinPtr->window windowNumber];
117         [theWindow orderWindow:NSWindowBelow relativeTo:upperNum];
118     } else {
119         [theWindow orderFront:nil];
120     }
121 #endif
123     [theWindow setAcceptsMouseMovedEvents:YES];
125     crWinPtr->window = theWindow;
126     crWinPtr->view = theView;
128     [theView lockFocus];
129     // Fill the window with white to make sure alpha channel is set
130     NSEraseRect(bounds);
131     crWinPtr->port = [theView qdPort];
132     crWinPtr->context = [[NSGraphicsContext currentContext] graphicsPort];
133     // CreateCGContextForPort(crWinPtr->port, &crWinPtr->context);
134     [theView unlockFocus];
136     // Store the implementation private frame ID
137     pFrame->wid = (RootlessFrameID) crWinPtr;
139     // Reshape the frame if it was created shaped.
140     if (pShape != NULL)
141         CRReshapeFrame(pFrame->wid, pShape);
143     return TRUE;
148  * CRDestroyFrame
149  *  Destroy a frame.
150  */
151 static void
152 CRDestroyFrame(RootlessFrameID wid)
154     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
156     [crWinPtr->window orderOut:nil];
157     [crWinPtr->window close];
158     [crWinPtr->view release];
159     free(crWinPtr);
164  * CRMoveFrame
165  *  Move a frame on screen.
166  */
167 static void
168 CRMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
170     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
171     NSPoint topLeft;
173     topLeft = NSMakePoint(newX,
174                           NSHeight([[NSScreen mainScreen] frame]) - newY);
176     [crWinPtr->window setFrameTopLeftPoint:topLeft];
181  * CRResizeFrame
182  *  Move and resize a frame.
183  */
184 static void
185 CRResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
186               int newX, int newY, unsigned int newW, unsigned int newH,
187               unsigned int gravity)
189     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
190     NSRect bounds = NSMakeRect(newX, NSHeight([[NSScreen mainScreen] frame]) -
191                                newY - newH, newW, newH);
193     [crWinPtr->window setFrame:bounds display:NO];
198  * CRRestackFrame
199  *  Change the frame order. Put the frame behind nextWid or on top if
200  *  it is NULL. Unmapped frames are mapped by restacking them.
201  */
202 static void
203 CRRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
205     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
206     CRWindowPtr crNextWinPtr = (CRWindowPtr) nextWid;
208     if (crNextWinPtr) {
209         int upperNum = [crNextWinPtr->window windowNumber];
211         [crWinPtr->window orderWindow:NSWindowBelow relativeTo:upperNum];
212     } else {
213         [crWinPtr->window makeKeyAndOrderFront:nil];
214     }
219  * CRReshapeFrame
220  *  Set the shape of a frame.
221  */
222 static void
223 CRReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
225     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
226     NSRect bounds = [crWinPtr->view frame];
227     int winHeight = NSHeight(bounds);
228     BoxRec localBox = {0, 0, NSWidth(bounds), winHeight};
230     [crWinPtr->view lockFocus];
232     if (pShape != NULL) {
233         // Calculate the region outside the new shape.
234         miInverse(pShape, pShape, &localBox);
235     }
237     // If window is currently shaped we need to undo the previous shape.
238     if (![crWinPtr->window isOpaque]) {
239         [[NSColor whiteColor] set];
240         NSRectFillUsingOperation(bounds, NSCompositeDestinationAtop);
241     }
243     if (pShape != NULL) {
244         int count = REGION_NUM_RECTS(pShape);
245         BoxRec *extRects = REGION_RECTS(pShape);
246         BoxRec *rects, *end;
248         // Make transparent if window is now shaped.
249         [crWinPtr->window setOpaque:NO];
251         // Clear the areas outside the window shape
252         [[NSColor clearColor] set];
253         for (rects = extRects, end = extRects+count; rects < end; rects++) {
254             int rectHeight = rects->y2 - rects->y1;
255             NSRectFill( NSMakeRect(rects->x1,
256                                    winHeight - rects->y1 - rectHeight,
257                                    rects->x2 - rects->x1, rectHeight) );
258         }
259         [[NSGraphicsContext currentContext] flushGraphics];
261         // force update of window shadow
262         [crWinPtr->window setHasShadow:NO];
263         [crWinPtr->window setHasShadow:YES];
265     } else {
266         [crWinPtr->window setOpaque:YES];
267         [[NSGraphicsContext currentContext] flushGraphics];
268     }
270     [crWinPtr->view unlockFocus];
275  * CRUnmapFrame
276  *  Unmap a frame.
277  */
278 static void
279 CRUnmapFrame(RootlessFrameID wid)
281     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
283     [crWinPtr->window orderOut:nil];
288  * CRStartDrawing
289  *  When a window's buffer is not being drawn to, the CoreGraphics
290  *  window server may compress or move it. Call this routine
291  *  to lock down the buffer during direct drawing. It returns
292  *  a pointer to the backing buffer.
293  */
294 static void
295 CRStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
297     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
298     PixMapHandle pix;
300     [crWinPtr->view lockFocus];
301     crWinPtr->port = [crWinPtr->view qdPort];
302     LockPortBits(crWinPtr->port);
303     [crWinPtr->view unlockFocus];
304     pix = GetPortPixMap(crWinPtr->port);
306     *pixelData = GetPixBaseAddr(pix);
307     *bytesPerRow = GetPixRowBytes(pix) & 0x3fff; // fixme is mask needed?
312  * CRStopDrawing
313  *  When direct access to a window's buffer is no longer needed, this
314  *  routine should be called to allow CoreGraphics to compress or
315  *  move it.
316  */
317 static void
318 CRStopDrawing(RootlessFrameID wid, Bool flush)
320     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
322     UnlockPortBits(crWinPtr->port);
324     if (flush) {
325         QDFlushPortBuffer(crWinPtr->port, NULL);
326     }
331  * CRUpdateRegion
332  *  Flush a region from a window's backing buffer to the screen.
333  */
334 static void
335 CRUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
337     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
339 #ifdef ROOTLESS_TRACK_DAMAGE
340     int count = REGION_NUM_RECTS(pDamage);
341     BoxRec *rects = REGION_RECTS(pDamage);
342     BoxRec *end;
344     static RgnHandle rgn = NULL;
345     static RgnHandle box = NULL;
347     if (!rgn) rgn = NewRgn();
348     if (!box) box = NewRgn();
350     for (end = rects+count; rects < end; rects++) {
351         Rect qdRect;
352         qdRect.left = rects->x1;
353         qdRect.top = rects->y1;
354         qdRect.right = rects->x2;
355         qdRect.bottom = rects->y2;
357         RectRgn(box, &qdRect);
358         UnionRgn(rgn, box, rgn);
359     }
361     QDFlushPortBuffer(crWinPtr->port, rgn);
363     SetEmptyRgn(rgn);
364     SetEmptyRgn(box);
366 #else   /* !ROOTLESS_TRACK_DAMAGE */
367     QDFlushPortBuffer(crWinPtr->port, NULL);
368 #endif
373  * CRDamageRects
374  *  Mark damaged rectangles as requiring redisplay to screen.
375  */
376 static void
377 CRDamageRects(RootlessFrameID wid, int count, const BoxRec *rects,
378                int shift_x, int shift_y)
380     CRWindowPtr crWinPtr = (CRWindowPtr) wid;
381     const BoxRec *end;
383     for (end = rects + count; rects < end; rects++) {
384         Rect qdRect;
385         qdRect.left = rects->x1 + shift_x;
386         qdRect.top = rects->y1 + shift_y;
387         qdRect.right = rects->x2 + shift_x;
388         qdRect.bottom = rects->y2 + shift_y;
390         QDAddRectToDirtyRegion(crWinPtr->port, &qdRect);
391     }
396  * Called to check if the frame should be reordered when it is restacked.
397  */
398 Bool CRDoReorderWindow(RootlessWindowPtr pFrame)
400     WindowPtr pWin = pFrame->win;
402     return AppleWMDoReorderWindow(pWin);
406 static RootlessFrameProcsRec CRRootlessProcs = {
407     CRCreateFrame,
408     CRDestroyFrame,
409     CRMoveFrame,
410     CRResizeFrame,
411     CRRestackFrame,
412     CRReshapeFrame,
413     CRUnmapFrame,
414     CRStartDrawing,
415     CRStopDrawing,
416     CRUpdateRegion,
417     CRDamageRects,
418     NULL,
419     CRDoReorderWindow,
420     NULL,
421     NULL,
422     NULL,
423     NULL
428  * Initialize CR implementation
429  */
430 Bool
431 CRInit(ScreenPtr pScreen)
433     RootlessInit(pScreen, &CRRootlessProcs);
435     rootless_CopyBytes_threshold = 0;
436     rootless_FillBytes_threshold = 0;
437     rootless_CompositePixels_threshold = 0;
438     rootless_CopyWindow_threshold = 0;
440     return TRUE;