VirtualBox

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

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

Main: merge IVirtualBox::FindHardDisk, GetHardDisk, FindDVDImage, GetDVDImage, FindFloppyImage and GetFloppyImage into one IVirtualBox::findMedium method

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