VirtualBox

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

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

FE/Qt: Runtime UI: Pass-through IStorageDeviceChangedEvent to UISession.

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