Commit 1c94bf39 authored by Ken Thomases's avatar Ken Thomases Committed by Alexandre Julliard

winemac: Add support for a high-resolution ("Retina") rendering mode.

When this Retina mode is enabled and the primary display is in the user's default configuration, Wine gets told that screen and window sizes and mouse coordinates are twice what Cocoa reports them as in its virtual coordinate system ("points"). The Windows apps then renders at that high resolution and the Mac driver blits it to screen. If the screen is actually a Retina display in a high-DPI mode, then this extra detail will be preserved. Otherwise, the rendering will be downsampled and blurry. This is intended to be combined with increasing the Windows DPI, as via winecfg. If that is doubled to 192, then, in theory, graphical elements will remain the same visual size on screen but be rendered with finer detail. Unfortunately, many Windows programs don't correctly handle non-standard DPI so the results are not always perfect. The registry setting to enable Retina mode is: [HKEY_CURRENT_USER\Software\Wine\Mac Driver] "RetinaMode"="y" Note that this setting is not looked for in the AppDefaults\<exe name> key because it doesn't make sense for only some processes in a Wine session to see the high-resolution sizes and coordinates. Signed-off-by: 's avatarKen Thomases <ken@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 91733274
...@@ -1590,6 +1590,7 @@ static NSString* WineLocalizedString(unsigned int stringID) ...@@ -1590,6 +1590,7 @@ static NSString* WineLocalizedString(unsigned int stringID)
{ {
if (clippingCursor) if (clippingCursor)
[self clipCursorLocation:&point]; [self clipCursorLocation:&point];
point = cgpoint_win_from_mac(point);
event = macdrv_create_event(MOUSE_MOVED_ABSOLUTE, targetWindow); event = macdrv_create_event(MOUSE_MOVED_ABSOLUTE, targetWindow);
event->mouse_moved.x = floor(point.x); event->mouse_moved.x = floor(point.x);
...@@ -1600,18 +1601,20 @@ static NSString* WineLocalizedString(unsigned int stringID) ...@@ -1600,18 +1601,20 @@ static NSString* WineLocalizedString(unsigned int stringID)
} }
else else
{ {
double scale = retina_on ? 2 : 1;
/* Add event delta to accumulated delta error */ /* Add event delta to accumulated delta error */
/* deltaY is already flipped */ /* deltaY is already flipped */
mouseMoveDeltaX += [anEvent deltaX]; mouseMoveDeltaX += [anEvent deltaX];
mouseMoveDeltaY += [anEvent deltaY]; mouseMoveDeltaY += [anEvent deltaY];
event = macdrv_create_event(MOUSE_MOVED, targetWindow); event = macdrv_create_event(MOUSE_MOVED, targetWindow);
event->mouse_moved.x = mouseMoveDeltaX; event->mouse_moved.x = mouseMoveDeltaX * scale;
event->mouse_moved.y = mouseMoveDeltaY; event->mouse_moved.y = mouseMoveDeltaY * scale;
/* Keep the remainder after integer truncation. */ /* Keep the remainder after integer truncation. */
mouseMoveDeltaX -= event->mouse_moved.x; mouseMoveDeltaX -= event->mouse_moved.x / scale;
mouseMoveDeltaY -= event->mouse_moved.y; mouseMoveDeltaY -= event->mouse_moved.y / scale;
} }
if (event->type == MOUSE_MOVED_ABSOLUTE || event->mouse_moved.x || event->mouse_moved.y) if (event->type == MOUSE_MOVED_ABSOLUTE || event->mouse_moved.x || event->mouse_moved.y)
...@@ -1730,6 +1733,8 @@ static NSString* WineLocalizedString(unsigned int stringID) ...@@ -1730,6 +1733,8 @@ static NSString* WineLocalizedString(unsigned int stringID)
{ {
macdrv_event* event; macdrv_event* event;
pt = cgpoint_win_from_mac(pt);
event = macdrv_create_event(MOUSE_BUTTON, window); event = macdrv_create_event(MOUSE_BUTTON, window);
event->mouse_button.button = [theEvent buttonNumber]; event->mouse_button.button = [theEvent buttonNumber];
event->mouse_button.pressed = pressed; event->mouse_button.pressed = pressed;
...@@ -1811,6 +1816,8 @@ static NSString* WineLocalizedString(unsigned int stringID) ...@@ -1811,6 +1816,8 @@ static NSString* WineLocalizedString(unsigned int stringID)
double x, y; double x, y;
BOOL continuous = FALSE; BOOL continuous = FALSE;
pt = cgpoint_win_from_mac(pt);
event = macdrv_create_event(MOUSE_SCROLL, window); event = macdrv_create_event(MOUSE_SCROLL, window);
event->mouse_scroll.x = floor(pt.x); event->mouse_scroll.x = floor(pt.x);
event->mouse_scroll.y = floor(pt.y); event->mouse_scroll.y = floor(pt.y);
...@@ -2146,6 +2153,26 @@ static NSString* WineLocalizedString(unsigned int stringID) ...@@ -2146,6 +2153,26 @@ static NSString* WineLocalizedString(unsigned int stringID)
} }
} }
- (void) setRetinaMode:(int)mode
{
retina_on = mode;
if (clippingCursor)
{
double scale = mode ? 0.5 : 2.0;
cursorClipRect.origin.x *= scale;
cursorClipRect.origin.y *= scale;
cursorClipRect.size.width *= scale;
cursorClipRect.size.height *= scale;
}
for (WineWindow* window in [NSApp windows])
{
if ([window isKindOfClass:[WineWindow class]])
[window setRetinaMode:mode];
}
}
/* /*
* ---------- NSApplicationDelegate methods ---------- * ---------- NSApplicationDelegate methods ----------
...@@ -2496,7 +2523,7 @@ int macdrv_get_cursor_position(CGPoint *pos) ...@@ -2496,7 +2523,7 @@ int macdrv_get_cursor_position(CGPoint *pos)
OnMainThread(^{ OnMainThread(^{
NSPoint location = [NSEvent mouseLocation]; NSPoint location = [NSEvent mouseLocation];
location = [[WineApplicationController sharedController] flippedMouseLocation:location]; location = [[WineApplicationController sharedController] flippedMouseLocation:location];
*pos = NSPointToCGPoint(location); *pos = cgpoint_win_from_mac(NSPointToCGPoint(location));
}); });
return TRUE; return TRUE;
...@@ -2513,7 +2540,7 @@ int macdrv_set_cursor_position(CGPoint pos) ...@@ -2513,7 +2540,7 @@ int macdrv_set_cursor_position(CGPoint pos)
__block int ret; __block int ret;
OnMainThread(^{ OnMainThread(^{
ret = [[WineApplicationController sharedController] setCursorPosition:pos]; ret = [[WineApplicationController sharedController] setCursorPosition:cgpoint_mac_from_win(pos)];
}); });
return ret; return ret;
...@@ -2526,13 +2553,17 @@ int macdrv_set_cursor_position(CGPoint pos) ...@@ -2526,13 +2553,17 @@ int macdrv_set_cursor_position(CGPoint pos)
* to or larger than the whole desktop region, the cursor is unclipped. * to or larger than the whole desktop region, the cursor is unclipped.
* Returns zero on failure, non-zero on success. * Returns zero on failure, non-zero on success.
*/ */
int macdrv_clip_cursor(CGRect rect) int macdrv_clip_cursor(CGRect r)
{ {
__block int ret; __block int ret;
OnMainThread(^{ OnMainThread(^{
WineApplicationController* controller = [WineApplicationController sharedController]; WineApplicationController* controller = [WineApplicationController sharedController];
BOOL clipping = FALSE; BOOL clipping = FALSE;
CGRect rect = r;
if (!CGRectIsInfinite(rect))
rect = cgrect_mac_from_win(rect);
if (!CGRectIsInfinite(rect)) if (!CGRectIsInfinite(rect))
{ {
...@@ -2676,3 +2707,10 @@ int macdrv_select_input_source(TISInputSourceRef input_source) ...@@ -2676,3 +2707,10 @@ int macdrv_select_input_source(TISInputSourceRef input_source)
return ret; return ret;
} }
void macdrv_set_cocoa_retina_mode(int new_mode)
{
OnMainThread(^{
[[WineApplicationController sharedController] setRetinaMode:new_mode];
});
}
...@@ -78,6 +78,8 @@ int macdrv_get_displays(struct macdrv_display** displays, int* count) ...@@ -78,6 +78,8 @@ int macdrv_get_displays(struct macdrv_display** displays, int* count)
convert_display_rect(&disps[i].frame, frame, primary_frame); convert_display_rect(&disps[i].frame, frame, primary_frame);
convert_display_rect(&disps[i].work_frame, visible_frame, convert_display_rect(&disps[i].work_frame, visible_frame,
primary_frame); primary_frame);
disps[i].frame = cgrect_win_from_mac(disps[i].frame);
disps[i].work_frame = cgrect_win_from_mac(disps[i].work_frame);
} }
*displays = disps; *displays = disps;
......
...@@ -323,6 +323,8 @@ static const OSType WineHotKeySignature = 'Wine'; ...@@ -323,6 +323,8 @@ static const OSType WineHotKeySignature = 'Wine';
{ {
MacDrvEvent* event; MacDrvEvent* event;
pos = cgpoint_win_from_mac(pos);
[eventsLock lock]; [eventsLock lock];
for (event in events) for (event in events)
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
NSView* latentView; NSView* latentView;
BOOL needsUpdate; BOOL needsUpdate;
BOOL shouldClearToBlack; BOOL shouldClearToBlack;
GLint backing_size[2];
} }
@property BOOL needsUpdate; @property BOOL needsUpdate;
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
@interface WineOpenGLContext () @interface WineOpenGLContext ()
@property (retain, nonatomic) NSView* latentView; @property (retain, nonatomic) NSView* latentView;
+ (NSView*) dummyView;
- (void) wine_updateBackingSize:(const CGSize*)size;
@end @end
...@@ -40,6 +44,81 @@ ...@@ -40,6 +44,81 @@
[super dealloc]; [super dealloc];
} }
+ (NSView*) dummyView
{
static NSWindow* dummyWindow;
static dispatch_once_t once;
dispatch_once(&once, ^{
OnMainThread(^{
dummyWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
});
});
return dummyWindow.contentView;
}
// Normally, we take care that disconnecting a context from a view doesn't
// destroy that view's GL surface (see -clearDrawableLeavingSurfaceOnScreen).
// However, if we're using a surface backing size and that size changes, we
// need to destroy and recreate the surface or we get weird behavior.
- (void) resetSurfaceIfBackingSizeChanged
{
if (!retina_enabled)
return;
int view_backing[2];
if (macdrv_get_view_backing_size((macdrv_view)self.view, view_backing) &&
(view_backing[0] != backing_size[0] || view_backing[1] != backing_size[1]))
{
view_backing[0] = backing_size[0];
view_backing[1] = backing_size[1];
macdrv_set_view_backing_size((macdrv_view)self.view, view_backing);
NSView* save = self.view;
[super clearDrawable];
[super setView:save];
shouldClearToBlack = TRUE;
}
}
- (void) wine_updateBackingSize:(const CGSize*)size
{
GLint enabled;
if (!retina_enabled)
return;
if (size)
{
if (CGLIsEnabled(self.CGLContextObj, kCGLCESurfaceBackingSize, &enabled) != kCGLNoError)
enabled = 0;
if (!enabled || backing_size[0] != size->width || backing_size[1] != size->height)
{
backing_size[0] = size->width;
backing_size[1] = size->height;
CGLSetParameter(self.CGLContextObj, kCGLCPSurfaceBackingSize, backing_size);
}
if (!enabled)
CGLEnable(self.CGLContextObj, kCGLCESurfaceBackingSize);
[self resetSurfaceIfBackingSizeChanged];
}
else
{
backing_size[0] = 0;
backing_size[1] = 0;
if (CGLIsEnabled(self.CGLContextObj, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
CGLDisable(self.CGLContextObj, kCGLCESurfaceBackingSize);
}
}
- (void) setView:(NSView*)newView - (void) setView:(NSView*)newView
{ {
NSView* oldView = [self view]; NSView* oldView = [self view];
...@@ -53,6 +132,8 @@ ...@@ -53,6 +132,8 @@
NSView* oldView = [self view]; NSView* oldView = [self view];
[super clearDrawable]; [super clearDrawable];
[oldView release]; [oldView release];
[self wine_updateBackingSize:NULL];
} }
/* On at least some versions of Mac OS X, -[NSOpenGLContext clearDrawable] has the /* On at least some versions of Mac OS X, -[NSOpenGLContext clearDrawable] has the
...@@ -64,19 +145,7 @@ ...@@ -64,19 +145,7 @@
original implementation proceed. */ original implementation proceed. */
- (void) clearDrawableLeavingSurfaceOnScreen - (void) clearDrawableLeavingSurfaceOnScreen
{ {
static NSWindow* dummyWindow; [self setView:[[self class] dummyView]];
static dispatch_once_t once;
dispatch_once(&once, ^{
OnMainThread(^{
dummyWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
});
});
[self setView:[dummyWindow contentView]];
[self clearDrawable]; [self clearDrawable];
} }
...@@ -189,7 +258,7 @@ void macdrv_dispose_opengl_context(macdrv_opengl_context c) ...@@ -189,7 +258,7 @@ void macdrv_dispose_opengl_context(macdrv_opengl_context c)
/*********************************************************************** /***********************************************************************
* macdrv_make_context_current * macdrv_make_context_current
*/ */
void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v) void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v, CGRect r)
{ {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
WineOpenGLContext *context = (WineOpenGLContext*)c; WineOpenGLContext *context = (WineOpenGLContext*)c;
...@@ -198,7 +267,10 @@ void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v) ...@@ -198,7 +267,10 @@ void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v)
if (context && view) if (context && view)
{ {
if (view == [context view] || view == [context latentView]) if (view == [context view] || view == [context latentView])
{
[context wine_updateBackingSize:&r.size];
macdrv_update_opengl_context(c); macdrv_update_opengl_context(c);
}
else else
{ {
[context removeFromViews:NO]; [context removeFromViews:NO];
...@@ -207,13 +279,18 @@ void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v) ...@@ -207,13 +279,18 @@ void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v)
if (context.needsUpdate) if (context.needsUpdate)
{ {
context.needsUpdate = FALSE; context.needsUpdate = FALSE;
if (context.view)
[context setView:[[context class] dummyView]];
[context wine_updateBackingSize:&r.size];
[context setView:view]; [context setView:view];
[context setLatentView:nil]; [context setLatentView:nil];
[context resetSurfaceIfBackingSizeChanged];
} }
else else
{ {
if ([context view]) if ([context view])
[context clearDrawableLeavingSurfaceOnScreen]; [context clearDrawableLeavingSurfaceOnScreen];
[context wine_updateBackingSize:&r.size];
[context setLatentView:view]; [context setLatentView:view];
} }
} }
...@@ -257,10 +334,14 @@ void macdrv_update_opengl_context(macdrv_opengl_context c) ...@@ -257,10 +334,14 @@ void macdrv_update_opengl_context(macdrv_opengl_context c)
[context setView:context.latentView]; [context setView:context.latentView];
context.latentView = nil; context.latentView = nil;
[context resetSurfaceIfBackingSizeChanged];
[context clearToBlackIfNeeded]; [context clearToBlackIfNeeded];
} }
else else
{
[context update]; [context update];
[context resetSurfaceIfBackingSizeChanged];
}
} }
[pool release]; [pool release];
......
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
CGDirectDisplayID _lastDisplayID; CGDirectDisplayID _lastDisplayID;
NSTimeInterval _lastDisplayTime; NSTimeInterval _lastDisplayTime;
NSRect wineFrame;
NSRect roundedWineFrame;
NSBezierPath* shape; NSBezierPath* shape;
NSData* shapeData; NSData* shapeData;
BOOL shapeChangedSinceLastDraw; BOOL shapeChangedSinceLastDraw;
...@@ -88,6 +91,7 @@ ...@@ -88,6 +91,7 @@
@property (readonly, nonatomic) BOOL floating; @property (readonly, nonatomic) BOOL floating;
@property (readonly, getter=isFullscreen, nonatomic) BOOL fullscreen; @property (readonly, getter=isFullscreen, nonatomic) BOOL fullscreen;
@property (readonly, getter=isFakingClose, nonatomic) BOOL fakingClose; @property (readonly, getter=isFakingClose, nonatomic) BOOL fakingClose;
@property (readonly, nonatomic) NSRect wine_fractionalFrame;
- (NSInteger) minimumLevelForActive:(BOOL)active; - (NSInteger) minimumLevelForActive:(BOOL)active;
- (void) updateFullscreen; - (void) updateFullscreen;
...@@ -99,4 +103,6 @@ ...@@ -99,4 +103,6 @@
- (void) updateForCursorClipping; - (void) updateForCursorClipping;
- (void) setRetinaMode:(int)mode;
@end @end
...@@ -294,12 +294,17 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -294,12 +294,17 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
NSMutableAttributedString* markedText; NSMutableAttributedString* markedText;
NSRange markedTextSelection; NSRange markedTextSelection;
int backingSize[2];
} }
- (void) addGLContext:(WineOpenGLContext*)context; - (void) addGLContext:(WineOpenGLContext*)context;
- (void) removeGLContext:(WineOpenGLContext*)context; - (void) removeGLContext:(WineOpenGLContext*)context;
- (void) updateGLContexts; - (void) updateGLContexts;
- (void) wine_getBackingSize:(int*)outBackingSize;
- (void) wine_setBackingSize:(const int*)newBackingSize;
@end @end
...@@ -393,6 +398,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -393,6 +398,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
if (get_surface_blit_rects(window.surface, &rects, &count) && count) if (get_surface_blit_rects(window.surface, &rects, &count) && count)
{ {
CGRect dirtyRect = cgrect_win_from_mac(NSRectToCGRect(rect));
CGContextRef context; CGContextRef context;
int i; int i;
...@@ -400,14 +406,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -400,14 +406,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
CGContextSetBlendMode(context, kCGBlendModeCopy); CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextSetInterpolationQuality(context, kCGInterpolationNone); CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
CGRect imageRect; CGRect imageRect;
CGImageRef image; CGImageRef image;
imageRect = CGRectIntersection(rects[i], NSRectToCGRect(rect)); imageRect = CGRectIntersection(rects[i], dirtyRect);
image = create_surface_image(window.surface, &imageRect, FALSE); image = create_surface_image(window.surface, &imageRect, FALSE);
if (image) if (image)
...@@ -426,7 +432,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -426,7 +432,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
} }
} }
CGContextDrawImage(context, imageRect, image); CGContextDrawImage(context, cgrect_mac_from_win(imageRect), image);
CGImageRelease(image); CGImageRelease(image);
} }
...@@ -490,6 +496,19 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -490,6 +496,19 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
return [glContexts count] || [pendingGlContexts count]; return [glContexts count] || [pendingGlContexts count];
} }
- (void) wine_getBackingSize:(int*)outBackingSize
{
@synchronized(self) {
memcpy(outBackingSize, backingSize, sizeof(backingSize));
}
}
- (void) wine_setBackingSize:(const int*)newBackingSize
{
@synchronized(self) {
memcpy(backingSize, newBackingSize, sizeof(backingSize));
}
}
- (BOOL) acceptsFirstMouse:(NSEvent*)theEvent - (BOOL) acceptsFirstMouse:(NSEvent*)theEvent
{ {
return YES; return YES;
...@@ -652,7 +671,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -652,7 +671,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
if ([window.queue query:query timeout:0.3 flags:WineQueryNoPreemptWait]) if ([window.queue query:query timeout:0.3 flags:WineQueryNoPreemptWait])
{ {
aRange = NSMakeRange(query->ime_char_rect.range.location, query->ime_char_rect.range.length); aRange = NSMakeRange(query->ime_char_rect.range.location, query->ime_char_rect.range.length);
ret = NSRectFromCGRect(query->ime_char_rect.rect); ret = NSRectFromCGRect(cgrect_mac_from_win(query->ime_char_rect.rect));
[[WineApplicationController sharedController] flipRect:&ret]; [[WineApplicationController sharedController] flipRect:&ret];
} }
else else
...@@ -772,6 +791,8 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -772,6 +791,8 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
name:NSWorkspaceActiveSpaceDidChangeNotification name:NSWorkspaceActiveSpaceDidChangeNotification
object:[NSWorkspace sharedWorkspace]]; object:[NSWorkspace sharedWorkspace]];
[window setFrameAndWineFrame:[window frameRectForContentRect:window_frame]];
return window; return window;
} }
...@@ -821,7 +842,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -821,7 +842,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
if ([self preventResizing]) if ([self preventResizing])
{ {
NSSize size = [self contentRectForFrameRect:[self frame]].size; NSSize size = [self contentRectForFrameRect:self.wine_fractionalFrame].size;
[self setContentMinSize:size]; [self setContentMinSize:size];
[self setContentMaxSize:size]; [self setContentMaxSize:size];
} }
...@@ -1433,7 +1454,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -1433,7 +1454,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
- (void) updateFullscreen - (void) updateFullscreen
{ {
NSRect contentRect = [self contentRectForFrameRect:[self frame]]; NSRect contentRect = [self contentRectForFrameRect:self.wine_fractionalFrame];
BOOL nowFullscreen = !([self styleMask] & NSFullScreenWindowMask) && screen_covered_by_rect(contentRect, [NSScreen screens]); BOOL nowFullscreen = !([self styleMask] & NSFullScreenWindowMask) && screen_covered_by_rect(contentRect, [NSScreen screens]);
if (nowFullscreen != fullscreen) if (nowFullscreen != fullscreen)
...@@ -1448,6 +1469,32 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -1448,6 +1469,32 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
} }
} }
- (void) setFrameAndWineFrame:(NSRect)frame
{
[self setFrame:frame display:YES];
wineFrame = frame;
roundedWineFrame = self.frame;
CGFloat junk;
#if CGFLOAT_IS_DOUBLE
if ((!modf(wineFrame.origin.x, &junk) && !modf(wineFrame.origin.y, &junk) &&
!modf(wineFrame.size.width, &junk) && !modf(wineFrame.size.height, &junk)) ||
fabs(wineFrame.origin.x - roundedWineFrame.origin.x) >= 1 ||
fabs(wineFrame.origin.y - roundedWineFrame.origin.y) >= 1 ||
fabs(wineFrame.size.width - roundedWineFrame.size.width) >= 1 ||
fabs(wineFrame.size.height - roundedWineFrame.size.height) >= 1)
roundedWineFrame = wineFrame;
#else
if ((!modff(wineFrame.origin.x, &junk) && !modff(wineFrame.origin.y, &junk) &&
!modff(wineFrame.size.width, &junk) && !modff(wineFrame.size.height, &junk)) ||
fabsf(wineFrame.origin.x - roundedWineFrame.origin.x) >= 1 ||
fabsf(wineFrame.origin.y - roundedWineFrame.origin.y) >= 1 ||
fabsf(wineFrame.size.width - roundedWineFrame.size.width) >= 1 ||
fabsf(wineFrame.size.height - roundedWineFrame.size.height) >= 1)
roundedWineFrame = wineFrame;
#endif
}
- (void) setFrameFromWine:(NSRect)contentRect - (void) setFrameFromWine:(NSRect)contentRect
{ {
/* Origin is (left, top) in a top-down space. Need to convert it to /* Origin is (left, top) in a top-down space. Need to convert it to
...@@ -1464,7 +1511,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -1464,7 +1511,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
{ {
NSRect frame, oldFrame; NSRect frame, oldFrame;
oldFrame = [self frame]; oldFrame = self.wine_fractionalFrame;
frame = [self frameRectForContentRect:contentRect]; frame = [self frameRectForContentRect:contentRect];
if (!NSEqualRects(frame, oldFrame)) if (!NSEqualRects(frame, oldFrame))
{ {
...@@ -1498,7 +1545,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -1498,7 +1545,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
ignore_windowResize = FALSE; ignore_windowResize = FALSE;
} }
[self setFrame:frame display:YES]; [self setFrameAndWineFrame:frame];
if ([self preventResizing]) if ([self preventResizing])
{ {
[self setContentMinSize:contentRect.size]; [self setContentMinSize:contentRect.size];
...@@ -1527,6 +1574,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -1527,6 +1574,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
} }
} }
- (NSRect) wine_fractionalFrame
{
NSRect frame = self.frame;
if (NSEqualRects(frame, roundedWineFrame))
frame = wineFrame;
return frame;
}
- (void) setMacDrvParentWindow:(WineWindow*)parent - (void) setMacDrvParentWindow:(WineWindow*)parent
{ {
WineWindow* oldParent = (WineWindow*)[self parentWindow]; WineWindow* oldParent = (WineWindow*)[self parentWindow];
...@@ -2052,7 +2107,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2052,7 +2107,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
event = macdrv_create_event(WINDOW_RESTORE_REQUESTED, self); event = macdrv_create_event(WINDOW_RESTORE_REQUESTED, self);
event->window_restore_requested.keep_frame = TRUE; event->window_restore_requested.keep_frame = TRUE;
event->window_restore_requested.frame = NSRectToCGRect(frame); event->window_restore_requested.frame = cgrect_win_from_mac(NSRectToCGRect(frame));
[queue postEvent:event]; [queue postEvent:event];
macdrv_release_event(event); macdrv_release_event(event);
...@@ -2165,6 +2220,57 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2165,6 +2220,57 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
[self checkTransparency]; [self checkTransparency];
} }
- (void) setRetinaMode:(int)mode
{
NSRect frame;
double scale = mode ? 0.5 : 2.0;
NSAffineTransform* transform = [NSAffineTransform transform];
[transform scaleBy:scale];
if (shape)
[shape transformUsingAffineTransform:transform];
for (WineContentView* subview in [self.contentView subviews])
{
if ([subview isKindOfClass:[WineContentView class]])
{
frame = subview.frame;
frame.origin.x *= scale;
frame.origin.y *= scale;
frame.size.width *= scale;
frame.size.height *= scale;
[subview setFrame:frame];
[subview updateGLContexts];
}
}
frame = [self contentRectForFrameRect:self.wine_fractionalFrame];
frame.origin.x *= scale;
frame.origin.y *= scale;
frame.size.width *= scale;
frame.size.height *= scale;
frame = [self frameRectForContentRect:frame];
savedContentMinSize = [transform transformSize:savedContentMinSize];
if (savedContentMaxSize.width != FLT_MAX && savedContentMaxSize.width != CGFLOAT_MAX)
savedContentMaxSize.width *= scale;
if (savedContentMaxSize.height != FLT_MAX && savedContentMaxSize.height != CGFLOAT_MAX)
savedContentMaxSize.height *= scale;
self.contentMinSize = [transform transformSize:self.contentMinSize];
NSSize temp = self.contentMaxSize;
if (temp.width != FLT_MAX && temp.width != CGFLOAT_MAX)
temp.width *= scale;
if (temp.height != FLT_MAX && temp.height != CGFLOAT_MAX)
temp.height *= scale;
self.contentMaxSize = temp;
ignore_windowResize = TRUE;
[self setFrameAndWineFrame:frame];
ignore_windowResize = FALSE;
}
/* /*
* ---------- NSResponder method overrides ---------- * ---------- NSResponder method overrides ----------
...@@ -2337,7 +2443,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2337,7 +2443,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
- (void) windowDidExitFullScreen:(NSNotification*)notification - (void) windowDidExitFullScreen:(NSNotification*)notification
{ {
exitingFullScreen = FALSE; exitingFullScreen = FALSE;
[self setFrame:nonFullscreenFrame display:YES animate:NO]; [self setFrameAndWineFrame:nonFullscreenFrame];
[self windowDidResize:nil]; [self windowDidResize:nil];
} }
...@@ -2379,7 +2485,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2379,7 +2485,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
- (void)windowDidResize:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification
{ {
macdrv_event* event; macdrv_event* event;
NSRect frame = [self frame]; NSRect frame = self.wine_fractionalFrame;
if ([self inLiveResize]) if ([self inLiveResize])
{ {
...@@ -2406,7 +2512,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2406,7 +2512,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
forWindow:self]; forWindow:self];
event = macdrv_create_event(WINDOW_FRAME_CHANGED, self); event = macdrv_create_event(WINDOW_FRAME_CHANGED, self);
event->window_frame_changed.frame = NSRectToCGRect(frame); event->window_frame_changed.frame = cgrect_win_from_mac(NSRectToCGRect(frame));
event->window_frame_changed.fullscreen = ([self styleMask] & NSFullScreenWindowMask) != 0; event->window_frame_changed.fullscreen = ([self styleMask] & NSFullScreenWindowMask) != 0;
event->window_frame_changed.in_resize = [self inLiveResize]; event->window_frame_changed.in_resize = [self inLiveResize];
[queue postEvent:event]; [queue postEvent:event];
...@@ -2466,7 +2572,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2466,7 +2572,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
- (void) windowWillEnterFullScreen:(NSNotification*)notification - (void) windowWillEnterFullScreen:(NSNotification*)notification
{ {
enteringFullScreen = TRUE; enteringFullScreen = TRUE;
nonFullscreenFrame = [self frame]; nonFullscreenFrame = self.wine_fractionalFrame;
} }
- (void) windowWillExitFullScreen:(NSNotification*)notification - (void) windowWillExitFullScreen:(NSNotification*)notification
...@@ -2485,7 +2591,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2485,7 +2591,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
if ([self inLiveResize]) if ([self inLiveResize])
{ {
if (maximized) if (maximized)
return self.frame.size; return self.wine_fractionalFrame.size;
NSRect rect; NSRect rect;
macdrv_query* query; macdrv_query* query;
...@@ -2502,13 +2608,13 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2502,13 +2608,13 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
query = macdrv_create_query(); query = macdrv_create_query();
query->type = QUERY_RESIZE_SIZE; query->type = QUERY_RESIZE_SIZE;
query->window = (macdrv_window)[self retain]; query->window = (macdrv_window)[self retain];
query->resize_size.rect = NSRectToCGRect(rect); query->resize_size.rect = cgrect_win_from_mac(NSRectToCGRect(rect));
query->resize_size.from_left = resizingFromLeft; query->resize_size.from_left = resizingFromLeft;
query->resize_size.from_top = resizingFromTop; query->resize_size.from_top = resizingFromTop;
if ([self.queue query:query timeout:0.1]) if ([self.queue query:query timeout:0.1])
{ {
rect = NSRectFromCGRect(query->resize_size.rect); rect = NSRectFromCGRect(cgrect_mac_from_win(query->resize_size.rect));
rect = [self frameRectForContentRect:rect]; rect = [self frameRectForContentRect:rect];
frameSize = rect.size; frameSize = rect.size;
} }
...@@ -2532,7 +2638,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2532,7 +2638,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
event = macdrv_create_event(WINDOW_RESTORE_REQUESTED, self); event = macdrv_create_event(WINDOW_RESTORE_REQUESTED, self);
event->window_restore_requested.keep_frame = TRUE; event->window_restore_requested.keep_frame = TRUE;
event->window_restore_requested.frame = NSRectToCGRect(frame); event->window_restore_requested.frame = cgrect_win_from_mac(NSRectToCGRect(frame));
[queue postEvent:event]; [queue postEvent:event];
macdrv_release_event(event); macdrv_release_event(event);
} }
...@@ -2625,13 +2731,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2625,13 +2731,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
{ {
NSDragOperation ret; NSDragOperation ret;
NSPoint pt = [[self contentView] convertPoint:[sender draggingLocation] fromView:nil]; NSPoint pt = [[self contentView] convertPoint:[sender draggingLocation] fromView:nil];
CGPoint cgpt = cgpoint_win_from_mac(NSPointToCGPoint(pt));
NSPasteboard* pb = [sender draggingPasteboard]; NSPasteboard* pb = [sender draggingPasteboard];
macdrv_query* query = macdrv_create_query(); macdrv_query* query = macdrv_create_query();
query->type = QUERY_DRAG_OPERATION; query->type = QUERY_DRAG_OPERATION;
query->window = (macdrv_window)[self retain]; query->window = (macdrv_window)[self retain];
query->drag_operation.x = floor(pt.x); query->drag_operation.x = floor(cgpt.x);
query->drag_operation.y = floor(pt.y); query->drag_operation.y = floor(cgpt.y);
query->drag_operation.offered_ops = [sender draggingSourceOperationMask]; query->drag_operation.offered_ops = [sender draggingSourceOperationMask];
query->drag_operation.accepted_op = NSDragOperationNone; query->drag_operation.accepted_op = NSDragOperationNone;
query->drag_operation.pasteboard = (CFTypeRef)[pb retain]; query->drag_operation.pasteboard = (CFTypeRef)[pb retain];
...@@ -2647,13 +2754,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi ...@@ -2647,13 +2754,14 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
{ {
BOOL ret; BOOL ret;
NSPoint pt = [[self contentView] convertPoint:[sender draggingLocation] fromView:nil]; NSPoint pt = [[self contentView] convertPoint:[sender draggingLocation] fromView:nil];
CGPoint cgpt = cgpoint_win_from_mac(NSPointToCGPoint(pt));
NSPasteboard* pb = [sender draggingPasteboard]; NSPasteboard* pb = [sender draggingPasteboard];
macdrv_query* query = macdrv_create_query(); macdrv_query* query = macdrv_create_query();
query->type = QUERY_DRAG_DROP; query->type = QUERY_DRAG_DROP;
query->window = (macdrv_window)[self retain]; query->window = (macdrv_window)[self retain];
query->drag_drop.x = floor(pt.x); query->drag_drop.x = floor(cgpt.x);
query->drag_drop.y = floor(pt.y); query->drag_drop.y = floor(cgpt.y);
query->drag_drop.op = [sender draggingSourceOperationMask]; query->drag_drop.op = [sender draggingSourceOperationMask];
query->drag_drop.pasteboard = (CFTypeRef)[pb retain]; query->drag_drop.pasteboard = (CFTypeRef)[pb retain];
...@@ -2685,7 +2793,7 @@ macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf ...@@ -2685,7 +2793,7 @@ macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf
OnMainThread(^{ OnMainThread(^{
window = [[WineWindow createWindowWithFeatures:wf window = [[WineWindow createWindowWithFeatures:wf
windowFrame:NSRectFromCGRect(frame) windowFrame:NSRectFromCGRect(cgrect_mac_from_win(frame))
hwnd:hwnd hwnd:hwnd
queue:(WineEventQueue*)queue] retain]; queue:(WineEventQueue*)queue] retain];
}); });
...@@ -2829,7 +2937,7 @@ void macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame) ...@@ -2829,7 +2937,7 @@ void macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame)
WineWindow* window = (WineWindow*)w; WineWindow* window = (WineWindow*)w;
OnMainThread(^{ OnMainThread(^{
[window setFrameFromWine:NSRectFromCGRect(*new_frame)]; [window setFrameFromWine:NSRectFromCGRect(cgrect_mac_from_win(*new_frame))];
}); });
} }
...@@ -2845,9 +2953,9 @@ void macdrv_get_cocoa_window_frame(macdrv_window w, CGRect* out_frame) ...@@ -2845,9 +2953,9 @@ void macdrv_get_cocoa_window_frame(macdrv_window w, CGRect* out_frame)
OnMainThread(^{ OnMainThread(^{
NSRect frame; NSRect frame;
frame = [window contentRectForFrameRect:[window frame]]; frame = [window contentRectForFrameRect:[window wine_fractionalFrame]];
[[WineApplicationController sharedController] flipRect:&frame]; [[WineApplicationController sharedController] flipRect:&frame];
*out_frame = NSRectToCGRect(frame); *out_frame = cgrect_win_from_mac(NSRectToCGRect(frame));
}); });
} }
...@@ -2894,7 +3002,7 @@ void macdrv_window_needs_display(macdrv_window w, CGRect rect) ...@@ -2894,7 +3002,7 @@ void macdrv_window_needs_display(macdrv_window w, CGRect rect)
WineWindow* window = (WineWindow*)w; WineWindow* window = (WineWindow*)w;
OnMainThreadAsync(^{ OnMainThreadAsync(^{
[[window contentView] setNeedsDisplayInRect:NSRectFromCGRect(rect)]; [[window contentView] setNeedsDisplayInRect:NSRectFromCGRect(cgrect_mac_from_win(rect))];
}); });
[pool release]; [pool release];
...@@ -2928,7 +3036,7 @@ void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count) ...@@ -2928,7 +3036,7 @@ void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count)
path = [NSBezierPath bezierPath]; path = [NSBezierPath bezierPath];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
[path appendBezierPathWithRect:NSRectFromCGRect(rects[i])]; [path appendBezierPathWithRect:NSRectFromCGRect(cgrect_mac_from_win(rects[i]))];
window.shape = path; window.shape = path;
window.shapeData = [NSData dataWithBytes:rects length:length]; window.shapeData = [NSData dataWithBytes:rects length:length];
[window checkEmptyShaped]; [window checkEmptyShaped];
...@@ -3030,7 +3138,7 @@ void macdrv_set_window_min_max_sizes(macdrv_window w, CGSize min_size, CGSize ma ...@@ -3030,7 +3138,7 @@ void macdrv_set_window_min_max_sizes(macdrv_window w, CGSize min_size, CGSize ma
WineWindow* window = (WineWindow*)w; WineWindow* window = (WineWindow*)w;
OnMainThread(^{ OnMainThread(^{
[window setWineMinSize:NSSizeFromCGSize(min_size) maxSize:NSSizeFromCGSize(max_size)]; [window setWineMinSize:NSSizeFromCGSize(cgsize_mac_from_win(min_size)) maxSize:NSSizeFromCGSize(cgsize_mac_from_win(max_size))];
}); });
} }
...@@ -3052,7 +3160,7 @@ macdrv_view macdrv_create_view(macdrv_window w, CGRect rect) ...@@ -3052,7 +3160,7 @@ macdrv_view macdrv_create_view(macdrv_window w, CGRect rect)
OnMainThread(^{ OnMainThread(^{
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(rect)]; view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))];
[view setAutoresizesSubviews:NO]; [view setAutoresizesSubviews:NO];
[nc addObserver:view [nc addObserver:view
selector:@selector(updateGLContexts) selector:@selector(updateGLContexts)
...@@ -3115,7 +3223,7 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec ...@@ -3115,7 +3223,7 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec
OnMainThread(^{ OnMainThread(^{
BOOL changedWindow = (window && window != [view window]); BOOL changedWindow = (window && window != [view window]);
NSRect newFrame = NSRectFromCGRect(rect); NSRect newFrame = NSRectFromCGRect(cgrect_mac_from_win(rect));
NSRect oldFrame = [view frame]; NSRect oldFrame = [view frame];
BOOL needUpdateWindowForGLSubviews = FALSE; BOOL needUpdateWindowForGLSubviews = FALSE;
...@@ -3140,6 +3248,12 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec ...@@ -3140,6 +3248,12 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec
[view setFrame:newFrame]; [view setFrame:newFrame];
[view setNeedsDisplay:YES]; [view setNeedsDisplay:YES];
needUpdateWindowForGLSubviews = TRUE; needUpdateWindowForGLSubviews = TRUE;
if (retina_enabled)
{
int backing_size[2] = { 0 };
[view wine_setBackingSize:backing_size];
}
} }
if (needUpdateWindowForGLSubviews) if (needUpdateWindowForGLSubviews)
...@@ -3185,6 +3299,25 @@ void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c) ...@@ -3185,6 +3299,25 @@ void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c)
[pool release]; [pool release];
} }
int macdrv_get_view_backing_size(macdrv_view v, int backing_size[2])
{
WineContentView* view = (WineContentView*)v;
if (![view isKindOfClass:[WineContentView class]])
return FALSE;
[view wine_getBackingSize:backing_size];
return TRUE;
}
void macdrv_set_view_backing_size(macdrv_view v, const int backing_size[2])
{
WineContentView* view = (WineContentView*)v;
if ([view isKindOfClass:[WineContentView class]])
[view wine_setBackingSize:backing_size];
}
/*********************************************************************** /***********************************************************************
* macdrv_window_background_color * macdrv_window_background_color
* *
......
...@@ -488,7 +488,7 @@ static int get_default_bpp(void) ...@@ -488,7 +488,7 @@ static int get_default_bpp(void)
#if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 #if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8
static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode) static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode, BOOL is_original)
{ {
CFDictionaryRef ret; CFDictionaryRef ret;
SInt32 io_flags = CGDisplayModeGetIOFlags(display_mode); SInt32 io_flags = CGDisplayModeGetIOFlags(display_mode);
...@@ -498,6 +498,12 @@ static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode) ...@@ -498,6 +498,12 @@ static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode)
CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode);
CFNumberRef cf_io_flags, cf_width, cf_height, cf_refresh; CFNumberRef cf_io_flags, cf_width, cf_height, cf_refresh;
if (retina_enabled && is_original)
{
width *= 2;
height *= 2;
}
io_flags &= kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeInterlacedFlag | io_flags &= kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeInterlacedFlag |
kDisplayModeStretchedFlag | kDisplayModeTelevisionFlag; kDisplayModeStretchedFlag | kDisplayModeTelevisionFlag;
cf_io_flags = CFNumberCreate(NULL, kCFNumberSInt32Type, &io_flags); cf_io_flags = CFNumberCreate(NULL, kCFNumberSInt32Type, &io_flags);
...@@ -581,7 +587,7 @@ static CFArrayRef copy_display_modes(CGDirectDisplayID display) ...@@ -581,7 +587,7 @@ static CFArrayRef copy_display_modes(CGDirectDisplayID display)
BOOL better = TRUE; BOOL better = TRUE;
CGDisplayModeRef new_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); CGDisplayModeRef new_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
BOOL new_is_original = display_mode_matches_descriptor(new_mode, desc); BOOL new_is_original = display_mode_matches_descriptor(new_mode, desc);
CFDictionaryRef key = create_mode_dict(new_mode); CFDictionaryRef key = create_mode_dict(new_mode, new_is_original);
/* If a given mode is the user's default, then always list it in preference to any similar /* If a given mode is the user's default, then always list it in preference to any similar
modes that may exist. */ modes that may exist. */
...@@ -667,6 +673,23 @@ static CFArrayRef copy_display_modes(CGDirectDisplayID display) ...@@ -667,6 +673,23 @@ static CFArrayRef copy_display_modes(CGDirectDisplayID display)
} }
void check_retina_status(void)
{
if (retina_enabled)
{
struct display_mode_descriptor* desc = create_original_display_mode_descriptor(kCGDirectMainDisplay);
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
BOOL new_value = display_mode_matches_descriptor(mode, desc);
CGDisplayModeRelease(mode);
free_display_mode_descriptor(desc);
if (new_value != retina_on)
macdrv_set_cocoa_retina_mode(new_value);
}
}
/*********************************************************************** /***********************************************************************
* ChangeDisplaySettingsEx (MACDRV.@) * ChangeDisplaySettingsEx (MACDRV.@)
* *
...@@ -681,9 +704,11 @@ LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, ...@@ -681,9 +704,11 @@ LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode,
struct macdrv_display *displays; struct macdrv_display *displays;
int num_displays; int num_displays;
CFArrayRef display_modes; CFArrayRef display_modes;
struct display_mode_descriptor* desc;
CFIndex count, i, safe, best; CFIndex count, i, safe, best;
CGDisplayModeRef best_display_mode; CGDisplayModeRef best_display_mode;
uint32_t best_io_flags; uint32_t best_io_flags;
BOOL best_is_original;
TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname), devmode, hwnd, flags, lpvoid); TRACE("%s %p %p 0x%08x %p\n", debugstr_w(devname), devmode, hwnd, flags, lpvoid);
...@@ -748,17 +773,26 @@ LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, ...@@ -748,17 +773,26 @@ LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode,
TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-");
TRACE("\n"); TRACE("\n");
desc = create_original_display_mode_descriptor(displays[0].displayID);
safe = -1; safe = -1;
best_display_mode = NULL; best_display_mode = NULL;
count = CFArrayGetCount(display_modes); count = CFArrayGetCount(display_modes);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
CGDisplayModeRef display_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(display_modes, i); CGDisplayModeRef display_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(display_modes, i);
BOOL is_original = display_mode_matches_descriptor(display_mode, desc);
uint32_t io_flags = CGDisplayModeGetIOFlags(display_mode); uint32_t io_flags = CGDisplayModeGetIOFlags(display_mode);
int mode_bpp = display_mode_bits_per_pixel(display_mode); int mode_bpp = display_mode_bits_per_pixel(display_mode);
size_t width = CGDisplayModeGetWidth(display_mode); size_t width = CGDisplayModeGetWidth(display_mode);
size_t height = CGDisplayModeGetHeight(display_mode); size_t height = CGDisplayModeGetHeight(display_mode);
if (is_original && retina_enabled)
{
width *= 2;
height *= 2;
}
if (!(io_flags & kDisplayModeValidFlag) || !(io_flags & kDisplayModeSafeFlag)) if (!(io_flags & kDisplayModeValidFlag) || !(io_flags & kDisplayModeSafeFlag))
continue; continue;
...@@ -817,6 +851,7 @@ better: ...@@ -817,6 +851,7 @@ better:
best_display_mode = display_mode; best_display_mode = display_mode;
best = safe; best = safe;
best_io_flags = io_flags; best_io_flags = io_flags;
best_is_original = is_original;
} }
if (best_display_mode) if (best_display_mode)
...@@ -837,6 +872,12 @@ better: ...@@ -837,6 +872,12 @@ better:
size_t width = CGDisplayModeGetWidth(best_display_mode); size_t width = CGDisplayModeGetWidth(best_display_mode);
size_t height = CGDisplayModeGetHeight(best_display_mode); size_t height = CGDisplayModeGetHeight(best_display_mode);
if (best_is_original && retina_enabled)
{
width *= 2;
height *= 2;
}
SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp,
MAKELPARAM(width, height)); MAKELPARAM(width, height));
ret = DISP_CHANGE_SUCCESSFUL; ret = DISP_CHANGE_SUCCESSFUL;
...@@ -854,6 +895,7 @@ better: ...@@ -854,6 +895,7 @@ better:
bpp, devmode->dmDisplayFrequency); bpp, devmode->dmDisplayFrequency);
} }
free_display_mode_descriptor(desc);
CFRelease(display_modes); CFRelease(display_modes);
macdrv_free_displays(displays); macdrv_free_displays(displays);
...@@ -1082,6 +1124,16 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, ...@@ -1082,6 +1124,16 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode,
devmode->dmPelsWidth = CGDisplayModeGetWidth(display_mode); devmode->dmPelsWidth = CGDisplayModeGetWidth(display_mode);
devmode->dmPelsHeight = CGDisplayModeGetHeight(display_mode); devmode->dmPelsHeight = CGDisplayModeGetHeight(display_mode);
if (retina_enabled)
{
struct display_mode_descriptor* desc = create_original_display_mode_descriptor(displays[0].displayID);
if (display_mode_matches_descriptor(display_mode, desc))
{
devmode->dmPelsWidth *= 2;
devmode->dmPelsHeight *= 2;
}
free_display_mode_descriptor(desc);
}
devmode->dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT; devmode->dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
devmode->dmDisplayFlags = 0; devmode->dmDisplayFlags = 0;
...@@ -1329,8 +1381,18 @@ void macdrv_displays_changed(const macdrv_event *event) ...@@ -1329,8 +1381,18 @@ void macdrv_displays_changed(const macdrv_event *event)
size_t width = CGDisplayModeGetWidth(mode); size_t width = CGDisplayModeGetWidth(mode);
size_t height = CGDisplayModeGetHeight(mode); size_t height = CGDisplayModeGetHeight(mode);
int mode_bpp = display_mode_bits_per_pixel(mode); int mode_bpp = display_mode_bits_per_pixel(mode);
struct display_mode_descriptor* desc = create_original_display_mode_descriptor(mainDisplay);
BOOL is_original = display_mode_matches_descriptor(mode, desc);
free_display_mode_descriptor(desc);
CGDisplayModeRelease(mode); CGDisplayModeRelease(mode);
if (is_original && retina_enabled)
{
width *= 2;
height *= 2;
}
SendMessageW(hwnd, WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, SendMessageW(hwnd, WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp,
MAKELPARAM(width, height)); MAKELPARAM(width, height));
} }
......
...@@ -51,6 +51,8 @@ static int desktop_vert_res; /* height in pixels of virtual desktop */ ...@@ -51,6 +51,8 @@ static int desktop_vert_res; /* height in pixels of virtual desktop */
static int bits_per_pixel; /* pixel depth of screen */ static int bits_per_pixel; /* pixel depth of screen */
static int device_data_valid; /* do the above variables have up-to-date values? */ static int device_data_valid; /* do the above variables have up-to-date values? */
int retina_on = FALSE;
static CRITICAL_SECTION device_data_section; static CRITICAL_SECTION device_data_section;
static CRITICAL_SECTION_DEBUG critsect_debug = static CRITICAL_SECTION_DEBUG critsect_debug =
{ {
...@@ -94,6 +96,29 @@ static DWORD get_dpi(void) ...@@ -94,6 +96,29 @@ static DWORD get_dpi(void)
/*********************************************************************** /***********************************************************************
* compute_desktop_rect
*/
static void compute_desktop_rect(void)
{
CGDirectDisplayID displayIDs[32];
uint32_t count, i;
desktop_rect = CGRectNull;
if (CGGetActiveDisplayList(sizeof(displayIDs)/sizeof(displayIDs[0]),
displayIDs, &count) != kCGErrorSuccess ||
!count)
{
displayIDs[0] = CGMainDisplayID();
count = 1;
}
for (i = 0; i < count; i++)
desktop_rect = CGRectUnion(desktop_rect, CGDisplayBounds(displayIDs[i]));
desktop_rect = cgrect_win_from_mac(desktop_rect);
}
/***********************************************************************
* macdrv_get_desktop_rect * macdrv_get_desktop_rect
* *
* Returns the rectangle encompassing all the screens. * Returns the rectangle encompassing all the screens.
...@@ -101,27 +126,16 @@ static DWORD get_dpi(void) ...@@ -101,27 +126,16 @@ static DWORD get_dpi(void)
CGRect macdrv_get_desktop_rect(void) CGRect macdrv_get_desktop_rect(void)
{ {
CGRect ret; CGRect ret;
CGDirectDisplayID displayIDs[32];
uint32_t count, i;
EnterCriticalSection(&device_data_section); EnterCriticalSection(&device_data_section);
if (!device_data_valid) if (!device_data_valid)
{ {
desktop_rect = CGRectNull; check_retina_status();
if (CGGetActiveDisplayList(sizeof(displayIDs)/sizeof(displayIDs[0]), compute_desktop_rect();
displayIDs, &count) != kCGErrorSuccess ||
!count)
{
displayIDs[0] = CGMainDisplayID();
count = 1;
}
for (i = 0; i < count; i++)
desktop_rect = CGRectUnion(desktop_rect, CGDisplayBounds(displayIDs[i]));
} }
ret = desktop_rect; ret = desktop_rect;
LeaveCriticalSection(&device_data_section); LeaveCriticalSection(&device_data_section);
TRACE("%s\n", wine_dbgstr_cgrect(ret)); TRACE("%s\n", wine_dbgstr_cgrect(ret));
...@@ -141,12 +155,23 @@ static void device_init(void) ...@@ -141,12 +155,23 @@ static void device_init(void)
CGSize size_mm = CGDisplayScreenSize(mainDisplay); CGSize size_mm = CGDisplayScreenSize(mainDisplay);
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay);
check_retina_status();
/* Initialize device caps */ /* Initialize device caps */
log_pixels_x = log_pixels_y = get_dpi(); log_pixels_x = log_pixels_y = get_dpi();
if (!log_pixels_x) if (!log_pixels_x)
{ {
size_t width = CGDisplayPixelsWide(mainDisplay); size_t width = CGDisplayPixelsWide(mainDisplay);
size_t height = CGDisplayPixelsHigh(mainDisplay); size_t height = CGDisplayPixelsHigh(mainDisplay);
if (retina_on)
{
/* Although CGDisplayPixelsWide/High() claim to report in pixels, they
actually report in points. */
width *= 2;
height *= 2;
}
log_pixels_x = MulDiv(width, 254, size_mm.width * 10); log_pixels_x = MulDiv(width, 254, size_mm.width * 10);
log_pixels_y = MulDiv(height, 254, size_mm.height * 10); log_pixels_y = MulDiv(height, 254, size_mm.height * 10);
} }
...@@ -181,7 +206,13 @@ static void device_init(void) ...@@ -181,7 +206,13 @@ static void device_init(void)
vert_res = CGDisplayPixelsHigh(mainDisplay); vert_res = CGDisplayPixelsHigh(mainDisplay);
} }
macdrv_get_desktop_rect(); if (retina_on)
{
horz_res *= 2;
vert_res *= 2;
}
compute_desktop_rect();
desktop_horz_res = desktop_rect.size.width; desktop_horz_res = desktop_rect.size.width;
desktop_vert_res = desktop_rect.size.height; desktop_vert_res = desktop_rect.size.height;
......
...@@ -219,6 +219,7 @@ extern CFArrayRef create_app_icon_images(void) DECLSPEC_HIDDEN; ...@@ -219,6 +219,7 @@ extern CFArrayRef create_app_icon_images(void) DECLSPEC_HIDDEN;
extern void macdrv_status_item_mouse_button(const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_status_item_mouse_button(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void check_retina_status(void) DECLSPEC_HIDDEN;
/************************************************************************** /**************************************************************************
* Mac IME driver * Mac IME driver
......
...@@ -160,6 +160,78 @@ extern int cursor_clipping_locks_windows DECLSPEC_HIDDEN; ...@@ -160,6 +160,78 @@ extern int cursor_clipping_locks_windows DECLSPEC_HIDDEN;
extern int use_precise_scrolling DECLSPEC_HIDDEN; extern int use_precise_scrolling DECLSPEC_HIDDEN;
extern int gl_surface_mode DECLSPEC_HIDDEN; extern int gl_surface_mode DECLSPEC_HIDDEN;
extern CFDictionaryRef localized_strings DECLSPEC_HIDDEN; extern CFDictionaryRef localized_strings DECLSPEC_HIDDEN;
extern int retina_enabled DECLSPEC_HIDDEN; /* Whether Retina mode is enabled via registry setting. */
extern int retina_on DECLSPEC_HIDDEN; /* Whether Retina mode is currently active (enabled and display is in default mode). */
static inline CGRect cgrect_mac_from_win(CGRect rect)
{
if (retina_on)
{
rect.origin.x /= 2;
rect.origin.y /= 2;
rect.size.width /= 2;
rect.size.height /= 2;
}
return rect;
}
static inline CGRect cgrect_win_from_mac(CGRect rect)
{
if (retina_on)
{
rect.origin.x *= 2;
rect.origin.y *= 2;
rect.size.width *= 2;
rect.size.height *= 2;
}
return rect;
}
static inline CGSize cgsize_mac_from_win(CGSize size)
{
if (retina_on)
{
size.width /= 2;
size.height /= 2;
}
return size;
}
static inline CGSize cgsize_win_from_mac(CGSize size)
{
if (retina_on)
{
size.width *= 2;
size.height *= 2;
}
return size;
}
static inline CGPoint cgpoint_mac_from_win(CGPoint point)
{
if (retina_on)
{
point.x /= 2;
point.y /= 2;
}
return point;
}
static inline CGPoint cgpoint_win_from_mac(CGPoint point)
{
if (retina_on)
{
point.x *= 2;
point.y *= 2;
}
return point;
}
extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN; extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN;
...@@ -168,6 +240,7 @@ extern void macdrv_set_application_icon(CFArrayRef images) DECLSPEC_HIDDEN; ...@@ -168,6 +240,7 @@ extern void macdrv_set_application_icon(CFArrayRef images) DECLSPEC_HIDDEN;
extern void macdrv_quit_reply(int reply) DECLSPEC_HIDDEN; extern void macdrv_quit_reply(int reply) DECLSPEC_HIDDEN;
extern int macdrv_using_input_method(void) DECLSPEC_HIDDEN; extern int macdrv_using_input_method(void) DECLSPEC_HIDDEN;
extern void macdrv_set_mouse_capture_window(macdrv_window window) DECLSPEC_HIDDEN; extern void macdrv_set_mouse_capture_window(macdrv_window window) DECLSPEC_HIDDEN;
extern void macdrv_set_cocoa_retina_mode(int new_mode) DECLSPEC_HIDDEN;
/* cursor */ /* cursor */
...@@ -443,6 +516,8 @@ extern void macdrv_dispose_view(macdrv_view v) DECLSPEC_HIDDEN; ...@@ -443,6 +516,8 @@ extern void macdrv_dispose_view(macdrv_view v) DECLSPEC_HIDDEN;
extern void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rect) DECLSPEC_HIDDEN; extern void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rect) DECLSPEC_HIDDEN;
extern void macdrv_add_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN; extern void macdrv_add_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN;
extern void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN; extern void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN;
extern int macdrv_get_view_backing_size(macdrv_view v, int backing_size[2]) DECLSPEC_HIDDEN;
extern void macdrv_set_view_backing_size(macdrv_view v, const int backing_size[2]) DECLSPEC_HIDDEN;
extern uint32_t macdrv_window_background_color(void) DECLSPEC_HIDDEN; extern uint32_t macdrv_window_background_color(void) DECLSPEC_HIDDEN;
extern void macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, int keyc, extern void macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, int keyc,
void* data, int* done) DECLSPEC_HIDDEN; void* data, int* done) DECLSPEC_HIDDEN;
...@@ -470,7 +545,7 @@ extern int macdrv_set_pasteboard_data(CFStringRef type, CFDataRef data, macdrv_w ...@@ -470,7 +545,7 @@ extern int macdrv_set_pasteboard_data(CFStringRef type, CFDataRef data, macdrv_w
/* opengl */ /* opengl */
extern macdrv_opengl_context macdrv_create_opengl_context(void* cglctx) DECLSPEC_HIDDEN; extern macdrv_opengl_context macdrv_create_opengl_context(void* cglctx) DECLSPEC_HIDDEN;
extern void macdrv_dispose_opengl_context(macdrv_opengl_context c) DECLSPEC_HIDDEN; extern void macdrv_dispose_opengl_context(macdrv_opengl_context c) DECLSPEC_HIDDEN;
extern void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v) DECLSPEC_HIDDEN; extern void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v, CGRect r) DECLSPEC_HIDDEN;
extern void macdrv_update_opengl_context(macdrv_opengl_context c) DECLSPEC_HIDDEN; extern void macdrv_update_opengl_context(macdrv_opengl_context c) DECLSPEC_HIDDEN;
extern void macdrv_flush_opengl_context(macdrv_opengl_context c) DECLSPEC_HIDDEN; extern void macdrv_flush_opengl_context(macdrv_opengl_context c) DECLSPEC_HIDDEN;
......
...@@ -58,6 +58,7 @@ int allow_immovable_windows = TRUE; ...@@ -58,6 +58,7 @@ int allow_immovable_windows = TRUE;
int cursor_clipping_locks_windows = TRUE; int cursor_clipping_locks_windows = TRUE;
int use_precise_scrolling = TRUE; int use_precise_scrolling = TRUE;
int gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE; int gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
int retina_enabled = FALSE;
HMODULE macdrv_module = 0; HMODULE macdrv_module = 0;
CFDictionaryRef localized_strings; CFDictionaryRef localized_strings;
...@@ -196,6 +197,11 @@ static void setup_options(void) ...@@ -196,6 +197,11 @@ static void setup_options(void)
gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE; gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
} }
/* Don't use appkey. The DPI and monitor sizes should be consistent for all
processes in the prefix. */
if (!get_config_key(hkey, NULL, "RetinaMode", buffer, sizeof(buffer)))
retina_enabled = IS_OPTION_TRUE(buffer[0]);
if (appkey) RegCloseKey(appkey); if (appkey) RegCloseKey(appkey);
if (hkey) RegCloseKey(hkey); if (hkey) RegCloseKey(hkey);
} }
......
...@@ -65,12 +65,15 @@ struct wgl_context ...@@ -65,12 +65,15 @@ struct wgl_context
CGLContextObj cglcontext; CGLContextObj cglcontext;
HWND draw_hwnd; HWND draw_hwnd;
macdrv_view draw_view; macdrv_view draw_view;
RECT draw_rect;
struct wgl_pbuffer *draw_pbuffer; struct wgl_pbuffer *draw_pbuffer;
macdrv_view read_view; macdrv_view read_view;
RECT read_rect;
struct wgl_pbuffer *read_pbuffer; struct wgl_pbuffer *read_pbuffer;
BOOL has_been_current; BOOL has_been_current;
BOOL sharing; BOOL sharing;
LONG update_swap_interval; LONG update_swap_interval;
LONG view_moved;
DWORD last_flush_time; DWORD last_flush_time;
UINT major; UINT major;
}; };
...@@ -1691,6 +1694,23 @@ done: ...@@ -1691,6 +1694,23 @@ done:
/********************************************************************** /**********************************************************************
* mark_contexts_for_moved_view
*/
static void mark_contexts_for_moved_view(macdrv_view view)
{
struct wgl_context *context;
EnterCriticalSection(&context_section);
LIST_FOR_EACH_ENTRY(context, &context_list, struct wgl_context, entry)
{
if (context->draw_view == view)
InterlockedExchange(&context->view_moved, TRUE);
}
LeaveCriticalSection(&context_section);
}
/**********************************************************************
* set_gl_view_parent * set_gl_view_parent
*/ */
void set_gl_view_parent(HWND hwnd, HWND parent) void set_gl_view_parent(HWND hwnd, HWND parent)
...@@ -1716,6 +1736,7 @@ void set_gl_view_parent(HWND hwnd, HWND parent) ...@@ -1716,6 +1736,7 @@ void set_gl_view_parent(HWND hwnd, HWND parent)
} }
macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect)); macdrv_set_view_window_and_frame(data->gl_view, cocoa_window, cgrect_from_rect(data->gl_rect));
mark_contexts_for_moved_view(data->gl_view);
} }
release_win_data(data); release_win_data(data);
...@@ -1723,28 +1744,59 @@ void set_gl_view_parent(HWND hwnd, HWND parent) ...@@ -1723,28 +1744,59 @@ void set_gl_view_parent(HWND hwnd, HWND parent)
/********************************************************************** /**********************************************************************
* sync_context_rect
*/
static BOOL sync_context_rect(struct wgl_context *context)
{
BOOL ret = FALSE;
if (InterlockedCompareExchange(&context->view_moved, FALSE, TRUE))
{
struct macdrv_win_data *data = get_win_data(context->draw_hwnd);
if (data && data->gl_view && data->gl_view == context->draw_view &&
memcmp(&context->draw_rect, &data->gl_rect, sizeof(context->draw_rect)))
{
context->draw_rect = data->gl_rect;
ret = TRUE;
}
release_win_data(data);
}
return ret;
}
/**********************************************************************
* make_context_current * make_context_current
*/ */
static void make_context_current(struct wgl_context *context, BOOL read) static void make_context_current(struct wgl_context *context, BOOL read)
{ {
macdrv_view view; macdrv_view view;
RECT view_rect;
struct wgl_pbuffer *pbuffer; struct wgl_pbuffer *pbuffer;
if (read) if (read)
{ {
view = context->read_view; view = context->read_view;
view_rect = context->read_rect;
pbuffer = context->read_pbuffer; pbuffer = context->read_pbuffer;
} }
else else
{ {
sync_context_rect(context);
view = context->draw_view; view = context->draw_view;
view_rect = context->draw_rect;
pbuffer = context->draw_pbuffer; pbuffer = context->draw_pbuffer;
} }
if (view || !pbuffer) if (view || !pbuffer)
macdrv_make_context_current(context->context, view); macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect));
else else
{ {
GLint enabled;
if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled)
CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize);
CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face, CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face,
pbuffer->level, 0); pbuffer->level, 0);
CGLSetCurrentContext(context->cglcontext); CGLSetCurrentContext(context->cglcontext);
...@@ -1753,6 +1805,16 @@ static void make_context_current(struct wgl_context *context, BOOL read) ...@@ -1753,6 +1805,16 @@ static void make_context_current(struct wgl_context *context, BOOL read)
/********************************************************************** /**********************************************************************
* sync_context
*/
static void sync_context(struct wgl_context *context)
{
if (sync_context_rect(context))
make_context_current(context, FALSE);
}
/**********************************************************************
* set_swap_interval * set_swap_interval
*/ */
static BOOL set_swap_interval(struct wgl_context *context, long interval) static BOOL set_swap_interval(struct wgl_context *context, long interval)
...@@ -2275,6 +2337,7 @@ static void macdrv_glFinish(void) ...@@ -2275,6 +2337,7 @@ static void macdrv_glFinish(void)
struct wgl_context *context = NtCurrentTeb()->glContext; struct wgl_context *context = NtCurrentTeb()->glContext;
sync_swap_interval(context); sync_swap_interval(context);
sync_context(context);
pglFinish(); pglFinish();
} }
...@@ -2287,6 +2350,7 @@ static void macdrv_glFlush(void) ...@@ -2287,6 +2350,7 @@ static void macdrv_glFlush(void)
struct wgl_context *context = NtCurrentTeb()->glContext; struct wgl_context *context = NtCurrentTeb()->glContext;
sync_swap_interval(context); sync_swap_interval(context);
sync_context(context);
if (skip_single_buffer_flushes) if (skip_single_buffer_flushes)
{ {
...@@ -2367,6 +2431,7 @@ static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) ...@@ -2367,6 +2431,7 @@ static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
{ {
struct wgl_context *context = NtCurrentTeb()->glContext; struct wgl_context *context = NtCurrentTeb()->glContext;
sync_context(context);
macdrv_update_opengl_context(context->context); macdrv_update_opengl_context(context->context);
pglViewport(x, y, width, height); pglViewport(x, y, width, height);
} }
...@@ -3552,7 +3617,7 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w ...@@ -3552,7 +3617,7 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w
if (!context) if (!context)
{ {
macdrv_make_context_current(NULL, NULL); macdrv_make_context_current(NULL, NULL, CGRectNull);
NtCurrentTeb()->glContext = NULL; NtCurrentTeb()->glContext = NULL;
return TRUE; return TRUE;
} }
...@@ -3585,6 +3650,7 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w ...@@ -3585,6 +3650,7 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w
context->draw_hwnd = hwnd; context->draw_hwnd = hwnd;
context->draw_view = data->gl_view; context->draw_view = data->gl_view;
context->draw_rect = data->gl_rect;
context->draw_pbuffer = NULL; context->draw_pbuffer = NULL;
release_win_data(data); release_win_data(data);
} }
...@@ -3631,7 +3697,10 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w ...@@ -3631,7 +3697,10 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w
if ((data = get_win_data(hwnd))) if ((data = get_win_data(hwnd)))
{ {
if (data->gl_view != context->draw_view) if (data->gl_view != context->draw_view)
{
context->read_view = data->gl_view; context->read_view = data->gl_view;
context->read_rect = data->gl_rect;
}
release_win_data(data); release_win_data(data);
} }
} }
...@@ -3643,8 +3712,9 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w ...@@ -3643,8 +3712,9 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w
} }
} }
TRACE("making context current with draw_view %p draw_pbuffer %p read_view %p read_pbuffer %p format %u\n", TRACE("making context current with draw_view %p %s draw_pbuffer %p read_view %p %s read_pbuffer %p format %u\n",
context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format); context->draw_view, wine_dbgstr_rect(&context->draw_rect), context->draw_pbuffer,
context->read_view, wine_dbgstr_rect(&context->read_rect), context->read_pbuffer, context->format);
make_context_current(context, FALSE); make_context_current(context, FALSE);
context->has_been_current = TRUE; context->has_been_current = TRUE;
...@@ -4361,6 +4431,7 @@ void sync_gl_view(struct macdrv_win_data *data) ...@@ -4361,6 +4431,7 @@ void sync_gl_view(struct macdrv_win_data *data)
TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect)); TRACE("Setting GL view %p frame to %s\n", data->gl_view, wine_dbgstr_rect(&rect));
macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect)); macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect));
data->gl_rect = rect; data->gl_rect = rect;
mark_contexts_for_moved_view(data->gl_view);
} }
} }
...@@ -4607,7 +4678,10 @@ static BOOL macdrv_wglSwapBuffers(HDC hdc) ...@@ -4607,7 +4678,10 @@ static BOOL macdrv_wglSwapBuffers(HDC hdc)
(context ? context->cglcontext : NULL)); (context ? context->cglcontext : NULL));
if (context) if (context)
{
sync_swap_interval(context); sync_swap_interval(context);
sync_context(context);
}
if ((hwnd = WindowFromDC(hdc))) if ((hwnd = WindowFromDC(hdc)))
{ {
......
...@@ -403,7 +403,7 @@ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_dat ...@@ -403,7 +403,7 @@ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_dat
cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect), cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect),
8, 32, bytes_per_row, colorspace, 8, 32, bytes_per_row, colorspace,
alphaInfo | kCGBitmapByteOrder32Little, alphaInfo | kCGBitmapByteOrder32Little,
provider, NULL, FALSE, kCGRenderingIntentDefault); provider, NULL, retina_on, kCGRenderingIntentDefault);
CGDataProviderRelease(provider); CGDataProviderRelease(provider);
CGColorSpaceRelease(colorspace); CGColorSpaceRelease(colorspace);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment