VirtualBox

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

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

FE/Qt: Runtime UI: Visual-mode adjustment code: Separate code reordering for r101761 to keep it clear.

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