VirtualBox

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

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

FE/Qt: Runtime UI: Do not interrupt fullscreen/seamless transition event-handling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.4 KB
Line 
1/* $Id: UIMachineWindowFullscreen.cpp 50916 2014-03-28 11:52:11Z 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 "UISession.h"
28#include "UIActionPoolRuntime.h"
29#include "UIMachineLogicFullscreen.h"
30#include "UIMachineWindowFullscreen.h"
31#include "UIMachineView.h"
32#include "UIMachineDefs.h"
33#include "UIMiniToolBar.h"
34#ifdef Q_WS_MAC
35# include "VBoxUtils-darwin.h"
36# include "UICocoaApplication.h"
37#endif /* Q_WS_MAC */
38
39/* COM includes: */
40#include "CSnapshot.h"
41
42UIMachineWindowFullscreen::UIMachineWindowFullscreen(UIMachineLogic *pMachineLogic, ulong uScreenId)
43 : UIMachineWindow(pMachineLogic, uScreenId)
44 , m_pMainMenu(0)
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}
95#endif /* Q_WS_MAC */
96
97void UIMachineWindowFullscreen::sltMachineStateChanged()
98{
99 /* Call to base-class: */
100 UIMachineWindow::sltMachineStateChanged();
101
102 /* Update mini-toolbar: */
103 updateAppearanceOf(UIVisualElement_MiniToolBar);
104}
105
106void UIMachineWindowFullscreen::sltPopupMainMenu()
107{
108 /* Popup main-menu if present: */
109 if (m_pMainMenu && !m_pMainMenu->isEmpty())
110 {
111 m_pMainMenu->popup(geometry().center());
112 QTimer::singleShot(0, m_pMainMenu, SLOT(sltHighlightFirstAction()));
113 }
114}
115
116#ifdef Q_WS_MAC
117void UIMachineWindowFullscreen::sltEnterNativeFullscreen(UIMachineWindow *pMachineWindow)
118{
119 /* Make sure this slot is called only under ML and next: */
120 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
121
122 /* Make sure it is NULL or 'this' window passed: */
123 if (pMachineWindow && pMachineWindow != this)
124 return;
125
126 /* Make sure this window should be shown at all: */
127 if (!uisession()->isScreenVisible(m_uScreenId))
128 return;
129
130 /* Make sure this window has fullscreen logic: */
131 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
132 if (!pFullscreenLogic)
133 return;
134
135 /* Make sure this window mapped to some host-screen: */
136 if (!pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
137 return;
138
139 /* Mark window 'transitioned to fullscreen': */
140 m_fIsInFullscreenTransition = true;
141
142 /* Enter native fullscreen mode if necessary: */
143 if ( (darwinScreensHaveSeparateSpaces() || m_uScreenId == 0)
144 && !darwinIsInFullscreenMode(this))
145 darwinToggleFullscreenMode(this);
146}
147
148void UIMachineWindowFullscreen::sltExitNativeFullscreen(UIMachineWindow *pMachineWindow)
149{
150 /* Make sure this slot is called only under ML and next: */
151 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
152
153 /* Make sure it is NULL or 'this' window passed: */
154 if (pMachineWindow && pMachineWindow != this)
155 return;
156
157 /* Mark window 'transitioned from fullscreen': */
158 m_fIsInFullscreenTransition = true;
159
160 /* Exit native fullscreen mode if necessary: */
161 if ( (darwinScreensHaveSeparateSpaces() || m_uScreenId == 0)
162 && darwinIsInFullscreenMode(this))
163 darwinToggleFullscreenMode(this);
164}
165#endif /* Q_WS_MAC */
166
167void UIMachineWindowFullscreen::sltRevokeFocus()
168{
169 /* Revoke stolen focus: */
170 m_pMachineView->setFocus();
171}
172
173void UIMachineWindowFullscreen::prepareMenu()
174{
175 /* Call to base-class: */
176 UIMachineWindow::prepareMenu();
177
178 /* Prepare menu: */
179 CMachine machine = session().GetMachine();
180 RuntimeMenuType restrictedMenus = VBoxGlobal::restrictedRuntimeMenuTypes(machine);
181 RuntimeMenuType allowedMenus = static_cast<RuntimeMenuType>(RuntimeMenuType_All ^ restrictedMenus);
182 m_pMainMenu = uisession()->newMenu(allowedMenus);
183}
184
185void UIMachineWindowFullscreen::prepareVisualState()
186{
187 /* Call to base-class: */
188 UIMachineWindow::prepareVisualState();
189
190 /* The background has to go black: */
191 QPalette palette(centralWidget()->palette());
192 palette.setColor(centralWidget()->backgroundRole(), Qt::black);
193 centralWidget()->setPalette(palette);
194 centralWidget()->setAutoFillBackground(true);
195 setAutoFillBackground(true);
196
197 /* Prepare mini-toolbar: */
198 prepareMiniToolbar();
199
200#ifdef Q_WS_MAC
201 /* Native fullscreen stuff on ML and next: */
202 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
203 {
204 /* Enable fullscreen support for every screen which requires it: */
205 if (darwinScreensHaveSeparateSpaces() || m_uScreenId == 0)
206 darwinEnableFullscreenSupport(this);
207 /* Enable transience support for other screens: */
208 else
209 darwinEnableTransienceSupport(this);
210 /* Register to native fullscreen notifications: */
211 UICocoaApplication::instance()->registerToNativeNotification("NSWindowWillEnterFullScreenNotification", this,
212 UIMachineWindow::handleNativeNotification);
213 UICocoaApplication::instance()->registerToNativeNotification("NSWindowDidEnterFullScreenNotification", this,
214 UIMachineWindow::handleNativeNotification);
215 UICocoaApplication::instance()->registerToNativeNotification("NSWindowWillExitFullScreenNotification", this,
216 UIMachineWindow::handleNativeNotification);
217 UICocoaApplication::instance()->registerToNativeNotification("NSWindowDidExitFullScreenNotification", this,
218 UIMachineWindow::handleNativeNotification);
219 }
220#endif /* Q_WS_MAC */
221}
222
223void UIMachineWindowFullscreen::prepareMiniToolbar()
224{
225 /* Get machine: */
226 CMachine m = machine();
227
228 /* Make sure mini-toolbar is necessary: */
229 bool fIsActive = m.GetExtraData(GUI_ShowMiniToolBar) != "no";
230 if (!fIsActive)
231 return;
232
233 /* Get the mini-toolbar alignment: */
234 bool fIsAtTop = m.GetExtraData(GUI_MiniToolBarAlignment) == "top";
235 /* Get the mini-toolbar auto-hide feature availability: */
236 bool fIsAutoHide = m.GetExtraData(GUI_MiniToolBarAutoHide) != "off";
237 /* Create mini-toolbar: */
238 m_pMiniToolBar = new UIRuntimeMiniToolBar(this,
239 fIsAtTop ? Qt::AlignTop : Qt::AlignBottom,
240 IntegrationMode_Embedded,
241 fIsAutoHide);
242 QList<QMenu*> menus;
243 RuntimeMenuType restrictedMenus = VBoxGlobal::restrictedRuntimeMenuTypes(m);
244 RuntimeMenuType allowedMenus = static_cast<RuntimeMenuType>(RuntimeMenuType_All ^ restrictedMenus);
245 QList<QAction*> actions = uisession()->newMenu(allowedMenus)->actions();
246 for (int i=0; i < actions.size(); ++i)
247 menus << actions.at(i)->menu();
248 m_pMiniToolBar->addMenus(menus);
249#ifndef RT_OS_DARWIN
250 connect(m_pMiniToolBar, SIGNAL(sigMinimizeAction()), this, SLOT(showMinimized()));
251#endif /* !RT_OS_DARWIN */
252 connect(m_pMiniToolBar, SIGNAL(sigExitAction()),
253 gActionPool->action(UIActionIndexRuntime_Toggle_Fullscreen), SLOT(trigger()));
254 connect(m_pMiniToolBar, SIGNAL(sigCloseAction()),
255 gActionPool->action(UIActionIndexRuntime_Simple_Close), SLOT(trigger()));
256 connect(m_pMiniToolBar, SIGNAL(sigNotifyAboutFocusStolen()), this, SLOT(sltRevokeFocus()));
257}
258
259void UIMachineWindowFullscreen::cleanupMiniToolbar()
260{
261 /* Make sure mini-toolbar was created: */
262 if (!m_pMiniToolBar)
263 return;
264
265 /* Save mini-toolbar settings: */
266 machine().SetExtraData(GUI_MiniToolBarAutoHide, m_pMiniToolBar->autoHide() ? QString() : "off");
267 /* Delete mini-toolbar: */
268 delete m_pMiniToolBar;
269 m_pMiniToolBar = 0;
270}
271
272void UIMachineWindowFullscreen::cleanupVisualState()
273{
274#ifdef Q_WS_MAC
275 /* Native fullscreen stuff on ML and next: */
276 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
277 {
278 /* Unregister from native fullscreen notifications: */
279 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowWillEnterFullScreenNotification", this);
280 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowDidEnterFullScreenNotification", this);
281 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowWillExitFullScreenNotification", this);
282 UICocoaApplication::instance()->unregisterFromNativeNotification("NSWindowDidExitFullScreenNotification", this);
283 }
284#endif /* Q_WS_MAC */
285
286 /* Cleanup mini-toolbar: */
287 cleanupMiniToolbar();
288
289 /* Call to base-class: */
290 UIMachineWindow::cleanupVisualState();
291}
292
293void UIMachineWindowFullscreen::cleanupMenu()
294{
295 /* Cleanup menu: */
296 delete m_pMainMenu;
297 m_pMainMenu = 0;
298
299 /* Call to base-class: */
300 UIMachineWindow::cleanupMenu();
301}
302
303void UIMachineWindowFullscreen::placeOnScreen()
304{
305 /* Get corresponding screen: */
306 int iScreen = qobject_cast<UIMachineLogicFullscreen*>(machineLogic())->hostScreenForGuestScreen(m_uScreenId);
307 /* Calculate working area: */
308 QRect workingArea = QApplication::desktop()->screenGeometry(iScreen);
309 /* Move to the appropriate position: */
310 move(workingArea.topLeft());
311#ifdef Q_WS_MAC
312 /* Resize to the appropriate size on Lion and previous: */
313 if (vboxGlobal().osRelease() <= MacOSXRelease_Lion)
314 resize(workingArea.size());
315 /* Resize to the appropriate size on ML and next
316 * only if that screen has no own user-space: */
317 else if (!darwinScreensHaveSeparateSpaces() && m_uScreenId != 0)
318 resize(workingArea.size());
319#else /* !Q_WS_MAC */
320 /* Resize to the appropriate size: */
321 resize(workingArea.size());
322#endif /* !Q_WS_MAC */
323 /* Adjust guest screen size if necessary: */
324 machineView()->maybeAdjustGuestScreenSize();
325 /* Move mini-toolbar into appropriate place: */
326 if (m_pMiniToolBar)
327 m_pMiniToolBar->adjustGeometry();
328}
329
330void UIMachineWindowFullscreen::showInNecessaryMode()
331{
332 /* Make sure this window should be shown at all: */
333 if (!uisession()->isScreenVisible(m_uScreenId))
334 return hide();
335
336 /* Make sure this window has fullscreen logic: */
337 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
338 if (!pFullscreenLogic)
339 return hide();
340
341 /* Make sure this window mapped to some host-screen: */
342 if (!pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
343 return hide();
344
345 /* Make sure this window is not minimized: */
346 if (isMinimized())
347 return;
348
349 /* Make sure this window is maximized and placed on valid screen: */
350 placeOnScreen();
351
352#ifdef Q_WS_MAC
353 /* ML and next using native stuff, so we can call for simple show(): */
354 if (vboxGlobal().osRelease() > MacOSXRelease_Lion) show();
355 /* Lion and previous using Qt stuff, so we should call for showFullScreen(): */
356 else showFullScreen();
357#else /* !Q_WS_MAC */
358 /* Show in fullscreen mode: */
359 showFullScreen();
360#endif /* !Q_WS_MAC */
361
362#ifdef Q_WS_X11
363 /* Make sure the window is placed on valid screen again
364 * after window is shown & window's decorations applied.
365 * That is required (still?) due to X11 Window Geometry Rules. */
366 placeOnScreen();
367#endif /* Q_WS_X11 */
368}
369
370void UIMachineWindowFullscreen::updateAppearanceOf(int iElement)
371{
372 /* Call to base-class: */
373 UIMachineWindow::updateAppearanceOf(iElement);
374
375 /* Update mini-toolbar: */
376 if (iElement & UIVisualElement_MiniToolBar)
377 {
378 if (m_pMiniToolBar)
379 {
380 /* Get machine: */
381 const CMachine &m = machine();
382 /* Get snapshot(s): */
383 QString strSnapshotName;
384 if (m.GetSnapshotCount() > 0)
385 {
386 CSnapshot snapshot = m.GetCurrentSnapshot();
387 strSnapshotName = " (" + snapshot.GetName() + ")";
388 }
389 /* Update mini-toolbar text: */
390 m_pMiniToolBar->setText(m.GetName() + strSnapshotName);
391 }
392 }
393}
394
Note: See TracBrowser for help on using the repository browser.

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