VirtualBox

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

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

FE/Qt: Mac OS X: Runtime UI: Native Full Screen: Handle NSWindowDidFailToEnterFullScreenNotification for native full screen fallback needs.

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