VirtualBox

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

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

FE/Qt: Runtime UI: Closing code adjustment.

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