2 * Cocoa rootless implementation frame functions
5 * Copyright (c) 2001 Greg Parker. All Rights Reserved.
6 * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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.
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.
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>
35 #include "quartz/quartzCommon.h"
36 #include "quartz/cr/cr.h"
41 #include "quartz/applewmExt.h"
42 #include "windowstr.h"
45 WindowPtr nextWindowToFrame = NULL;
46 unsigned int nextWindowStyle = 0;
48 static void CRReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
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.
60 CRCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
61 int newX, int newY, RegionPtr pShape)
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;
80 nextWindowToFrame = NULL;
82 // Create an NSWindow for the new X11 window
83 theWindow = [[NSWindow alloc] initWithContentRect:bounds
84 styleMask:theStyleMask
85 backing:NSBackingStoreBuffered
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];
119 [theWindow orderFront:nil];
123 [theWindow setAcceptsMouseMovedEvents:YES];
125 crWinPtr->window = theWindow;
126 crWinPtr->view = theView;
129 // Fill the window with white to make sure alpha channel is set
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.
141 CRReshapeFrame(pFrame->wid, pShape);
152 CRDestroyFrame(RootlessFrameID wid)
154 CRWindowPtr crWinPtr = (CRWindowPtr) wid;
156 [crWinPtr->window orderOut:nil];
157 [crWinPtr->window close];
158 [crWinPtr->view release];
165 * Move a frame on screen.
168 CRMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
170 CRWindowPtr crWinPtr = (CRWindowPtr) wid;
173 topLeft = NSMakePoint(newX,
174 NSHeight([[NSScreen mainScreen] frame]) - newY);
176 [crWinPtr->window setFrameTopLeftPoint:topLeft];
182 * Move and resize a frame.
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];
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.
203 CRRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
205 CRWindowPtr crWinPtr = (CRWindowPtr) wid;
206 CRWindowPtr crNextWinPtr = (CRWindowPtr) nextWid;
209 int upperNum = [crNextWinPtr->window windowNumber];
211 [crWinPtr->window orderWindow:NSWindowBelow relativeTo:upperNum];
213 [crWinPtr->window makeKeyAndOrderFront:nil];
220 * Set the shape of a frame.
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);
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);
243 if (pShape != NULL) {
244 int count = REGION_NUM_RECTS(pShape);
245 BoxRec *extRects = REGION_RECTS(pShape);
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) );
259 [[NSGraphicsContext currentContext] flushGraphics];
261 // force update of window shadow
262 [crWinPtr->window setHasShadow:NO];
263 [crWinPtr->window setHasShadow:YES];
266 [crWinPtr->window setOpaque:YES];
267 [[NSGraphicsContext currentContext] flushGraphics];
270 [crWinPtr->view unlockFocus];
279 CRUnmapFrame(RootlessFrameID wid)
281 CRWindowPtr crWinPtr = (CRWindowPtr) wid;
283 [crWinPtr->window orderOut:nil];
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.
295 CRStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
297 CRWindowPtr crWinPtr = (CRWindowPtr) wid;
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?
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
318 CRStopDrawing(RootlessFrameID wid, Bool flush)
320 CRWindowPtr crWinPtr = (CRWindowPtr) wid;
322 UnlockPortBits(crWinPtr->port);
325 QDFlushPortBuffer(crWinPtr->port, NULL);
332 * Flush a region from a window's backing buffer to the screen.
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);
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++) {
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);
361 QDFlushPortBuffer(crWinPtr->port, rgn);
366 #else /* !ROOTLESS_TRACK_DAMAGE */
367 QDFlushPortBuffer(crWinPtr->port, NULL);
374 * Mark damaged rectangles as requiring redisplay to screen.
377 CRDamageRects(RootlessFrameID wid, int count, const BoxRec *rects,
378 int shift_x, int shift_y)
380 CRWindowPtr crWinPtr = (CRWindowPtr) wid;
383 for (end = rects + count; rects < end; rects++) {
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);
396 * Called to check if the frame should be reordered when it is restacked.
398 Bool CRDoReorderWindow(RootlessWindowPtr pFrame)
400 WindowPtr pWin = pFrame->win;
402 return AppleWMDoReorderWindow(pWin);
406 static RootlessFrameProcsRec CRRootlessProcs = {
428 * Initialize CR implementation
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;