VirtualBox

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

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

FE/Qt: Runtime UI: A bit more logging regarding GA state change events.

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