VirtualBox

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

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

FE/Qt: 6909: Medium-enumeration cleanup/rework (part 6).

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