VirtualBox

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

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

FE/Qt: 5978: Runtime UI: Mini-toolbar: Simplify window activation stealing handling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.2 KB
Line 
1/* $Id: UIMachineWindowFullscreen.cpp 57050 2015-07-21 17:52: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::sltRevokeWindowActivation()
126{
127 /* Make sure window is visible: */
128 if (!isVisible() || isMinimized())
129 return;
130
131 /* Revoke stolen activation: */
132 activateWindow();
133}
134#endif /* Q_WS_WIN || Q_WS_X11 */
135
136#ifdef Q_WS_MAC
137void UIMachineWindowFullscreen::sltEnterNativeFullscreen(UIMachineWindow *pMachineWindow)
138{
139 /* Make sure this slot is called only under ML and next: */
140 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
141
142 /* Make sure it is NULL or 'this' window passed: */
143 if (pMachineWindow && pMachineWindow != this)
144 return;
145
146 /* Make sure this window has fullscreen logic: */
147 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
148 AssertPtrReturnVoid(pFullscreenLogic);
149
150 /* Make sure this window should be shown and mapped to host-screen: */
151 if (!uisession()->isScreenVisible(m_uScreenId) ||
152 !pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
153 return;
154
155 /* Mark window 'transitioned to fullscreen': */
156 m_fIsInFullscreenTransition = true;
157
158 /* Enter native fullscreen mode if necessary: */
159 if ( (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
160 && !darwinIsInFullscreenMode(this))
161 darwinToggleFullscreenMode(this);
162}
163
164void UIMachineWindowFullscreen::sltExitNativeFullscreen(UIMachineWindow *pMachineWindow)
165{
166 /* Make sure this slot is called only under ML and next: */
167 AssertReturnVoid(vboxGlobal().osRelease() > MacOSXRelease_Lion);
168
169 /* Make sure it is NULL or 'this' window passed: */
170 if (pMachineWindow && pMachineWindow != this)
171 return;
172
173 /* Make sure this window has fullscreen logic: */
174 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
175 AssertPtrReturnVoid(pFullscreenLogic);
176
177 /* Mark window 'transitioned from fullscreen': */
178 m_fIsInFullscreenTransition = true;
179
180 /* Exit native fullscreen mode if necessary: */
181 if ( (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
182 && darwinIsInFullscreenMode(this))
183 darwinToggleFullscreenMode(this);
184}
185#endif /* Q_WS_MAC */
186
187void UIMachineWindowFullscreen::prepareVisualState()
188{
189 /* Call to base-class: */
190 UIMachineWindow::prepareVisualState();
191
192 /* The background has to go black: */
193 QPalette palette(centralWidget()->palette());
194 palette.setColor(centralWidget()->backgroundRole(), Qt::black);
195 centralWidget()->setPalette(palette);
196 centralWidget()->setAutoFillBackground(true);
197 setAutoFillBackground(true);
198
199#if defined(Q_WS_WIN) || defined(Q_WS_X11)
200 /* Prepare mini-toolbar: */
201 prepareMiniToolbar();
202#endif /* Q_WS_WIN || Q_WS_X11 */
203
204#ifdef Q_WS_MAC
205 /* Native fullscreen stuff on ML and next: */
206 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
207 {
208 /* Make sure this window has fullscreen logic: */
209 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
210 AssertPtrReturnVoid(pFullscreenLogic);
211 /* Enable fullscreen support for every screen which requires it: */
212 if (pFullscreenLogic->screensHaveSeparateSpaces() || m_uScreenId == 0)
213 darwinEnableFullscreenSupport(this);
214 /* Enable transience support for other screens: */
215 else
216 darwinEnableTransienceSupport(this);
217 /* Register to native fullscreen notifications: */
218 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowWillEnterFullScreenNotification", this,
219 UIMachineWindow::handleNativeNotification);
220 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowDidEnterFullScreenNotification", this,
221 UIMachineWindow::handleNativeNotification);
222 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowWillExitFullScreenNotification", this,
223 UIMachineWindow::handleNativeNotification);
224 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowDidExitFullScreenNotification", this,
225 UIMachineWindow::handleNativeNotification);
226 UICocoaApplication::instance()->registerToNotificationOfWindow("NSWindowDidFailToEnterFullScreenNotification", this,
227 UIMachineWindow::handleNativeNotification);
228 }
229#endif /* Q_WS_MAC */
230}
231
232#if defined(Q_WS_WIN) || defined(Q_WS_X11)
233void UIMachineWindowFullscreen::prepareMiniToolbar()
234{
235 /* Make sure mini-toolbar is not restricted: */
236 if (!gEDataManager->miniToolbarEnabled(vboxGlobal().managedVMUuid()))
237 return;
238
239 /* Create mini-toolbar: */
240 m_pMiniToolBar = new UIMiniToolBar(this,
241 GeometryType_Full,
242 gEDataManager->miniToolbarAlignment(vboxGlobal().managedVMUuid()),
243 gEDataManager->autoHideMiniToolbar(vboxGlobal().managedVMUuid()));
244 AssertPtrReturnVoid(m_pMiniToolBar);
245 {
246 /* Configure mini-toolbar: */
247 m_pMiniToolBar->addMenus(actionPool()->menus());
248 connect(m_pMiniToolBar, SIGNAL(sigMinimizeAction()),
249 this, SLOT(showMinimized()), Qt::QueuedConnection);
250 connect(m_pMiniToolBar, SIGNAL(sigExitAction()),
251 actionPool()->action(UIActionIndexRT_M_View_T_Fullscreen), SLOT(trigger()));
252 connect(m_pMiniToolBar, SIGNAL(sigCloseAction()),
253 actionPool()->action(UIActionIndex_M_Application_S_Close), SLOT(trigger()));
254 connect(m_pMiniToolBar, SIGNAL(sigNotifyAboutWindowActivationStolen()),
255 this, SLOT(sltRevokeWindowActivation()), Qt::QueuedConnection);
256 }
257}
258#endif /* Q_WS_WIN || Q_WS_X11 */
259
260#if defined(Q_WS_WIN) || defined(Q_WS_X11)
261void UIMachineWindowFullscreen::cleanupMiniToolbar()
262{
263 /* Make sure mini-toolbar was created: */
264 if (!m_pMiniToolBar)
265 return;
266
267 /* Save mini-toolbar settings: */
268 gEDataManager->setAutoHideMiniToolbar(m_pMiniToolBar->autoHide(), vboxGlobal().managedVMUuid());
269 /* Delete mini-toolbar: */
270 delete m_pMiniToolBar;
271 m_pMiniToolBar = 0;
272}
273#endif /* Q_WS_WIN || Q_WS_X11 */
274
275void UIMachineWindowFullscreen::cleanupVisualState()
276{
277#ifdef Q_WS_MAC
278 /* Native fullscreen stuff on ML and next: */
279 if (vboxGlobal().osRelease() > MacOSXRelease_Lion)
280 {
281 /* Unregister from native fullscreen notifications: */
282 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowWillEnterFullScreenNotification", this);
283 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowDidEnterFullScreenNotification", this);
284 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowWillExitFullScreenNotification", this);
285 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowDidExitFullScreenNotification", this);
286 UICocoaApplication::instance()->unregisterFromNotificationOfWindow("NSWindowDidFailToEnterFullScreenNotification", this);
287 }
288#endif /* Q_WS_MAC */
289
290#if defined(Q_WS_WIN) || defined(Q_WS_X11)
291 /* Cleanup mini-toolbar: */
292 cleanupMiniToolbar();
293#endif /* Q_WS_WIN || Q_WS_X11 */
294
295 /* Call to base-class: */
296 UIMachineWindow::cleanupVisualState();
297}
298
299void UIMachineWindowFullscreen::placeOnScreen()
300{
301 /* Get corresponding host-screen: */
302 const int iHostScreen = qobject_cast<UIMachineLogicFullscreen*>(machineLogic())->hostScreenForGuestScreen(m_uScreenId);
303 /* And corresponding working area: */
304 const QRect workingArea = QApplication::desktop()->screenGeometry(iHostScreen);
305
306#if defined(Q_WS_WIN) || defined(Q_WS_X11)
307 /* Set appropriate geometry for window: */
308 move(workingArea.topLeft());
309 resize(workingArea.size());
310
311 /* If there is a mini-toolbar: */
312 if (m_pMiniToolBar)
313 {
314 /* Set appropriate geometry for mini-toolbar: */
315 m_pMiniToolBar->move(workingArea.topLeft());
316 m_pMiniToolBar->resize(workingArea.size());
317 }
318#elif defined(Q_WS_MAC)
319 /* Make sure this window has fullscreen logic: */
320 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
321 AssertPtrReturnVoid(pFullscreenLogic);
322
323 /* Move window to the appropriate position: */
324 move(workingArea.topLeft());
325
326 /* Resize window to the appropriate size on Lion and previous: */
327 if (vboxGlobal().osRelease() <= MacOSXRelease_Lion)
328 resize(workingArea.size());
329 /* Resize window to the appropriate size on ML and next
330 * only if that screen has no own user-space: */
331 else if (!pFullscreenLogic->screensHaveSeparateSpaces() && m_uScreenId != 0)
332 resize(workingArea.size());
333 else
334 {
335 /* Load normal geometry first of all: */
336 QRect geo = gEDataManager->machineWindowGeometry(UIVisualStateType_Normal, m_uScreenId, vboxGlobal().managedVMUuid());
337 /* If normal geometry is null => use frame-buffer size: */
338 if (geo.isNull())
339 {
340 const UIFrameBuffer *pFrameBuffer = uisession()->frameBuffer(m_uScreenId);
341 geo = QRect(QPoint(0, 0), QSize(pFrameBuffer->width(), pFrameBuffer->height()).boundedTo(workingArea.size()));
342 }
343 /* If frame-buffer size is null => use default size: */
344 if (geo.isNull())
345 geo = QRect(QPoint(0, 0), QSize(800, 600).boundedTo(workingArea.size()));
346 /* Move window to the center of working-area: */
347 geo.moveCenter(workingArea.center());
348 setGeometry(geo);
349 }
350#endif /* Q_WS_MAC */
351}
352
353void UIMachineWindowFullscreen::showInNecessaryMode()
354{
355 /* Make sure window has fullscreen logic: */
356 UIMachineLogicFullscreen *pFullscreenLogic = qobject_cast<UIMachineLogicFullscreen*>(machineLogic());
357 AssertPtrReturnVoid(pFullscreenLogic);
358
359 /* Make sure window should be shown and mapped to some host-screen: */
360 if (!uisession()->isScreenVisible(m_uScreenId) ||
361 !pFullscreenLogic->hasHostScreenForGuestScreen(m_uScreenId))
362 {
363#if defined(Q_WS_WIN) || defined(Q_WS_X11)
364 /* If there is a mini-toolbar: */
365 if (m_pMiniToolBar)
366 {
367 /* Hide mini-toolbar: */
368 m_pMiniToolBar->hide();
369 }
370#endif /* Q_WS_WIN || Q_WS_X11 */
371
372 /* Hide window: */
373 hide();
374 }
375 else
376 {
377 /* Ignore if window minimized: */
378 if (isMinimized())
379 return;
380
381#ifdef Q_WS_X11
382 /* If WM doesn't support native stuff, we need to call for placeOnScreen(): */
383 const bool fSupportsNativeFullScreen = VBoxGlobal::supportsFullScreenMonitorsProtocolX11() &&
384 !gEDataManager->legacyFullscreenModeRequested();
385 if (!fSupportsNativeFullScreen)
386 {
387 /* Make sure window have appropriate geometry: */
388 placeOnScreen();
389 }
390#else /* !Q_WS_X11 */
391 /* Make sure window have appropriate geometry: */
392 placeOnScreen();
393#endif /* !Q_WS_X11 */
394
395#if defined(Q_WS_MAC)
396 /* ML and next using native stuff, so we can call for simple show(),
397 * Lion and previous using Qt stuff, so we should call for showFullScreen(): */
398 const bool fSupportsNativeFullScreen = vboxGlobal().osRelease() > MacOSXRelease_Lion;
399 if (fSupportsNativeFullScreen)
400 {
401 /* Show window in normal mode: */
402 show();
403 }
404 else
405 {
406 /* Show window in fullscreen mode: */
407 showFullScreen();
408 }
409#elif defined(Q_WS_WIN) || defined(Q_WS_X11)
410 /* Show window in fullscreen mode: */
411 showFullScreen();
412
413 /* If there is a mini-toolbar: */
414 if (m_pMiniToolBar)
415 {
416 /* Show mini-toolbar in full-screen mode: */
417 m_pMiniToolBar->showFullScreen();
418 }
419#endif /* Q_WS_WIN || Q_WS_X11 */
420
421#ifdef Q_WS_X11
422 /* If WM supports native stuff, we need to map window to corresponding host-screen. */
423 if (fSupportsNativeFullScreen)
424 {
425 /* Tell recent window managers which host-screen this window should be mapped to: */
426 VBoxGlobal::setFullScreenMonitorX11(this, pFullscreenLogic->hostScreenForGuestScreen(m_uScreenId));
427
428 /* If there is a mini-toolbar: */
429 if (m_pMiniToolBar)
430 {
431 /* Tell recent window managers which host-screen this mini-toolbar should be mapped to: */
432 VBoxGlobal::setFullScreenMonitorX11(m_pMiniToolBar, pFullscreenLogic->hostScreenForGuestScreen(m_uScreenId));
433 }
434 }
435#endif /* Q_WS_X11 */
436
437 /* Adjust machine-view size if necessary: */
438 adjustMachineViewSize();
439
440 /* Make sure machine-view have focus: */
441 m_pMachineView->setFocus();
442 }
443}
444
445#if defined(Q_WS_WIN) || defined(Q_WS_X11)
446void UIMachineWindowFullscreen::updateAppearanceOf(int iElement)
447{
448 /* Call to base-class: */
449 UIMachineWindow::updateAppearanceOf(iElement);
450
451 /* Update mini-toolbar: */
452 if (iElement & UIVisualElement_MiniToolBar)
453 {
454 /* If there is a mini-toolbar: */
455 if (m_pMiniToolBar)
456 {
457 /* Get snapshot(s): */
458 QString strSnapshotName;
459 if (machine().GetSnapshotCount() > 0)
460 {
461 CSnapshot snapshot = machine().GetCurrentSnapshot();
462 strSnapshotName = " (" + snapshot.GetName() + ")";
463 }
464 /* Update mini-toolbar text: */
465 m_pMiniToolBar->setText(machineName() + strSnapshotName);
466 }
467 }
468}
469#endif /* Q_WS_WIN || Q_WS_X11 */
470
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