VirtualBox

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

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

Release logging.

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