VirtualBox

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

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

FE/Qt: Mac OS X: 6985: Window menu for Runtime UI.

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