VirtualBox

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

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

Guest Additions Update/Main+Fe/Qt4: Don't show errors (also don't in log) when old Guest Additions can't be updated automatically or when Guest Additions are not installed on guest - just use the "old" .ISO mounting approach.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.1 KB
Line 
1/* $Id: UISession.cpp 34254 2010-11-22 15:48:33Z 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(), mainMachineWindow(), 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", 0);
367#else
368 CProgress progressInstall = guest.UpdateGuestAdditions(strSource, 0 /* Flags, not used. */);
369#endif
370 bool fResult = guest.isOk();
371 if (fResult)
372 {
373 vboxProblem().showModalProgressDialog(progressInstall, tr("Install"),
374 mainMachineWindow(), 500 /* 500ms delay. */);
375 if (progressInstall.GetCanceled())
376 return;
377
378 HRESULT rc = progressInstall.GetResultCode();
379 if (!progressInstall.isOk() || rc != S_OK)
380 {
381 /* If we got back a VBOX_E_NOT_SUPPORTED we don't complain (guest OS
382 * simply isn't supported yet), so silently fall back to "old" .ISO
383 * mounting method. */
384 if ( !SUCCEEDED_WARNING(rc)
385 && rc != VBOX_E_NOT_SUPPORTED)
386 {
387 vboxProblem().cannotUpdateGuestAdditions(progressInstall, mainMachineWindow());
388
389 /* Log the error message in the release log. */
390 QString strErr = progressInstall.GetErrorInfo().GetText();
391 if (!strErr.isEmpty())
392 LogRel(("%s\n", strErr.toLatin1().constData()));
393 }
394 fDoMount = true; /* Since automatic updating failed, fall back to .ISO mounting. */
395 }
396 }
397
398 if (fDoMount) /* Fallback to only mounting the .ISO file. */
399 {
400 QString strUuid;
401 CMedium image = vbox.FindMedium(strSource, KDeviceType_DVD);
402 if (image.isNull())
403 {
404 image = vbox.OpenMedium(strSource, KDeviceType_DVD, KAccessMode_ReadWrite);
405 if (vbox.isOk())
406 strUuid = image.GetId();
407 }
408 else
409 strUuid = image.GetId();
410
411 if (!vbox.isOk())
412 {
413 vboxProblem().cannotOpenMedium(0, vbox, VBoxDefs::MediumType_DVD, strSource);
414 return;
415 }
416
417 AssertMsg(!strUuid.isNull(), ("Guest Additions image UUID should be valid!\n"));
418
419 QString strCntName;
420 LONG iCntPort = -1, iCntDevice = -1;
421 /* Searching for the first suitable slot */
422 {
423 CStorageControllerVector controllers = machine.GetStorageControllers();
424 int i = 0;
425 while (i < controllers.size() && strCntName.isNull())
426 {
427 CStorageController controller = controllers[i];
428 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName());
429 int j = 0;
430 while (j < attachments.size() && strCntName.isNull())
431 {
432 CMediumAttachment attachment = attachments[j];
433 if (attachment.GetType() == KDeviceType_DVD)
434 {
435 strCntName = controller.GetName();
436 iCntPort = attachment.GetPort();
437 iCntDevice = attachment.GetDevice();
438 }
439 ++ j;
440 }
441 ++ i;
442 }
443 }
444
445 if (!strCntName.isNull())
446 {
447 bool fIsMounted = false;
448
449 VBoxMedium vmedium = vboxGlobal().findMedium(strUuid);
450 CMedium medium = vmedium.medium(); // @todo r=dj can this be cached somewhere?
451
452 /* Mount medium to the predefined port/device */
453 machine.MountMedium(strCntName, iCntPort, iCntDevice, medium, false /* force */);
454 if (machine.isOk())
455 fIsMounted = true;
456 else
457 {
458 /* Ask for force mounting */
459 if (vboxProblem().cannotRemountMedium(0, machine, VBoxMedium(image, VBoxDefs::MediumType_DVD),
460 true /* mount? */, true /* retry? */) == QIMessageBox::Ok)
461 {
462 /* Force mount medium to the predefined port/device */
463 machine.MountMedium(strCntName, iCntPort, iCntDevice, medium, true /* force */);
464 if (machine.isOk())
465 fIsMounted = true;
466 else
467 vboxProblem().cannotRemountMedium(0, machine, VBoxMedium(image, VBoxDefs::MediumType_DVD),
468 true /* mount? */, false /* retry? */);
469 }
470 }
471 }
472 else
473 vboxProblem().cannotMountGuestAdditions(machine.GetName());
474 }
475}
476
477void UISession::sltCloseVirtualSession()
478{
479 /* Recursively close all the usual modal & popup widgets... */
480 QWidget *widget = QApplication::activeModalWidget() ?
481 QApplication::activeModalWidget() :
482 QApplication::activePopupWidget() ?
483 QApplication::activePopupWidget() : 0;
484 if (widget)
485 {
486 widget->hide();
487 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
488 return;
489 }
490
491 /* Recursively close all the opened warnings... */
492 if (vboxProblem().isAnyWarningShown())
493 {
494 vboxProblem().closeAllWarnings();
495 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
496 return;
497 }
498
499 /* Finally, ask for closing virtual machine: */
500 QTimer::singleShot(0, m_pMachine, SLOT(sltCloseVirtualMachine()));
501}
502
503void UISession::sltMousePointerShapeChange(bool fVisible, bool fAlpha, QPoint hotCorner, QSize size, QVector<uint8_t> shape)
504{
505 /* In case of shape data is present: */
506 if (shape.size() > 0)
507 {
508 /* We are ignoring visibility flag: */
509 m_fIsHidingHostPointer = false;
510
511 /* And updating current cursor shape: */
512 setPointerShape(shape.data(), fAlpha,
513 hotCorner.x(), hotCorner.y(),
514 size.width(), size.height());
515 }
516 /* In case of shape data is NOT present: */
517 else
518 {
519 /* Remember if we should hide the cursor: */
520 m_fIsHidingHostPointer = !fVisible;
521 }
522
523 /* Notify listeners about mouse capability changed: */
524 emit sigMousePointerShapeChange();
525
526}
527
528void UISession::sltMouseCapabilityChange(bool fSupportsAbsolute, bool fSupportsRelative, bool fNeedsHostCursor)
529{
530 /* Check if something had changed: */
531 if ( m_fIsMouseSupportsAbsolute != fSupportsAbsolute
532 || m_fIsMouseSupportsRelative != fSupportsRelative
533 || m_fIsMouseHostCursorNeeded != fNeedsHostCursor)
534 {
535 /* Store new data: */
536 m_fIsMouseSupportsAbsolute = fSupportsAbsolute;
537 m_fIsMouseSupportsRelative = fSupportsRelative;
538 m_fIsMouseHostCursorNeeded = fNeedsHostCursor;
539
540 /* Notify listeners about mouse capability changed: */
541 emit sigMouseCapabilityChange();
542 }
543}
544
545void UISession::sltKeyboardLedsChangeEvent(bool fNumLock, bool fCapsLock, bool fScrollLock)
546{
547 /* Check if something had changed: */
548 if ( m_fNumLock != fNumLock
549 || m_fCapsLock != fCapsLock
550 || m_fScrollLock != fScrollLock)
551 {
552 /* Store new num lock data: */
553 if (m_fNumLock != fNumLock)
554 {
555 m_fNumLock = fNumLock;
556 m_uNumLockAdaptionCnt = 2;
557 }
558
559 /* Store new caps lock data: */
560 if (m_fCapsLock != fCapsLock)
561 {
562 m_fCapsLock = fCapsLock;
563 m_uCapsLockAdaptionCnt = 2;
564 }
565
566 /* Store new scroll lock data: */
567 if (m_fScrollLock != fScrollLock)
568 {
569 m_fScrollLock = fScrollLock;
570 }
571
572 /* Notify listeners about mouse capability changed: */
573 emit sigKeyboardLedsChange();
574 }
575}
576
577void UISession::sltStateChange(KMachineState state)
578{
579 /* Check if something had changed: */
580 if (m_machineState != state)
581 {
582 /* Store new data: */
583 m_machineState = state;
584
585 /* Notify listeners about machine state changed: */
586 emit sigMachineStateChange();
587 }
588}
589
590void UISession::sltAdditionsChange()
591{
592 /* Get our guest: */
593 CGuest guest = session().GetConsole().GetGuest();
594
595 /* Variable flags: */
596 ULONG ulGuestAdditionsRunLevel = guest.GetAdditionsRunLevel();
597 bool fIsGuestSupportsGraphics = guest.GetSupportsGraphics();
598 bool fIsGuestSupportsSeamless = guest.GetSupportsSeamless();
599
600 /* Check if something had changed: */
601 if (m_ulGuestAdditionsRunLevel != ulGuestAdditionsRunLevel ||
602 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
603 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
604 {
605 /* Store new data: */
606 m_ulGuestAdditionsRunLevel = ulGuestAdditionsRunLevel;
607 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
608 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
609
610 /* Notify listeners about guest additions state changed: */
611 emit sigAdditionsStateChange();
612 }
613}
614
615void UISession::prepareMenuPool()
616{
617 m_pMenuPool = new UIMachineMenuBar;
618}
619
620void UISession::loadSessionSettings()
621{
622 /* Get uisession machine: */
623 CMachine machine = session().GetConsole().GetMachine();
624
625 /* Load extra-data settings: */
626 {
627 /* Temporary: */
628 QString strSettings;
629
630 /* Is there should be First RUN Wizard? */
631 strSettings = machine.GetExtraData(VBoxDefs::GUI_FirstRun);
632 if (strSettings == "yes")
633 m_fIsFirstTimeStarted = true;
634
635 /* Ignore mediums mounted at runtime? */
636 strSettings = machine.GetExtraData(VBoxDefs::GUI_SaveMountedAtRuntime);
637 if (strSettings == "no")
638 m_fIsIgnoreRuntimeMediumsChanging = true;
639
640 /* Should guest autoresize? */
641 strSettings = machine.GetExtraData(VBoxDefs::GUI_AutoresizeGuest);
642 QAction *pGuestAutoresizeSwitch = uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize);
643 pGuestAutoresizeSwitch->setChecked(strSettings != "off");
644
645#if 0 /* Disabled for now! */
646# ifdef Q_WS_WIN
647 /* Disable host screen-saver if requested: */
648 if (vboxGlobal().settings().hostScreenSaverDisabled())
649 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, 0, 0);
650# endif /* Q_WS_WIN */
651#endif
652 }
653}
654
655void UISession::saveSessionSettings()
656{
657 /* Get uisession machine: */
658 CMachine machine = session().GetConsole().GetMachine();
659
660 /* Save extra-data settings: */
661 {
662 /* Disable First RUN Wizard for the since now: */
663 machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString());
664
665 /* Remember if guest should autoresize: */
666 machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest,
667 uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->isChecked() ?
668 QString() : "off");
669
670#if 0 /* Disabled for now! */
671# ifdef Q_WS_WIN
672 /* Restore screen-saver activity to system default: */
673 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, true, 0, 0);
674# endif /* Q_WS_WIN */
675#endif
676 }
677}
678
679void UISession::cleanupMenuPool()
680{
681 delete m_pMenuPool;
682 m_pMenuPool = 0;
683}
684
685WId UISession::winId() const
686{
687 return mainMachineWindow()->winId();
688}
689
690void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
691 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
692{
693 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
694
695 m_fIsValidPointerShapePresent = false;
696 const uchar *srcAndMaskPtr = pShapeData;
697 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
698 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
699 uint srcShapePtrScan = uWidth * 4;
700
701#if defined (Q_WS_WIN)
702
703 BITMAPV5HEADER bi;
704 HBITMAP hBitmap;
705 void *lpBits;
706
707 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
708 bi.bV5Size = sizeof(BITMAPV5HEADER);
709 bi.bV5Width = uWidth;
710 bi.bV5Height = - (LONG)uHeight;
711 bi.bV5Planes = 1;
712 bi.bV5BitCount = 32;
713 bi.bV5Compression = BI_BITFIELDS;
714 bi.bV5RedMask = 0x00FF0000;
715 bi.bV5GreenMask = 0x0000FF00;
716 bi.bV5BlueMask = 0x000000FF;
717 if (fHasAlpha)
718 bi.bV5AlphaMask = 0xFF000000;
719 else
720 bi.bV5AlphaMask = 0;
721
722 HDC hdc = GetDC(NULL);
723
724 /* Create the DIB section with an alpha channel: */
725 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
726
727 ReleaseDC(NULL, hdc);
728
729 HBITMAP hMonoBitmap = NULL;
730 if (fHasAlpha)
731 {
732 /* Create an empty mask bitmap: */
733 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
734 }
735 else
736 {
737 /* Word aligned AND mask. Will be allocated and created if necessary. */
738 uint8_t *pu8AndMaskWordAligned = NULL;
739
740 /* Width in bytes of the original AND mask scan line. */
741 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
742
743 if (cbAndMaskScan & 1)
744 {
745 /* Original AND mask is not word aligned. */
746
747 /* Allocate memory for aligned AND mask. */
748 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
749
750 Assert(pu8AndMaskWordAligned);
751
752 if (pu8AndMaskWordAligned)
753 {
754 /* According to MSDN the padding bits must be 0.
755 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
756 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
757 Assert(u32PaddingBits < 8);
758 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
759
760 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
761 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
762
763 uint8_t *src = (uint8_t *)srcAndMaskPtr;
764 uint8_t *dst = pu8AndMaskWordAligned;
765
766 unsigned i;
767 for (i = 0; i < uHeight; i++)
768 {
769 memcpy(dst, src, cbAndMaskScan);
770
771 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
772
773 src += cbAndMaskScan;
774 dst += cbAndMaskScan + 1;
775 }
776 }
777 }
778
779 /* Create the AND mask bitmap: */
780 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
781 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
782
783 if (pu8AndMaskWordAligned)
784 {
785 RTMemTmpFree(pu8AndMaskWordAligned);
786 }
787 }
788
789 Assert(hBitmap);
790 Assert(hMonoBitmap);
791 if (hBitmap && hMonoBitmap)
792 {
793 DWORD *dstShapePtr = (DWORD *) lpBits;
794
795 for (uint y = 0; y < uHeight; y ++)
796 {
797 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
798 srcShapePtr += srcShapePtrScan;
799 dstShapePtr += uWidth;
800 }
801
802 ICONINFO ii;
803 ii.fIcon = FALSE;
804 ii.xHotspot = uXHot;
805 ii.yHotspot = uYHot;
806 ii.hbmMask = hMonoBitmap;
807 ii.hbmColor = hBitmap;
808
809 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
810 Assert(hAlphaCursor);
811 if (hAlphaCursor)
812 {
813 /* Set the new cursor: */
814 m_cursor = QCursor(hAlphaCursor);
815 if (m_alphaCursor)
816 DestroyIcon(m_alphaCursor);
817 m_alphaCursor = hAlphaCursor;
818 m_fIsValidPointerShapePresent = true;
819 }
820 }
821
822 if (hMonoBitmap)
823 DeleteObject(hMonoBitmap);
824 if (hBitmap)
825 DeleteObject(hBitmap);
826
827#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
828
829 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
830 Assert(img);
831 if (img)
832 {
833 img->xhot = uXHot;
834 img->yhot = uYHot;
835
836 XcursorPixel *dstShapePtr = img->pixels;
837
838 for (uint y = 0; y < uHeight; y ++)
839 {
840 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
841
842 if (!fHasAlpha)
843 {
844 /* Convert AND mask to the alpha channel: */
845 uchar byte = 0;
846 for (uint x = 0; x < uWidth; x ++)
847 {
848 if (!(x % 8))
849 byte = *(srcAndMaskPtr ++);
850 else
851 byte <<= 1;
852
853 if (byte & 0x80)
854 {
855 /* Linux doesn't support inverted pixels (XOR ops,
856 * to be exact) in cursor shapes, so we detect such
857 * pixels and always replace them with black ones to
858 * make them visible at least over light colors */
859 if (dstShapePtr [x] & 0x00FFFFFF)
860 dstShapePtr [x] = 0xFF000000;
861 else
862 dstShapePtr [x] = 0x00000000;
863 }
864 else
865 dstShapePtr [x] |= 0xFF000000;
866 }
867 }
868
869 srcShapePtr += srcShapePtrScan;
870 dstShapePtr += uWidth;
871 }
872
873 /* Set the new cursor: */
874 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
875 m_fIsValidPointerShapePresent = true;
876
877 XcursorImageDestroy(img);
878 }
879
880#elif defined(Q_WS_MAC)
881
882 /* Create a ARGB image out of the shape data. */
883 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
884 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
885 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
886 for (unsigned int y = 0; y < uHeight; ++y)
887 {
888 for (unsigned int x = 0; x < uWidth; ++x)
889 {
890 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
891 /* If the alpha channel isn't in the shape data, we have to
892 * create them from the and-mask. This is a bit field where 1
893 * represent transparency & 0 opaque respectively. */
894 if (!fHasAlpha)
895 {
896 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
897 color |= 0xff000000;
898 else
899 {
900 /* This isn't quite right, but it's the best we can do I think... */
901 if (color & 0x00ffffff)
902 color = 0xff000000;
903 else
904 color = 0x00000000;
905 }
906 }
907 image.setPixel (x, y, color);
908 }
909 /* Move one scanline forward. */
910 pbSrcMask += cbSrcMaskLine;
911 }
912
913 /* Set the new cursor: */
914 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
915 m_fIsValidPointerShapePresent = true;
916 NOREF(srcShapePtrScan);
917
918#else
919
920# warning "port me"
921
922#endif
923}
924
925void UISession::reinitMenuPool()
926{
927 /* Get uisession machine: */
928 const CMachine &machine = session().GetConsole().GetMachine();
929
930 /* Storage stuff: */
931 {
932 /* Initialize CD/FD menus: */
933 int iDevicesCountCD = 0;
934 int iDevicesCountFD = 0;
935 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
936 for (int i = 0; i < attachments.size(); ++i)
937 {
938 const CMediumAttachment &attachment = attachments[i];
939 if (attachment.GetType() == KDeviceType_DVD)
940 ++iDevicesCountCD;
941 if (attachment.GetType() == KDeviceType_Floppy)
942 ++iDevicesCountFD;
943 }
944 QAction *pOpticalDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices);
945 QAction *pFloppyDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_FloppyDevices);
946 pOpticalDevicesMenu->setData(iDevicesCountCD);
947 pOpticalDevicesMenu->setVisible(iDevicesCountCD);
948 pFloppyDevicesMenu->setData(iDevicesCountFD);
949 pFloppyDevicesMenu->setVisible(iDevicesCountFD);
950 }
951
952 /* VRDE stuff: */
953 {
954 /* Get VRDE server: */
955 CVRDEServer server = machine.GetVRDEServer();
956 bool fIsVRDEServerAvailable = !server.isNull();
957 /* Show/Hide VRDE action depending on VRDE server availability status: */
958 uimachine()->actionsPool()->action(UIActionIndex_Toggle_VRDEServer)->setVisible(fIsVRDEServerAvailable);
959 /* Check/Uncheck VRDE action depending on VRDE server activity status: */
960 if (fIsVRDEServerAvailable)
961 uimachine()->actionsPool()->action(UIActionIndex_Toggle_VRDEServer)->setChecked(server.GetEnabled());
962 }
963
964 /* Network stuff: */
965 {
966 bool fAtLeastOneAdapterActive = false;
967 ULONG uSlots = vboxGlobal().virtualBox().GetSystemProperties().GetNetworkAdapterCount();
968 for (ULONG uSlot = 0; uSlot < uSlots; ++uSlot)
969 {
970 const CNetworkAdapter &adapter = machine.GetNetworkAdapter(uSlot);
971 if (adapter.GetEnabled())
972 {
973 fAtLeastOneAdapterActive = true;
974 break;
975 }
976 }
977 /* Show/Hide Network Adapters action depending on overall adapters activity status: */
978 uimachine()->actionsPool()->action(UIActionIndex_Simple_NetworkAdaptersDialog)->setVisible(fAtLeastOneAdapterActive);
979 }
980
981 /* USB stuff: */
982 {
983 /* Get USB controller: */
984 const CUSBController &usbController = machine.GetUSBController();
985 bool fUSBControllerEnabled = !usbController.isNull() && usbController.GetEnabled() && usbController.GetProxyAvailable();
986 /* Show/Hide USB menu depending on controller availability, activity and USB-proxy presence: */
987 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setVisible(fUSBControllerEnabled);
988 }
989}
990
991void UISession::preparePowerUp()
992{
993#ifdef VBOX_WITH_UPDATE_REQUEST
994 /* Check for updates if necessary: */
995 vboxGlobal().showUpdateDialog(false /* force request? */);
996#endif
997
998 /* Notify user about mouse&keyboard auto-capturing: */
999 if (vboxGlobal().settings().autoCapture())
1000 vboxProblem().remindAboutAutoCapture();
1001
1002 /* Shows first run wizard if necessary: */
1003 const CMachine &machine = session().GetMachine();
1004 /* Check if we are in teleportation waiting mode. In that case no first run
1005 * wizard is necessary. */
1006 KMachineState state = machine.GetState();
1007 if ( isFirstTimeStarted()
1008 && !(( state == KMachineState_PoweredOff
1009 || state == KMachineState_Aborted
1010 || state == KMachineState_Teleported)
1011 && machine.GetTeleporterEnabled()))
1012 {
1013 UIFirstRunWzd wzd(mainMachineWindow(), session().GetMachine());
1014 wzd.exec();
1015 }
1016}
1017
1018#ifdef VBOX_WITH_VIDEOHWACCEL
1019UIFrameBuffer* UISession::frameBuffer(ulong screenId) const
1020{
1021 Assert(screenId < (ulong)m_FrameBufferVector.size());
1022 return m_FrameBufferVector.value((int)screenId, NULL);
1023}
1024
1025int UISession::setFrameBuffer(ulong screenId, UIFrameBuffer* pFrameBuffer)
1026{
1027 Assert(screenId < (ulong)m_FrameBufferVector.size());
1028 if (screenId < (ulong)m_FrameBufferVector.size())
1029 {
1030 m_FrameBufferVector[(int)screenId] = pFrameBuffer;
1031 return VINF_SUCCESS;
1032 }
1033 return VERR_INVALID_PARAMETER;
1034}
1035#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