VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/fullscreen/UIMachineWindowFullscreen.cpp@ 52300

Last change on this file since 52300 was 52300, checked in by vboxsync, 11 years ago

FE/Qt: Mac OS X: Runtime UI: Native full-screen support: Do not fade in/out on full-screen transitions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 KB
Line 
1/* $Id: UIMachineWindowFullscreen.cpp 52300 2014-08-06 17:05:04Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UIMachineWindowFullscreen class implementation
6 */
7
8/*
9 * Copyright (C) 2010-2013 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Qt includes: */
21#include <QDesktopWidget>
22#include <QMenu>
23#include <QTimer>
24
25/* GUI includes: */
26#include "VBoxGlobal.h"
27#include "UIExtraDataManager.h"
28#include "UISession.h"
29#include "UIActionPoolRuntime.h"
30#include "UIMachineLogicFullscreen.h"
31#include "UIMachineWindowFullscreen.h"
32#include "UIMachineView.h"
33#include "UIMachineDefs.h"
34#include "UIMiniToolBar.h"
35#ifdef Q_WS_MAC
36# include "VBoxUtils-darwin.h"
37# include "UICocoaApplication.h"
38#endif /* Q_WS_MAC */
39
40/* COM includes: */
41#include "CSnapshot.h"
42
43UIMachineWindowFullscreen::UIMachineWindowFullscreen(UIMachineLogic *pMachineLogic, ulong uScreenId)
44 : UIMachineWindow(pMachineLogic, uScreenId)
45 , m_pMiniToolBar(0)
46#ifdef Q_WS_MAC
47 , m_fIsInFullscreenTransition(false)
48#endif /* Q_WS_MAC */
49{
50}
51
52#ifdef Q_WS_MAC
53void UIMachineWindowFullscreen::handleNativeNotification(const QString &strNativeNotificationName)
54{
55 /* Make sure this method is only used for ML and next: */
56 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
57
58 /* Log all arrived notifications: */
59 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: Notification '%s' received.\n",
60 strNativeNotificationName.toAscii().constData()));
61
62 /* Handle 'NSWindowWillEnterFullScreenNotification' notification: */
63 if (strNativeNotificationName == "NSWindowWillEnterFullScreenNotification")
64 {
65 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
66 "Native fullscreen mode about to enter, notifying listener...\n"));
67 emit sigNotifyAboutNativeFullscreenWillEnter();
68 }
69 /* Handle 'NSWindowDidEnterFullScreenNotification' notification: */
70 else if (strNativeNotificationName == "NSWindowDidEnterFullScreenNotification")
71 {
72 /* Mark window transition complete: */
73 m_fIsInFullscreenTransition = false;
74 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
75 "Native fullscreen mode entered, notifying listener...\n"));
76 emit sigNotifyAboutNativeFullscreenDidEnter();
77 }
78 /* Handle 'NSWindowWillExitFullScreenNotification' notification: */
79 else if (strNativeNotificationName == "NSWindowWillExitFullScreenNotification")
80 {
81 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
82 "Native fullscreen mode about to exit, notifying listener...\n"));
83 emit sigNotifyAboutNativeFullscreenWillExit();
84 }
85 /* Handle 'NSWindowDidExitFullScreenNotification' notification: */
86 else if (strNativeNotificationName == "NSWindowDidExitFullScreenNotification")
87 {
88 /* Mark window transition complete: */
89 m_fIsInFullscreenTransition = false;
90 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
91 "Native fullscreen mode exited, notifying listener...\n"));
92 emit sigNotifyAboutNativeFullscreenDidExit();
93 }
94 /* Handle 'NSWindowDidFailToEnterFullScreenNotification' notification: */
95 else if (strNativeNotificationName == "NSWindowDidFailToEnterFullScreenNotification")
96 {
97 /* Mark window transition complete: */
98 m_fIsInFullscreenTransition = false;
99 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
100 "Native fullscreen mode fail to enter, notifying listener...\n"));
101 emit sigNotifyAboutNativeFullscreenFailToEnter();
102 }
103}
104#endif /* Q_WS_MAC */
105
106void UIMachineWindowFullscreen::sltMachineStateChanged()
107{
108 /* Call to base-class: */
109 UIMachineWindow::sltMachineStateChanged();
110
111 /* Update mini-toolbar: */
112 updateAppearanceOf(UIVisualElement_MiniToolBar);
113}
114
115#ifdef Q_WS_MAC
116void UIMachineWindowFullscreen::sltEnterNativeFullscreen(UIMachineWindow *pMachineWindow)
117{
118 /* Make sure this slot is called only under ML and next: */
119 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
120
121 /* Make sure it is NULL or 'this' window passed: */
122 if (pMachineWindow && pMachineWindow != this)
123 return;
124
125 /* Make sure this window has fullscreen logic: */
126 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
127 AssertPtrReturnVoid(pFullscreenLogic);
128
129 /* Make sure this window should be shown and mapped to host-screen: */
130 if (!uisession()->isScreenVisible(m_uScreenId) ||
131 !pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
132 return;
133
134 /* Mark window 'transitioned to fullscreen': */
135 m_fIsInFullscreenTransition = true;
136
137 /* Enter native fullscreen mode if necessary: */
138 if ( (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
139 && !darwinIsInFullscreenMode(this))
140 darwinToggleFullscreenMode(this);
141}
142
143void UIMachineWindowFullscreen::sltExitNativeFullscreen(UIMachineWindow *pMachineWindow)
144{
145 /* Make sure this slot is called only under ML and next: */
146 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
147
148 /* Make sure it is NULL or 'this' window passed: */
149 if (pMachineWindow && pMachineWindow != this)
150 return;
151
152 /* Make sure this window has fullscreen logic: */
153 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
154 AssertPtrReturnVoid(pFullscreenLogic);
155
156 /* Mark window 'transitioned from fullscreen': */
157 m_fIsInFullscreenTransition = true;
158
159 /* Exit native fullscreen mode if necessary: */
160 if ( (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
161 && darwinIsInFullscreenMode(this))
162 darwinToggleFullscreenMode(this);
163}
164#endif /* Q_WS_MAC */
165
166void UIMachineWindowFullscreen::sltRevokeFocus()
167{
168 /* Revoke stolen focus: */
169 m_pMachineView->setFocus();
170}
171
172void UIMachineWindowFullscreen::prepareVisualState()
173{
174 /* Call to base-class: */
175 UIMachineWindow::prepareVisualState();
176
177 /* The background has to go black: */
178 QPalette palette(centralWidget()->palette());
179 palette.setColor(centralWidget()->backgroundRole(), Qt::black);
180 centralWidget()->setPalette(palette);
181 centralWidget()->setAutoFillBackground(true);
182 setAutoFillBackground(true);
183
184 /* Prepare mini-toolbar: */
185 prepareMiniToolbar();
186
187#ifdef Q_WS_MAC
188 /* Native fullscreen stuff on ML and next: */
189 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
190 {
191 /* Make sure this window has fullscreen logic: */
192 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
193 AssertPtrReturnVoid(pFullscreenLogic);
194 /* Enable fullscreen support for every screen which requires it: */
195 if (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
196 darwinEnableFullscreenSupport(this);
197 /* Enable transience support for other screens: */
198 else
199 darwinEnableTransienceSupport(this);
200 /* Register to native fullscreen notifications: */
201 UICocoaApplication::instance()->registerToNativeNotification("NSWindowWillEnterFullScreenNotification", this,
202 UIMachineWindow::handleNativeNotification);
203 UICocoaApplication::instance()->registerToNativeNotification("NSWindowDidEnterFullScreenNotification", this,
204 UIMachineWindow::handleNativeNotification);
205 UICocoaApplication::instance()->registerToNativeNotification("NSWindowWillExitFullScreenNotification", this,
206 UIMachineWindow::handleNativeNotification);
207 UICocoaApplication::instance()->registerToNativeNotification("NSWindowDidExitFullScreenNotification", this,
208 UIMachineWindow::handleNativeNotification);
209 UICocoaApplication::instance()->registerToNativeNotification("NSWindowDidFailToEnterFullScreenNotification", this,
210 UIMachineWindow::handleNativeNotification);
211 }
212#endif /* Q_WS_MAC */
213}
214
215void UIMachineWindowFullscreen::prepareMiniToolbar()
216{
217 /* Make sure mini-toolbar is not restricted: */
218 if (!gEDataManager->miniToolbarEnabled(vboxGlobal().managedVMUuid()))
219 return;
220
221 /* Create mini-toolbar: */
222 m_pMiniToolBar = new UIRuntimeMiniToolBar(this,
223 IntegrationMode_Embedded,
224 gEDataManager->miniToolbarAlignment(vboxGlobal().managedVMUuid()),
225 gEDataManager->autoHideMiniToolbar(vboxGlobal().managedVMUuid()));
226 m_pMiniToolBar->addMenus(actionPool()->menus());
227#ifndef RT_OS_DARWIN
228 connect(m_pMiniToolBar, SIGNAL(sigMinimizeAction()), this, SLOT(showMinimized()));
229#endif /* !RT_OS_DARWIN */
230 connect(m_pMiniToolBar, SIGNAL(sigExitAction()),
231 actionPool()->action(UIActionIndexRT_M_View_T_Fullscreen), SLOT(trigger()));
232 connect(m_pMiniToolBar, SIGNAL(sigCloseAction()),
233 actionPool()->action(UIActionIndexRT_M_Machine_S_Close), SLOT(trigger()));
234 connect(m_pMiniToolBar, SIGNAL(sigNotifyAboutFocusStolen()), this, SLOT(sltRevokeFocus()));
235}
236
237void UIMachineWindowFullscreen::cleanupMiniToolbar()
238{
239 /* Make sure mini-toolbar was created: */
240 if (!m_pMiniToolBar)
241 return;
242
243 /* Save mini-toolbar settings: */
244 gEDataManager->setAutoHideMiniToolbar(m_pMiniToolBar->autoHide(), vboxGlobal().managedVMUuid());
245 /* Delete mini-toolbar: */
246 delete m_pMiniToolBar;
247 m_pMiniToolBar = 0;
248}
249
250void UIMachineWindowFullscreen::cleanupVisualState()
251{
252#ifdef Q_WS_MAC
253 /* Native fullscreen stuff on ML and next: */
254 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
255 {
256 /* Unregister from native fullscreen notifications: */
257 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowWillEnterFullScreenNotification", this);
258 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowDidEnterFullScreenNotification", this);
259 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowWillExitFullScreenNotification", this);
260 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowDidExitFullScreenNotification", this);
261 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowDidFailToEnterFullScreenNotification", this);
262 }
263#endif /* Q_WS_MAC */
264
265 /* Cleanup mini-toolbar: */
266 cleanupMiniToolbar();
267
268 /* Call to base-class: */
269 UIMachineWindow::cleanupVisualState();
270}
271
272void UIMachineWindowFullscreen::placeOnScreen()
273{
274 /* Get corresponding screen: */
275 int iScreen = qobject_cast<UIMachineLogicFullscreen*>(machineLogic())->hostScreenForGuestScreen(m_uScreenId);
276 /* Calculate working area: */
277 QRect workingArea = QApplication::desktop()->screenGeometry(iScreen);
278 /* Move to the appropriate position: */
279 move(workingArea.topLeft());
280#ifdef Q_WS_MAC
281 /* Make sure this window has fullscreen logic: */
282 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
283 AssertPtrReturnVoid(pFullscreenLogic);
284 /* Resize to the appropriate size on Lion and previous: */
285 if (vboxGlobal().osRelease() <= MacOSXRelease_Lion)
286 resize(workingArea.size());
287 /* Resize to the appropriate size on ML and next
288 * only if that screen has no own user-space: */
289 else if (!pFullscreenLogic->screensHaveSeparateSpaces() && m_uScreenId != 0)
290 resize(workingArea.size());
291 else
292 {
293 /* Move window to the center of working-area: */
294 QRect geo = gEDataManager->machineWindowGeometry(UIVisualStateType_Normal, m_uScreenId, vboxGlobal().managedVMUuid());
295 geo.moveCenter(workingArea.center());
296 setGeometry(geo);
297 }
298#else /* !Q_WS_MAC */
299 /* Resize to the appropriate size: */
300 resize(workingArea.size());
301#endif /* !Q_WS_MAC */
302 /* Adjust guest screen size if necessary: */
303 machineView()->maybeAdjustGuestScreenSize();
304 /* Move mini-toolbar into appropriate place: */
305 if (m_pMiniToolBar)
306 m_pMiniToolBar->adjustGeometry();
307}
308
309void UIMachineWindowFullscreen::showInNecessaryMode()
310{
311 /* Make sure this window should be shown at all: */
312 if (!uisession()->isScreenVisible(m_uScreenId))
313 return hide();
314
315 /* Make sure this window has fullscreen logic: */
316 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
317 if (!pFullscreenLogic)
318 return hide();
319
320 /* Make sure this window mapped to some host-screen: */
321 if (!pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
322 return hide();
323
324 /* Make sure this window is not minimized: */
325 if (isMinimized())
326 return;
327
328 /* Make sure this window is maximized and placed on valid screen: */
329 placeOnScreen();
330
331#ifdef Q_WS_MAC
332 /* ML and next using native stuff, so we can call for simple show(): */
333 if (vboxGlobal().osRelease() > MacOSXRelease_Lion) show();
334 /* Lion and previous using Qt stuff, so we should call for showFullScreen(): */
335 else showFullScreen();
336#else /* !Q_WS_MAC */
337 /* Show in fullscreen mode: */
338 showFullScreen();
339#endif /* !Q_WS_MAC */
340
341#ifdef Q_WS_X11
342 /* Make sure the window is placed on valid screen again
343 * after window is shown & window's decorations applied.
344 * That is required (still?) due to X11 Window Geometry Rules. */
345 placeOnScreen();
346#endif /* Q_WS_X11 */
347}
348
349void UIMachineWindowFullscreen::updateAppearanceOf(int iElement)
350{
351 /* Call to base-class: */
352 UIMachineWindow::updateAppearanceOf(iElement);
353
354 /* Update mini-toolbar: */
355 if (iElement & UIVisualElement_MiniToolBar)
356 {
357 if (m_pMiniToolBar)
358 {
359 /* Get machine: */
360 const CMachine &m = machine();
361 /* Get snapshot(s): */
362 QString strSnapshotName;
363 if (m.GetSnapshotCount() > 0)
364 {
365 CSnapshot snapshot = m.GetCurrentSnapshot();
366 strSnapshotName = " (" + snapshot.GetName() + ")";
367 }
368 /* Update mini-toolbar text: */
369 m_pMiniToolBar->setText(m.GetName() + strSnapshotName);
370 }
371 }
372}
373
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette