diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m index 97d13e2e05f..f64de31632a 100644 --- a/dlls/winemac.drv/cocoa_app.m +++ b/dlls/winemac.drv/cocoa_app.m @@ -1590,6 +1590,7 @@ - (void) handleMouseMove:(NSEvent*)anEvent { if (clippingCursor) [self clipCursorLocation:&point]; + point = cgpoint_win_from_mac(point); event = macdrv_create_event(MOUSE_MOVED_ABSOLUTE, targetWindow); event->mouse_moved.x = floor(point.x); @@ -1600,18 +1601,20 @@ - (void) handleMouseMove:(NSEvent*)anEvent } else { + double scale = retina_on ? 2 : 1; + /* Add event delta to accumulated delta error */ /* deltaY is already flipped */ mouseMoveDeltaX += [anEvent deltaX]; mouseMoveDeltaY += [anEvent deltaY]; event = macdrv_create_event(MOUSE_MOVED, targetWindow); - event->mouse_moved.x = mouseMoveDeltaX; - event->mouse_moved.y = mouseMoveDeltaY; + event->mouse_moved.x = mouseMoveDeltaX * scale; + event->mouse_moved.y = mouseMoveDeltaY * scale; /* Keep the remainder after integer truncation. */ - mouseMoveDeltaX -= event->mouse_moved.x; - mouseMoveDeltaY -= event->mouse_moved.y; + mouseMoveDeltaX -= event->mouse_moved.x / scale; + mouseMoveDeltaY -= event->mouse_moved.y / scale; } if (event->type == MOUSE_MOVED_ABSOLUTE || event->mouse_moved.x || event->mouse_moved.y) @@ -1730,6 +1733,8 @@ - (void) handleMouseButton:(NSEvent*)theEvent { macdrv_event* event; + pt = cgpoint_win_from_mac(pt); + event = macdrv_create_event(MOUSE_BUTTON, window); event->mouse_button.button = [theEvent buttonNumber]; event->mouse_button.pressed = pressed; @@ -1811,6 +1816,8 @@ - (void) handleScrollWheel:(NSEvent*)theEvent double x, y; BOOL continuous = FALSE; + pt = cgpoint_win_from_mac(pt); + event = macdrv_create_event(MOUSE_SCROLL, window); event->mouse_scroll.x = floor(pt.x); event->mouse_scroll.y = floor(pt.y); @@ -2146,6 +2153,26 @@ - (void) unminimizeWindowIfNoneVisible } } + - (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 ---------- @@ -2496,7 +2523,7 @@ int macdrv_get_cursor_position(CGPoint *pos) OnMainThread(^{ NSPoint location = [NSEvent mouseLocation]; location = [[WineApplicationController sharedController] flippedMouseLocation:location]; - *pos = NSPointToCGPoint(location); + *pos = cgpoint_win_from_mac(NSPointToCGPoint(location)); }); return TRUE; @@ -2513,7 +2540,7 @@ int macdrv_set_cursor_position(CGPoint pos) __block int ret; OnMainThread(^{ - ret = [[WineApplicationController sharedController] setCursorPosition:pos]; + ret = [[WineApplicationController sharedController] setCursorPosition:cgpoint_mac_from_win(pos)]; }); return ret; @@ -2526,13 +2553,17 @@ int macdrv_set_cursor_position(CGPoint pos) * to or larger than the whole desktop region, the cursor is unclipped. * Returns zero on failure, non-zero on success. */ -int macdrv_clip_cursor(CGRect rect) +int macdrv_clip_cursor(CGRect r) { __block int ret; OnMainThread(^{ WineApplicationController* controller = [WineApplicationController sharedController]; BOOL clipping = FALSE; + CGRect rect = r; + + if (!CGRectIsInfinite(rect)) + rect = cgrect_mac_from_win(rect); if (!CGRectIsInfinite(rect)) { @@ -2676,3 +2707,10 @@ int macdrv_select_input_source(TISInputSourceRef input_source) return ret; } + +void macdrv_set_cocoa_retina_mode(int new_mode) +{ + OnMainThread(^{ + [[WineApplicationController sharedController] setRetinaMode:new_mode]; + }); +} diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m index 5e3c8f34161..93a0fbca353 100644 --- a/dlls/winemac.drv/cocoa_display.m +++ b/dlls/winemac.drv/cocoa_display.m @@ -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].work_frame, visible_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; diff --git a/dlls/winemac.drv/cocoa_event.m b/dlls/winemac.drv/cocoa_event.m index 9ce43fb0ba7..08a706fd8ba 100644 --- a/dlls/winemac.drv/cocoa_event.m +++ b/dlls/winemac.drv/cocoa_event.m @@ -323,6 +323,8 @@ - (void) resetMouseEventPositions:(CGPoint)pos { MacDrvEvent* event; + pos = cgpoint_win_from_mac(pos); + [eventsLock lock]; for (event in events) diff --git a/dlls/winemac.drv/cocoa_opengl.h b/dlls/winemac.drv/cocoa_opengl.h index 2cdcdbdefb1..e7e16868e93 100644 --- a/dlls/winemac.drv/cocoa_opengl.h +++ b/dlls/winemac.drv/cocoa_opengl.h @@ -26,6 +26,8 @@ @interface WineOpenGLContext : NSOpenGLContext NSView* latentView; BOOL needsUpdate; BOOL shouldClearToBlack; + + GLint backing_size[2]; } @property BOOL needsUpdate; diff --git a/dlls/winemac.drv/cocoa_opengl.m b/dlls/winemac.drv/cocoa_opengl.m index ec2b19198c2..debeb78c523 100644 --- a/dlls/winemac.drv/cocoa_opengl.m +++ b/dlls/winemac.drv/cocoa_opengl.m @@ -27,6 +27,10 @@ @interface WineOpenGLContext () @property (retain, nonatomic) NSView* latentView; + + + (NSView*) dummyView; + - (void) wine_updateBackingSize:(const CGSize*)size; + @end @@ -40,6 +44,81 @@ - (void) 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 { NSView* oldView = [self view]; @@ -53,6 +132,8 @@ - (void) clearDrawable NSView* oldView = [self view]; [super clearDrawable]; [oldView release]; + + [self wine_updateBackingSize:NULL]; } /* On at least some versions of Mac OS X, -[NSOpenGLContext clearDrawable] has the @@ -64,19 +145,7 @@ a different view (the content view of an off-screen window) and then letting the original implementation proceed. */ - (void) clearDrawableLeavingSurfaceOnScreen { - 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]; - }); - }); - - [self setView:[dummyWindow contentView]]; + [self setView:[[self class] dummyView]]; [self clearDrawable]; } @@ -189,7 +258,7 @@ void macdrv_dispose_opengl_context(macdrv_opengl_context c) /*********************************************************************** * 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]; WineOpenGLContext *context = (WineOpenGLContext*)c; @@ -198,7 +267,10 @@ void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v) if (context && view) { if (view == [context view] || view == [context latentView]) + { + [context wine_updateBackingSize:&r.size]; macdrv_update_opengl_context(c); + } else { [context removeFromViews:NO]; @@ -207,13 +279,18 @@ void macdrv_make_context_current(macdrv_opengl_context c, macdrv_view v) if (context.needsUpdate) { context.needsUpdate = FALSE; + if (context.view) + [context setView:[[context class] dummyView]]; + [context wine_updateBackingSize:&r.size]; [context setView:view]; [context setLatentView:nil]; + [context resetSurfaceIfBackingSizeChanged]; } else { if ([context view]) [context clearDrawableLeavingSurfaceOnScreen]; + [context wine_updateBackingSize:&r.size]; [context setLatentView:view]; } } @@ -257,10 +334,14 @@ void macdrv_update_opengl_context(macdrv_opengl_context c) [context setView:context.latentView]; context.latentView = nil; + [context resetSurfaceIfBackingSizeChanged]; [context clearToBlackIfNeeded]; } else + { [context update]; + [context resetSurfaceIfBackingSizeChanged]; + } } [pool release]; diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index 19e57789950..d52a9d2f8ec 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -46,6 +46,9 @@ @interface WineWindow : NSPanel CGDirectDisplayID _lastDisplayID; NSTimeInterval _lastDisplayTime; + NSRect wineFrame; + NSRect roundedWineFrame; + NSBezierPath* shape; NSData* shapeData; BOOL shapeChangedSinceLastDraw; @@ -88,6 +91,7 @@ @interface WineWindow : NSPanel @property (readonly, nonatomic) BOOL floating; @property (readonly, getter=isFullscreen, nonatomic) BOOL fullscreen; @property (readonly, getter=isFakingClose, nonatomic) BOOL fakingClose; +@property (readonly, nonatomic) NSRect wine_fractionalFrame; - (NSInteger) minimumLevelForActive:(BOOL)active; - (void) updateFullscreen; @@ -99,4 +103,6 @@ - (WineWindow*) ancestorWineWindow; - (void) updateForCursorClipping; + - (void) setRetinaMode:(int)mode; + @end diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 1b0b6555a4d..aee99816f89 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -294,12 +294,17 @@ @interface WineContentView : NSView NSMutableAttributedString* markedText; NSRange markedTextSelection; + + int backingSize[2]; } - (void) addGLContext:(WineOpenGLContext*)context; - (void) removeGLContext:(WineOpenGLContext*)context; - (void) updateGLContexts; + - (void) wine_getBackingSize:(int*)outBackingSize; + - (void) wine_setBackingSize:(const int*)newBackingSize; + @end @@ -393,6 +398,7 @@ - (void) drawRect:(NSRect)rect if (get_surface_blit_rects(window.surface, &rects, &count) && count) { + CGRect dirtyRect = cgrect_win_from_mac(NSRectToCGRect(rect)); CGContextRef context; int i; @@ -400,14 +406,14 @@ - (void) drawRect:(NSRect)rect context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; CGContextSetBlendMode(context, kCGBlendModeCopy); - CGContextSetInterpolationQuality(context, kCGInterpolationNone); + CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone); for (i = 0; i < count; i++) { CGRect imageRect; CGImageRef image; - imageRect = CGRectIntersection(rects[i], NSRectToCGRect(rect)); + imageRect = CGRectIntersection(rects[i], dirtyRect); image = create_surface_image(window.surface, &imageRect, FALSE); if (image) @@ -426,7 +432,7 @@ - (void) drawRect:(NSRect)rect } } - CGContextDrawImage(context, imageRect, image); + CGContextDrawImage(context, cgrect_mac_from_win(imageRect), image); CGImageRelease(image); } @@ -490,6 +496,19 @@ - (BOOL) hasGLContext 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 { return YES; @@ -652,7 +671,7 @@ - (NSRect) firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointe if ([window.queue query:query timeout:0.3 flags:WineQueryNoPreemptWait]) { 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]; } else @@ -772,6 +791,8 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w name:NSWorkspaceActiveSpaceDidChangeNotification object:[NSWorkspace sharedWorkspace]]; + [window setFrameAndWineFrame:[window frameRectForContentRect:window_frame]]; + return window; } @@ -821,7 +842,7 @@ - (void) adjustFeaturesForState if ([self preventResizing]) { - NSSize size = [self contentRectForFrameRect:[self frame]].size; + NSSize size = [self contentRectForFrameRect:self.wine_fractionalFrame].size; [self setContentMinSize:size]; [self setContentMaxSize:size]; } @@ -1433,7 +1454,7 @@ - (void) doOrderOut - (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]); if (nowFullscreen != fullscreen) @@ -1448,6 +1469,32 @@ - (void) updateFullscreen } } + - (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 { /* Origin is (left, top) in a top-down space. Need to convert it to @@ -1464,7 +1511,7 @@ - (void) setFrameFromWine:(NSRect)contentRect { NSRect frame, oldFrame; - oldFrame = [self frame]; + oldFrame = self.wine_fractionalFrame; frame = [self frameRectForContentRect:contentRect]; if (!NSEqualRects(frame, oldFrame)) { @@ -1498,7 +1545,7 @@ - (void) setFrameFromWine:(NSRect)contentRect ignore_windowResize = FALSE; } - [self setFrame:frame display:YES]; + [self setFrameAndWineFrame:frame]; if ([self preventResizing]) { [self setContentMinSize:contentRect.size]; @@ -1527,6 +1574,14 @@ - (void) setFrameFromWine:(NSRect)contentRect } } + - (NSRect) wine_fractionalFrame + { + NSRect frame = self.frame; + if (NSEqualRects(frame, roundedWineFrame)) + frame = wineFrame; + return frame; + } + - (void) setMacDrvParentWindow:(WineWindow*)parent { WineWindow* oldParent = (WineWindow*)[self parentWindow]; @@ -2052,7 +2107,7 @@ - (void) sendEvent:(NSEvent*)event event = macdrv_create_event(WINDOW_RESTORE_REQUESTED, self); 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]; macdrv_release_event(event); @@ -2165,6 +2220,57 @@ - (void) updateForGLSubviews [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 ---------- @@ -2337,7 +2443,7 @@ - (void) windowDidEnterFullScreen:(NSNotification*)notification - (void) windowDidExitFullScreen:(NSNotification*)notification { exitingFullScreen = FALSE; - [self setFrame:nonFullscreenFrame display:YES animate:NO]; + [self setFrameAndWineFrame:nonFullscreenFrame]; [self windowDidResize:nil]; } @@ -2379,7 +2485,7 @@ - (void)windowDidResignKey:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification { macdrv_event* event; - NSRect frame = [self frame]; + NSRect frame = self.wine_fractionalFrame; if ([self inLiveResize]) { @@ -2406,7 +2512,7 @@ - (void)windowDidResize:(NSNotification *)notification forWindow: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.in_resize = [self inLiveResize]; [queue postEvent:event]; @@ -2466,7 +2572,7 @@ - (void) windowWillClose:(NSNotification*)notification - (void) windowWillEnterFullScreen:(NSNotification*)notification { enteringFullScreen = TRUE; - nonFullscreenFrame = [self frame]; + nonFullscreenFrame = self.wine_fractionalFrame; } - (void) windowWillExitFullScreen:(NSNotification*)notification @@ -2485,7 +2591,7 @@ - (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize if ([self inLiveResize]) { if (maximized) - return self.frame.size; + return self.wine_fractionalFrame.size; NSRect rect; macdrv_query* query; @@ -2502,13 +2608,13 @@ - (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize query = macdrv_create_query(); query->type = QUERY_RESIZE_SIZE; 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_top = resizingFromTop; 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]; frameSize = rect.size; } @@ -2532,7 +2638,7 @@ - (void) windowWillStartLiveResize:(NSNotification *)notification event = macdrv_create_event(WINDOW_RESTORE_REQUESTED, self); 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]; macdrv_release_event(event); } @@ -2625,13 +2731,14 @@ - (NSDragOperation) draggingUpdated:(id )sender { NSDragOperation ret; NSPoint pt = [[self contentView] convertPoint:[sender draggingLocation] fromView:nil]; + CGPoint cgpt = cgpoint_win_from_mac(NSPointToCGPoint(pt)); NSPasteboard* pb = [sender draggingPasteboard]; macdrv_query* query = macdrv_create_query(); query->type = QUERY_DRAG_OPERATION; query->window = (macdrv_window)[self retain]; - query->drag_operation.x = floor(pt.x); - query->drag_operation.y = floor(pt.y); + query->drag_operation.x = floor(cgpt.x); + query->drag_operation.y = floor(cgpt.y); query->drag_operation.offered_ops = [sender draggingSourceOperationMask]; query->drag_operation.accepted_op = NSDragOperationNone; query->drag_operation.pasteboard = (CFTypeRef)[pb retain]; @@ -2647,13 +2754,14 @@ - (BOOL) performDragOperation:(id )sender { BOOL ret; NSPoint pt = [[self contentView] convertPoint:[sender draggingLocation] fromView:nil]; + CGPoint cgpt = cgpoint_win_from_mac(NSPointToCGPoint(pt)); NSPasteboard* pb = [sender draggingPasteboard]; macdrv_query* query = macdrv_create_query(); query->type = QUERY_DRAG_DROP; query->window = (macdrv_window)[self retain]; - query->drag_drop.x = floor(pt.x); - query->drag_drop.y = floor(pt.y); + query->drag_drop.x = floor(cgpt.x); + query->drag_drop.y = floor(cgpt.y); query->drag_drop.op = [sender draggingSourceOperationMask]; query->drag_drop.pasteboard = (CFTypeRef)[pb retain]; @@ -2685,7 +2793,7 @@ macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf OnMainThread(^{ window = [[WineWindow createWindowWithFeatures:wf - windowFrame:NSRectFromCGRect(frame) + windowFrame:NSRectFromCGRect(cgrect_mac_from_win(frame)) hwnd:hwnd queue:(WineEventQueue*)queue] retain]; }); @@ -2829,7 +2937,7 @@ void macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame) WineWindow* window = (WineWindow*)w; 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) OnMainThread(^{ NSRect frame; - frame = [window contentRectForFrameRect:[window frame]]; + frame = [window contentRectForFrameRect:[window wine_fractionalFrame]]; [[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) WineWindow* window = (WineWindow*)w; OnMainThreadAsync(^{ - [[window contentView] setNeedsDisplayInRect:NSRectFromCGRect(rect)]; + [[window contentView] setNeedsDisplayInRect:NSRectFromCGRect(cgrect_mac_from_win(rect))]; }); [pool release]; @@ -2928,7 +3036,7 @@ void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count) path = [NSBezierPath bezierPath]; for (i = 0; i < count; i++) - [path appendBezierPathWithRect:NSRectFromCGRect(rects[i])]; + [path appendBezierPathWithRect:NSRectFromCGRect(cgrect_mac_from_win(rects[i]))]; window.shape = path; window.shapeData = [NSData dataWithBytes:rects length:length]; [window checkEmptyShaped]; @@ -3030,7 +3138,7 @@ void macdrv_set_window_min_max_sizes(macdrv_window w, CGSize min_size, CGSize ma WineWindow* window = (WineWindow*)w; 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) OnMainThread(^{ NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; - view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(rect)]; + view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))]; [view setAutoresizesSubviews:NO]; [nc addObserver:view selector:@selector(updateGLContexts) @@ -3115,7 +3223,7 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec OnMainThread(^{ BOOL changedWindow = (window && window != [view window]); - NSRect newFrame = NSRectFromCGRect(rect); + NSRect newFrame = NSRectFromCGRect(cgrect_mac_from_win(rect)); NSRect oldFrame = [view frame]; BOOL needUpdateWindowForGLSubviews = FALSE; @@ -3140,6 +3248,12 @@ void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rec [view setFrame:newFrame]; [view setNeedsDisplay:YES]; needUpdateWindowForGLSubviews = TRUE; + + if (retina_enabled) + { + int backing_size[2] = { 0 }; + [view wine_setBackingSize:backing_size]; + } } if (needUpdateWindowForGLSubviews) @@ -3185,6 +3299,25 @@ void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c) [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 * diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c index ad01191eaf0..49892ca3ef2 100644 --- a/dlls/winemac.drv/display.c +++ b/dlls/winemac.drv/display.c @@ -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 -static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode) +static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode, BOOL is_original) { CFDictionaryRef ret; SInt32 io_flags = CGDisplayModeGetIOFlags(display_mode); @@ -498,6 +498,12 @@ static CFDictionaryRef create_mode_dict(CGDisplayModeRef display_mode) CFStringRef pixel_encoding = CGDisplayModeCopyPixelEncoding(display_mode); CFNumberRef cf_io_flags, cf_width, cf_height, cf_refresh; + if (retina_enabled && is_original) + { + width *= 2; + height *= 2; + } + io_flags &= kDisplayModeValidFlag | kDisplayModeSafeFlag | kDisplayModeInterlacedFlag | kDisplayModeStretchedFlag | kDisplayModeTelevisionFlag; cf_io_flags = CFNumberCreate(NULL, kCFNumberSInt32Type, &io_flags); @@ -581,7 +587,7 @@ static CFArrayRef copy_display_modes(CGDirectDisplayID display) BOOL better = TRUE; CGDisplayModeRef new_mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i); 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 modes that may exist. */ @@ -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.@) * @@ -681,9 +704,11 @@ LONG CDECL macdrv_ChangeDisplaySettingsEx(LPCWSTR devname, LPDEVMODEW devmode, struct macdrv_display *displays; int num_displays; CFArrayRef display_modes; + struct display_mode_descriptor* desc; CFIndex count, i, safe, best; CGDisplayModeRef best_display_mode; uint32_t best_io_flags; + BOOL best_is_original; 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, TRACE(" %sinterlaced", devmode->dmDisplayFlags & DM_INTERLACED ? "" : "non-"); TRACE("\n"); + desc = create_original_display_mode_descriptor(displays[0].displayID); + safe = -1; best_display_mode = NULL; count = CFArrayGetCount(display_modes); for (i = 0; i < count; 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); int mode_bpp = display_mode_bits_per_pixel(display_mode); size_t width = CGDisplayModeGetWidth(display_mode); size_t height = CGDisplayModeGetHeight(display_mode); + if (is_original && retina_enabled) + { + width *= 2; + height *= 2; + } + if (!(io_flags & kDisplayModeValidFlag) || !(io_flags & kDisplayModeSafeFlag)) continue; @@ -817,6 +851,7 @@ better: best_display_mode = display_mode; best = safe; best_io_flags = io_flags; + best_is_original = is_original; } if (best_display_mode) @@ -837,6 +872,12 @@ better: size_t width = CGDisplayModeGetWidth(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, MAKELPARAM(width, height)); ret = DISP_CHANGE_SUCCESSFUL; @@ -854,6 +895,7 @@ better: bpp, devmode->dmDisplayFrequency); } + free_display_mode_descriptor(desc); CFRelease(display_modes); macdrv_free_displays(displays); @@ -1082,6 +1124,16 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, devmode->dmPelsWidth = CGDisplayModeGetWidth(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->dmDisplayFlags = 0; @@ -1329,8 +1381,18 @@ void macdrv_displays_changed(const macdrv_event *event) size_t width = CGDisplayModeGetWidth(mode); size_t height = CGDisplayModeGetHeight(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); + + if (is_original && retina_enabled) + { + width *= 2; + height *= 2; + } + SendMessageW(hwnd, WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp, MAKELPARAM(width, height)); } diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index 9f18ac4865c..e110227037e 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -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 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_DEBUG critsect_debug = { @@ -93,6 +95,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 * @@ -101,27 +126,16 @@ static DWORD get_dpi(void) CGRect macdrv_get_desktop_rect(void) { CGRect ret; - CGDirectDisplayID displayIDs[32]; - uint32_t count, i; EnterCriticalSection(&device_data_section); if (!device_data_valid) { - 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])); + check_retina_status(); + compute_desktop_rect(); } - ret = desktop_rect; + LeaveCriticalSection(&device_data_section); TRACE("%s\n", wine_dbgstr_cgrect(ret)); @@ -141,12 +155,23 @@ static void device_init(void) CGSize size_mm = CGDisplayScreenSize(mainDisplay); CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay); + check_retina_status(); + /* Initialize device caps */ log_pixels_x = log_pixels_y = get_dpi(); if (!log_pixels_x) { size_t width = CGDisplayPixelsWide(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_y = MulDiv(height, 254, size_mm.height * 10); } @@ -181,7 +206,13 @@ static void device_init(void) 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_vert_res = desktop_rect.size.height; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index f3b5e65ccb0..b6b4819c0d7 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -219,6 +219,7 @@ extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP 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 check_retina_status(void) DECLSPEC_HIDDEN; /************************************************************************** * Mac IME driver diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 5dc84e20485..2c06beab5c3 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -160,6 +160,78 @@ extern int use_precise_scrolling DECLSPEC_HIDDEN; extern int gl_surface_mode 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 void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN; @@ -168,6 +240,7 @@ extern void macdrv_quit_reply(int reply) 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_cocoa_retina_mode(int new_mode) DECLSPEC_HIDDEN; /* cursor */ @@ -443,6 +516,8 @@ extern void macdrv_set_window_color_key(macdrv_window w, CGFloat keyRed, CGFloat 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_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 void macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, int keyc, void* data, int* done) DECLSPEC_HIDDEN; @@ -470,7 +545,7 @@ extern void macdrv_get_input_source_info(CFDataRef* uchr,CGEventSourceKeyboardTy /* opengl */ 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_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_flush_opengl_context(macdrv_opengl_context c) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index 5af0f411409..2ce78d1caa2 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -58,6 +58,7 @@ int allow_immovable_windows = TRUE; int cursor_clipping_locks_windows = TRUE; int use_precise_scrolling = TRUE; int gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE; +int retina_enabled = FALSE; HMODULE macdrv_module = 0; CFDictionaryRef localized_strings; @@ -196,6 +197,11 @@ static void setup_options(void) 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 (hkey) RegCloseKey(hkey); } diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index 728866b82df..fbdc645919e 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -65,12 +65,15 @@ struct wgl_context CGLContextObj cglcontext; HWND draw_hwnd; macdrv_view draw_view; + RECT draw_rect; struct wgl_pbuffer *draw_pbuffer; macdrv_view read_view; + RECT read_rect; struct wgl_pbuffer *read_pbuffer; BOOL has_been_current; BOOL sharing; LONG update_swap_interval; + LONG view_moved; DWORD last_flush_time; UINT major; }; @@ -1690,6 +1693,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 */ @@ -1716,35 +1736,67 @@ 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)); + mark_contexts_for_moved_view(data->gl_view); } release_win_data(data); } +/********************************************************************** + * 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 */ static void make_context_current(struct wgl_context *context, BOOL read) { macdrv_view view; + RECT view_rect; struct wgl_pbuffer *pbuffer; if (read) { view = context->read_view; + view_rect = context->read_rect; pbuffer = context->read_pbuffer; } else { + sync_context_rect(context); + view = context->draw_view; + view_rect = context->draw_rect; pbuffer = context->draw_pbuffer; } if (view || !pbuffer) - macdrv_make_context_current(context->context, view); + macdrv_make_context_current(context->context, view, cgrect_from_rect(view_rect)); else { + GLint enabled; + + if (CGLIsEnabled(context->cglcontext, kCGLCESurfaceBackingSize, &enabled) == kCGLNoError && enabled) + CGLDisable(context->cglcontext, kCGLCESurfaceBackingSize); CGLSetPBuffer(context->cglcontext, pbuffer->pbuffer, pbuffer->face, pbuffer->level, 0); CGLSetCurrentContext(context->cglcontext); @@ -1752,6 +1804,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 */ @@ -2275,6 +2337,7 @@ static void macdrv_glFinish(void) struct wgl_context *context = NtCurrentTeb()->glContext; sync_swap_interval(context); + sync_context(context); pglFinish(); } @@ -2287,6 +2350,7 @@ static void macdrv_glFlush(void) struct wgl_context *context = NtCurrentTeb()->glContext; sync_swap_interval(context); + sync_context(context); if (skip_single_buffer_flushes) { @@ -2367,6 +2431,7 @@ static void macdrv_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { struct wgl_context *context = NtCurrentTeb()->glContext; + sync_context(context); macdrv_update_opengl_context(context->context); pglViewport(x, y, width, height); } @@ -3552,7 +3617,7 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w if (!context) { - macdrv_make_context_current(NULL, NULL); + macdrv_make_context_current(NULL, NULL, CGRectNull); NtCurrentTeb()->glContext = NULL; return TRUE; } @@ -3585,6 +3650,7 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w context->draw_hwnd = hwnd; context->draw_view = data->gl_view; + context->draw_rect = data->gl_rect; context->draw_pbuffer = NULL; release_win_data(data); } @@ -3631,7 +3697,10 @@ static BOOL macdrv_wglMakeContextCurrentARB(HDC draw_hdc, HDC read_hdc, struct w if ((data = get_win_data(hwnd))) { if (data->gl_view != context->draw_view) + { context->read_view = data->gl_view; + context->read_rect = data->gl_rect; + } release_win_data(data); } } @@ -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", - context->draw_view, context->draw_pbuffer, context->read_view, context->read_pbuffer, context->format); + 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, 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); context->has_been_current = TRUE; @@ -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)); macdrv_set_view_window_and_frame(data->gl_view, NULL, cgrect_from_rect(rect)); data->gl_rect = rect; + mark_contexts_for_moved_view(data->gl_view); } } @@ -4607,7 +4678,10 @@ static BOOL macdrv_wglSwapBuffers(HDC hdc) (context ? context->cglcontext : NULL)); if (context) + { sync_swap_interval(context); + sync_context(context); + } if ((hwnd = WindowFromDC(hdc))) { diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index a79ec474563..1230bbed736 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -403,7 +403,7 @@ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_dat cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect), 8, 32, bytes_per_row, colorspace, alphaInfo | kCGBitmapByteOrder32Little, - provider, NULL, FALSE, kCGRenderingIntentDefault); + provider, NULL, retina_on, kCGRenderingIntentDefault); CGDataProviderRelease(provider); CGColorSpaceRelease(colorspace); }