VirtualBox

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

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

FE/Qt: bugref:8200: Runtime UI: Stability fix for PowerUp procedure: Using actual machine state instead of cached one when necessary.

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