VirtualBox

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

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

FE/Qt: bugref:10322: Runtime UI: Reworking CConsole wrapper usage step-by-step; This one is about webcams stuff.

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