VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.1 KB
Line 
1/* $Id: UIMachineLogicNormal.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMachineLogicNormal 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#ifndef VBOX_WS_MAC
30# include <QTimer>
31#endif /* !VBOX_WS_MAC */
32
33/* GUI includes: */
34#include "UIActionPoolRuntime.h"
35#include "UICommon.h"
36#include "UIDesktopWidgetWatchdog.h"
37#include "UIExtraDataManager.h"
38#include "UIFrameBuffer.h"
39#include "UILoggingDefs.h"
40#include "UIMachine.h"
41#include "UIMachineLogicNormal.h"
42#include "UIMachineWindow.h"
43#include "UIMenuBarEditor.h"
44#include "UIMessageCenter.h"
45#include "UIStatusBarEditor.h"
46#ifndef VBOX_WS_MAC
47# include "QIMenu.h"
48#else
49# include "VBoxUtils.h"
50#endif
51
52/* COM includes: */
53#include "CConsole.h"
54#include "CGraphicsAdapter.h"
55
56
57UIMachineLogicNormal::UIMachineLogicNormal(UIMachine *pMachine)
58 : UIMachineLogic(pMachine)
59#ifndef VBOX_WS_MAC
60 , m_pPopupMenu(0)
61#endif /* !VBOX_WS_MAC */
62{
63}
64
65bool UIMachineLogicNormal::checkAvailability()
66{
67 /* Normal mode is always available: */
68 return true;
69}
70
71void UIMachineLogicNormal::sltCheckForRequestedVisualStateType()
72{
73 LogRel(("GUI: UIMachineLogicNormal::sltCheckForRequestedVisualStateType: Requested-state=%d, Machine-state=%d\n",
74 uimachine()->requestedVisualState(), uimachine()->machineState()));
75
76 /* Do not try to change visual-state type if machine was not started yet: */
77 if (!uimachine()->isRunning() && !uimachine()->isPaused())
78 return;
79
80 /* Do not try to change visual-state type in 'manual override' mode: */
81 if (uimachine()->isManualOverrideMode())
82 return;
83
84 /* Check requested visual-state types: */
85 switch (uimachine()->requestedVisualState())
86 {
87 /* If 'seamless' visual-state type is requested: */
88 case UIVisualStateType_Seamless:
89 {
90 /* And supported: */
91 if (uimachine()->isGuestSupportsSeamless())
92 {
93 LogRel(("GUI: UIMachineLogicNormal::sltCheckForRequestedVisualStateType: "
94 "Going 'seamless' as requested...\n"));
95 uimachine()->setRequestedVisualState(UIVisualStateType_Invalid);
96 uimachine()->asyncChangeVisualState(UIVisualStateType_Seamless);
97 }
98 else
99 LogRel(("GUI: UIMachineLogicNormal::sltCheckForRequestedVisualStateType: "
100 "Rejecting 'seamless' as is it not yet supported...\n"));
101 break;
102 }
103 default:
104 break;
105 }
106}
107
108#ifndef RT_OS_DARWIN
109void UIMachineLogicNormal::sltInvokePopupMenu()
110{
111 /* Popup main-menu if present: */
112 if (m_pPopupMenu && !m_pPopupMenu->isEmpty())
113 {
114 m_pPopupMenu->popup(activeMachineWindow()->geometry().center());
115 QTimer::singleShot(0, m_pPopupMenu, SLOT(sltHighlightFirstAction()));
116 }
117}
118#endif /* RT_OS_DARWIN */
119
120void UIMachineLogicNormal::sltOpenMenuBarSettings()
121{
122 /* Do not process if window(s) missed! */
123 AssertReturnVoid(isMachineWindowsCreated());
124
125#ifndef VBOX_WS_MAC
126 /* Make sure menu-bar is enabled: */
127 const bool fEnabled = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility)->isChecked();
128 AssertReturnVoid(fEnabled);
129#endif /* !VBOX_WS_MAC */
130
131 /* Prevent user from opening another one editor or toggle menu-bar: */
132 actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings)->setEnabled(false);
133#ifndef VBOX_WS_MAC
134 actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility)->setEnabled(false);
135#endif /* !VBOX_WS_MAC */
136 /* Create menu-bar editor: */
137 UIMenuBarEditorWindow *pMenuBarEditor = new UIMenuBarEditorWindow(activeMachineWindow(), actionPool());
138 AssertPtrReturnVoid(pMenuBarEditor);
139 {
140 /* Configure menu-bar editor: */
141 connect(pMenuBarEditor, &UIMenuBarEditorWindow::destroyed,
142 this, &UIMachineLogicNormal::sltMenuBarSettingsClosed);
143 /* Show window: */
144 pMenuBarEditor->show();
145 }
146}
147
148void UIMachineLogicNormal::sltMenuBarSettingsClosed()
149{
150#ifndef VBOX_WS_MAC
151 /* Make sure menu-bar is enabled: */
152 const bool fEnabled = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility)->isChecked();
153 AssertReturnVoid(fEnabled);
154#endif /* !VBOX_WS_MAC */
155
156 /* Allow user to open editor and toggle menu-bar again: */
157 actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings)->setEnabled(true);
158#ifndef VBOX_WS_MAC
159 actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility)->setEnabled(true);
160#endif /* !VBOX_WS_MAC */
161}
162
163#ifndef RT_OS_DARWIN
164void UIMachineLogicNormal::sltToggleMenuBar()
165{
166 /* Do not process if window(s) missed! */
167 AssertReturnVoid(isMachineWindowsCreated());
168
169 /* Invert menu-bar availability option: */
170 const bool fEnabled = gEDataManager->menuBarEnabled(uiCommon().managedVMUuid());
171 gEDataManager->setMenuBarEnabled(!fEnabled, uiCommon().managedVMUuid());
172}
173#endif /* !RT_OS_DARWIN */
174
175void UIMachineLogicNormal::sltOpenStatusBarSettings()
176{
177 /* Do not process if window(s) missed! */
178 AssertReturnVoid(isMachineWindowsCreated());
179
180 /* Make sure status-bar is enabled: */
181 const bool fEnabled = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility)->isChecked();
182 AssertReturnVoid(fEnabled);
183
184 /* Prevent user from opening another one editor or toggle status-bar: */
185 actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings)->setEnabled(false);
186 actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility)->setEnabled(false);
187 /* Create status-bar editor: */
188 UIStatusBarEditorWindow *pStatusBarEditor = new UIStatusBarEditorWindow(activeMachineWindow());
189 AssertPtrReturnVoid(pStatusBarEditor);
190 {
191 /* Configure status-bar editor: */
192 connect(pStatusBarEditor, &UIStatusBarEditorWindow::destroyed,
193 this, &UIMachineLogicNormal::sltStatusBarSettingsClosed);
194 /* Show window: */
195 pStatusBarEditor->show();
196 }
197}
198
199void UIMachineLogicNormal::sltStatusBarSettingsClosed()
200{
201 /* Make sure status-bar is enabled: */
202 const bool fEnabled = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility)->isChecked();
203 AssertReturnVoid(fEnabled);
204
205 /* Allow user to open editor and toggle status-bar again: */
206 actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings)->setEnabled(true);
207 actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility)->setEnabled(true);
208}
209
210void UIMachineLogicNormal::sltToggleStatusBar()
211{
212 /* Do not process if window(s) missed! */
213 AssertReturnVoid(isMachineWindowsCreated());
214
215 /* Invert status-bar availability option: */
216 const bool fEnabled = gEDataManager->statusBarEnabled(uiCommon().managedVMUuid());
217 gEDataManager->setStatusBarEnabled(!fEnabled, uiCommon().managedVMUuid());
218}
219
220void UIMachineLogicNormal::sltHostScreenAvailableAreaChange()
221{
222#if defined(VBOX_WS_NIX) && !defined(VBOX_GUI_WITH_CUSTOMIZATIONS1)
223 /* Prevent handling if fake screen detected: */
224 if (UIDesktopWidgetWatchdog::isFakeScreenDetected())
225 return;
226
227 /* Make sure all machine-window(s) have previous but normalized geometry: */
228 foreach (UIMachineWindow *pMachineWindow, machineWindows())
229 if (!pMachineWindow->isMaximized())
230 pMachineWindow->restoreCachedGeometry();
231#endif /* VBOX_WS_NIX && !VBOX_GUI_WITH_CUSTOMIZATIONS1 */
232
233 /* Call to base-class: */
234 UIMachineLogic::sltHostScreenAvailableAreaChange();
235}
236
237void UIMachineLogicNormal::prepareActionGroups()
238{
239 /* Call to base-class: */
240 UIMachineLogic::prepareActionGroups();
241
242 /* Restrict 'Remap' actions for 'View' menu: */
243 actionPool()->toRuntime()->setRestrictionForMenuView(UIActionRestrictionLevel_Logic,
244 (UIExtraDataMetaDefs::RuntimeMenuViewActionType)
245 (UIExtraDataMetaDefs::RuntimeMenuViewActionType_Remap));
246}
247
248void UIMachineLogicNormal::prepareActionConnections()
249{
250 /* Call to base-class: */
251 UIMachineLogic::prepareActionConnections();
252
253 /* Prepare 'View' actions connections: */
254 connect(actionPool()->action(UIActionIndexRT_M_View_T_Fullscreen), &UIAction::triggered,
255 this, &UIMachineLogicNormal::sltChangeVisualStateToFullscreen);
256 connect(actionPool()->action(UIActionIndexRT_M_View_T_Seamless), &UIAction::triggered,
257 this, &UIMachineLogicNormal::sltChangeVisualStateToSeamless);
258 connect(actionPool()->action(UIActionIndexRT_M_View_T_Scale), &UIAction::triggered,
259 this, &UIMachineLogicNormal::sltChangeVisualStateToScale);
260 connect(actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings), &UIAction::triggered,
261 this, &UIMachineLogicNormal::sltOpenMenuBarSettings);
262#ifndef VBOX_WS_MAC
263 connect(actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility), &UIAction::triggered,
264 this, &UIMachineLogicNormal::sltToggleMenuBar);
265#endif /* !VBOX_WS_MAC */
266 connect(actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings), &UIAction::triggered,
267 this, &UIMachineLogicNormal::sltOpenStatusBarSettings);
268 connect(actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility), &UIAction::triggered,
269 this, &UIMachineLogicNormal::sltToggleStatusBar);
270}
271
272void UIMachineLogicNormal::prepareMachineWindows()
273{
274 /* Do not create machine-window(s) if they created already: */
275 if (isMachineWindowsCreated())
276 return;
277
278#ifdef VBOX_WS_MAC /// @todo Is that really need here?
279 /* We have to make sure that we are getting the front most process.
280 * This is necessary for Qt versions > 4.3.3: */
281 ::darwinSetFrontMostProcess();
282#endif /* VBOX_WS_MAC */
283
284 /* Acquire monitor count: */
285 ulong cMonitorCount = 0;
286 uimachine()->acquireMonitorCount(cMonitorCount);
287
288 /* Create machine window(s): */
289 for (ulong uScreenId = 0; uScreenId < cMonitorCount; ++ uScreenId)
290 addMachineWindow(UIMachineWindow::create(this, uScreenId));
291 /* Order machine window(s): */
292 for (ulong uScreenId = cMonitorCount; uScreenId > 0; -- uScreenId)
293 machineWindows()[uScreenId - 1]->raise();
294
295 /* Mark machine-window(s) created: */
296 setMachineWindowsCreated(true);
297}
298
299#ifndef VBOX_WS_MAC
300void UIMachineLogicNormal::prepareMenu()
301{
302 /* Prepare popup-menu: */
303 m_pPopupMenu = new QIMenu;
304 AssertPtrReturnVoid(m_pPopupMenu);
305 {
306 /* Prepare popup-menu: */
307 foreach (QMenu *pMenu, actionPool()->menus())
308 m_pPopupMenu->addMenu(pMenu);
309 }
310}
311#endif /* !VBOX_WS_MAC */
312
313#ifndef VBOX_WS_MAC
314void UIMachineLogicNormal::cleanupMenu()
315{
316 /* Cleanup popup-menu: */
317 delete m_pPopupMenu;
318 m_pPopupMenu = 0;
319}
320#endif /* !VBOX_WS_MAC */
321
322void UIMachineLogicNormal::cleanupMachineWindows()
323{
324 /* Do not destroy machine-window(s) if they destroyed already: */
325 if (!isMachineWindowsCreated())
326 return;
327
328 /* Mark machine-window(s) destroyed: */
329 setMachineWindowsCreated(false);
330
331 /* Cleanup machine-window(s): */
332 foreach (UIMachineWindow *pMachineWindow, machineWindows())
333 UIMachineWindow::destroy(pMachineWindow);
334}
335
336void UIMachineLogicNormal::cleanupActionConnections()
337{
338 /* "View" actions disconnections: */
339 disconnect(actionPool()->action(UIActionIndexRT_M_View_T_Fullscreen), &UIAction::triggered,
340 this, &UIMachineLogicNormal::sltChangeVisualStateToFullscreen);
341 disconnect(actionPool()->action(UIActionIndexRT_M_View_T_Seamless), &UIAction::triggered,
342 this, &UIMachineLogicNormal::sltChangeVisualStateToSeamless);
343 disconnect(actionPool()->action(UIActionIndexRT_M_View_T_Scale), &UIAction::triggered,
344 this, &UIMachineLogicNormal::sltChangeVisualStateToScale);
345 disconnect(actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings), &UIAction::triggered,
346 this, &UIMachineLogicNormal::sltOpenMenuBarSettings);
347#ifndef VBOX_WS_MAC
348 disconnect(actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility), &UIAction::triggered,
349 this, &UIMachineLogicNormal::sltToggleMenuBar);
350#endif /* !VBOX_WS_MAC */
351 disconnect(actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings), &UIAction::triggered,
352 this, &UIMachineLogicNormal::sltOpenStatusBarSettings);
353 disconnect(actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility), &UIAction::triggered,
354 this, &UIMachineLogicNormal::sltToggleStatusBar);
355
356 /* Call to base-class: */
357 UIMachineLogic::cleanupActionConnections();
358}
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