VirtualBox

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

Last change on this file since 39968 was 39968, checked in by vboxsync, 13 years ago

FE/Qt: cache vboxGlobal().virtualBox().GetHost()

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.3 KB
Line 
1/* $Id: UISession.cpp 39968 2012-02-02 19:26:12Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UISession stuff implementation
6 */
7
8/*
9 * Copyright (C) 2006-2011 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/* Global includes */
21#include <QApplication>
22#include <QWidget>
23#include <QTimer>
24
25/* Local includes */
26#include "UISession.h"
27#include "UIMachine.h"
28#include "UIActionPoolRuntime.h"
29#include "UIMachineLogic.h"
30#include "UIMachineWindow.h"
31#include "UIMachineMenuBar.h"
32#include "UIMessageCenter.h"
33#include "UIFirstRunWzd.h"
34#include "UIConsoleEventHandler.h"
35#ifdef VBOX_WITH_VIDEOHWACCEL
36# include "VBoxFBOverlay.h"
37# include "UIFrameBuffer.h"
38#endif
39
40#ifdef Q_WS_X11
41# include <QX11Info>
42# include <X11/Xlib.h>
43# include <X11/Xutil.h>
44# ifndef VBOX_WITHOUT_XCURSOR
45# include <X11/Xcursor/Xcursor.h>
46# endif
47#endif
48
49#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
50# include "UIKeyboardHandler.h"
51# include <signal.h>
52#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
53
54UISession::UISession(UIMachine *pMachine, CSession &sessionReference)
55 : QObject(pMachine)
56 /* Base variables: */
57 , m_pMachine(pMachine)
58 , m_session(sessionReference)
59 /* Common variables: */
60 , m_pMenuPool(0)
61#ifdef VBOX_WITH_VIDEOHWACCEL
62 , m_FrameBufferVector(sessionReference.GetMachine().GetMonitorCount())
63#endif
64 , m_machineState(KMachineState_Null)
65#if defined(Q_WS_WIN)
66 , m_alphaCursor(0)
67#endif
68 /* Common flags: */
69 , m_fIsFirstTimeStarted(false)
70 , m_fIsIgnoreRuntimeMediumsChanging(false)
71 , m_fIsGuestResizeIgnored(false)
72 , m_fIsSeamlessModeRequested(false)
73 , m_fIsAutoCaptureDisabled(false)
74 /* Guest additions flags: */
75 , m_ulGuestAdditionsRunLevel(0)
76 , m_fIsGuestSupportsGraphics(false)
77 , m_fIsGuestSupportsSeamless(false)
78 /* Mouse flags: */
79 , m_fNumLock(false)
80 , m_fCapsLock(false)
81 , m_fScrollLock(false)
82 , m_uNumLockAdaptionCnt(2)
83 , m_uCapsLockAdaptionCnt(2)
84 /* Mouse flags: */
85 , m_fIsMouseSupportsAbsolute(false)
86 , m_fIsMouseSupportsRelative(false)
87 , m_fIsMouseHostCursorNeeded(false)
88 , m_fIsMouseCaptured(false)
89 , m_fIsMouseIntegrated(true)
90 , m_fIsValidPointerShapePresent(false)
91 , m_fIsHidingHostPointer(true)
92{
93 /* Explicit initialize the console event handler */
94 UIConsoleEventHandler::instance(this);
95
96 /* Add console event connections */
97 connect(gConsoleEvents, SIGNAL(sigMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)),
98 this, SLOT(sltMousePointerShapeChange(bool, bool, QPoint, QSize, QVector<uint8_t>)));
99
100 connect(gConsoleEvents, SIGNAL(sigMouseCapabilityChange(bool, bool, bool)),
101 this, SLOT(sltMouseCapabilityChange(bool, bool, bool)));
102
103 connect(gConsoleEvents, SIGNAL(sigKeyboardLedsChangeEvent(bool, bool, bool)),
104 this, SLOT(sltKeyboardLedsChangeEvent(bool, bool, bool)));
105
106 connect(gConsoleEvents, SIGNAL(sigStateChange(KMachineState)),
107 this, SLOT(sltStateChange(KMachineState)));
108
109 connect(gConsoleEvents, SIGNAL(sigAdditionsChange()),
110 this, SLOT(sltAdditionsChange()));
111
112 connect(gConsoleEvents, SIGNAL(sigVRDEChange()),
113 this, SLOT(sltVRDEChange()));
114
115 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)),
116 this, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)));
117
118 connect(gConsoleEvents, SIGNAL(sigMediumChange(CMediumAttachment)),
119 this, SIGNAL(sigMediumChange(CMediumAttachment)));
120
121 connect(gConsoleEvents, SIGNAL(sigUSBControllerChange()),
122 this, SIGNAL(sigUSBControllerChange()));
123
124 connect(gConsoleEvents, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)),
125 this, SIGNAL(sigUSBDeviceStateChange(CUSBDevice, bool, CVirtualBoxErrorInfo)));
126
127 connect(gConsoleEvents, SIGNAL(sigSharedFolderChange()),
128 this, SIGNAL(sigSharedFolderChange()));
129
130 connect(gConsoleEvents, SIGNAL(sigRuntimeError(bool, QString, QString)),
131 this, SIGNAL(sigRuntimeError(bool, QString, QString)));
132
133#ifdef Q_WS_MAC
134 connect(gConsoleEvents, SIGNAL(sigShowWindow()),
135 this, SIGNAL(sigShowWindows()),
136 Qt::QueuedConnection);
137#endif /* Q_WS_MAC */
138
139 connect(gConsoleEvents, SIGNAL(sigCPUExecutionCapChange()),
140 this, SIGNAL(sigCPUExecutionCapChange()));
141
142 /* Prepare main menu: */
143 prepareMenuPool();
144
145 /* Load uisession settings: */
146 loadSessionSettings();
147
148#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
149 struct sigaction sa;
150 sa.sa_sigaction = &signalHandlerSIGUSR1;
151 sigemptyset(&sa.sa_mask);
152 sa.sa_flags = SA_RESTART | SA_SIGINFO;
153 sigaction(SIGUSR1, &sa, NULL);
154#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
155}
156
157UISession::~UISession()
158{
159 /* Save uisession settings: */
160 saveSessionSettings();
161
162 /* Cleanup main menu: */
163 cleanupMenuPool();
164
165 /* Destroy the console event handler */
166 UIConsoleEventHandler::destroy();
167
168#if defined(Q_WS_WIN)
169 /* Destroy alpha cursor: */
170 if (m_alphaCursor)
171 DestroyIcon(m_alphaCursor);
172#endif
173
174#ifdef VBOX_WITH_VIDEOHWACCEL
175 for (int i = m_FrameBufferVector.size() - 1; i >= 0; --i)
176 {
177 UIFrameBuffer *pFb = m_FrameBufferVector[i];
178 if (pFb)
179 {
180 /* Warn framebuffer about its no more necessary: */
181 pFb->setDeleted(true);
182 /* Detach framebuffer from Display: */
183 CDisplay display = session().GetConsole().GetDisplay();
184 display.SetFramebuffer(i, CFramebuffer(NULL));
185 /* Release the reference: */
186 pFb->Release();
187 }
188 }
189#endif
190}
191
192void UISession::powerUp()
193{
194 /* Do nothing if we had started already: */
195 if (isRunning() || isPaused())
196 return;
197
198 /* Prepare powerup: */
199 preparePowerUp();
200
201 /* Get current machine/console: */
202 CMachine machine = session().GetMachine();
203 CConsole console = session().GetConsole();
204
205 /* Apply debug settings from the command line. */
206 CMachineDebugger debugger = console.GetDebugger();
207 if (debugger.isOk())
208 {
209 if (vboxGlobal().isPatmDisabled())
210 debugger.SetPATMEnabled(false);
211 if (vboxGlobal().isCsamDisabled())
212 debugger.SetCSAMEnabled(false);
213 if (vboxGlobal().isSupervisorCodeExecedRecompiled())
214 debugger.SetRecompileSupervisor(true);
215 if (vboxGlobal().isUserCodeExecedRecompiled())
216 debugger.SetRecompileUser(true);
217 }
218
219 /* Power UP machine: */
220 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled(machine) ?
221 console.PowerUpPaused() : console.PowerUp();
222
223 /* Check for immediate failure: */
224 if (!console.isOk())
225 {
226 if (vboxGlobal().showStartVMErrors())
227 msgCenter().cannotStartMachine(console);
228 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
229 return;
230 }
231
232 /* Guard progressbar warnings from auto-closing: */
233 if (uimachine()->machineLogic())
234 uimachine()->machineLogic()->setPreventAutoClose(true);
235
236 /* Show "Starting/Restoring" progress dialog: */
237 if (isSaved())
238 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_state_restore_90px.png", mainMachineWindow(), true, 0);
239 else
240 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_start_90px.png", mainMachineWindow(), true);
241
242 /* Check for a progress failure: */
243 if (progress.GetResultCode() != 0)
244 {
245 if (vboxGlobal().showStartVMErrors())
246 msgCenter().cannotStartMachine(progress);
247 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
248 return;
249 }
250
251 /* Allow further auto-closing: */
252 if (uimachine()->machineLogic())
253 uimachine()->machineLogic()->setPreventAutoClose(false);
254
255 /* Check if we missed a really quick termination after successful startup, and process it if we did: */
256 if (isTurnedOff())
257 {
258 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
259 return;
260 }
261
262 /* Check if the required virtualization features are active. We get this
263 * info only when the session is active. */
264 bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetIs64Bit();
265 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx();
266 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n"));
267 bool fIsVirtEnabled = console.GetDebugger().GetHWVirtExEnabled();
268 if (fRecommendVirtEx && !fIsVirtEnabled)
269 {
270 bool fShouldWeClose;
271
272 bool fVTxAMDVSupported = vboxGlobal().host().GetProcessorFeature(KProcessorFeature_HWVirtEx);
273
274 QApplication::processEvents();
275 setPause(true);
276
277 if (fIs64BitsGuest)
278 fShouldWeClose = msgCenter().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported);
279 else
280 fShouldWeClose = msgCenter().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported);
281
282 if (fShouldWeClose)
283 {
284 /* At this point the console is powered up. So we have to close
285 * this session again. */
286 CProgress progress = console.PowerDown();
287 if (console.isOk())
288 {
289 /* Guard progressbar warnings from auto-closing: */
290 if (uimachine()->machineLogic())
291 uimachine()->machineLogic()->setPreventAutoClose(true);
292 /* Show the power down progress dialog */
293 msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_poweroff_90px.png", mainMachineWindow(), true);
294 if (progress.GetResultCode() != 0)
295 msgCenter().cannotStopMachine(progress);
296 /* Allow further auto-closing: */
297 if (uimachine()->machineLogic())
298 uimachine()->machineLogic()->setPreventAutoClose(false);
299 }
300 else
301 msgCenter().cannotStopMachine(console);
302 /* Now signal the destruction of the rest. */
303 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
304 return;
305 }
306
307 setPause(false);
308 }
309
310#ifdef VBOX_WITH_VIDEOHWACCEL
311 LogRel(("2D video acceleration is %s.\n",
312 machine.GetAccelerate2DVideoEnabled() && VBoxGlobal::isAcceleration2DVideoAvailable()
313 ? "enabled"
314 : "disabled"));
315#endif
316
317#ifdef VBOX_GUI_WITH_PIDFILE
318 vboxGlobal().createPidfile();
319#endif
320
321 /* Warn listeners about machine was started: */
322 emit sigMachineStarted();
323}
324
325QWidget* UISession::mainMachineWindow() const
326{
327 return uimachine()->machineLogic()->mainMachineWindow()->machineWindow();
328}
329
330UIMachineLogic* UISession::machineLogic() const
331{
332 return uimachine()->machineLogic();
333}
334
335QMenu* UISession::newMenu(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
336{
337 /* Create new menu: */
338 QMenu *pMenu = m_pMenuPool->createMenu(fOptions);
339
340 /* Re-init menu pool for the case menu were recreated: */
341 reinitMenuPool();
342
343 /* Return newly created menu: */
344 return pMenu;
345}
346
347QMenuBar* UISession::newMenuBar(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
348{
349 /* Create new menubar: */
350 QMenuBar *pMenuBar = m_pMenuPool->createMenuBar(fOptions);
351
352 /* Re-init menu pool for the case menu were recreated: */
353 reinitMenuPool();
354
355 /* Return newly created menubar: */
356 return pMenuBar;
357}
358
359bool UISession::setPause(bool fOn)
360{
361 /* Commenting it out as isPaused() could reflect
362 * quite obsolete state due to synchronization: */
363 //if (isPaused() == fOn)
364 // return true;
365
366 CConsole console = session().GetConsole();
367
368 if (fOn)
369 console.Pause();
370 else
371 console.Resume();
372
373 bool ok = console.isOk();
374 if (!ok)
375 {
376 if (fOn)
377 msgCenter().cannotPauseMachine(console);
378 else
379 msgCenter().cannotResumeMachine(console);
380 }
381
382 return ok;
383}
384
385void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
386{
387 CMachine machine = session().GetMachine();
388 CVirtualBox vbox = vboxGlobal().virtualBox();
389
390 /*
391 * Flag indicating whether we want to do the usual .ISO mounting or not.
392 * First try updating the Guest Additions directly without mounting the .ISO.
393 */
394 bool fDoMount = false;
395 /* Auto-update in GUI currently is disabled. */
396#ifndef VBOX_WITH_ADDITIONS_AUTOUPDATE_UI
397 fDoMount = true;
398#else
399 CGuest guest = session().GetConsole().GetGuest();
400 /* Since we are going to show a modal progress dialog we don't want to wait for the whole
401 * update progress being complete - the user might need to interact with the VM to confirm (WHQL)
402 * popups - instead we only wait until the actual update process was started. */
403 CProgress progressInstall = guest.UpdateGuestAdditions(strSource,
404 AdditionsUpdateFlag_WaitForUpdateStartOnly);
405 bool fResult = guest.isOk();
406 if (fResult)
407 {
408 msgCenter().showModalProgressDialog(progressInstall, tr("Install"), ":/progress_install_guest_additions_90px.png",
409 mainMachineWindow(), true, 500 /* 500ms delay. */);
410 if (progressInstall.GetCanceled())
411 return;
412
413 HRESULT rc = progressInstall.GetResultCode();
414 if (!progressInstall.isOk() || rc != S_OK)
415 {
416 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS
417 * simply isn't supported yet), so silently fall back to "old" .ISO
418 * mounting method. */
419 if ( !SUCCEEDED_WARNING(rc)
420 && rc != VBOX_E_NOT_SUPPORTED)
421 {
422 msgCenter().cannotUpdateGuestAdditions(progressInstall, mainMachineWindow());
423
424 /* Log the error message in the release log. */
425 QString strErr = progressInstall.GetErrorInfo().GetText();
426 if (!strErr.isEmpty())
427 LogRel(("%s\n", strErr.toLatin1().constData()));
428 }
429 fDoMount = true; /* Since automatic updating failed, fall back to .ISO mounting. */
430 }
431 }
432#endif /* VBOX_WITH_ADDITIONS_AUTOUPDATE_UI */
433
434 if (fDoMount) /* Fallback to only mounting the .ISO file. */
435 {
436 QString strUuid;
437 CMedium image = vbox.FindMedium(strSource, KDeviceType_DVD);
438 if (image.isNull())
439 {
440 image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite, false /* fForceNewUuid */);
441 if (vbox.isOk())
442 strUuid = image.GetId();
443 }
444 else
445 strUuid = image.GetId();
446
447 if (!vbox.isOk())
448 {
449 msgCenter().cannotOpenMedium(0, vbox, VBoxDefs::MediumType_DVD, strSource);
450 return;
451 }
452
453 AssertMsg(!strUuid.isNull(), ("Guest Additions image UUID should be valid!\n"));
454
455 QString strCntName;
456 LONG iCntPort = -1, iCntDevice = -1;
457 /* Searching for the first suitable slot */
458 {
459 CStorageControllerVector controllers = machine.GetStorageControllers();
460 int i = 0;
461 while (i < controllers.size() && strCntName.isNull())
462 {
463 CStorageController controller = controllers[i];
464 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName());
465 int j = 0;
466 while (j < attachments.size() && strCntName.isNull())
467 {
468 CMediumAttachment attachment = attachments[j];
469 if (attachment.GetType() == KDeviceType_DVD)
470 {
471 strCntName = controller.GetName();
472 iCntPort = attachment.GetPort();
473 iCntDevice = attachment.GetDevice();
474 }
475 ++ j;
476 }
477 ++ i;
478 }
479 }
480
481 if (!strCntName.isNull())
482 {
483 /* Create a new VBoxMedium: */
484 VBoxMedium vboxMedium(image, VBoxDefs::MediumType_DVD, KMediumState_Created);
485 /* Register it in GUI internal list: */
486 vboxGlobal().addMedium(vboxMedium);
487
488 /* Mount medium to the predefined port/device: */
489 machine.MountMedium(strCntName, iCntPort, iCntDevice, vboxMedium.medium(), false /* force */);
490 if (!machine.isOk())
491 {
492 /* Ask for force mounting: */
493 if (msgCenter().cannotRemountMedium(0, machine, vboxMedium, true /* mount? */, true /* retry? */) == QIMessageBox::Ok)
494 {
495 /* Force mount medium to the predefined port/device: */
496 machine.MountMedium(strCntName, iCntPort, iCntDevice, vboxMedium.medium(), true /* force */);
497 if (!machine.isOk())
498 msgCenter().cannotRemountMedium(0, machine, vboxMedium, true /* mount? */, false /* retry? */);
499 }
500 }
501 }
502 else
503 msgCenter().cannotMountGuestAdditions(machine.GetName());
504 }
505}
506
507void UISession::sltCloseVirtualSession()
508{
509 /* Recursively close all the usual modal & popup widgets... */
510 QWidget *widget = QApplication::activeModalWidget() ?
511 QApplication::activeModalWidget() :
512 QApplication::activePopupWidget() ?
513 QApplication::activePopupWidget() : 0;
514 if (widget)
515 {
516 widget->hide();
517 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
518 return;
519 }
520
521 /* Recursively close all the opened warnings... */
522 if (msgCenter().isAnyWarningShown())
523 {
524 msgCenter().closeAllWarnings();
525 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
526 return;
527 }
528
529 /* Finally, ask for closing virtual machine: */
530 QTimer::singleShot(0, m_pMachine, SLOT(sltCloseVirtualMachine()));
531}
532
533void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape)
534{
535 /* In case of shape data is present: */
536 if (shape.size() > 0)
537 {
538 /* We are ignoring visibility flag: */
539 m_fIsHidingHostPointer = false;
540
541 /* And updating current cursor shape: */
542 setPointerShape(shape.data(), fAlpha,
543 hotCorner.x(), hotCorner.y(),
544 size.width(), size.height());
545 }
546 /* In case of shape data is NOT present: */
547 else
548 {
549 /* Remember if we should hide the cursor: */
550 m_fIsHidingHostPointer = !fVisible;
551 }
552
553 /* Notify listeners about mouse capability changed: */
554 emit sigMousePointerShapeChange();
555
556}
557
558void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fNeedsHostCursor)
559{
560 /* Check if something had changed: */
561 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute
562 || m_fIsMouseSupportsRelative != fSupportsRelative
563 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor)
564 {
565 /* Store new data: */
566 m_fIsMouseSupportsAbsolute = fSupportsAbsolute;
567 m_fIsMouseSupportsRelative = fSupportsRelative;
568 m_fIsMouseHostCursorNeeded = fNeedsHostCursor;
569
570 /* Notify listeners about mouse capability changed: */
571 emit sigMouseCapabilityChange();
572 }
573}
574
575void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock)
576{
577 /* Check if something had changed: */
578 if ( m_fNumLock != fNumLock
579 || m_fCapsLock != fCapsLock
580 || m_fScrollLock != fScrollLock)
581 {
582 /* Store new num lock data: */
583 if (m_fNumLock != fNumLock)
584 {
585 m_fNumLock = fNumLock;
586 m_uNumLockAdaptionCnt = 2;
587 }
588
589 /* Store new caps lock data: */
590 if (m_fCapsLock != fCapsLock)
591 {
592 m_fCapsLock = fCapsLock;
593 m_uCapsLockAdaptionCnt = 2;
594 }
595
596 /* Store new scroll lock data: */
597 if (m_fScrollLock != fScrollLock)
598 {
599 m_fScrollLock = fScrollLock;
600 }
601
602 /* Notify listeners about mouse capability changed: */
603 emit sigKeyboardLedsChange();
604 }
605}
606
607void UISession::sltStateChange(KMachineState state)
608{
609 /* Check if something had changed: */
610 if (m_machineState != state)
611 {
612 /* Store new data: */
613 m_machineState = state;
614
615 /* Notify listeners about machine state changed: */
616 emit sigMachineStateChange();
617 }
618}
619
620void UISession::sltVRDEChange()
621{
622 /* Get machine: */
623 const CMachine &machine = session().GetMachine();
624 /* Get VRDE server: */
625 const CVRDEServer &server = machine.GetVRDEServer();
626 bool fIsVRDEServerAvailable = !server.isNull();
627 /* Show/Hide VRDE action depending on VRDE server availability status: */
628 gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer)->setVisible(fIsVRDEServerAvailable);
629 /* Check/Uncheck VRDE action depending on VRDE server activity status: */
630 if (fIsVRDEServerAvailable)
631 gActionPool->action(UIActionIndexRuntime_Toggle_VRDEServer)->setChecked(server.GetEnabled());
632 /* Notify listeners about VRDE change: */
633 emit sigVRDEChange();
634}
635
636void UISession::sltAdditionsChange()
637{
638 /* Get our guest: */
639 CGuest guest = session().GetConsole().GetGuest();
640
641 /* Variable flags: */
642 ULONG ulGuestAdditionsRunLevel = guest.GetAdditionsRunLevel();
643 LONG64 lLastUpdatedIgnored;
644 bool fIsGuestSupportsGraphics = guest.GetFacilityStatus(KAdditionsFacilityType_Graphics, lLastUpdatedIgnored)
645 == KAdditionsFacilityStatus_Active;
646 bool fIsGuestSupportsSeamless = guest.GetFacilityStatus(KAdditionsFacilityType_Seamless, lLastUpdatedIgnored)
647 == KAdditionsFacilityStatus_Active;
648 /* Check if something had changed: */
649 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel ||
650 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
651 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
652 {
653 /* Store new data: */
654 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
655 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
656 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
657
658 /* Notify listeners about guest additions state changed: */
659 emit sigAdditionsStateChange();
660 }
661}
662
663void UISession::prepareMenuPool()
664{
665 m_pMenuPool = new UIMachineMenuBar;
666}
667
668void UISession::loadSessionSettings()
669{
670 /* Get uisession machine: */
671 CMachine machine = session().GetConsole().GetMachine();
672
673 /* Load extra-data settings: */
674 {
675 /* Temporary: */
676 QString strSettings;
677
678 /* Is there should be First RUN Wizard? */
679 strSettings = machine.GetExtraData(VBoxDefs::GUI_FirstRun);
680 if (strSettings == "yes")
681 m_fIsFirstTimeStarted = true;
682
683 /* Ignore mediums mounted at runtime? */
684 strSettings = machine.GetExtraData(VBoxDefs::GUI_SaveMountedAtRuntime);
685 if (strSettings == "no")
686 m_fIsIgnoreRuntimeMediumsChanging = true;
687
688 /* Should guest autoresize? */
689 strSettings = machine.GetExtraData(VBoxDefs::GUI_AutoresizeGuest);
690 QAction *pGuestAutoresizeSwitch = gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize);
691 pGuestAutoresizeSwitch->setChecked(strSettings != "off");
692
693#if 0 /* Disabled for now! */
694# ifdef Q_WS_WIN
695 /* Disable host screen-saver if requested: */
696 if (vboxGlobal().settings().hostScreenSaverDisabled())
697 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, 0, 0);
698# endif /* Q_WS_WIN */
699#endif
700 }
701}
702
703void UISession::saveSessionSettings()
704{
705 /* Get uisession machine: */
706 CMachine machine = session().GetConsole().GetMachine();
707
708 /* Save extra-data settings: */
709 {
710 /* Disable First RUN Wizard for the since now: */
711 machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString());
712
713 /* Remember if guest should autoresize: */
714 machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest,
715 gActionPool->action(UIActionIndexRuntime_Toggle_GuestAutoresize)->isChecked() ?
716 QString() : "off");
717
718#if 0 /* Disabled for now! */
719# ifdef Q_WS_WIN
720 /* Restore screen-saver activity to system default: */
721 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, true, 0, 0);
722# endif /* Q_WS_WIN */
723#endif
724 }
725}
726
727void UISession::cleanupMenuPool()
728{
729 delete m_pMenuPool;
730 m_pMenuPool = 0;
731}
732
733WId UISession::winId() const
734{
735 return mainMachineWindow()->winId();
736}
737
738void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
739 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
740{
741 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
742
743 m_fIsValidPointerShapePresent = false;
744 const uchar *srcAndMaskPtr = pShapeData;
745 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
746 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
747 uint srcShapePtrScan = uWidth * 4;
748
749#if defined (Q_WS_WIN)
750
751 BITMAPV5HEADER bi;
752 HBITMAP hBitmap;
753 void *lpBits;
754
755 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
756 bi.bV5Size = sizeof(BITMAPV5HEADER);
757 bi.bV5Width = uWidth;
758 bi.bV5Height = - (LONG)uHeight;
759 bi.bV5Planes = 1;
760 bi.bV5BitCount = 32;
761 bi.bV5Compression = BI_BITFIELDS;
762 bi.bV5RedMask = 0x00FF0000;
763 bi.bV5GreenMask = 0x0000FF00;
764 bi.bV5BlueMask = 0x000000FF;
765 if (fHasAlpha)
766 bi.bV5AlphaMask = 0xFF000000;
767 else
768 bi.bV5AlphaMask = 0;
769
770 HDC hdc = GetDC(NULL);
771
772 /* Create the DIB section with an alpha channel: */
773 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
774
775 ReleaseDC(NULL, hdc);
776
777 HBITMAP hMonoBitmap = NULL;
778 if (fHasAlpha)
779 {
780 /* Create an empty mask bitmap: */
781 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
782 }
783 else
784 {
785 /* Word aligned AND mask. Will be allocated and created if necessary. */
786 uint8_t *pu8AndMaskWordAligned = NULL;
787
788 /* Width in bytes of the original AND mask scan line. */
789 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
790
791 if (cbAndMaskScan & 1)
792 {
793 /* Original AND mask is not word aligned. */
794
795 /* Allocate memory for aligned AND mask. */
796 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
797
798 Assert(pu8AndMaskWordAligned);
799
800 if (pu8AndMaskWordAligned)
801 {
802 /* According to MSDN the padding bits must be 0.
803 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
804 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
805 Assert(u32PaddingBits < 8);
806 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
807
808 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
809 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
810
811 uint8_t *src = (uint8_t *)srcAndMaskPtr;
812 uint8_t *dst = pu8AndMaskWordAligned;
813
814 unsigned i;
815 for (i = 0; i < uHeight; i++)
816 {
817 memcpy(dst, src, cbAndMaskScan);
818
819 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
820
821 src += cbAndMaskScan;
822 dst += cbAndMaskScan + 1;
823 }
824 }
825 }
826
827 /* Create the AND mask bitmap: */
828 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
829 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
830
831 if (pu8AndMaskWordAligned)
832 {
833 RTMemTmpFree(pu8AndMaskWordAligned);
834 }
835 }
836
837 Assert(hBitmap);
838 Assert(hMonoBitmap);
839 if (hBitmap && hMonoBitmap)
840 {
841 DWORD *dstShapePtr = (DWORD *) lpBits;
842
843 for (uint y = 0; y < uHeight; y ++)
844 {
845 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
846 srcShapePtr += srcShapePtrScan;
847 dstShapePtr += uWidth;
848 }
849
850 ICONINFO ii;
851 ii.fIcon = FALSE;
852 ii.xHotspot = uXHot;
853 ii.yHotspot = uYHot;
854 ii.hbmMask = hMonoBitmap;
855 ii.hbmColor = hBitmap;
856
857 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
858 Assert(hAlphaCursor);
859 if (hAlphaCursor)
860 {
861 /* Set the new cursor: */
862 m_cursor = QCursor(hAlphaCursor);
863 if (m_alphaCursor)
864 DestroyIcon(m_alphaCursor);
865 m_alphaCursor = hAlphaCursor;
866 m_fIsValidPointerShapePresent = true;
867 }
868 }
869
870 if (hMonoBitmap)
871 DeleteObject(hMonoBitmap);
872 if (hBitmap)
873 DeleteObject(hBitmap);
874
875#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
876
877 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
878 Assert(img);
879 if (img)
880 {
881 img->xhot = uXHot;
882 img->yhot = uYHot;
883
884 XcursorPixel *dstShapePtr = img->pixels;
885
886 for (uint y = 0; y < uHeight; y ++)
887 {
888 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
889
890 if (!fHasAlpha)
891 {
892 /* Convert AND mask to the alpha channel: */
893 uchar byte = 0;
894 for (uint x = 0; x < uWidth; x ++)
895 {
896 if (!(x % 8))
897 byte = *(srcAndMaskPtr ++);
898 else
899 byte <<= 1;
900
901 if (byte & 0x80)
902 {
903 /* Linux doesn't support inverted pixels (XOR ops,
904 * to be exact) in cursor shapes, so we detect such
905 * pixels and always replace them with black ones to
906 * make them visible at least over light colors */
907 if (dstShapePtr [x] & 0x00FFFFFF)
908 dstShapePtr [x] = 0xFF000000;
909 else
910 dstShapePtr [x] = 0x00000000;
911 }
912 else
913 dstShapePtr [x] |= 0xFF000000;
914 }
915 }
916
917 srcShapePtr += srcShapePtrScan;
918 dstShapePtr += uWidth;
919 }
920
921 /* Set the new cursor: */
922 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
923 m_fIsValidPointerShapePresent = true;
924
925 XcursorImageDestroy(img);
926 }
927
928#elif defined(Q_WS_MAC)
929
930 /* Create a ARGB image out of the shape data. */
931 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
932 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
933 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
934 for (unsigned int y = 0; y < uHeight; ++y)
935 {
936 for (unsigned int x = 0; x < uWidth; ++x)
937 {
938 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
939 /* If the alpha channel isn't in the shape data, we have to
940 * create them from the and-mask. This is a bit field where 1
941 * represent transparency & 0 opaque respectively. */
942 if (!fHasAlpha)
943 {
944 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
945 color |= 0xff000000;
946 else
947 {
948 /* This isn't quite right, but it's the best we can do I think... */
949 if (color & 0x00ffffff)
950 color = 0xff000000;
951 else
952 color = 0x00000000;
953 }
954 }
955 image.setPixel (x, y, color);
956 }
957 /* Move one scanline forward. */
958 pbSrcMask += cbSrcMaskLine;
959 }
960
961 /* Set the new cursor: */
962 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
963 m_fIsValidPointerShapePresent = true;
964 NOREF(srcShapePtrScan);
965
966#else
967
968# warning "port me"
969
970#endif
971}
972
973void UISession::reinitMenuPool()
974{
975 /* Get uisession machine: */
976 const CMachine &machine = session().GetConsole().GetMachine();
977
978 /* Storage stuff: */
979 {
980 /* Initialize CD/FD menus: */
981 int iDevicesCountCD = 0;
982 int iDevicesCountFD = 0;
983 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
984 for (int i = 0; i < attachments.size(); ++i)
985 {
986 const CMediumAttachment &attachment = attachments[i];
987 if (attachment.GetType() == KDeviceType_DVD)
988 ++iDevicesCountCD;
989 if (attachment.GetType() == KDeviceType_Floppy)
990 ++iDevicesCountFD;
991 }
992 QAction *pOpticalDevicesMenu = gActionPool->action(UIActionIndexRuntime_Menu_OpticalDevices);
993 QAction *pFloppyDevicesMenu = gActionPool->action(UIActionIndexRuntime_Menu_FloppyDevices);
994 pOpticalDevicesMenu->setData(iDevicesCountCD);
995 pOpticalDevicesMenu->setVisible(iDevicesCountCD);
996 pFloppyDevicesMenu->setData(iDevicesCountFD);
997 pFloppyDevicesMenu->setVisible(iDevicesCountFD);
998 }
999
1000 /* Network stuff: */
1001 {
1002 bool fAtLeastOneAdapterActive = false;
1003 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);
1004 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot)
1005 {
1006 const CNetworkAdapter &adapter = machine.GetNetworkAdapter(uSlot);
1007 if (adapter.GetEnabled())
1008 {
1009 fAtLeastOneAdapterActive = true;
1010 break;
1011 }
1012 }
1013 /* Show/Hide Network Adapters action depending on overall adapters activity status: */
1014 gActionPool->action(UIActionIndexRuntime_Simple_NetworkAdaptersDialog)->setVisible(fAtLeastOneAdapterActive);
1015 }
1016
1017 /* USB stuff: */
1018 {
1019 /* Get USB controller: */
1020 const CUSBController &usbController = machine.GetUSBController();
1021 bool fUSBControllerEnabled = !usbController.isNull() && usbController.GetEnabled() && usbController.GetProxyAvailable();
1022 /* Show/Hide USB menu depending on controller availability, activity and USB-proxy presence: */
1023 gActionPool->action(UIActionIndexRuntime_Menu_USBDevices)->setVisible(fUSBControllerEnabled);
1024 }
1025}
1026
1027void UISession::preparePowerUp()
1028{
1029 /* Notify user about mouse&keyboard auto-capturing: */
1030 if (vboxGlobal().settings().autoCapture())
1031 msgCenter().remindAboutAutoCapture();
1032
1033 /* Shows first run wizard if necessary: */
1034 const CMachine &machine = session().GetMachine();
1035 /* Check if we are in teleportation waiting mode. In that case no first run
1036 * wizard is necessary. */
1037 m_machineState = machine.GetState();
1038 if ( isFirstTimeStarted()
1039 && !(( m_machineState == KMachineState_PoweredOff
1040 || m_machineState == KMachineState_Aborted
1041 || m_machineState == KMachineState_Teleported)
1042 && machine.GetTeleporterEnabled()))
1043 {
1044 UIFirstRunWzd wzd(mainMachineWindow(), session().GetMachine());
1045 wzd.exec();
1046 }
1047}
1048
1049UIFrameBuffer* UISession::frameBuffer(ulong screenId) const
1050{
1051 Assert(screenId < (ulong)m_FrameBufferVector.size());
1052 return m_FrameBufferVector.value((int)screenId, NULL);
1053}
1054
1055int UISession::setFrameBuffer(ulong screenId, UIFrameBuffer* pFrameBuffer)
1056{
1057 Assert(screenId < (ulong)m_FrameBufferVector.size());
1058 if (screenId < (ulong)m_FrameBufferVector.size())
1059 {
1060 m_FrameBufferVector[(int)screenId] = pFrameBuffer;
1061 return VINF_SUCCESS;
1062 }
1063 return VERR_INVALID_PARAMETER;
1064}
1065
1066#ifdef VBOX_GUI_WITH_KEYS_RESET_HANDLER
1067/**
1068 * Custom signal handler. When switching VTs, we might not get release events
1069 * for Ctrl-Alt and in case a savestate is performed on the new VT, the VM will
1070 * be saved with modifier keys stuck. This is annoying enough for introducing
1071 * this hack.
1072 */
1073/* static */
1074void UISession::signalHandlerSIGUSR1(int sig, siginfo_t * /* pInfo */, void * /*pSecret */)
1075{
1076 /* only SIGUSR1 is interesting */
1077 if (sig == SIGUSR1)
1078 if (UIMachine *pMachine = vboxGlobal().virtualMachine())
1079 pMachine->uisession()->machineLogic()->keyboardHandler()->releaseAllPressedKeys();
1080}
1081#endif /* VBOX_GUI_WITH_KEYS_RESET_HANDLER */
1082
Note: See TracBrowser for help on using the repository browser.

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