VirtualBox

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

Last change on this file since 54505 was 54505, checked in by vboxsync, 10 years ago

FE/Qt: 7614: Make sure 'desired' and 'actual' option values have different NLS to let the user distinguish them.

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