VirtualBox

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

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

FE/Qt: Small cleanup related to UIMachine.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 67.7 KB
Line 
1/* $Id: UISession.cpp 57805 2015-09-17 15:01:21Z 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 /* Check if display count changed: */
802 if (vboxGlobal().screenCount() != m_hostScreens.size())
803 {
804 /* Reset watchdog: */
805 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
806 /* Notify listeners about screen-count changed: */
807 return sltHandleHostScreenCountChange();
808 }
809 else
810 {
811 /* Check if at least one display geometry changed: */
812 for (int iScreenIndex = 0; iScreenIndex < vboxGlobal().screenCount(); ++iScreenIndex)
813 {
814 if (vboxGlobal().screenGeometry(iScreenIndex) != m_hostScreens.at(iScreenIndex))
815 {
816 /* Reset watchdog: */
817 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
818 /* Notify listeners about screen-geometry changed: */
819 return sltHandleHostScreenGeometryChange();
820 }
821 }
822 }
823
824 /* Check if watchdog expired, restart if not: */
825 int cTryNumber = m_pWatchdogDisplayChange->property("tryNumber").toInt();
826 if (cTryNumber > 0 && cTryNumber < 40)
827 {
828 /* Restart watchdog again: */
829 m_pWatchdogDisplayChange->setProperty("tryNumber", ++cTryNumber);
830 m_pWatchdogDisplayChange->start();
831 }
832 else
833 {
834 /* Reset watchdog: */
835 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
836 }
837}
838#endif /* RT_OS_DARWIN */
839
840void UISession::sltHandleHostScreenCountChange()
841{
842 LogRelFlow(("GUI: UISession: Host-screen count changed.\n"));
843
844 /* Recache display data: */
845 updateHostScreenData();
846
847 /* Notify current machine-logic: */
848 emit sigHostScreenCountChange();
849}
850
851void UISession::sltHandleHostScreenGeometryChange()
852{
853 LogRelFlow(("GUI: UISession: Host-screen geometry changed.\n"));
854
855 /* Recache display data: */
856 updateHostScreenData();
857
858 /* Notify current machine-logic: */
859 emit sigHostScreenGeometryChange();
860}
861
862void UISession::sltHandleHostScreenAvailableAreaChange()
863{
864 LogRelFlow(("GUI: UISession: Host-screen available-area changed.\n"));
865
866 /* Notify current machine-logic: */
867 emit sigHostScreenAvailableAreaChange();
868}
869
870void UISession::sltAdditionsChange()
871{
872 /* Variable flags: */
873 ULONG ulGuestAdditionsRunLevel = guest().GetAdditionsRunLevel();
874 LONG64 lLastUpdatedIgnored;
875 bool fIsGuestSupportsGraphics = guest().GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored)
876 == KAdditionsFacilityStatus_Active;
877 bool fIsGuestSupportsSeamless = guest().GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored)
878 == KAdditionsFacilityStatus_Active;
879 /* Check if something had changed: */
880 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel ||
881 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
882 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
883 {
884 /* Store new data: */
885 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
886 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
887 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
888
889 /* Notify listeners about GA state really changed: */
890 LogRel(("GUI: UISession::sltAdditionsChange: GA state really changed, notifying listeners.\n"));
891 emit sigAdditionsStateActualChange();
892 }
893
894 /* Notify listeners about GA state change event came: */
895 LogRel(("GUI: UISession::sltAdditionsChange: GA state change event came, notifying listeners.\n"));
896 emit sigAdditionsStateChange();
897}
898
899UISession::UISession(UIMachine *pMachine)
900 : QObject(pMachine)
901 /* Base variables: */
902 , m_pMachine(pMachine)
903 , m_pActionPool(0)
904#ifdef Q_WS_MAC
905 , m_pMenuBar(0)
906#endif /* Q_WS_MAC */
907 /* Common variables: */
908 , m_machineStatePrevious(KMachineState_Null)
909 , m_machineState(KMachineState_Null)
910#ifndef Q_WS_MAC
911 , m_pMachineWindowIcon(0)
912#endif /* !Q_WS_MAC */
913 , m_requestedVisualStateType(UIVisualStateType_Invalid)
914#ifdef Q_WS_WIN
915 , m_alphaCursor(0)
916#endif /* Q_WS_WIN */
917#ifdef Q_WS_MAC
918 , m_pWatchdogDisplayChange(0)
919#endif /* Q_WS_MAC */
920 , m_defaultCloseAction(MachineCloseAction_Invalid)
921 , m_restrictedCloseActions(MachineCloseAction_Invalid)
922 , m_fAllCloseActionsRestricted(false)
923 /* Common flags: */
924 , m_fInitialized(false)
925 , m_fIsFirstTimeStarted(false)
926 , m_fIsGuestResizeIgnored(false)
927 , m_fIsAutoCaptureDisabled(false)
928 /* Guest additions flags: */
929 , m_ulGuestAdditionsRunLevel(0)
930 , m_fIsGuestSupportsGraphics(false)
931 , m_fIsGuestSupportsSeamless(false)
932 /* Mouse flags: */
933 , m_fNumLock(false)
934 , m_fCapsLock(false)
935 , m_fScrollLock(false)
936 , m_uNumLockAdaptionCnt(2)
937 , m_uCapsLockAdaptionCnt(2)
938 /* Mouse flags: */
939 , m_fIsMouseSupportsAbsolute(false)
940 , m_fIsMouseSupportsRelative(false)
941 , m_fIsMouseSupportsMultiTouch(false)
942 , m_fIsMouseHostCursorNeeded(false)
943 , m_fIsMouseCaptured(false)
944 , m_fIsMouseIntegrated(true)
945 , m_fIsValidPointerShapePresent(false)
946 , m_fIsHidingHostPointer(true)
947{
948}
949
950UISession::~UISession()
951{
952}
953
954bool UISession::prepare()
955{
956 /* Prepare session: */
957 if (!prepareSession())
958 return false;
959
960 /* Prepare actions: */
961 prepareActions();
962
963 /* Prepare connections: */
964 prepareConnections();
965
966 /* Prepare console event-handlers: */
967 prepareConsoleEventHandlers();
968
969 /* Prepare screens: */
970 prepareScreens();
971
972 /* Prepare framebuffers: */
973 prepareFramebuffers();
974
975 /* Load settings: */
976 loadSessionSettings();
977
978#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
979 struct sigaction sa;
980 sa.sa_sigaction = &signalHandlerSIGUSR1;
981 sigemptyset(&sa.sa_mask);
982 sa.sa_flags = SA_RESTART | SA_SIGINFO;
983 sigaction(SIGUSR1, &sa, NULL);
984#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
985
986 /* True by default: */
987 return true;
988}
989
990bool UISession::prepareSession()
991{
992 /* Open session: */
993 m_session = vboxGlobal().openSession(vboxGlobal().managedVMUuid(),
994 vboxGlobal().isSeparateProcess()
995 ? KLockType_Shared : KLockType_VM);
996 if (m_session.isNull())
997 return false;
998
999 /* Get machine: */
1000 m_machine = m_session.GetMachine();
1001 if (m_machine.isNull())
1002 return false;
1003
1004 /* Get console: */
1005 m_console = m_session.GetConsole();
1006 if (m_console.isNull())
1007 return false;
1008
1009 /* Get display: */
1010 m_display = m_console.GetDisplay();
1011 if (m_display.isNull())
1012 return false;
1013
1014 /* Get guest: */
1015 m_guest = m_console.GetGuest();
1016 if (m_guest.isNull())
1017 return false;
1018
1019 /* Get mouse: */
1020 m_mouse = m_console.GetMouse();
1021 if (m_mouse.isNull())
1022 return false;
1023
1024 /* Get keyboard: */
1025 m_keyboard = m_console.GetKeyboard();
1026 if (m_keyboard.isNull())
1027 return false;
1028
1029 /* Get debugger: */
1030 m_debugger = m_console.GetDebugger();
1031 if (m_debugger.isNull())
1032 return false;
1033
1034 /* Update machine-name: */
1035 m_strMachineName = machine().GetName();
1036
1037 /* Update machine-state: */
1038 m_machineState = machine().GetState();
1039
1040 /* True by default: */
1041 return true;
1042}
1043
1044void UISession::prepareActions()
1045{
1046 /* Create action-pool: */
1047 m_pActionPool = UIActionPool::create(UIActionPoolType_Runtime);
1048 AssertPtrReturnVoid(actionPool());
1049 {
1050 /* Configure action-pool: */
1051 actionPool()->toRuntime()->setSession(this);
1052
1053 /* Get host: */
1054 const CHost host = vboxGlobal().host();
1055 UIExtraDataMetaDefs::RuntimeMenuViewActionType restrictionForView = UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid;
1056 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType restrictionForDevices = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid;
1057
1058 /* VRDE server stuff: */
1059 {
1060 /* Initialize 'View' menu: */
1061 const CVRDEServer server = machine().GetVRDEServer();
1062 if (server.isNull())
1063 restrictionForView = (UIExtraDataMetaDefs::RuntimeMenuViewActionType)(restrictionForView | UIExtraDataMetaDefs::RuntimeMenuViewActionType_VRDEServer);
1064 }
1065
1066 /* Storage stuff: */
1067 {
1068 /* Initialize CD/FD menus: */
1069 int iDevicesCountCD = 0;
1070 int iDevicesCountFD = 0;
1071 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachments())
1072 {
1073 if (attachment.GetType() == KDeviceType_DVD)
1074 ++iDevicesCountCD;
1075 if (attachment.GetType() == KDeviceType_Floppy)
1076 ++iDevicesCountFD;
1077 }
1078 QAction *pOpticalDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_OpticalDevices);
1079 QAction *pFloppyDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_FloppyDevices);
1080 pOpticalDevicesMenu->setData(iDevicesCountCD);
1081 pFloppyDevicesMenu->setData(iDevicesCountFD);
1082 if (!iDevicesCountCD)
1083 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_OpticalDevices);
1084 if (!iDevicesCountFD)
1085 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_FloppyDevices);
1086 }
1087
1088 /* Network stuff: */
1089 {
1090 /* Initialize Network menu: */
1091 bool fAtLeastOneAdapterActive = false;
1092 const KChipsetType chipsetType = machine().GetChipsetType();
1093 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(chipsetType);
1094 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot)
1095 {
1096 const CNetworkAdapter &adapter = machine().GetNetworkAdapter(uSlot);
1097 if (adapter.GetEnabled())
1098 {
1099 fAtLeastOneAdapterActive = true;
1100 break;
1101 }
1102 }
1103 if (!fAtLeastOneAdapterActive)
1104 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Network);
1105 }
1106
1107 /* USB stuff: */
1108 {
1109 /* Check whether there is at least one USB controller with an available proxy. */
1110 const bool fUSBEnabled = !machine().GetUSBDeviceFilters().isNull()
1111 && !machine().GetUSBControllers().isEmpty()
1112 && machine().GetUSBProxyAvailable();
1113 if (!fUSBEnabled)
1114 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_USBDevices);
1115 }
1116
1117 /* WebCams stuff: */
1118 {
1119 /* Check whether there is an accessible video input devices pool: */
1120 host.GetVideoInputDevices();
1121 const bool fWebCamsEnabled = host.isOk() && !machine().GetUSBControllers().isEmpty();
1122 if (!fWebCamsEnabled)
1123 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_WebCams);
1124 }
1125
1126 /* Apply cumulative restriction for 'View' menu: */
1127 actionPool()->toRuntime()->setRestrictionForMenuView(UIActionRestrictionLevel_Session, restrictionForView);
1128 /* Apply cumulative restriction for 'Devices' menu: */
1129 actionPool()->toRuntime()->setRestrictionForMenuDevices(UIActionRestrictionLevel_Session, restrictionForDevices);
1130
1131#ifdef Q_WS_MAC
1132 /* Create Mac OS X menu-bar: */
1133 m_pMenuBar = new UIMenuBar;
1134 AssertPtrReturnVoid(m_pMenuBar);
1135 {
1136 /* Configure Mac OS X menu-bar: */
1137 connect(gEDataManager, SIGNAL(sigMenuBarConfigurationChange(const QString&)),
1138 this, SLOT(sltHandleMenuBarConfigurationChange(const QString&)));
1139 /* Update Mac OS X menu-bar: */
1140 updateMenu();
1141 }
1142#endif /* Q_WS_MAC */
1143 }
1144}
1145
1146void UISession::prepareConnections()
1147{
1148 connect(this, SIGNAL(sigInitialized()), this, SLOT(sltMarkInitialized()));
1149
1150#ifdef Q_WS_MAC
1151 /* Install native display reconfiguration callback: */
1152 CGDisplayRegisterReconfigurationCallback(cgDisplayReconfigurationCallback, this);
1153#else /* !Q_WS_MAC */
1154 /* Install Qt display reconfiguration callbacks: */
1155 connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)),
1156 this, SLOT(sltHandleHostScreenCountChange()));
1157 connect(QApplication::desktop(), SIGNAL(resized(int)),
1158 this, SLOT(sltHandleHostScreenGeometryChange()));
1159 connect(QApplication::desktop(), SIGNAL(workAreaResized(int)),
1160 this, SLOT(sltHandleHostScreenAvailableAreaChange()));
1161#endif /* !Q_WS_MAC */
1162}
1163
1164void UISession::prepareConsoleEventHandlers()
1165{
1166 /* Create console event-handler: */
1167 UIConsoleEventHandler::create(this);
1168
1169 /* Add console event connections: */
1170 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)),
1171 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)));
1172
1173 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool, bool)),
1174 this, SLOT(sltMouseCapabilityChange(bool, bool, bool, bool)));
1175
1176 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)),
1177 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool)));
1178
1179 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)),
1180 this, SLOT(sltStateChange(KMachineState)));
1181
1182 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()),
1183 this, SLOT(sltAdditionsChange()));
1184
1185 connect(gConsoleEvents, SIGNAL(sigVRDEChange()),
1186 this, SLOT(sltVRDEChange()));
1187
1188 connect(gConsoleEvents, SIGNAL(sigVideoCaptureChange()),
1189 this, SLOT(sltVideoCaptureChange()));
1190
1191 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)),
1192 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)));
1193
1194 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)),
1195 this, SIGNAL(sigMediumChange(CMediumAttachment)));
1196
1197 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()),
1198 this, SIGNAL(sigUSBControllerChange()));
1199
1200 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)),
1201 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)));
1202
1203 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()),
1204 this, SIGNAL(sigSharedFolderChange()));
1205
1206 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)),
1207 this, SIGNAL(sigRuntimeError(bool, QString, QString)));
1208
1209#ifdef Q_WS_MAC
1210 connect(gConsoleEvents, SIGNAL(sigShowWindow()),
1211 this, SIGNAL(sigShowWindows()), Qt::QueuedConnection);
1212#endif /* Q_WS_MAC */
1213
1214 connect(gConsoleEvents, SIGNAL(sigCPUExecutionCapChange()),
1215 this, SIGNAL(sigCPUExecutionCapChange()));
1216
1217 connect(gConsoleEvents, SIGNAL(sigGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)),
1218 this, SLOT(sltGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)));
1219}
1220
1221void UISession::prepareScreens()
1222{
1223 /* Recache display data: */
1224 updateHostScreenData();
1225
1226#ifdef Q_WS_MAC
1227 /* Prepare display-change watchdog: */
1228 m_pWatchdogDisplayChange = new QTimer(this);
1229 {
1230 m_pWatchdogDisplayChange->setInterval(500);
1231 m_pWatchdogDisplayChange->setSingleShot(true);
1232 connect(m_pWatchdogDisplayChange, SIGNAL(timeout()),
1233 this, SLOT(sltCheckIfHostDisplayChanged()));
1234 }
1235#endif /* Q_WS_MAC */
1236
1237 /* Prepare initial screen visibility status: */
1238 m_monitorVisibilityVector.resize(machine().GetMonitorCount());
1239 m_monitorVisibilityVector.fill(false);
1240 m_monitorVisibilityVector[0] = true;
1241
1242 /* Prepare empty last full-screen size vector: */
1243 m_monitorLastFullScreenSizeVector.resize(machine().GetMonitorCount());
1244 m_monitorLastFullScreenSizeVector.fill(QSize(-1, -1));
1245
1246 /* If machine is in 'saved' state: */
1247 if (isSaved())
1248 {
1249 /* Update screen visibility status from saved-state: */
1250 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1251 {
1252 BOOL fEnabled = true;
1253 ULONG uGuestOriginX = 0, uGuestOriginY = 0, uGuestWidth = 0, uGuestHeight = 0;
1254 machine().QuerySavedGuestScreenInfo(iScreenIndex,
1255 uGuestOriginX, uGuestOriginY,
1256 uGuestWidth, uGuestHeight, fEnabled);
1257 m_monitorVisibilityVector[iScreenIndex] = fEnabled;
1258 }
1259 /* And make sure at least one of them is visible (primary if others are hidden): */
1260 if (countOfVisibleWindows() < 1)
1261 m_monitorVisibilityVector[0] = true;
1262 }
1263 else if (vboxGlobal().isSeparateProcess())
1264 {
1265 /* Update screen visibility status from display directly: */
1266 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1267 {
1268 KGuestMonitorStatus enmStatus = KGuestMonitorStatus_Disabled;
1269 ULONG uGuestWidth = 0, uGuestHeight = 0, uBpp = 0;
1270 LONG iGuestOriginX = 0, iGuestOriginY = 0;
1271 display().GetScreenResolution(iScreenIndex,
1272 uGuestWidth, uGuestHeight, uBpp,
1273 iGuestOriginX, iGuestOriginY, enmStatus);
1274 m_monitorVisibilityVector[iScreenIndex] = (enmStatus == KGuestMonitorStatus_Enabled);
1275 }
1276 /* And make sure at least one of them is visible (primary if others are hidden): */
1277 if (countOfVisibleWindows() < 1)
1278 m_monitorVisibilityVector[0] = true;
1279 }
1280}
1281
1282void UISession::prepareFramebuffers()
1283{
1284 /* Each framebuffer will be really prepared on first UIMachineView creation: */
1285 m_frameBufferVector.resize(machine().GetMonitorCount());
1286}
1287
1288void UISession::loadSessionSettings()
1289{
1290 /* Load extra-data settings: */
1291 {
1292 /* Get machine ID: */
1293 const QString strMachineID = vboxGlobal().managedVMUuid();
1294
1295#ifndef Q_WS_MAC
1296 /* Load/prepare user's machine-window icon: */
1297 QIcon icon;
1298 foreach (const QString &strIconName, gEDataManager->machineWindowIconNames(strMachineID))
1299 if (!strIconName.isEmpty())
1300 icon.addFile(strIconName);
1301 if (!icon.isNull())
1302 m_pMachineWindowIcon = new QIcon(icon);
1303
1304 /* Load user's machine-window name postfix: */
1305 m_strMachineWindowNamePostfix = gEDataManager->machineWindowNamePostfix(strMachineID);
1306#endif /* !Q_WS_MAC */
1307
1308 /* Is there should be First RUN Wizard? */
1309 m_fIsFirstTimeStarted = gEDataManager->machineFirstTimeStarted(strMachineID);
1310
1311 /* Should guest autoresize? */
1312 QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize);
1313 pGuestAutoresizeSwitch->setChecked(gEDataManager->guestScreenAutoResizeEnabled(strMachineID));
1314
1315#ifndef Q_WS_MAC
1316 /* Menu-bar options: */
1317 {
1318 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noMenuBar");
1319 const bool fEnabledForMachine = gEDataManager->menuBarEnabled(strMachineID);
1320 const bool fEnabled = fEnabledGlobally && fEnabledForMachine;
1321 QAction *pActionMenuBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings);
1322 pActionMenuBarSettings->setEnabled(fEnabled);
1323 QAction *pActionMenuBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility);
1324 pActionMenuBarSwitch->blockSignals(true);
1325 pActionMenuBarSwitch->setChecked(fEnabled);
1326 pActionMenuBarSwitch->blockSignals(false);
1327 }
1328#endif /* !Q_WS_MAC */
1329
1330 /* Status-bar options: */
1331 {
1332 const bool fEnabledGlobally = !vboxGlobal().settings().isFeatureActive("noStatusBar");
1333 const bool fEnabledForMachine = gEDataManager->statusBarEnabled(strMachineID);
1334 const bool fEnabled = fEnabledGlobally && fEnabledForMachine;
1335 QAction *pActionStatusBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings);
1336 pActionStatusBarSettings->setEnabled(fEnabled);
1337 QAction *pActionStatusBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility);
1338 pActionStatusBarSwitch->blockSignals(true);
1339 pActionStatusBarSwitch->setChecked(fEnabled);
1340 pActionStatusBarSwitch->blockSignals(false);
1341 }
1342
1343 /* Input options: */
1344 actionPool()->action(UIActionIndexRT_M_Input_M_Mouse_T_Integration)->setChecked(isMouseIntegrated());
1345
1346 /* What is the default close action and the restricted are? */
1347 m_defaultCloseAction = gEDataManager->defaultMachineCloseAction(strMachineID);
1348 m_restrictedCloseActions = gEDataManager->restrictedMachineCloseActions(strMachineID);
1349 m_fAllCloseActionsRestricted = (!vboxGlobal().isSeparateProcess() || (m_restrictedCloseActions & MachineCloseAction_Detach))
1350 && (m_restrictedCloseActions & MachineCloseAction_SaveState)
1351 && (m_restrictedCloseActions & MachineCloseAction_Shutdown)
1352 && (m_restrictedCloseActions & MachineCloseAction_PowerOff);
1353 // Close VM Dialog hides PowerOff_RestoringSnapshot implicitly if PowerOff is hidden..
1354 // && (m_restrictedCloseActions & MachineCloseAction_PowerOff_RestoringSnapshot);
1355 }
1356}
1357
1358void UISession::saveSessionSettings()
1359{
1360 /* Save extra-data settings: */
1361 {
1362 /* Disable First RUN Wizard: */
1363 gEDataManager->setMachineFirstTimeStarted(false, vboxGlobal().managedVMUuid());
1364
1365 /* Remember if guest should autoresize: */
1366 if (actionPool())
1367 {
1368 const QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize);
1369 gEDataManager->setGuestScreenAutoResizeEnabled(pGuestAutoresizeSwitch->isChecked(), vboxGlobal().managedVMUuid());
1370 }
1371
1372#ifndef Q_WS_MAC
1373 /* Cleanup user's machine-window icon: */
1374 delete m_pMachineWindowIcon;
1375 m_pMachineWindowIcon = 0;
1376#endif /* !Q_WS_MAC */
1377 }
1378}
1379
1380void UISession::cleanupFramebuffers()
1381{
1382 /* Cleanup framebuffers finally: */
1383 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i)
1384 {
1385 UIFrameBuffer *pFrameBuffer = m_frameBufferVector[i];
1386 if (pFrameBuffer)
1387 {
1388 /* Mark framebuffer as unused: */
1389 pFrameBuffer->setMarkAsUnused(true);
1390 /* Detach framebuffer from Display: */
1391 pFrameBuffer->detach();
1392 /* Delete framebuffer reference: */
1393 delete pFrameBuffer;
1394 }
1395 }
1396 m_frameBufferVector.clear();
1397}
1398
1399void UISession::cleanupConsoleEventHandlers()
1400{
1401 /* Destroy console event-handler if necessary: */
1402 if (gConsoleEvents)
1403 UIConsoleEventHandler::destroy();
1404}
1405
1406void UISession::cleanupConnections()
1407{
1408#ifdef Q_WS_MAC
1409 /* Remove display reconfiguration callback: */
1410 CGDisplayRemoveReconfigurationCallback(cgDisplayReconfigurationCallback, this);
1411#endif /* Q_WS_MAC */
1412}
1413
1414void UISession::cleanupActions()
1415{
1416#ifdef Q_WS_MAC
1417 /* Destroy Mac OS X menu-bar: */
1418 delete m_pMenuBar;
1419 m_pMenuBar = 0;
1420#endif /* Q_WS_MAC */
1421
1422 /* Destroy action-pool if necessary: */
1423 if (actionPool())
1424 UIActionPool::destroy(actionPool());
1425}
1426
1427void UISession::cleanupSession()
1428{
1429 /* Detach debugger: */
1430 if (!m_debugger.isNull())
1431 m_debugger.detach();
1432
1433 /* Detach keyboard: */
1434 if (!m_keyboard.isNull())
1435 m_keyboard.detach();
1436
1437 /* Detach mouse: */
1438 if (!m_mouse.isNull())
1439 m_mouse.detach();
1440
1441 /* Detach guest: */
1442 if (!m_guest.isNull())
1443 m_guest.detach();
1444
1445 /* Detach display: */
1446 if (!m_display.isNull())
1447 m_display.detach();
1448
1449 /* Detach console: */
1450 if (!m_console.isNull())
1451 m_console.detach();
1452
1453 /* Detach machine: */
1454 if (!m_machine.isNull())
1455 m_machine.detach();
1456
1457 /* Close session: */
1458 if (!m_session.isNull() && vboxGlobal().isVBoxSVCAvailable())
1459 {
1460 m_session.UnlockMachine();
1461 m_session.detach();
1462 }
1463}
1464
1465void UISession::cleanup()
1466{
1467#ifdef Q_WS_WIN
1468 /* Destroy alpha cursor: */
1469 if (m_alphaCursor)
1470 DestroyIcon(m_alphaCursor);
1471#endif /* Q_WS_WIN */
1472
1473 /* Save settings: */
1474 saveSessionSettings();
1475
1476 /* Cleanup framebuffers: */
1477 cleanupFramebuffers();
1478
1479 /* Cleanup console event-handlers: */
1480 cleanupConsoleEventHandlers();
1481
1482 /* Cleanup connections: */
1483 cleanupConnections();
1484
1485 /* Cleanup actions: */
1486 cleanupActions();
1487
1488 /* Cleanup session: */
1489 cleanupSession();
1490}
1491
1492#ifdef Q_WS_MAC
1493void UISession::updateMenu()
1494{
1495 /* Rebuild Mac OS X menu-bar: */
1496 m_pMenuBar->clear();
1497 foreach (QMenu *pMenu, actionPool()->menus())
1498 {
1499 UIMenu *pMenuUI = qobject_cast<UIMenu*>(pMenu);
1500 if (!pMenuUI->isConsumable() || !pMenuUI->isConsumed())
1501 m_pMenuBar->addMenu(pMenuUI);
1502 if (pMenuUI->isConsumable() && !pMenuUI->isConsumed())
1503 pMenuUI->setConsumed(true);
1504 }
1505}
1506#endif /* Q_WS_MAC */
1507
1508WId UISession::winId() const
1509{
1510 return mainMachineWindow()->winId();
1511}
1512
1513void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
1514 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
1515{
1516 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
1517
1518 m_fIsValidPointerShapePresent = false;
1519 const uchar *srcAndMaskPtr = pShapeData;
1520 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
1521 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
1522 uint srcShapePtrScan = uWidth * 4;
1523
1524#if defined (Q_WS_WIN)
1525
1526 BITMAPV5HEADER bi;
1527 HBITMAP hBitmap;
1528 void *lpBits;
1529
1530 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
1531 bi.bV5Size = sizeof(BITMAPV5HEADER);
1532 bi.bV5Width = uWidth;
1533 bi.bV5Height = - (LONG)uHeight;
1534 bi.bV5Planes = 1;
1535 bi.bV5BitCount = 32;
1536 bi.bV5Compression = BI_BITFIELDS;
1537 bi.bV5RedMask = 0x00FF0000;
1538 bi.bV5GreenMask = 0x0000FF00;
1539 bi.bV5BlueMask = 0x000000FF;
1540 if (fHasAlpha)
1541 bi.bV5AlphaMask = 0xFF000000;
1542 else
1543 bi.bV5AlphaMask = 0;
1544
1545 HDC hdc = GetDC(NULL);
1546
1547 /* Create the DIB section with an alpha channel: */
1548 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
1549
1550 ReleaseDC(NULL, hdc);
1551
1552 HBITMAP hMonoBitmap = NULL;
1553 if (fHasAlpha)
1554 {
1555 /* Create an empty mask bitmap: */
1556 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
1557 }
1558 else
1559 {
1560 /* Word aligned AND mask. Will be allocated and created if necessary. */
1561 uint8_t *pu8AndMaskWordAligned = NULL;
1562
1563 /* Width in bytes of the original AND mask scan line. */
1564 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
1565
1566 if (cbAndMaskScan & 1)
1567 {
1568 /* Original AND mask is not word aligned. */
1569
1570 /* Allocate memory for aligned AND mask. */
1571 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
1572
1573 Assert(pu8AndMaskWordAligned);
1574
1575 if (pu8AndMaskWordAligned)
1576 {
1577 /* According to MSDN the padding bits must be 0.
1578 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
1579 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
1580 Assert(u32PaddingBits < 8);
1581 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
1582
1583 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
1584 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
1585
1586 uint8_t *src = (uint8_t *)srcAndMaskPtr;
1587 uint8_t *dst = pu8AndMaskWordAligned;
1588
1589 unsigned i;
1590 for (i = 0; i < uHeight; i++)
1591 {
1592 memcpy(dst, src, cbAndMaskScan);
1593
1594 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
1595
1596 src += cbAndMaskScan;
1597 dst += cbAndMaskScan + 1;
1598 }
1599 }
1600 }
1601
1602 /* Create the AND mask bitmap: */
1603 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
1604 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
1605
1606 if (pu8AndMaskWordAligned)
1607 {
1608 RTMemTmpFree(pu8AndMaskWordAligned);
1609 }
1610 }
1611
1612 Assert(hBitmap);
1613 Assert(hMonoBitmap);
1614 if (hBitmap && hMonoBitmap)
1615 {
1616 DWORD *dstShapePtr = (DWORD *) lpBits;
1617
1618 for (uint y = 0; y < uHeight; y ++)
1619 {
1620 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
1621 srcShapePtr += srcShapePtrScan;
1622 dstShapePtr += uWidth;
1623 }
1624
1625 ICONINFO ii;
1626 ii.fIcon = FALSE;
1627 ii.xHotspot = uXHot;
1628 ii.yHotspot = uYHot;
1629 ii.hbmMask = hMonoBitmap;
1630 ii.hbmColor = hBitmap;
1631
1632 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
1633 Assert(hAlphaCursor);
1634 if (hAlphaCursor)
1635 {
1636 /* Set the new cursor: */
1637 m_cursor = QCursor(hAlphaCursor);
1638 if (m_alphaCursor)
1639 DestroyIcon(m_alphaCursor);
1640 m_alphaCursor = hAlphaCursor;
1641 m_fIsValidPointerShapePresent = true;
1642 }
1643 }
1644
1645 if (hMonoBitmap)
1646 DeleteObject(hMonoBitmap);
1647 if (hBitmap)
1648 DeleteObject(hBitmap);
1649
1650#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
1651
1652 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
1653 Assert(img);
1654 if (img)
1655 {
1656 img->xhot = uXHot;
1657 img->yhot = uYHot;
1658
1659 XcursorPixel *dstShapePtr = img->pixels;
1660
1661 for (uint y = 0; y < uHeight; y ++)
1662 {
1663 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
1664
1665 if (!fHasAlpha)
1666 {
1667 /* Convert AND mask to the alpha channel: */
1668 uchar byte = 0;
1669 for (uint x = 0; x < uWidth; x ++)
1670 {
1671 if (!(x % 8))
1672 byte = *(srcAndMaskPtr ++);
1673 else
1674 byte <<= 1;
1675
1676 if (byte & 0x80)
1677 {
1678 /* Linux doesn't support inverted pixels (XOR ops,
1679 * to be exact) in cursor shapes, so we detect such
1680 * pixels and always replace them with black ones to
1681 * make them visible at least over light colors */
1682 if (dstShapePtr [x] & 0x00FFFFFF)
1683 dstShapePtr [x] = 0xFF000000;
1684 else
1685 dstShapePtr [x] = 0x00000000;
1686 }
1687 else
1688 dstShapePtr [x] |= 0xFF000000;
1689 }
1690 }
1691
1692 srcShapePtr += srcShapePtrScan;
1693 dstShapePtr += uWidth;
1694 }
1695
1696 /* Set the new cursor: */
1697 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
1698 m_fIsValidPointerShapePresent = true;
1699
1700 XcursorImageDestroy(img);
1701 }
1702
1703#elif defined(Q_WS_MAC)
1704
1705 /* Create a ARGB image out of the shape data. */
1706 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
1707 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
1708 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
1709 for (unsigned int y = 0; y < uHeight; ++y)
1710 {
1711 for (unsigned int x = 0; x < uWidth; ++x)
1712 {
1713 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
1714 /* If the alpha channel isn't in the shape data, we have to
1715 * create them from the and-mask. This is a bit field where 1
1716 * represent transparency & 0 opaque respectively. */
1717 if (!fHasAlpha)
1718 {
1719 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
1720 color |= 0xff000000;
1721 else
1722 {
1723 /* This isn't quite right, but it's the best we can do I think... */
1724 if (color & 0x00ffffff)
1725 color = 0xff000000;
1726 else
1727 color = 0x00000000;
1728 }
1729 }
1730 image.setPixel (x, y, color);
1731 }
1732 /* Move one scanline forward. */
1733 pbSrcMask += cbSrcMaskLine;
1734 }
1735
1736 /* Set the new cursor: */
1737 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
1738 m_fIsValidPointerShapePresent = true;
1739 NOREF(srcShapePtrScan);
1740
1741#else
1742
1743# warning "port me"
1744
1745#endif
1746}
1747
1748bool UISession::preprocessInitialization()
1749{
1750#ifdef VBOX_WITH_NETFLT
1751 /* Skip further checks if VM in saved state */
1752 if (isSaved())
1753 return true;
1754
1755 /* Make sure all the attached and enabled network
1756 * adapters are present on the host. This check makes sense
1757 * in two cases only - when attachement type is Bridged Network
1758 * or Host-only Interface. NOTE: Only currently enabled
1759 * attachement type is checked (incorrect parameters check for
1760 * currently disabled attachement types is skipped). */
1761 QStringList failedInterfaceNames;
1762 QStringList availableInterfaceNames;
1763
1764 /* Create host network interface names list */
1765 foreach (const CHostNetworkInterface &iface, vboxGlobal().host().GetNetworkInterfaces())
1766 {
1767 availableInterfaceNames << iface.GetName();
1768 availableInterfaceNames << iface.GetShortName();
1769 }
1770
1771 ulong cCount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine().GetChipsetType());
1772 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex)
1773 {
1774 CNetworkAdapter na = machine().GetNetworkAdapter(uAdapterIndex);
1775
1776 if (na.GetEnabled())
1777 {
1778 QString strIfName = QString();
1779
1780 /* Get physical network interface name for currently
1781 * enabled network attachement type */
1782 switch (na.GetAttachmentType())
1783 {
1784 case KNetworkAttachmentType_Bridged:
1785 strIfName = na.GetBridgedInterface();
1786 break;
1787 case KNetworkAttachmentType_HostOnly:
1788 strIfName = na.GetHostOnlyInterface();
1789 break;
1790 }
1791
1792 if (!strIfName.isEmpty() &&
1793 !availableInterfaceNames.contains(strIfName))
1794 {
1795 LogFlow(("Found invalid network interface: %s\n", strIfName.toStdString().c_str()));
1796 failedInterfaceNames << QString("%1 (adapter %2)").arg(strIfName).arg(uAdapterIndex + 1);
1797 }
1798 }
1799 }
1800
1801 /* Check if non-existent interfaces found */
1802 if (!failedInterfaceNames.isEmpty())
1803 {
1804 if (msgCenter().cannotStartWithoutNetworkIf(machineName(), failedInterfaceNames.join(", ")))
1805 machineLogic()->openNetworkSettingsDialog();
1806 else
1807 return false;
1808 }
1809#endif /* VBOX_WITH_NETFLT */
1810
1811 /* True by default: */
1812 return true;
1813}
1814
1815bool UISession::mountAdHocImage(KDeviceType enmDeviceType, UIMediumType enmMediumType, const QString &strImage)
1816{
1817 /* The 'none' image name means ejecting what ever is in the drive,
1818 * so leave the image variables null. */
1819 CVirtualBox vbox = vboxGlobal().virtualBox();
1820 UIMedium uiImage;
1821 if (strImage != "none")
1822 {
1823 /* Open the image: */
1824 CVirtualBox vbox = vboxGlobal().virtualBox();
1825 CMedium vboxImage = vbox.OpenMedium(strImage, enmDeviceType, KAccessMode_ReadWrite, false /* fForceNewUuid */);
1826 if (!vbox.isOk() || vboxImage.isNull())
1827 {
1828 msgCenter().cannotOpenMedium(vbox, enmMediumType, strImage);
1829 return false;
1830 }
1831
1832 /* Work the cache and use the cached image if possible: */
1833 uiImage = vboxGlobal().medium(vboxImage.GetId());
1834 if (uiImage.isNull())
1835 {
1836 uiImage = UIMedium(vboxImage, enmMediumType, KMediumState_Created);
1837 vboxGlobal().createMedium(uiImage);
1838 }
1839 }
1840 if (vbox.isOk())
1841 {
1842 /* Find suitable storage controller: */
1843 foreach (const CStorageController &controller, machine().GetStorageControllers())
1844 {
1845 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachmentsOfController(controller.GetName()))
1846 {
1847 if (attachment.GetType() == enmDeviceType)
1848 {
1849 /* Mount the image: */
1850 machine().MountMedium(controller.GetName(), attachment.GetPort(), attachment.GetDevice(), uiImage.medium(), true /* force */);
1851 if (machine().isOk())
1852 return true;
1853 msgCenter().cannotRemountMedium(machine(), uiImage, !uiImage.isNull() /* mount */, false /* retry */);
1854 return false;
1855 }
1856 }
1857 }
1858 msgCenter().cannotRemountMedium(machine(), uiImage, !uiImage.isNull() /* mount */, false /* retry */);
1859 }
1860 else
1861 msgCenter().cannotOpenMedium(vbox, enmMediumType, strImage);
1862 return false;
1863}
1864
1865bool UISession::postprocessInitialization()
1866{
1867 /* Check if the required virtualization features are active. We get this info only when the session is active. */
1868 const bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetIs64Bit();
1869 const bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetRecommendedVirtEx();
1870 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n"));
1871 const bool fIsVirtActive = debugger().GetHWVirtExEnabled();
1872 if (fRecommendVirtEx && !fIsVirtActive)
1873 {
1874 /* Check whether vt-x / amd-v supported: */
1875 bool fVTxAMDVSupported = vboxGlobal().host().GetProcessorFeature(KProcessorFeature_HWVirtEx);
1876
1877 /* Pause VM: */
1878 setPause(true);
1879
1880 /* Ask the user about further actions: */
1881 bool fShouldWeClose;
1882 if (fIs64BitsGuest)
1883 fShouldWeClose = msgCenter().warnAboutVirtExInactiveFor64BitsGuest(fVTxAMDVSupported);
1884 else
1885 fShouldWeClose = msgCenter().warnAboutVirtExInactiveForRecommendedGuest(fVTxAMDVSupported);
1886
1887 /* If user asked to close VM: */
1888 if (fShouldWeClose)
1889 {
1890 /* Enable 'manual-override',
1891 * preventing automatic Runtime UI closing: */
1892 if (machineLogic())
1893 machineLogic()->setManualOverrideMode(true);
1894 /* Power off VM: */
1895 bool fServerCrashed = false;
1896 powerOff(false, fServerCrashed);
1897 return false;
1898 }
1899
1900 /* Resume VM: */
1901 setPause(false);
1902 }
1903
1904 /* True by default: */
1905 return true;
1906}
1907
1908bool UISession::isScreenVisible(ulong uScreenId) const
1909{
1910 /* Make sure index feats the bounds: */
1911 AssertReturn(uScreenId < (ulong)m_monitorVisibilityVector.size(), false);
1912
1913 /* Return 'actual' visibility status: */
1914 return m_monitorVisibilityVector.value((int)uScreenId);
1915}
1916
1917void UISession::setScreenVisible(ulong uScreenId, bool fIsMonitorVisible)
1918{
1919 /* Make sure index feats the bounds: */
1920 AssertReturnVoid(uScreenId < (ulong)m_monitorVisibilityVector.size());
1921
1922 /* Remember 'actual' visibility status: */
1923 m_monitorVisibilityVector[(int)uScreenId] = fIsMonitorVisible;
1924 /* Remember 'desired' visibility status: */
1925 gEDataManager->setLastGuestScreenVisibilityStatus(uScreenId, fIsMonitorVisible, vboxGlobal().managedVMUuid());
1926}
1927
1928QSize UISession::lastFullScreenSize(ulong uScreenId) const
1929{
1930 /* Make sure index fits the bounds: */
1931 AssertReturn(uScreenId < (ulong)m_monitorLastFullScreenSizeVector.size(), QSize(-1, -1));
1932
1933 /* Return last full-screen size: */
1934 return m_monitorLastFullScreenSizeVector.value((int)uScreenId);
1935}
1936
1937void UISession::setLastFullScreenSize(ulong uScreenId, QSize size)
1938{
1939 /* Make sure index fits the bounds: */
1940 AssertReturnVoid(uScreenId < (ulong)m_monitorLastFullScreenSizeVector.size());
1941
1942 /* Remember last full-screen size: */
1943 m_monitorLastFullScreenSizeVector[(int)uScreenId] = size;
1944}
1945
1946int UISession::countOfVisibleWindows()
1947{
1948 int cCountOfVisibleWindows = 0;
1949 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i)
1950 if (m_monitorVisibilityVector[i])
1951 ++cCountOfVisibleWindows;
1952 return cCountOfVisibleWindows;
1953}
1954
1955UIFrameBuffer* UISession::frameBuffer(ulong uScreenId) const
1956{
1957 Assert(uScreenId < (ulong)m_frameBufferVector.size());
1958 return m_frameBufferVector.value((int)uScreenId, 0);
1959}
1960
1961void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer* pFrameBuffer)
1962{
1963 Assert(uScreenId < (ulong)m_frameBufferVector.size());
1964 if (uScreenId < (ulong)m_frameBufferVector.size())
1965 m_frameBufferVector[(int)uScreenId] = pFrameBuffer;
1966}
1967
1968void UISession::updateHostScreenData()
1969{
1970 m_hostScreens.clear();
1971 for (int iScreenIndex = 0; iScreenIndex < vboxGlobal().screenCount(); ++iScreenIndex)
1972 m_hostScreens << vboxGlobal().screenGeometry(iScreenIndex);
1973}
1974
1975#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
1976/**
1977 * Custom signal handler. When switching VTs, we might not get release events
1978 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will
1979 * be saved with modifier keys stuck. This is annoying enough for introducing
1980 * this hack.
1981 */
1982/* static */
1983static void signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */)
1984{
1985 /* Only SIGUSR1 is interesting: */
1986 if (sig == SIGUSR1)
1987 if (gpMachine)
1988 gpMachine->uisession()->machineLogic()->keyboardHandler()->releaseAllPressedKeys();
1989}
1990#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
1991
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