VirtualBox

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

Last change on this file since 46524 was 46524, checked in by vboxsync, 12 years ago

Main/IGuest::UpdateGuestAdditions: Implemented support for passing optional command line arguments to the performing installer on the guest (untested).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.6 KB
Line 
1/* $Id: UISession.cpp 46524 2013-06-13 12:10:23Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UISession stuff implementation
6 */
7
8/*
9 * Copyright (C) 2006-2012 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/* Qt includes: */
21#include <QApplication>
22#include <QDesktopWidget>
23#include <QWidget>
24
25/* GUI includes: */
26#include "VBoxGlobal.h"
27#include "UISession.h"
28#include "UIMachine.h"
29#include "UIActionPoolRuntime.h"
30#include "UIMachineLogic.h"
31#include "UIMachineView.h"
32#include "UIMachineWindow.h"
33#include "UIMachineMenuBar.h"
34#include "UIMessageCenter.h"
35#include "UIWizardFirstRun.h"
36#include "UIConsoleEventHandler.h"
37#include "UIFrameBuffer.h"
38#ifdef VBOX_WITH_VIDEOHWACCEL
39# include "VBoxFBOverlay.h"
40#endif /* VBOX_WITH_VIDEOHWACCEL */
41
42#ifdef Q_WS_X11
43# include <QX11Info>
44# include <X11/Xlib.h>
45# include <X11/Xutil.h>
46# ifndef VBOX_WITHOUT_XCURSOR
47# include <X11/Xcursor/Xcursor.h>
48# endif /* VBOX_WITHOUT_XCURSOR */
49#endif /* Q_WS_X11 */
50
51#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
52# include "UIKeyboardHandler.h"
53# include <signal.h>
54#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
55
56/* COM includes: */
57#include "CConsole.h"
58#include "CSystemProperties.h"
59#include "CMachineDebugger.h"
60#include "CGuest.h"
61#include "CStorageController.h"
62#include "CMediumAttachment.h"
63#include "CDisplay.h"
64#include "CFramebuffer.h"
65#include "CNetworkAdapter.h"
66#include "CHostNetworkInterface.h"
67#include "CVRDEServer.h"
68#include "CUSBController.h"
69#include "CSnapshot.h"
70
71UISession::UISession(UIMachine *pMachine, CSession &sessionReference)
72 : QObject(pMachine)
73 /* Base variables: */
74 , m_pMachine(pMachine)
75 , m_session(sessionReference)
76 /* Common variables: */
77 , m_pMenuPool(0)
78 , m_machineState(session().GetMachine().GetState())
79#ifdef Q_WS_WIN
80 , m_alphaCursor(0)
81#endif /* Q_WS_WIN */
82 /* Common flags: */
83 , m_fIsFirstTimeStarted(false)
84 , m_fIsIgnoreRuntimeMediumsChanging(false)
85 , m_fIsGuestResizeIgnored(false)
86 , m_fIsSeamlessModeRequested(false)
87 , m_fIsAutoCaptureDisabled(false)
88 , m_fReconfigurable(false)
89 /* Guest additions flags: */
90 , m_ulGuestAdditionsRunLevel(0)
91 , m_fIsGuestSupportsGraphics(false)
92 , m_fIsGuestSupportsSeamless(false)
93 /* Mouse flags: */
94 , m_fNumLock(false)
95 , m_fCapsLock(false)
96 , m_fScrollLock(false)
97 , m_uNumLockAdaptionCnt(2)
98 , m_uCapsLockAdaptionCnt(2)
99 /* Mouse flags: */
100 , m_fIsMouseSupportsAbsolute(false)
101 , m_fIsMouseSupportsRelative(false)
102 , m_fIsMouseHostCursorNeeded(false)
103 , m_fIsMouseCaptured(false)
104 , m_fIsMouseIntegrated(true)
105 , m_fIsValidPointerShapePresent(false)
106 , m_fIsHidingHostPointer(true)
107{
108 /* Prepare connections: */
109 prepareConnections();
110
111 /* Prepare console event-handlers: */
112 prepareConsoleEventHandlers();
113
114 /* Prepare screens: */
115 prepareScreens();
116
117 /* Prepare framebuffers: */
118 prepareFramebuffers();
119
120 /* Prepare main-menu: */
121 prepareMenuPool();
122
123 /* Load settings: */
124 loadSessionSettings();
125
126#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
127 struct sigaction sa;
128 sa.sa_sigaction = &signalHandlerSIGUSR1;
129 sigemptyset(&sa.sa_mask);
130 sa.sa_flags = SA_RESTART | SA_SIGINFO;
131 sigaction(SIGUSR1, &sa, NULL);
132#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
133}
134
135UISession::~UISession()
136{
137 /* Save settings: */
138 saveSessionSettings();
139
140 /* Cleanup main-menu: */
141 cleanupMenuPool();
142
143 /* Cleanup framebuffers: */
144 cleanupFramebuffers();
145
146 /* Cleanup console event-handlers: */
147 cleanupConsoleEventHandlers();
148
149#ifdef Q_WS_WIN
150 /* Destroy alpha cursor: */
151 if (m_alphaCursor)
152 DestroyIcon(m_alphaCursor);
153#endif /* Q_WS_WIN */
154}
155
156void UISession::adjustGuestView()
157{
158 foreach(UIMachineWindow *pMachineWindow, machineLogic()->machineWindows())
159 {
160 bool fAdjustPosition = false;
161 UIVisualStateType visualStateType = machineLogic()->visualStateType();
162
163 if (visualStateType == UIVisualStateType_Normal ||
164 visualStateType == UIVisualStateType_Scale)
165 fAdjustPosition = true;
166
167 /* Normalize view's geometry: */
168 pMachineWindow->machineView()->normalizeGeometry(fAdjustPosition);
169 }
170}
171
172void UISession::powerUp()
173{
174 /* Do nothing if we had started already: */
175 if (isRunning() || isPaused())
176 return;
177
178 /* Prepare powerup: */
179 bool fPrepared = preparePowerUp();
180 if (!fPrepared)
181 return;
182
183 /* Get current machine/console: */
184 CMachine machine = session().GetMachine();
185 CConsole console = session().GetConsole();
186
187 /* Apply debug settings from the command line. */
188 CMachineDebugger debugger = console.GetDebugger();
189 if (debugger.isOk())
190 {
191 if (vboxGlobal().isPatmDisabled())
192 debugger.SetPATMEnabled(false);
193 if (vboxGlobal().isCsamDisabled())
194 debugger.SetCSAMEnabled(false);
195 if (vboxGlobal().isSupervisorCodeExecedRecompiled())
196 debugger.SetRecompileSupervisor(true);
197 if (vboxGlobal().isUserCodeExecedRecompiled())
198 debugger.SetRecompileUser(true);
199 if (vboxGlobal().areWeToExecuteAllInIem())
200 debugger.SetExecuteAllInIEM(true);
201 if (!vboxGlobal().isDefaultWarpPct())
202 debugger.SetVirtualTimeRate(vboxGlobal().getWarpPct());
203 }
204
205 /* Power UP machine: */
206 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled(machine) ?
207 console.PowerUpPaused() : console.PowerUp();
208
209 /* Check for immediate failure: */
210 if (!console.isOk())
211 {
212 if (vboxGlobal().showStartVMErrors())
213 msgCenter().cannotStartMachine(console, machine.GetName());
214 closeRuntimeUI();
215 return;
216 }
217
218 /* Guard progressbar warnings from auto-closing: */
219 if (uimachine()->machineLogic())
220 uimachine()->machineLogic()->setPreventAutoClose(true);
221
222 /* Show "Starting/Restoring" progress dialog: */
223 if (isSaved())
224 {
225 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_state_restore_90px.png", 0, 0);
226 /* If restoring from saved state, guest MachineView
227 should be notified about host MachineWindow geometry change */
228 adjustGuestView();
229 }
230 else
231 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_start_90px.png");
232
233 /* Check for a progress failure: */
234 if (!progress.isOk() || progress.GetResultCode() != 0)
235 {
236 if (vboxGlobal().showStartVMErrors())
237 msgCenter().cannotStartMachine(progress, machine.GetName());
238 closeRuntimeUI();
239 return;
240 }
241
242 /* Allow further auto-closing: */
243 if (uimachine()->machineLogic())
244 uimachine()->machineLogic()->setPreventAutoClose(false);
245
246 /* Check if we missed a really quick termination after successful startup, and process it if we did: */
247 if (isTurnedOff())
248 {
249 closeRuntimeUI();
250 return;
251 }
252
253 /* Check if the required virtualization features are active. We get this
254 * info only when the session is active. */
255 bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetIs64Bit();
256 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx();
257 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n"));
258 bool fIsVirtEnabled = console.GetDebugger().GetHWVirtExEnabled();
259 if (fRecommendVirtEx && !fIsVirtEnabled)
260 {
261 bool fShouldWeClose;
262
263 bool fVTxAMDVSupported = vboxGlobal().host().GetProcessorFeature(KProcessorFeature_HWVirtEx);
264
265 QApplication::processEvents();
266 setPause(true);
267
268 if (fIs64BitsGuest)
269 fShouldWeClose = msgCenter().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported);
270 else
271 fShouldWeClose = msgCenter().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported);
272
273 if (fShouldWeClose)
274 {
275 /* At this point the console is powered up. So we have to close
276 * this session again. */
277 CProgress progress = console.PowerDown();
278 if (console.isOk())
279 {
280 /* Guard progressbar warnings from auto-closing: */
281 if (uimachine()->machineLogic())
282 uimachine()->machineLogic()->setPreventAutoClose(true);
283 /* Show the power down progress dialog */
284 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_poweroff_90px.png");
285 if (!progress.isOk() || progress.GetResultCode() != 0)
286 msgCenter().cannotPowerDownMachine(progress, machine.GetName());
287 /* Allow further auto-closing: */
288 if (uimachine()->machineLogic())
289 uimachine()->machineLogic()->setPreventAutoClose(false);
290 }
291 else
292 msgCenter().cannotPowerDownMachine(console);
293 closeRuntimeUI();
294 return;
295 }
296
297 setPause(false);
298 }
299
300#ifdef VBOX_WITH_VIDEOHWACCEL
301 LogRel(("2D video acceleration is %s.\n",
302 machine.GetAccelerate2DVideoEnabled() && VBoxGlobal::isAcceleration2DVideoAvailable()
303 ? "enabled"
304 : "disabled"));
305#endif
306
307#ifdef VBOX_GUI_WITH_PIDFILE
308 vboxGlobal().createPidfile();
309#endif
310
311 /* Warn listeners about machine was started: */
312 emit sigMachineStarted();
313}
314
315bool UISession::saveState()
316{
317 /* Prepare the saving progress: */
318 CMachine machine = m_session.GetMachine();
319 CConsole console = m_session.GetConsole();
320 CProgress progress = console.SaveState();
321 if (console.isOk())
322 {
323 /* Show the saving progress: */
324 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_state_save_90px.png");
325 if (!progress.isOk() || progress.GetResultCode() != 0)
326 {
327 /* Failed in progress: */
328 msgCenter().cannotSaveMachineState(progress, machine.GetName());
329 return false;
330 }
331 }
332 else
333 {
334 /* Failed in console: */
335 msgCenter().cannotSaveMachineState(console);
336 return false;
337 }
338 /* Passed: */
339 return true;
340}
341
342bool UISession::shutdown()
343{
344 /* Send ACPI shutdown signal if possible: */
345 CConsole console = m_session.GetConsole();
346 console.PowerButton();
347 if (!console.isOk())
348 {
349 /* Failed in console: */
350 msgCenter().cannotACPIShutdownMachine(console);
351 return false;
352 }
353 /* Passed: */
354 return true;
355}
356
357bool UISession::powerOff(bool fIncludingDiscard, bool &fServerCrashed)
358{
359 /* Prepare the power-off progress: */
360 CMachine machine = m_session.GetMachine();
361 CConsole console = m_session.GetConsole();
362 CProgress progress = console.PowerDown();
363 if (console.isOk())
364 {
365 /* Show the power-off progress: */
366 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_poweroff_90px.png");
367 if (progress.isOk() && progress.GetResultCode() == 0)
368 {
369 /* Discard the current state if requested: */
370 if (fIncludingDiscard)
371 {
372 /* Prepare the snapshot-discard progress: */
373 CSnapshot snapshot = machine.GetCurrentSnapshot();
374 CProgress progress = console.RestoreSnapshot(snapshot);
375 if (console.isOk())
376 {
377 /* Show the snapshot-discard progress: */
378 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_snapshot_discard_90px.png");
379 if (progress.GetResultCode() != 0)
380 {
381 /* Failed in progress: */
382 msgCenter().cannotRestoreSnapshot(progress, snapshot.GetName(), machine.GetName());
383 return false;
384 }
385 }
386 else
387 {
388 /* Failed in console: */
389 msgCenter().cannotRestoreSnapshot(console, snapshot.GetName(), machine.GetName());
390 return false;
391 }
392 }
393 }
394 else
395 {
396 /* Failed in progress: */
397 msgCenter().cannotPowerDownMachine(progress, machine.GetName());
398 return false;
399 }
400 }
401 else
402 {
403 /* Failed in console: */
404 COMResult res(console);
405 /* This can happen if VBoxSVC is not running: */
406 if (FAILED_DEAD_INTERFACE(res.rc()))
407 fServerCrashed = true;
408 else
409 msgCenter().cannotPowerDownMachine(console);
410 return false;
411 }
412 /* Passed: */
413 return true;
414}
415
416void UISession::closeRuntimeUI()
417{
418 /* Start corresponding slot asynchronously: */
419 emit sigCloseRuntimeUI();
420}
421
422UIMachineLogic* UISession::machineLogic() const
423{
424 return uimachine()->machineLogic();
425}
426
427QWidget* UISession::mainMachineWindow() const
428{
429 return machineLogic()->mainMachineWindow();
430}
431
432QMenu* UISession::newMenu(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
433{
434 /* Create new menu: */
435 QMenu *pMenu = m_pMenuPool->createMenu(fOptions);
436
437 /* Re-init menu pool for the case menu were recreated: */
438 reinitMenuPool();
439
440 /* Return newly created menu: */
441 return pMenu;
442}
443
444QMenuBar* UISession::newMenuBar(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
445{
446 /* Create new menubar: */
447 QMenuBar *pMenuBar = m_pMenuPool->createMenuBar(fOptions);
448
449 /* Re-init menu pool for the case menu were recreated: */
450 reinitMenuPool();
451
452 /* Return newly created menubar: */
453 return pMenuBar;
454}
455
456bool UISession::setPause(bool fOn)
457{
458 CConsole console = session().GetConsole();
459
460 if (fOn)
461 console.Pause();
462 else
463 console.Resume();
464
465 bool ok = console.isOk();
466 if (!ok)
467 {
468 if (fOn)
469 msgCenter().cannotPauseMachine(console);
470 else
471 msgCenter().cannotResumeMachine(console);
472 }
473
474 return ok;
475}
476
477void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
478{
479 CMachine machine = session().GetMachine();
480 CVirtualBox vbox = vboxGlobal().virtualBox();
481
482 /*
483 * Flag indicating whether we want to do the usual .ISO mounting or not.
484 * First try updating the Guest Additions directly without mounting the .ISO.
485 */
486 bool fDoMount = false;
487 /* Auto-update in GUI currently is disabled. */
488#ifndef VBOX_WITH_ADDITIONS_AUTOUPDATE_UI
489 fDoMount = true;
490#else
491 CGuest guest = session().GetConsole().GetGuest();
492 QVector<KAdditionsUpdateFlag> aFlagsUpdate;
493 QVector<QString> aArgs;
494 CProgress progressInstall = guest.UpdateGuestAdditions(strSource,
495 aArgs, aFlagsUpdate);
496 bool fResult = guest.isOk();
497 if (fResult)
498 {
499 msgCenter().showModalProgressDialog(progressInstall, tr("Updating Guest Additions"),
500 ":/progress_install_guest_additions_90px.png",
501 0, 500 /* 500ms delay. */);
502 if (progressInstall.GetCanceled())
503 return;
504
505 HRESULT rc = progressInstall.GetResultCode();
506 if (!progressInstall.isOk() || rc != S_OK)
507 {
508 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS
509 * simply isn't supported yet), so silently fall back to "old" .ISO
510 * mounting method. */
511 if ( !SUCCEEDED_WARNING(rc)
512 && rc != VBOX_E_NOT_SUPPORTED)
513 {
514 msgCenter().cannotUpdateGuestAdditions(progressInstall);
515
516 /* Log the error message in the release log. */
517 QString strErr = progressInstall.GetErrorInfo().GetText();
518 if (!strErr.isEmpty())
519 LogRel(("%s\n", strErr.toLatin1().constData()));
520 }
521 fDoMount = true; /* Since automatic updating failed, fall back to .ISO mounting. */
522 }
523 }
524#endif /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */
525
526 if (fDoMount) /* Fallback to only mounting the .ISO file. */
527 {
528 QString strUuid;
529 CMedium image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite, false /* fForceNewUuid */);
530 if (image.isNull())
531 {
532 image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite, false /* fForceNewUuid */);
533 if (vbox.isOk())
534 strUuid = image.GetId();
535 }
536 else
537 strUuid = image.GetId();
538
539 if (!vbox.isOk())
540 {
541 msgCenter().cannotOpenMedium(vbox, UIMediumType_DVD, strSource, mainMachineWindow());
542 return;
543 }
544
545 AssertMsg(!strUuid.isNull(), ("Guest Additions image UUID should be valid!\n"));
546
547 QString strCntName;
548 LONG iCntPort = -1, iCntDevice = -1;
549 /* Searching for the first suitable slot */
550 {
551 CStorageControllerVector controllers = machine.GetStorageControllers();
552 int i = 0;
553 while (i < controllers.size() && strCntName.isNull())
554 {
555 CStorageController controller = controllers[i];
556 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName());
557 int j = 0;
558 while (j < attachments.size() && strCntName.isNull())
559 {
560 CMediumAttachment attachment = attachments[j];
561 if (attachment.GetType() == KDeviceType_DVD)
562 {
563 strCntName = controller.GetName();
564 iCntPort = attachment.GetPort();
565 iCntDevice = attachment.GetDevice();
566 }
567 ++ j;
568 }
569 ++ i;
570 }
571 }
572
573 if (!strCntName.isNull())
574 {
575 /* Create a new UIMedium: */
576 UIMedium vboxMedium(image, UIMediumType_DVD, KMediumState_Created);
577 /* Register it in GUI internal list: */
578 vboxGlobal().addMedium(vboxMedium);
579
580 /* Mount medium to the predefined port/device: */
581 machine.MountMedium(strCntName, iCntPort, iCntDevice, vboxMedium.medium(), false /* force */);
582 if (!machine.isOk())
583 {
584 /* Ask for force mounting: */
585 if (msgCenter().cannotRemountMedium(machine, vboxMedium, true /* mount? */,
586 true /* retry? */, mainMachineWindow()))
587 {
588 /* Force mount medium to the predefined port/device: */
589 machine.MountMedium(strCntName, iCntPort, iCntDevice, vboxMedium.medium(), true /* force */);
590 if (!machine.isOk())
591 msgCenter().cannotRemountMedium(machine, vboxMedium, true /* mount? */,
592 false /* retry? */, mainMachineWindow());
593 }
594 }
595 }
596 else
597 msgCenter().cannotMountGuestAdditions(machine.GetName());
598 }
599}
600
601void UISession::sltCloseRuntimeUI()
602{
603 /* First, we have to hide any opened modal/popup widgets.
604 * They then should unlock their event-loops synchronously.
605 * If all such loops are unlocked, we can close Runtime UI: */
606 if (QWidget *pWidget = QApplication::activeModalWidget() ?
607 QApplication::activeModalWidget() :
608 QApplication::activePopupWidget() ?
609 QApplication::activePopupWidget() : 0)
610 {
611 /* First we should try to close this widget: */
612 pWidget->close();
613 /* If widget rejected the 'close-event' we can
614 * still hide it and hope it will behave correctly
615 * and unlock his event-loop if any: */
616 if (!pWidget->isHidden())
617 pWidget->hide();
618 /* Restart this slot asynchronously: */
619 emit sigCloseRuntimeUI();
620 return;
621 }
622
623 /* Finally close the Runtime UI: */
624 m_pMachine->deleteLater();
625}
626
627void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape)
628{
629 /* In case of shape data is present: */
630 if (shape.size() > 0)
631 {
632 /* We are ignoring visibility flag: */
633 m_fIsHidingHostPointer = false;
634
635 /* And updating current cursor shape: */
636 setPointerShape(shape.data(), fAlpha,
637 hotCorner.x(), hotCorner.y(),
638 size.width(), size.height());
639 }
640 /* In case of shape data is NOT present: */
641 else
642 {
643 /* Remember if we should hide the cursor: */
644 m_fIsHidingHostPointer = !fVisible;
645 }
646
647 /* Notify listeners about mouse capability changed: */
648 emit sigMousePointerShapeChange();
649
650}
651
652void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fNeedsHostCursor)
653{
654 /* Check if something had changed: */
655 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute
656 || m_fIsMouseSupportsRelative != fSupportsRelative
657 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor)
658 {
659 /* Store new data: */
660 m_fIsMouseSupportsAbsolute = fSupportsAbsolute;
661 m_fIsMouseSupportsRelative = fSupportsRelative;
662 m_fIsMouseHostCursorNeeded = fNeedsHostCursor;
663
664 /* Notify listeners about mouse capability changed: */
665 emit sigMouseCapabilityChange();
666 }
667}
668
669void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock)
670{
671 /* Check if something had changed: */
672 if ( m_fNumLock != fNumLock
673 || m_fCapsLock != fCapsLock
674 || m_fScrollLock != fScrollLock)
675 {
676 /* Store new num lock data: */
677 if (m_fNumLock != fNumLock)
678 {
679 m_fNumLock = fNumLock;
680 m_uNumLockAdaptionCnt = 2;
681 }
682
683 /* Store new caps lock data: */
684 if (m_fCapsLock != fCapsLock)
685 {
686 m_fCapsLock = fCapsLock;
687 m_uCapsLockAdaptionCnt = 2;
688 }
689
690 /* Store new scroll lock data: */
691 if (m_fScrollLock != fScrollLock)
692 {
693 m_fScrollLock = fScrollLock;
694 }
695
696 /* Notify listeners about mouse capability changed: */
697 emit sigKeyboardLedsChange();
698 }
699}
700
701void UISession::sltStateChange(KMachineState state)
702{
703 /* Check if something had changed: */
704 if (m_machineState != state)
705 {
706 /* Store new data: */
707 m_machineState = state;
708
709 /* Update session settings: */
710 updateSessionSettings();
711
712 /* Notify listeners about machine state changed: */
713 emit sigMachineStateChange();
714 }
715}
716
717void UISession::sltVRDEChange()
718{
719 /* Get machine: */
720 const CMachine &machine = session().GetMachine();
721 /* Get VRDE server: */
722 const CVRDEServer &server = machine.GetVRDEServer();
723 bool fIsVRDEServerAvailable = !server.isNull();
724 /* Show/Hide VRDE action depending on VRDE server availability status: */
725 gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer)->setVisible(fIsVRDEServerAvailable);
726 /* Check/Uncheck VRDE action depending on VRDE server activity status: */
727 if (fIsVRDEServerAvailable)
728 gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer)->setChecked(server.GetEnabled());
729 /* Notify listeners about VRDE change: */
730 emit sigVRDEChange();
731}
732
733void UISession::sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo)
734{
735 /* Ignore KGuestMonitorChangedEventType_NewOrigin change event: */
736 if (changeType == KGuestMonitorChangedEventType_NewOrigin)
737 return;
738 /* Ignore KGuestMonitorChangedEventType_Disabled event if there is only one window visible: */
739 AssertMsg(countOfVisibleWindows() > 0, ("All machine windows are hidden!"));
740 if ( changeType == KGuestMonitorChangedEventType_Disabled
741 && countOfVisibleWindows() == 1
742 && isScreenVisible(uScreenId))
743 return;
744
745 /* Process KGuestMonitorChangedEventType_Enabled change event: */
746 if ( !isScreenVisible(uScreenId)
747 && changeType == KGuestMonitorChangedEventType_Enabled)
748 setScreenVisible(uScreenId, true);
749 /* Process KGuestMonitorChangedEventType_Disabled change event: */
750 else if ( isScreenVisible(uScreenId)
751 && changeType == KGuestMonitorChangedEventType_Disabled)
752 setScreenVisible(uScreenId, false);
753
754 /* Notify listeners about the change: */
755 emit sigGuestMonitorChange(changeType, uScreenId, screenGeo);
756}
757
758void UISession::sltAdditionsChange()
759{
760 /* Get our guest: */
761 CGuest guest = session().GetConsole().GetGuest();
762
763 /* Variable flags: */
764 ULONG ulGuestAdditionsRunLevel = guest.GetAdditionsRunLevel();
765 LONG64 lLastUpdatedIgnored;
766 bool fIsGuestSupportsGraphics = guest.GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored)
767 == KAdditionsFacilityStatus_Active;
768 bool fIsGuestSupportsSeamless = guest.GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored)
769 == KAdditionsFacilityStatus_Active;
770 /* Check if something had changed: */
771 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel ||
772 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
773 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
774 {
775 /* Store new data: */
776 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
777 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
778 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
779
780 /* Notify listeners about guest additions state changed: */
781 emit sigAdditionsStateChange();
782 }
783}
784
785void UISession::prepareConsoleEventHandlers()
786{
787 /* Initialize console event-handler: */
788 UIConsoleEventHandler::instance(this);
789
790 /* Add console event connections: */
791 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)),
792 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)));
793
794 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool)),
795 this, SLOT(sltMouseCapabilityChange(bool, bool, bool)));
796
797 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)),
798 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool)));
799
800 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)),
801 this, SLOT(sltStateChange(KMachineState)));
802
803 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()),
804 this, SLOT(sltAdditionsChange()));
805
806 connect(gConsoleEvents, SIGNAL(sigVRDEChange()),
807 this, SLOT(sltVRDEChange()));
808
809 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)),
810 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)));
811
812 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)),
813 this, SIGNAL(sigMediumChange(CMediumAttachment)));
814
815 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()),
816 this, SIGNAL(sigUSBControllerChange()));
817
818 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)),
819 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)));
820
821 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()),
822 this, SIGNAL(sigSharedFolderChange()));
823
824 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)),
825 this, SIGNAL(sigRuntimeError(bool, QString, QString)));
826
827#ifdef Q_WS_MAC
828 connect(gConsoleEvents, SIGNAL(sigShowWindow()),
829 this, SIGNAL(sigShowWindows()), Qt::QueuedConnection);
830#endif /* Q_WS_MAC */
831
832 connect(gConsoleEvents, SIGNAL(sigCPUExecutionCapChange()),
833 this, SIGNAL(sigCPUExecutionCapChange()));
834
835 connect(gConsoleEvents, SIGNAL(sigGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)),
836 this, SLOT(sltGuestMonitorChange(KGuestMonitorChangedEventType, ulong, QRect)));
837}
838
839void UISession::prepareConnections()
840{
841 connect(this, SIGNAL(sigCloseRuntimeUI()), this, SLOT(sltCloseRuntimeUI()));
842
843 connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)),
844 this, SIGNAL(sigHostScreenCountChanged(int)));
845}
846
847void UISession::prepareScreens()
848{
849 /* Get machine: */
850 CMachine machine = m_session.GetMachine();
851
852 /* Prepare initial screen visibility status: */
853 m_monitorVisibilityVector.resize(machine.GetMonitorCount());
854 m_monitorVisibilityVector.fill(false);
855 m_monitorVisibilityVector[0] = true;
856
857 /* If machine is in 'saved' state: */
858 if (isSaved())
859 {
860 /* Update screen visibility status from saved-state: */
861 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i)
862 {
863 BOOL fEnabled = true;
864 ULONG guestOriginX = 0, guestOriginY = 0, guestWidth = 0, guestHeight = 0;
865 machine.QuerySavedGuestScreenInfo(i, guestOriginX, guestOriginY, guestWidth, guestHeight, fEnabled);
866 m_monitorVisibilityVector[i] = fEnabled;
867 }
868 /* And make sure at least one of them is visible (primary if others are hidden): */
869 if (countOfVisibleWindows() < 1)
870 m_monitorVisibilityVector[0] = true;
871 }
872}
873
874void UISession::prepareFramebuffers()
875{
876 /* Each framebuffer will be really prepared on first UIMachineView creation: */
877 m_frameBufferVector.resize(m_session.GetMachine().GetMonitorCount());
878}
879
880void UISession::prepareMenuPool()
881{
882 m_pMenuPool = new UIMachineMenuBar;
883}
884
885void UISession::loadSessionSettings()
886{
887 /* Get uisession machine: */
888 CMachine machine = session().GetConsole().GetMachine();
889
890 /* Load extra-data settings: */
891 {
892 /* Temporary: */
893 QString strSettings;
894
895 /* Is there should be First RUN Wizard? */
896 strSettings = machine.GetExtraData(GUI_FirstRun);
897 if (strSettings == "yes")
898 m_fIsFirstTimeStarted = true;
899
900 /* Ignore mediums mounted at runtime? */
901 strSettings = machine.GetExtraData(GUI_SaveMountedAtRuntime);
902 if (strSettings == "no")
903 m_fIsIgnoreRuntimeMediumsChanging = true;
904
905 /* Should guest autoresize? */
906 strSettings = machine.GetExtraData(GUI_AutoresizeGuest);
907 QAction *pGuestAutoresizeSwitch = gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize);
908 pGuestAutoresizeSwitch->setChecked(strSettings != "off");
909
910 /* Should we allow reconfiguration? */
911 m_fReconfigurable = VBoxGlobal::shouldWeAllowMachineReconfiguration(machine);
912 updateSessionSettings();
913
914#if 0 /* Disabled for now! */
915# ifdef Q_WS_WIN
916 /* Disable host screen-saver if requested: */
917 if (vboxGlobal().settings().hostScreenSaverDisabled())
918 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, 0, 0);
919# endif /* Q_WS_WIN */
920#endif
921 }
922}
923
924void UISession::saveSessionSettings()
925{
926 /* Get uisession machine: */
927 CMachine machine = session().GetConsole().GetMachine();
928
929 /* Save extra-data settings: */
930 {
931 /* Disable First RUN Wizard for the since now: */
932 machine.SetExtraData(GUI_FirstRun, QString());
933
934 /* Remember if guest should autoresize: */
935 machine.SetExtraData(GUI_AutoresizeGuest,
936 gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize)->isChecked() ?
937 QString() : "off");
938
939#if 0 /* Disabled for now! */
940# ifdef Q_WS_WIN
941 /* Restore screen-saver activity to system default: */
942 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, true, 0, 0);
943# endif /* Q_WS_WIN */
944#endif
945 }
946}
947
948void UISession::cleanupMenuPool()
949{
950 delete m_pMenuPool;
951 m_pMenuPool = 0;
952}
953
954void UISession::cleanupFramebuffers()
955{
956 /* Cleanup framebuffers finally: */
957 for (int i = m_frameBufferVector.size() - 1; i >= 0; --i)
958 {
959 UIFrameBuffer *pFb = m_frameBufferVector[i];
960 if (pFb)
961 {
962 /* Warn framebuffer about its no more necessary: */
963 pFb->setScheduledToDelete(true);
964 /* Detach framebuffer from Display: */
965 CDisplay display = session().GetConsole().GetDisplay();
966 display.SetFramebuffer(i, CFramebuffer(NULL));
967 /* Release the reference: */
968 pFb->Release();
969 }
970 }
971 m_frameBufferVector.clear();
972}
973
974void UISession::cleanupConsoleEventHandlers()
975{
976 /* Destroy console event-handler: */
977 UIConsoleEventHandler::destroy();
978}
979
980void UISession::updateSessionSettings()
981{
982 bool fAllowReconfiguration = m_machineState != KMachineState_Stuck && m_fReconfigurable;
983 gActionPool->action(UIActionIndexRuntime_Simple_SettingsDialog)->setEnabled(fAllowReconfiguration);
984 gActionPool->action(UIActionIndexRuntime_Simple_SharedFoldersDialog)->setEnabled(fAllowReconfiguration);
985 gActionPool->action(UIActionIndexRuntime_Simple_NetworkAdaptersDialog)->setEnabled(fAllowReconfiguration);
986}
987
988WId UISession::winId() const
989{
990 return mainMachineWindow()->winId();
991}
992
993void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
994 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
995{
996 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
997
998 m_fIsValidPointerShapePresent = false;
999 const uchar *srcAndMaskPtr = pShapeData;
1000 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
1001 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
1002 uint srcShapePtrScan = uWidth * 4;
1003
1004#if defined (Q_WS_WIN)
1005
1006 BITMAPV5HEADER bi;
1007 HBITMAP hBitmap;
1008 void *lpBits;
1009
1010 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
1011 bi.bV5Size = sizeof(BITMAPV5HEADER);
1012 bi.bV5Width = uWidth;
1013 bi.bV5Height = - (LONG)uHeight;
1014 bi.bV5Planes = 1;
1015 bi.bV5BitCount = 32;
1016 bi.bV5Compression = BI_BITFIELDS;
1017 bi.bV5RedMask = 0x00FF0000;
1018 bi.bV5GreenMask = 0x0000FF00;
1019 bi.bV5BlueMask = 0x000000FF;
1020 if (fHasAlpha)
1021 bi.bV5AlphaMask = 0xFF000000;
1022 else
1023 bi.bV5AlphaMask = 0;
1024
1025 HDC hdc = GetDC(NULL);
1026
1027 /* Create the DIB section with an alpha channel: */
1028 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
1029
1030 ReleaseDC(NULL, hdc);
1031
1032 HBITMAP hMonoBitmap = NULL;
1033 if (fHasAlpha)
1034 {
1035 /* Create an empty mask bitmap: */
1036 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
1037 }
1038 else
1039 {
1040 /* Word aligned AND mask. Will be allocated and created if necessary. */
1041 uint8_t *pu8AndMaskWordAligned = NULL;
1042
1043 /* Width in bytes of the original AND mask scan line. */
1044 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
1045
1046 if (cbAndMaskScan & 1)
1047 {
1048 /* Original AND mask is not word aligned. */
1049
1050 /* Allocate memory for aligned AND mask. */
1051 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
1052
1053 Assert(pu8AndMaskWordAligned);
1054
1055 if (pu8AndMaskWordAligned)
1056 {
1057 /* According to MSDN the padding bits must be 0.
1058 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
1059 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
1060 Assert(u32PaddingBits < 8);
1061 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
1062
1063 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
1064 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
1065
1066 uint8_t *src = (uint8_t *)srcAndMaskPtr;
1067 uint8_t *dst = pu8AndMaskWordAligned;
1068
1069 unsigned i;
1070 for (i = 0; i < uHeight; i++)
1071 {
1072 memcpy(dst, src, cbAndMaskScan);
1073
1074 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
1075
1076 src += cbAndMaskScan;
1077 dst += cbAndMaskScan + 1;
1078 }
1079 }
1080 }
1081
1082 /* Create the AND mask bitmap: */
1083 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
1084 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
1085
1086 if (pu8AndMaskWordAligned)
1087 {
1088 RTMemTmpFree(pu8AndMaskWordAligned);
1089 }
1090 }
1091
1092 Assert(hBitmap);
1093 Assert(hMonoBitmap);
1094 if (hBitmap && hMonoBitmap)
1095 {
1096 DWORD *dstShapePtr = (DWORD *) lpBits;
1097
1098 for (uint y = 0; y < uHeight; y ++)
1099 {
1100 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
1101 srcShapePtr += srcShapePtrScan;
1102 dstShapePtr += uWidth;
1103 }
1104
1105 ICONINFO ii;
1106 ii.fIcon = FALSE;
1107 ii.xHotspot = uXHot;
1108 ii.yHotspot = uYHot;
1109 ii.hbmMask = hMonoBitmap;
1110 ii.hbmColor = hBitmap;
1111
1112 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
1113 Assert(hAlphaCursor);
1114 if (hAlphaCursor)
1115 {
1116 /* Set the new cursor: */
1117 m_cursor = QCursor(hAlphaCursor);
1118 if (m_alphaCursor)
1119 DestroyIcon(m_alphaCursor);
1120 m_alphaCursor = hAlphaCursor;
1121 m_fIsValidPointerShapePresent = true;
1122 }
1123 }
1124
1125 if (hMonoBitmap)
1126 DeleteObject(hMonoBitmap);
1127 if (hBitmap)
1128 DeleteObject(hBitmap);
1129
1130#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
1131
1132 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
1133 Assert(img);
1134 if (img)
1135 {
1136 img->xhot = uXHot;
1137 img->yhot = uYHot;
1138
1139 XcursorPixel *dstShapePtr = img->pixels;
1140
1141 for (uint y = 0; y < uHeight; y ++)
1142 {
1143 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
1144
1145 if (!fHasAlpha)
1146 {
1147 /* Convert AND mask to the alpha channel: */
1148 uchar byte = 0;
1149 for (uint x = 0; x < uWidth; x ++)
1150 {
1151 if (!(x % 8))
1152 byte = *(srcAndMaskPtr ++);
1153 else
1154 byte <<= 1;
1155
1156 if (byte & 0x80)
1157 {
1158 /* Linux doesn't support inverted pixels (XOR ops,
1159 * to be exact) in cursor shapes, so we detect such
1160 * pixels and always replace them with black ones to
1161 * make them visible at least over light colors */
1162 if (dstShapePtr [x] & 0x00FFFFFF)
1163 dstShapePtr [x] = 0xFF000000;
1164 else
1165 dstShapePtr [x] = 0x00000000;
1166 }
1167 else
1168 dstShapePtr [x] |= 0xFF000000;
1169 }
1170 }
1171
1172 srcShapePtr += srcShapePtrScan;
1173 dstShapePtr += uWidth;
1174 }
1175
1176 /* Set the new cursor: */
1177 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
1178 m_fIsValidPointerShapePresent = true;
1179
1180 XcursorImageDestroy(img);
1181 }
1182
1183#elif defined(Q_WS_MAC)
1184
1185 /* Create a ARGB image out of the shape data. */
1186 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
1187 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
1188 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
1189 for (unsigned int y = 0; y < uHeight; ++y)
1190 {
1191 for (unsigned int x = 0; x < uWidth; ++x)
1192 {
1193 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
1194 /* If the alpha channel isn't in the shape data, we have to
1195 * create them from the and-mask. This is a bit field where 1
1196 * represent transparency & 0 opaque respectively. */
1197 if (!fHasAlpha)
1198 {
1199 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
1200 color |= 0xff000000;
1201 else
1202 {
1203 /* This isn't quite right, but it's the best we can do I think... */
1204 if (color & 0x00ffffff)
1205 color = 0xff000000;
1206 else
1207 color = 0x00000000;
1208 }
1209 }
1210 image.setPixel (x, y, color);
1211 }
1212 /* Move one scanline forward. */
1213 pbSrcMask += cbSrcMaskLine;
1214 }
1215
1216 /* Set the new cursor: */
1217 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
1218 m_fIsValidPointerShapePresent = true;
1219 NOREF(srcShapePtrScan);
1220
1221#else
1222
1223# warning "port me"
1224
1225#endif
1226}
1227
1228void UISession::reinitMenuPool()
1229{
1230 /* Get uisession machine: */
1231 const CMachine &machine = session().GetConsole().GetMachine();
1232
1233 /* Storage stuff: */
1234 {
1235 /* Initialize CD/FD menus: */
1236 int iDevicesCountCD = 0;
1237 int iDevicesCountFD = 0;
1238 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
1239 for (int i = 0; i < attachments.size(); ++i)
1240 {
1241 const CMediumAttachment &attachment = attachments[i];
1242 if (attachment.GetType() == KDeviceType_DVD)
1243 ++iDevicesCountCD;
1244 if (attachment.GetType() == KDeviceType_Floppy)
1245 ++iDevicesCountFD;
1246 }
1247 QAction *pOpticalDevicesMenu = gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices);
1248 QAction *pFloppyDevicesMenu = gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices);
1249 pOpticalDevicesMenu->setData(iDevicesCountCD);
1250 pOpticalDevicesMenu->setVisible(iDevicesCountCD);
1251 pFloppyDevicesMenu->setData(iDevicesCountFD);
1252 pFloppyDevicesMenu->setVisible(iDevicesCountFD);
1253 }
1254
1255 /* Network stuff: */
1256 {
1257 bool fAtLeastOneAdapterActive = false;
1258 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);
1259 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot)
1260 {
1261 const CNetworkAdapter &adapter = machine.GetNetworkAdapter(uSlot);
1262 if (adapter.GetEnabled())
1263 {
1264 fAtLeastOneAdapterActive = true;
1265 break;
1266 }
1267 }
1268 /* Show/Hide Network Adapters action depending on overall adapters activity status: */
1269 gActionPool->action(UIActionIndexRuntime_Simple_NetworkAdaptersDialog)->setVisible(fAtLeastOneAdapterActive);
1270 }
1271
1272 /* USB stuff: */
1273 {
1274 /* Get USB controller: */
1275 const CUSBController &usbController = machine.GetUSBController();
1276 bool fUSBControllerEnabled = !usbController.isNull() && usbController.GetEnabled() && usbController.GetProxyAvailable();
1277 /* Show/Hide USB menu depending on controller availability, activity and USB-proxy presence: */
1278 gActionPool->action(UIActionIndexRuntime_Menu_USBDevices)->setVisible(fUSBControllerEnabled);
1279 }
1280}
1281
1282bool UISession::preparePowerUp()
1283{
1284 /* Notify user about mouse&keyboard auto-capturing: */
1285 if (vboxGlobal().settings().autoCapture())
1286 msgCenter().remindAboutAutoCapture();
1287
1288 /* Shows First Run wizard if necessary: */
1289 const CMachine &machine = session().GetMachine();
1290 /* Check if we are in teleportation waiting mode.
1291 * In that case no first run wizard is necessary. */
1292 m_machineState = machine.GetState();
1293 if ( isFirstTimeStarted()
1294 && !(( m_machineState == KMachineState_PoweredOff
1295 || m_machineState == KMachineState_Aborted
1296 || m_machineState == KMachineState_Teleported)
1297 && machine.GetTeleporterEnabled()))
1298 {
1299 UISafePointerWizard pWizard = new UIWizardFirstRun(mainMachineWindow(), session().GetMachine());
1300 pWizard->prepare();
1301 pWizard->exec();
1302 if (pWizard)
1303 delete pWizard;
1304 }
1305
1306#ifdef VBOX_WITH_NETFLT
1307
1308 /* Skip further checks if VM in saved state */
1309 if (isSaved())
1310 return true;
1311
1312 /* Make sure all the attached and enabled network
1313 * adapters are present on the host. This check makes sense
1314 * in two cases only - when attachement type is Bridged Network
1315 * or Host-only Interface. NOTE: Only currently enabled
1316 * attachement type is checked (incorrect parameters check for
1317 * currently disabled attachement types is skipped). */
1318 QStringList failedInterfaceNames;
1319 QStringList availableInterfaceNames;
1320
1321 /* Create host network interface names list */
1322 foreach (const CHostNetworkInterface &iface, vboxGlobal().host().GetNetworkInterfaces())
1323 {
1324 availableInterfaceNames << iface.GetName();
1325 }
1326
1327 ulong cCount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(machine.GetChipsetType());
1328 for (ulong uAdapterIndex = 0; uAdapterIndex < cCount; ++uAdapterIndex)
1329 {
1330 CNetworkAdapter na = machine.GetNetworkAdapter(uAdapterIndex);
1331
1332 if (na.GetEnabled())
1333 {
1334 QString strIfName = QString();
1335
1336 /* Get physical network interface name for currently
1337 * enabled network attachement type */
1338 switch (na.GetAttachmentType())
1339 {
1340 case KNetworkAttachmentType_Bridged:
1341 strIfName = na.GetBridgedInterface();
1342 break;
1343 case KNetworkAttachmentType_HostOnly:
1344 strIfName = na.GetHostOnlyInterface();
1345 break;
1346 }
1347
1348 if (!strIfName.isEmpty() &&
1349 !availableInterfaceNames.contains(strIfName))
1350 {
1351 LogFlow(("Found invalid network interface: %s\n", strIfName.toStdString().c_str()));
1352 failedInterfaceNames << QString("%1 (adapter %2)").arg(strIfName).arg(uAdapterIndex + 1);
1353 }
1354 }
1355 }
1356
1357 /* Check if non-existent interfaces found */
1358 if (!failedInterfaceNames.isEmpty())
1359 {
1360 if (msgCenter().UIMessageCenter::cannotStartWithoutNetworkIf(machine.GetName(), failedInterfaceNames.join(", ")))
1361 machineLogic()->openNetworkAdaptersDialog();
1362 else
1363 {
1364 closeRuntimeUI();
1365 return false;
1366 }
1367 }
1368
1369#endif
1370
1371 return true;
1372}
1373
1374bool UISession::isScreenVisible(ulong uScreenId) const
1375{
1376 Assert(uScreenId < (ulong)m_monitorVisibilityVector.size());
1377 return m_monitorVisibilityVector.value((int)uScreenId, false);
1378}
1379
1380void UISession::setScreenVisible(ulong uScreenId, bool fIsMonitorVisible)
1381{
1382 Assert(uScreenId < (ulong)m_monitorVisibilityVector.size());
1383 if (uScreenId < (ulong)m_monitorVisibilityVector.size())
1384 m_monitorVisibilityVector[(int)uScreenId] = fIsMonitorVisible;
1385}
1386
1387int UISession::countOfVisibleWindows()
1388{
1389 int cCountOfVisibleWindows = 0;
1390 for (int i = 0; i < m_monitorVisibilityVector.size(); ++i)
1391 if (m_monitorVisibilityVector[i])
1392 ++cCountOfVisibleWindows;
1393 return cCountOfVisibleWindows;
1394}
1395
1396UIFrameBuffer* UISession::frameBuffer(ulong uScreenId) const
1397{
1398 Assert(uScreenId < (ulong)m_frameBufferVector.size());
1399 return m_frameBufferVector.value((int)uScreenId, 0);
1400}
1401
1402void UISession::setFrameBuffer(ulong uScreenId, UIFrameBuffer* pFrameBuffer)
1403{
1404 Assert(uScreenId < (ulong)m_frameBufferVector.size());
1405 if (uScreenId < (ulong)m_frameBufferVector.size())
1406 m_frameBufferVector[(int)uScreenId] = pFrameBuffer;
1407}
1408
1409#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
1410/**
1411 * Custom signal handler. When switching VTs, we might not get release events
1412 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will
1413 * be saved with modifier keys stuck. This is annoying enough for introducing
1414 * this hack.
1415 */
1416/* static */
1417void UISession::signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */)
1418{
1419 /* only SIGUSR1 is interesting */
1420 if (sig == SIGUSR1)
1421 if (UIMachine *pMachine = vboxGlobal().virtualMachine())
1422 pMachine->uisession()->machineLogic()->keyboardHandler()->releaseAllPressedKeys();
1423}
1424#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
1425
Note: See TracBrowser for help on using the repository browser.

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