VirtualBox

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

Last change on this file since 56931 was 56931, checked in by vboxsync, 9 years ago

FE/Qt: X11: 5978: Set transiency for mini-toolbar once, no need to do it every time.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.7 KB
Line 
1/* $Id: UIMachineWindowFullscreen.cpp 56931 2015-07-14 14:36:43Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMachineWindowFullscreen class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifdef VBOX_WITH_PRECOMPILED_HEADERS
19# include <precomp.h>
20#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
21
22/* Qt includes: */
23# include <QDesktopWidget>
24# include <QMenu>
25# include <QTimer>
26
27/* GUI includes: */
28# include "VBoxGlobal.h"
29# include "UIExtraDataManager.h"
30# include "UISession.h"
31# include "UIActionPoolRuntime.h"
32# include "UIMachineLogicFullscreen.h"
33# include "UIMachineWindowFullscreen.h"
34# include "UIMachineView.h"
35# include "UIFrameBuffer.h"
36# include "UIMachineDefs.h"
37# include "UIMiniToolBar.h"
38# ifdef Q_WS_MAC
39# include "VBoxUtils-darwin.h"
40# include "UICocoaApplication.h"
41# endif /* Q_WS_MAC */
42
43/* COM includes: */
44# include "CSnapshot.h"
45
46#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
47
48
49UIMachineWindowFullscreen::UIMachineWindowFullscreen(UIMachineLogic *pMachineLogic, ulong uScreenId)
50 : UIMachineWindow(pMachineLogic, uScreenId)
51#ifndef Q_WS_MAC
52 , m_pMiniToolBar(0)
53#endif /* !Q_WS_MAC */
54#ifdef Q_WS_MAC
55 , m_fIsInFullscreenTransition(false)
56#endif /* Q_WS_MAC */
57{
58}
59
60#ifdef Q_WS_MAC
61void UIMachineWindowFullscreen::handleNativeNotification(const QString &strNativeNotificationName)
62{
63 /* Make sure this method is only used for ML and next: */
64 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
65
66 /* Log all arrived notifications: */
67 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: Notification '%s' received.\n",
68 strNativeNotificationName.toAscii().constData()));
69
70 /* Handle 'NSWindowWillEnterFullScreenNotification' notification: */
71 if (strNativeNotificationName == "NSWindowWillEnterFullScreenNotification")
72 {
73 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
74 "Native fullscreen mode about to enter, notifying listener...\n"));
75 emit sigNotifyAboutNativeFullscreenWillEnter();
76 }
77 /* Handle 'NSWindowDidEnterFullScreenNotification' notification: */
78 else if (strNativeNotificationName == "NSWindowDidEnterFullScreenNotification")
79 {
80 /* Mark window transition complete: */
81 m_fIsInFullscreenTransition = false;
82 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
83 "Native fullscreen mode entered, notifying listener...\n"));
84 emit sigNotifyAboutNativeFullscreenDidEnter();
85 }
86 /* Handle 'NSWindowWillExitFullScreenNotification' notification: */
87 else if (strNativeNotificationName == "NSWindowWillExitFullScreenNotification")
88 {
89 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
90 "Native fullscreen mode about to exit, notifying listener...\n"));
91 emit sigNotifyAboutNativeFullscreenWillExit();
92 }
93 /* Handle 'NSWindowDidExitFullScreenNotification' notification: */
94 else if (strNativeNotificationName == "NSWindowDidExitFullScreenNotification")
95 {
96 /* Mark window transition complete: */
97 m_fIsInFullscreenTransition = false;
98 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
99 "Native fullscreen mode exited, notifying listener...\n"));
100 emit sigNotifyAboutNativeFullscreenDidExit();
101 }
102 /* Handle 'NSWindowDidFailToEnterFullScreenNotification' notification: */
103 else if (strNativeNotificationName == "NSWindowDidFailToEnterFullScreenNotification")
104 {
105 /* Mark window transition complete: */
106 m_fIsInFullscreenTransition = false;
107 LogRel(("UIMachineWindowFullscreen::handleNativeNotification: "
108 "Native fullscreen mode fail to enter, notifying listener...\n"));
109 emit sigNotifyAboutNativeFullscreenFailToEnter();
110 }
111}
112#endif /* Q_WS_MAC */
113
114#ifndef Q_WS_MAC
115void UIMachineWindowFullscreen::sltMachineStateChanged()
116{
117 /* Call to base-class: */
118 UIMachineWindow::sltMachineStateChanged();
119
120 /* Update mini-toolbar: */
121 updateAppearanceOf(UIVisualElement_MiniToolBar);
122}
123#endif /* !Q_WS_MAC */
124
125#ifdef Q_WS_MAC
126void UIMachineWindowFullscreen::sltEnterNativeFullscreen(UIMachineWindow *pMachineWindow)
127{
128 /* Make sure this slot is called only under ML and next: */
129 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
130
131 /* Make sure it is NULL or 'this' window passed: */
132 if (pMachineWindow && pMachineWindow != this)
133 return;
134
135 /* Make sure this window has fullscreen logic: */
136 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
137 AssertPtrReturnVoid(pFullscreenLogic);
138
139 /* Make sure this window should be shown and mapped to host-screen: */
140 if (!uisession()->isScreenVisible(m_uScreenId) ||
141 !pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
142 return;
143
144 /* Mark window 'transitioned to fullscreen': */
145 m_fIsInFullscreenTransition = true;
146
147 /* Enter native fullscreen mode if necessary: */
148 if ( (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
149 && !darwinIsInFullscreenMode(this))
150 darwinToggleFullscreenMode(this);
151}
152
153void UIMachineWindowFullscreen::sltExitNativeFullscreen(UIMachineWindow *pMachineWindow)
154{
155 /* Make sure this slot is called only under ML and next: */
156 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
157
158 /* Make sure it is NULL or 'this' window passed: */
159 if (pMachineWindow && pMachineWindow != this)
160 return;
161
162 /* Make sure this window has fullscreen logic: */
163 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
164 AssertPtrReturnVoid(pFullscreenLogic);
165
166 /* Mark window 'transitioned from fullscreen': */
167 m_fIsInFullscreenTransition = true;
168
169 /* Exit native fullscreen mode if necessary: */
170 if ( (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
171 && darwinIsInFullscreenMode(this))
172 darwinToggleFullscreenMode(this);
173}
174#endif /* Q_WS_MAC */
175
176void UIMachineWindowFullscreen::sltRevokeFocus()
177{
178 /* Make sure window is visible: */
179 if (!isVisible())
180 return;
181
182#if defined(Q_WS_WIN)
183 /* Revoke stolen focus: */
184 m_pMachineView->setFocus();
185#elif defined(Q_WS_MAC) || defined(Q_WS_X11)
186 /* Revoke stolen activation: */
187 activateWindow();
188#endif /* Q_WS_MAC || Q_WS_X11 */
189}
190
191void UIMachineWindowFullscreen::showMinimized()
192{
193#ifdef Q_WS_X11
194 /* If there is mini-toolbar: */
195 if (m_pMiniToolBar)
196 {
197 /* Minimize it first: */
198 m_pMiniToolBar->showMinimized();
199 }
200#endif /* Q_WS_X11 */
201
202 /* Call to base-class: */
203 UIMachineWindow::showMinimized();
204}
205
206void UIMachineWindowFullscreen::prepareVisualState()
207{
208 /* Call to base-class: */
209 UIMachineWindow::prepareVisualState();
210
211 /* The background has to go black: */
212 QPalette palette(centralWidget()->palette());
213 palette.setColor(centralWidget()->backgroundRole(), Qt::black);
214 centralWidget()->setPalette(palette);
215 centralWidget()->setAutoFillBackground(true);
216 setAutoFillBackground(true);
217
218#ifndef Q_WS_MAC
219 /* Prepare mini-toolbar: */
220 prepareMiniToolbar();
221#endif /* !Q_WS_MAC */
222
223#ifdef Q_WS_MAC
224 /* Native fullscreen stuff on ML and next: */
225 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
226 {
227 /* Make sure this window has fullscreen logic: */
228 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
229 AssertPtrReturnVoid(pFullscreenLogic);
230 /* Enable fullscreen support for every screen which requires it: */
231 if (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
232 darwinEnableFullscreenSupport(this);
233 /* Enable transience support for other screens: */
234 else
235 darwinEnableTransienceSupport(this);
236 /* Register to native fullscreen notifications: */
237 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowWillEnterFullScreenNotification", this,
238 UIMachineWindow::handleNativeNotification);
239 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowDidEnterFullScreenNotification", this,
240 UIMachineWindow::handleNativeNotification);
241 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowWillExitFullScreenNotification", this,
242 UIMachineWindow::handleNativeNotification);
243 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowDidExitFullScreenNotification", this,
244 UIMachineWindow::handleNativeNotification);
245 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowDidFailToEnterFullScreenNotification", this,
246 UIMachineWindow::handleNativeNotification);
247 }
248#endif /* Q_WS_MAC */
249}
250
251#ifndef Q_WS_MAC
252void UIMachineWindowFullscreen::prepareMiniToolbar()
253{
254 /* Make sure mini-toolbar is not restricted: */
255 if (!gEDataManager->miniToolbarEnabled(vboxGlobal().managedVMUuid()))
256 return;
257
258 /* Create mini-toolbar: */
259 m_pMiniToolBar = new UIRuntimeMiniToolBar(this,
260 GeometryType_Full,
261 gEDataManager->miniToolbarAlignment(vboxGlobal().managedVMUuid()),
262 gEDataManager->autoHideMiniToolbar(vboxGlobal().managedVMUuid()));
263 AssertPtrReturnVoid(m_pMiniToolBar);
264 {
265 /* Make sure mini-toolbar is always-on-top of machine-window: */
266 VBoxGlobal::setTransientFor(m_pMiniToolBar, this);
267 /* Configure mini-toolbar: */
268 m_pMiniToolBar->addMenus(actionPool()->menus());
269 connect(m_pMiniToolBar, SIGNAL(sigMinimizeAction()),
270 this, SLOT(showMinimized()), Qt::QueuedConnection);
271 connect(m_pMiniToolBar, SIGNAL(sigExitAction()),
272 actionPool()->action(UIActionIndexRT_M_View_T_Fullscreen), SLOT(trigger()));
273 connect(m_pMiniToolBar, SIGNAL(sigCloseAction()),
274 actionPool()->action(UIActionIndex_M_Application_S_Close), SLOT(trigger()));
275 connect(m_pMiniToolBar, SIGNAL(sigNotifyAboutFocusStolen()),
276 this, SLOT(sltRevokeFocus()), Qt::QueuedConnection);
277 }
278}
279#endif /* !Q_WS_MAC */
280
281#ifndef Q_WS_MAC
282void UIMachineWindowFullscreen::cleanupMiniToolbar()
283{
284 /* Make sure mini-toolbar was created: */
285 if (!m_pMiniToolBar)
286 return;
287
288 /* Save mini-toolbar settings: */
289 gEDataManager->setAutoHideMiniToolbar(m_pMiniToolBar->autoHide(), vboxGlobal().managedVMUuid());
290 /* Delete mini-toolbar: */
291 delete m_pMiniToolBar;
292 m_pMiniToolBar = 0;
293}
294#endif /* !Q_WS_MAC */
295
296void UIMachineWindowFullscreen::cleanupVisualState()
297{
298#ifdef Q_WS_MAC
299 /* Native fullscreen stuff on ML and next: */
300 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
301 {
302 /* Unregister from native fullscreen notifications: */
303 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowWillEnterFullScreenNotification", this);
304 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowDidEnterFullScreenNotification", this);
305 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowWillExitFullScreenNotification", this);
306 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowDidExitFullScreenNotification", this);
307 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowDidFailToEnterFullScreenNotification", this);
308 }
309#endif /* Q_WS_MAC */
310
311#ifndef Q_WS_MAC
312 /* Cleanup mini-toolbar: */
313 cleanupMiniToolbar();
314#endif /* !Q_WS_MAC */
315
316 /* Call to base-class: */
317 UIMachineWindow::cleanupVisualState();
318}
319
320void UIMachineWindowFullscreen::placeOnScreen()
321{
322 /* Get corresponding screen: */
323 const int iScreen = qobject_cast<UIMachineLogicFullscreen*>(machineLogic())->hostScreenForGuestScreen(m_uScreenId);
324 /* And corresponding working area: */
325 const QRect workingArea = QApplication::desktop()->screenGeometry(iScreen);
326
327 /* Move to the appropriate position: */
328 move(workingArea.topLeft());
329
330#ifdef Q_WS_MAC
331 /* Make sure this window has fullscreen logic: */
332 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
333 AssertPtrReturnVoid(pFullscreenLogic);
334
335 /* Resize to the appropriate size on Lion and previous: */
336 if (vboxGlobal().osRelease() <= MacOSXRelease_Lion)
337 resize(workingArea.size());
338 /* Resize to the appropriate size on ML and next
339 * only if that screen has no own user-space: */
340 else if (!pFullscreenLogic->screensHaveSeparateSpaces() && m_uScreenId != 0)
341 resize(workingArea.size());
342 else
343 {
344 /* Load normal geometry first of all: */
345 QRect geo = gEDataManager->machineWindowGeometry(UIVisualStateType_Normal, m_uScreenId, vboxGlobal().managedVMUuid());
346 /* If normal geometry is null => use frame-buffer size: */
347 if (geo.isNull())
348 {
349 const UIFrameBuffer *pFrameBuffer = uisession()->frameBuffer(m_uScreenId);
350 geo = QRect(QPoint(0, 0), QSize(pFrameBuffer->width(), pFrameBuffer->height()).boundedTo(workingArea.size()));
351 }
352 /* If frame-buffer size is null => use default size: */
353 if (geo.isNull())
354 geo = QRect(QPoint(0, 0), QSize(800, 600).boundedTo(workingArea.size()));
355 /* Move window to the center of working-area: */
356 geo.moveCenter(workingArea.center());
357 setGeometry(geo);
358 }
359#else /* !Q_WS_MAC */
360 /* Resize to the appropriate size: */
361 resize(workingArea.size());
362#endif /* !Q_WS_MAC */
363}
364
365void UIMachineWindowFullscreen::showInNecessaryMode()
366{
367 /* Make sure this window has fullscreen logic: */
368 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
369 AssertPtrReturnVoid(pFullscreenLogic);
370
371#ifdef Q_WS_MAC
372 /* ML and next using native stuff: */
373 const bool fSupportsNativeFullScreen = vboxGlobal().osRelease() > MacOSXRelease_Lion;
374#endif /* Q_WS_MAC */
375
376 /* Make sure this window should be shown and mapped to some host-screen: */
377 if (!uisession()->isScreenVisible(m_uScreenId) ||
378 !pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
379 {
380#ifndef Q_WS_MAC
381 /* If there is mini-toolbar: */
382 if (m_pMiniToolBar)
383 {
384 /* Just hide mini-toolbar: */
385 m_pMiniToolBar->hide();
386 }
387#endif /* !Q_WS_MAC */
388 /* Hide window: */
389 hide();
390 return;
391 }
392
393 /* Make sure this window is not minimized: */
394 if (isMinimized())
395 return;
396
397#ifdef Q_WS_X11
398 /* On X11 calling placeOnScreen() is only needed for legacy window managers
399 * which we do not test, so this is 'best effort' code. With window managers which
400 * support the _NET_WM_FULLSCREEN_MONITORS protocol this would interfere unreliable. */
401 const bool fSupportsNativeFullScreen = VBoxGlobal::supportsFullScreenMonitorsProtocolX11() &&
402 !gEDataManager->legacyFullscreenModeRequested();
403 if (!fSupportsNativeFullScreen)
404 placeOnScreen();
405#else /* !Q_WS_X11 */
406 /* Make sure this window is maximized and placed on valid screen: */
407 placeOnScreen();
408#endif /* !Q_WS_X11 */
409
410#ifdef Q_WS_MAC
411 /* ML and next using native stuff, so we can call for simple show(),
412 * Lion and previous using Qt stuff, so we should call for showFullScreen(): */
413 if (fSupportsNativeFullScreen)
414 show();
415 else
416 showFullScreen();
417#else /* !Q_WS_MAC */
418 /* Show in fullscreen mode: */
419 showFullScreen();
420#endif /* !Q_WS_MAC */
421
422#ifdef Q_WS_X11
423 if (fSupportsNativeFullScreen)
424 {
425 /* Tell recent window managers which screen this window should be mapped to.
426 * Apparently some window managers will not respond to requests for
427 * unmapped windows, so do this *after* the call to showFullScreen(). */
428 VBoxGlobal::setFullScreenMonitorX11(this, pFullscreenLogic->hostScreenForGuestScreen(m_uScreenId));
429 }
430 else
431 {
432 /* On X11 calling placeOnScreen() is only needed for legacy window managers
433 * which we do not test, so this is 'best effort' code. With window managers which
434 * support the _NET_WM_FULLSCREEN_MONITORS protocol this would interfere unreliable. */
435 placeOnScreen();
436 }
437#endif /* Q_WS_X11 */
438
439 /* Adjust machine-view size if necessary: */
440 adjustMachineViewSize();
441
442#ifndef Q_WS_MAC
443 /* If there is mini-toolbar: */
444 if (m_pMiniToolBar)
445 {
446# if defined(Q_WS_WIN)
447 /* Just show mini-toolbar: */
448 m_pMiniToolBar->show();
449# elif defined(Q_WS_X11)
450 /* Allow mini-toolbar to be located on full-screen area: */
451 m_pMiniToolBar->showFullScreen();
452 /* On modern window managers: */
453 if (fSupportsNativeFullScreen)
454 {
455 /* We also can map mini-toolbar directly on corresponding machine-window: */
456 VBoxGlobal::setFullScreenMonitorX11(m_pMiniToolBar, pFullscreenLogic->hostScreenForGuestScreen(m_uScreenId));
457 }
458# endif /* Q_WS_X11 */
459 }
460#endif /* !Q_WS_MAC */
461
462 /* Make sure machine-view have focus: */
463 m_pMachineView->setFocus();
464}
465
466void UIMachineWindowFullscreen::adjustMachineViewSize()
467{
468 /* Call to base-class: */
469 UIMachineWindow::adjustMachineViewSize();
470
471#ifndef Q_WS_MAC
472 /* If mini-toolbar present: */
473 if (m_pMiniToolBar)
474 {
475 /* Make sure this window has fullscreen logic: */
476 const UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
477 AssertPtrReturnVoid(pFullscreenLogic);
478
479 /* Which host-screen should that machine-window located on? */
480 const int iHostScreen = pFullscreenLogic->hostScreenForGuestScreen(m_uScreenId);
481
482#ifndef Q_WS_X11
483 /* Move mini-toolbar into appropriate place: */
484 m_pMiniToolBar->adjustGeometry(iHostScreen);
485#else /* Q_WS_X11 */
486 /* On modern WMs we are mapping mini-toolbar to corresponding host-screen directly. */
487 const bool fSupportsNativeFullScreen = VBoxGlobal::supportsFullScreenMonitorsProtocolX11() &&
488 !gEDataManager->legacyFullscreenModeRequested();
489 /* Adjust mini-toolbar and move into appropriate place if necessary: */
490 m_pMiniToolBar->adjustGeometry(fSupportsNativeFullScreen ? -1 : iHostScreen);
491#endif /* Q_WS_X11 */
492 }
493#endif /* !Q_WS_MAC */
494}
495
496#ifndef Q_WS_MAC
497void UIMachineWindowFullscreen::updateAppearanceOf(int iElement)
498{
499 /* Call to base-class: */
500 UIMachineWindow::updateAppearanceOf(iElement);
501
502 /* Update mini-toolbar: */
503 if (iElement & UIVisualElement_MiniToolBar)
504 {
505 if (m_pMiniToolBar)
506 {
507 /* Get snapshot(s): */
508 QString strSnapshotName;
509 if (machine().GetSnapshotCount() > 0)
510 {
511 CSnapshot snapshot = machine().GetCurrentSnapshot();
512 strSnapshotName = " (" + snapshot.GetName() + ")";
513 }
514 /* Update mini-toolbar text: */
515 m_pMiniToolBar->setText(machineName() + strSnapshotName);
516 }
517 }
518}
519#endif /* !Q_WS_MAC */
520
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