VirtualBox

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

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

FE/Qt: 7599: Handle menu-bar / status-bar extra-data changes on the broadcast basis.

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