VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp

Last change on this file was 106349, checked in by vboxsync, 7 weeks ago

FE/Qt: bugref:10407. Default to Wayland QPA even if XWayland is around.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.6 KB
Line 
1/* $Id: UIMachineWindow.cpp 106349 2024-10-16 10:03:28Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMachineWindow class implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QCloseEvent>
30#include <QGridLayout>
31#include <QProcess>
32#include <QStyle>
33#include <QTimer>
34
35/* GUI includes: */
36#include "UIActionPoolRuntime.h"
37#include "UICommon.h"
38#include "UIConverter.h"
39#include "UIModalWindowManager.h"
40#include "UIExtraDataManager.h"
41#include "UILoggingDefs.h"
42#include "UIMachine.h"
43#include "UIMessageCenter.h"
44#include "UIMachineLogic.h"
45#include "UIMachineWindow.h"
46#include "UIMachineWindowNormal.h"
47#include "UIMachineWindowFullscreen.h"
48#include "UIMachineWindowSeamless.h"
49#include "UIMachineWindowScale.h"
50#include "UIMachineView.h"
51#include "UIKeyboardHandler.h"
52#include "UIMouseHandler.h"
53#include "UITranslationEventListener.h"
54#include "UIVMCloseDialog.h"
55
56/* COM includes: */
57#include "CGraphicsAdapter.h"
58#include "CSnapshot.h"
59
60/* Other VBox includes: */
61#include <VBox/version.h>
62#ifdef VBOX_BLEEDING_EDGE
63# include <iprt/buildconfig.h>
64#endif /* VBOX_BLEEDING_EDGE */
65
66
67/* static */
68UIMachineWindow* UIMachineWindow::create(UIMachineLogic *pMachineLogic, ulong uScreenId)
69{
70 /* Create machine-window: */
71 UIMachineWindow *pMachineWindow = 0;
72 switch (pMachineLogic->visualStateType())
73 {
74 case UIVisualStateType_Normal:
75 pMachineWindow = new UIMachineWindowNormal(pMachineLogic, uScreenId);
76 break;
77 case UIVisualStateType_Fullscreen:
78 pMachineWindow = new UIMachineWindowFullscreen(pMachineLogic, uScreenId);
79 break;
80 case UIVisualStateType_Seamless:
81 pMachineWindow = new UIMachineWindowSeamless(pMachineLogic, uScreenId);
82 break;
83 case UIVisualStateType_Scale:
84 pMachineWindow = new UIMachineWindowScale(pMachineLogic, uScreenId);
85 break;
86 default:
87 AssertMsgFailed(("Incorrect visual state!"));
88 break;
89 }
90 /* Prepare machine-window: */
91 pMachineWindow->prepare();
92 /* Return machine-window: */
93 return pMachineWindow;
94}
95
96/* static */
97void UIMachineWindow::destroy(UIMachineWindow *pWhichWindow)
98{
99 /* Cleanup machine-window: */
100 pWhichWindow->cleanup();
101 /* Delete machine-window: */
102 delete pWhichWindow;
103}
104
105void UIMachineWindow::prepare()
106{
107 /* Prepare dialog itself: */
108 prepareSelf();
109
110 /* Prepare session-connections: */
111 prepareSessionConnections();
112
113 /* Prepare main-layout: */
114 prepareMainLayout();
115
116 /* Prepare menu: */
117 prepareMenu();
118
119 /* Prepare status-bar: */
120 prepareStatusBar();
121
122 /* Prepare visual-state: */
123 prepareVisualState();
124
125 /* Prepare machine-view: */
126 prepareMachineView();
127
128 /* Prepare notification-center: */
129 prepareNotificationCenter();
130
131 /* Prepare handlers: */
132 prepareHandlers();
133
134 /* Load settings: */
135 loadSettings();
136
137 /* Retranslate window: */
138 sltRetranslateUI();
139 connect(&translationEventListener(), &UITranslationEventListener::sigRetranslateUI,
140 this, &UIMachineWindow::sltRetranslateUI);
141
142 /* Show (must be done before updating the appearance): */
143 showInNecessaryMode();
144
145 /* Update all the elements: */
146 updateAppearanceOf(UIVisualElement_AllStuff);
147
148#ifdef VBOX_WS_NIX
149 /* Prepare default class/name values: */
150 const QString strWindowClass = QString("VirtualBox Machine");
151 QString strWindowName = strWindowClass;
152 /* Check if we want Window Manager to distinguish Virtual Machine windows: */
153 if (gEDataManager->distinguishMachineWindowGroups(uiCommon().managedVMUuid()))
154 strWindowName = QString("VirtualBox Machine UUID: %1").arg(uiCommon().managedVMUuid().toString());
155 /* Assign WM_CLASS property: */
156 NativeWindowSubsystem::setWMClass(this, strWindowName, strWindowClass);
157 /* Tell the WM we are well behaved wrt Xwayland keyboard-grabs: */
158 NativeWindowSubsystem::setXwaylandMayGrabKeyboardFlag(this);
159#endif
160}
161
162void UIMachineWindow::cleanup()
163{
164 /* Save window settings: */
165 saveSettings();
166
167 /* Cleanup handlers: */
168 cleanupHandlers();
169
170 /* Cleanup visual-state: */
171 cleanupVisualState();
172
173 /* Cleanup notification-center: */
174 cleanupNotificationCenter();
175
176 /* Cleanup machine-view: */
177 cleanupMachineView();
178
179 /* Cleanup status-bar: */
180 cleanupStatusBar();
181
182 /* Cleanup menu: */
183 cleanupMenu();
184
185 /* Cleanup main layout: */
186 cleanupMainLayout();
187
188 /* Cleanup session connections: */
189 cleanupSessionConnections();
190}
191
192void UIMachineWindow::sltMachineStateChanged()
193{
194 /* Update window-title: */
195 updateAppearanceOf(UIVisualElement_WindowTitle);
196}
197
198UIMachineWindow::UIMachineWindow(UIMachineLogic *pMachineLogic, ulong uScreenId)
199 : QMainWindow(0, pMachineLogic->windowFlags(uScreenId))
200 , m_pMachineLogic(pMachineLogic)
201 , m_pMachineView(0)
202 , m_uScreenId(uScreenId)
203 , m_pMainLayout(0)
204 , m_pTopSpacer(0)
205 , m_pBottomSpacer(0)
206 , m_pLeftSpacer(0)
207 , m_pRightSpacer(0)
208{
209}
210
211UIMachine *UIMachineWindow::uimachine() const
212{
213 return machineLogic()->uimachine();
214}
215
216UIActionPool *UIMachineWindow::actionPool() const
217{
218 return machineLogic()->actionPool();
219}
220
221QString UIMachineWindow::machineName() const
222{
223 return uimachine()->machineName();
224}
225
226bool UIMachineWindow::shouldResizeToGuestDisplay() const
227{
228 return actionPool()
229 && actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize)
230 && actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize)->isChecked();
231}
232
233void UIMachineWindow::adjustMachineViewSize()
234{
235 /* We need to adjust guest-screen size if necessary: */
236 machineView()->adjustGuestScreenSize();
237}
238
239void UIMachineWindow::sendMachineViewSizeHint()
240{
241 /* Send machine-view size-hint to the guest: */
242 machineView()->resendSizeHint();
243}
244
245#ifdef VBOX_WITH_MASKED_SEAMLESS
246void UIMachineWindow::setMask(const QRegion &region)
247{
248 /* Call to base-class: */
249 QMainWindow::setMask(region);
250}
251#endif /* VBOX_WITH_MASKED_SEAMLESS */
252
253void UIMachineWindow::updateAppearanceOf(int iElement)
254{
255 /* Update window title: */
256 if (iElement & UIVisualElement_WindowTitle)
257 {
258 /* Make sure machine state is one of valid: */
259 const KMachineState enmState = uimachine()->machineState();
260 if (enmState == KMachineState_Null)
261 {
262 /* Assign default window title: */
263 setWindowTitle(defaultWindowTitle());
264 }
265 else
266 {
267 /* Prepare full name: */
268 QString strMachineName = machineName();
269
270 /* Append snapshot name: */
271 ulong uSnapshotCount = 0;
272 uimachine()->acquireSnapshotCount(uSnapshotCount);
273 if (uSnapshotCount > 0)
274 {
275 QString strCurrentSnapshotName;
276 uimachine()->acquireCurrentSnapshotName(strCurrentSnapshotName);
277 strMachineName += " (" + strCurrentSnapshotName + ")";
278 }
279
280 /* Append state name: */
281 strMachineName += " [" + gpConverter->toString(enmState) + "]";
282
283#ifndef VBOX_WS_MAC
284 /* Append user product name (besides macOS): */
285 const QString strUserProductName = uimachine()->machineWindowNamePostfix();
286 strMachineName += " - " + (strUserProductName.isEmpty() ? defaultWindowTitle() : strUserProductName);
287#endif /* !VBOX_WS_MAC */
288
289 /* Append screen number only if there are more than one present: */
290 ulong cMonitorCount = 0;
291 uimachine()->acquireMonitorCount(cMonitorCount);
292 if (cMonitorCount > 1)
293 strMachineName += QString(" : %1").arg(m_uScreenId + 1);
294
295 /* Assign title finally: */
296 setWindowTitle(strMachineName);
297 }
298 }
299}
300
301void UIMachineWindow::sltRetranslateUI()
302{
303 /* Compose window-title prefix: */
304 m_strWindowTitlePrefix = VBOX_PRODUCT;
305#ifdef VBOX_BLEEDING_EDGE
306 m_strWindowTitlePrefix += UIMachineWindow::tr(" EXPERIMENTAL build %1r%2 - %3")
307 .arg(RTBldCfgVersion())
308 .arg(RTBldCfgRevisionStr())
309 .arg(VBOX_BLEEDING_EDGE);
310#endif /* VBOX_BLEEDING_EDGE */
311 /* Update appearance of the window-title: */
312 updateAppearanceOf(UIVisualElement_WindowTitle);
313}
314
315bool UIMachineWindow::event(QEvent *pEvent)
316{
317 /* Call to base-class: */
318 const bool fResult = QMainWindow::event(pEvent);
319
320 /* Handle particular events: */
321 switch (pEvent->type())
322 {
323 case QEvent::WindowActivate:
324 {
325 /* Initiate registration in the modal window manager: */
326 windowManager().setMainWindowShown(this);
327 break;
328 }
329 default:
330 break;
331 }
332
333 /* Return result: */
334 return fResult;
335}
336
337void UIMachineWindow::showEvent(QShowEvent *pEvent)
338{
339 /* Call to base-class: */
340 QMainWindow::showEvent(pEvent);
341
342 /* Initiate registration in the modal window manager: */
343 windowManager().setMainWindowShown(this);
344
345 /* Update appearance for indicator-pool: */
346 updateAppearanceOf(UIVisualElement_IndicatorPool);
347}
348
349void UIMachineWindow::hideEvent(QHideEvent *pEvent)
350{
351 /* Update registration in the modal window manager: */
352 if (windowManager().mainWindowShown() == this)
353 {
354 if (machineLogic()->activeMachineWindow())
355 windowManager().setMainWindowShown(machineLogic()->activeMachineWindow());
356 else
357 windowManager().setMainWindowShown(machineLogic()->mainMachineWindow());
358 }
359
360 /* Call to base-class: */
361 QMainWindow::hideEvent(pEvent);
362}
363
364void UIMachineWindow::closeEvent(QCloseEvent *pCloseEvent)
365{
366 /* Always ignore close-event first: */
367 pCloseEvent->ignore();
368 /* But accept close-event if app quit was requested: */
369 if (uimachine()->isQuitRequested())
370 {
371 pCloseEvent->accept();
372 return;
373 }
374
375 /* In certain cases we need to just request app quit: */
376 if ( !uimachine()->isSessionValid()
377 || uimachine()->isTurnedOff())
378 {
379 uimachine()->closeRuntimeUI();
380 return;
381 }
382
383 /* Make sure machine is in one of the allowed states: */
384 if (!uimachine()->isRunning() && !uimachine()->isPaused() && !uimachine()->isStuck())
385 return;
386
387 /* If there is a close hook script defined: */
388 const QString strScript = gEDataManager->machineCloseHookScript(uiCommon().managedVMUuid());
389 if (!strScript.isEmpty())
390 {
391 /* Execute asynchronously and leave: */
392 QProcess::startDetached(strScript, QStringList() << uiCommon().managedVMUuid().toString());
393 return;
394 }
395
396 /* Choose the close action: */
397 MachineCloseAction closeAction = MachineCloseAction_Invalid;
398
399 /* If default close-action defined and not restricted: */
400 MachineCloseAction defaultCloseAction = uimachine()->defaultCloseAction();
401 MachineCloseAction restrictedCloseActions = uimachine()->restrictedCloseActions();
402 if ((defaultCloseAction != MachineCloseAction_Invalid) &&
403 !(restrictedCloseActions & defaultCloseAction))
404 {
405 switch (defaultCloseAction)
406 {
407 /* If VM is stuck, and the default close-action is 'detach', 'save-state' or 'shutdown',
408 * we should ask the user about what to do: */
409 case MachineCloseAction_Detach:
410 case MachineCloseAction_SaveState:
411 case MachineCloseAction_Shutdown:
412 closeAction = uimachine()->isStuck() ? MachineCloseAction_Invalid : defaultCloseAction;
413 break;
414 /* Otherwise we just use what we have: */
415 default:
416 closeAction = defaultCloseAction;
417 break;
418 }
419 }
420
421 /* If the close-action still undefined: */
422 if (closeAction == MachineCloseAction_Invalid)
423 {
424 /* Prepare close-dialog: */
425 QWidget *pParentDlg = windowManager().realParentWindow(this);
426 bool fInACPIMode = false;
427 uimachine()->acquireWhetherGuestEnteredACPIMode(fInACPIMode);
428 QPointer<UIVMCloseDialog> pCloseDlg = new UIVMCloseDialog(pParentDlg, uimachine(),
429 fInACPIMode,
430 restrictedCloseActions);
431 /* Configure close-dialog: */
432 if (uimachine()->machineWindowIcon())
433 pCloseDlg->setIcon(*uimachine()->machineWindowIcon());
434
435 /* Make sure close-dialog is valid: */
436 if (pCloseDlg->isValid())
437 {
438 /* We are going to show close-dialog: */
439 bool fShowCloseDialog = true;
440 /* Check if VM is paused or stuck: */
441 const bool fWasPaused = uimachine()->isPaused();
442 const bool fIsStuck = uimachine()->isStuck();
443 /* If VM is NOT paused and NOT stuck: */
444 if (!fWasPaused && !fIsStuck)
445 {
446 /* We should pause it first: */
447 const bool fIsPaused = uimachine()->pause();
448 /* If we were unable to pause VM: */
449 if (!fIsPaused)
450 {
451 /* If that is NOT the separate VM process UI: */
452 if (!uiCommon().isSeparateProcess())
453 {
454 /* We are not going to show close-dialog: */
455 fShowCloseDialog = false;
456 }
457 /* If that is the separate VM process UI: */
458 else
459 {
460 // WORKAROUND:
461 // We are going to show close-dialog only
462 // if headless frontend stopped/killed already:
463 KMachineState enmActualState = KMachineState_Null;
464 uimachine()->acquireLiveMachineState(enmActualState);
465 fShowCloseDialog = enmActualState == KMachineState_Null;
466 }
467 }
468 }
469 /* If we are going to show close-dialog: */
470 if (fShowCloseDialog)
471 {
472 /* Show close-dialog to let the user make the choice: */
473 windowManager().registerNewParent(pCloseDlg, pParentDlg);
474 closeAction = static_cast<MachineCloseAction>(pCloseDlg->exec());
475
476 /* Make sure the dialog still valid: */
477 if (!pCloseDlg)
478 return;
479
480 /* If VM was not paused before but paused now,
481 * we should resume it if user canceled dialog or chosen shutdown: */
482 if (!fWasPaused && uimachine()->isPaused() &&
483 (closeAction == MachineCloseAction_Invalid ||
484 closeAction == MachineCloseAction_Detach ||
485 closeAction == MachineCloseAction_Shutdown))
486 {
487 /* If we unable to resume VM, cancel closing: */
488 if (!uimachine()->unpause())
489 closeAction = MachineCloseAction_Invalid;
490 }
491 }
492 }
493 else
494 {
495 /* Else user misconfigured .vbox file, we will reject closing UI: */
496 closeAction = MachineCloseAction_Invalid;
497 }
498
499 /* Cleanup close-dialog: */
500 delete pCloseDlg;
501 }
502
503 /* Depending on chosen result: */
504 switch (closeAction)
505 {
506 case MachineCloseAction_Detach:
507 {
508 /* Detach GUI: */
509 LogRel(("GUI: Request for close-action to detach GUI.\n"));
510 uimachine()->detachUi();
511 break;
512 }
513 case MachineCloseAction_SaveState:
514 {
515 /* Save VM state: */
516 LogRel(("GUI: Request for close-action to save VM state.\n"));
517 uimachine()->saveState();
518 break;
519 }
520 case MachineCloseAction_Shutdown:
521 {
522 /* Shutdown VM: */
523 LogRel(("GUI: Request for close-action to shutdown VM.\n"));
524 uimachine()->shutdown();
525 break;
526 }
527 case MachineCloseAction_PowerOff:
528 case MachineCloseAction_PowerOff_RestoringSnapshot:
529 {
530 /* Power VM off: */
531 LogRel(("GUI: Request for close-action to power VM off.\n"));
532 ulong uSnapshotCount = 0;
533 uimachine()->acquireSnapshotCount(uSnapshotCount);
534 const bool fDiscardStateOnPowerOff = gEDataManager->discardStateOnPowerOff(uiCommon().managedVMUuid())
535 || closeAction == MachineCloseAction_PowerOff_RestoringSnapshot;
536 uimachine()->powerOff(uSnapshotCount > 0 && fDiscardStateOnPowerOff);
537 break;
538 }
539 default:
540 break;
541 }
542}
543
544void UIMachineWindow::prepareSelf()
545{
546#ifndef VBOX_WS_MAC
547 /* Set machine-window icon if any: */
548 // On macOS window icon is referenced in info.plist.
549 if (uimachine()->machineWindowIcon())
550 setWindowIcon(*uimachine()->machineWindowIcon());
551#endif /* !VBOX_WS_MAC */
552}
553
554void UIMachineWindow::prepareSessionConnections()
555{
556 /* We should watch for console events: */
557 connect(uimachine(), &UIMachine::sigMachineStateChange, this, &UIMachineWindow::sltMachineStateChanged);
558}
559
560void UIMachineWindow::prepareMainLayout()
561{
562 /* Create central-widget: */
563 setCentralWidget(new QWidget);
564
565 /* Create main-layout: */
566 m_pMainLayout = new QGridLayout(centralWidget());
567 m_pMainLayout->setContentsMargins(0, 0, 0, 0);
568 m_pMainLayout->setSpacing(0);
569
570 /* Create shifting-spacers: */
571 m_pTopSpacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
572 m_pBottomSpacer = new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding);
573 m_pLeftSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
574 m_pRightSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed);
575
576 /* Add shifting-spacers into main-layout: */
577 m_pMainLayout->addItem(m_pTopSpacer, 0, 1);
578 m_pMainLayout->addItem(m_pBottomSpacer, 2, 1);
579 m_pMainLayout->addItem(m_pLeftSpacer, 1, 0);
580 m_pMainLayout->addItem(m_pRightSpacer, 1, 2);
581}
582
583void UIMachineWindow::prepareMachineView()
584{
585 /* Get visual-state type: */
586 UIVisualStateType visualStateType = machineLogic()->visualStateType();
587
588 /* Create machine-view: */
589 m_pMachineView = UIMachineView::create(this, m_uScreenId, visualStateType);
590
591 /* Add machine-view into main-layout: */
592 m_pMainLayout->addWidget(m_pMachineView, 1, 1, viewAlignment(visualStateType));
593
594 /* Install focus-proxy: */
595 setFocusProxy(m_pMachineView);
596}
597
598void UIMachineWindow::prepareNotificationCenter()
599{
600 // for now it will be added from within particular visual mode windows ..
601}
602
603void UIMachineWindow::prepareHandlers()
604{
605 /* Register keyboard-handler: */
606 machineLogic()->keyboardHandler()->prepareListener(m_uScreenId, this);
607
608 /* Register mouse-handler: */
609 machineLogic()->mouseHandler()->prepareListener(m_uScreenId, this);
610}
611
612void UIMachineWindow::cleanupHandlers()
613{
614 /* Unregister mouse-handler: */
615 machineLogic()->mouseHandler()->cleanupListener(m_uScreenId);
616
617 /* Unregister keyboard-handler: */
618 machineLogic()->keyboardHandler()->cleanupListener(m_uScreenId);
619}
620
621void UIMachineWindow::cleanupNotificationCenter()
622{
623 // for now it will be removed from within particular visual mode windows ..
624}
625
626void UIMachineWindow::cleanupMachineView()
627{
628 /* Destroy machine-view: */
629 UIMachineView::destroy(m_pMachineView);
630 m_pMachineView = 0;
631}
632
633void UIMachineWindow::cleanupSessionConnections()
634{
635 /* We should stop watching for console events: */
636 disconnect(uimachine(), &UIMachine::sigMachineStateChange, this, &UIMachineWindow::sltMachineStateChanged);
637}
638
639#ifdef VBOX_WITH_DEBUGGER_GUI
640void UIMachineWindow::updateDbgWindows()
641{
642 /* The debugger windows are bind to the main VM window. */
643 if (m_uScreenId == 0)
644 uimachine()->dbgAdjustRelativePos();
645}
646#endif /* VBOX_WITH_DEBUGGER_GUI */
647
648/* static */
649Qt::Alignment UIMachineWindow::viewAlignment(UIVisualStateType visualStateType)
650{
651 switch (visualStateType)
652 {
653 case UIVisualStateType_Normal: return Qt::Alignment();
654 case UIVisualStateType_Fullscreen: return Qt::AlignVCenter | Qt::AlignHCenter;
655 case UIVisualStateType_Seamless: return Qt::Alignment();
656 case UIVisualStateType_Scale: return Qt::Alignment();
657 case UIVisualStateType_Invalid: case UIVisualStateType_All: break; /* Shut up, MSC! */
658 }
659 AssertMsgFailed(("Incorrect visual state!"));
660 return Qt::Alignment();
661}
662
663#ifdef VBOX_WS_MAC
664void UIMachineWindow::handleStandardWindowButtonCallback(StandardWindowButtonType enmButtonType, bool fWithOptionKey)
665{
666 switch (enmButtonType)
667 {
668 case StandardWindowButtonType_Zoom:
669 {
670 /* Handle 'Zoom' button for 'Normal' and 'Scaled' modes: */
671 if ( machineLogic()->visualStateType() == UIVisualStateType_Normal
672 || machineLogic()->visualStateType() == UIVisualStateType_Scale)
673 {
674 if (fWithOptionKey)
675 {
676 /* Toggle window zoom: */
677 darwinToggleWindowZoom(this);
678 }
679 else
680 {
681 /* Enter 'full-screen' mode: */
682 uimachine()->setRequestedVisualState(UIVisualStateType_Invalid);
683 uimachine()->asyncChangeVisualState(UIVisualStateType_Fullscreen);
684 }
685 }
686 break;
687 }
688 default:
689 break;
690 }
691}
692
693/* static */
694void UIMachineWindow::handleNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget)
695{
696 /* Handle arrived notification: */
697 LogRel(("GUI: UIMachineWindow::handleNativeNotification: Notification '%s' received\n",
698 strNativeNotificationName.toLatin1().constData()));
699 AssertPtrReturnVoid(pWidget);
700 if (UIMachineWindow *pMachineWindow = qobject_cast<UIMachineWindow*>(pWidget))
701 {
702 /* Redirect arrived notification: */
703 LogRel2(("UIMachineWindow::handleNativeNotification: Redirecting '%s' notification to corresponding machine-window...\n",
704 strNativeNotificationName.toLatin1().constData()));
705 pMachineWindow->handleNativeNotification(strNativeNotificationName);
706 }
707}
708
709/* static */
710void UIMachineWindow::handleStandardWindowButtonCallback(StandardWindowButtonType enmButtonType, bool fWithOptionKey, QWidget *pWidget)
711{
712 /* Handle arrived callback: */
713 LogRel(("GUI: UIMachineWindow::handleStandardWindowButtonCallback: Callback for standard window button '%d' with option key '%d' received\n",
714 (int)enmButtonType, (int)fWithOptionKey));
715 AssertPtrReturnVoid(pWidget);
716 if (UIMachineWindow *pMachineWindow = qobject_cast<UIMachineWindow*>(pWidget))
717 {
718 /* Redirect arrived callback: */
719 LogRel2(("UIMachineWindow::handleStandardWindowButtonCallback: Redirecting callback for standard window button '%d' with option key '%d' to corresponding machine-window...\n",
720 (int)enmButtonType, (int)fWithOptionKey));
721 pMachineWindow->handleStandardWindowButtonCallback(enmButtonType, fWithOptionKey);
722 }
723}
724#endif /* VBOX_WS_MAC */
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