VirtualBox

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

Last change on this file since 59816 was 59816, checked in by vboxsync, 9 years ago

FE/Qt: 7340: Runtime UI: Potential crash fix for r93191.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 72.8 KB
Line 
1/* $Id: UISession.cpp 59816 2016-02-25 14:38:22Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UISession class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifdef VBOX_WITH_PRECOMPILED_HEADERS
19# include <precomp.h>
20#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
21
22/* Qt includes: */
23# include <QApplication>
24# include <QDesktopWidget>
25# include <QWidget>
26# ifdef Q_WS_MAC
27# include <QTimer>
28# endif /* Q_WS_MAC */
29
30/* GUI includes: */
31# include "VBoxGlobal.h"
32# include "UIExtraDataManager.h"
33# include "UISession.h"
34# include "UIMachine.h"
35# include "UIMedium.h"
36# include "UIActionPoolRuntime.h"
37# include "UIMachineLogic.h"
38# include "UIMachineView.h"
39# include "UIMachineWindow.h"
40# include "UIMessageCenter.h"
41# include "UIPopupCenter.h"
42# include "UIWizardFirstRun.h"
43# include "UIConsoleEventHandler.h"
44# include "UIFrameBuffer.h"
45# include "UISettingsDialogSpecific.h"
46# ifdef VBOX_WITH_VIDEOHWACCEL
47# include "VBoxFBOverlay.h"
48# endif /* VBOX_WITH_VIDEOHWACCEL */
49# ifdef Q_WS_MAC
50# include "UIMenuBar.h"
51# include "VBoxUtils-darwin.h"
52# endif /* Q_WS_MAC */
53
54# ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
55# include "UIKeyboardHandler.h"
56# include <signal.h>
57# endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
58
59/* COM includes: */
60# include "CSystemProperties.h"
61# include "CStorageController.h"
62# include "CMediumAttachment.h"
63# include "CNetworkAdapter.h"
64# include "CHostNetworkInterface.h"
65# include "CVRDEServer.h"
66# include "CUSBController.h"
67# include "CUSBDeviceFilters.h"
68# include "CHostVideoInputDevice.h"
69# include "CSnapshot.h"
70# include "CMedium.h"
71
72#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
73
74/* Qt includes: */
75#ifdef Q_WS_WIN
76# if QT_VERSION >= 0x050000
77# include <QtWin>
78# endif /* QT_VERSION >= 0x050000 */
79#endif /* Q_WS_WIN */
80
81#ifdef Q_WS_X11
82# include <QX11Info>
83# include <X11/Xlib.h>
84# include <X11/Xutil.h>
85#endif /* Q_WS_X11 */
86
87#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
88static void signalHandlerSIGUSR1(int sig, siginfo_t *, void *);
89#endif
90
91#ifdef Q_WS_MAC
92/**
93 * MacOS X: Application Services: Core Graphics: Display reconfiguration callback.
94 *
95 * Notifies UISession about @a display configuration change.
96 * Corresponding change described by Core Graphics @a flags.
97 * Uses UISession @a pHandler to process this change.
98 *
99 * @note Last argument (@a pHandler) must always be valid pointer to UISession object.
100 * @note Calls for UISession::sltHandleHostDisplayAboutToChange() slot if display configuration changed.
101 */
102void cgDisplayReconfigurationCallback(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *pHandler)
103{
104 /* Which flags we are handling? */
105 int iHandledFlags = kCGDisplayAddFlag /* display added */
106 | kCGDisplayRemoveFlag /* display removed */
107 | kCGDisplaySetModeFlag /* display mode changed */;
108
109 /* Handle 'display-add' case: */
110 if (flags & kCGDisplayAddFlag)
111 LogRelFlow(("GUI: UISession::cgDisplayReconfigurationCallback: Display added.\n"));
112 /* Handle 'display-remove' case: */
113 else if (flags & kCGDisplayRemoveFlag)
114 LogRelFlow(("GUI: UISession::cgDisplayReconfigurationCallback: Display removed.\n"));
115 /* Handle 'mode-set' case: */
116 else if (flags & kCGDisplaySetModeFlag)
117 LogRelFlow(("GUI: UISession::cgDisplayReconfigurationCallback: Display mode changed.\n"));
118
119 /* Ask handler to process our callback: */
120 if (flags & iHandledFlags)
121 QTimer::singleShot(0, static_cast<UISession*>(pHandler),
122 SLOT(sltHandleHostDisplayAboutToChange()));
123
124 Q_UNUSED(display);
125}
126#endif /* Q_WS_MAC */
127
128/* static */
129bool UISession::create(UISession *&pSession, UIMachine *pMachine)
130{
131 /* Make sure null pointer passed: */
132 AssertReturn(pSession == 0, false);
133
134 /* Create session UI: */
135 pSession = new UISession(pMachine);
136 /* Make sure it's prepared: */
137 if (!pSession->prepare())
138 {
139 /* Destroy session UI otherwise: */
140 destroy(pSession);
141 /* False in that case: */
142 return false;
143 }
144 /* True by default: */
145 return true;
146}
147
148/* static */
149void UISession::destroy(UISession *&pSession)
150{
151 /* Make sure valid pointer passed: */
152 AssertReturnVoid(pSession != 0);
153
154 /* Cleanup session UI: */
155 pSession->cleanup();
156 /* Destroy session: */
157 delete pSession;
158 pSession = 0;
159}
160
161bool UISession::initialize()
162{
163 /* Preprocess initialization: */
164 if (!preprocessInitialization())
165 return false;
166
167 /* Notify user about mouse&keyboard auto-capturing: */
168 if (vboxGlobal().settings().autoCapture())
169 popupCenter().remindAboutAutoCapture(machineLogic()->activeMachineWindow());
170
171 /* Check if we are in teleportation waiting mode.
172 * In that case no first run wizard is necessary. */
173 m_machineState = machine().GetState();
174 if ( isFirstTimeStarted()
175 && !(( m_machineState == KMachineState_PoweredOff
176 || m_machineState == KMachineState_Aborted
177 || m_machineState == KMachineState_Teleported)
178 && machine().GetTeleporterEnabled()))
179 {
180 UISafePointerWizard pWizard = new UIWizardFirstRun(mainMachineWindow(), machine());
181 pWizard->prepare();
182 pWizard->exec();
183 if (pWizard)
184 delete pWizard;
185 }
186
187 /* Apply debug settings from the command line. */
188 if (!debugger().isNull() && debugger().isOk())
189 {
190 if (vboxGlobal().isPatmDisabled())
191 debugger().SetPATMEnabled(false);
192 if (vboxGlobal().isCsamDisabled())
193 debugger().SetCSAMEnabled(false);
194 if (vboxGlobal().isSupervisorCodeExecedRecompiled())
195 debugger().SetRecompileSupervisor(true);
196 if (vboxGlobal().isUserCodeExecedRecompiled())
197 debugger().SetRecompileUser(true);
198 if (vboxGlobal().areWeToExecuteAllInIem())
199 debugger().SetExecuteAllInIEM(true);
200 if (!vboxGlobal().isDefaultWarpPct())
201 debugger().SetVirtualTimeRate(vboxGlobal().getWarpPct());
202 }
203
204 /* Apply ad-hoc reconfigurations from the command line: */
205 if (vboxGlobal().hasFloppyImageToMount())
206 mountAdHocImage(KDeviceType_Floppy, UIMediumType_Floppy, vboxGlobal().getFloppyImage());
207 if (vboxGlobal().hasDvdImageToMount())
208 mountAdHocImage(KDeviceType_DVD, UIMediumType_DVD, vboxGlobal().getDvdImage());
209
210 /* Power UP if this is NOT separate process: */
211 if (!vboxGlobal().isSeparateProcess())
212 if (!powerUp())
213 return false;
214
215 /* Check if we missed a really quick termination after successful startup: */
216 if (isTurnedOff())
217 return false;
218
219 /* Postprocess initialization: */
220 if (!postprocessInitialization())
221 return false;
222
223 /* Fetch corresponding states: */
224 if (vboxGlobal().isSeparateProcess())
225 {
226 m_fIsMouseSupportsAbsolute = mouse().GetAbsoluteSupported();
227 m_fIsMouseSupportsRelative = mouse().GetRelativeSupported();
228 m_fIsMouseSupportsMultiTouch = mouse().GetMultiTouchSupported();
229 m_fIsMouseHostCursorNeeded = mouse().GetNeedsHostCursor();
230 sltAdditionsChange();
231 }
232 machineLogic()->initializePostPowerUp();
233
234 /* Load VM settings: */
235 loadVMSettings();
236
237#ifdef VBOX_WITH_VIDEOHWACCEL
238 /* Log whether 2D video acceleration is enabled: */
239 LogRel(("GUI: 2D video acceleration is %s\n",
240 machine().GetAccelerate2DVideoEnabled() && VBoxGlobal::isAcceleration2DVideoAvailable()
241 ? "enabled" : "disabled"));
242#endif /* VBOX_WITH_VIDEOHWACCEL */
243
244/* Log whether HID LEDs sync is enabled: */
245#if defined(Q_WS_MAC) || defined(Q_WS_WIN)
246 LogRel(("GUI: HID LEDs sync is %s\n",
247 uimachine()->machineLogic()->isHidLedsSyncEnabled()
248 ? "enabled" : "disabled"));
249#else /* !Q_WS_MAC && !Q_WS_WIN */
250 LogRel(("GUI: HID LEDs sync is not supported on this platform\n"));
251#endif /* !Q_WS_MAC && !Q_WS_WIN */
252
253#ifdef VBOX_GUI_WITH_PIDFILE
254 vboxGlobal().createPidfile();
255#endif /* VBOX_GUI_WITH_PIDFILE */
256
257 /* Warn listeners about we are initialized: */
258 emit sigInitialized();
259
260 /* True by default: */
261 return true;
262}
263
264bool UISession::powerUp()
265{
266 /* Power UP machine: */
267 CProgress progress = vboxGlobal().shouldStartPaused() ? console().PowerUpPaused() : console().PowerUp();
268
269 /* Check for immediate failure: */
270 if (!console().isOk() || progress.isNull())
271 {
272 if (vboxGlobal().showStartVMErrors())
273 msgCenter().cannotStartMachine(console(), machineName());
274 return false;
275 }
276
277 /* Enable 'manual-override',
278 * preventing automatic Runtime UI closing
279 * and visual representation mode changes: */
280 if (machineLogic())
281 machineLogic()->setManualOverrideMode(true);
282
283 /* Show "Starting/Restoring" progress dialog: */
284 if (isSaved())
285 {
286 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_restore_90px.png", 0, 0);
287 /* After restoring from 'saved' state, machine-window(s) geometry should be adjusted: */
288 machineLogic()->adjustMachineWindowsGeometry();
289 }
290 else
291 {
292 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_start_90px.png");
293 /* After VM start, machine-window(s) size-hint(s) should be sent: */
294 machineLogic()->sendMachineWindowsSizeHints();
295 }
296
297 /* Check for progress failure: */
298 if (!progress.isOk() || progress.GetResultCode() != 0)
299 {
300 if (vboxGlobal().showStartVMErrors())
301 msgCenter().cannotStartMachine(progress, machineName());
302 return false;
303 }
304
305 /* Disable 'manual-override' finally: */
306 if (machineLogic())
307 machineLogic()->setManualOverrideMode(false);
308
309 /* True by default: */
310 return true;
311}
312
313bool UISession::saveState()
314{
315 /* Prepare the saving progress: */
316 CProgress progress = machine().SaveState();
317 if (machine().isOk())
318 {
319 /* Show the saving progress: */
320 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_save_90px.png");
321 if (!progress.isOk() || progress.GetResultCode() != 0)
322 {
323 /* Failed in progress: */
324 msgCenter().cannotSaveMachineState(progress, machineName());
325 return false;
326 }
327 }
328 else
329 {
330 /* Failed in console: */
331 msgCenter().cannotSaveMachineState(machine());
332 return false;
333 }
334 /* Passed: */
335 return true;
336}
337
338bool UISession::shutdown()
339{
340 /* Send ACPI shutdown signal if possible: */
341 console().PowerButton();
342 if (!console().isOk())
343 {
344 /* Failed in console: */
345 msgCenter().cannotACPIShutdownMachine(console());
346 return false;
347 }
348 /* Passed: */
349 return true;
350}
351
352bool UISession::powerOff(bool fIncludingDiscard, bool &fServerCrashed)
353{
354 /* Prepare the power-off progress: */
355 CProgress progress = console().PowerDown();
356 if (console().isOk())
357 {
358 /* Show the power-off progress: */
359 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_poweroff_90px.png");
360 if (progress.isOk() && progress.GetResultCode() == 0)
361 {
362 /* Discard the current state if requested: */
363 if (fIncludingDiscard)
364 return restoreCurrentSnapshot();
365 }
366 else
367 {
368 /* Failed in progress: */
369 msgCenter().cannotPowerDownMachine(progress, machineName());
370 return false;
371 }
372 }
373 else
374 {
375 /* Check the machine state, it might be already gone: */
376 if (!console().isNull())
377 {
378 /* Failed in console: */
379 COMResult res(console());
380 /* This can happen if VBoxSVC is not running: */
381 if (FAILED_DEAD_INTERFACE(res.rc()))
382 fServerCrashed = true;
383 else
384 msgCenter().cannotPowerDownMachine(console());
385 return false;
386 }
387 }
388 /* Passed: */
389 return true;
390}
391
392bool UISession::restoreCurrentSnapshot()
393{
394 /* Prepare result: */
395 bool fResult = false;
396
397 /* Simulate try-catch block: */
398 do
399 {
400 /* Search for corresponding VM: */
401 CVirtualBox vbox = vboxGlobal().virtualBox();
402 const QString strMachineID = vboxGlobal().managedVMUuid();
403 const CMachine mach = vbox.FindMachine(strMachineID);
404 if (!vbox.isOk() || mach.isNull())
405 {
406 /* Unable to find VM: */
407 msgCenter().cannotFindMachineById(vbox, strMachineID);
408 break;
409 }
410
411 /* Open a direct session to modify that VM: */
412 CSession sess = vboxGlobal().openSession(vboxGlobal().managedVMUuid(),
413 vboxGlobal().isSeparateProcess()
414 ? KLockType_Write : KLockType_Shared);
415 if (sess.isNull())
416 {
417 /* Unable to open session: */
418 break;
419 }
420
421 /* Simulate try-catch block: */
422 do
423 {
424 /* Acquire machine for this session: */
425 CMachine machine = sess.GetMachine();
426 if (machine.isNull())
427 {
428 /* Unable to acquire machine: */
429 break;
430 }
431
432 /* Prepare the snapshot-discard progress: */
433 const CSnapshot snap = machine.GetCurrentSnapshot();
434 CProgress prog = machine.RestoreSnapshot(snap);
435 if (!machine.isOk() || prog.isNull())
436 {
437 /* Unable to restore snapshot: */
438 msgCenter().cannotRestoreSnapshot(machine, snap.GetName(), machineName());
439 break;
440 }
441
442 /* Show the snapshot-discard progress: */
443 msgCenter().showModalProgressDialog(prog, machine.GetName(), ":/progress_snapshot_discard_90px.png");
444 if (prog.GetResultCode() != 0)
445 {
446 /* Unable to restore snapshot: */
447 msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), machine.GetName());
448 break;
449 }
450
451 /* Success: */
452 fResult = true;
453 }
454 while (0);
455
456 /* Unlock machine finally: */
457 sess.UnlockMachine();
458 }
459 while (0);
460
461 /* Return result: */
462 return fResult;
463}
464
465UIMachineLogic* UISession::machineLogic() const
466{
467 return uimachine() ? uimachine()->machineLogic() : 0;
468}
469
470QWidget* UISession::mainMachineWindow() const
471{
472 return machineLogic() ? machineLogic()->mainMachineWindow() : 0;
473}
474
475bool UISession::isVisualStateAllowed(UIVisualStateType state) const
476{
477 return m_pMachine->isVisualStateAllowed(state);
478}
479
480void UISession::changeVisualState(UIVisualStateType visualStateType)
481{
482 m_pMachine->asyncChangeVisualState(visualStateType);
483}
484
485bool UISession::setPause(bool fOn)
486{
487 if (fOn)
488 console().Pause();
489 else
490 console().Resume();
491
492 bool ok = console().isOk();
493 if (!ok)
494 {
495 if (fOn)
496 msgCenter().cannotPauseMachine(console());
497 else
498 msgCenter().cannotResumeMachine(console());
499 }
500
501 return ok;
502}
503
504void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
505{
506 /* This flag indicates whether we want to do the usual .ISO mounting or not.
507 * First try updating the Guest Additions directly without mounting the .ISO. */
508 bool fDoMount = false;
509
510 /* Auto-update in GUI currently is disabled. */
511#ifndef VBOX_WITH_ADDITIONS_AUTOUPDATE_UI
512 fDoMount = true;
513#else /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */
514 QVector<KAdditionsUpdateFlag> aFlagsUpdate;
515 QVector<QString> aArgs;
516 CProgress progressInstall = guest().UpdateGuestAdditions(strSource,
517 aArgs, aFlagsUpdate);
518 bool fResult = guest().isOk();
519 if (fResult)
520 {
521 msgCenter().showModalProgressDialog(progressInstall, tr("Updating Guest Additions"),
522 ":/progress_install_guest_additions_90px.png",
523 0, 500 /* 500ms delay. */);
524 if (progressInstall.GetCanceled())
525 return;
526
527 HRESULT rc = progressInstall.GetResultCode();
528 if (!progressInstall.isOk() || rc != S_OK)
529 {
530 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS
531 * simply isn't supported yet), so silently fall back to "old" .ISO
532 * mounting method. */
533 if ( !SUCCEEDED_WARNING(rc)
534 && rc != VBOX_E_NOT_SUPPORTED)
535 {
536 msgCenter().cannotUpdateGuestAdditions(progressInstall);
537
538 /* Log the error message in the release log. */
539 QString strErr = progressInstall.GetErrorInfo().GetText();
540 if (!strErr.isEmpty())
541 LogRel(("%s\n", strErr.toLatin1().constData()));
542 }
543 fDoMount = true; /* Since automatic updating failed, fall back to .ISO mounting. */
544 }
545 }
546#endif /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */
547
548 /* Do we still want mounting? */
549 if (!fDoMount)
550 return;
551
552 /* Open corresponding medium: */
553 QString strMediumID;
554 CVirtualBox vbox = vboxGlobal().virtualBox();
555 CMedium image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite, false /* fForceNewUuid */);
556 if (vbox.isOk() && !image.isNull())
557 strMediumID = image.GetId();
558 else
559 {
560 msgCenter().cannotOpenMedium(vbox, UIMediumType_DVD, strSource, mainMachineWindow());
561 return;
562 }
563
564 /* Make sure GA medium ID is valid: */
565 AssertReturnVoid(!strMediumID.isNull());
566
567 /* Searching for the first suitable controller/slot: */
568 QString strControllerName;
569 LONG iCntPort = -1, iCntDevice = -1;
570 foreach (const CStorageController &controller, machine().GetStorageControllers())
571 {
572 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachmentsOfController(controller.GetName()))
573 {
574 if (attachment.GetType() == KDeviceType_DVD)
575 {
576 strControllerName = controller.GetName();
577 iCntPort = attachment.GetPort();
578 iCntDevice = attachment.GetDevice();
579 break;
580 }
581 }
582 if (!strControllerName.isNull())
583 break;
584 }
585
586 /* Make sure suitable controller/slot were found: */
587 if (strControllerName.isNull())
588 {
589 msgCenter().cannotMountGuestAdditions(machineName());
590 return;
591 }
592
593 /* Try to find UIMedium among cached: */
594 UIMedium medium = vboxGlobal().medium(strMediumID);
595 if (medium.isNull())
596 {
597 /* Create new one if necessary: */
598 medium = UIMedium(image, UIMediumType_DVD, KMediumState_Created);
599 vboxGlobal().createMedium(medium);
600 }
601
602 /* Mount medium to corresponding controller/slot: */
603 machine().MountMedium(strControllerName, iCntPort, iCntDevice, medium.medium(), false /* force */);
604 if (!machine().isOk())
605 {
606 /* Ask for force mounting: */
607 if (msgCenter().cannotRemountMedium(machine(), medium, true /* mount? */,
608 true /* retry? */, mainMachineWindow()))
609 {
610 /* Force mount medium to the predefined port/device: */
611 machine().MountMedium(strControllerName, iCntPort, iCntDevice, medium.medium(), true /* force */);
612 if (!machine().isOk())
613 msgCenter().cannotRemountMedium(machine(), medium, true /* mount? */,
614 false /* retry? */, mainMachineWindow());
615 }
616 }
617}
618
619void UISession::sltCloseRuntimeUI()
620{
621 /* Ask UIMachine to close Runtime UI: */
622 uimachine()->closeRuntimeUI();
623}
624
625#ifdef RT_OS_DARWIN
626void UISession::sltHandleMenuBarConfigurationChange(const QString &strMachineID)
627{
628 /* Skip unrelated machine IDs: */
629 if (vboxGlobal().managedVMUuid() != strMachineID)
630 return;
631
632 /* Update Mac OS X menu-bar: */
633 updateMenu();
634}
635#endif /* RT_OS_DARWIN */
636
637void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape)
638{
639 /* In case of shape data is present: */
640 if (shape.size() > 0)
641 {
642 /* We are ignoring visibility flag: */
643 m_fIsHidingHostPointer = false;
644
645 /* And updating current cursor shape: */
646 setPointerShape(shape.data(), fAlpha,
647 hotCorner.x(), hotCorner.y(),
648 size.width(), size.height());
649 }
650 /* In case of shape data is NOT present: */
651 else
652 {
653 /* Remember if we should hide the cursor: */
654 m_fIsHidingHostPointer = !fVisible;
655 }
656
657 /* Notify listeners about mouse capability changed: */
658 emit sigMousePointerShapeChange();
659
660}
661
662void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fSupportsMultiTouch, bool fNeedsHostCursor)
663{
664 LogRelFlow(("GUI: UISession::sltMouseCapabilityChange: "
665 "Supports absolute: %s, Supports relative: %s, "
666 "Supports multi-touch: %s, Needs host cursor: %s\n",
667 fSupportsAbsolute ? "TRUE" : "FALSE", fSupportsRelative ? "TRUE" : "FALSE",
668 fSupportsMultiTouch ? "TRUE" : "FALSE", fNeedsHostCursor ? "TRUE" : "FALSE"));
669
670 /* Check if something had changed: */
671 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute
672 || m_fIsMouseSupportsRelative != fSupportsRelative
673 || m_fIsMouseSupportsMultiTouch != fSupportsMultiTouch
674 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor)
675 {
676 /* Store new data: */
677 m_fIsMouseSupportsAbsolute = fSupportsAbsolute;
678 m_fIsMouseSupportsRelative = fSupportsRelative;
679 m_fIsMouseSupportsMultiTouch = fSupportsMultiTouch;
680 m_fIsMouseHostCursorNeeded = fNeedsHostCursor;
681
682 /* Notify listeners about mouse capability changed: */
683 emit sigMouseCapabilityChange();
684 }
685}
686
687void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock)
688{
689 /* Check if something had changed: */
690 if ( m_fNumLock != fNumLock
691 || m_fCapsLock != fCapsLock
692 || m_fScrollLock != fScrollLock)
693 {
694 /* Store new num lock data: */
695 if (m_fNumLock != fNumLock)
696 {
697 m_fNumLock = fNumLock;
698 m_uNumLockAdaptionCnt = 2;
699 }
700
701 /* Store new caps lock data: */
702 if (m_fCapsLock != fCapsLock)
703 {
704 m_fCapsLock = fCapsLock;
705 m_uCapsLockAdaptionCnt = 2;
706 }
707
708 /* Store new scroll lock data: */
709 if (m_fScrollLock != fScrollLock)
710 {
711 m_fScrollLock = fScrollLock;
712 }
713
714 /* Notify listeners about mouse capability changed: */
715 emit sigKeyboardLedsChange();
716 }
717}
718
719void UISession::sltStateChange(KMachineState state)
720{
721 /* Check if something had changed: */
722 if (m_machineState != state)
723 {
724 /* Store new data: */
725 m_machineStatePrevious = m_machineState;
726 m_machineState = state;
727
728 /* Notify listeners about machine state changed: */
729 emit sigMachineStateChange();
730 }
731}
732
733void UISession::sltVRDEChange()
734{
735 /* Make sure VRDE server is present: */
736 const CVRDEServer server = machine().GetVRDEServer();
737 AssertMsgReturnVoid(machine().isOk() && !server.isNull(),
738 ("VRDE server should NOT be null!\n"));
739
740 /* Check/Uncheck VRDE Server action depending on feature status: */
741 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(true);
742 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->setChecked(server.GetEnabled());
743 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(false);
744
745 /* Notify listeners about VRDE change: */
746 emit sigVRDEChange();
747}
748
749void UISession::sltVideoCaptureChange()
750{
751 /* Check/Uncheck Video Capture action depending on feature status: */
752 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(true);
753 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->setChecked(machine().GetVideoCaptureEnabled());
754 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(false);
755
756 /* Notify listeners about Video Capture change: */
757 emit sigVideoCaptureChange();
758}
759
760void UISession::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo)
761{
762 /* Ignore KGuestMonitorChangedEventType_NewOrigin change event: */
763 if (changeType == KGuestMonitorChangedEventType_NewOrigin)
764 return;
765 /* Ignore KGuestMonitorChangedEventType_Disabled event for primary screen: */
766 AssertMsg(countOfVisibleWindows() > 0, ("All machine windows are hidden!"));
767 if (changeType == KGuestMonitorChangedEventType_Disabled && uScreenId == 0)
768 return;
769
770 /* Process KGuestMonitorChangedEventType_Enabled change event: */
771 if ( !isScreenVisible(uScreenId)
772 && changeType == KGuestMonitorChangedEventType_Enabled)
773 setScreenVisible(uScreenId, true);
774 /* Process KGuestMonitorChangedEventType_Disabled change event: */
775 else if ( isScreenVisible(uScreenId)
776 && changeType == KGuestMonitorChangedEventType_Disabled)
777 setScreenVisible(uScreenId, false);
778
779 /* Notify listeners about the change: */
780 emit sigGuestMonitorChange(changeType, uScreenId, screenGeo);
781}
782
783void UISession::sltHandleStorageDeviceChange(const CMediumAttachment &attachment, bool fRemoved, bool fSilent)
784{
785 /* Update action restrictions: */
786 updateActionRestrictions();
787
788 /* Notify listeners about storage device change: */
789 emit sigStorageDeviceChange(attachment, fRemoved, fSilent);
790}
791
792#ifdef RT_OS_DARWIN
793/**
794 * MacOS X: Restarts display-reconfiguration watchdog timer from the beginning.
795 * @note Watchdog is trying to determine display reconfiguration in
796 * UISession::sltCheckIfHostDisplayChanged() slot every 500ms for 40 tries.
797 */
798void UISession::sltHandleHostDisplayAboutToChange()
799{
800 LogRelFlow(("GUI: UISession::sltHandleHostDisplayAboutToChange()\n"));
801
802 if (m_pWatchdogDisplayChange->isActive())
803 m_pWatchdogDisplayChange->stop();
804 m_pWatchdogDisplayChange->setProperty("tryNumber", 1);
805 m_pWatchdogDisplayChange->start();
806}
807
808/**
809 * MacOS X: Determines display reconfiguration.
810 * @note Calls for UISession::sltHandleHostScreenCountChange() if screen count changed.
811 * @note Calls for UISession::sltHandleHostScreenGeometryChange() if screen geometry changed.
812 */
813void UISession::sltCheckIfHostDisplayChanged()
814{
815 LogRelFlow(("GUI: UISession::sltCheckIfHostDisplayChanged()\n"));
816
817 /* Check if display count changed: */
818 if (vboxGlobal().screenCount() != m_hostScreens.size())
819 {
820 /* Reset watchdog: */
821 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
822 /* Notify listeners about screen-count changed: */
823 return sltHandleHostScreenCountChange();
824 }
825 else
826 {
827 /* Check if at least one display geometry changed: */
828 for (int iScreenIndex = 0; iScreenIndex < vboxGlobal().screenCount(); ++iScreenIndex)
829 {
830 if (vboxGlobal().screenGeometry(iScreenIndex) != m_hostScreens.at(iScreenIndex))
831 {
832 /* Reset watchdog: */
833 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
834 /* Notify listeners about screen-geometry changed: */
835 return sltHandleHostScreenGeometryChange();
836 }
837 }
838 }
839
840 /* Check if watchdog expired, restart if not: */
841 int cTryNumber = m_pWatchdogDisplayChange->property("tryNumber").toInt();
842 if (cTryNumber > 0 && cTryNumber < 40)
843 {
844 /* Restart watchdog again: */
845 m_pWatchdogDisplayChange->setProperty("tryNumber", ++cTryNumber);
846 m_pWatchdogDisplayChange->start();
847 }
848 else
849 {
850 /* Reset watchdog: */
851 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
852 }
853}
854#endif /* RT_OS_DARWIN */
855
856void UISession::sltHandleHostScreenCountChange()
857{
858 LogRelFlow(("GUI: UISession: Host-screen count changed.\n"));
859
860 /* Recache display data: */
861 updateHostScreenData();
862
863 /* Notify current machine-logic: */
864 emit sigHostScreenCountChange();
865}
866
867void UISession::sltHandleHostScreenGeometryChange()
868{
869 LogRelFlow(("GUI: UISession: Host-screen geometry changed.\n"));
870
871 /* Recache display data: */
872 updateHostScreenData();
873
874 /* Notify current machine-logic: */
875 emit sigHostScreenGeometryChange();
876}
877
878void UISession::sltHandleHostScreenAvailableAreaChange()
879{
880 LogRelFlow(("GUI: UISession: Host-screen available-area changed.\n"));
881
882 /* Notify current machine-logic: */
883 emit sigHostScreenAvailableAreaChange();
884}
885
886void UISession::sltAdditionsChange()
887{
888 /* Variable flags: */
889 ULONG ulGuestAdditionsRunLevel = guest().GetAdditionsRunLevel();
890 LONG64 lLastUpdatedIgnored;
891 bool fIsGuestSupportsGraphics = guest().GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored)
892 == KAdditionsFacilityStatus_Active;
893 bool fIsGuestSupportsSeamless = guest().GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored)
894 == KAdditionsFacilityStatus_Active;
895 /* Check if something had changed: */
896 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel ||
897 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
898 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
899 {
900 /* Store new data: */
901 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
902 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
903 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
904
905 /* Notify listeners about GA state really changed: */
906 LogRel(("GUI: UISession::sltAdditionsChange: GA state really changed, notifying listeners.\n"));
907 emit sigAdditionsStateActualChange();
908 }
909
910 /* Notify listeners about GA state change event came: */
911 LogRel(("GUI: UISession::sltAdditionsChange: GA state change event came, notifying listeners.\n"));
912 emit sigAdditionsStateChange();
913}
914
915UISession::UISession(UIMachine *pMachine)
916 : QObject(pMachine)
917 /* Base variables: */
918 , m_pMachine(pMachine)
919 , m_pActionPool(0)
920#ifdef Q_WS_MAC
921 , m_pMenuBar(0)
922#endif /* Q_WS_MAC */
923 /* Common variables: */
924 , m_machineStatePrevious(KMachineState_Null)
925 , m_machineState(KMachineState_Null)
926#ifndef Q_WS_MAC
927 , m_pMachineWindowIcon(0)
928#endif /* !Q_WS_MAC */
929 , m_requestedVisualStateType(UIVisualStateType_Invalid)
930#ifdef Q_WS_WIN
931 , m_alphaCursor(0)
932#endif /* Q_WS_WIN */
933#ifdef Q_WS_MAC
934 , m_pWatchdogDisplayChange(0)
935#endif /* Q_WS_MAC */
936 , m_defaultCloseAction(MachineCloseAction_Invalid)
937 , m_restrictedCloseActions(MachineCloseAction_Invalid)
938 , m_fAllCloseActionsRestricted(false)
939 /* Common flags: */
940 , m_fInitialized(false)
941 , m_fIsFirstTimeStarted(false)
942 , m_fIsGuestResizeIgnored(false)
943 , m_fIsAutoCaptureDisabled(false)
944 /* Guest additions flags: */
945 , m_ulGuestAdditionsRunLevel(0)
946 , m_fIsGuestSupportsGraphics(false)
947 , m_fIsGuestSupportsSeamless(false)
948 /* Mouse flags: */
949 , m_fNumLock(false)
950 , m_fCapsLock(false)
951 , m_fScrollLock(false)
952 , m_uNumLockAdaptionCnt(2)
953 , m_uCapsLockAdaptionCnt(2)
954 /* Mouse flags: */
955 , m_fIsMouseSupportsAbsolute(false)
956 , m_fIsMouseSupportsRelative(false)
957 , m_fIsMouseSupportsMultiTouch(false)
958 , m_fIsMouseHostCursorNeeded(false)
959 , m_fIsMouseCaptured(false)
960 , m_fIsMouseIntegrated(true)
961 , m_fIsValidPointerShapePresent(false)
962 , m_fIsHidingHostPointer(true)
963 /* CPU hardware virtualization features for VM: */
964 , m_fIsHWVirtExEnabled(false)
965 , m_fIsHWVirtExNestedPagingEnabled(false)
966 , m_fIsHWVirtExUXEnabled(false)
967 /* VM's effective paravirtualization provider: */
968 , m_paraVirtProvider(KParavirtProvider_None)
969{
970}
971
972UISession::~UISession()
973{
974}
975
976bool UISession::prepare()
977{
978 /* Prepare session: */
979 if (!prepareSession())
980 return false;
981
982 /* Prepare actions: */
983 prepareActions();
984
985 /* Prepare connections: */
986 prepareConnections();
987
988 /* Prepare console event-handlers: */
989 prepareConsoleEventHandlers();
990
991 /* Prepare screens: */
992 prepareScreens();
993
994 /* Prepare framebuffers: */
995 prepareFramebuffers();
996
997 /* Load settings: */
998 loadSessionSettings();
999
1000#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
1001 struct sigaction sa;
1002 sa.sa_sigaction = &signalHandlerSIGUSR1;
1003 sigemptyset(&sa.sa_mask);
1004 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1005 sigaction(SIGUSR1, &sa, NULL);
1006#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
1007
1008 /* True by default: */
1009 return true;
1010}
1011
1012bool UISession::prepareSession()
1013{
1014 /* Open session: */
1015 m_session = vboxGlobal().openSession(vboxGlobal().managedVMUuid(),
1016 vboxGlobal().isSeparateProcess()
1017 ? KLockType_Shared : KLockType_VM);
1018 if (m_session.isNull())
1019 return false;
1020
1021 /* Get machine: */
1022 m_machine = m_session.GetMachine();
1023 if (m_machine.isNull())
1024 return false;
1025
1026 /* Get console: */
1027 m_console = m_session.GetConsole();
1028 if (m_console.isNull())
1029 return false;
1030
1031 /* Get display: */
1032 m_display = m_console.GetDisplay();
1033 if (m_display.isNull())
1034 return false;
1035
1036 /* Get guest: */
1037 m_guest = m_console.GetGuest();
1038 if (m_guest.isNull())
1039 return false;
1040
1041 /* Get mouse: */
1042 m_mouse = m_console.GetMouse();
1043 if (m_mouse.isNull())
1044 return false;
1045
1046 /* Get keyboard: */
1047 m_keyboard = m_console.GetKeyboard();
1048 if (m_keyboard.isNull())
1049 return false;
1050
1051 /* Get debugger: */
1052 m_debugger = m_console.GetDebugger();
1053 if (m_debugger.isNull())
1054 return false;
1055
1056 /* Update machine-name: */
1057 m_strMachineName = machine().GetName();
1058
1059 /* Update machine-state: */
1060 m_machineState = machine().GetState();
1061
1062 /* True by default: */
1063 return true;
1064}
1065
1066void UISession::prepareActions()
1067{
1068 /* Create action-pool: */
1069 m_pActionPool = UIActionPool::create(UIActionPoolType_Runtime);
1070 AssertPtrReturnVoid(actionPool());
1071 {
1072 /* Configure action-pool: */
1073 actionPool()->toRuntime()->setSession(this);
1074
1075 /* Update action restrictions: */
1076 updateActionRestrictions();
1077
1078#ifdef Q_WS_MAC
1079 /* Create Mac OS X menu-bar: */
1080 m_pMenuBar = new UIMenuBar;
1081 AssertPtrReturnVoid(m_pMenuBar);
1082 {
1083 /* Configure Mac OS X menu-bar: */
1084 connect(gEDataManager, SIGNAL(sigMenuBarConfigurationChange(const QString&)),
1085 this, SLOT(sltHandleMenuBarConfigurationChange(const QString&)));
1086 /* Update Mac OS X menu-bar: */
1087 updateMenu();
1088 }
1089#endif /* Q_WS_MAC */
1090 }
1091}
1092
1093void UISession::prepareConnections()
1094{
1095 connect(this, SIGNAL(sigInitialized()), this, SLOT(sltMarkInitialized()));
1096
1097#ifdef Q_WS_MAC
1098 /* Install native display reconfiguration callback: */
1099 CGDisplayRegisterReconfigurationCallback(cgDisplayReconfigurationCallback, this);
1100#else /* !Q_WS_MAC */
1101 /* Install Qt display reconfiguration callbacks: */
1102 connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)),
1103 this, SLOT(sltHandleHostScreenCountChange()));
1104 connect(QApplication::desktop(), SIGNAL(resized(int)),
1105 this, SLOT(sltHandleHostScreenGeometryChange()));
1106 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)),
1107 this, SLOT(sltHandleHostScreenAvailableAreaChange()));
1108#endif /* !Q_WS_MAC */
1109}
1110
1111void UISession::prepareConsoleEventHandlers()
1112{
1113 /* Create console event-handler: */
1114 UIConsoleEventHandler::create(this);
1115
1116 /* Add console event connections: */
1117 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)),
1118 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)));
1119
1120 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool, bool)),
1121 this, SLOT(sltMouseCapabilityChange(bool, bool, bool, bool)));
1122
1123 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)),
1124 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool)));
1125
1126 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)),
1127 this, SLOT(sltStateChange(KMachineState)));
1128
1129 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()),
1130 this, SLOT(sltAdditionsChange()));
1131
1132 connect(gConsoleEvents, SIGNAL(sigVRDEChange()),
1133 this, SLOT(sltVRDEChange()));
1134
1135 connect(gConsoleEvents, SIGNAL(sigVideoCaptureChange()),
1136 this, SLOT(sltVideoCaptureChange()));
1137
1138 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)),
1139 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)));
1140
1141 connect(gConsoleEvents, SIGNAL(sigStorageDeviceChange(CMediumAttachment, bool, bool)),
1142 this, SLOT(sltHandleStorageDeviceChange(CMediumAttachment, bool, bool)));
1143
1144 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)),
1145 this, SIGNAL(sigMediumChange(CMediumAttachment)));
1146
1147 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()),
1148 this, SIGNAL(sigUSBControllerChange()));
1149
1150 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)),
1151 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)));
1152
1153 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()),
1154 this, SIGNAL(sigSharedFolderChange()));
1155
1156 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)),
1157 this, SIGNAL(sigRuntimeError(bool, QString, QString)));
1158
1159#ifdef Q_WS_MAC
1160 connect(gConsoleEvents, SIGNAL(sigShowWindow()),
1161 this, SIGNAL(sigShowWindows()), Qt::QueuedConnection);
1162#endif /* Q_WS_MAC */
1163
1164 connect(gConsoleEvents, SIGNAL(sigCPUExecutionCapChange()),
1165 this, SIGNAL(sigCPUExecutionCapChange()));
1166
1167 connect(gConsoleEvents, SIGNAL(sigGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)),
1168 this, SLOT(sltGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)));
1169}
1170
1171void UISession::prepareScreens()
1172{
1173 /* Recache display data: */
1174 updateHostScreenData();
1175
1176#ifdef Q_WS_MAC
1177 /* Prepare display-change watchdog: */
1178 m_pWatchdogDisplayChange = new QTimer(this);
1179 {
1180 m_pWatchdogDisplayChange->setInterval(500);
1181 m_pWatchdogDisplayChange->setSingleShot(true);
1182 connect(m_pWatchdogDisplayChange, SIGNAL(timeout()),
1183 this, SLOT(sltCheckIfHostDisplayChanged()));
1184 }
1185#endif /* Q_WS_MAC */
1186
1187 /* Prepare initial screen visibility status: */
1188 m_monitorVisibilityVector.resize(machine().GetMonitorCount());
1189 m_monitorVisibilityVector.fill(false);
1190 m_monitorVisibilityVector[0] = true;
1191
1192 /* Prepare empty last full-screen size vector: */
1193 m_monitorLastFullScreenSizeVector.resize(machine().GetMonitorCount());
1194 m_monitorLastFullScreenSizeVector.fill(QSize(-1, -1));
1195
1196 /* If machine is in 'saved' state: */
1197 if (isSaved())
1198 {
1199 /* Update screen visibility status from saved-state: */
1200 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1201 {
1202 BOOL fEnabled = true;
1203 ULONG uGuestOriginX = 0, uGuestOriginY = 0, uGuestWidth = 0, uGuestHeight = 0;
1204 machine().QuerySavedGuestScreenInfo(iScreenIndex,
1205 uGuestOriginX, uGuestOriginY,
1206 uGuestWidth, uGuestHeight, fEnabled);
1207 m_monitorVisibilityVector[iScreenIndex] = fEnabled;
1208 }
1209 /* And make sure at least one of them is visible (primary if others are hidden): */
1210 if (countOfVisibleWindows() < 1)
1211 m_monitorVisibilityVector[0] = true;
1212 }
1213 else if (vboxGlobal().isSeparateProcess())
1214 {
1215 /* Update screen visibility status from display directly: */
1216 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1217 {
1218 KGuestMonitorStatus enmStatus = KGuestMonitorStatus_Disabled;
1219 ULONG uGuestWidth = 0, uGuestHeight = 0, uBpp = 0;
1220 LONG iGuestOriginX = 0, iGuestOriginY = 0;
1221 display().GetScreenResolution(iScreenIndex,
1222 uGuestWidth, uGuestHeight, uBpp,
1223 iGuestOriginX, iGuestOriginY, enmStatus);
1224 m_monitorVisibilityVector[iScreenIndex] = (enmStatus == KGuestMonitorStatus_Enabled);
1225 }
1226 /* And make sure at least one of them is visible (primary if others are hidden): */
1227 if (countOfVisibleWindows() < 1)
1228 m_monitorVisibilityVector[0] = true;
1229 }
1230
1231 /* Prepare initial screen visibility status of host-desires.
1232 * This is mostly dummy initialization as host-desires should get updated later in multi-screen layout.
1233 * By default making host-desires same as facts. */
1234 m_monitorVisibilityVectorHostDesires.resize(machine().GetMonitorCount());
1235 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1236 m_monitorVisibilityVectorHostDesires[iScreenIndex] = m_monitorVisibilityVector[iScreenIndex];
1237}
1238
1239void UISession::prepareFramebuffers()
1240{
1241 /* Each framebuffer will be really prepared on first UIMachineView creation: */
1242 m_frameBufferVector.resize(machine().GetMonitorCount());
1243}
1244
1245void UISession::loadSessionSettings()
1246{
1247 /* Load extra-data settings: */
1248 {
1249 /* Get machine ID: */
1250 const QString strMachineID = vboxGlobal().managedVMUuid();
1251
1252#ifndef Q_WS_MAC
1253 /* Load/prepare user's machine-window icon: */
1254 QIcon icon;
1255 foreach (const QString &strIconName, gEDataManager->machineWindowIconNames(strMachineID))
1256 if (!strIconName.isEmpty() && QFile::exists(strIconName))
1257 icon.addFile(strIconName);
1258 if (!icon.isNull())
1259 m_pMachineWindowIcon = new QIcon(icon);
1260
1261 /* Load user's machine-window name postfix: */
1262 m_strMachineWindowNamePostfix = gEDataManager->machineWindowNamePostfix(strMachineID);
1263#endif /* !Q_WS_MAC */
1264
1265 /* Is there should be First RUN Wizard? */
1266 m_fIsFirstTimeStarted = gEDataManager->machineFirstTimeStarted(strMachineID);
1267
1268 /* Should guest autoresize? */
1269 QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize);
1270 pGuestAutoresizeSwitch->setChecked(gEDataManager->guestScreenAutoResizeEnabled(strMachineID));
1271
1272#ifndef Q_WS_MAC
1273 /* Menu-bar options: */
1274 {
1275 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noMenuBar");
1276 const bool fEnabledForMachine = gEDataManager->menuBarEnabled(strMachineID);
1277 const bool fEnabled = fEnabledGlobally && fEnabledForMachine;
1278 QAction *pActionMenuBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings);
1279 pActionMenuBarSettings->setEnabled(fEnabled);
1280 QAction *pActionMenuBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility);
1281 pActionMenuBarSwitch->blockSignals(true);
1282 pActionMenuBarSwitch->setChecked(fEnabled);
1283 pActionMenuBarSwitch->blockSignals(false);
1284 }
1285#endif /* !Q_WS_MAC */
1286
1287 /* Status-bar options: */
1288 {
1289 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noStatusBar");
1290 const bool fEnabledForMachine = gEDataManager->statusBarEnabled(strMachineID);
1291 const bool fEnabled = fEnabledGlobally && fEnabledForMachine;
1292 QAction *pActionStatusBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings);
1293 pActionStatusBarSettings->setEnabled(fEnabled);
1294 QAction *pActionStatusBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility);
1295 pActionStatusBarSwitch->blockSignals(true);
1296 pActionStatusBarSwitch->setChecked(fEnabled);
1297 pActionStatusBarSwitch->blockSignals(false);
1298 }
1299
1300 /* Input options: */
1301 actionPool()->action(UIActionIndexRT_M_Input_M_Mouse_T_Integration)->setChecked(isMouseIntegrated());
1302
1303 /* What is the default close action and the restricted are? */
1304 m_defaultCloseAction = gEDataManager->defaultMachineCloseAction(strMachineID);
1305 m_restrictedCloseActions = gEDataManager->restrictedMachineCloseActions(strMachineID);
1306 m_fAllCloseActionsRestricted = (!vboxGlobal().isSeparateProcess() || (m_restrictedCloseActions & MachineCloseAction_Detach))
1307 && (m_restrictedCloseActions & MachineCloseAction_SaveState)
1308 && (m_restrictedCloseActions & MachineCloseAction_Shutdown)
1309 && (m_restrictedCloseActions & MachineCloseAction_PowerOff);
1310 // Close VM Dialog hides PowerOff_RestoringSnapshot implicitly if PowerOff is hidden..
1311 // && (m_restrictedCloseActions & MachineCloseAction_PowerOff_RestoringSnapshot);
1312 }
1313}
1314
1315void UISession::saveSessionSettings()
1316{
1317 /* Save extra-data settings: */
1318 {
1319 /* Disable First RUN Wizard: */
1320 gEDataManager->setMachineFirstTimeStarted(false, vboxGlobal().managedVMUuid());
1321
1322 /* Remember if guest should autoresize: */
1323 if (actionPool())
1324 {
1325 const QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize);
1326 gEDataManager->setGuestScreenAutoResizeEnabled(pGuestAutoresizeSwitch->isChecked(), vboxGlobal().managedVMUuid());
1327 }
1328
1329#ifndef Q_WS_MAC
1330 /* Cleanup user's machine-window icon: */
1331 delete m_pMachineWindowIcon;
1332 m_pMachineWindowIcon = 0;
1333#endif /* !Q_WS_MAC */
1334 }
1335}
1336
1337void UISession::cleanupFramebuffers()
1338{
1339 /* Cleanup framebuffers finally: */
1340 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i)
1341 {
1342 UIFrameBuffer *pFrameBuffer = m_frameBufferVector[i];
1343 if (pFrameBuffer)
1344 {
1345 /* Mark framebuffer as unused: */
1346 pFrameBuffer->setMarkAsUnused(true);
1347 /* Detach framebuffer from Display: */
1348 pFrameBuffer->detach();
1349 /* Delete framebuffer reference: */
1350 delete pFrameBuffer;
1351 }
1352 }
1353 m_frameBufferVector.clear();
1354}
1355
1356void UISession::cleanupConsoleEventHandlers()
1357{
1358 /* Destroy console event-handler if necessary: */
1359 if (gConsoleEvents)
1360 UIConsoleEventHandler::destroy();
1361}
1362
1363void UISession::cleanupConnections()
1364{
1365#ifdef Q_WS_MAC
1366 /* Remove display reconfiguration callback: */
1367 CGDisplayRemoveReconfigurationCallback(cgDisplayReconfigurationCallback, this);
1368#endif /* Q_WS_MAC */
1369}
1370
1371void UISession::cleanupActions()
1372{
1373#ifdef Q_WS_MAC
1374 /* Destroy Mac OS X menu-bar: */
1375 delete m_pMenuBar;
1376 m_pMenuBar = 0;
1377#endif /* Q_WS_MAC */
1378
1379 /* Destroy action-pool if necessary: */
1380 if (actionPool())
1381 UIActionPool::destroy(actionPool());
1382}
1383
1384void UISession::cleanupSession()
1385{
1386 /* Detach debugger: */
1387 if (!m_debugger.isNull())
1388 m_debugger.detach();
1389
1390 /* Detach keyboard: */
1391 if (!m_keyboard.isNull())
1392 m_keyboard.detach();
1393
1394 /* Detach mouse: */
1395 if (!m_mouse.isNull())
1396 m_mouse.detach();
1397
1398 /* Detach guest: */
1399 if (!m_guest.isNull())
1400 m_guest.detach();
1401
1402 /* Detach display: */
1403 if (!m_display.isNull())
1404 m_display.detach();
1405
1406 /* Detach console: */
1407 if (!m_console.isNull())
1408 m_console.detach();
1409
1410 /* Detach machine: */
1411 if (!m_machine.isNull())
1412 m_machine.detach();
1413
1414 /* Close session: */
1415 if (!m_session.isNull() && vboxGlobal().isVBoxSVCAvailable())
1416 {
1417 m_session.UnlockMachine();
1418 m_session.detach();
1419 }
1420}
1421
1422void UISession::cleanup()
1423{
1424#ifdef Q_WS_WIN
1425 /* Destroy alpha cursor: */
1426 if (m_alphaCursor)
1427 DestroyIcon(m_alphaCursor);
1428#endif /* Q_WS_WIN */
1429
1430 /* Save settings: */
1431 saveSessionSettings();
1432
1433 /* Cleanup framebuffers: */
1434 cleanupFramebuffers();
1435
1436 /* Cleanup console event-handlers: */
1437 cleanupConsoleEventHandlers();
1438
1439 /* Cleanup connections: */
1440 cleanupConnections();
1441
1442 /* Cleanup actions: */
1443 cleanupActions();
1444
1445 /* Cleanup session: */
1446 cleanupSession();
1447}
1448
1449#ifdef Q_WS_MAC
1450void UISession::updateMenu()
1451{
1452 /* Rebuild Mac OS X menu-bar: */
1453 m_pMenuBar->clear();
1454 foreach (QMenu *pMenu, actionPool()->menus())
1455 {
1456 UIMenu *pMenuUI = qobject_cast<UIMenu*>(pMenu);
1457 if (!pMenuUI->isConsumable() || !pMenuUI->isConsumed())
1458 m_pMenuBar->addMenu(pMenuUI);
1459 if (pMenuUI->isConsumable() && !pMenuUI->isConsumed())
1460 pMenuUI->setConsumed(true);
1461 }
1462}
1463#endif /* Q_WS_MAC */
1464
1465WId UISession::winId() const
1466{
1467 return mainMachineWindow()->winId();
1468}
1469
1470/** Generate a BGRA bitmap which approximates a XOR/AND mouse pointer.
1471 *
1472 * Pixels which has 1 in the AND mask and not 0 in the XOR mask are replaced by
1473 * the inverted pixel and 8 surrounding pixels with the original color.
1474 * Fort example a white pixel (W) is replaced with a black (B) pixel:
1475 * WWW
1476 * W -> WBW
1477 * WWW
1478 * The surrounding pixels are written only if the corresponding source pixel
1479 * does not affect the screen, i.e. AND bit is 1 and XOR value is 0.
1480 */
1481static void renderCursorPixels(const uint32_t *pu32XOR, const uint8_t *pu8AND,
1482 uint32_t u32Width, uint32_t u32Height,
1483 uint32_t *pu32Pixels, uint32_t cbPixels)
1484{
1485 /* Output pixels set to 0 which allow to not write transparent pixels anymore. */
1486 memset(pu32Pixels, 0, cbPixels);
1487
1488 const uint32_t *pu32XORSrc = pu32XOR; /* Iterator for source XOR pixels. */
1489 const uint8_t *pu8ANDSrcLine = pu8AND; /* The current AND mask scanline. */
1490 uint32_t *pu32Dst = pu32Pixels; /* Iterator for all destination BGRA pixels. */
1491
1492 /* Some useful constants. */
1493 const int cbANDLine = ((int)u32Width + 7) / 8;
1494
1495 int y;
1496 for (y = 0; y < (int)u32Height; ++y)
1497 {
1498 int x;
1499 for (x = 0; x < (int)u32Width; ++x)
1500 {
1501 const uint32_t u32Pixel = *pu32XORSrc; /* Current pixel at (x,y) */
1502 const uint8_t *pu8ANDSrc = pu8ANDSrcLine + x / 8; /* Byte which containt current AND bit. */
1503
1504 if ((*pu8ANDSrc << (x % 8)) & 0x80)
1505 {
1506 if (u32Pixel)
1507 {
1508 const uint32_t u32PixelInverted = ~u32Pixel;
1509
1510 /* Scan neighbor pixels and assign them if they are transparent. */
1511 int dy;
1512 for (dy = -1; dy <= 1; ++dy)
1513 {
1514 const int yn = y + dy;
1515 if (yn < 0 || yn >= (int)u32Height)
1516 continue; /* Do not cross the bounds. */
1517
1518 int dx;
1519 for (dx = -1; dx <= 1; ++dx)
1520 {
1521 const int xn = x + dx;
1522 if (xn < 0 || xn >= (int)u32Width)
1523 continue; /* Do not cross the bounds. */
1524
1525 if (dx != 0 || dy != 0)
1526 {
1527 /* Check if the neighbor pixel is transparent. */
1528 const uint32_t *pu32XORNeighborSrc = &pu32XORSrc[dy * (int)u32Width + dx];
1529 const uint8_t *pu8ANDNeighborSrc = pu8ANDSrcLine + dy * cbANDLine + xn / 8;
1530 if ( *pu32XORNeighborSrc == 0
1531 && ((*pu8ANDNeighborSrc << (xn % 8)) & 0x80) != 0)
1532 {
1533 /* Transparent neighbor pixels are replaced with the source pixel value. */
1534 uint32_t *pu32PixelNeighborDst = &pu32Dst[dy * (int)u32Width + dx];
1535 *pu32PixelNeighborDst = u32Pixel | 0xFF000000;
1536 }
1537 }
1538 else
1539 {
1540 /* The pixel itself is replaced with inverted value. */
1541 *pu32Dst = u32PixelInverted | 0xFF000000;
1542 }
1543 }
1544 }
1545 }
1546 else
1547 {
1548 /* The pixel does not affect the screen.
1549 * Do nothing. Do not touch destination which can already contain generated pixels.
1550 */
1551 }
1552 }
1553 else
1554 {
1555 /* AND bit is 0, the pixel will be just drawn. */
1556 *pu32Dst = u32Pixel | 0xFF000000;
1557 }
1558
1559 ++pu32XORSrc; /* Next source pixel. */
1560 ++pu32Dst; /* Next destination pixel. */
1561 }
1562
1563 /* Next AND scanline. */
1564 pu8ANDSrcLine += cbANDLine;
1565 }
1566}
1567void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
1568 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
1569{
1570 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
1571
1572 m_fIsValidPointerShapePresent = false;
1573 const uchar *srcAndMaskPtr = pShapeData;
1574 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
1575 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
1576 uint srcShapePtrScan = uWidth * 4;
1577
1578#if defined (Q_WS_WIN)
1579
1580 BITMAPV5HEADER bi;
1581 HBITMAP hBitmap;
1582 void *lpBits;
1583
1584 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
1585 bi.bV5Size = sizeof(BITMAPV5HEADER);
1586 bi.bV5Width = uWidth;
1587 bi.bV5Height = - (LONG)uHeight;
1588 bi.bV5Planes = 1;
1589 bi.bV5BitCount = 32;
1590 bi.bV5Compression = BI_BITFIELDS;
1591 bi.bV5RedMask = 0x00FF0000;
1592 bi.bV5GreenMask = 0x0000FF00;
1593 bi.bV5BlueMask = 0x000000FF;
1594 if (fHasAlpha)
1595 bi.bV5AlphaMask = 0xFF000000;
1596 else
1597 bi.bV5AlphaMask = 0;
1598
1599 HDC hdc = GetDC(NULL);
1600
1601 /* Create the DIB section with an alpha channel: */
1602 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
1603
1604 ReleaseDC(NULL, hdc);
1605
1606 HBITMAP hMonoBitmap = NULL;
1607 if (fHasAlpha)
1608 {
1609 /* Create an empty mask bitmap: */
1610 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
1611 }
1612 else
1613 {
1614 /* Word aligned AND mask. Will be allocated and created if necessary. */
1615 uint8_t *pu8AndMaskWordAligned = NULL;
1616
1617 /* Width in bytes of the original AND mask scan line. */
1618 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
1619
1620 if (cbAndMaskScan & 1)
1621 {
1622 /* Original AND mask is not word aligned. */
1623
1624 /* Allocate memory for aligned AND mask. */
1625 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
1626
1627 Assert(pu8AndMaskWordAligned);
1628
1629 if (pu8AndMaskWordAligned)
1630 {
1631 /* According to MSDN the padding bits must be 0.
1632 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
1633 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
1634 Assert(u32PaddingBits < 8);
1635 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
1636
1637 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
1638 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
1639
1640 uint8_t *src = (uint8_t *)srcAndMaskPtr;
1641 uint8_t *dst = pu8AndMaskWordAligned;
1642
1643 unsigned i;
1644 for (i = 0; i < uHeight; i++)
1645 {
1646 memcpy(dst, src, cbAndMaskScan);
1647
1648 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
1649
1650 src += cbAndMaskScan;
1651 dst += cbAndMaskScan + 1;
1652 }
1653 }
1654 }
1655
1656 /* Create the AND mask bitmap: */
1657 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
1658 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
1659
1660 if (pu8AndMaskWordAligned)
1661 {
1662 RTMemTmpFree(pu8AndMaskWordAligned);
1663 }
1664 }
1665
1666 Assert(hBitmap);
1667 Assert(hMonoBitmap);
1668 if (hBitmap && hMonoBitmap)
1669 {
1670 DWORD *dstShapePtr = (DWORD *) lpBits;
1671
1672 for (uint y = 0; y < uHeight; y ++)
1673 {
1674 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
1675 srcShapePtr += srcShapePtrScan;
1676 dstShapePtr += uWidth;
1677 }
1678
1679 ICONINFO ii;
1680 ii.fIcon = FALSE;
1681 ii.xHotspot = uXHot;
1682 ii.yHotspot = uYHot;
1683 ii.hbmMask = hMonoBitmap;
1684 ii.hbmColor = hBitmap;
1685
1686 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
1687 Assert(hAlphaCursor);
1688 if (hAlphaCursor)
1689 {
1690 /* Set the new cursor: */
1691# if QT_VERSION < 0x050000
1692 m_cursor = QCursor(hAlphaCursor);
1693# else /* QT_VERSION >= 0x050000 */
1694 m_cursor = QCursor(QtWin::fromHBITMAP(hBitmap, QtWin::HBitmapAlpha), uXHot, uYHot);
1695# endif /* QT_VERSION >= 0x050000 */
1696 if (m_alphaCursor)
1697 DestroyIcon(m_alphaCursor);
1698 m_alphaCursor = hAlphaCursor;
1699 m_fIsValidPointerShapePresent = true;
1700 }
1701 }
1702
1703 if (hMonoBitmap)
1704 DeleteObject(hMonoBitmap);
1705 if (hBitmap)
1706 DeleteObject(hBitmap);
1707
1708#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
1709
1710 /* Create a ARGB image out of the shape data: */
1711 QImage image(uWidth, uHeight, QImage::Format_ARGB32);
1712
1713 if (fHasAlpha)
1714 {
1715 memcpy(image.bits(), srcShapePtr, uHeight * uWidth * 4);
1716 }
1717 else
1718 {
1719 renderCursorPixels((uint32_t *)srcShapePtr, srcAndMaskPtr,
1720 uWidth, uHeight,
1721 (uint32_t *)image.bits(), uHeight * uWidth * 4);
1722 }
1723
1724 /* Create cursor-pixmap from the image: */
1725 QPixmap cursorPixmap = QPixmap::fromImage(image);
1726# ifdef Q_WS_MAC
1727# ifdef VBOX_GUI_WITH_HIDPI
1728 /* Adjust backing-scale-factor: */
1729 // TODO: In case of multi-monitor setup check whether backing-scale factor and cursor are screen specific.
1730 /* Get screen-id of main-window: */
1731 const ulong uScreenID = machineLogic()->activeMachineWindow()->screenId();
1732 /* Get backing-scale-factor: */
1733 const double dBackingScaleFactor = frameBuffer(uScreenID)->backingScaleFactor();
1734 /* Adjust backing-scale-factor if necessary: */
1735 if (dBackingScaleFactor > 1.0 && frameBuffer(uScreenID)->useUnscaledHiDPIOutput())
1736 cursorPixmap.setDevicePixelRatio(dBackingScaleFactor);
1737# endif /* VBOX_GUI_WITH_HIDPI */
1738# endif /* Q_WS_MAC */
1739 /* Set the new cursor: */
1740 m_cursor = QCursor(cursorPixmap, uXHot, uYHot);
1741 m_fIsValidPointerShapePresent = true;
1742 NOREF(srcShapePtrScan);
1743
1744#else
1745
1746# warning "port me"
1747
1748#endif
1749}
1750
1751bool UISession::preprocessInitialization()
1752{
1753#ifdef VBOX_WITH_NETFLT
1754 /* Skip further checks if VM in saved state */
1755 if (isSaved())
1756 return true;
1757
1758 /* Make sure all the attached and enabled network
1759 * adapters are present on the host. This check makes sense
1760 * in two cases only - when attachement type is Bridged Network
1761 * or Host-only Interface. NOTE: Only currently enabled
1762 * attachement type is checked (incorrect parameters check for
1763 * currently disabled attachement types is skipped). */
1764 QStringList failedInterfaceNames;
1765 QStringList availableInterfaceNames;
1766
1767 /* Create host network interface names list */
1768 foreach (const CHostNetworkInterface &iface, vboxGlobal().host().GetNetworkInterfaces())
1769 {
1770 availableInterfaceNames << iface.GetName();
1771 availableInterfaceNames << iface.GetShortName();
1772 }
1773
1774 ulong cCount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine().GetChipsetType());
1775 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex)
1776 {
1777 CNetworkAdapter na = machine().GetNetworkAdapter(uAdapterIndex);
1778
1779 if (na.GetEnabled())
1780 {
1781 QString strIfName = QString();
1782
1783 /* Get physical network interface name for currently
1784 * enabled network attachement type */
1785 switch (na.GetAttachmentType())
1786 {
1787 case KNetworkAttachmentType_Bridged:
1788 strIfName = na.GetBridgedInterface();
1789 break;
1790 case KNetworkAttachmentType_HostOnly:
1791 strIfName = na.GetHostOnlyInterface();
1792 break;
1793 }
1794
1795 if (!strIfName.isEmpty() &&
1796 !availableInterfaceNames.contains(strIfName))
1797 {
1798 LogFlow(("Found invalid network interface: %s\n", strIfName.toStdString().c_str()));
1799 failedInterfaceNames << QString("%1 (adapter %2)").arg(strIfName).arg(uAdapterIndex + 1);
1800 }
1801 }
1802 }
1803
1804 /* Check if non-existent interfaces found */
1805 if (!failedInterfaceNames.isEmpty())
1806 {
1807 if (msgCenter().cannotStartWithoutNetworkIf(machineName(), failedInterfaceNames.join(", ")))
1808 machineLogic()->openNetworkSettingsDialog();
1809 else
1810 return false;
1811 }
1812#endif /* VBOX_WITH_NETFLT */
1813
1814 /* True by default: */
1815 return true;
1816}
1817
1818bool UISession::mountAdHocImage(KDeviceType enmDeviceType, UIMediumType enmMediumType, const QString &strImage)
1819{
1820 /* The 'none' image name means ejecting what ever is in the drive,
1821 * so leave the image variables null. */
1822 CVirtualBox vbox = vboxGlobal().virtualBox();
1823 UIMedium uiImage;
1824 if (strImage != "none")
1825 {
1826 /* Open the image: */
1827 CVirtualBox vbox = vboxGlobal().virtualBox();
1828 CMedium vboxImage = vbox.OpenMedium(strImage, enmDeviceType, KAccessMode_ReadWrite, false /* fForceNewUuid */);
1829 if (!vbox.isOk() || vboxImage.isNull())
1830 {
1831 msgCenter().cannotOpenMedium(vbox, enmMediumType, strImage);
1832 return false;
1833 }
1834
1835 /* Work the cache and use the cached image if possible: */
1836 uiImage = vboxGlobal().medium(vboxImage.GetId());
1837 if (uiImage.isNull())
1838 {
1839 uiImage = UIMedium(vboxImage, enmMediumType, KMediumState_Created);
1840 vboxGlobal().createMedium(uiImage);
1841 }
1842 }
1843 if (vbox.isOk())
1844 {
1845 /* Find suitable storage controller: */
1846 foreach (const CStorageController &controller, machine().GetStorageControllers())
1847 {
1848 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachmentsOfController(controller.GetName()))
1849 {
1850 if (attachment.GetType() == enmDeviceType)
1851 {
1852 /* Mount the image: */
1853 machine().MountMedium(controller.GetName(), attachment.GetPort(), attachment.GetDevice(), uiImage.medium(), true /* force */);
1854 if (machine().isOk())
1855 return true;
1856 msgCenter().cannotRemountMedium(machine(), uiImage, !uiImage.isNull() /* mount */, false /* retry */);
1857 return false;
1858 }
1859 }
1860 }
1861 msgCenter().cannotRemountMedium(machine(), uiImage, !uiImage.isNull() /* mount */, false /* retry */);
1862 }
1863 else
1864 msgCenter().cannotOpenMedium(vbox, enmMediumType, strImage);
1865 return false;
1866}
1867
1868bool UISession::postprocessInitialization()
1869{
1870 /* Check if the required virtualization features are active. We get this info only when the session is active. */
1871 const bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetIs64Bit();
1872 const bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetRecommendedVirtEx();
1873 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n"));
1874 const bool fIsVirtActive = debugger().GetHWVirtExEnabled();
1875 if (fRecommendVirtEx && !fIsVirtActive)
1876 {
1877 /* Check whether vt-x / amd-v supported: */
1878 bool fVTxAMDVSupported = vboxGlobal().host().GetProcessorFeature(KProcessorFeature_HWVirtEx);
1879
1880 /* Pause VM: */
1881 setPause(true);
1882
1883 /* Ask the user about further actions: */
1884 bool fShouldWeClose;
1885 if (fIs64BitsGuest)
1886 fShouldWeClose = msgCenter().warnAboutVirtExInactiveFor64BitsGuest(fVTxAMDVSupported);
1887 else
1888 fShouldWeClose = msgCenter().warnAboutVirtExInactiveForRecommendedGuest(fVTxAMDVSupported);
1889
1890 /* If user asked to close VM: */
1891 if (fShouldWeClose)
1892 {
1893 /* Enable 'manual-override',
1894 * preventing automatic Runtime UI closing: */
1895 if (machineLogic())
1896 machineLogic()->setManualOverrideMode(true);
1897 /* Power off VM: */
1898 bool fServerCrashed = false;
1899 powerOff(false, fServerCrashed);
1900 return false;
1901 }
1902
1903 /* Resume VM: */
1904 setPause(false);
1905 }
1906
1907 /* True by default: */
1908 return true;
1909}
1910
1911bool UISession::isScreenVisibleHostDesires(ulong uScreenId) const
1912{
1913 /* Make sure index feats the bounds: */
1914 AssertReturn(uScreenId < (ulong)m_monitorVisibilityVectorHostDesires.size(), false);
1915
1916 /* Return 'actual' (host-desire) visibility status: */
1917 return m_monitorVisibilityVectorHostDesires.value((int)uScreenId);
1918}
1919
1920void UISession::setScreenVisibleHostDesires(ulong uScreenId, bool fIsMonitorVisible)
1921{
1922 /* Make sure index feats the bounds: */
1923 AssertReturnVoid(uScreenId < (ulong)m_monitorVisibilityVectorHostDesires.size());
1924
1925 /* Remember 'actual' (host-desire) visibility status: */
1926 m_monitorVisibilityVectorHostDesires[(int)uScreenId] = fIsMonitorVisible;
1927}
1928
1929bool UISession::isScreenVisible(ulong uScreenId) const
1930{
1931 /* Make sure index feats the bounds: */
1932 AssertReturn(uScreenId < (ulong)m_monitorVisibilityVector.size(), false);
1933
1934 /* Return 'actual' visibility status: */
1935 return m_monitorVisibilityVector.value((int)uScreenId);
1936}
1937
1938void UISession::setScreenVisible(ulong uScreenId, bool fIsMonitorVisible)
1939{
1940 /* Make sure index feats the bounds: */
1941 AssertReturnVoid(uScreenId < (ulong)m_monitorVisibilityVector.size());
1942
1943 /* Remember 'actual' visibility status: */
1944 m_monitorVisibilityVector[(int)uScreenId] = fIsMonitorVisible;
1945 /* Remember 'desired' visibility status: */
1946 gEDataManager->setLastGuestScreenVisibilityStatus(uScreenId, fIsMonitorVisible, vboxGlobal().managedVMUuid());
1947}
1948
1949QSize UISession::lastFullScreenSize(ulong uScreenId) const
1950{
1951 /* Make sure index fits the bounds: */
1952 AssertReturn(uScreenId < (ulong)m_monitorLastFullScreenSizeVector.size(), QSize(-1, -1));
1953
1954 /* Return last full-screen size: */
1955 return m_monitorLastFullScreenSizeVector.value((int)uScreenId);
1956}
1957
1958void UISession::setLastFullScreenSize(ulong uScreenId, QSize size)
1959{
1960 /* Make sure index fits the bounds: */
1961 AssertReturnVoid(uScreenId < (ulong)m_monitorLastFullScreenSizeVector.size());
1962
1963 /* Remember last full-screen size: */
1964 m_monitorLastFullScreenSizeVector[(int)uScreenId] = size;
1965}
1966
1967int UISession::countOfVisibleWindows()
1968{
1969 int cCountOfVisibleWindows = 0;
1970 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i)
1971 if (m_monitorVisibilityVector[i])
1972 ++cCountOfVisibleWindows;
1973 return cCountOfVisibleWindows;
1974}
1975
1976void UISession::loadVMSettings()
1977{
1978 /* Load CPU hardware virtualization extension: */
1979 m_fIsHWVirtExEnabled = m_debugger.GetHWVirtExEnabled();
1980 /* Load nested-paging CPU hardware virtualization extension: */
1981 m_fIsHWVirtExNestedPagingEnabled = m_debugger.GetHWVirtExNestedPagingEnabled();
1982 /* Load whether the VM is currently making use of the unrestricted execution feature of VT-x: */
1983 m_fIsHWVirtExUXEnabled = m_debugger.GetHWVirtExUXEnabled();
1984 /* Load VM's effective paravirtualization provider: */
1985 m_paraVirtProvider = m_machine.GetEffectiveParavirtProvider();
1986}
1987
1988UIFrameBuffer* UISession::frameBuffer(ulong uScreenId) const
1989{
1990 Assert(uScreenId < (ulong)m_frameBufferVector.size());
1991 return m_frameBufferVector.value((int)uScreenId, 0);
1992}
1993
1994void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer* pFrameBuffer)
1995{
1996 Assert(uScreenId < (ulong)m_frameBufferVector.size());
1997 if (uScreenId < (ulong)m_frameBufferVector.size())
1998 m_frameBufferVector[(int)uScreenId] = pFrameBuffer;
1999}
2000
2001void UISession::updateHostScreenData()
2002{
2003 m_hostScreens.clear();
2004 for (int iScreenIndex = 0; iScreenIndex < vboxGlobal().screenCount(); ++iScreenIndex)
2005 m_hostScreens << vboxGlobal().screenGeometry(iScreenIndex);
2006}
2007
2008void UISession::updateActionRestrictions()
2009{
2010 /* Get host and prepare restrictions: */
2011 const CHost host = vboxGlobal().host();
2012 UIExtraDataMetaDefs::RuntimeMenuViewActionType restrictionForView = UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid;
2013 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType restrictionForDevices = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid;
2014
2015 /* VRDE server stuff: */
2016 {
2017 /* Initialize 'View' menu: */
2018 const CVRDEServer server = machine().GetVRDEServer();
2019 if (server.isNull())
2020 restrictionForView = (UIExtraDataMetaDefs::RuntimeMenuViewActionType)(restrictionForView | UIExtraDataMetaDefs::RuntimeMenuViewActionType_VRDEServer);
2021 }
2022
2023 /* Storage stuff: */
2024 {
2025 /* Initialize CD/FD menus: */
2026 int iDevicesCountCD = 0;
2027 int iDevicesCountFD = 0;
2028 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachments())
2029 {
2030 if (attachment.GetType() == KDeviceType_DVD)
2031 ++iDevicesCountCD;
2032 if (attachment.GetType() == KDeviceType_Floppy)
2033 ++iDevicesCountFD;
2034 }
2035 QAction *pOpticalDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_OpticalDevices);
2036 QAction *pFloppyDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_FloppyDevices);
2037 pOpticalDevicesMenu->setData(iDevicesCountCD);
2038 pFloppyDevicesMenu->setData(iDevicesCountFD);
2039 if (!iDevicesCountCD)
2040 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_OpticalDevices);
2041 if (!iDevicesCountFD)
2042 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_FloppyDevices);
2043 }
2044
2045 /* Network stuff: */
2046 {
2047 /* Initialize Network menu: */
2048 bool fAtLeastOneAdapterActive = false;
2049 const KChipsetType chipsetType = machine().GetChipsetType();
2050 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(chipsetType);
2051 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot)
2052 {
2053 const CNetworkAdapter &adapter = machine().GetNetworkAdapter(uSlot);
2054 if (adapter.GetEnabled())
2055 {
2056 fAtLeastOneAdapterActive = true;
2057 break;
2058 }
2059 }
2060 if (!fAtLeastOneAdapterActive)
2061 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Network);
2062 }
2063
2064 /* USB stuff: */
2065 {
2066 /* Check whether there is at least one USB controller with an available proxy. */
2067 const bool fUSBEnabled = !machine().GetUSBDeviceFilters().isNull()
2068 && !machine().GetUSBControllers().isEmpty()
2069 && machine().GetUSBProxyAvailable();
2070 if (!fUSBEnabled)
2071 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_USBDevices);
2072 }
2073
2074 /* WebCams stuff: */
2075 {
2076 /* Check whether there is an accessible video input devices pool: */
2077 host.GetVideoInputDevices();
2078 const bool fWebCamsEnabled = host.isOk() && !machine().GetUSBControllers().isEmpty();
2079 if (!fWebCamsEnabled)
2080 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_WebCams);
2081 }
2082
2083 /* Apply cumulative restriction for 'View' menu: */
2084 actionPool()->toRuntime()->setRestrictionForMenuView(UIActionRestrictionLevel_Session, restrictionForView);
2085 /* Apply cumulative restriction for 'Devices' menu: */
2086 actionPool()->toRuntime()->setRestrictionForMenuDevices(UIActionRestrictionLevel_Session, restrictionForDevices);
2087}
2088
2089#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
2090/**
2091 * Custom signal handler. When switching VTs, we might not get release events
2092 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will
2093 * be saved with modifier keys stuck. This is annoying enough for introducing
2094 * this hack.
2095 */
2096/* static */
2097static void signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */)
2098{
2099 /* Only SIGUSR1 is interesting: */
2100 if (sig == SIGUSR1)
2101 if (gpMachine)
2102 gpMachine->uisession()->machineLogic()->keyboardHandler()->releaseAllPressedKeys();
2103}
2104#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
2105
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