VirtualBox

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

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

FE/Qt: 7676: Runtime UI: Disk Encryption (DE) support: Fixing condition bug which seems related to MSCOM issue.

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