VirtualBox

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

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

FE/Qt: bugref:10322: Runtime UI: Reworking CConsole wrapper usage step-by-step; VM reset stuff this time.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 56.0 KB
Line 
1/* $Id: UISession.cpp 98653 2023-02-20 13:36:19Z 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 "CEmulatedUSB.h"
60#include "CGraphicsAdapter.h"
61#include "CHostNetworkInterface.h"
62#include "CHostUSBDevice.h"
63#include "CHostVideoInputDevice.h"
64#include "CMedium.h"
65#include "CMediumAttachment.h"
66#include "CSnapshot.h"
67#include "CStorageController.h"
68#include "CSystemProperties.h"
69#include "CUSBController.h"
70#include "CUSBDevice.h"
71#include "CUSBDeviceFilter.h"
72#include "CUSBDeviceFilters.h"
73#ifdef VBOX_WITH_NETFLT
74# include "CNetworkAdapter.h"
75#endif
76
77/* Other VBox includes: */
78#ifdef VBOX_WITH_DEBUGGER_GUI
79# include <VBox/dbggui.h>
80# include <iprt/ldr.h>
81#endif
82
83/* VirtualBox interface declarations: */
84#include <VBox/com/VirtualBox.h>
85
86/* External includes: */
87#ifdef VBOX_WS_X11
88# include <X11/Xlib.h>
89# include <X11/Xutil.h>
90#endif
91
92
93#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
94static void signalHandlerSIGUSR1(int sig, siginfo_t *, void *);
95#endif
96
97/* static */
98bool UISession::create(UISession *&pSession, UIMachine *pMachine)
99{
100 /* Make sure NULL pointer passed: */
101 AssertReturn(!pSession, false);
102
103 /* Create session UI: */
104 pSession = new UISession(pMachine);
105 AssertPtrReturn(pSession, false);
106
107 /* Make sure it's prepared: */
108 if (!pSession->prepare())
109 {
110 /* Destroy session UI otherwise: */
111 destroy(pSession);
112 /* False in that case: */
113 return false;
114 }
115
116 /* True by default: */
117 return true;
118}
119
120/* static */
121void UISession::destroy(UISession *&pSession)
122{
123 /* Make sure valid pointer passed: */
124 AssertPtrReturnVoid(pSession);
125
126 /* Delete session: */
127 delete pSession;
128 pSession = 0;
129}
130
131bool UISession::initialize()
132{
133 /* Preprocess initialization: */
134 if (!preprocessInitialization())
135 return false;
136
137 /* Notify user about mouse&keyboard auto-capturing: */
138 if (gEDataManager->autoCaptureEnabled())
139 UINotificationMessage::remindAboutAutoCapture();
140
141 m_enmMachineState = machine().GetState();
142
143 /* Apply debug settings from the command line. */
144 if (!debugger().isNull() && debugger().isOk())
145 {
146 if (uiCommon().areWeToExecuteAllInIem())
147 debugger().SetExecuteAllInIEM(true);
148 if (!uiCommon().isDefaultWarpPct())
149 debugger().SetVirtualTimeRate(uiCommon().getWarpPct());
150 }
151
152 /* Apply ad-hoc reconfigurations from the command line: */
153 if (uiCommon().hasFloppyImageToMount())
154 mountAdHocImage(KDeviceType_Floppy, UIMediumDeviceType_Floppy, uiCommon().getFloppyImage().toString());
155 if (uiCommon().hasDvdImageToMount())
156 mountAdHocImage(KDeviceType_DVD, UIMediumDeviceType_DVD, uiCommon().getDvdImage().toString());
157
158 /* Power UP if this is NOT separate process: */
159 if (!uiCommon().isSeparateProcess())
160 if (!powerUp())
161 return false;
162
163 /* Make sure all the pending Console events converted to signals
164 * during the powerUp() progress above reached their destinations.
165 * That is necessary to make sure all the pending machine state change events processed.
166 * We can't just use the machine state directly acquired from IMachine because there
167 * will be few places which are using stale machine state, not just this one. */
168 QApplication::sendPostedEvents(0, QEvent::MetaCall);
169
170 /* Check if we missed a really quick termination after successful startup: */
171 if (isTurnedOff())
172 {
173 LogRel(("GUI: Aborting startup due to invalid machine state detected: %d\n", machineState()));
174 return false;
175 }
176
177 /* Fetch corresponding states: */
178 if (uiCommon().isSeparateProcess())
179 {
180 sltAdditionsChange();
181 }
182 machineLogic()->initializePostPowerUp();
183
184#ifdef VBOX_GUI_WITH_PIDFILE
185 uiCommon().createPidfile();
186#endif /* VBOX_GUI_WITH_PIDFILE */
187
188 /* True by default: */
189 return true;
190}
191
192bool UISession::powerUp()
193{
194 /* Power UP machine: */
195 CProgress comProgress = uiCommon().shouldStartPaused() ? console().PowerUpPaused() : console().PowerUp();
196
197 /* Check for immediate failure: */
198 if (!console().isOk() || comProgress.isNull())
199 {
200 if (uiCommon().showStartVMErrors())
201 msgCenter().cannotStartMachine(console(), machineName());
202 LogRel(("GUI: Aborting startup due to power up issue detected...\n"));
203 return false;
204 }
205
206 /* Some logging right after we powered up: */
207 LogRel(("GUI: Qt version: %s\n", UICommon::qtRTVersionString().toUtf8().constData()));
208#ifdef VBOX_WS_X11
209 LogRel(("GUI: X11 Window Manager code: %d\n", (int)uiCommon().typeOfWindowManager()));
210#endif
211#if defined(VBOX_WS_MAC) || defined(VBOX_WS_WIN)
212 LogRel(("GUI: HID LEDs sync is %s\n", uimachine()->isHidLedsSyncEnabled() ? "enabled" : "disabled"));
213#else
214 LogRel(("GUI: HID LEDs sync is not supported on this platform\n"));
215#endif
216
217 /* Enable 'manual-override',
218 * preventing automatic Runtime UI closing
219 * and visual representation mode changes: */
220 uimachine()->setManualOverrideMode(true);
221
222 /* Show "Starting/Restoring" progress dialog: */
223 if (isSaved())
224 {
225 msgCenter().showModalProgressDialog(comProgress, machineName(), ":/progress_state_restore_90px.png", 0, 0);
226 /* After restoring from 'saved' state, machine-window(s) geometry should be adjusted: */
227 machineLogic()->adjustMachineWindowsGeometry();
228 }
229 else
230 {
231#ifdef VBOX_IS_QT6_OR_LATER /** @todo why is this any problem on qt6? */
232 msgCenter().showModalProgressDialog(comProgress, machineName(), ":/progress_start_90px.png", 0, 0);
233#else
234 msgCenter().showModalProgressDialog(comProgress, machineName(), ":/progress_start_90px.png");
235#endif
236 /* After VM start, machine-window(s) size-hint(s) should be sent: */
237 machineLogic()->sendMachineWindowsSizeHints();
238 }
239
240 /* Check for progress failure: */
241 if (!comProgress.isOk() || comProgress.GetResultCode() != 0)
242 {
243 if (uiCommon().showStartVMErrors())
244 msgCenter().cannotStartMachine(comProgress, machineName());
245 LogRel(("GUI: Aborting startup due to power up progress issue detected...\n"));
246 return false;
247 }
248
249 /* Disable 'manual-override' finally: */
250 uimachine()->setManualOverrideMode(false);
251
252 /* True by default: */
253 return true;
254}
255
256WId UISession::mainMachineWindowId() const
257{
258 return mainMachineWindow() ? mainMachineWindow()->winId() : 0;
259}
260
261bool UISession::reset()
262{
263 CConsole comConsole = console();
264 comConsole.Reset();
265 const bool fSuccess = comConsole.isOk();
266 if (!fSuccess)
267 UINotificationMessage::cannotResetMachine(comConsole);
268 return fSuccess;
269}
270
271bool UISession::setPause(bool fPause)
272{
273 CConsole comConsole = console();
274 if (fPause)
275 comConsole.Pause();
276 else
277 comConsole.Resume();
278 const bool fSuccess = comConsole.isOk();
279 if (!fSuccess)
280 {
281 if (fPause)
282 UINotificationMessage::cannotPauseMachine(comConsole);
283 else
284 UINotificationMessage::cannotResumeMachine(comConsole);
285 }
286 return fSuccess;
287}
288
289bool UISession::putScancode(LONG iCode)
290{
291 CKeyboard comKeyboard = keyboard();
292 comKeyboard.PutScancode(iCode);
293 const bool fSuccess = comKeyboard.isOk();
294 if (!fSuccess)
295 UINotificationMessage::cannotChangeKeyboardParameter(comKeyboard);
296 return fSuccess;
297}
298
299bool UISession::putScancodes(const QVector<LONG> &codes)
300{
301 CKeyboard comKeyboard = keyboard();
302 comKeyboard.PutScancodes(codes);
303 const bool fSuccess = comKeyboard.isOk();
304 if (!fSuccess)
305 UINotificationMessage::cannotChangeKeyboardParameter(comKeyboard);
306 return fSuccess;
307}
308
309bool UISession::putCAD()
310{
311 CKeyboard comKeyboard = keyboard();
312 comKeyboard.PutCAD();
313 const bool fSuccess = comKeyboard.isOk();
314 if (!fSuccess)
315 UINotificationMessage::cannotChangeKeyboardParameter(comKeyboard);
316 return fSuccess;
317}
318
319bool UISession::releaseKeys()
320{
321 CKeyboard comKeyboard = keyboard();
322 comKeyboard.ReleaseKeys();
323 const bool fSuccess = comKeyboard.isOk();
324 if (!fSuccess)
325 UINotificationMessage::cannotChangeKeyboardParameter(comKeyboard);
326 return fSuccess;
327}
328
329bool UISession::putUsageCode(LONG iUsageCode, LONG iUsagePage, bool fKeyRelease)
330{
331 CKeyboard comKeyboard = keyboard();
332 comKeyboard.PutUsageCode(iUsageCode, iUsagePage, fKeyRelease);
333 const bool fSuccess = comKeyboard.isOk();
334 if (!fSuccess)
335 UINotificationMessage::cannotChangeKeyboardParameter(comKeyboard);
336 return fSuccess;
337}
338
339bool UISession::getAbsoluteSupported()
340{
341 return mouse().GetAbsoluteSupported();
342}
343
344bool UISession::getRelativeSupported()
345{
346 return mouse().GetRelativeSupported();
347}
348
349bool UISession::getTouchScreenSupported()
350{
351 return mouse().GetTouchScreenSupported();
352}
353
354bool UISession::getTouchPadSupported()
355{
356 return mouse().GetTouchPadSupported();
357}
358
359bool UISession::getNeedsHostCursor()
360{
361 return mouse().GetNeedsHostCursor();
362}
363
364bool UISession::putMouseEvent(long iDx, long iDy, long iDz, long iDw, long iButtonState)
365{
366 CMouse comMouse = mouse();
367 comMouse.PutMouseEvent(iDx, iDy, iDz, iDw, iButtonState);
368 const bool fSuccess = comMouse.isOk();
369 if (!fSuccess)
370 UINotificationMessage::cannotChangeMouseParameter(comMouse);
371 return fSuccess;
372}
373
374bool UISession::putMouseEventAbsolute(long iX, long iY, long iDz, long iDw, long iButtonState)
375{
376 CMouse comMouse = mouse();
377 comMouse.PutMouseEventAbsolute(iX, iY, iDz, iDw, iButtonState);
378 const bool fSuccess = comMouse.isOk();
379 if (!fSuccess)
380 UINotificationMessage::cannotChangeMouseParameter(comMouse);
381 return fSuccess;
382}
383
384bool UISession::putEventMultiTouch(long iCount, const QVector<LONG64> &contacts, bool fIsTouchScreen, ulong uScanTime)
385{
386 CMouse comMouse = mouse();
387 comMouse.PutEventMultiTouch(iCount, contacts, fIsTouchScreen, uScanTime);
388 const bool fSuccess = comMouse.isOk();
389 if (!fSuccess)
390 UINotificationMessage::cannotChangeMouseParameter(comMouse);
391 return fSuccess;
392}
393
394bool UISession::usbDevices(QList<USBDeviceInfo> &guiUSBDevices)
395{
396 const CHost comHost = uiCommon().host();
397 const CHostUSBDeviceVector comHostUSBDevices = comHost.GetUSBDevices();
398 bool fSuccess = comHost.isOk();
399 if (!fSuccess)
400 UINotificationMessage::cannotAcquireHostParameter(comHost);
401 else
402 {
403 foreach (const CHostUSBDevice &comHostUSBDevice, comHostUSBDevices)
404 {
405 /* Get USB device from current host USB device,
406 * this stuff requires #include <VBox/com/VirtualBox.h> */
407 const CUSBDevice comUSBDevice(comHostUSBDevice);
408
409 /* Fill structure fields: */
410 USBDeviceInfo guiUSBDevice;
411 if (fSuccess)
412 {
413 guiUSBDevice.m_uId = comUSBDevice.GetId();
414 fSuccess = comUSBDevice.isOk();
415 }
416 if (fSuccess)
417 {
418 /// @todo make sure UICommon::usbDetails is checked for errors as well
419 guiUSBDevice.m_strName = uiCommon().usbDetails(comUSBDevice);
420 fSuccess = comUSBDevice.isOk();
421 }
422 if (fSuccess)
423 {
424 /// @todo make sure UICommon::usbToolTip is checked for errors as well
425 guiUSBDevice.m_strToolTip = uiCommon().usbToolTip(comUSBDevice);
426 fSuccess = comUSBDevice.isOk();
427 }
428 if (fSuccess)
429 {
430 /* Check if that USB device was already attached to this session;
431 * Nothing to check for errors here because error is valid case as well. */
432 const CUSBDevice comAttachedDevice = console().FindUSBDeviceById(guiUSBDevice.m_uId);
433 guiUSBDevice.m_fIsChecked = !comAttachedDevice.isNull();
434 }
435 if (fSuccess)
436 {
437 guiUSBDevice.m_fIsEnabled = comHostUSBDevice.GetState() != KUSBDeviceState_Unavailable;
438 fSuccess = comHostUSBDevice.isOk();
439 }
440
441 /* Append or break if necessary: */
442 if (fSuccess)
443 guiUSBDevices << guiUSBDevice;
444 else
445 break;
446 }
447 }
448 return fSuccess;
449}
450
451bool UISession::attachUSBDevice(const QUuid &uId)
452{
453 CConsole comConsole = console();
454 comConsole.AttachUSBDevice(uId, QString(""));
455 const bool fSuccess = comConsole.isOk();
456 if (!fSuccess)
457 {
458 CHost comHost = uiCommon().host();
459 /* Nothing to check for errors here because error is valid case as well. */
460 CHostUSBDevice comHostUSBDevice = comHost.FindUSBDeviceById(uId);
461 /* Get USB device from current host USB device,
462 * this stuff requires #include <VBox/com/VirtualBox.h> */
463 CUSBDevice comUSBDevice(comHostUSBDevice);
464 UINotificationMessage::cannotAttachUSBDevice(comConsole, uiCommon().usbDetails(comUSBDevice));
465 /// @todo make sure UICommon::usbDetails is checked for errors as well
466 }
467 return fSuccess;
468}
469
470bool UISession::detachUSBDevice(const QUuid &uId)
471{
472 CConsole comConsole = console();
473 comConsole.DetachUSBDevice(uId);
474 const bool fSuccess = comConsole.isOk();
475 if (!fSuccess)
476 {
477 CUSBDevice comUSBDevice = CConsole(comConsole).FindUSBDeviceById(uId);
478 UINotificationMessage::cannotDetachUSBDevice(comConsole, uiCommon().usbDetails(comUSBDevice));
479 /// @todo make sure UICommon::usbDetails is checked for errors as well
480 }
481 return fSuccess;
482}
483
484bool UISession::webcamDevices(QList<WebcamDeviceInfo> &guiWebcamDevices)
485{
486 const CHost comHost = uiCommon().host();
487 const CHostVideoInputDeviceVector comHostVideoInputDevices = comHost.GetVideoInputDevices();
488 bool fSuccess = comHost.isOk();
489 if (!fSuccess)
490 UINotificationMessage::cannotAcquireHostParameter(comHost);
491 else
492 {
493 CConsole comConsole = console();
494 CEmulatedUSB comEmulatedUSB = comConsole.GetEmulatedUSB();
495 fSuccess = comConsole.isOk();
496 if (!fSuccess)
497 UINotificationMessage::cannotAcquireConsoleParameter(comConsole);
498 else
499 {
500 const QVector<QString> attachedWebcamPaths = comEmulatedUSB.GetWebcams();
501 fSuccess = comEmulatedUSB.isOk();
502 if (!fSuccess)
503 UINotificationMessage::cannotAcquireEmulatedUSBParameter(comEmulatedUSB);
504 else
505 {
506 foreach (const CHostVideoInputDevice &comHostVideoInputDevice, comHostVideoInputDevices)
507 {
508 /* Fill structure fields: */
509 WebcamDeviceInfo guiWebcamDevice;
510 if (fSuccess)
511 {
512 guiWebcamDevice.m_strName = comHostVideoInputDevice.GetName();
513 fSuccess = comHostVideoInputDevice.isOk();
514 }
515 if (fSuccess)
516 {
517 guiWebcamDevice.m_strPath = comHostVideoInputDevice.GetPath();
518 fSuccess = comHostVideoInputDevice.isOk();
519 }
520 if (fSuccess)
521 {
522 /// @todo make sure UICommon::usbToolTip is checked for errors as well
523 guiWebcamDevice.m_strToolTip = uiCommon().usbToolTip(comHostVideoInputDevice);
524 fSuccess = comHostVideoInputDevice.isOk();
525 }
526 if (fSuccess)
527 guiWebcamDevice.m_fIsChecked = attachedWebcamPaths.contains(guiWebcamDevice.m_strPath);
528
529 /* Append or break if necessary: */
530 if (fSuccess)
531 guiWebcamDevices << guiWebcamDevice;
532 else
533 break;
534 }
535 }
536 }
537 }
538 return fSuccess;
539}
540
541bool UISession::webcamAttach(const QString &strPath, const QString &strName)
542{
543 CConsole comConsole = console();
544 CEmulatedUSB comDispatcher = comConsole.GetEmulatedUSB();
545 bool fSuccess = comConsole.isOk();
546 if (!fSuccess)
547 UINotificationMessage::cannotAcquireConsoleParameter(comConsole);
548 else
549 {
550 comDispatcher.WebcamAttach(strPath, "");
551 fSuccess = comDispatcher.isOk();
552 if (!fSuccess)
553 UINotificationMessage::cannotAttachWebCam(comDispatcher, strName, machineName());
554 }
555 return fSuccess;
556}
557
558bool UISession::webcamDetach(const QString &strPath, const QString &strName)
559{
560 CConsole comConsole = console();
561 CEmulatedUSB comDispatcher = comConsole.GetEmulatedUSB();
562 bool fSuccess = comConsole.isOk();
563 if (!fSuccess)
564 UINotificationMessage::cannotAcquireConsoleParameter(comConsole);
565 else
566 {
567 comDispatcher.WebcamDetach(strPath);
568 fSuccess = comDispatcher.isOk();
569 if (!fSuccess)
570 UINotificationMessage::cannotDetachWebCam(comDispatcher, strName, machineName());
571 }
572 return fSuccess;
573}
574
575bool UISession::guestAdditionsUpgradable()
576{
577 if (!machine().isOk())
578 return false;
579
580 /* Auto GA update is currently for Windows and Linux guests only */
581 const CGuestOSType osType = uiCommon().vmGuestOSType(machine().GetOSTypeId());
582 if (!osType.isOk())
583 return false;
584
585 const QString strGuestFamily = osType.GetFamilyId();
586 bool fIsWindowOrLinux = strGuestFamily.contains("windows", Qt::CaseInsensitive) || strGuestFamily.contains("linux", Qt::CaseInsensitive);
587
588 if (!fIsWindowOrLinux)
589 return false;
590
591 /* Also check whether we have something to update automatically: */
592 if (m_ulGuestAdditionsRunLevel < (ulong)KAdditionsRunLevelType_Userland)
593 return false;
594
595 return true;
596}
597
598UIFrameBuffer *UISession::frameBuffer(ulong uScreenId) const
599{
600 Assert(uScreenId < (ulong)m_frameBufferVector.size());
601 return m_frameBufferVector.value((int)uScreenId, 0);
602}
603
604void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer *pFrameBuffer)
605{
606 Assert(uScreenId < (ulong)m_frameBufferVector.size());
607 if (uScreenId < (ulong)m_frameBufferVector.size())
608 m_frameBufferVector[(int)uScreenId] = pFrameBuffer;
609}
610
611QSize UISession::frameBufferSize(ulong uScreenId) const
612{
613 UIFrameBuffer *pFramebuffer = frameBuffer(uScreenId);
614 return pFramebuffer ? QSize(pFramebuffer->width(), pFramebuffer->height()) : QSize();
615}
616
617bool UISession::acquireGuestScreenParameters(ulong uScreenId,
618 ulong &uWidth, ulong &uHeight, ulong &uBitsPerPixel,
619 long &xOrigin, long &yOrigin, KGuestMonitorStatus &enmMonitorStatus)
620{
621 CDisplay comDisplay = display();
622 ULONG uGuestWidth = 0, uGuestHeight = 0, uGuestBitsPerPixel = 0;
623 LONG iGuestXOrigin = 0, iGuestYOrigin = 0;
624 KGuestMonitorStatus enmGuestMonitorStatus = KGuestMonitorStatus_Disabled;
625 comDisplay.GetScreenResolution(uScreenId, uGuestWidth, uGuestHeight, uGuestBitsPerPixel,
626 iGuestXOrigin, iGuestYOrigin, enmGuestMonitorStatus);
627 const bool fSuccess = comDisplay.isOk();
628 if (!fSuccess)
629 UINotificationMessage::cannotAcquireDisplayParameter(comDisplay);
630 uWidth = uGuestWidth;
631 uHeight = uGuestHeight;
632 uBitsPerPixel = uGuestBitsPerPixel;
633 xOrigin = iGuestXOrigin;
634 yOrigin = iGuestYOrigin;
635 enmMonitorStatus = enmGuestMonitorStatus;
636 return fSuccess;
637}
638
639bool UISession::setVideoModeHint(ulong uScreenId, bool fEnabled, bool fChangeOrigin, long xOrigin, long yOrigin,
640 ulong uWidth, ulong uHeight, ulong uBitsPerPixel, bool fNotify)
641{
642 CDisplay comDisplay = display();
643 comDisplay.SetVideoModeHint(uScreenId, fEnabled, fChangeOrigin, xOrigin, yOrigin,
644 uWidth, uHeight, uBitsPerPixel, fNotify);
645 const bool fSuccess = comDisplay.isOk();
646 if (!fSuccess)
647 UINotificationMessage::cannotChangeDisplayParameter(comDisplay);
648 return fSuccess;
649}
650
651bool UISession::acquireVideoModeHint(ulong uScreenId, bool &fEnabled, bool &fChangeOrigin,
652 long &xOrigin, long &yOrigin, ulong &uWidth, ulong &uHeight,
653 ulong &uBitsPerPixel)
654{
655 CDisplay comDisplay = display();
656 BOOL fGuestEnabled = false, fGuestChangeOrigin = false;
657 LONG iGuestXOrigin = 0, iGuestYOrigin = 0;
658 ULONG uGuestWidth = 0, uGuestHeight = 0, uGuestBitsPerPixel = 0;
659 comDisplay.GetVideoModeHint(uScreenId, fGuestEnabled, fGuestChangeOrigin,
660 iGuestXOrigin, iGuestYOrigin, uGuestWidth, uGuestHeight,
661 uGuestBitsPerPixel);
662 const bool fSuccess = comDisplay.isOk();
663 if (!fSuccess)
664 UINotificationMessage::cannotAcquireDisplayParameter(comDisplay);
665 fEnabled = fGuestEnabled;
666 fChangeOrigin = fGuestChangeOrigin;
667 xOrigin = iGuestXOrigin;
668 yOrigin = iGuestYOrigin;
669 uWidth = uGuestWidth;
670 uHeight = uGuestHeight;
671 uBitsPerPixel = uGuestBitsPerPixel;
672 return fSuccess;
673}
674
675bool UISession::acquireScreenShot(ulong uScreenId, ulong uWidth, ulong uHeight, KBitmapFormat enmFormat, uchar *pBits)
676{
677 CDisplay comDisplay = display();
678 bool fSuccess = false;
679 /* For separate process: */
680 if (uiCommon().isSeparateProcess())
681 {
682 /* Take screen-data to array first: */
683 const QVector<BYTE> screenData = comDisplay.TakeScreenShotToArray(uScreenId, uWidth, uHeight, enmFormat);
684 fSuccess = comDisplay.isOk();
685 if (!fSuccess)
686 UINotificationMessage::cannotAcquireDisplayParameter(comDisplay);
687 else
688 {
689 /* And copy that data to screen-shot if it is Ok: */
690 if (!screenData.isEmpty())
691 memcpy(pBits, screenData.data(), uWidth * uHeight * 4);
692 }
693 }
694 /* For the same process: */
695 else
696 {
697 /* Take the screen-shot directly: */
698 comDisplay.TakeScreenShot(uScreenId, pBits, uWidth, uHeight, enmFormat);
699 fSuccess = comDisplay.isOk();
700 if (!fSuccess)
701 UINotificationMessage::cannotAcquireDisplayParameter(comDisplay);
702 }
703 return fSuccess;
704}
705
706bool UISession::notifyScaleFactorChange(ulong uScreenId, ulong uScaleFactorWMultiplied, ulong uScaleFactorHMultiplied)
707{
708 CDisplay comDisplay = display();
709 comDisplay.NotifyScaleFactorChange(uScreenId, uScaleFactorWMultiplied, uScaleFactorHMultiplied);
710 const bool fSuccess = comDisplay.isOk();
711 if (!fSuccess)
712 UINotificationMessage::cannotChangeDisplayParameter(comDisplay);
713 return fSuccess;
714}
715
716bool UISession::notifyHiDPIOutputPolicyChange(bool fUnscaledHiDPI)
717{
718 CDisplay comDisplay = display();
719 comDisplay.NotifyHiDPIOutputPolicyChange(fUnscaledHiDPI);
720 const bool fSuccess = comDisplay.isOk();
721 if (!fSuccess)
722 UINotificationMessage::cannotChangeDisplayParameter(comDisplay);
723 return fSuccess;
724}
725
726bool UISession::setSeamlessMode(bool fEnabled)
727{
728 CDisplay comDisplay = display();
729 comDisplay.SetSeamlessMode(fEnabled);
730 const bool fSuccess = comDisplay.isOk();
731 if (!fSuccess)
732 UINotificationMessage::cannotChangeDisplayParameter(comDisplay);
733 return fSuccess;
734}
735
736bool UISession::viewportChanged(ulong uScreenId, ulong xOrigin, ulong yOrigin, ulong uWidth, ulong uHeight)
737{
738 CDisplay comDisplay = display();
739 comDisplay.ViewportChanged(uScreenId, xOrigin, yOrigin, uWidth, uHeight);
740 const bool fSuccess = comDisplay.isOk();
741 if (!fSuccess)
742 UINotificationMessage::cannotChangeDisplayParameter(comDisplay);
743 return fSuccess;
744}
745
746bool UISession::invalidateAndUpdate()
747{
748 CDisplay comDisplay = display();
749 comDisplay.InvalidateAndUpdate();
750 const bool fSuccess = comDisplay.isOk();
751 if (!fSuccess)
752 UINotificationMessage::cannotChangeDisplayParameter(comDisplay);
753 return fSuccess;
754}
755
756bool UISession::invalidateAndUpdateScreen(ulong uScreenId)
757{
758 CDisplay comDisplay = display();
759 comDisplay.InvalidateAndUpdateScreen(uScreenId);
760 const bool fSuccess = comDisplay.isOk();
761 if (!fSuccess)
762 UINotificationMessage::cannotChangeDisplayParameter(comDisplay);
763 return fSuccess;
764}
765
766bool UISession::acquireDeviceActivity(const QVector<KDeviceType> &deviceTypes, QVector<KDeviceActivity> &states)
767{
768 CConsole comConsole = console();
769 states = comConsole.GetDeviceActivity(deviceTypes);
770 const bool fSuccess = comConsole.isOk();
771 if (!fSuccess)
772 UINotificationMessage::cannotAcquireConsoleParameter(comConsole);
773 return fSuccess;
774}
775
776void UISession::acquireHardDiskStatusInfo(QString &strInfo, bool &fAttachmentsPresent)
777{
778 CMachine comMachine = machine();
779 UIDetailsGenerator::acquireHardDiskStatusInfo(comMachine, strInfo, fAttachmentsPresent);
780}
781
782void UISession::acquireOpticalDiskStatusInfo(QString &strInfo, bool &fAttachmentsPresent, bool &fAttachmentsMounted)
783{
784 CMachine comMachine = machine();
785 UIDetailsGenerator::acquireOpticalDiskStatusInfo(comMachine, strInfo, fAttachmentsPresent, fAttachmentsMounted);
786}
787
788void UISession::acquireFloppyDiskStatusInfo(QString &strInfo, bool &fAttachmentsPresent, bool &fAttachmentsMounted)
789{
790 CMachine comMachine = machine();
791 UIDetailsGenerator::acquireFloppyDiskStatusInfo(comMachine, strInfo, fAttachmentsPresent, fAttachmentsMounted);
792}
793
794void UISession::acquireAudioStatusInfo(QString &strInfo, bool &fAudioEnabled, bool &fEnabledOutput, bool &fEnabledInput)
795{
796 CMachine comMachine = machine();
797 UIDetailsGenerator::acquireAudioStatusInfo(comMachine, strInfo, fAudioEnabled, fEnabledOutput, fEnabledInput);
798}
799
800void UISession::acquireNetworkStatusInfo(QString &strInfo, bool &fAdaptersPresent, bool &fCablesDisconnected)
801{
802 CMachine comMachine = machine();
803 UIDetailsGenerator::acquireNetworkStatusInfo(comMachine, strInfo, fAdaptersPresent, fCablesDisconnected);
804}
805
806void UISession::acquireUsbStatusInfo(QString &strInfo, bool &fUsbEnableds)
807{
808 CMachine comMachine = machine();
809 CConsole comConsole = console();
810 UIDetailsGenerator::acquireUsbStatusInfo(comMachine, comConsole, strInfo, fUsbEnableds);
811}
812
813void UISession::acquireSharedFoldersStatusInfo(QString &strInfo, bool &fFoldersPresent)
814{
815 CMachine comMachine = machine();
816 CConsole comConsole = console();
817 CGuest comGuest = guest();
818 UIDetailsGenerator::acquireSharedFoldersStatusInfo(comMachine, comConsole, comGuest, strInfo, fFoldersPresent);
819}
820
821void UISession::acquireDisplayStatusInfo(QString &strInfo, bool &fAcceleration3D)
822{
823 CMachine comMachine = machine();
824 UIDetailsGenerator::acquireDisplayStatusInfo(comMachine, strInfo, fAcceleration3D);
825}
826
827void UISession::acquireRecordingStatusInfo(QString &strInfo, bool &fRecordingEnabled, bool &fMachinePaused)
828{
829 CMachine comMachine = machine();
830 fMachinePaused = isPaused();
831 UIDetailsGenerator::acquireRecordingStatusInfo(comMachine, strInfo, fRecordingEnabled);
832}
833
834void UISession::acquireFeaturesStatusInfo(QString &strInfo, KVMExecutionEngine &enmEngine,
835 bool fNestedPagingEnabled, bool fUxEnabled,
836 KParavirtProvider enmProvider)
837{
838 CMachine comMachine = machine();
839 UIDetailsGenerator::acquireFeaturesStatusInfo(comMachine, strInfo,
840 enmEngine,
841 fNestedPagingEnabled, fUxEnabled,
842 enmProvider);
843}
844
845bool UISession::setLogEnabled(bool fEnabled)
846{
847 CMachineDebugger comDebugger = debugger();
848 comDebugger.SetLogEnabled(fEnabled ? TRUE : FALSE);
849 const bool fSuccess = comDebugger.isOk();
850 if (!fSuccess)
851 UINotificationMessage::cannotChangeMachineDebuggerParameter(comDebugger);
852 return fSuccess;
853}
854
855bool UISession::acquireWhetherLogEnabled(bool &fEnabled)
856{
857 CMachineDebugger comDebugger = debugger();
858 const BOOL fLogEnabled = comDebugger.GetLogEnabled();
859 const bool fSuccess = comDebugger.isOk();
860 if (!fSuccess)
861 UINotificationMessage::cannotAcquireMachineDebuggerParameter(comDebugger);
862 else
863 fEnabled = fLogEnabled == TRUE;
864 return fSuccess;
865}
866
867bool UISession::acquireExecutionEngineType(KVMExecutionEngine &enmType)
868{
869 CMachineDebugger comDebugger = debugger();
870 const KVMExecutionEngine enmEngineType = comDebugger.GetExecutionEngine();
871 const bool fSuccess = comDebugger.isOk();
872 if (!fSuccess)
873 UINotificationMessage::cannotAcquireMachineDebuggerParameter(comDebugger);
874 else
875 enmType = enmEngineType;
876 return fSuccess;
877}
878
879bool UISession::acquireWhetherHwVirtExNestedPagingEnabled(bool &fEnabled)
880{
881 CMachineDebugger comDebugger = debugger();
882 const BOOL fFeatureEnabled = comDebugger.GetHWVirtExNestedPagingEnabled();
883 const bool fSuccess = comDebugger.isOk();
884 if (!fSuccess)
885 UINotificationMessage::cannotAcquireMachineDebuggerParameter(comDebugger);
886 else
887 fEnabled = fFeatureEnabled == TRUE;
888 return fSuccess;
889}
890
891bool UISession::acquireWhetherHwVirtExUXEnabled(bool &fEnabled)
892{
893 CMachineDebugger comDebugger = debugger();
894 const BOOL fFeatureEnabled = comDebugger.GetHWVirtExUXEnabled();
895 const bool fSuccess = comDebugger.isOk();
896 if (!fSuccess)
897 UINotificationMessage::cannotAcquireMachineDebuggerParameter(comDebugger);
898 else
899 fEnabled = fFeatureEnabled == TRUE;
900 return fSuccess;
901}
902
903bool UISession::acquireEffectiveCPULoad(ulong &uLoad)
904{
905 CMachineDebugger comDebugger = debugger();
906 ULONG uPctExecuting;
907 ULONG uPctHalted;
908 ULONG uPctOther;
909 comDebugger.GetCPULoad(0x7fffffff, uPctExecuting, uPctHalted, uPctOther);
910 const bool fSuccess = comDebugger.isOk();
911 if (!fSuccess)
912 UINotificationMessage::cannotAcquireMachineDebuggerParameter(comDebugger);
913 else
914 uLoad = uPctExecuting + uPctOther;
915 return fSuccess;
916}
917
918#ifdef VBOX_WITH_DEBUGGER_GUI
919bool UISession::dbgCreated(void *pActionDebug)
920{
921 if (m_pDbgGui)
922 return true;
923
924 RTLDRMOD hLdrMod = uiCommon().getDebuggerModule();
925 if (hLdrMod == NIL_RTLDRMOD)
926 return false;
927
928 PFNDBGGUICREATE pfnGuiCreate;
929 int rc = RTLdrGetSymbol(hLdrMod, "DBGGuiCreate", (void**)&pfnGuiCreate);
930 if (RT_SUCCESS(rc))
931 {
932 ISession *pISession = session().raw();
933 rc = pfnGuiCreate(pISession, &m_pDbgGui, &m_pDbgGuiVT);
934 if (RT_SUCCESS(rc))
935 {
936 if ( DBGGUIVT_ARE_VERSIONS_COMPATIBLE(m_pDbgGuiVT->u32Version, DBGGUIVT_VERSION)
937 || m_pDbgGuiVT->u32EndVersion == m_pDbgGuiVT->u32Version)
938 {
939 m_pDbgGuiVT->pfnSetParent(m_pDbgGui, activeMachineWindow());
940 m_pDbgGuiVT->pfnSetMenu(m_pDbgGui, pActionDebug);
941 dbgAdjustRelativePos();
942 return true;
943 }
944
945 LogRel(("GUI: DBGGuiCreate failed, incompatible versions (loaded %#x/%#x, expected %#x)\n",
946 m_pDbgGuiVT->u32Version, m_pDbgGuiVT->u32EndVersion, DBGGUIVT_VERSION));
947 }
948 else
949 LogRel(("GUI: DBGGuiCreate failed, rc=%Rrc\n", rc));
950 }
951 else
952 LogRel(("GUI: RTLdrGetSymbol(,\"DBGGuiCreate\",) -> %Rrc\n", rc));
953
954 m_pDbgGui = 0;
955 m_pDbgGuiVT = 0;
956 return false;
957}
958
959void UISession::dbgDestroy()
960{
961 if (m_pDbgGui)
962 {
963 m_pDbgGuiVT->pfnDestroy(m_pDbgGui);
964 m_pDbgGui = 0;
965 m_pDbgGuiVT = 0;
966 }
967}
968
969void UISession::dbgShowStatistics()
970{
971 const QByteArray &expandBytes = uiCommon().getDebuggerStatisticsExpand().toUtf8();
972 const QByteArray &filterBytes = uiCommon().getDebuggerStatisticsFilter().toUtf8();
973 m_pDbgGuiVT->pfnShowStatistics(m_pDbgGui, filterBytes.constData(), expandBytes.constData());
974}
975
976void UISession::dbgShowCommandLine()
977{
978 m_pDbgGuiVT->pfnShowCommandLine(m_pDbgGui);
979}
980
981void UISession::dbgAdjustRelativePos()
982{
983 if (m_pDbgGui)
984 {
985 const QRect rct = activeMachineWindow()->frameGeometry();
986 m_pDbgGuiVT->pfnAdjustRelativePos(m_pDbgGui, rct.x(), rct.y(), rct.width(), rct.height());
987 }
988}
989#endif /* VBOX_WITH_DEBUGGER_GUI */
990
991bool UISession::acquireWhetherGuestEnteredACPIMode(bool &fEntered)
992{
993 CConsole comConsole = console();
994 const BOOL fGuestEntered = comConsole.GetGuestEnteredACPIMode();
995 const bool fSuccess = comConsole.isOk();
996 if (!fSuccess)
997 UINotificationMessage::cannotAcquireConsoleParameter(comConsole);
998 else
999 fEntered = fGuestEntered == TRUE;
1000 return fSuccess;
1001}
1002
1003void UISession::saveState()
1004{
1005 if ( isPaused()
1006 || (isRunning() && pause()))
1007 {
1008 /* Enable 'manual-override',
1009 * preventing automatic Runtime UI closing: */
1010 uimachine()->setManualOverrideMode(true);
1011
1012 /* Now, do the magic: */
1013 LogRel(("GUI: Saving VM state..\n"));
1014 UINotificationProgressMachineSaveState *pNotification =
1015 new UINotificationProgressMachineSaveState(machine());
1016 connect(pNotification, &UINotificationProgressMachineSaveState::sigMachineStateSaved,
1017 this, &UISession::sltHandleMachineStateSaved);
1018 gpNotificationCenter->append(pNotification);
1019 }
1020}
1021
1022void UISession::shutdown()
1023{
1024 /* Check whether guest is in proper mode: */
1025 bool fValidMode = false;
1026 acquireWhetherGuestEnteredACPIMode(fValidMode);
1027 if (!fValidMode)
1028 UINotificationMessage::cannotSendACPIToMachine();
1029 else
1030 {
1031 /* Now, do the magic: */
1032 LogRel(("GUI: Sending ACPI shutdown signal..\n"));
1033 CConsole comConsole = console();
1034 comConsole.PowerButton();
1035 if (!comConsole.isOk())
1036 UINotificationMessage::cannotACPIShutdownMachine(comConsole);
1037 }
1038}
1039
1040void UISession::powerOff(bool fIncludingDiscard)
1041{
1042 /* Enable 'manual-override',
1043 * preventing automatic Runtime UI closing: */
1044 uimachine()->setManualOverrideMode(true);
1045
1046 /* Now, do the magic: */
1047 LogRel(("GUI: Powering VM off..\n"));
1048 UINotificationProgressMachinePowerOff *pNotification =
1049 new UINotificationProgressMachinePowerOff(machine(),
1050 console(),
1051 fIncludingDiscard);
1052 connect(pNotification, &UINotificationProgressMachinePowerOff::sigMachinePoweredOff,
1053 this, &UISession::sltHandleMachinePoweredOff);
1054 gpNotificationCenter->append(pNotification);
1055}
1056
1057void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
1058{
1059 if (!guestAdditionsUpgradable())
1060 return sltMountDVDAdHoc(strSource);
1061
1062 /* Update guest additions automatically: */
1063 UINotificationProgressGuestAdditionsInstall *pNotification =
1064 new UINotificationProgressGuestAdditionsInstall(guest(), strSource);
1065 connect(pNotification, &UINotificationProgressGuestAdditionsInstall::sigGuestAdditionsInstallationFailed,
1066 this, &UISession::sltMountDVDAdHoc);
1067 gpNotificationCenter->append(pNotification);
1068}
1069
1070void UISession::sltMountDVDAdHoc(const QString &strSource)
1071{
1072 mountAdHocImage(KDeviceType_DVD, UIMediumDeviceType_DVD, strSource);
1073}
1074
1075void UISession::sltDetachCOM()
1076{
1077 /* Cleanup everything COM related: */
1078 cleanupFramebuffers();
1079 cleanupConsoleEventHandlers();
1080 cleanupNotificationCenter();
1081 cleanupSession();
1082}
1083
1084void UISession::sltStateChange(KMachineState enmState)
1085{
1086 /* Check if something had changed: */
1087 if (m_enmMachineState != enmState)
1088 {
1089 /* Store new data: */
1090 m_enmMachineStatePrevious = m_enmMachineState;
1091 m_enmMachineState = enmState;
1092
1093 /* Notify listeners about machine state changed: */
1094 emit sigMachineStateChange();
1095 }
1096}
1097
1098void UISession::sltAdditionsChange()
1099{
1100 /* Acquire actual states: */
1101 const ulong ulGuestAdditionsRunLevel = guest().GetAdditionsRunLevel();
1102 LONG64 iLastUpdatedIgnored;
1103 const bool fIsGuestSupportsGraphics = guest().GetFacilityStatus(KAdditionsFacilityType_Graphics, iLastUpdatedIgnored)
1104 == KAdditionsFacilityStatus_Active;
1105 const bool fIsGuestSupportsSeamless = guest().GetFacilityStatus(KAdditionsFacilityType_Seamless, iLastUpdatedIgnored)
1106 == KAdditionsFacilityStatus_Active;
1107
1108 /* Check if something had changed: */
1109 if ( m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel
1110 || m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics
1111 || m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
1112 {
1113 /* Store new data: */
1114 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
1115 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
1116 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
1117
1118 /* Notify listeners about GA state really changed: */
1119 LogRel(("GUI: UISession::sltAdditionsChange: GA state really changed, notifying listeners.\n"));
1120 emit sigAdditionsStateActualChange();
1121 }
1122 else
1123 LogRel(("GUI: UISession::sltAdditionsChange: GA state doesn't really changed, still notifying listeners.\n"));
1124
1125 /* Notify listeners about GA state change event came: */
1126 emit sigAdditionsStateChange();
1127}
1128
1129void UISession::sltHandleMachineStateSaved(bool fSuccess)
1130{
1131 /* Let user try again if saving failed: */
1132 if (!fSuccess)
1133 {
1134 /* Disable 'manual-override' finally: */
1135 uimachine()->setManualOverrideMode(false);
1136 }
1137 /* Close Runtime UI otherwise: */
1138 else
1139 uimachine()->closeRuntimeUI();
1140}
1141
1142void UISession::sltHandleMachinePoweredOff(bool fSuccess, bool fIncludingDiscard)
1143{
1144 /* Let user try again if power off failed: */
1145 if (!fSuccess)
1146 {
1147 /* Disable 'manual-override' finally: */
1148 uimachine()->setManualOverrideMode(false);
1149 }
1150 /* Check for other tasks otherwise: */
1151 else
1152 {
1153 if (fIncludingDiscard)
1154 {
1155 /* Now, do more magic! */
1156 UINotificationProgressSnapshotRestore *pNotification =
1157 new UINotificationProgressSnapshotRestore(uiCommon().managedVMUuid());
1158 connect(pNotification, &UINotificationProgressSnapshotRestore::sigSnapshotRestored,
1159 this, &UISession::sltHandleSnapshotRestored);
1160 gpNotificationCenter->append(pNotification);
1161 }
1162 else
1163 uimachine()->closeRuntimeUI();
1164 }
1165}
1166
1167void UISession::sltHandleSnapshotRestored(bool)
1168{
1169 /* Close Runtime UI independent of snapshot restoring state: */
1170 uimachine()->closeRuntimeUI();
1171}
1172
1173UISession::UISession(UIMachine *pMachine)
1174 : QObject(pMachine)
1175 /* Base variables: */
1176 , m_pMachine(pMachine)
1177 , m_pConsoleEventhandler(0)
1178 /* Common variables: */
1179 , m_enmMachineStatePrevious(KMachineState_Null)
1180 , m_enmMachineState(KMachineState_Null)
1181 /* Guest additions flags: */
1182 , m_ulGuestAdditionsRunLevel(0)
1183 , m_fIsGuestSupportsGraphics(false)
1184 , m_fIsGuestSupportsSeamless(false)
1185#ifdef VBOX_WITH_DEBUGGER_GUI
1186 /* Debug UI stuff: */
1187 , m_pDbgGui(0)
1188 , m_pDbgGuiVT(0)
1189#endif /* VBOX_WITH_DEBUGGER_GUI */
1190{
1191}
1192
1193UISession::~UISession()
1194{
1195}
1196
1197bool UISession::prepare()
1198{
1199 /* Prepare COM stuff: */
1200 if (!prepareSession())
1201 return false;
1202
1203 /* Cache media early if requested: */
1204 if (uiCommon().agressiveCaching())
1205 recacheMachineMedia();
1206
1207 /* Prepare GUI stuff: */
1208 prepareNotificationCenter();
1209 prepareConsoleEventHandlers();
1210 prepareFramebuffers();
1211 prepareConnections();
1212 prepareSignalHandling();
1213
1214 /* True by default: */
1215 return true;
1216}
1217
1218bool UISession::prepareSession()
1219{
1220 /* Open session: */
1221 m_comSession = uiCommon().openSession(uiCommon().managedVMUuid(),
1222 uiCommon().isSeparateProcess()
1223 ? KLockType_Shared
1224 : KLockType_VM);
1225 if (m_comSession.isNull())
1226 return false;
1227
1228 /* Get machine: */
1229 m_comMachine = m_comSession.GetMachine();
1230 if (m_comMachine.isNull())
1231 return false;
1232
1233 /* Get console: */
1234 m_comConsole = m_comSession.GetConsole();
1235 if (m_comConsole.isNull())
1236 return false;
1237
1238 /* Get display: */
1239 m_comDisplay = m_comConsole.GetDisplay();
1240 if (m_comDisplay.isNull())
1241 return false;
1242
1243 /* Get guest: */
1244 m_comGuest = m_comConsole.GetGuest();
1245 if (m_comGuest.isNull())
1246 return false;
1247
1248 /* Get mouse: */
1249 m_comMouse = m_comConsole.GetMouse();
1250 if (m_comMouse.isNull())
1251 return false;
1252
1253 /* Get keyboard: */
1254 m_comKeyboard = m_comConsole.GetKeyboard();
1255 if (m_comKeyboard.isNull())
1256 return false;
1257
1258 /* Get debugger: */
1259 m_comDebugger = m_comConsole.GetDebugger();
1260 if (m_comDebugger.isNull())
1261 return false;
1262
1263 /* Update machine-name: */
1264 m_strMachineName = machine().GetName();
1265
1266 /* Update machine-state: */
1267 m_enmMachineState = machine().GetState();
1268
1269 /* True by default: */
1270 return true;
1271}
1272
1273void UISession::prepareNotificationCenter()
1274{
1275 UINotificationCenter::create();
1276}
1277
1278void UISession::prepareConsoleEventHandlers()
1279{
1280 /* Create console event-handler: */
1281 m_pConsoleEventhandler = new UIConsoleEventHandler(this);
1282
1283 /* Console event connections: */
1284 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigAdditionsChange,
1285 this, &UISession::sltAdditionsChange);
1286 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigAudioAdapterChange,
1287 this, &UISession::sigAudioAdapterChange);
1288 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigClipboardModeChange,
1289 this, &UISession::sigClipboardModeChange);
1290 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigCPUExecutionCapChange,
1291 this, &UISession::sigCPUExecutionCapChange);
1292 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigDnDModeChange,
1293 this, &UISession::sigDnDModeChange);
1294 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigGuestMonitorChange,
1295 this, &UISession::sigGuestMonitorChange);
1296 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigMediumChange,
1297 this, &UISession::sigMediumChange);
1298 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigNetworkAdapterChange,
1299 this, &UISession::sigNetworkAdapterChange);
1300 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigRecordingChange,
1301 this, &UISession::sigRecordingChange);
1302 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigSharedFolderChange,
1303 this, &UISession::sigSharedFolderChange);
1304 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigStateChange,
1305 this, &UISession::sltStateChange);
1306 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigStorageDeviceChange,
1307 this, &UISession::sigStorageDeviceChange);
1308 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigUSBControllerChange,
1309 this, &UISession::sigUSBControllerChange);
1310 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigUSBDeviceStateChange,
1311 this, &UISession::sigUSBDeviceStateChange);
1312 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigVRDEChange,
1313 this, &UISession::sigVRDEChange);
1314 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigRuntimeError,
1315 this, &UISession::sigRuntimeError);
1316
1317#ifdef VBOX_WS_MAC
1318 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigShowWindow,
1319 this, &UISession::sigShowWindows, Qt::QueuedConnection);
1320#endif
1321
1322 /* Console keyboard connections: */
1323 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigKeyboardLedsChange,
1324 this, &UISession::sigKeyboardLedsChange);
1325
1326 /* Console mouse connections: */
1327 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigMousePointerShapeChange,
1328 this, &UISession::sigMousePointerShapeChange);
1329 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigMouseCapabilityChange,
1330 this, &UISession::sigMouseCapabilityChange);
1331 connect(m_pConsoleEventhandler, &UIConsoleEventHandler::sigCursorPositionChange,
1332 this, &UISession::sigCursorPositionChange);
1333}
1334
1335void UISession::prepareFramebuffers()
1336{
1337 /* Each framebuffer will be really prepared on first UIMachineView creation: */
1338 m_frameBufferVector.resize(machine().GetGraphicsAdapter().GetMonitorCount());
1339}
1340
1341void UISession::prepareConnections()
1342{
1343 /* UICommon connections: */
1344 connect(&uiCommon(), &UICommon::sigAskToDetachCOM, this, &UISession::sltDetachCOM);
1345}
1346
1347void UISession::prepareSignalHandling()
1348{
1349#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
1350 struct sigaction sa;
1351 sa.sa_sigaction = &signalHandlerSIGUSR1;
1352 sigemptyset(&sa.sa_mask);
1353 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1354 sigaction(SIGUSR1, &sa, NULL);
1355#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
1356}
1357
1358void UISession::cleanupFramebuffers()
1359{
1360 /* Cleanup framebuffers finally: */
1361 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i)
1362 {
1363 UIFrameBuffer *pFrameBuffer = m_frameBufferVector[i];
1364 if (pFrameBuffer)
1365 {
1366 /* Mark framebuffer as unused: */
1367 pFrameBuffer->setMarkAsUnused(true);
1368 /* Detach framebuffer from Display: */
1369 pFrameBuffer->detach();
1370 /* Delete framebuffer reference: */
1371 delete pFrameBuffer;
1372 }
1373 }
1374 m_frameBufferVector.clear();
1375}
1376
1377void UISession::cleanupConsoleEventHandlers()
1378{
1379 /* Destroy console event-handler: */
1380 delete m_pConsoleEventhandler;
1381 m_pConsoleEventhandler = 0;
1382}
1383
1384void UISession::cleanupNotificationCenter()
1385{
1386 UINotificationCenter::destroy();
1387}
1388
1389void UISession::cleanupSession()
1390{
1391 /* Detach debugger: */
1392 if (!m_comDebugger.isNull())
1393 m_comDebugger.detach();
1394
1395 /* Detach keyboard: */
1396 if (!m_comKeyboard.isNull())
1397 m_comKeyboard.detach();
1398
1399 /* Detach mouse: */
1400 if (!m_comMouse.isNull())
1401 m_comMouse.detach();
1402
1403 /* Detach guest: */
1404 if (!m_comGuest.isNull())
1405 m_comGuest.detach();
1406
1407 /* Detach display: */
1408 if (!m_comDisplay.isNull())
1409 m_comDisplay.detach();
1410
1411 /* Detach console: */
1412 if (!m_comConsole.isNull())
1413 m_comConsole.detach();
1414
1415 /* Detach machine: */
1416 if (!m_comMachine.isNull())
1417 m_comMachine.detach();
1418
1419 /* Close session: */
1420 if (!m_comSession.isNull() && uiCommon().isVBoxSVCAvailable())
1421 {
1422 m_comSession.UnlockMachine();
1423 m_comSession.detach();
1424 }
1425}
1426
1427UIMachineLogic *UISession::machineLogic() const
1428{
1429 return uimachine() ? uimachine()->machineLogic() : 0;
1430}
1431
1432UIMachineWindow *UISession::activeMachineWindow() const
1433{
1434 return machineLogic() ? machineLogic()->activeMachineWindow() : 0;
1435}
1436
1437QWidget *UISession::mainMachineWindow() const
1438{
1439 return machineLogic() ? machineLogic()->mainMachineWindow() : 0;
1440}
1441
1442bool UISession::preprocessInitialization()
1443{
1444#ifdef VBOX_WITH_NETFLT
1445 /* Skip network interface name checks if VM in saved state: */
1446 if (!isSaved())
1447 {
1448 /* Make sure all the attached and enabled network
1449 * adapters are present on the host. This check makes sense
1450 * in two cases only - when attachement type is Bridged Network
1451 * or Host-only Interface. NOTE: Only currently enabled
1452 * attachement type is checked (incorrect parameters check for
1453 * currently disabled attachement types is skipped). */
1454 QStringList failedInterfaceNames;
1455 QStringList availableInterfaceNames;
1456
1457 /* Create host network interface names list: */
1458 foreach (const CHostNetworkInterface &comNetIface, uiCommon().host().GetNetworkInterfaces())
1459 {
1460 availableInterfaceNames << comNetIface.GetName();
1461 availableInterfaceNames << comNetIface.GetShortName();
1462 }
1463
1464 /* Enumerate all the virtual network adapters: */
1465 const ulong cCount = uiCommon().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine().GetChipsetType());
1466 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex)
1467 {
1468 CNetworkAdapter comNetworkAdapter = machine().GetNetworkAdapter(uAdapterIndex);
1469 if (comNetworkAdapter.GetEnabled())
1470 {
1471 /* Get physical network interface name for
1472 * currently enabled network attachement type: */
1473 QString strInterfaceName;
1474 switch (comNetworkAdapter.GetAttachmentType())
1475 {
1476 case KNetworkAttachmentType_Bridged:
1477 strInterfaceName = comNetworkAdapter.GetBridgedInterface();
1478 break;
1479#ifndef VBOX_WITH_VMNET
1480 case KNetworkAttachmentType_HostOnly:
1481 strInterfaceName = comNetworkAdapter.GetHostOnlyInterface();
1482 break;
1483#endif /* !VBOX_WITH_VMNET */
1484 default:
1485 break;
1486 }
1487
1488 if ( !strInterfaceName.isEmpty()
1489 && !availableInterfaceNames.contains(strInterfaceName))
1490 {
1491 LogRel(("GUI: Invalid network interface found: %s\n", strInterfaceName.toUtf8().constData()));
1492 failedInterfaceNames << QString("%1 (adapter %2)").arg(strInterfaceName).arg(uAdapterIndex + 1);
1493 }
1494 }
1495 }
1496
1497 /* Check if non-existent interfaces found: */
1498 if (!failedInterfaceNames.isEmpty())
1499 {
1500 if (msgCenter().warnAboutNetworkInterfaceNotFound(machineName(), failedInterfaceNames.join(", ")))
1501 machineLogic()->openNetworkSettingsDialog();
1502 else
1503 {
1504 LogRel(("GUI: Aborting startup due to preprocess initialization issue detected...\n"));
1505 return false;
1506 }
1507 }
1508 }
1509#endif /* VBOX_WITH_NETFLT */
1510
1511 /* Check for USB enumeration warning. Don't return false even if we have a warning: */
1512 CHost comHost = uiCommon().host();
1513 if (comHost.GetUSBDevices().isEmpty() && comHost.isWarning())
1514 {
1515 /* Do not bitch if USB disabled: */
1516 if (!machine().GetUSBControllers().isEmpty())
1517 {
1518 /* Do not bitch if there are no filters (check if enabled too?): */
1519 if (!machine().GetUSBDeviceFilters().GetDeviceFilters().isEmpty())
1520 UINotificationMessage::cannotEnumerateHostUSBDevices(comHost);
1521 }
1522 }
1523
1524 /* True by default: */
1525 return true;
1526}
1527
1528bool UISession::mountAdHocImage(KDeviceType enmDeviceType, UIMediumDeviceType enmMediumType, const QString &strMediumName)
1529{
1530 /* Get VBox: */
1531 CVirtualBox comVBox = uiCommon().virtualBox();
1532
1533 /* Prepare medium to mount: */
1534 UIMedium guiMedium;
1535
1536 /* The 'none' medium name means ejecting what ever is in the drive,
1537 * in that case => leave the guiMedium variable null. */
1538 if (strMediumName != "none")
1539 {
1540 /* Open the medium: */
1541 const CMedium comMedium = comVBox.OpenMedium(strMediumName, enmDeviceType, KAccessMode_ReadWrite, false /* fForceNewUuid */);
1542 if (!comVBox.isOk() || comMedium.isNull())
1543 {
1544 UINotificationMessage::cannotOpenMedium(comVBox, strMediumName);
1545 return false;
1546 }
1547
1548 /* Make sure medium ID is valid: */
1549 const QUuid uMediumId = comMedium.GetId();
1550 AssertReturn(!uMediumId.isNull(), false);
1551
1552 /* Try to find UIMedium among cached: */
1553 guiMedium = uiCommon().medium(uMediumId);
1554 if (guiMedium.isNull())
1555 {
1556 /* Cache new one if necessary: */
1557 guiMedium = UIMedium(comMedium, enmMediumType, KMediumState_Created);
1558 uiCommon().createMedium(guiMedium);
1559 }
1560 }
1561
1562 /* Search for a suitable storage slots: */
1563 QList<ExactStorageSlot> aFreeStorageSlots;
1564 QList<ExactStorageSlot> aBusyStorageSlots;
1565 foreach (const CStorageController &comController, machine().GetStorageControllers())
1566 {
1567 foreach (const CMediumAttachment &comAttachment, machine().GetMediumAttachmentsOfController(comController.GetName()))
1568 {
1569 /* Look for an optical devices only: */
1570 if (comAttachment.GetType() == enmDeviceType)
1571 {
1572 /* Append storage slot to corresponding list: */
1573 if (comAttachment.GetMedium().isNull())
1574 aFreeStorageSlots << ExactStorageSlot(comController.GetName(), comController.GetBus(),
1575 comAttachment.GetPort(), comAttachment.GetDevice());
1576 else
1577 aBusyStorageSlots << ExactStorageSlot(comController.GetName(), comController.GetBus(),
1578 comAttachment.GetPort(), comAttachment.GetDevice());
1579 }
1580 }
1581 }
1582
1583 /* Make sure at least one storage slot found: */
1584 QList<ExactStorageSlot> sStorageSlots = aFreeStorageSlots + aBusyStorageSlots;
1585 if (sStorageSlots.isEmpty())
1586 {
1587 UINotificationMessage::cannotMountImage(machineName(), strMediumName);
1588 return false;
1589 }
1590
1591 /* Try to mount medium into first available storage slot: */
1592 while (!sStorageSlots.isEmpty())
1593 {
1594 const ExactStorageSlot storageSlot = sStorageSlots.takeFirst();
1595 machine().MountMedium(storageSlot.controller, storageSlot.port, storageSlot.device, guiMedium.medium(), false /* force */);
1596 if (machine().isOk())
1597 break;
1598 }
1599
1600 /* Show error message if necessary: */
1601 if (!machine().isOk())
1602 {
1603 msgCenter().cannotRemountMedium(machine(), guiMedium, true /* mount? */, false /* retry? */, activeMachineWindow());
1604 return false;
1605 }
1606
1607 /* Save machine settings: */
1608 machine().SaveSettings();
1609
1610 /* Show error message if necessary: */
1611 if (!machine().isOk())
1612 {
1613 UINotificationMessage::cannotSaveMachineSettings(machine());
1614 return false;
1615 }
1616
1617 /* True by default: */
1618 return true;
1619}
1620
1621void UISession::recacheMachineMedia()
1622{
1623 /* Compose a list of machine media: */
1624 CMediumVector comMedia;
1625
1626 /* Enumerate all the controllers: */
1627 foreach (const CStorageController &comController, machine().GetStorageControllers())
1628 {
1629 /* Enumerate all the attachments: */
1630 foreach (const CMediumAttachment &comAttachment, machine().GetMediumAttachmentsOfController(comController.GetName()))
1631 {
1632 /* Skip unrelated device types: */
1633 const KDeviceType enmDeviceType = comAttachment.GetType();
1634 if ( enmDeviceType != KDeviceType_HardDisk
1635 && enmDeviceType != KDeviceType_Floppy
1636 && enmDeviceType != KDeviceType_DVD)
1637 continue;
1638 if ( comAttachment.GetIsEjected()
1639 || comAttachment.GetMedium().isNull())
1640 continue;
1641 comMedia.append(comAttachment.GetMedium());
1642 }
1643 }
1644
1645 /* Start media enumeration: */
1646 uiCommon().enumerateMedia(comMedia);
1647}
1648
1649#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
1650/**
1651 * Custom signal handler. When switching VTs, we might not get release events
1652 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will
1653 * be saved with modifier keys stuck. This is annoying enough for introducing
1654 * this hack.
1655 */
1656/* static */
1657static void signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */)
1658{
1659 /* Only SIGUSR1 is interesting: */
1660 if (sig == SIGUSR1)
1661 if (gpMachine)
1662 gpMachine->machineLogic()->keyboardHandler()->releaseAllPressedKeys();
1663}
1664#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