[24377] | 1 | /* $Id: UICocoaDockIconPreview.mm 98421 2023-02-02 09:21:40Z vboxsync $ */
|
---|
[17340] | 2 | /** @file
|
---|
[52727] | 3 | * VBox Qt GUI - Cocoa helper for the dock icon preview.
|
---|
[17340] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2009-2023 Oracle and/or its affiliates.
|
---|
[17340] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[17340] | 26 | */
|
---|
| 27 |
|
---|
[24377] | 28 | /* VBox includes */
|
---|
[27215] | 29 | #include "UICocoaDockIconPreview.h"
|
---|
[24377] | 30 | #include "VBoxCocoaHelper.h"
|
---|
[17340] | 31 |
|
---|
[24377] | 32 | /* System includes */
|
---|
| 33 | #import <Cocoa/Cocoa.h>
|
---|
[17340] | 34 |
|
---|
[27215] | 35 | @interface UIDockTileMonitor: NSView
|
---|
[24377] | 36 | {
|
---|
[27215] | 37 | UICocoaDockIconPreviewPrivate *p;
|
---|
[17340] | 38 |
|
---|
[24377] | 39 | NSImageView *mScreenContent;
|
---|
| 40 | NSImageView *mMonitorGlossy;
|
---|
| 41 | }
|
---|
[27215] | 42 | - (id)initWithFrame:(NSRect)frame parent:(UICocoaDockIconPreviewPrivate*)parent;
|
---|
[24377] | 43 | - (NSImageView*)screenContent;
|
---|
| 44 | - (void)resize:(NSSize)size;
|
---|
| 45 | @end
|
---|
[17340] | 46 |
|
---|
[27215] | 47 | @interface UIDockTileOverlay: NSView
|
---|
[17340] | 48 | {
|
---|
[27215] | 49 | UICocoaDockIconPreviewPrivate *p;
|
---|
[24377] | 50 | }
|
---|
[27215] | 51 | - (id)initWithFrame:(NSRect)frame parent:(UICocoaDockIconPreviewPrivate*)parent;
|
---|
[24377] | 52 | @end
|
---|
[17340] | 53 |
|
---|
[27215] | 54 | @interface UIDockTile: NSView
|
---|
[24377] | 55 | {
|
---|
[27215] | 56 | UICocoaDockIconPreviewPrivate *p;
|
---|
[17340] | 57 |
|
---|
[27215] | 58 | UIDockTileMonitor *mMonitor;
|
---|
[28342] | 59 | NSImageView *mAppIcon;
|
---|
[24377] | 60 |
|
---|
[27215] | 61 | UIDockTileOverlay *mOverlay;
|
---|
[17340] | 62 | }
|
---|
[27215] | 63 | - (id)initWithParent:(UICocoaDockIconPreviewPrivate*)parent;
|
---|
[28279] | 64 | - (void)destroy;
|
---|
[28342] | 65 | - (NSView*)screenContentWithParentView:(NSView*)parentView;
|
---|
[24377] | 66 | - (void)cleanup;
|
---|
| 67 | - (void)restoreAppIcon;
|
---|
| 68 | - (void)updateAppIcon;
|
---|
| 69 | - (void)restoreMonitor;
|
---|
| 70 | - (void)updateMonitorWithImage:(CGImageRef)image;
|
---|
| 71 | - (void)resizeMonitor:(NSSize)size;
|
---|
| 72 | @end
|
---|
[17340] | 73 |
|
---|
[29200] | 74 | /*
|
---|
[24377] | 75 | * Helper class which allow us to access all members/methods of AbstractDockIconPreviewHelper
|
---|
| 76 | * from any Cocoa class.
|
---|
| 77 | */
|
---|
[27215] | 78 | class UICocoaDockIconPreviewPrivate: public UIAbstractDockIconPreviewHelper
|
---|
[17340] | 79 | {
|
---|
[24377] | 80 | public:
|
---|
[98421] | 81 | inline UICocoaDockIconPreviewPrivate(UIMachine *pMachine, const QPixmap& overlayImage)
|
---|
| 82 | : UIAbstractDockIconPreviewHelper(pMachine, overlayImage)
|
---|
[24377] | 83 | {
|
---|
[27215] | 84 | mUIDockTile = [[UIDockTile alloc] initWithParent:this];
|
---|
[24377] | 85 | }
|
---|
[17340] | 86 |
|
---|
[27215] | 87 | inline ~UICocoaDockIconPreviewPrivate()
|
---|
[17340] | 88 | {
|
---|
[28279] | 89 |
|
---|
| 90 | [mUIDockTile destroy];
|
---|
[27215] | 91 | [mUIDockTile release];
|
---|
[17340] | 92 | }
|
---|
[29200] | 93 |
|
---|
[27215] | 94 | UIDockTile *mUIDockTile;
|
---|
[24377] | 95 | };
|
---|
[17340] | 96 |
|
---|
[29200] | 97 | /*
|
---|
| 98 | * Cocoa wrapper for the abstract dock icon preview class
|
---|
[24377] | 99 | */
|
---|
[98421] | 100 | UICocoaDockIconPreview::UICocoaDockIconPreview(UIMachine *pMachine, const QPixmap& overlayImage)
|
---|
| 101 | : UIAbstractDockIconPreview(pMachine, overlayImage)
|
---|
[24377] | 102 | {
|
---|
| 103 | CocoaAutoreleasePool pool;
|
---|
| 104 |
|
---|
[98421] | 105 | d = new UICocoaDockIconPreviewPrivate(pMachine, overlayImage);
|
---|
[17340] | 106 | }
|
---|
| 107 |
|
---|
[27215] | 108 | UICocoaDockIconPreview::~UICocoaDockIconPreview()
|
---|
[17340] | 109 | {
|
---|
[24377] | 110 | CocoaAutoreleasePool pool;
|
---|
[17340] | 111 |
|
---|
[24377] | 112 | delete d;
|
---|
| 113 | }
|
---|
[17340] | 114 |
|
---|
[27215] | 115 | void UICocoaDockIconPreview::updateDockOverlay()
|
---|
[24377] | 116 | {
|
---|
| 117 | CocoaAutoreleasePool pool;
|
---|
[17340] | 118 |
|
---|
[27215] | 119 | [d->mUIDockTile updateAppIcon];
|
---|
[17340] | 120 | }
|
---|
| 121 |
|
---|
[27215] | 122 | void UICocoaDockIconPreview::updateDockPreview(CGImageRef VMImage)
|
---|
[17340] | 123 | {
|
---|
[24377] | 124 | CocoaAutoreleasePool pool;
|
---|
[17340] | 125 |
|
---|
[27215] | 126 | [d->mUIDockTile updateMonitorWithImage:VMImage];
|
---|
[24377] | 127 | }
|
---|
[17340] | 128 |
|
---|
[27215] | 129 | void UICocoaDockIconPreview::updateDockPreview(UIFrameBuffer *pFrameBuffer)
|
---|
[24377] | 130 | {
|
---|
| 131 | CocoaAutoreleasePool pool;
|
---|
[17340] | 132 |
|
---|
[27215] | 133 | UIAbstractDockIconPreview::updateDockPreview(pFrameBuffer);
|
---|
[17340] | 134 | }
|
---|
| 135 |
|
---|
[27215] | 136 | void UICocoaDockIconPreview::setOriginalSize(int width, int height)
|
---|
[17340] | 137 | {
|
---|
[24377] | 138 | CocoaAutoreleasePool pool;
|
---|
[17340] | 139 |
|
---|
[27215] | 140 | [d->mUIDockTile resizeMonitor:NSMakeSize(width, height)];
|
---|
[24377] | 141 | }
|
---|
| 142 |
|
---|
[29200] | 143 | /*
|
---|
[24377] | 144 | * Class for arranging/updating the layers for the glossy monitor preview.
|
---|
| 145 | */
|
---|
[61244] | 146 | @implementation UIDockTileMonitor
|
---|
[27215] | 147 | - (id)initWithFrame:(NSRect)frame parent:(UICocoaDockIconPreviewPrivate*)parent
|
---|
[24377] | 148 | {
|
---|
| 149 | self = [super initWithFrame:frame];
|
---|
| 150 |
|
---|
| 151 | if (self != nil)
|
---|
[17340] | 152 | {
|
---|
[24377] | 153 | p = parent;
|
---|
| 154 | /* The screen content view */
|
---|
[27215] | 155 | mScreenContent = [[NSImageView alloc] initWithFrame:NSRectFromCGRect(p->flipRect(p->m_updateRect))];
|
---|
[24377] | 156 | // [mScreenContent setImageAlignment: NSImageAlignCenter];
|
---|
[85329] | 157 | [mScreenContent setImageAlignment: NSImageAlignTopLeft];
|
---|
[85330] | 158 | [mScreenContent setImageScaling: NSImageScaleAxesIndependently];
|
---|
[24377] | 159 | [self addSubview: mScreenContent];
|
---|
| 160 | /* The state view */
|
---|
[27215] | 161 | mMonitorGlossy = [[NSImageView alloc] initWithFrame:NSRectFromCGRect(p->flipRect(p->m_monitorRect))];
|
---|
[30151] | 162 | [mMonitorGlossy setImage: ::darwinToNSImageRef(p->m_dockMonitorGlossy)];
|
---|
[24377] | 163 | [self addSubview: mMonitorGlossy];
|
---|
[17340] | 164 | }
|
---|
[24377] | 165 |
|
---|
| 166 | return self;
|
---|
[17340] | 167 | }
|
---|
| 168 |
|
---|
[61244] | 169 | - (void)drawRect:(NSRect)aRect
|
---|
[17340] | 170 | {
|
---|
[30151] | 171 | NSImage *dockMonitor = ::darwinToNSImageRef(p->m_dockMonitor);
|
---|
[85335] | 172 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
|
---|
[85331] | 173 | [dockMonitor drawInRect:NSRectFromCGRect(p->flipRect(p->m_monitorRect)) fromRect:aRect operation:NSCompositingOperationSourceOver fraction:1.0];
|
---|
| 174 | #else
|
---|
[27215] | 175 | [dockMonitor drawInRect:NSRectFromCGRect(p->flipRect(p->m_monitorRect)) fromRect:aRect operation:NSCompositeSourceOver fraction:1.0];
|
---|
[85331] | 176 | #endif
|
---|
[24377] | 177 | [dockMonitor release];
|
---|
| 178 | }
|
---|
[17340] | 179 |
|
---|
[24377] | 180 | - (NSImageView*)screenContent
|
---|
| 181 | {
|
---|
| 182 | return mScreenContent;
|
---|
| 183 | }
|
---|
[17340] | 184 |
|
---|
[61244] | 185 | - (void)resize:(NSSize)size
|
---|
[24377] | 186 | {
|
---|
| 187 | /* Calculate the new size based on the aspect ratio of the original screen
|
---|
| 188 | size */
|
---|
| 189 | float w, h;
|
---|
| 190 | if (size.width > size.height)
|
---|
| 191 | {
|
---|
[27215] | 192 | w = p->m_updateRect.size.width;
|
---|
| 193 | h = ((float)size.height / size.width * p->m_updateRect.size.height);
|
---|
[24377] | 194 | }
|
---|
| 195 | else
|
---|
| 196 | {
|
---|
[27215] | 197 | w = ((float)size.width / size.height * p->m_updateRect.size.width);
|
---|
| 198 | h = p->m_updateRect.size.height;
|
---|
[24377] | 199 | }
|
---|
[27215] | 200 | CGRect r = (p->flipRect (p->centerRectTo (CGRectMake (0, 0, (int)w, (int)h), p->m_updateRect)));
|
---|
[24377] | 201 | r.origin.x = (int)r.origin.x;
|
---|
| 202 | r.origin.y = (int)r.origin.y;
|
---|
| 203 | r.size.width = (int)r.size.width;
|
---|
| 204 | r.size.height = (int)r.size.height;
|
---|
| 205 | // printf("gui %f %f %f %f\n", r.origin.x, r.origin.y, r.size.width, r.size.height);
|
---|
| 206 | /* Center within the update rect */
|
---|
| 207 | [mScreenContent setFrame:NSRectFromCGRect (r)];
|
---|
[17340] | 208 | }
|
---|
[24377] | 209 | @end
|
---|
[17340] | 210 |
|
---|
[29200] | 211 | /*
|
---|
[24377] | 212 | * Simple implementation for the overlay of the OS & the state icon. Is used both
|
---|
| 213 | * in the application icon & preview mode.
|
---|
| 214 | */
|
---|
[27215] | 215 | @implementation UIDockTileOverlay
|
---|
| 216 | - (id)initWithFrame:(NSRect)frame parent:(UICocoaDockIconPreviewPrivate*)parent
|
---|
[24377] | 217 | {
|
---|
| 218 | self = [super initWithFrame:frame];
|
---|
| 219 |
|
---|
| 220 | if (self != nil)
|
---|
| 221 | p = parent;
|
---|
| 222 |
|
---|
| 223 | return self;
|
---|
| 224 | }
|
---|
| 225 |
|
---|
[61244] | 226 | - (void)drawRect:(NSRect)aRect
|
---|
[24377] | 227 | {
|
---|
[63492] | 228 | RT_NOREF(aRect);
|
---|
[24377] | 229 | NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
|
---|
| 230 | CGContextRef pCGContext = (CGContextRef)[nsContext graphicsPort];
|
---|
| 231 | p->drawOverlayIcons (pCGContext);
|
---|
| 232 | }
|
---|
| 233 | @end
|
---|
| 234 |
|
---|
[29200] | 235 | /*
|
---|
[24377] | 236 | * VirtualBox Dock Tile implementation. Manage the switching between the icon
|
---|
| 237 | * and preview mode & forwards all update request to the appropriate methods.
|
---|
| 238 | */
|
---|
[27215] | 239 | @implementation UIDockTile
|
---|
| 240 | - (id)initWithParent:(UICocoaDockIconPreviewPrivate*)parent
|
---|
[24377] | 241 | {
|
---|
| 242 | self = [super init];
|
---|
| 243 |
|
---|
| 244 | if (self != nil)
|
---|
| 245 | {
|
---|
| 246 | p = parent;
|
---|
| 247 | /* Add self as the content view of the dock tile */
|
---|
| 248 | NSDockTile *dock = [[NSApplication sharedApplication] dockTile];
|
---|
| 249 | [dock setContentView: self];
|
---|
| 250 | /* App icon is default */
|
---|
| 251 | [self restoreAppIcon];
|
---|
| 252 | /* The overlay */
|
---|
[27215] | 253 | mOverlay = [[UIDockTileOverlay alloc] initWithFrame:NSRectFromCGRect(p->flipRect (p->m_dockIconRect)) parent:p];
|
---|
[24377] | 254 | [self addSubview: mOverlay];
|
---|
| 255 | }
|
---|
| 256 |
|
---|
| 257 | return self;
|
---|
| 258 | }
|
---|
| 259 |
|
---|
[28279] | 260 | - (void)destroy
|
---|
| 261 | {
|
---|
| 262 | /* Remove all content from the application dock tile. */
|
---|
| 263 | [mOverlay removeFromSuperview];
|
---|
| 264 | [mOverlay release];
|
---|
| 265 | mOverlay = nil;
|
---|
| 266 | NSDockTile *dock = [[NSApplication sharedApplication] dockTile];
|
---|
| 267 | [dock setContentView: nil];
|
---|
| 268 | /* Cleanup all other resources */
|
---|
| 269 | [self cleanup];
|
---|
| 270 | }
|
---|
| 271 |
|
---|
[28342] | 272 | - (NSView*)screenContentWithParentView:(NSView*)parentView
|
---|
[24377] | 273 | {
|
---|
[28342] | 274 | if (mMonitor != nil)
|
---|
| 275 | {
|
---|
| 276 | void *pId = p->currentPreviewWindowId();
|
---|
| 277 | if (parentView == pId)
|
---|
| 278 | return [mMonitor screenContent];
|
---|
| 279 | }
|
---|
| 280 | return nil;
|
---|
[24377] | 281 | }
|
---|
| 282 |
|
---|
| 283 | - (void)cleanup
|
---|
| 284 | {
|
---|
| 285 | if (mAppIcon != nil)
|
---|
| 286 | {
|
---|
| 287 | [mAppIcon removeFromSuperview];
|
---|
| 288 | [mAppIcon release];
|
---|
| 289 | mAppIcon = nil;
|
---|
| 290 | }
|
---|
| 291 | if (mMonitor != nil)
|
---|
| 292 | {
|
---|
| 293 | [mMonitor removeFromSuperview];
|
---|
| 294 | [mMonitor release];
|
---|
| 295 | mMonitor = nil;
|
---|
| 296 | }
|
---|
| 297 | }
|
---|
| 298 |
|
---|
| 299 | - (void)restoreAppIcon
|
---|
| 300 | {
|
---|
| 301 | if (mAppIcon == nil)
|
---|
| 302 | {
|
---|
| 303 | [self cleanup];
|
---|
[27215] | 304 | mAppIcon = [[NSImageView alloc] initWithFrame:NSRectFromCGRect (p->flipRect (p->m_dockIconRect))];
|
---|
[24377] | 305 | [mAppIcon setImage: [NSImage imageNamed:@"NSApplicationIcon"]];
|
---|
| 306 | [self addSubview: mAppIcon positioned:NSWindowBelow relativeTo:mOverlay];
|
---|
| 307 | }
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | - (void)updateAppIcon
|
---|
| 311 | {
|
---|
| 312 | [self restoreAppIcon];
|
---|
| 313 | [[[NSApplication sharedApplication] dockTile] display];
|
---|
| 314 | }
|
---|
| 315 |
|
---|
| 316 | - (void)restoreMonitor
|
---|
| 317 | {
|
---|
| 318 | if (mMonitor == nil)
|
---|
| 319 | {
|
---|
| 320 | p->initPreviewImages();
|
---|
| 321 | [self cleanup];
|
---|
[27215] | 322 | mMonitor = [[UIDockTileMonitor alloc] initWithFrame:NSRectFromCGRect (p->flipRect (p->m_dockIconRect)) parent:p];
|
---|
[24377] | 323 | [self addSubview: mMonitor positioned:NSWindowBelow relativeTo:mOverlay];
|
---|
| 324 | }
|
---|
| 325 | }
|
---|
| 326 |
|
---|
| 327 | - (void)updateMonitorWithImage:(CGImageRef)image
|
---|
| 328 | {
|
---|
| 329 | [self restoreMonitor];
|
---|
[30151] | 330 | NSImage *nsimage = ::darwinToNSImageRef(image);
|
---|
[24377] | 331 | [[mMonitor screenContent] setImage: nsimage];
|
---|
| 332 | [nsimage release];
|
---|
| 333 | [[[NSApplication sharedApplication] dockTile] display];
|
---|
| 334 | }
|
---|
| 335 |
|
---|
[61244] | 336 | - (void)resizeMonitor:(NSSize)size
|
---|
[24377] | 337 | {
|
---|
[28540] | 338 | [self restoreMonitor];
|
---|
[24377] | 339 | [mMonitor resize:size];
|
---|
| 340 | }
|
---|
| 341 | @end
|
---|
| 342 |
|
---|