mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-11 01:30:32 +00:00
332 lines
8.9 KiB
Mathematica
332 lines
8.9 KiB
Mathematica
|
/*
|
||
|
* MACDRV Cocoa window code
|
||
|
*
|
||
|
* Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation; either
|
||
|
* version 2.1 of the License, or (at your option) any later version.
|
||
|
*
|
||
|
* This library is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public
|
||
|
* License along with this library; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||
|
*/
|
||
|
|
||
|
#import "cocoa_window.h"
|
||
|
|
||
|
#include "macdrv_cocoa.h"
|
||
|
#import "cocoa_app.h"
|
||
|
|
||
|
|
||
|
static NSUInteger style_mask_for_features(const struct macdrv_window_features* wf)
|
||
|
{
|
||
|
NSUInteger style_mask;
|
||
|
|
||
|
if (wf->title_bar)
|
||
|
{
|
||
|
style_mask = NSTitledWindowMask;
|
||
|
if (wf->close_button) style_mask |= NSClosableWindowMask;
|
||
|
if (wf->minimize_button) style_mask |= NSMiniaturizableWindowMask;
|
||
|
if (wf->resizable) style_mask |= NSResizableWindowMask;
|
||
|
if (wf->utility) style_mask |= NSUtilityWindowMask;
|
||
|
}
|
||
|
else style_mask = NSBorderlessWindowMask;
|
||
|
|
||
|
return style_mask;
|
||
|
}
|
||
|
|
||
|
|
||
|
static BOOL frame_intersects_screens(NSRect frame, NSArray* screens)
|
||
|
{
|
||
|
NSScreen* screen;
|
||
|
for (screen in screens)
|
||
|
{
|
||
|
if (NSIntersectsRect(frame, [screen frame]))
|
||
|
return TRUE;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
@interface WineContentView : NSView
|
||
|
@end
|
||
|
|
||
|
|
||
|
@interface WineWindow ()
|
||
|
|
||
|
+ (void) flipRect:(NSRect*)rect;
|
||
|
|
||
|
@end
|
||
|
|
||
|
|
||
|
@implementation WineContentView
|
||
|
|
||
|
- (BOOL) isFlipped
|
||
|
{
|
||
|
return YES;
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
|
||
|
@implementation WineWindow
|
||
|
|
||
|
+ (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)wf
|
||
|
windowFrame:(NSRect)window_frame
|
||
|
{
|
||
|
WineWindow* window;
|
||
|
WineContentView* contentView;
|
||
|
|
||
|
[self flipRect:&window_frame];
|
||
|
|
||
|
window = [[[self alloc] initWithContentRect:window_frame
|
||
|
styleMask:style_mask_for_features(wf)
|
||
|
backing:NSBackingStoreBuffered
|
||
|
defer:YES] autorelease];
|
||
|
|
||
|
/* Standardize windows to eliminate differences between titled and
|
||
|
borderless windows and between NSWindow and NSPanel. */
|
||
|
[window setHidesOnDeactivate:NO];
|
||
|
[window setReleasedWhenClosed:NO];
|
||
|
|
||
|
[window disableCursorRects];
|
||
|
[window setShowsResizeIndicator:NO];
|
||
|
[window setHasShadow:wf->shadow];
|
||
|
[window setDelegate:window];
|
||
|
|
||
|
contentView = [[[WineContentView alloc] initWithFrame:NSZeroRect] autorelease];
|
||
|
if (!contentView)
|
||
|
return nil;
|
||
|
[contentView setAutoresizesSubviews:NO];
|
||
|
|
||
|
[window setContentView:contentView];
|
||
|
|
||
|
return window;
|
||
|
}
|
||
|
|
||
|
+ (void) flipRect:(NSRect*)rect
|
||
|
{
|
||
|
rect->origin.y = NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - NSMaxY(*rect);
|
||
|
}
|
||
|
|
||
|
- (void) setWindowFeatures:(const struct macdrv_window_features*)wf
|
||
|
{
|
||
|
[self setStyleMask:style_mask_for_features(wf)];
|
||
|
[self setHasShadow:wf->shadow];
|
||
|
}
|
||
|
|
||
|
/* Returns whether or not the window was ordered in, which depends on if
|
||
|
its frame intersects any screen. */
|
||
|
- (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next
|
||
|
{
|
||
|
BOOL on_screen = frame_intersects_screens([self frame], [NSScreen screens]);
|
||
|
if (on_screen)
|
||
|
{
|
||
|
[NSApp transformProcessToForeground];
|
||
|
|
||
|
if (prev)
|
||
|
[self orderWindow:NSWindowBelow relativeTo:[prev windowNumber]];
|
||
|
else
|
||
|
[self orderWindow:NSWindowAbove relativeTo:[next windowNumber]];
|
||
|
}
|
||
|
|
||
|
return on_screen;
|
||
|
}
|
||
|
|
||
|
- (BOOL) setFrameIfOnScreen:(NSRect)contentRect
|
||
|
{
|
||
|
NSArray* screens = [NSScreen screens];
|
||
|
BOOL on_screen = [self isVisible];
|
||
|
NSRect frame, oldFrame;
|
||
|
|
||
|
if (![screens count]) return on_screen;
|
||
|
|
||
|
/* Origin is (left, top) in a top-down space. Need to convert it to
|
||
|
(left, bottom) in a bottom-up space. */
|
||
|
[[self class] flipRect:&contentRect];
|
||
|
|
||
|
if (on_screen)
|
||
|
{
|
||
|
on_screen = frame_intersects_screens(contentRect, screens);
|
||
|
if (!on_screen)
|
||
|
[self orderOut:nil];
|
||
|
}
|
||
|
|
||
|
oldFrame = [self frame];
|
||
|
frame = [self frameRectForContentRect:contentRect];
|
||
|
if (!NSEqualRects(frame, oldFrame))
|
||
|
{
|
||
|
if (NSEqualSizes(frame.size, oldFrame.size))
|
||
|
[self setFrameOrigin:frame.origin];
|
||
|
else
|
||
|
[self setFrame:frame display:YES];
|
||
|
}
|
||
|
|
||
|
return on_screen;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ---------- NSWindow method overrides ----------
|
||
|
*/
|
||
|
- (BOOL) canBecomeKeyWindow
|
||
|
{
|
||
|
return YES;
|
||
|
}
|
||
|
|
||
|
- (BOOL) canBecomeMainWindow
|
||
|
{
|
||
|
return [self canBecomeKeyWindow];
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ---------- NSWindowDelegate methods ----------
|
||
|
*/
|
||
|
- (BOOL)windowShouldClose:(id)sender
|
||
|
{
|
||
|
return NO;
|
||
|
}
|
||
|
|
||
|
@end
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* macdrv_create_cocoa_window
|
||
|
*
|
||
|
* Create a Cocoa window with the given content frame and features (e.g.
|
||
|
* title bar, close box, etc.).
|
||
|
*/
|
||
|
macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf,
|
||
|
CGRect frame)
|
||
|
{
|
||
|
__block WineWindow* window;
|
||
|
|
||
|
OnMainThread(^{
|
||
|
window = [[WineWindow createWindowWithFeatures:wf
|
||
|
windowFrame:NSRectFromCGRect(frame)] retain];
|
||
|
});
|
||
|
|
||
|
return (macdrv_window)window;
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
* macdrv_destroy_cocoa_window
|
||
|
*
|
||
|
* Destroy a Cocoa window.
|
||
|
*/
|
||
|
void macdrv_destroy_cocoa_window(macdrv_window w)
|
||
|
{
|
||
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||
|
WineWindow* window = (WineWindow*)w;
|
||
|
|
||
|
[window close];
|
||
|
[window release];
|
||
|
|
||
|
[pool release];
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
* macdrv_set_cocoa_window_features
|
||
|
*
|
||
|
* Update a Cocoa window's features.
|
||
|
*/
|
||
|
void macdrv_set_cocoa_window_features(macdrv_window w,
|
||
|
const struct macdrv_window_features* wf)
|
||
|
{
|
||
|
WineWindow* window = (WineWindow*)w;
|
||
|
|
||
|
OnMainThread(^{
|
||
|
[window setWindowFeatures:wf];
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
* macdrv_set_cocoa_window_title
|
||
|
*
|
||
|
* Set a Cocoa window's title.
|
||
|
*/
|
||
|
void macdrv_set_cocoa_window_title(macdrv_window w, const unsigned short* title,
|
||
|
size_t length)
|
||
|
{
|
||
|
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||
|
WineWindow* window = (WineWindow*)w;
|
||
|
NSString* titleString;
|
||
|
|
||
|
if (title)
|
||
|
titleString = [NSString stringWithCharacters:title length:length];
|
||
|
else
|
||
|
titleString = @"";
|
||
|
OnMainThreadAsync(^{
|
||
|
[window setTitle:titleString];
|
||
|
});
|
||
|
|
||
|
[pool release];
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
* macdrv_order_cocoa_window
|
||
|
*
|
||
|
* Reorder a Cocoa window relative to other windows. If prev is
|
||
|
* non-NULL, it is ordered below that window. Else, if next is non-NULL,
|
||
|
* it is ordered above that window. Otherwise, it is ordered to the
|
||
|
* front.
|
||
|
*
|
||
|
* Returns true if the window has actually been ordered onto the screen
|
||
|
* (i.e. if its frame intersects with a screen). Otherwise, false.
|
||
|
*/
|
||
|
int macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev,
|
||
|
macdrv_window next)
|
||
|
{
|
||
|
WineWindow* window = (WineWindow*)w;
|
||
|
__block BOOL on_screen;
|
||
|
|
||
|
OnMainThread(^{
|
||
|
on_screen = [window orderBelow:(WineWindow*)prev
|
||
|
orAbove:(WineWindow*)next];
|
||
|
});
|
||
|
|
||
|
return on_screen;
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
* macdrv_hide_cocoa_window
|
||
|
*
|
||
|
* Hides a Cocoa window.
|
||
|
*/
|
||
|
void macdrv_hide_cocoa_window(macdrv_window w)
|
||
|
{
|
||
|
WineWindow* window = (WineWindow*)w;
|
||
|
|
||
|
OnMainThread(^{
|
||
|
[window orderOut:nil];
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/***********************************************************************
|
||
|
* macdrv_set_cocoa_window_frame
|
||
|
*
|
||
|
* Move a Cocoa window. If the window has been moved out of the bounds
|
||
|
* of the desktop, it is ordered out. (This routine won't ever order a
|
||
|
* window in, though.)
|
||
|
*
|
||
|
* Returns true if the window is on screen; false otherwise.
|
||
|
*/
|
||
|
int macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame)
|
||
|
{
|
||
|
WineWindow* window = (WineWindow*)w;
|
||
|
__block BOOL on_screen;
|
||
|
|
||
|
OnMainThread(^{
|
||
|
on_screen = [window setFrameIfOnScreen:NSRectFromCGRect(*new_frame)];
|
||
|
});
|
||
|
|
||
|
return on_screen;
|
||
|
}
|