VirtualBox

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

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

FE/Qt: logrel consistency.

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

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