VirtualBox

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

Last change on this file since 76164 was 76164, checked in by vboxsync, 6 years ago

FE/Qt: for guests using VMSVGA, do not remember guest-initiated resizes.
bugref:5329: Implement VMWare SVGA compatible video device
Currently we remember the last size set by the guest operating system to the
virtual display hardware before it was shut down and resend it on next start-
up. This is similar to having the same monitor plugged into a physical
system next time it is started. However, Linux guests using VMSVGA always
set the size to 800x600 with one screen on shut-down, which is not what we
want to remember. So for guests with the VMSVGA graphics controller type
(normally only used for Linux guests) we only remember sizes which we
explicitly send ourselves, as of this change, to get around this.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 82.4 KB
Line 
1/* $Id: UISession.cpp 76164 2018-12-11 16:14:25Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UISession class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2017 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 <QBitmap>
25# include <QMenuBar>
26# include <QWidget>
27# ifdef VBOX_WS_MAC
28# include <QTimer>
29# endif /* VBOX_WS_MAC */
30
31/* GUI includes: */
32# include "VBoxGlobal.h"
33# include "UIDesktopWidgetWatchdog.h"
34# include "UIExtraDataManager.h"
35# include "UISession.h"
36# include "UIMachine.h"
37# include "UIMedium.h"
38# include "UIActionPoolRuntime.h"
39# include "UIMachineLogic.h"
40# include "UIMachineView.h"
41# include "UIMachineWindow.h"
42# include "UIMessageCenter.h"
43# include "UIPopupCenter.h"
44# include "UIWizardFirstRun.h"
45# include "UIConsoleEventHandler.h"
46# include "UIFrameBuffer.h"
47# include "UISettingsDialogSpecific.h"
48# ifdef VBOX_WITH_VIDEOHWACCEL
49# include "VBox2DHelpers.h"
50# endif /* VBOX_WITH_VIDEOHWACCEL */
51# ifdef VBOX_WS_MAC
52# include "VBoxUtils-darwin.h"
53# endif /* VBOX_WS_MAC */
54
55# ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
56# include "UIKeyboardHandler.h"
57# include <signal.h>
58# endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
59
60/* COM includes: */
61# include "CAudioAdapter.h"
62# include "CRecordingSettings.h"
63# include "CSystemProperties.h"
64# include "CStorageController.h"
65# include "CMediumAttachment.h"
66# include "CNetworkAdapter.h"
67# include "CHostNetworkInterface.h"
68# include "CVRDEServer.h"
69# include "CUSBController.h"
70# include "CUSBDeviceFilters.h"
71# include "CHostVideoInputDevice.h"
72# include "CSnapshot.h"
73# include "CMedium.h"
74
75#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
76
77/* Qt includes: */
78#ifdef VBOX_WS_WIN
79# include <QtWin>
80#endif /* VBOX_WS_WIN */
81
82#ifdef VBOX_WS_X11
83# include <QX11Info>
84# include <X11/Xlib.h>
85# include <X11/Xutil.h>
86#endif /* VBOX_WS_X11 */
87
88#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
89static void signalHandlerSIGUSR1(int sig, siginfo_t *, void *);
90#endif
91
92#ifdef VBOX_WS_MAC
93/**
94 * MacOS X: Application Services: Core Graphics: Display reconfiguration callback.
95 *
96 * Notifies UISession about @a display configuration change.
97 * Corresponding change described by Core Graphics @a flags.
98 * Uses UISession @a pHandler to process this change.
99 *
100 * @note Last argument (@a pHandler) must always be valid pointer to UISession object.
101 * @note Calls for UISession::sltHandleHostDisplayAboutToChange() slot if display configuration changed.
102 */
103void cgDisplayReconfigurationCallback(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *pHandler)
104{
105 /* Which flags we are handling? */
106 int iHandledFlags = kCGDisplayAddFlag /* display added */
107 | kCGDisplayRemoveFlag /* display removed */
108 | kCGDisplaySetModeFlag /* display mode changed */;
109
110 /* Handle 'display-add' case: */
111 if (flags & kCGDisplayAddFlag)
112 LogRelFlow(("GUI: UISession::cgDisplayReconfigurationCallback: Display added.\n"));
113 /* Handle 'display-remove' case: */
114 else if (flags & kCGDisplayRemoveFlag)
115 LogRelFlow(("GUI: UISession::cgDisplayReconfigurationCallback: Display removed.\n"));
116 /* Handle 'mode-set' case: */
117 else if (flags & kCGDisplaySetModeFlag)
118 LogRelFlow(("GUI: UISession::cgDisplayReconfigurationCallback: Display mode changed.\n"));
119
120 /* Ask handler to process our callback: */
121 if (flags & iHandledFlags)
122 QTimer::singleShot(0, static_cast<UISession*>(pHandler),
123 SLOT(sltHandleHostDisplayAboutToChange()));
124
125 Q_UNUSED(display);
126}
127#endif /* VBOX_WS_MAC */
128
129/* static */
130bool UISession::create(UISession *&pSession, UIMachine *pMachine)
131{
132 /* Make sure null pointer passed: */
133 AssertReturn(pSession == 0, false);
134
135 /* Create session UI: */
136 pSession = new UISession(pMachine);
137 /* Make sure it's prepared: */
138 if (!pSession->prepare())
139 {
140 /* Destroy session UI otherwise: */
141 destroy(pSession);
142 /* False in that case: */
143 return false;
144 }
145 /* True by default: */
146 return true;
147}
148
149/* static */
150void UISession::destroy(UISession *&pSession)
151{
152 /* Make sure valid pointer passed: */
153 AssertReturnVoid(pSession != 0);
154
155 /* Cleanup session UI: */
156 pSession->cleanup();
157 /* Destroy session: */
158 delete pSession;
159 pSession = 0;
160}
161
162bool UISession::initialize()
163{
164 /* Preprocess initialization: */
165 if (!preprocessInitialization())
166 return false;
167
168 /* Notify user about mouse&keyboard auto-capturing: */
169 if (gEDataManager->autoCaptureEnabled())
170 popupCenter().remindAboutAutoCapture(activeMachineWindow());
171
172 /* Check if we are in teleportation waiting mode.
173 * In that case no first run wizard is necessary. */
174 m_machineState = machine().GetState();
175 if ( isFirstTimeStarted()
176 && !(( m_machineState == KMachineState_PoweredOff
177 || m_machineState == KMachineState_Aborted
178 || m_machineState == KMachineState_Teleported)
179 && machine().GetTeleporterEnabled()))
180 {
181 UISafePointerWizard pWizard = new UIWizardFirstRun(mainMachineWindow(), machine());
182 pWizard->prepare();
183 pWizard->exec();
184 if (pWizard)
185 delete pWizard;
186 }
187
188 /* Apply debug settings from the command line. */
189 if (!debugger().isNull() && debugger().isOk())
190 {
191 if (vboxGlobal().isPatmDisabled())
192 debugger().SetPATMEnabled(false);
193 if (vboxGlobal().isCsamDisabled())
194 debugger().SetCSAMEnabled(false);
195 if (vboxGlobal().isSupervisorCodeExecedRecompiled())
196 debugger().SetRecompileSupervisor(true);
197 if (vboxGlobal().isUserCodeExecedRecompiled())
198 debugger().SetRecompileUser(true);
199 if (vboxGlobal().areWeToExecuteAllInIem())
200 debugger().SetExecuteAllInIEM(true);
201 if (!vboxGlobal().isDefaultWarpPct())
202 debugger().SetVirtualTimeRate(vboxGlobal().getWarpPct());
203 }
204
205 /* Apply ad-hoc reconfigurations from the command line: */
206 if (vboxGlobal().hasFloppyImageToMount())
207 mountAdHocImage(KDeviceType_Floppy, UIMediumDeviceType_Floppy, vboxGlobal().getFloppyImage().toString());
208 if (vboxGlobal().hasDvdImageToMount())
209 mountAdHocImage(KDeviceType_DVD, UIMediumDeviceType_DVD, vboxGlobal().getDvdImage().toString());
210
211 /* Power UP if this is NOT separate process: */
212 if (!vboxGlobal().isSeparateProcess())
213 if (!powerUp())
214 return false;
215
216 /* Make sure all the pending Console events converted to signals
217 * during the powerUp() progress above reached their destinations.
218 * That is necessary to make sure all the pending machine state change events processed.
219 * We can't just use the machine state directly acquired from IMachine because there
220 * will be few places which are using stale machine state, not just this one. */
221 QApplication::sendPostedEvents(0, QEvent::MetaCall);
222
223 /* Check if we missed a really quick termination after successful startup: */
224 if (isTurnedOff())
225 {
226 LogRel(("GUI: Aborting startup due to invalid machine state detected: %d\n", machineState()));
227 return false;
228 }
229
230 /* Postprocess initialization: */
231 if (!postprocessInitialization())
232 return false;
233
234 /* Fetch corresponding states: */
235 if (vboxGlobal().isSeparateProcess())
236 {
237 m_fIsMouseSupportsAbsolute = mouse().GetAbsoluteSupported();
238 m_fIsMouseSupportsRelative = mouse().GetRelativeSupported();
239 m_fIsMouseSupportsMultiTouch = mouse().GetMultiTouchSupported();
240 m_fIsMouseHostCursorNeeded = mouse().GetNeedsHostCursor();
241 sltAdditionsChange();
242 }
243 machineLogic()->initializePostPowerUp();
244
245 /* Load VM settings: */
246 loadVMSettings();
247
248#ifdef VBOX_WITH_VIDEOHWACCEL
249 /* Log whether 2D video acceleration is enabled: */
250 LogRel(("GUI: 2D video acceleration is %s\n",
251 machine().GetAccelerate2DVideoEnabled() && VBox2DHelpers::isAcceleration2DVideoAvailable()
252 ? "enabled" : "disabled"));
253#endif /* VBOX_WITH_VIDEOHWACCEL */
254
255/* Log whether HID LEDs sync is enabled: */
256#if defined(VBOX_WS_MAC) || defined(VBOX_WS_WIN)
257 LogRel(("GUI: HID LEDs sync is %s\n",
258 uimachine()->machineLogic()->isHidLedsSyncEnabled()
259 ? "enabled" : "disabled"));
260#else /* !VBOX_WS_MAC && !VBOX_WS_WIN */
261 LogRel(("GUI: HID LEDs sync is not supported on this platform\n"));
262#endif /* !VBOX_WS_MAC && !VBOX_WS_WIN */
263
264#ifdef VBOX_GUI_WITH_PIDFILE
265 vboxGlobal().createPidfile();
266#endif /* VBOX_GUI_WITH_PIDFILE */
267
268 /* Warn listeners about we are initialized: */
269 emit sigInitialized();
270
271 /* True by default: */
272 return true;
273}
274
275bool UISession::powerUp()
276{
277 /* Power UP machine: */
278 CProgress progress = vboxGlobal().shouldStartPaused() ? console().PowerUpPaused() : console().PowerUp();
279
280 /* Check for immediate failure: */
281 if (!console().isOk() || progress.isNull())
282 {
283 if (vboxGlobal().showStartVMErrors())
284 msgCenter().cannotStartMachine(console(), machineName());
285 LogRel(("GUI: Aborting startup due to power up issue detected...\n"));
286 return false;
287 }
288
289 /* Some logging right after we powered up: */
290 LogRel(("Qt version: %s\n", VBoxGlobal::qtRTVersionString().toUtf8().constData()));
291#ifdef VBOX_WS_X11
292 LogRel(("X11 Window Manager code: %d\n", (int)vboxGlobal().typeOfWindowManager()));
293#endif
294
295 /* Enable 'manual-override',
296 * preventing automatic Runtime UI closing
297 * and visual representation mode changes: */
298 if (machineLogic())
299 machineLogic()->setManualOverrideMode(true);
300
301 /* Show "Starting/Restoring" progress dialog: */
302 if (isSaved())
303 {
304 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_restore_90px.png", 0, 0);
305 /* After restoring from 'saved' state, machine-window(s) geometry should be adjusted: */
306 machineLogic()->adjustMachineWindowsGeometry();
307 }
308 else
309 {
310 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_start_90px.png");
311 /* After VM start, machine-window(s) size-hint(s) should be sent: */
312 machineLogic()->sendMachineWindowsSizeHints();
313 }
314
315 /* Check for progress failure: */
316 if (!progress.isOk() || progress.GetResultCode() != 0)
317 {
318 if (vboxGlobal().showStartVMErrors())
319 msgCenter().cannotStartMachine(progress, machineName());
320 LogRel(("GUI: Aborting startup due to power up progress issue detected...\n"));
321 return false;
322 }
323
324 /* Disable 'manual-override' finally: */
325 if (machineLogic())
326 machineLogic()->setManualOverrideMode(false);
327
328 /* True by default: */
329 return true;
330}
331
332bool UISession::detach()
333{
334 /* Nothing here for now: */
335 return true;
336}
337
338bool UISession::saveState()
339{
340 /* Prepare the saving progress: */
341 CProgress progress = machine().SaveState();
342 if (machine().isOk())
343 {
344 /* Show the saving progress: */
345 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_state_save_90px.png");
346 if (!progress.isOk() || progress.GetResultCode() != 0)
347 {
348 /* Failed in progress: */
349 msgCenter().cannotSaveMachineState(progress, machineName());
350 return false;
351 }
352 }
353 else
354 {
355 /* Failed in console: */
356 msgCenter().cannotSaveMachineState(machine());
357 return false;
358 }
359 /* Passed: */
360 return true;
361}
362
363bool UISession::shutdown()
364{
365 /* Send ACPI shutdown signal if possible: */
366 console().PowerButton();
367 if (!console().isOk())
368 {
369 /* Failed in console: */
370 msgCenter().cannotACPIShutdownMachine(console());
371 return false;
372 }
373 /* Passed: */
374 return true;
375}
376
377bool UISession::powerOff(bool fIncludingDiscard, bool &fServerCrashed)
378{
379 /* Prepare the power-off progress: */
380 LogRel(("GUI: Powering VM down on UI session power off request...\n"));
381 CProgress progress = console().PowerDown();
382 if (console().isOk())
383 {
384 /* Show the power-off progress: */
385 msgCenter().showModalProgressDialog(progress, machineName(), ":/progress_poweroff_90px.png");
386 if (progress.isOk() && progress.GetResultCode() == 0)
387 {
388 /* Discard the current state if requested: */
389 if (fIncludingDiscard)
390 return restoreCurrentSnapshot();
391 }
392 else
393 {
394 /* Failed in progress: */
395 msgCenter().cannotPowerDownMachine(progress, machineName());
396 return false;
397 }
398 }
399 else
400 {
401 /* Check the machine state, it might be already gone: */
402 if (!console().isNull())
403 {
404 /* Failed in console: */
405 COMResult res(console());
406 /* This can happen if VBoxSVC is not running: */
407 if (FAILED_DEAD_INTERFACE(res.rc()))
408 fServerCrashed = true;
409 else
410 msgCenter().cannotPowerDownMachine(console());
411 return false;
412 }
413 }
414 /* Passed: */
415 return true;
416}
417
418bool UISession::restoreCurrentSnapshot()
419{
420 /* Prepare result: */
421 bool fResult = false;
422
423 /* Simulate try-catch block: */
424 do
425 {
426 /* Search for corresponding VM: */
427 CVirtualBox vbox = vboxGlobal().virtualBox();
428 const QUuid uMachineID = vboxGlobal().managedVMUuid();
429 const CMachine mach = vbox.FindMachine(uMachineID.toString());
430 if (!vbox.isOk() || mach.isNull())
431 {
432 /* Unable to find VM: */
433 msgCenter().cannotFindMachineById(vbox, uMachineID);
434 break;
435 }
436
437 /* Open a direct session to modify that VM: */
438 CSession sess = vboxGlobal().openSession(vboxGlobal().managedVMUuid(),
439 vboxGlobal().isSeparateProcess()
440 ? KLockType_Write : KLockType_Shared);
441 if (sess.isNull())
442 {
443 /* Unable to open session: */
444 break;
445 }
446
447 /* Simulate try-catch block: */
448 do
449 {
450 /* Acquire machine for this session: */
451 CMachine machine = sess.GetMachine();
452 if (machine.isNull())
453 {
454 /* Unable to acquire machine: */
455 break;
456 }
457
458 /* Prepare the snapshot-discard progress: */
459 const CSnapshot snap = machine.GetCurrentSnapshot();
460 CProgress prog = machine.RestoreSnapshot(snap);
461 if (!machine.isOk() || prog.isNull())
462 {
463 /* Unable to restore snapshot: */
464 msgCenter().cannotRestoreSnapshot(machine, snap.GetName(), machineName());
465 break;
466 }
467
468 /* Show the snapshot-discard progress: */
469 msgCenter().showModalProgressDialog(prog, machine.GetName(), ":/progress_snapshot_discard_90px.png");
470 if (prog.GetResultCode() != 0)
471 {
472 /* Unable to restore snapshot: */
473 msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), machine.GetName());
474 break;
475 }
476
477 /* Success: */
478 fResult = true;
479 }
480 while (0);
481
482 /* Unlock machine finally: */
483 sess.UnlockMachine();
484 }
485 while (0);
486
487 /* Return result: */
488 return fResult;
489}
490
491UIMachineLogic* UISession::machineLogic() const
492{
493 return uimachine() ? uimachine()->machineLogic() : 0;
494}
495
496QWidget* UISession::mainMachineWindow() const
497{
498 return machineLogic() ? machineLogic()->mainMachineWindow() : 0;
499}
500
501WId UISession::mainMachineWindowId() const
502{
503 return mainMachineWindow()->winId();
504}
505
506UIMachineWindow *UISession::activeMachineWindow() const
507{
508 return machineLogic() ? machineLogic()->activeMachineWindow() : 0;
509}
510
511bool UISession::isVisualStateAllowed(UIVisualStateType state) const
512{
513 return m_pMachine->isVisualStateAllowed(state);
514}
515
516void UISession::changeVisualState(UIVisualStateType visualStateType)
517{
518 m_pMachine->asyncChangeVisualState(visualStateType);
519}
520
521bool UISession::setPause(bool fOn)
522{
523 if (fOn)
524 console().Pause();
525 else
526 console().Resume();
527
528 bool ok = console().isOk();
529 if (!ok)
530 {
531 if (fOn)
532 msgCenter().cannotPauseMachine(console());
533 else
534 msgCenter().cannotResumeMachine(console());
535 }
536
537 return ok;
538}
539
540void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
541{
542 /* This flag indicates whether we want to do the usual .ISO mounting or not.
543 * First try updating the Guest Additions directly without mounting the .ISO. */
544 bool fDoMount = false;
545
546 /* Auto-update through GUI is currently disabled. */
547#ifndef VBOX_WITH_ADDITIONS_AUTOUPDATE_UI
548 fDoMount = true;
549#else /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */
550 /* Initiate installation progress: */
551 QVector<QString> aArgs;
552 QVector<KAdditionsUpdateFlag> aFlagsUpdate;
553 CProgress comProgressInstall = guest().UpdateGuestAdditions(strSource, aArgs, aFlagsUpdate);
554 if (guest().isOk() && comProgressInstall.isNotNull())
555 {
556 /* Show installation progress: */
557 msgCenter().showModalProgressDialog(comProgressInstall, tr("Updating Guest Additions"),
558 ":/progress_install_guest_additions_90px.png",
559 0, 500 /* 500ms delay. */);
560 if (comProgressInstall.GetCanceled())
561 return;
562
563 /* Check whether progress result isn't Ok: */
564 const HRESULT rc = comProgressInstall.GetResultCode();
565 if (!comProgressInstall.isOk() || rc != S_OK)
566 {
567 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS simply isn't
568 * supported yet), so silently fall back to "old" .ISO mounting method. */
569 if ( !SUCCEEDED_WARNING(rc)
570 && rc != VBOX_E_NOT_SUPPORTED)
571 {
572 msgCenter().cannotUpdateGuestAdditions(comProgressInstall);
573
574 /* Throw the error message into release log as well: */
575 const QString &strErr = comProgressInstall.GetErrorInfo().GetText();
576 if (!strErr.isEmpty())
577 LogRel(("%s\n", strErr.toLatin1().constData()));
578 }
579
580 /* Since automatic updating failed, fall back to .ISO mounting: */
581 fDoMount = true;
582 }
583 }
584#endif /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */
585
586 /* Check whether we still want mounting? */
587 if (!fDoMount)
588 return;
589
590 /* Mount medium add-hoc: */
591 mountAdHocImage(KDeviceType_DVD, UIMediumDeviceType_DVD, strSource);
592}
593
594void UISession::sltCloseRuntimeUI()
595{
596 /* Ask UIMachine to close Runtime UI: */
597 uimachine()->closeRuntimeUI();
598}
599
600#ifdef RT_OS_DARWIN
601void UISession::sltHandleMenuBarConfigurationChange(const QUuid &uMachineID)
602{
603 /* Skip unrelated machine IDs: */
604 if (vboxGlobal().managedVMUuid() != uMachineID)
605 return;
606
607 /* Update Mac OS X menu-bar: */
608 updateMenu();
609}
610#endif /* RT_OS_DARWIN */
611
612void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape)
613{
614 /* In case of shape data is present: */
615 if (shape.size() > 0)
616 {
617 /* We are ignoring visibility flag: */
618 m_fIsHidingHostPointer = false;
619
620 /* And updating current cursor shape: */
621 setPointerShape(shape.data(), fAlpha,
622 hotCorner.x(), hotCorner.y(),
623 size.width(), size.height());
624 }
625 /* In case of shape data is NOT present: */
626 else
627 {
628 /* Remember if we should hide the cursor: */
629 m_fIsHidingHostPointer = !fVisible;
630 }
631
632 /* Notify listeners about mouse capability changed: */
633 emit sigMousePointerShapeChange();
634
635}
636
637void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fSupportsMultiTouch, bool fNeedsHostCursor)
638{
639 LogRelFlow(("GUI: UISession::sltMouseCapabilityChange: "
640 "Supports absolute: %s, Supports relative: %s, "
641 "Supports multi-touch: %s, Needs host cursor: %s\n",
642 fSupportsAbsolute ? "TRUE" : "FALSE", fSupportsRelative ? "TRUE" : "FALSE",
643 fSupportsMultiTouch ? "TRUE" : "FALSE", fNeedsHostCursor ? "TRUE" : "FALSE"));
644
645 /* Check if something had changed: */
646 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute
647 || m_fIsMouseSupportsRelative != fSupportsRelative
648 || m_fIsMouseSupportsMultiTouch != fSupportsMultiTouch
649 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor)
650 {
651 /* Store new data: */
652 m_fIsMouseSupportsAbsolute = fSupportsAbsolute;
653 m_fIsMouseSupportsRelative = fSupportsRelative;
654 m_fIsMouseSupportsMultiTouch = fSupportsMultiTouch;
655 m_fIsMouseHostCursorNeeded = fNeedsHostCursor;
656
657 /* Notify listeners about mouse capability changed: */
658 emit sigMouseCapabilityChange();
659 }
660}
661
662void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock)
663{
664 /* Check if something had changed: */
665 if ( m_fNumLock != fNumLock
666 || m_fCapsLock != fCapsLock
667 || m_fScrollLock != fScrollLock)
668 {
669 /* Store new num lock data: */
670 if (m_fNumLock != fNumLock)
671 {
672 m_fNumLock = fNumLock;
673 m_uNumLockAdaptionCnt = 2;
674 }
675
676 /* Store new caps lock data: */
677 if (m_fCapsLock != fCapsLock)
678 {
679 m_fCapsLock = fCapsLock;
680 m_uCapsLockAdaptionCnt = 2;
681 }
682
683 /* Store new scroll lock data: */
684 if (m_fScrollLock != fScrollLock)
685 {
686 m_fScrollLock = fScrollLock;
687 }
688
689 /* Notify listeners about mouse capability changed: */
690 emit sigKeyboardLedsChange();
691 }
692}
693
694void UISession::sltStateChange(KMachineState state)
695{
696 /* Check if something had changed: */
697 if (m_machineState != state)
698 {
699 /* Store new data: */
700 m_machineStatePrevious = m_machineState;
701 m_machineState = state;
702
703 /* Notify listeners about machine state changed: */
704 emit sigMachineStateChange();
705 }
706}
707
708void UISession::sltVRDEChange()
709{
710 /* Make sure VRDE server is present: */
711 const CVRDEServer server = machine().GetVRDEServer();
712 AssertMsgReturnVoid(machine().isOk() && !server.isNull(),
713 ("VRDE server should NOT be null!\n"));
714
715 /* Check/Uncheck VRDE Server action depending on feature status: */
716 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(true);
717 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->setChecked(server.GetEnabled());
718 actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)->blockSignals(false);
719
720 /* Notify listeners about VRDE change: */
721 emit sigVRDEChange();
722}
723
724void UISession::sltRecordingChange()
725{
726 CRecordingSettings comRecordingSettings = machine().GetRecordingSettings();
727
728 /* Check/Uncheck Capture action depending on feature status: */
729 actionPool()->action(UIActionIndexRT_M_View_M_Recording_T_Start)->blockSignals(true);
730 actionPool()->action(UIActionIndexRT_M_View_M_Recording_T_Start)->setChecked(comRecordingSettings.GetEnabled());
731 actionPool()->action(UIActionIndexRT_M_View_M_Recording_T_Start)->blockSignals(false);
732
733 /* Notify listeners about Recording change: */
734 emit sigRecordingChange();
735}
736
737void UISession::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo)
738{
739 /* Ignore KGuestMonitorChangedEventType_NewOrigin change event: */
740 if (changeType == KGuestMonitorChangedEventType_NewOrigin)
741 return;
742 /* Ignore KGuestMonitorChangedEventType_Disabled event for primary screen: */
743 AssertMsg(countOfVisibleWindows() > 0, ("All machine windows are hidden!"));
744 if (changeType == KGuestMonitorChangedEventType_Disabled && uScreenId == 0)
745 return;
746
747 /* Process KGuestMonitorChangedEventType_Enabled change event: */
748 if ( !isScreenVisible(uScreenId)
749 && changeType == KGuestMonitorChangedEventType_Enabled)
750 setScreenVisible(uScreenId, true);
751 /* Process KGuestMonitorChangedEventType_Disabled change event: */
752 else if ( isScreenVisible(uScreenId)
753 && changeType == KGuestMonitorChangedEventType_Disabled)
754 setScreenVisible(uScreenId, false);
755
756 /* Notify listeners about the change: */
757 emit sigGuestMonitorChange(changeType, uScreenId, screenGeo);
758}
759
760void UISession::sltHandleStorageDeviceChange(const CMediumAttachment &attachment, bool fRemoved, bool fSilent)
761{
762 /* Update action restrictions: */
763 updateActionRestrictions();
764
765 /* Notify listeners about storage device change: */
766 emit sigStorageDeviceChange(attachment, fRemoved, fSilent);
767}
768
769void UISession::sltAudioAdapterChange()
770{
771 /* Make sure Audio adapter is present: */
772 const CAudioAdapter comAdapter = machine().GetAudioAdapter();
773 AssertMsgReturnVoid(machine().isOk() && comAdapter.isNotNull(),
774 ("Audio adapter should NOT be null!\n"));
775
776 /* Check/Uncheck Audio adapter output/input actions depending on features status: */
777 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Output)->blockSignals(true);
778 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Output)->setChecked(comAdapter.GetEnabledOut());
779 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Output)->blockSignals(false);
780 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Input)->blockSignals(true);
781 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Input)->setChecked(comAdapter.GetEnabledIn());
782 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Input)->blockSignals(false);
783
784 /* Notify listeners about Audio adapter change: */
785 emit sigAudioAdapterChange();
786
787}
788
789#ifdef RT_OS_DARWIN
790/**
791 * MacOS X: Restarts display-reconfiguration watchdog timer from the beginning.
792 * @note Watchdog is trying to determine display reconfiguration in
793 * UISession::sltCheckIfHostDisplayChanged() slot every 500ms for 40 tries.
794 */
795void UISession::sltHandleHostDisplayAboutToChange()
796{
797 LogRelFlow(("GUI: UISession::sltHandleHostDisplayAboutToChange()\n"));
798
799 if (m_pWatchdogDisplayChange->isActive())
800 m_pWatchdogDisplayChange->stop();
801 m_pWatchdogDisplayChange->setProperty("tryNumber", 1);
802 m_pWatchdogDisplayChange->start();
803}
804
805/**
806 * MacOS X: Determines display reconfiguration.
807 * @note Calls for UISession::sltHandleHostScreenCountChange() if screen count changed.
808 * @note Calls for UISession::sltHandleHostScreenGeometryChange() if screen geometry changed.
809 */
810void UISession::sltCheckIfHostDisplayChanged()
811{
812 LogRelFlow(("GUI: UISession::sltCheckIfHostDisplayChanged()\n"));
813
814 /* Check if display count changed: */
815 if (gpDesktop->screenCount() != m_hostScreens.size())
816 {
817 /* Reset watchdog: */
818 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
819 /* Notify listeners about screen-count changed: */
820 return sltHandleHostScreenCountChange();
821 }
822 else
823 {
824 /* Check if at least one display geometry changed: */
825 for (int iScreenIndex = 0; iScreenIndex < gpDesktop->screenCount(); ++iScreenIndex)
826 {
827 if (gpDesktop->screenGeometry(iScreenIndex) != m_hostScreens.at(iScreenIndex))
828 {
829 /* Reset watchdog: */
830 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
831 /* Notify listeners about screen-geometry changed: */
832 return sltHandleHostScreenGeometryChange();
833 }
834 }
835 }
836
837 /* Check if watchdog expired, restart if not: */
838 int cTryNumber = m_pWatchdogDisplayChange->property("tryNumber").toInt();
839 if (cTryNumber > 0 && cTryNumber < 40)
840 {
841 /* Restart watchdog again: */
842 m_pWatchdogDisplayChange->setProperty("tryNumber", ++cTryNumber);
843 m_pWatchdogDisplayChange->start();
844 }
845 else
846 {
847 /* Reset watchdog: */
848 m_pWatchdogDisplayChange->setProperty("tryNumber", 0);
849 }
850}
851#endif /* RT_OS_DARWIN */
852
853void UISession::sltHandleHostScreenCountChange()
854{
855 LogRelFlow(("GUI: UISession: Host-screen count changed.\n"));
856
857 /* Recache display data: */
858 updateHostScreenData();
859
860 /* Notify current machine-logic: */
861 emit sigHostScreenCountChange();
862}
863
864void UISession::sltHandleHostScreenGeometryChange()
865{
866 LogRelFlow(("GUI: UISession: Host-screen geometry changed.\n"));
867
868 /* Recache display data: */
869 updateHostScreenData();
870
871 /* Notify current machine-logic: */
872 emit sigHostScreenGeometryChange();
873}
874
875void UISession::sltHandleHostScreenAvailableAreaChange()
876{
877 LogRelFlow(("GUI: UISession: Host-screen available-area changed.\n"));
878
879 /* Notify current machine-logic: */
880 emit sigHostScreenAvailableAreaChange();
881}
882
883void UISession::sltAdditionsChange()
884{
885 /* Variable flags: */
886 ULONG ulGuestAdditionsRunLevel = guest().GetAdditionsRunLevel();
887 LONG64 lLastUpdatedIgnored;
888 bool fIsGuestSupportsGraphics = guest().GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored)
889 == KAdditionsFacilityStatus_Active;
890 bool fIsGuestSupportsSeamless = guest().GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored)
891 == KAdditionsFacilityStatus_Active;
892 /* Check if something had changed: */
893 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel ||
894 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
895 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
896 {
897 /* Store new data: */
898 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
899 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
900 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
901
902 /* Make sure action-pool knows whether GA supports graphics: */
903 actionPool()->toRuntime()->setGuestSupportsGraphics(m_fIsGuestSupportsGraphics);
904
905 /* Notify listeners about GA state really changed: */
906 LogRel(("GUI: UISession::sltAdditionsChange: GA state really changed, notifying listeners\n"));
907 emit sigAdditionsStateActualChange();
908 }
909
910 /* Notify listeners about GA state change event came: */
911 LogRel(("GUI: UISession::sltAdditionsChange: GA state change event came, notifying listeners\n"));
912 emit sigAdditionsStateChange();
913}
914
915UISession::UISession(UIMachine *pMachine)
916 : QObject(pMachine)
917 /* Base variables: */
918 , m_pMachine(pMachine)
919 , m_pActionPool(0)
920#ifdef VBOX_WS_MAC
921 , m_pMenuBar(0)
922#endif /* VBOX_WS_MAC */
923 /* Common variables: */
924 , m_machineStatePrevious(KMachineState_Null)
925 , m_machineState(KMachineState_Null)
926 , m_pMachineWindowIcon(0)
927 , m_requestedVisualStateType(UIVisualStateType_Invalid)
928#ifdef VBOX_WS_WIN
929 , m_alphaCursor(0)
930#endif /* VBOX_WS_WIN */
931#ifdef VBOX_WS_MAC
932 , m_pWatchdogDisplayChange(0)
933#endif /* VBOX_WS_MAC */
934 , m_defaultCloseAction(MachineCloseAction_Invalid)
935 , m_restrictedCloseActions(MachineCloseAction_Invalid)
936 , m_fAllCloseActionsRestricted(false)
937 /* Common flags: */
938 , m_fInitialized(false)
939 , m_fIsFirstTimeStarted(false)
940 , m_fIsGuestResizeIgnored(false)
941 , m_fIsAutoCaptureDisabled(false)
942 /* Guest additions flags: */
943 , m_ulGuestAdditionsRunLevel(0)
944 , m_fIsGuestSupportsGraphics(false)
945 , m_fIsGuestSupportsSeamless(false)
946 /* Mouse flags: */
947 , m_fNumLock(false)
948 , m_fCapsLock(false)
949 , m_fScrollLock(false)
950 , m_uNumLockAdaptionCnt(2)
951 , m_uCapsLockAdaptionCnt(2)
952 /* Mouse flags: */
953 , m_fIsMouseSupportsAbsolute(false)
954 , m_fIsMouseSupportsRelative(false)
955 , m_fIsMouseSupportsMultiTouch(false)
956 , m_fIsMouseHostCursorNeeded(false)
957 , m_fIsMouseCaptured(false)
958 , m_fIsMouseIntegrated(true)
959 , m_fIsValidPointerShapePresent(false)
960 , m_fIsHidingHostPointer(true)
961 , m_enmVMExecutionEngine(KVMExecutionEngine_NotSet)
962 /* CPU hardware virtualization features for VM: */
963 , m_fIsHWVirtExNestedPagingEnabled(false)
964 , m_fIsHWVirtExUXEnabled(false)
965 /* VM's effective paravirtualization provider: */
966 , m_paraVirtProvider(KParavirtProvider_None)
967{
968}
969
970UISession::~UISession()
971{
972}
973
974bool UISession::prepare()
975{
976 /* Prepare session: */
977 if (!prepareSession())
978 return false;
979
980 /* Prepare actions: */
981 prepareActions();
982
983 /* Prepare connections: */
984 prepareConnections();
985
986 /* Prepare console event-handlers: */
987 prepareConsoleEventHandlers();
988
989 /* Prepare screens: */
990 prepareScreens();
991
992 /* Prepare framebuffers: */
993 prepareFramebuffers();
994
995 /* Load settings: */
996 loadSessionSettings();
997
998#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
999 struct sigaction sa;
1000 sa.sa_sigaction = &signalHandlerSIGUSR1;
1001 sigemptyset(&sa.sa_mask);
1002 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1003 sigaction(SIGUSR1, &sa, NULL);
1004#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
1005
1006 /* True by default: */
1007 return true;
1008}
1009
1010bool UISession::prepareSession()
1011{
1012 /* Open session: */
1013 m_session = vboxGlobal().openSession(vboxGlobal().managedVMUuid(),
1014 vboxGlobal().isSeparateProcess()
1015 ? KLockType_Shared : KLockType_VM);
1016 if (m_session.isNull())
1017 return false;
1018
1019 /* Get machine: */
1020 m_machine = m_session.GetMachine();
1021 if (m_machine.isNull())
1022 return false;
1023
1024 /* Get console: */
1025 m_console = m_session.GetConsole();
1026 if (m_console.isNull())
1027 return false;
1028
1029 /* Get display: */
1030 m_display = m_console.GetDisplay();
1031 if (m_display.isNull())
1032 return false;
1033
1034 /* Get guest: */
1035 m_guest = m_console.GetGuest();
1036 if (m_guest.isNull())
1037 return false;
1038
1039 /* Get mouse: */
1040 m_mouse = m_console.GetMouse();
1041 if (m_mouse.isNull())
1042 return false;
1043
1044 /* Get keyboard: */
1045 m_keyboard = m_console.GetKeyboard();
1046 if (m_keyboard.isNull())
1047 return false;
1048
1049 /* Get debugger: */
1050 m_debugger = m_console.GetDebugger();
1051 if (m_debugger.isNull())
1052 return false;
1053
1054 /* Update machine-name: */
1055 m_strMachineName = machine().GetName();
1056
1057 /* Update machine-state: */
1058 m_machineState = machine().GetState();
1059
1060 /* True by default: */
1061 return true;
1062}
1063
1064void UISession::prepareActions()
1065{
1066 /* Create action-pool: */
1067 m_pActionPool = UIActionPool::create(UIActionPoolType_Runtime);
1068 AssertPtrReturnVoid(actionPool());
1069 {
1070 /* Update action restrictions: */
1071 updateActionRestrictions();
1072
1073#ifdef VBOX_WS_MAC
1074 /* Create Mac OS X menu-bar: */
1075 m_pMenuBar = new QMenuBar;
1076 AssertPtrReturnVoid(m_pMenuBar);
1077 {
1078 /* Configure Mac OS X menu-bar: */
1079 connect(gEDataManager, SIGNAL(sigMenuBarConfigurationChange(const QUuid &)),
1080 this, SLOT(sltHandleMenuBarConfigurationChange(const QUuid &)));
1081 /* Update Mac OS X menu-bar: */
1082 updateMenu();
1083 }
1084#endif /* VBOX_WS_MAC */
1085 }
1086}
1087
1088void UISession::prepareConnections()
1089{
1090 connect(this, SIGNAL(sigInitialized()), this, SLOT(sltMarkInitialized()));
1091
1092#ifdef VBOX_WS_MAC
1093 /* Install native display reconfiguration callback: */
1094 CGDisplayRegisterReconfigurationCallback(cgDisplayReconfigurationCallback, this);
1095#else /* !VBOX_WS_MAC */
1096 /* Install Qt display reconfiguration callbacks: */
1097 connect(gpDesktop, SIGNAL(sigHostScreenCountChanged(int)),
1098 this, SLOT(sltHandleHostScreenCountChange()));
1099 connect(gpDesktop, SIGNAL(sigHostScreenResized(int)),
1100 this, SLOT(sltHandleHostScreenGeometryChange()));
1101# ifdef VBOX_WS_X11
1102 connect(gpDesktop, SIGNAL(sigHostScreenWorkAreaRecalculated(int)),
1103 this, SLOT(sltHandleHostScreenAvailableAreaChange()));
1104# else /* !VBOX_WS_X11 */
1105 connect(gpDesktop, SIGNAL(sigHostScreenWorkAreaResized(int)),
1106 this, SLOT(sltHandleHostScreenAvailableAreaChange()));
1107# endif /* !VBOX_WS_X11 */
1108#endif /* !VBOX_WS_MAC */
1109}
1110
1111void UISession::prepareConsoleEventHandlers()
1112{
1113 /* Create console event-handler: */
1114 UIConsoleEventHandler::create(this);
1115
1116 /* Add console event connections: */
1117 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)),
1118 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)));
1119
1120 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool, bool)),
1121 this, SLOT(sltMouseCapabilityChange(bool, bool, bool, bool)));
1122
1123 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)),
1124 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool)));
1125
1126 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)),
1127 this, SLOT(sltStateChange(KMachineState)));
1128
1129 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()),
1130 this, SLOT(sltAdditionsChange()));
1131
1132 connect(gConsoleEvents, SIGNAL(sigVRDEChange()),
1133 this, SLOT(sltVRDEChange()));
1134
1135 connect(gConsoleEvents, SIGNAL(sigRecordingChange()),
1136 this, SLOT(sltRecordingChange()));
1137
1138 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)),
1139 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)));
1140
1141 connect(gConsoleEvents, SIGNAL(sigStorageDeviceChange(CMediumAttachment, bool, bool)),
1142 this, SLOT(sltHandleStorageDeviceChange(CMediumAttachment, bool, bool)));
1143
1144 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)),
1145 this, SIGNAL(sigMediumChange(CMediumAttachment)));
1146
1147 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()),
1148 this, SIGNAL(sigUSBControllerChange()));
1149
1150 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)),
1151 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)));
1152
1153 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()),
1154 this, SIGNAL(sigSharedFolderChange()));
1155
1156 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)),
1157 this, SIGNAL(sigRuntimeError(bool, QString, QString)));
1158
1159#ifdef VBOX_WS_MAC
1160 connect(gConsoleEvents, SIGNAL(sigShowWindow()),
1161 this, SIGNAL(sigShowWindows()), Qt::QueuedConnection);
1162#endif /* VBOX_WS_MAC */
1163
1164 connect(gConsoleEvents, SIGNAL(sigCPUExecutionCapChange()),
1165 this, SIGNAL(sigCPUExecutionCapChange()));
1166
1167 connect(gConsoleEvents, SIGNAL(sigGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)),
1168 this, SLOT(sltGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)));
1169
1170 connect(gConsoleEvents, SIGNAL(sigAudioAdapterChange()),
1171 this, SLOT(sltAudioAdapterChange()));
1172}
1173
1174void UISession::prepareScreens()
1175{
1176 /* Recache display data: */
1177 updateHostScreenData();
1178
1179#ifdef VBOX_WS_MAC
1180 /* Prepare display-change watchdog: */
1181 m_pWatchdogDisplayChange = new QTimer(this);
1182 {
1183 m_pWatchdogDisplayChange->setInterval(500);
1184 m_pWatchdogDisplayChange->setSingleShot(true);
1185 connect(m_pWatchdogDisplayChange, SIGNAL(timeout()),
1186 this, SLOT(sltCheckIfHostDisplayChanged()));
1187 }
1188#endif /* VBOX_WS_MAC */
1189
1190 /* Prepare initial screen visibility status: */
1191 m_monitorVisibilityVector.resize(machine().GetMonitorCount());
1192 m_monitorVisibilityVector.fill(false);
1193 m_monitorVisibilityVector[0] = true;
1194
1195 /* Prepare empty last full-screen size vector: */
1196 m_monitorLastFullScreenSizeVector.resize(machine().GetMonitorCount());
1197 m_monitorLastFullScreenSizeVector.fill(QSize(-1, -1));
1198
1199 /* If machine is in 'saved' state: */
1200 if (isSaved())
1201 {
1202 /* Update screen visibility status from saved-state: */
1203 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1204 {
1205 BOOL fEnabled = true;
1206 ULONG uGuestOriginX = 0, uGuestOriginY = 0, uGuestWidth = 0, uGuestHeight = 0;
1207 machine().QuerySavedGuestScreenInfo(iScreenIndex,
1208 uGuestOriginX, uGuestOriginY,
1209 uGuestWidth, uGuestHeight, fEnabled);
1210 m_monitorVisibilityVector[iScreenIndex] = fEnabled;
1211 }
1212 /* And make sure at least one of them is visible (primary if others are hidden): */
1213 if (countOfVisibleWindows() < 1)
1214 m_monitorVisibilityVector[0] = true;
1215 }
1216 else if (vboxGlobal().isSeparateProcess())
1217 {
1218 /* Update screen visibility status from display directly: */
1219 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1220 {
1221 KGuestMonitorStatus enmStatus = KGuestMonitorStatus_Disabled;
1222 ULONG uGuestWidth = 0, uGuestHeight = 0, uBpp = 0;
1223 LONG iGuestOriginX = 0, iGuestOriginY = 0;
1224 display().GetScreenResolution(iScreenIndex,
1225 uGuestWidth, uGuestHeight, uBpp,
1226 iGuestOriginX, iGuestOriginY, enmStatus);
1227 m_monitorVisibilityVector[iScreenIndex] = ( enmStatus == KGuestMonitorStatus_Enabled
1228 || enmStatus == KGuestMonitorStatus_Blank);
1229 }
1230 /* And make sure at least one of them is visible (primary if others are hidden): */
1231 if (countOfVisibleWindows() < 1)
1232 m_monitorVisibilityVector[0] = true;
1233 }
1234
1235 /* Prepare initial screen visibility status of host-desires (same as facts): */
1236 m_monitorVisibilityVectorHostDesires.resize(machine().GetMonitorCount());
1237 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1238 m_monitorVisibilityVectorHostDesires[iScreenIndex] = m_monitorVisibilityVector[iScreenIndex];
1239
1240 /* Make sure action-pool knows guest-screen visibility status: */
1241 for (int iScreenIndex = 0; iScreenIndex < m_monitorVisibilityVector.size(); ++iScreenIndex)
1242 actionPool()->toRuntime()->setGuestScreenVisible(iScreenIndex, m_monitorVisibilityVector.at(iScreenIndex));
1243}
1244
1245void UISession::prepareFramebuffers()
1246{
1247 /* Each framebuffer will be really prepared on first UIMachineView creation: */
1248 m_frameBufferVector.resize(machine().GetMonitorCount());
1249
1250 /* Make sure action-pool knows guest-screen count: */
1251 actionPool()->toRuntime()->setGuestScreenCount(m_frameBufferVector.size());
1252}
1253
1254void UISession::loadSessionSettings()
1255{
1256 /* Load extra-data settings: */
1257 {
1258 /* Get machine ID: */
1259 const QUuid uMachineID = vboxGlobal().managedVMUuid();
1260
1261 /* Prepare machine-window icon: */
1262 {
1263 /* Acquire user machine-window icon: */
1264 QIcon icon = vboxGlobal().vmUserIcon(machine());
1265 /* Use the OS type icon if user one was not set: */
1266 if (icon.isNull())
1267 icon = vboxGlobal().vmGuestOSTypeIcon(machine().GetOSTypeId());
1268 /* Use the default icon if nothing else works: */
1269 if (icon.isNull())
1270 icon = QIcon(":/VirtualBox_48px.png");
1271 /* Store the icon dynamically: */
1272 m_pMachineWindowIcon = new QIcon(icon);
1273 }
1274
1275#ifndef VBOX_WS_MAC
1276 /* Load user's machine-window name postfix: */
1277 m_strMachineWindowNamePostfix = gEDataManager->machineWindowNamePostfix(uMachineID);
1278#endif
1279
1280 /* Is there should be First RUN Wizard? */
1281 m_fIsFirstTimeStarted = gEDataManager->machineFirstTimeStarted(uMachineID);
1282
1283 /* Should guest autoresize? */
1284 QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize);
1285 pGuestAutoresizeSwitch->setChecked(gEDataManager->guestScreenAutoResizeEnabled(uMachineID));
1286
1287#ifndef VBOX_WS_MAC
1288 /* Menu-bar options: */
1289 {
1290 const bool fEnabledGlobally = !gEDataManager->guiFeatureEnabled(GUIFeatureType_NoMenuBar);
1291 const bool fEnabledForMachine = gEDataManager->menuBarEnabled(uMachineID);
1292 const bool fEnabled = fEnabledGlobally && fEnabledForMachine;
1293 QAction *pActionMenuBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_S_Settings);
1294 pActionMenuBarSettings->setEnabled(fEnabled);
1295 QAction *pActionMenuBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_MenuBar_T_Visibility);
1296 pActionMenuBarSwitch->blockSignals(true);
1297 pActionMenuBarSwitch->setChecked(fEnabled);
1298 pActionMenuBarSwitch->blockSignals(false);
1299 }
1300#endif /* !VBOX_WS_MAC */
1301
1302 /* Status-bar options: */
1303 {
1304 const bool fEnabledGlobally = !gEDataManager->guiFeatureEnabled(GUIFeatureType_NoStatusBar);
1305 const bool fEnabledForMachine = gEDataManager->statusBarEnabled(uMachineID);
1306 const bool fEnabled = fEnabledGlobally && fEnabledForMachine;
1307 QAction *pActionStatusBarSettings = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_S_Settings);
1308 pActionStatusBarSettings->setEnabled(fEnabled);
1309 QAction *pActionStatusBarSwitch = actionPool()->action(UIActionIndexRT_M_View_M_StatusBar_T_Visibility);
1310 pActionStatusBarSwitch->blockSignals(true);
1311 pActionStatusBarSwitch->setChecked(fEnabled);
1312 pActionStatusBarSwitch->blockSignals(false);
1313 }
1314
1315 /* Input options: */
1316 actionPool()->action(UIActionIndexRT_M_Input_M_Mouse_T_Integration)->setChecked(isMouseIntegrated());
1317
1318 /* Devices options: */
1319 {
1320 const CAudioAdapter comAudio = m_machine.GetAudioAdapter();
1321 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Output)->blockSignals(true);
1322 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Output)->setChecked(comAudio.GetEnabledOut());
1323 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Output)->blockSignals(false);
1324 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Input)->blockSignals(true);
1325 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Input)->setChecked(comAudio.GetEnabledIn());
1326 actionPool()->action(UIActionIndexRT_M_Devices_M_Audio_T_Input)->blockSignals(false);
1327 }
1328
1329 /* What is the default close action and the restricted are? */
1330 m_defaultCloseAction = gEDataManager->defaultMachineCloseAction(uMachineID);
1331 m_restrictedCloseActions = gEDataManager->restrictedMachineCloseActions(uMachineID);
1332 m_fAllCloseActionsRestricted = (!vboxGlobal().isSeparateProcess() || (m_restrictedCloseActions & MachineCloseAction_Detach))
1333 && (m_restrictedCloseActions & MachineCloseAction_SaveState)
1334 && (m_restrictedCloseActions & MachineCloseAction_Shutdown)
1335 && (m_restrictedCloseActions & MachineCloseAction_PowerOff);
1336 // Close VM Dialog hides PowerOff_RestoringSnapshot implicitly if PowerOff is hidden..
1337 // && (m_restrictedCloseActions & MachineCloseAction_PowerOff_RestoringSnapshot);
1338 }
1339}
1340
1341void UISession::saveSessionSettings()
1342{
1343 /* Save extra-data settings: */
1344 {
1345 /* Disable First RUN Wizard: */
1346 gEDataManager->setMachineFirstTimeStarted(false, vboxGlobal().managedVMUuid());
1347
1348 /* Remember if guest should autoresize: */
1349 if (actionPool())
1350 {
1351 const QAction *pGuestAutoresizeSwitch = actionPool()->action(UIActionIndexRT_M_View_T_GuestAutoresize);
1352 gEDataManager->setGuestScreenAutoResizeEnabled(pGuestAutoresizeSwitch->isChecked(), vboxGlobal().managedVMUuid());
1353 }
1354
1355 /* Cleanup machine-window icon: */
1356 delete m_pMachineWindowIcon;
1357 m_pMachineWindowIcon = 0;
1358 }
1359}
1360
1361void UISession::cleanupFramebuffers()
1362{
1363 /* Cleanup framebuffers finally: */
1364 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i)
1365 {
1366 UIFrameBuffer *pFrameBuffer = m_frameBufferVector[i];
1367 if (pFrameBuffer)
1368 {
1369 /* Mark framebuffer as unused: */
1370 pFrameBuffer->setMarkAsUnused(true);
1371 /* Detach framebuffer from Display: */
1372 pFrameBuffer->detach();
1373 /* Delete framebuffer reference: */
1374 delete pFrameBuffer;
1375 }
1376 }
1377 m_frameBufferVector.clear();
1378
1379 /* Make sure action-pool knows guest-screen count: */
1380 actionPool()->toRuntime()->setGuestScreenCount(m_frameBufferVector.size());
1381}
1382
1383void UISession::cleanupConsoleEventHandlers()
1384{
1385 /* Destroy console event-handler if necessary: */
1386 if (gConsoleEvents)
1387 UIConsoleEventHandler::destroy();
1388}
1389
1390void UISession::cleanupConnections()
1391{
1392#ifdef VBOX_WS_MAC
1393 /* Remove display reconfiguration callback: */
1394 CGDisplayRemoveReconfigurationCallback(cgDisplayReconfigurationCallback, this);
1395#endif /* VBOX_WS_MAC */
1396}
1397
1398void UISession::cleanupActions()
1399{
1400#ifdef VBOX_WS_MAC
1401 /* Destroy Mac OS X menu-bar: */
1402 delete m_pMenuBar;
1403 m_pMenuBar = 0;
1404#endif /* VBOX_WS_MAC */
1405
1406 /* Destroy action-pool if necessary: */
1407 if (actionPool())
1408 UIActionPool::destroy(actionPool());
1409}
1410
1411void UISession::cleanupSession()
1412{
1413 /* Detach debugger: */
1414 if (!m_debugger.isNull())
1415 m_debugger.detach();
1416
1417 /* Detach keyboard: */
1418 if (!m_keyboard.isNull())
1419 m_keyboard.detach();
1420
1421 /* Detach mouse: */
1422 if (!m_mouse.isNull())
1423 m_mouse.detach();
1424
1425 /* Detach guest: */
1426 if (!m_guest.isNull())
1427 m_guest.detach();
1428
1429 /* Detach display: */
1430 if (!m_display.isNull())
1431 m_display.detach();
1432
1433 /* Detach console: */
1434 if (!m_console.isNull())
1435 m_console.detach();
1436
1437 /* Detach machine: */
1438 if (!m_machine.isNull())
1439 m_machine.detach();
1440
1441 /* Close session: */
1442 if (!m_session.isNull() && vboxGlobal().isVBoxSVCAvailable())
1443 {
1444 m_session.UnlockMachine();
1445 m_session.detach();
1446 }
1447}
1448
1449void UISession::cleanup()
1450{
1451#ifdef VBOX_WS_WIN
1452 /* Destroy alpha cursor: */
1453 if (m_alphaCursor)
1454 DestroyIcon(m_alphaCursor);
1455#endif /* VBOX_WS_WIN */
1456
1457 /* Save settings: */
1458 saveSessionSettings();
1459
1460 /* Cleanup framebuffers: */
1461 cleanupFramebuffers();
1462
1463 /* Cleanup console event-handlers: */
1464 cleanupConsoleEventHandlers();
1465
1466 /* Cleanup connections: */
1467 cleanupConnections();
1468
1469 /* Cleanup actions: */
1470 cleanupActions();
1471
1472 /* Cleanup session: */
1473 cleanupSession();
1474}
1475
1476#ifdef VBOX_WS_MAC
1477void UISession::updateMenu()
1478{
1479 /* Rebuild Mac OS X menu-bar: */
1480 m_pMenuBar->clear();
1481 foreach (QMenu *pMenu, actionPool()->menus())
1482 {
1483 UIMenu *pMenuUI = qobject_cast<UIMenu*>(pMenu);
1484 if (!pMenuUI->isConsumable() || !pMenuUI->isConsumed())
1485 m_pMenuBar->addMenu(pMenuUI);
1486 if (pMenuUI->isConsumable() && !pMenuUI->isConsumed())
1487 pMenuUI->setConsumed(true);
1488 }
1489 /* Update the dock menu as well: */
1490 if (machineLogic())
1491 machineLogic()->updateDock();
1492}
1493#endif /* VBOX_WS_MAC */
1494
1495/** Generate a BGRA bitmap which approximates a XOR/AND mouse pointer.
1496 *
1497 * Pixels which has 1 in the AND mask and not 0 in the XOR mask are replaced by
1498 * the inverted pixel and 8 surrounding pixels with the original color.
1499 * Fort example a white pixel (W) is replaced with a black (B) pixel:
1500 * WWW
1501 * W -> WBW
1502 * WWW
1503 * The surrounding pixels are written only if the corresponding source pixel
1504 * does not affect the screen, i.e. AND bit is 1 and XOR value is 0.
1505 */
1506static void renderCursorPixels(const uint32_t *pu32XOR, const uint8_t *pu8AND,
1507 uint32_t u32Width, uint32_t u32Height,
1508 uint32_t *pu32Pixels, uint32_t cbPixels)
1509{
1510 /* Output pixels set to 0 which allow to not write transparent pixels anymore. */
1511 memset(pu32Pixels, 0, cbPixels);
1512
1513 const uint32_t *pu32XORSrc = pu32XOR; /* Iterator for source XOR pixels. */
1514 const uint8_t *pu8ANDSrcLine = pu8AND; /* The current AND mask scanline. */
1515 uint32_t *pu32Dst = pu32Pixels; /* Iterator for all destination BGRA pixels. */
1516
1517 /* Some useful constants. */
1518 const int cbANDLine = ((int)u32Width + 7) / 8;
1519
1520 int y;
1521 for (y = 0; y < (int)u32Height; ++y)
1522 {
1523 int x;
1524 for (x = 0; x < (int)u32Width; ++x)
1525 {
1526 const uint32_t u32Pixel = *pu32XORSrc; /* Current pixel at (x,y) */
1527 const uint8_t *pu8ANDSrc = pu8ANDSrcLine + x / 8; /* Byte which containt current AND bit. */
1528
1529 if ((*pu8ANDSrc << (x % 8)) & 0x80)
1530 {
1531 if (u32Pixel)
1532 {
1533 const uint32_t u32PixelInverted = ~u32Pixel;
1534
1535 /* Scan neighbor pixels and assign them if they are transparent. */
1536 int dy;
1537 for (dy = -1; dy <= 1; ++dy)
1538 {
1539 const int yn = y + dy;
1540 if (yn < 0 || yn >= (int)u32Height)
1541 continue; /* Do not cross the bounds. */
1542
1543 int dx;
1544 for (dx = -1; dx <= 1; ++dx)
1545 {
1546 const int xn = x + dx;
1547 if (xn < 0 || xn >= (int)u32Width)
1548 continue; /* Do not cross the bounds. */
1549
1550 if (dx != 0 || dy != 0)
1551 {
1552 /* Check if the neighbor pixel is transparent. */
1553 const uint32_t *pu32XORNeighborSrc = &pu32XORSrc[dy * (int)u32Width + dx];
1554 const uint8_t *pu8ANDNeighborSrc = pu8ANDSrcLine + dy * cbANDLine + xn / 8;
1555 if ( *pu32XORNeighborSrc == 0
1556 && ((*pu8ANDNeighborSrc << (xn % 8)) & 0x80) != 0)
1557 {
1558 /* Transparent neighbor pixels are replaced with the source pixel value. */
1559 uint32_t *pu32PixelNeighborDst = &pu32Dst[dy * (int)u32Width + dx];
1560 *pu32PixelNeighborDst = u32Pixel | 0xFF000000;
1561 }
1562 }
1563 else
1564 {
1565 /* The pixel itself is replaced with inverted value. */
1566 *pu32Dst = u32PixelInverted | 0xFF000000;
1567 }
1568 }
1569 }
1570 }
1571 else
1572 {
1573 /* The pixel does not affect the screen.
1574 * Do nothing. Do not touch destination which can already contain generated pixels.
1575 */
1576 }
1577 }
1578 else
1579 {
1580 /* AND bit is 0, the pixel will be just drawn. */
1581 *pu32Dst = u32Pixel | 0xFF000000;
1582 }
1583
1584 ++pu32XORSrc; /* Next source pixel. */
1585 ++pu32Dst; /* Next destination pixel. */
1586 }
1587
1588 /* Next AND scanline. */
1589 pu8ANDSrcLine += cbANDLine;
1590 }
1591}
1592
1593#ifdef VBOX_WS_WIN
1594static bool isPointer1bpp(const uint8_t *pu8XorMask,
1595 uint uWidth,
1596 uint uHeight)
1597{
1598 /* Check if the pointer has only 0 and 0xFFFFFF pixels, ignoring the alpha channel. */
1599 const uint32_t *pu32Src = (uint32_t *)pu8XorMask;
1600
1601 uint y;
1602 for (y = 0; y < uHeight ; ++y)
1603 {
1604 uint x;
1605 for (x = 0; x < uWidth; ++x)
1606 {
1607 const uint32_t u32Pixel = pu32Src[x] & UINT32_C(0xFFFFFF);
1608 if (u32Pixel != 0 && u32Pixel != UINT32_C(0xFFFFFF))
1609 return false;
1610 }
1611
1612 pu32Src += uWidth;
1613 }
1614
1615 return true;
1616}
1617#endif /* VBOX_WS_WIN */
1618
1619void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
1620 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
1621{
1622 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
1623
1624 m_fIsValidPointerShapePresent = false;
1625 const uchar *srcAndMaskPtr = pShapeData;
1626 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
1627 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
1628 uint srcShapePtrScan = uWidth * 4;
1629
1630#if defined (VBOX_WS_WIN)
1631
1632 /* Create a ARGB image out of the shape data: */
1633
1634 /*
1635 * Qt5 QCursor recommends 32 x 32 cursor, therefore the original data is copied to
1636 * a larger QImage if necessary. Cursors like 10x16 did not work correctly (Solaris 10 guest).
1637 */
1638 uint uCursorWidth = uWidth >= 32? uWidth: 32;
1639 uint uCursorHeight = uHeight >= 32? uHeight: 32;
1640 uint x, y;
1641
1642 if (fHasAlpha)
1643 {
1644 QImage image(uCursorWidth, uCursorHeight, QImage::Format_ARGB32);
1645 memset(image.bits(), 0, image.byteCount());
1646
1647 const uint32_t *pu32SrcShapeScanline = (uint32_t *)srcShapePtr;
1648 for (y = 0; y < uHeight; ++y, pu32SrcShapeScanline += uWidth)
1649 memcpy(image.scanLine(y), pu32SrcShapeScanline, uWidth * sizeof(uint32_t));
1650
1651 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
1652 }
1653 else
1654 {
1655 if (isPointer1bpp(srcShapePtr, uWidth, uHeight))
1656 {
1657 /* Incoming data consist of 32 bit BGR XOR mask and 1 bit AND mask.
1658 * XOR pixels contain either 0x00000000 or 0x00FFFFFF.
1659 *
1660 * Originally intended result (F denotes 0x00FFFFFF):
1661 * XOR AND
1662 * 0 0 black
1663 * F 0 white
1664 * 0 1 transparent
1665 * F 1 xor'd
1666 *
1667 * Actual Qt5 result for color table 0:0xFF000000, 1:0xFFFFFFFF
1668 * (tested on Windows 7 and 10 64 bit hosts):
1669 * Bitmap Mask
1670 * 0 0 black
1671 * 1 0 white
1672 * 0 1 xor
1673 * 1 1 transparent
1674 *
1675 */
1676
1677 QVector<QRgb> colors(2);
1678 colors[0] = UINT32_C(0xFF000000);
1679 colors[1] = UINT32_C(0xFFFFFFFF);
1680
1681 QImage bitmap(uCursorWidth, uCursorHeight, QImage::Format_Mono);
1682 bitmap.setColorTable(colors);
1683 memset(bitmap.bits(), 0xFF, bitmap.byteCount());
1684
1685 QImage mask(uCursorWidth, uCursorHeight, QImage::Format_Mono);
1686 mask.setColorTable(colors);
1687 memset(mask.bits(), 0xFF, mask.byteCount());
1688
1689 const uint8_t *pu8SrcAndScanline = srcAndMaskPtr;
1690 const uint32_t *pu32SrcShapeScanline = (uint32_t *)srcShapePtr;
1691 for (y = 0; y < uHeight; ++y)
1692 {
1693 for (x = 0; x < uWidth; ++x)
1694 {
1695 const uint8_t u8Bit = (uint8_t)(1 << (7 - x % 8));
1696
1697 const uint8_t u8SrcMaskByte = pu8SrcAndScanline[x / 8];
1698 const uint8_t u8SrcMaskBit = u8SrcMaskByte & u8Bit;
1699 const uint32_t u32SrcPixel = pu32SrcShapeScanline[x] & UINT32_C(0xFFFFFF);
1700
1701 uint8_t *pu8DstMaskByte = &mask.scanLine(y)[x / 8];
1702 uint8_t *pu8DstBitmapByte = &bitmap.scanLine(y)[x / 8];
1703
1704 if (u8SrcMaskBit == 0)
1705 {
1706 if (u32SrcPixel == 0)
1707 {
1708 /* Black: Qt Bitmap = 0, Mask = 0 */
1709 *pu8DstMaskByte &= ~u8Bit;
1710 *pu8DstBitmapByte &= ~u8Bit;
1711 }
1712 else
1713 {
1714 /* White: Qt Bitmap = 1, Mask = 0 */
1715 *pu8DstMaskByte &= ~u8Bit;
1716 *pu8DstBitmapByte |= u8Bit;
1717 }
1718 }
1719 else
1720 {
1721 if (u32SrcPixel == 0)
1722 {
1723 /* Transparent: Qt Bitmap = 1, Mask = 1 */
1724 *pu8DstMaskByte |= u8Bit;
1725 *pu8DstBitmapByte |= u8Bit;
1726 }
1727 else
1728 {
1729 /* Xor'ed: Qt Bitmap = 0, Mask = 1 */
1730 *pu8DstMaskByte |= u8Bit;
1731 *pu8DstBitmapByte &= ~u8Bit;
1732 }
1733 }
1734 }
1735
1736 pu8SrcAndScanline += (uWidth + 7) / 8;
1737 pu32SrcShapeScanline += uWidth;
1738 }
1739
1740 m_cursor = QCursor(QBitmap::fromImage(bitmap), QBitmap::fromImage(mask), uXHot, uYHot);
1741 }
1742 else
1743 {
1744 /* Assign alpha channel values according to the AND mask: 1 -> 0x00, 0 -> 0xFF: */
1745 QImage image(uCursorWidth, uCursorHeight, QImage::Format_ARGB32);
1746 memset(image.bits(), 0, image.byteCount());
1747
1748 const uint8_t *pu8SrcAndScanline = srcAndMaskPtr;
1749 const uint32_t *pu32SrcShapeScanline = (uint32_t *)srcShapePtr;
1750
1751 for (y = 0; y < uHeight; ++y)
1752 {
1753 uint32_t *pu32DstPixel = (uint32_t *)image.scanLine(y);
1754
1755 for (x = 0; x < uWidth; ++x)
1756 {
1757 const uint8_t u8Bit = (uint8_t)(1 << (7 - x % 8));
1758 const uint8_t u8SrcMaskByte = pu8SrcAndScanline[x / 8];
1759
1760 if (u8SrcMaskByte & u8Bit)
1761 *pu32DstPixel++ = pu32SrcShapeScanline[x] & UINT32_C(0x00FFFFFF);
1762 else
1763 *pu32DstPixel++ = pu32SrcShapeScanline[x] | UINT32_C(0xFF000000);
1764 }
1765
1766 pu32SrcShapeScanline += uWidth;
1767 pu8SrcAndScanline += (uWidth + 7) / 8;
1768 }
1769
1770 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
1771 }
1772 }
1773
1774 m_fIsValidPointerShapePresent = true;
1775 NOREF(srcShapePtrScan);
1776
1777#elif defined(VBOX_WS_X11) || defined(VBOX_WS_MAC)
1778
1779 /* Create a ARGB image out of the shape data: */
1780 QImage image(uWidth, uHeight, QImage::Format_ARGB32);
1781
1782 if (fHasAlpha)
1783 {
1784 memcpy(image.bits(), srcShapePtr, uHeight * uWidth * 4);
1785 }
1786 else
1787 {
1788 renderCursorPixels((uint32_t *)srcShapePtr, srcAndMaskPtr,
1789 uWidth, uHeight,
1790 (uint32_t *)image.bits(), uHeight * uWidth * 4);
1791 }
1792
1793 /* Create cursor-pixmap from the image: */
1794 QPixmap cursorPixmap = QPixmap::fromImage(image);
1795
1796# if defined(VBOX_WS_MAC)
1797 /* Adjust device-pixel-ratio: */
1798 /// @todo In case of multi-monitor setup check whether device-pixel-ratio and cursor are screen specific.
1799 /* Get screen-id of main-window: */
1800 const ulong uScreenID = activeMachineWindow()->screenId();
1801 /* Get device-pixel-ratio: */
1802 const double dDevicePixelRatio = frameBuffer(uScreenID)->devicePixelRatio();
1803 /* Adjust device-pixel-ratio if necessary: */
1804 if (dDevicePixelRatio > 1.0 && frameBuffer(uScreenID)->useUnscaledHiDPIOutput())
1805 {
1806 uXHot /= dDevicePixelRatio;
1807 uYHot /= dDevicePixelRatio;
1808 cursorPixmap.setDevicePixelRatio(dDevicePixelRatio);
1809 }
1810# elif defined(VBOX_WS_X11)
1811 /* Adjust device-pixel-ratio: */
1812 /// @todo In case of multi-monitor setup check whether device-pixel-ratio and cursor are screen specific.
1813 /* Get screen-id of main-window: */
1814 const ulong uScreenID = activeMachineWindow()->screenId();
1815 /* Get device-pixel-ratio: */
1816 const double dDevicePixelRatio = frameBuffer(uScreenID)->devicePixelRatio();
1817 /* Adjust device-pixel-ratio if necessary: */
1818 if (dDevicePixelRatio > 1.0 && !frameBuffer(uScreenID)->useUnscaledHiDPIOutput())
1819 {
1820 uXHot *= dDevicePixelRatio;
1821 uYHot *= dDevicePixelRatio;
1822 cursorPixmap = cursorPixmap.scaled(cursorPixmap.width() * dDevicePixelRatio, cursorPixmap.height() * dDevicePixelRatio,
1823 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
1824 }
1825# endif /* VBOX_WS_X11 */
1826
1827 /* Set the new cursor: */
1828 m_cursor = QCursor(cursorPixmap, uXHot, uYHot);
1829 m_fIsValidPointerShapePresent = true;
1830 NOREF(srcShapePtrScan);
1831
1832#else
1833
1834# warning "port me"
1835
1836#endif
1837}
1838
1839bool UISession::preprocessInitialization()
1840{
1841#ifdef VBOX_WITH_NETFLT
1842 /* Skip further checks if VM in saved state */
1843 if (isSaved())
1844 return true;
1845
1846 /* Make sure all the attached and enabled network
1847 * adapters are present on the host. This check makes sense
1848 * in two cases only - when attachement type is Bridged Network
1849 * or Host-only Interface. NOTE: Only currently enabled
1850 * attachement type is checked (incorrect parameters check for
1851 * currently disabled attachement types is skipped). */
1852 QStringList failedInterfaceNames;
1853 QStringList availableInterfaceNames;
1854
1855 /* Create host network interface names list */
1856 foreach (const CHostNetworkInterface &iface, vboxGlobal().host().GetNetworkInterfaces())
1857 {
1858 availableInterfaceNames << iface.GetName();
1859 availableInterfaceNames << iface.GetShortName();
1860 }
1861
1862 ulong cCount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine().GetChipsetType());
1863 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex)
1864 {
1865 CNetworkAdapter na = machine().GetNetworkAdapter(uAdapterIndex);
1866
1867 if (na.GetEnabled())
1868 {
1869 QString strIfName = QString();
1870
1871 /* Get physical network interface name for currently
1872 * enabled network attachement type */
1873 switch (na.GetAttachmentType())
1874 {
1875 case KNetworkAttachmentType_Bridged:
1876 strIfName = na.GetBridgedInterface();
1877 break;
1878 case KNetworkAttachmentType_HostOnly:
1879 strIfName = na.GetHostOnlyInterface();
1880 break;
1881 default: break; /* Shut up, MSC! */
1882 }
1883
1884 if (!strIfName.isEmpty() &&
1885 !availableInterfaceNames.contains(strIfName))
1886 {
1887 LogFlow(("Found invalid network interface: %s\n", strIfName.toStdString().c_str()));
1888 failedInterfaceNames << QString("%1 (adapter %2)").arg(strIfName).arg(uAdapterIndex + 1);
1889 }
1890 }
1891 }
1892
1893 /* Check if non-existent interfaces found */
1894 if (!failedInterfaceNames.isEmpty())
1895 {
1896 if (msgCenter().cannotStartWithoutNetworkIf(machineName(), failedInterfaceNames.join(", ")))
1897 machineLogic()->openNetworkSettingsDialog();
1898 else
1899 {
1900 LogRel(("GUI: Aborting startup due to preprocess initialization issue detected...\n"));
1901 return false;
1902 }
1903 }
1904#endif /* VBOX_WITH_NETFLT */
1905
1906 /* True by default: */
1907 return true;
1908}
1909
1910bool UISession::mountAdHocImage(KDeviceType enmDeviceType, UIMediumDeviceType enmMediumType, const QString &strMediumName)
1911{
1912 /* Get VBox: */
1913 CVirtualBox comVBox = vboxGlobal().virtualBox();
1914
1915 /* Prepare medium to mount: */
1916 UIMedium guiMedium;
1917
1918 /* The 'none' medium name means ejecting what ever is in the drive,
1919 * in that case => leave the guiMedium variable null. */
1920 if (strMediumName != "none")
1921 {
1922 /* Open the medium: */
1923 const CMedium comMedium = comVBox.OpenMedium(strMediumName, enmDeviceType, KAccessMode_ReadWrite, false /* fForceNewUuid */);
1924 if (!comVBox.isOk() || comMedium.isNull())
1925 {
1926 popupCenter().cannotOpenMedium(activeMachineWindow(), comVBox, enmMediumType, strMediumName);
1927 return false;
1928 }
1929
1930 /* Make sure medium ID is valid: */
1931 const QUuid uMediumId = comMedium.GetId();
1932 AssertReturn(!uMediumId.isNull(), false);
1933
1934 /* Try to find UIMedium among cached: */
1935 guiMedium = vboxGlobal().medium(uMediumId);
1936 if (guiMedium.isNull())
1937 {
1938 /* Cache new one if necessary: */
1939 guiMedium = UIMedium(comMedium, enmMediumType, KMediumState_Created);
1940 vboxGlobal().createMedium(guiMedium);
1941 }
1942 }
1943
1944 /* Search for a suitable storage slots: */
1945 QList<ExactStorageSlot> aFreeStorageSlots;
1946 QList<ExactStorageSlot> aBusyStorageSlots;
1947 foreach (const CStorageController &comController, machine().GetStorageControllers())
1948 {
1949 foreach (const CMediumAttachment &comAttachment, machine().GetMediumAttachmentsOfController(comController.GetName()))
1950 {
1951 /* Look for an optical devices only: */
1952 if (comAttachment.GetType() == enmDeviceType)
1953 {
1954 /* Append storage slot to corresponding list: */
1955 if (comAttachment.GetMedium().isNull())
1956 aFreeStorageSlots << ExactStorageSlot(comController.GetName(), comController.GetBus(),
1957 comAttachment.GetPort(), comAttachment.GetDevice());
1958 else
1959 aBusyStorageSlots << ExactStorageSlot(comController.GetName(), comController.GetBus(),
1960 comAttachment.GetPort(), comAttachment.GetDevice());
1961 }
1962 }
1963 }
1964
1965 /* Make sure at least one storage slot found: */
1966 QList<ExactStorageSlot> sStorageSlots = aFreeStorageSlots + aBusyStorageSlots;
1967 if (sStorageSlots.isEmpty())
1968 {
1969 popupCenter().cannotMountImage(activeMachineWindow(), machineName(), strMediumName);
1970 return false;
1971 }
1972
1973 /* Try to mount medium into first available storage slot: */
1974 while (!sStorageSlots.isEmpty())
1975 {
1976 const ExactStorageSlot storageSlot = sStorageSlots.takeFirst();
1977 machine().MountMedium(storageSlot.controller, storageSlot.port, storageSlot.device, guiMedium.medium(), false /* force */);
1978 if (machine().isOk())
1979 break;
1980 }
1981
1982 /* Show error message if necessary: */
1983 if (!machine().isOk())
1984 {
1985 msgCenter().cannotRemountMedium(machine(), guiMedium, true /* mount? */, false /* retry? */, activeMachineWindow());
1986 return false;
1987 }
1988
1989 /* Save machine settings: */
1990 machine().SaveSettings();
1991
1992 /* Show error message if necessary: */
1993 if (!machine().isOk())
1994 {
1995 popupCenter().cannotSaveMachineSettings(activeMachineWindow(), machine());
1996 return false;
1997 }
1998
1999 /* True by default: */
2000 return true;
2001}
2002
2003bool UISession::postprocessInitialization()
2004{
2005 /* Check if the required virtualization features are active. We get this info only when the session is active. */
2006 const bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetIs64Bit();
2007 const bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(guest().GetOSTypeId()).GetRecommendedVirtEx();
2008 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n"));
2009 const KVMExecutionEngine enmEngine = debugger().GetExecutionEngine();
2010 if (fRecommendVirtEx && enmEngine == KVMExecutionEngine_RawMode)
2011 {
2012 /* Check whether vt-x / amd-v supported: */
2013 bool fVTxAMDVSupported = vboxGlobal().host().GetProcessorFeature(KProcessorFeature_HWVirtEx);
2014
2015 /* Pause VM: */
2016 setPause(true);
2017
2018 /* Ask the user about further actions: */
2019 bool fShouldWeClose;
2020 if (fIs64BitsGuest)
2021 fShouldWeClose = msgCenter().warnAboutVirtExInactiveFor64BitsGuest(fVTxAMDVSupported);
2022 else
2023 fShouldWeClose = msgCenter().warnAboutVirtExInactiveForRecommendedGuest(fVTxAMDVSupported);
2024
2025 /* If user asked to close VM: */
2026 if (fShouldWeClose)
2027 {
2028 /* Enable 'manual-override',
2029 * preventing automatic Runtime UI closing: */
2030 if (machineLogic())
2031 machineLogic()->setManualOverrideMode(true);
2032 /* Power off VM: */
2033 bool fServerCrashed = false;
2034 LogRel(("GUI: Aborting startup due to postprocess initialization issue detected...\n"));
2035 powerOff(false, fServerCrashed);
2036 return false;
2037 }
2038
2039 /* Resume VM: */
2040 setPause(false);
2041 }
2042
2043 /* True by default: */
2044 return true;
2045}
2046
2047bool UISession::isScreenVisibleHostDesires(ulong uScreenId) const
2048{
2049 /* Make sure index feats the bounds: */
2050 AssertReturn(uScreenId < (ulong)m_monitorVisibilityVectorHostDesires.size(), false);
2051
2052 /* Return 'actual' (host-desire) visibility status: */
2053 return m_monitorVisibilityVectorHostDesires.value((int)uScreenId);
2054}
2055
2056void UISession::setScreenVisibleHostDesires(ulong uScreenId, bool fIsMonitorVisible)
2057{
2058 /* Make sure index feats the bounds: */
2059 AssertReturnVoid(uScreenId < (ulong)m_monitorVisibilityVectorHostDesires.size());
2060
2061 /* Remember 'actual' (host-desire) visibility status: */
2062 m_monitorVisibilityVectorHostDesires[(int)uScreenId] = fIsMonitorVisible;
2063
2064 /* And remember the request in extra data for guests with VMSVGA: */
2065 gEDataManager->setLastGuestScreenVisibilityStatus(uScreenId, fIsMonitorVisible, vboxGlobal().managedVMUuid());
2066}
2067
2068bool UISession::isScreenVisible(ulong uScreenId) const
2069{
2070 /* Make sure index feats the bounds: */
2071 AssertReturn(uScreenId < (ulong)m_monitorVisibilityVector.size(), false);
2072
2073 /* Return 'actual' visibility status: */
2074 return m_monitorVisibilityVector.value((int)uScreenId);
2075}
2076
2077void UISession::setScreenVisible(ulong uScreenId, bool fIsMonitorVisible)
2078{
2079 /* Make sure index feats the bounds: */
2080 AssertReturnVoid(uScreenId < (ulong)m_monitorVisibilityVector.size());
2081
2082 /* Remember 'actual' visibility status: */
2083 m_monitorVisibilityVector[(int)uScreenId] = fIsMonitorVisible;
2084 /* Remember 'desired' visibility status: */
2085 /* See note in UIMachineView::sltHandleNotifyChange() regarding the graphics controller check. */
2086 if (machine().GetGraphicsControllerType() != KGraphicsControllerType_VMSVGA)
2087 gEDataManager->setLastGuestScreenVisibilityStatus(uScreenId, fIsMonitorVisible, vboxGlobal().managedVMUuid());
2088
2089 /* Make sure action-pool knows guest-screen visibility status: */
2090 actionPool()->toRuntime()->setGuestScreenVisible(uScreenId, fIsMonitorVisible);
2091}
2092
2093QSize UISession::lastFullScreenSize(ulong uScreenId) const
2094{
2095 /* Make sure index fits the bounds: */
2096 AssertReturn(uScreenId < (ulong)m_monitorLastFullScreenSizeVector.size(), QSize(-1, -1));
2097
2098 /* Return last full-screen size: */
2099 return m_monitorLastFullScreenSizeVector.value((int)uScreenId);
2100}
2101
2102void UISession::setLastFullScreenSize(ulong uScreenId, QSize size)
2103{
2104 /* Make sure index fits the bounds: */
2105 AssertReturnVoid(uScreenId < (ulong)m_monitorLastFullScreenSizeVector.size());
2106
2107 /* Remember last full-screen size: */
2108 m_monitorLastFullScreenSizeVector[(int)uScreenId] = size;
2109}
2110
2111int UISession::countOfVisibleWindows()
2112{
2113 int cCountOfVisibleWindows = 0;
2114 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i)
2115 if (m_monitorVisibilityVector[i])
2116 ++cCountOfVisibleWindows;
2117 return cCountOfVisibleWindows;
2118}
2119
2120QList<int> UISession::listOfVisibleWindows() const
2121{
2122 QList<int> visibleWindows;
2123 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i)
2124 if (m_monitorVisibilityVector.at(i))
2125 visibleWindows.push_back(i);
2126 return visibleWindows;
2127}
2128
2129CMediumVector UISession::getMachineMedia() const
2130{
2131 CMediumVector media;
2132 foreach (const CStorageController &comController, m_machine.GetStorageControllers())
2133 {
2134 QString strAttData;
2135 /* Enumerate all the attachments: */
2136 foreach (const CMediumAttachment &comAttachment, m_machine.GetMediumAttachmentsOfController(comController.GetName()))
2137 {
2138 /* Skip unrelated attachments: */
2139 if (comAttachment.GetType() != KDeviceType_HardDisk &&
2140 comAttachment.GetType() != KDeviceType_Floppy &&
2141 comAttachment.GetType() != KDeviceType_DVD)
2142 continue;
2143 if (comAttachment.GetIsEjected() || comAttachment.GetMedium().isNull())
2144 continue;
2145 media.append(comAttachment.GetMedium());
2146 }
2147 }
2148 return media;
2149}
2150
2151void UISession::loadVMSettings()
2152{
2153 /* Cache IMachine::ExecutionEngine value. */
2154 m_enmVMExecutionEngine = m_debugger.GetExecutionEngine();
2155 /* Load nested-paging CPU hardware virtualization extension: */
2156 m_fIsHWVirtExNestedPagingEnabled = m_debugger.GetHWVirtExNestedPagingEnabled();
2157 /* Load whether the VM is currently making use of the unrestricted execution feature of VT-x: */
2158 m_fIsHWVirtExUXEnabled = m_debugger.GetHWVirtExUXEnabled();
2159 /* Load VM's effective paravirtualization provider: */
2160 m_paraVirtProvider = m_machine.GetEffectiveParavirtProvider();
2161}
2162
2163UIFrameBuffer* UISession::frameBuffer(ulong uScreenId) const
2164{
2165 Assert(uScreenId < (ulong)m_frameBufferVector.size());
2166 return m_frameBufferVector.value((int)uScreenId, 0);
2167}
2168
2169void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer* pFrameBuffer)
2170{
2171 Assert(uScreenId < (ulong)m_frameBufferVector.size());
2172 if (uScreenId < (ulong)m_frameBufferVector.size())
2173 m_frameBufferVector[(int)uScreenId] = pFrameBuffer;
2174}
2175
2176void UISession::updateHostScreenData()
2177{
2178 /* Rebuild host-screen data vector: */
2179 m_hostScreens.clear();
2180 for (int iScreenIndex = 0; iScreenIndex < gpDesktop->screenCount(); ++iScreenIndex)
2181 m_hostScreens << gpDesktop->screenGeometry(iScreenIndex);
2182
2183 /* Make sure action-pool knows host-screen count: */
2184 actionPool()->toRuntime()->setHostScreenCount(m_hostScreens.size());
2185}
2186
2187void UISession::updateActionRestrictions()
2188{
2189 /* Get host and prepare restrictions: */
2190 const CHost host = vboxGlobal().host();
2191 UIExtraDataMetaDefs::RuntimeMenuMachineActionType restrictionForMachine = UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Invalid;
2192 UIExtraDataMetaDefs::RuntimeMenuViewActionType restrictionForView = UIExtraDataMetaDefs::RuntimeMenuViewActionType_Invalid;
2193 UIExtraDataMetaDefs::RuntimeMenuDevicesActionType restrictionForDevices = UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Invalid;
2194
2195 /* Separate process stuff: */
2196 {
2197 /* Initialize 'Machine' menu: */
2198 if (!vboxGlobal().isSeparateProcess())
2199 restrictionForMachine = (UIExtraDataMetaDefs::RuntimeMenuMachineActionType)(restrictionForMachine | UIExtraDataMetaDefs::RuntimeMenuMachineActionType_Detach);
2200 }
2201
2202 /* VRDE server stuff: */
2203 {
2204 /* Initialize 'View' menu: */
2205 const CVRDEServer server = machine().GetVRDEServer();
2206 if (server.isNull())
2207 restrictionForView = (UIExtraDataMetaDefs::RuntimeMenuViewActionType)(restrictionForView | UIExtraDataMetaDefs::RuntimeMenuViewActionType_VRDEServer);
2208 }
2209
2210 /* Storage stuff: */
2211 {
2212 /* Initialize CD/FD menus: */
2213 int iDevicesCountCD = 0;
2214 int iDevicesCountFD = 0;
2215 foreach (const CMediumAttachment &attachment, machine().GetMediumAttachments())
2216 {
2217 if (attachment.GetType() == KDeviceType_DVD)
2218 ++iDevicesCountCD;
2219 if (attachment.GetType() == KDeviceType_Floppy)
2220 ++iDevicesCountFD;
2221 }
2222 QAction *pOpticalDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_OpticalDevices);
2223 QAction *pFloppyDevicesMenu = actionPool()->action(UIActionIndexRT_M_Devices_M_FloppyDevices);
2224 pOpticalDevicesMenu->setData(iDevicesCountCD);
2225 pFloppyDevicesMenu->setData(iDevicesCountFD);
2226 if (!iDevicesCountCD)
2227 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_OpticalDevices);
2228 if (!iDevicesCountFD)
2229 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_FloppyDevices);
2230 }
2231
2232 /* Audio stuff: */
2233 {
2234 /* Check whether audio controller is enabled. */
2235 const CAudioAdapter &comAdapter = machine().GetAudioAdapter();
2236 if (comAdapter.isNull() || !comAdapter.GetEnabled())
2237 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Audio);
2238 }
2239
2240 /* Network stuff: */
2241 {
2242 /* Initialize Network menu: */
2243 bool fAtLeastOneAdapterActive = false;
2244 const KChipsetType chipsetType = machine().GetChipsetType();
2245 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(chipsetType);
2246 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot)
2247 {
2248 const CNetworkAdapter &adapter = machine().GetNetworkAdapter(uSlot);
2249 if (adapter.GetEnabled())
2250 {
2251 fAtLeastOneAdapterActive = true;
2252 break;
2253 }
2254 }
2255 if (!fAtLeastOneAdapterActive)
2256 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_Network);
2257 }
2258
2259 /* USB stuff: */
2260 {
2261 /* Check whether there is at least one USB controller with an available proxy. */
2262 const bool fUSBEnabled = !machine().GetUSBDeviceFilters().isNull()
2263 && !machine().GetUSBControllers().isEmpty()
2264 && machine().GetUSBProxyAvailable();
2265 if (!fUSBEnabled)
2266 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_USBDevices);
2267 }
2268
2269 /* WebCams stuff: */
2270 {
2271 /* Check whether there is an accessible video input devices pool: */
2272 host.GetVideoInputDevices();
2273 const bool fWebCamsEnabled = host.isOk() && !machine().GetUSBControllers().isEmpty();
2274 if (!fWebCamsEnabled)
2275 restrictionForDevices = (UIExtraDataMetaDefs::RuntimeMenuDevicesActionType)(restrictionForDevices | UIExtraDataMetaDefs::RuntimeMenuDevicesActionType_WebCams);
2276 }
2277
2278 /* Apply cumulative restriction for 'Machine' menu: */
2279 actionPool()->toRuntime()->setRestrictionForMenuMachine(UIActionRestrictionLevel_Session, restrictionForMachine);
2280 /* Apply cumulative restriction for 'View' menu: */
2281 actionPool()->toRuntime()->setRestrictionForMenuView(UIActionRestrictionLevel_Session, restrictionForView);
2282 /* Apply cumulative restriction for 'Devices' menu: */
2283 actionPool()->toRuntime()->setRestrictionForMenuDevices(UIActionRestrictionLevel_Session, restrictionForDevices);
2284}
2285
2286#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
2287/**
2288 * Custom signal handler. When switching VTs, we might not get release events
2289 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will
2290 * be saved with modifier keys stuck. This is annoying enough for introducing
2291 * this hack.
2292 */
2293/* static */
2294static void signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */)
2295{
2296 /* Only SIGUSR1 is interesting: */
2297 if (sig == SIGUSR1)
2298 if (gpMachine)
2299 gpMachine->uisession()->machineLogic()->keyboardHandler()->releaseAllPressedKeys();
2300}
2301#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
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