VirtualBox

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

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

Main/Console+Machine+Session+Snapshot: move the save state and snapshot related methods from IConsole to IMachine, with lots of unavoidable code restructuring and cleanup. Also define two new machine states (so that the "Saving" one is specifically for saving state now) which requires more changes everywhere
Frontends: necessary adjustments
doc/SDK: document the changes

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette