VirtualBox

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

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

FE/Qt: Using popup-center stuff for *auto-capture* warning.

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