2 * MACDRV Cocoa window code
4 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #import "cocoa_window.h"
23 #include "macdrv_cocoa.h"
27 static NSUInteger style_mask_for_features(const struct macdrv_window_features* wf)
29 NSUInteger style_mask;
33 style_mask = NSTitledWindowMask;
34 if (wf->close_button) style_mask |= NSClosableWindowMask;
35 if (wf->minimize_button) style_mask |= NSMiniaturizableWindowMask;
36 if (wf->resizable) style_mask |= NSResizableWindowMask;
37 if (wf->utility) style_mask |= NSUtilityWindowMask;
39 else style_mask = NSBorderlessWindowMask;
45 static BOOL frame_intersects_screens(NSRect frame, NSArray* screens)
48 for (screen in screens)
50 if (NSIntersectsRect(frame, [screen frame]))
57 @interface WineContentView : NSView
61 @interface WineWindow ()
63 + (void) flipRect:(NSRect*)rect;
68 @implementation WineContentView
78 @implementation WineWindow
80 + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)wf
81 windowFrame:(NSRect)window_frame
84 WineContentView* contentView;
86 [self flipRect:&window_frame];
88 window = [[[self alloc] initWithContentRect:window_frame
89 styleMask:style_mask_for_features(wf)
90 backing:NSBackingStoreBuffered
91 defer:YES] autorelease];
93 /* Standardize windows to eliminate differences between titled and
94 borderless windows and between NSWindow and NSPanel. */
95 [window setHidesOnDeactivate:NO];
96 [window setReleasedWhenClosed:NO];
98 [window disableCursorRects];
99 [window setShowsResizeIndicator:NO];
100 [window setHasShadow:wf->shadow];
101 [window setDelegate:window];
103 contentView = [[[WineContentView alloc] initWithFrame:NSZeroRect] autorelease];
106 [contentView setAutoresizesSubviews:NO];
108 [window setContentView:contentView];
113 + (void) flipRect:(NSRect*)rect
115 rect->origin.y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - NSMaxY(*rect);
118 - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
120 [self setStyleMask:style_mask_for_features(wf)];
121 [self setHasShadow:wf->shadow];
124 /* Returns whether or not the window was ordered in, which depends on if
125 its frame intersects any screen. */
126 - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next
128 BOOL on_screen = frame_intersects_screens([self frame], [NSScreen screens]);
131 [NSApp transformProcessToForeground];
134 [self orderWindow:NSWindowBelow relativeTo:[prev windowNumber]];
136 [self orderWindow:NSWindowAbove relativeTo:[next windowNumber]];
142 - (BOOL) setFrameIfOnScreen:(NSRect)contentRect
144 NSArray* screens = [NSScreen screens];
145 BOOL on_screen = [self isVisible];
146 NSRect frame, oldFrame;
148 if (![screens count]) return on_screen;
150 /* Origin is (left, top) in a top-down space. Need to convert it to
151 (left, bottom) in a bottom-up space. */
152 [[self class] flipRect:&contentRect];
156 on_screen = frame_intersects_screens(contentRect, screens);
161 oldFrame = [self frame];
162 frame = [self frameRectForContentRect:contentRect];
163 if (!NSEqualRects(frame, oldFrame))
165 if (NSEqualSizes(frame.size, oldFrame.size))
166 [self setFrameOrigin:frame.origin];
168 [self setFrame:frame display:YES];
176 * ---------- NSWindow method overrides ----------
178 - (BOOL) canBecomeKeyWindow
183 - (BOOL) canBecomeMainWindow
185 return [self canBecomeKeyWindow];
190 * ---------- NSWindowDelegate methods ----------
192 - (BOOL)windowShouldClose:(id)sender
200 /***********************************************************************
201 * macdrv_create_cocoa_window
203 * Create a Cocoa window with the given content frame and features (e.g.
204 * title bar, close box, etc.).
206 macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf,
209 __block WineWindow* window;
212 window = [[WineWindow createWindowWithFeatures:wf
213 windowFrame:NSRectFromCGRect(frame)] retain];
216 return (macdrv_window)window;
219 /***********************************************************************
220 * macdrv_destroy_cocoa_window
222 * Destroy a Cocoa window.
224 void macdrv_destroy_cocoa_window(macdrv_window w)
226 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
227 WineWindow* window = (WineWindow*)w;
235 /***********************************************************************
236 * macdrv_set_cocoa_window_features
238 * Update a Cocoa window's features.
240 void macdrv_set_cocoa_window_features(macdrv_window w,
241 const struct macdrv_window_features* wf)
243 WineWindow* window = (WineWindow*)w;
246 [window setWindowFeatures:wf];
250 /***********************************************************************
251 * macdrv_set_cocoa_window_title
253 * Set a Cocoa window's title.
255 void macdrv_set_cocoa_window_title(macdrv_window w, const unsigned short* title,
258 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
259 WineWindow* window = (WineWindow*)w;
260 NSString* titleString;
263 titleString = [NSString stringWithCharacters:title length:length];
267 [window setTitle:titleString];
273 /***********************************************************************
274 * macdrv_order_cocoa_window
276 * Reorder a Cocoa window relative to other windows. If prev is
277 * non-NULL, it is ordered below that window. Else, if next is non-NULL,
278 * it is ordered above that window. Otherwise, it is ordered to the
281 * Returns true if the window has actually been ordered onto the screen
282 * (i.e. if its frame intersects with a screen). Otherwise, false.
284 int macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev,
287 WineWindow* window = (WineWindow*)w;
288 __block BOOL on_screen;
291 on_screen = [window orderBelow:(WineWindow*)prev
292 orAbove:(WineWindow*)next];
298 /***********************************************************************
299 * macdrv_hide_cocoa_window
301 * Hides a Cocoa window.
303 void macdrv_hide_cocoa_window(macdrv_window w)
305 WineWindow* window = (WineWindow*)w;
308 [window orderOut:nil];
312 /***********************************************************************
313 * macdrv_set_cocoa_window_frame
315 * Move a Cocoa window. If the window has been moved out of the bounds
316 * of the desktop, it is ordered out. (This routine won't ever order a
317 * window in, though.)
319 * Returns true if the window is on screen; false otherwise.
321 int macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame)
323 WineWindow* window = (WineWindow*)w;
324 __block BOOL on_screen;
327 on_screen = [window setFrameIfOnScreen:NSRectFromCGRect(*new_frame)];