VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp@ 98487

Last change on this file since 98487 was 98487, checked in by vboxsync, 2 years ago

FE/Qt: bugref:10322: Runtime UI: Reworking UIIndicatorsPool network indicator to move COM related logic to UISession.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.8 KB
Line 
1/* $Id: UISession.cpp 98487 2023-02-07 11:15:01Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UISession class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2023 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 <QApplication>
30#include <QWidget>
31#ifdef VBOX_WS_WIN
32# include <iprt/win/windows.h> /* Workaround for compile errors if included directly by QtWin. */
33# include <QtWin>
34#endif
35
36/* GUI includes: */
37#include "UIActionPoolRuntime.h"
38#include "UICommon.h"
39#include "UIConsoleEventHandler.h"
40#include "UIDetailsGenerator.h"
41#include "UIExtraDataManager.h"
42#include "UIFrameBuffer.h"
43#include "UIMachine.h"
44#include "UIMachineLogic.h"
45#include "UIMachineView.h"
46#include "UIMachineWindow.h"
47#include "UIMedium.h"
48#include "UIMessageCenter.h"
49#include "UIMousePointerShapeData.h"
50#include "UINotificationCenter.h"
51#include "UISession.h"
52#include "UISettingsDialogSpecific.h"
53#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
54# include "UIKeyboardHandler.h"
55# include <signal.h>
56#endif
57
58/* COM includes: */
59#include "CGraphicsAdapter.h"
60#include "CHostNetworkInterface.h"
61#include "CHostUSBDevice.h"
62#include "CMedium.h"
63#include "CMediumAttachment.h"
64#include "CSnapshot.h"
65#include "CStorageController.h"
66#include "CSystemProperties.h"
67#include "CUSBController.h"
68#include "CUSBDeviceFilter.h"
69#include "CUSBDeviceFilters.h"
70#ifdef VBOX_WITH_NETFLT
71# include "CNetworkAdapter.h"
72#endif
73
74/* External includes: */
75#ifdef VBOX_WS_X11
76# include <X11/Xlib.h>
77# include <X11/Xutil.h>
78#endif
79
80
81#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
82static void signalHandlerSIGUSR1(int sig, siginfo_t *, void *);
83#endif
84
85/* static */
86bool UISession::create(UISession *&pSession, UIMachine *pMachine)
87{
88 /* Make sure NULL pointer passed: */
89 AssertReturn(!pSession, false);
90
91 /* Create session UI: */
92 pSession = new UISession(pMachine);
93 AssertPtrReturn(pSession, false);
94
95 /* Make sure it's prepared: */
96 if (!pSession->prepare())
97 {
98 /* Destroy session UI otherwise: */
99 destroy(pSession);
100 /* False in that case: */
101 return false;
102 }
103
104 /* True by default: */
105 return true;
106}
107
108/* static */
109void UISession::destroy(UISession *&pSession)
110{
111 /* Make sure valid pointer passed: */
112 AssertPtrReturnVoid(pSession);
113
114 /* Delete session: */
115 delete pSession;
116 pSession = 0;
117}
118
119bool UISession::initialize()
120{
121 /* Preprocess initialization: */
122 if (!preprocessInitialization())
123 return false;
124
125 /* Notify user about mouse&keyboard auto-capturing: */
126 if (gEDataManager->autoCaptureEnabled())
127 UINotificationMessage::remindAboutAutoCapture();
128
129 m_enmMachineState = machine().GetState();
130
131 /* Apply debug settings from the command line. */
132 if (!debugger().isNull() && debugger().isOk())
133 {
134 if (uiCommon().areWeToExecuteAllInIem())
135 debugger().SetExecuteAllInIEM(true);
136 if (!uiCommon().isDefaultWarpPct())
137 debugger().SetVirtualTimeRate(uiCommon().getWarpPct());
138 }
139
140 /* Apply ad-hoc reconfigurations from the command line: */
141 if (uiCommon().hasFloppyImageToMount())
142 mountAdHocImage(KDeviceType_Floppy, UIMediumDeviceType_Floppy, uiCommon().getFloppyImage().toString());
143 if (uiCommon().hasDvdImageToMount())
144 mountAdHocImage(KDeviceType_DVD, UIMediumDeviceType_DVD, uiCommon().getDvdImage().toString());
145
146 /* Power UP if this is NOT separate process: */
147 if (!uiCommon().isSeparateProcess())
148 if (!powerUp())
149 return false;
150
151 /* Make sure all the pending Console events converted to signals
152 * during the powerUp() progress above reached their destinations.
153 * That is necessary to make sure all the pending machine state change events processed.
154 * We can't just use the machine state directly acquired from IMachine because there
155 * will be few places which are using stale machine state, not just this one. */
156 QApplication::sendPostedEvents(0, QEvent::MetaCall);
157
158 /* Check if we missed a really quick termination after successful startup: */
159 if (isTurnedOff())
160 {
161 LogRel(("GUI: Aborting startup due to invalid machine state detected: %d\n", machineState()));
162 return false;
163 }
164
165 /* Fetch corresponding states: */
166 if (uiCommon().isSeparateProcess())
167 {
168 sltAdditionsChange();
169 }
170 machineLogic()->initializePostPowerUp();
171
172#ifdef VBOX_GUI_WITH_PIDFILE
173 uiCommon().createPidfile();
174#endif /* VBOX_GUI_WITH_PIDFILE */
175
176 /* True by default: */
177 return true;
178}
179
180bool UISession::powerUp()
181{
182 /* Power UP machine: */
183 CProgress comProgress = uiCommon().shouldStartPaused() ? console().PowerUpPaused() : console().PowerUp();
184
185 /* Check for immediate failure: */
186 if (!console().isOk() || comProgress.isNull())
187 {
188 if (uiCommon().showStartVMErrors())
189 msgCenter().cannotStartMachine(console(), machineName());
190 LogRel(("GUI: Aborting startup due to power up issue detected...\n"));
191 return false;
192 }
193
194 /* Some logging right after we powered up: */
195 LogRel(("GUI: Qt version: %s\n", UICommon::qtRTVersionString().toUtf8().constData()));
196#ifdef VBOX_WS_X11
197 LogRel(("GUI: X11 Window Manager code: %d\n", (int)uiCommon().typeOfWindowManager()));
198#endif
199#if defined(VBOX_WS_MAC) || defined(VBOX_WS_WIN)
200 LogRel(("GUI: HID LEDs sync is %s\n", uimachine()->isHidLedsSyncEnabled() ? "enabled" : "disabled"));
201#else
202 LogRel(("GUI: HID LEDs sync is not supported on this platform\n"));
203#endif
204
205 /* Enable 'manual-override',
206 * preventing automatic Runtime UI closing
207 * and visual representation mode changes: */
208 uimachine()->setManualOverrideMode(true);
209
210 /* Show "Starting/Restoring" progress dialog: */
211 if (isSaved())
212 {
213 msgCenter().showModalProgressDialog(comProgress, machineName(), ":/progress_state_restore_90px.png", 0, 0);
214 /* After restoring from 'saved' state, machine-window(s) geometry should be adjusted: */
215 machineLogic()->adjustMachineWindowsGeometry();
216 }
217 else
218 {
219#ifdef VBOX_IS_QT6_OR_LATER /** @todo why is this any problem on qt6? */
220 msgCenter().showModalProgressDialog(comProgress, machineName(), ":/progress_start_90px.png", 0, 0);
221#else
222 msgCenter().showModalProgressDialog(comProgress, machineName(), ":/progress_start_90px.png");
223#endif
224 /* After VM start, machine-window(s) size-hint(s) should be sent: */
225 machineLogic()->sendMachineWindowsSizeHints();
226 }
227
228 /* Check for progress failure: */
229 if (!comProgress.isOk() || comProgress.GetResultCode() != 0)
230 {
231 if (uiCommon().showStartVMErrors())
232 msgCenter().cannotStartMachine(comProgress, machineName());
233 LogRel(("GUI: Aborting startup due to power up progress issue detected...\n"));
234 return false;
235 }
236
237 /* Disable 'manual-override' finally: */
238 uimachine()->setManualOverrideMode(false);
239
240 /* True by default: */
241 return true;
242}
243
244WId UISession::mainMachineWindowId() const
245{
246 return mainMachineWindow() ? mainMachineWindow()->winId() : 0;
247}
248
249bool UISession::setPause(bool fPause)
250{
251 if (fPause)
252 console().Pause();
253 else
254 console().Resume();
255
256 const bool fOk = console().isOk();
257 if (!fOk)
258 {
259 if (fPause)
260 UINotificationMessage::cannotPauseMachine(console());
261 else
262 UINotificationMessage::cannotResumeMachine(console());
263 }
264
265 return fOk;
266}
267
268bool UISession::guestAdditionsUpgradable()
269{
270 if (!machine().isOk())
271 return false;
272
273 /* Auto GA update is currently for Windows and Linux guests only */
274 const CGuestOSType osType = uiCommon().vmGuestOSType(machine().GetOSTypeId());
275 if (!osType.isOk())
276 return false;
277
278 const QString strGuestFamily = osType.GetFamilyId();
279 bool fIsWindowOrLinux = strGuestFamily.contains("windows", Qt::CaseInsensitive) || strGuestFamily.contains("linux", Qt::CaseInsensitive);
280
281 if (!fIsWindowOrLinux)
282 return false;
283
284 /* Also check whether we have something to update automatically: */
285 if (m_ulGuestAdditionsRunLevel < (ULONG)KAdditionsRunLevelType_Userland)
286 return false;
287
288 return true;
289}
290
291UIFrameBuffer *UISession::frameBuffer(ulong uScreenId) const
292{
293 Assert(uScreenId < (ulong)m_frameBufferVector.size());
294 return m_frameBufferVector.value((int)uScreenId, 0);
295}
296
297void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer *pFrameBuffer)
298{
299 Assert(uScreenId < (ulong)m_frameBufferVector.size());
300 if (uScreenId < (ulong)m_frameBufferVector.size())
301 m_frameBufferVector[(int)uScreenId] = pFrameBuffer;
302}
303
304QSize UISession::frameBufferSize(ulong uScreenId) const
305{
306 UIFrameBuffer *pFramebuffer = frameBuffer(uScreenId);
307 return pFramebuffer ? QSize(pFramebuffer->width(), pFramebuffer->height()) : QSize();
308}
309
310void UISession::acquireDeviceActivity(const QVector<KDeviceType> &deviceTypes, QVector<KDeviceActivity> &states)
311{
312 CConsole comConsole = console();
313 states = comConsole.GetDeviceActivity(deviceTypes);
314 if (!comConsole.isOk())
315 UINotificationMessage::cannotAcquireConsoleParameter(comConsole);
316}
317
318void UISession::acquireHardDiskStatusInfo(QString &strInfo, bool &fAttachmentsPresent)
319{
320 CMachine comMachine = machine();
321 UIDetailsGenerator::acquireHardDiskStatusInfo(comMachine, strInfo, fAttachmentsPresent);
322}
323
324void UISession::acquireOpticalDiskStatusInfo(QString &strInfo, bool &fAttachmentsPresent, bool &fAttachmentsMounted)
325{
326 CMachine comMachine = machine();
327 UIDetailsGenerator::acquireOpticalDiskStatusInfo(comMachine, strInfo, fAttachmentsPresent, fAttachmentsMounted);
328}
329
330void UISession::acquireFloppyDiskStatusInfo(QString &strInfo, bool &fAttachmentsPresent, bool &fAttachmentsMounted)
331{
332 CMachine comMachine = machine();
333 UIDetailsGenerator::acquireFloppyDiskStatusInfo(comMachine, strInfo, fAttachmentsPresent, fAttachmentsMounted);
334}
335
336void UISession::acquireAudioStatusInfo(QString &strInfo, bool &fAudioEnabled, bool &fEnabledOutput, bool &fEnabledInput)
337{
338 CMachine comMachine = machine();
339 UIDetailsGenerator::acquireAudioStatusInfo(comMachine, strInfo, fAudioEnabled, fEnabledOutput, fEnabledInput);
340}
341
342void UISession::acquireNetworkStatusInfo(QString &strInfo, bool &fAdaptersPresent, bool &fCablesDisconnected)
343{
344 CMachine comMachine = machine();
345 UIDetailsGenerator::acquireNetworkStatusInfo(comMachine, strInfo, fAdaptersPresent, fCablesDisconnected);
346}
347
348void UISession::acquireDisplayStatusInfo(QString &strInfo, bool &fAcceleration3D)
349{
350 CMachine comMachine = machine();
351 UIDetailsGenerator::acquireDisplayStatusInfo(comMachine, strInfo, fAcceleration3D);
352}
353
354bool UISession::prepareToBeSaved()
355{
356 return isPaused()
357 || (isRunning() && pause());
358}
359
360bool UISession::prepareToBeShutdowned()
361{
362 const bool fValidMode = console().GetGuestEnteredACPIMode();
363 if (!fValidMode)
364 UINotificationMessage::cannotSendACPIToMachine();
365 return fValidMode;
366}
367
368void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
369{
370 if (!guestAdditionsUpgradable())
371 return sltMountDVDAdHoc(strSource);
372
373 /* Update guest additions automatically: */
374 UINotificationProgressGuestAdditionsInstall *pNotification =
375 new UINotificationProgressGuestAdditionsInstall(guest(), strSource);
376 connect(pNotification, &UINotificationProgressGuestAdditionsInstall::sigGuestAdditionsInstallationFailed,
377 this, &UISession::sltMountDVDAdHoc);
378 gpNotificationCenter->append(pNotification);
379}
380
381void UISession::sltMountDVDAdHoc(const QString &strSource)
382{
383 mountAdHocImage(KDeviceType_DVD, UIMediumDeviceType_DVD, strSource);
384}
385
386void UISession::sltDetachCOM()
387{
388 /* Cleanup everything COM related: */
389 cleanupFramebuffers();
390 cleanupConsoleEventHandlers();
391 cleanupNotificationCenter();
392 cleanupSession();
393}
394
395void UISession::sltStateChange(KMachineState enmState)
396{
397 /* Check if something had changed: */
398 if (m_enmMachineState != enmState)
399 {
400 /* Store new data: */
401 m_enmMachineStatePrevious = m_enmMachineState;
402 m_enmMachineState = enmState;
403
404 /* Notify listeners about machine state changed: */
405 emit sigMachineStateChange();
406 }
407}
408
409void UISession::sltAdditionsChange()
410{
411 /* Acquire actual states: */
412 const ULONG ulGuestAdditionsRunLevel = guest().GetAdditionsRunLevel();
413 LONG64 lLastUpdatedIgnored;
414 const bool fIsGuestSupportsGraphics = guest().GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored)
415 == KAdditionsFacilityStatus_Active;
416 const bool fIsGuestSupportsSeamless = guest().GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored)
417 == KAdditionsFacilityStatus_Active;
418
419 /* Check if something had changed: */
420 if ( m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel
421 || m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics
422 || m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
423 {
424 /* Store new data: */
425 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
426 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
427 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
428
429 /* Notify listeners about GA state really changed: */
430 LogRel(("GUI: UISession::sltAdditionsChange: GA state really changed, notifying listeners.\n"));
431 emit sigAdditionsStateActualChange();
432 }
433 else
434 LogRel(("GUI: UISession::sltAdditionsChange: GA state doesn't really changed, still notifying listeners.\n"));
435
436 /* Notify listeners about GA state change event came: */
437 emit sigAdditionsStateChange();
438}
439
440UISession::UISession(UIMachine *pMachine)
441 : QObject(pMachine)
442 /* Base variables: */
443 , m_pMachine(pMachine)
444 , m_pConsoleEventhandler(0)
445 /* Common variables: */
446 , m_enmMachineStatePrevious(KMachineState_Null)
447 , m_enmMachineState(KMachineState_Null)
448 /* Guest additions flags: */
449 , m_ulGuestAdditionsRunLevel(0)
450 , m_fIsGuestSupportsGraphics(false)
451 , m_fIsGuestSupportsSeamless(false)
452{
453}
454
455UISession::~UISession()
456{
457}
458
459bool UISession::prepare()
460{
461 /* Prepare COM stuff: */
462 if (!prepareSession())
463 return false;
464
465 /* Cache media early if requested: */
466 if (uiCommon().agressiveCaching())
467 recacheMachineMedia();
468
469 /* Prepare GUI stuff: */
470 prepareNotificationCenter();
471 prepareConsoleEventHandlers();
472 prepareFramebuffers();
473 prepareConnections();
474 prepareSignalHandling();
475
476 /* True by default: */
477 return true;
478}
479
480bool UISession::prepareSession()
481{
482 /* Open session: */
483 m_comSession = uiCommon().openSession(uiCommon().managedVMUuid(),
484 uiCommon().isSeparateProcess()
485 ? KLockType_Shared
486 : KLockType_VM);
487 if (m_comSession.isNull())
488 return false;
489
490 /* Get machine: */
491 m_comMachine = m_comSession.GetMachine();
492 if (m_comMachine.isNull())
493 return false;
494
495 /* Get console: */
496 m_comConsole = m_comSession.GetConsole();
497 if (m_comConsole.isNull())
498 return false;
499
500 /* Get display: */
501 m_comDisplay = m_comConsole.GetDisplay();
502 if (m_comDisplay.isNull())
503 return false;
504
505 /* Get guest: */
506 m_comGuest = m_comConsole.GetGuest();
507 if (m_comGuest.isNull())
508 return false;
509
510 /* Get mouse: */
511 m_comMouse = m_comConsole.GetMouse();
512 if (m_comMouse.isNull())
513 return false;
514
515 /* Get keyboard: */
516 m_comKeyboard = m_comConsole.GetKeyboard();
517 if (m_comKeyboard.isNull())
518 return false;
519
520 /* Get debugger: */
521 m_comDebugger = m_comConsole.GetDebugger();
522 if (m_comDebugger.isNull())
523 return false;
524
525 /* Update machine-name: */
526 m_strMachineName = machine().GetName();
527
528 /* Update machine-state: */
529 m_enmMachineState = machine().GetState();
530
531 /* True by default: */
532 return true;
533}
534
535void UISession::prepareNotificationCenter()
536{
537 UINotificationCenter::create();
538}
539
540void UISession::prepareConsoleEventHandlers()
541{
542 /* Create console event-handler: */
543 m_pConsoleEventhandler = new UIConsoleEventHandler(this);
544
545 /* Console event connections: */
546 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigAdditionsChange,
547 this, &UISession::sltAdditionsChange);
548 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigAudioAdapterChange,
549 this, &UISession::sigAudioAdapterChange);
550 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigClipboardModeChange,
551 this, &UISession::sigClipboardModeChange);
552 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigCPUExecutionCapChange,
553 this, &UISession::sigCPUExecutionCapChange);
554 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigDnDModeChange,
555 this, &UISession::sigDnDModeChange);
556 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigGuestMonitorChange,
557 this, &UISession::sigGuestMonitorChange);
558 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigMediumChange,
559 this, &UISession::sigMediumChange);
560 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigNetworkAdapterChange,
561 this, &UISession::sigNetworkAdapterChange);
562 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigRecordingChange,
563 this, &UISession::sigRecordingChange);
564 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigSharedFolderChange,
565 this, &UISession::sigSharedFolderChange);
566 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigStateChange,
567 this, &UISession::sltStateChange);
568 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigStorageDeviceChange,
569 this, &UISession::sigStorageDeviceChange);
570 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigUSBControllerChange,
571 this, &UISession::sigUSBControllerChange);
572 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigUSBDeviceStateChange,
573 this, &UISession::sigUSBDeviceStateChange);
574 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigVRDEChange,
575 this, &UISession::sigVRDEChange);
576 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigRuntimeError,
577 this, &UISession::sigRuntimeError);
578
579#ifdef VBOX_WS_MAC
580 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigShowWindow,
581 this, &UISession::sigShowWindows, Qt::QueuedConnection);
582#endif
583
584 /* Console keyboard connections: */
585 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigKeyboardLedsChange,
586 this, &UISession::sigKeyboardLedsChange);
587
588 /* Console mouse connections: */
589 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigMousePointerShapeChange,
590 this, &UISession::sigMousePointerShapeChange);
591 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigMouseCapabilityChange,
592 this, &UISession::sigMouseCapabilityChange);
593 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigCursorPositionChange,
594 this, &UISession::sigCursorPositionChange);
595}
596
597void UISession::prepareFramebuffers()
598{
599 /* Each framebuffer will be really prepared on first UIMachineView creation: */
600 m_frameBufferVector.resize(machine().GetGraphicsAdapter().GetMonitorCount());
601}
602
603void UISession::prepareConnections()
604{
605 /* UICommon connections: */
606 connect(&uiCommon(), &UICommon::sigAskToDetachCOM, this, &UISession::sltDetachCOM);
607}
608
609void UISession::prepareSignalHandling()
610{
611#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
612 struct sigaction sa;
613 sa.sa_sigaction = &signalHandlerSIGUSR1;
614 sigemptyset(&sa.sa_mask);
615 sa.sa_flags = SA_RESTART | SA_SIGINFO;
616 sigaction(SIGUSR1, &sa, NULL);
617#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
618}
619
620void UISession::cleanupFramebuffers()
621{
622 /* Cleanup framebuffers finally: */
623 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i)
624 {
625 UIFrameBuffer *pFrameBuffer = m_frameBufferVector[i];
626 if (pFrameBuffer)
627 {
628 /* Mark framebuffer as unused: */
629 pFrameBuffer->setMarkAsUnused(true);
630 /* Detach framebuffer from Display: */
631 pFrameBuffer->detach();
632 /* Delete framebuffer reference: */
633 delete pFrameBuffer;
634 }
635 }
636 m_frameBufferVector.clear();
637}
638
639void UISession::cleanupConsoleEventHandlers()
640{
641 /* Destroy console event-handler: */
642 delete m_pConsoleEventhandler;
643 m_pConsoleEventhandler = 0;
644}
645
646void UISession::cleanupNotificationCenter()
647{
648 UINotificationCenter::destroy();
649}
650
651void UISession::cleanupSession()
652{
653 /* Detach debugger: */
654 if (!m_comDebugger.isNull())
655 m_comDebugger.detach();
656
657 /* Detach keyboard: */
658 if (!m_comKeyboard.isNull())
659 m_comKeyboard.detach();
660
661 /* Detach mouse: */
662 if (!m_comMouse.isNull())
663 m_comMouse.detach();
664
665 /* Detach guest: */
666 if (!m_comGuest.isNull())
667 m_comGuest.detach();
668
669 /* Detach display: */
670 if (!m_comDisplay.isNull())
671 m_comDisplay.detach();
672
673 /* Detach console: */
674 if (!m_comConsole.isNull())
675 m_comConsole.detach();
676
677 /* Detach machine: */
678 if (!m_comMachine.isNull())
679 m_comMachine.detach();
680
681 /* Close session: */
682 if (!m_comSession.isNull() && uiCommon().isVBoxSVCAvailable())
683 {
684 m_comSession.UnlockMachine();
685 m_comSession.detach();
686 }
687}
688
689UIMachineLogic *UISession::machineLogic() const
690{
691 return uimachine() ? uimachine()->machineLogic() : 0;
692}
693
694UIMachineWindow *UISession::activeMachineWindow() const
695{
696 return machineLogic() ? machineLogic()->activeMachineWindow() : 0;
697}
698
699QWidget *UISession::mainMachineWindow() const
700{
701 return machineLogic() ? machineLogic()->mainMachineWindow() : 0;
702}
703
704bool UISession::preprocessInitialization()
705{
706#ifdef VBOX_WITH_NETFLT
707 /* Skip network interface name checks if VM in saved state: */
708 if (!isSaved())
709 {
710 /* Make sure all the attached and enabled network
711 * adapters are present on the host. This check makes sense
712 * in two cases only - when attachement type is Bridged Network
713 * or Host-only Interface. NOTE: Only currently enabled
714 * attachement type is checked (incorrect parameters check for
715 * currently disabled attachement types is skipped). */
716 QStringList failedInterfaceNames;
717 QStringList availableInterfaceNames;
718
719 /* Create host network interface names list: */
720 foreach (const CHostNetworkInterface &comNetIface, uiCommon().host().GetNetworkInterfaces())
721 {
722 availableInterfaceNames << comNetIface.GetName();
723 availableInterfaceNames << comNetIface.GetShortName();
724 }
725
726 /* Enumerate all the virtual network adapters: */
727 const ulong cCount = uiCommon().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine().GetChipsetType());
728 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex)
729 {
730 CNetworkAdapter comNetworkAdapter = machine().GetNetworkAdapter(uAdapterIndex);
731 if (comNetworkAdapter.GetEnabled())
732 {
733 /* Get physical network interface name for
734 * currently enabled network attachement type: */
735 QString strInterfaceName;
736 switch (comNetworkAdapter.GetAttachmentType())
737 {
738 case KNetworkAttachmentType_Bridged:
739 strInterfaceName = comNetworkAdapter.GetBridgedInterface();
740 break;
741#ifndef VBOX_WITH_VMNET
742 case KNetworkAttachmentType_HostOnly:
743 strInterfaceName = comNetworkAdapter.GetHostOnlyInterface();
744 break;
745#endif /* !VBOX_WITH_VMNET */
746 default:
747 break;
748 }
749
750 if ( !strInterfaceName.isEmpty()
751 && !availableInterfaceNames.contains(strInterfaceName))
752 {
753 LogRel(("GUI: Invalid network interface found: %s\n", strInterfaceName.toUtf8().constData()));
754 failedInterfaceNames << QString("%1 (adapter %2)").arg(strInterfaceName).arg(uAdapterIndex + 1);
755 }
756 }
757 }
758
759 /* Check if non-existent interfaces found: */
760 if (!failedInterfaceNames.isEmpty())
761 {
762 if (msgCenter().warnAboutNetworkInterfaceNotFound(machineName(), failedInterfaceNames.join(", ")))
763 machineLogic()->openNetworkSettingsDialog();
764 else
765 {
766 LogRel(("GUI: Aborting startup due to preprocess initialization issue detected...\n"));
767 return false;
768 }
769 }
770 }
771#endif /* VBOX_WITH_NETFLT */
772
773 /* Check for USB enumeration warning. Don't return false even if we have a warning: */
774 CHost comHost = uiCommon().host();
775 if (comHost.GetUSBDevices().isEmpty() && comHost.isWarning())
776 {
777 /* Do not bitch if USB disabled: */
778 if (!machine().GetUSBControllers().isEmpty())
779 {
780 /* Do not bitch if there are no filters (check if enabled too?): */
781 if (!machine().GetUSBDeviceFilters().GetDeviceFilters().isEmpty())
782 UINotificationMessage::cannotEnumerateHostUSBDevices(comHost);
783 }
784 }
785
786 /* True by default: */
787 return true;
788}
789
790bool UISession::mountAdHocImage(KDeviceType enmDeviceType, UIMediumDeviceType enmMediumType, const QString &strMediumName)
791{
792 /* Get VBox: */
793 CVirtualBox comVBox = uiCommon().virtualBox();
794
795 /* Prepare medium to mount: */
796 UIMedium guiMedium;
797
798 /* The 'none' medium name means ejecting what ever is in the drive,
799 * in that case => leave the guiMedium variable null. */
800 if (strMediumName != "none")
801 {
802 /* Open the medium: */
803 const CMedium comMedium = comVBox.OpenMedium(strMediumName, enmDeviceType, KAccessMode_ReadWrite, false /* fForceNewUuid */);
804 if (!comVBox.isOk() || comMedium.isNull())
805 {
806 UINotificationMessage::cannotOpenMedium(comVBox, strMediumName);
807 return false;
808 }
809
810 /* Make sure medium ID is valid: */
811 const QUuid uMediumId = comMedium.GetId();
812 AssertReturn(!uMediumId.isNull(), false);
813
814 /* Try to find UIMedium among cached: */
815 guiMedium = uiCommon().medium(uMediumId);
816 if (guiMedium.isNull())
817 {
818 /* Cache new one if necessary: */
819 guiMedium = UIMedium(comMedium, enmMediumType, KMediumState_Created);
820 uiCommon().createMedium(guiMedium);
821 }
822 }
823
824 /* Search for a suitable storage slots: */
825 QList<ExactStorageSlot> aFreeStorageSlots;
826 QList<ExactStorageSlot> aBusyStorageSlots;
827 foreach (const CStorageController &comController, machine().GetStorageControllers())
828 {
829 foreach (const CMediumAttachment &comAttachment, machine().GetMediumAttachmentsOfController(comController.GetName()))
830 {
831 /* Look for an optical devices only: */
832 if (comAttachment.GetType() == enmDeviceType)
833 {
834 /* Append storage slot to corresponding list: */
835 if (comAttachment.GetMedium().isNull())
836 aFreeStorageSlots << ExactStorageSlot(comController.GetName(), comController.GetBus(),
837 comAttachment.GetPort(), comAttachment.GetDevice());
838 else
839 aBusyStorageSlots << ExactStorageSlot(comController.GetName(), comController.GetBus(),
840 comAttachment.GetPort(), comAttachment.GetDevice());
841 }
842 }
843 }
844
845 /* Make sure at least one storage slot found: */
846 QList<ExactStorageSlot> sStorageSlots = aFreeStorageSlots + aBusyStorageSlots;
847 if (sStorageSlots.isEmpty())
848 {
849 UINotificationMessage::cannotMountImage(machineName(), strMediumName);
850 return false;
851 }
852
853 /* Try to mount medium into first available storage slot: */
854 while (!sStorageSlots.isEmpty())
855 {
856 const ExactStorageSlot storageSlot = sStorageSlots.takeFirst();
857 machine().MountMedium(storageSlot.controller, storageSlot.port, storageSlot.device, guiMedium.medium(), false /* force */);
858 if (machine().isOk())
859 break;
860 }
861
862 /* Show error message if necessary: */
863 if (!machine().isOk())
864 {
865 msgCenter().cannotRemountMedium(machine(), guiMedium, true /* mount? */, false /* retry? */, activeMachineWindow());
866 return false;
867 }
868
869 /* Save machine settings: */
870 machine().SaveSettings();
871
872 /* Show error message if necessary: */
873 if (!machine().isOk())
874 {
875 UINotificationMessage::cannotSaveMachineSettings(machine());
876 return false;
877 }
878
879 /* True by default: */
880 return true;
881}
882
883void UISession::recacheMachineMedia()
884{
885 /* Compose a list of machine media: */
886 CMediumVector comMedia;
887
888 /* Enumerate all the controllers: */
889 foreach (const CStorageController &comController, machine().GetStorageControllers())
890 {
891 /* Enumerate all the attachments: */
892 foreach (const CMediumAttachment &comAttachment, machine().GetMediumAttachmentsOfController(comController.GetName()))
893 {
894 /* Skip unrelated device types: */
895 const KDeviceType enmDeviceType = comAttachment.GetType();
896 if ( enmDeviceType != KDeviceType_HardDisk
897 && enmDeviceType != KDeviceType_Floppy
898 && enmDeviceType != KDeviceType_DVD)
899 continue;
900 if ( comAttachment.GetIsEjected()
901 || comAttachment.GetMedium().isNull())
902 continue;
903 comMedia.append(comAttachment.GetMedium());
904 }
905 }
906
907 /* Start media enumeration: */
908 uiCommon().enumerateMedia(comMedia);
909}
910
911#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
912/**
913 * Custom signal handler. When switching VTs, we might not get release events
914 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will
915 * be saved with modifier keys stuck. This is annoying enough for introducing
916 * this hack.
917 */
918/* static */
919static void signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */)
920{
921 /* Only SIGUSR1 is interesting: */
922 if (sig == SIGUSR1)
923 if (gpMachine)
924 gpMachine->machineLogic()->keyboardHandler()->releaseAllPressedKeys();
925}
926#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
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