VirtualBox

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

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

FE/Qt: Runtime UI: Close-event rework/cleanup (part 2).

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