VirtualBox

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

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

FE/Qt: Message-center: Parent choosing rule simplification.

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