VirtualBox

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

Last change on this file since 51593 was 51593, checked in by vboxsync, 11 years ago

FE/Qt: 6660: Advanced extra-data management framework: Remove code related to unused GUI_SaveMountedAtRuntime.

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