VirtualBox

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

Last change on this file since 34479 was 34479, checked in by vboxsync, 14 years ago

FE/Qt4: UIProgressDialog cleanup; it's possible to add an image to the progress
dialog now; images and sheet windows for save/restore state

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