VirtualBox

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

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

GUI: HID LEDs sync: add log message on VM startup regarding to if feature enabled, disabled or not supported on a certain platform.

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