VirtualBox

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

Last change on this file since 29518 was 29518, checked in by vboxsync, 15 years ago

Main: onMousePointerShapeChange reworked

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 47.2 KB
Line 
1/* $Id: UISession.cpp 29518 2010-05-17 10:06:22Z 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#ifdef VBOX_WITH_VIDEOHWACCEL
35# include "VBoxFBOverlay.h"
36# include "UIFrameBuffer.h"
37#endif
38
39#ifdef Q_WS_X11
40# include <QX11Info>
41# include <X11/Xlib.h>
42# include <X11/Xutil.h>
43# ifndef VBOX_WITHOUT_XCURSOR
44# include <X11/Xcursor/Xcursor.h>
45# endif
46#endif
47
48#if defined (Q_WS_MAC)
49# include "VBoxUtils.h"
50#endif
51
52/* Guest mouse pointer shape change event: */
53class UIMousePointerShapeChangeEvent : public QEvent
54{
55public:
56
57 UIMousePointerShapeChangeEvent(bool bIsVisible, bool bIsAlpha, uint uXHot, uint uYHot, uint uWidth, uint uHeight, ComSafeArrayIn(BYTE,pShape))
58 : QEvent((QEvent::Type)UIConsoleEventType_MousePointerShapeChange)
59 , m_bIsVisible(bIsVisible), m_bIsAlpha(bIsAlpha), m_uXHot(uXHot), m_uYHot(uYHot), m_uWidth(uWidth), m_uHeight(uHeight)
60 {
61 com::SafeArray <BYTE> aShape(ComSafeArrayInArg (pShape));
62 size_t cbShapeSize = aShape.size();
63 m_shape.resize(cbShapeSize);
64 ::memcpy(m_shape.raw(), aShape.raw(), cbShapeSize);
65 }
66
67 virtual ~UIMousePointerShapeChangeEvent()
68 {
69 }
70
71 bool isVisible() const { return m_bIsVisible; }
72 bool hasAlpha() const { return m_bIsAlpha; }
73 uint xHot() const { return m_uXHot; }
74 uint yHot() const { return m_uYHot; }
75 uint width() const { return m_uWidth; }
76 uint height() const { return m_uHeight; }
77 const uchar *shapeData() const { return m_shape.raw(); }
78
79private:
80
81 bool m_bIsVisible, m_bIsAlpha;
82 uint m_uXHot, m_uYHot, m_uWidth, m_uHeight;
83 com::SafeArray <uint8_t> m_shape;
84};
85
86/* Guest mouse absolute positioning capability change event: */
87class UIMouseCapabilityChangeEvent : public QEvent
88{
89public:
90
91 UIMouseCapabilityChangeEvent(bool bSupportsAbsolute, bool bSupportsRelative, bool bNeedsHostCursor)
92 : QEvent((QEvent::Type)UIConsoleEventType_MouseCapabilityChange)
93 , m_bSupportsAbsolute(bSupportsAbsolute), m_bSupportsRelative(bSupportsRelative), m_bNeedsHostCursor(bNeedsHostCursor) {}
94
95 bool supportsAbsolute() const { return m_bSupportsAbsolute; }
96 bool supportsRelative() const { return m_bSupportsRelative; }
97 bool needsHostCursor() const { return m_bNeedsHostCursor; }
98
99private:
100
101 bool m_bSupportsAbsolute;
102 bool m_bSupportsRelative;
103 bool m_bNeedsHostCursor;
104};
105
106/* Keyboard LEDs change event: */
107class UIKeyboardLedsChangeEvent : public QEvent
108{
109public:
110
111 UIKeyboardLedsChangeEvent(bool bNumLock, bool bCapsLock, bool bScrollLock)
112 : QEvent((QEvent::Type)UIConsoleEventType_KeyboardLedsChange)
113 , m_bNumLock(bNumLock), m_bCapsLock(bCapsLock), m_bScrollLock(bScrollLock) {}
114
115 bool numLock() const { return m_bNumLock; }
116 bool capsLock() const { return m_bCapsLock; }
117 bool scrollLock() const { return m_bScrollLock; }
118
119private:
120
121 bool m_bNumLock;
122 bool m_bCapsLock;
123 bool m_bScrollLock;
124};
125
126/* Machine state change event: */
127class UIStateChangeEvent : public QEvent
128{
129public:
130
131 UIStateChangeEvent(KMachineState machineState)
132 : QEvent((QEvent::Type)UIConsoleEventType_StateChange)
133 , m_machineState(machineState) {}
134
135 KMachineState machineState() const { return m_machineState; }
136
137private:
138
139 KMachineState m_machineState;
140};
141
142/* Guest Additions state change event: */
143class UIAdditionsStateChangeEvent : public QEvent
144{
145public:
146
147 UIAdditionsStateChangeEvent()
148 : QEvent((QEvent::Type)UIConsoleEventType_AdditionsStateChange) {}
149};
150
151/* Network adapter change event: */
152class UINetworkAdapterChangeEvent : public QEvent
153{
154public:
155
156 UINetworkAdapterChangeEvent(const CNetworkAdapter &networkAdapter)
157 : QEvent((QEvent::Type)UIConsoleEventType_NetworkAdapterChange)
158 , m_networkAdapter(networkAdapter) {}
159
160 const CNetworkAdapter& networkAdapter() { return m_networkAdapter; }
161
162private:
163
164 const CNetworkAdapter m_networkAdapter;
165};
166
167/* Serial port change event: */
168/* Not used:
169class UISerialPortChangeEvent : public QEvent
170{
171public:
172
173 UISerialPortChangeEvent(const CSerialPort &serialPort)
174 : QEvent((QEvent::Type)UIConsoleEventType_SerialPortChange)
175 , m_serialPort(serialPort) {}
176
177 const CSerialPort& serialPort() { return m_serialPort; }
178
179private:
180
181 const CSerialPort m_serialPort;
182};
183*/
184
185/* Parallel port change event: */
186/* Not used:
187class UIParallelPortChangeEvent : public QEvent
188{
189public:
190
191 UIParallelPortChangeEvent(const CParallelPort &parallelPort)
192 : QEvent((QEvent::Type)UIConsoleEventType_ParallelPortChange)
193 , m_parallelPort(parallelPort) {}
194
195 const CParallelPort& parallelPort() { return m_parallelPort; }
196
197private:
198
199 const CParallelPort m_parallelPort;
200};
201*/
202
203/* Storage controller change event: */
204/* Not used:
205class UIStorageControllerChangeEvent : public QEvent
206{
207public:
208
209 UIStorageControllerChangeEvent()
210 : QEvent((QEvent::Type)UIConsoleEventType_StorageControllerChange) {}
211};
212*/
213
214/* Storage medium change event: */
215class UIMediumChangeEvent : public QEvent
216{
217public:
218
219 UIMediumChangeEvent(const CMediumAttachment &mediumAttachment)
220 : QEvent((QEvent::Type)UIConsoleEventType_MediumChange)
221 , m_mediumAttachment(mediumAttachment) {}
222 const CMediumAttachment& mediumAttachment() { return m_mediumAttachment; }
223
224private:
225
226 const CMediumAttachment m_mediumAttachment;
227};
228
229/* CPU change event: */
230/* Not used:
231class UICPUChangeEvent : public QEvent
232{
233public:
234
235 UICPUChangeEvent(ulong uCPU, bool bRemove)
236 : QEvent((QEvent::Type)UIConsoleEventType_CPUChange)
237 , m_uCPU(uCPU), m_bRemove(bRemove) {}
238
239 ulong cpu() const { return m_uCPU; }
240 bool remove() const { return m_bRemove; }
241
242private:
243
244 ulong m_uCPU;
245 bool m_bRemove;
246};
247*/
248
249/* VRDP server change event: */
250/* Not used:
251class UIVRDPServerChangeEvent : public QEvent
252{
253public:
254
255 UIVRDPServerChangeEvent()
256 : QEvent((QEvent::Type)UIConsoleEventType_VRDPServerChange) {}
257};
258*/
259
260/* Remote display info change event: */
261/* Not used:
262class UIRemoteDisplayInfoChangeEvent : public QEvent
263{
264public:
265
266 UIRemoteDisplayInfoChangeEvent()
267 : QEvent((QEvent::Type)UIConsoleEventType_RemoteDisplayInfoChange) {}
268};
269*/
270
271/* USB controller change event: */
272class UIUSBControllerChangeEvent : public QEvent
273{
274public:
275
276 UIUSBControllerChangeEvent()
277 : QEvent((QEvent::Type)UIConsoleEventType_USBControllerChange) {}
278};
279
280/* USB device state change event: */
281class UIUSBDeviceUIStateChangeEvent : public QEvent
282{
283public:
284
285 UIUSBDeviceUIStateChangeEvent(const CUSBDevice &device, bool bAttached, const CVirtualBoxErrorInfo &error)
286 : QEvent((QEvent::Type)UIConsoleEventType_USBDeviceStateChange)
287 , m_device(device), m_bAttached(bAttached), m_error(error) {}
288
289 const CUSBDevice& device() const { return m_device; }
290 bool attached() const { return m_bAttached; }
291 const CVirtualBoxErrorInfo& error() const { return m_error; }
292
293private:
294
295 const CUSBDevice m_device;
296 bool m_bAttached;
297 const CVirtualBoxErrorInfo m_error;
298};
299
300/* Shared folder change event: */
301class UISharedFolderChangeEvent : public QEvent
302{
303public:
304
305 UISharedFolderChangeEvent()
306 : QEvent((QEvent::Type)UIConsoleEventType_SharedFolderChange) {}
307};
308
309/* VM Runtime error event: */
310class UIRuntimeErrorEvent : public QEvent
311{
312public:
313
314 UIRuntimeErrorEvent(bool bFatal, const QString &strErrorID, const QString &strMessage)
315 : QEvent((QEvent::Type)UIConsoleEventType_RuntimeError)
316 , m_bFatal(bFatal), m_strErrorID(strErrorID), m_strMessage(strMessage) {}
317
318 bool fatal() const { return m_bFatal; }
319 QString errorID() const { return m_strErrorID; }
320 QString message() const { return m_strMessage; }
321
322private:
323
324 bool m_bFatal;
325 QString m_strErrorID;
326 QString m_strMessage;
327};
328
329/* Can show window event: */
330/* Not used:
331class UICanUIShowWindowEvent : public QEvent
332{
333public:
334
335 UICanUIShowWindowEvent()
336 : QEvent((QEvent::Type)UIConsoleEventType_CanShowWindow) {}
337};
338*/
339
340/* Show window event: */
341#ifdef Q_WS_MAC
342class UIShowWindowEvent : public QEvent
343{
344public:
345
346 UIShowWindowEvent()
347 : QEvent((QEvent::Type)UIConsoleEventType_ShowWindow) {}
348};
349#endif /* Q_WS_MAC */
350
351class UIConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback)
352{
353public:
354
355 UIConsoleCallback(UISession *pEventHandler)
356 : m_pEventHandler(pEventHandler)
357#if defined (Q_WS_WIN)
358 , m_iRefCount(0)
359#endif
360 {
361 }
362
363 virtual ~UIConsoleCallback()
364 {
365 }
366
367 NS_DECL_ISUPPORTS
368
369#if defined (Q_WS_WIN)
370 STDMETHOD_(ULONG, AddRef)()
371 {
372 return ::InterlockedIncrement(&m_iRefCount);
373 }
374 STDMETHOD_(ULONG, Release)()
375 {
376 long iCount = ::InterlockedDecrement(&m_iRefCount);
377 if (iCount == 0)
378 delete this;
379 return iCount;
380 }
381#endif
382
383 VBOX_SCRIPTABLE_DISPATCH_IMPL(IConsoleCallback)
384
385 STDMETHOD(OnMousePointerShapeChange)(BOOL bIsVisible, BOOL bAlpha, ULONG uXHot, ULONG uYHot, ULONG uWidth, ULONG uHeight, ComSafeArrayIn(BYTE,pShape))
386 {
387 QApplication::postEvent(m_pEventHandler, new UIMousePointerShapeChangeEvent(bIsVisible, bAlpha, uXHot, uYHot, uWidth, uHeight, ComSafeArrayInArg(pShape)));
388 return S_OK;
389 }
390
391 STDMETHOD(OnMouseCapabilityChange)(BOOL bSupportsAbsolute, BOOL bSupportsRelative, BOOL bNeedHostCursor)
392 {
393 QApplication::postEvent(m_pEventHandler, new UIMouseCapabilityChangeEvent(bSupportsAbsolute, bSupportsRelative, bNeedHostCursor));
394 return S_OK;
395 }
396
397 STDMETHOD(OnKeyboardLedsChange)(BOOL bNumLock, BOOL bCapsLock, BOOL bScrollLock)
398 {
399 QApplication::postEvent(m_pEventHandler, new UIKeyboardLedsChangeEvent(bNumLock, bCapsLock, bScrollLock));
400 return S_OK;
401 }
402
403 STDMETHOD(OnStateChange)(MachineState_T machineState)
404 {
405 QApplication::postEvent(m_pEventHandler, new UIStateChangeEvent((KMachineState)machineState));
406 return S_OK;
407 }
408
409 STDMETHOD(OnAdditionsStateChange)()
410 {
411 QApplication::postEvent(m_pEventHandler, new UIAdditionsStateChangeEvent);
412 return S_OK;
413 }
414
415 STDMETHOD(OnNetworkAdapterChange)(INetworkAdapter *pNetworkAdapter)
416 {
417 QApplication::postEvent(m_pEventHandler, new UINetworkAdapterChangeEvent(CNetworkAdapter(pNetworkAdapter)));
418 return S_OK;
419 }
420
421 STDMETHOD(OnSerialPortChange)(ISerialPort * /* pSerialPort */)
422 {
423 /* Not used: QApplication::postEvent(m_pEventHandler, new UISerialPortChangeEvent(CSerialPort(pSerialPort))); */
424 return VBOX_E_DONT_CALL_AGAIN;
425 }
426
427 STDMETHOD(OnParallelPortChange)(IParallelPort * /* pParallelPort */)
428 {
429 /* Not used: QApplication::postEvent(m_pEventHandler, new UIParallelPortChangeEvent(CParallelPort(pParallelPort))); */
430 return VBOX_E_DONT_CALL_AGAIN;
431 }
432
433 STDMETHOD(OnStorageControllerChange)()
434 {
435 /* Not used: QApplication::postEvent(m_pEventHandler, new UIStorageControllerChangeEvent); */
436 return VBOX_E_DONT_CALL_AGAIN;
437 }
438
439 STDMETHOD(OnMediumChange)(IMediumAttachment *pMediumAttachment)
440 {
441 QApplication::postEvent(m_pEventHandler, new UIMediumChangeEvent(CMediumAttachment(pMediumAttachment)));
442 return S_OK;
443 }
444
445 STDMETHOD(OnCPUChange)(ULONG /* uCPU */, BOOL /* bRemove */)
446 {
447 /* Not used: QApplication::postEvent(m_pEventHandler, new UICPUChangeEvent(uCPU, bRemove)); */
448 return VBOX_E_DONT_CALL_AGAIN;
449 }
450
451 STDMETHOD(OnVRDPServerChange)()
452 {
453 /* Not used: QApplication::postEvent(m_pEventHandler, new UIVRDPServerChangeEvent); */
454 return VBOX_E_DONT_CALL_AGAIN;
455 }
456
457 STDMETHOD(OnRemoteDisplayInfoChange)()
458 {
459 /* Not used: QApplication::postEvent(m_pEventHandler, new UIRemoteDisplayInfoChangeEvent); */
460 return VBOX_E_DONT_CALL_AGAIN;
461 }
462
463 STDMETHOD(OnUSBControllerChange)()
464 {
465 QApplication::postEvent(m_pEventHandler, new UIUSBControllerChangeEvent);
466 return S_OK;
467 }
468
469 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *pDevice, BOOL bAttached, IVirtualBoxErrorInfo *pError)
470 {
471 QApplication::postEvent(m_pEventHandler, new UIUSBDeviceUIStateChangeEvent(CUSBDevice(pDevice), bAttached, CVirtualBoxErrorInfo(pError)));
472 return S_OK;
473 }
474
475 STDMETHOD(OnSharedFolderChange)(Scope_T scope)
476 {
477 NOREF(scope);
478 QApplication::postEvent(m_pEventHandler, new UISharedFolderChangeEvent);
479 return S_OK;
480 }
481
482 STDMETHOD(OnRuntimeError)(BOOL bFatal, IN_BSTR strId, IN_BSTR strMessage)
483 {
484 QApplication::postEvent(m_pEventHandler, new UIRuntimeErrorEvent(bFatal, QString::fromUtf16(strId), QString::fromUtf16(strMessage)));
485 return S_OK;
486 }
487
488 STDMETHOD(OnCanShowWindow)(BOOL *pbCanShow)
489 {
490 if (!pbCanShow)
491 return E_POINTER;
492
493 *pbCanShow = TRUE;
494 return S_OK;
495 }
496
497 STDMETHOD(OnShowWindow)(ULONG64 *puWinId)
498 {
499 if (!puWinId)
500 return E_POINTER;
501
502#ifdef Q_WS_MAC
503 /* Let's try the simple approach first - grab the focus.
504 * Getting a window out of the dock (minimized or whatever it's called)
505 * needs to be done on the GUI thread, so post it a note: */
506 *puWinId = 0;
507 if (!m_pEventHandler)
508 return S_OK;
509
510 if (::darwinSetFrontMostProcess())
511 QApplication::postEvent(m_pEventHandler, new UIShowWindowEvent);
512 else
513 {
514 /* It failed for some reason, send the other process our PSN so it can try.
515 * (This is just a precaution should Mac OS X start imposing the same sensible
516 * focus stealing restrictions that other window managers implement). */
517 *puWinId = ::darwinGetCurrentProcessId();
518 }
519#else /* Q_WS_MAC */
520 /* Return the ID of the top-level console window. */
521 *puWinId = (ULONG64)m_pEventHandler->winId();
522#endif /* !Q_WS_MAC */
523
524 return S_OK;
525 }
526
527private:
528
529 UISession *m_pEventHandler;
530
531#if defined (Q_WS_WIN)
532 long m_iRefCount;
533#endif
534};
535
536#if !defined (Q_WS_WIN)
537NS_DECL_CLASSINFO(UIConsoleCallback)
538NS_IMPL_THREADSAFE_ISUPPORTS1_CI(UIConsoleCallback, IConsoleCallback)
539#endif
540
541UISession::UISession(UIMachine *pMachine, CSession &sessionReference)
542 : QObject(pMachine)
543 /* Base variables: */
544 , m_pMachine(pMachine)
545 , m_session(sessionReference)
546 , m_callback(CConsoleCallback(new UIConsoleCallback(this)))
547 /* Common variables: */
548 , m_pMenuPool(0)
549#ifdef VBOX_WITH_VIDEOHWACCEL
550 , m_FrameBufferVector(sessionReference.GetMachine().GetMonitorCount())
551#endif
552 , m_machineState(KMachineState_Null)
553#if defined(Q_WS_WIN)
554 , m_alphaCursor(0)
555#endif
556 /* Common flags: */
557 , m_fIsFirstTimeStarted(false)
558 , m_fIsIgnoreRuntimeMediumsChanging(false)
559 , m_fIsGuestResizeIgnored(false)
560 , m_fIsSeamlessModeRequested(false)
561 /* Guest additions flags: */
562 , m_fIsGuestAdditionsActive(false)
563 , m_fIsGuestSupportsGraphics(false)
564 , m_fIsGuestSupportsSeamless(false)
565 /* Mouse flags: */
566 , m_fNumLock(false)
567 , m_fCapsLock(false)
568 , m_fScrollLock(false)
569 , m_uNumLockAdaptionCnt(2)
570 , m_uCapsLockAdaptionCnt(2)
571 /* Mouse flags: */
572 , m_fIsMouseSupportsAbsolute(false)
573 , m_fIsMouseSupportsRelative(false)
574 , m_fIsMouseHostCursorNeeded(false)
575 , m_fIsMouseCaptured(false)
576 , m_fIsMouseIntegrated(true)
577 , m_fIsValidPointerShapePresent(false)
578 , m_fIsHidingHostPointer(true)
579{
580 /* Register console callback: */
581 session().GetConsole().RegisterCallback(m_callback);
582
583 /* Prepare main menu: */
584 prepareMenuPool();
585
586 /* Load uisession settings: */
587 loadSessionSettings();
588}
589
590UISession::~UISession()
591{
592 /* Save uisession settings: */
593 saveSessionSettings();
594
595 /* Cleanup main menu: */
596 cleanupMenuPool();
597
598 /* Unregister console callback: */
599 session().GetConsole().UnregisterCallback(m_callback);
600
601#if defined(Q_WS_WIN)
602 /* Destroy alpha cursor: */
603 if (m_alphaCursor)
604 DestroyIcon(m_alphaCursor);
605#endif
606
607#ifdef VBOX_WITH_VIDEOHWACCEL
608 for (int i = m_FrameBufferVector.size() - 1; i >= 0; --i)
609 {
610 UIFrameBuffer *pFb = m_FrameBufferVector[i];
611 if (pFb)
612 {
613 /* Warn framebuffer about its no more necessary: */
614 pFb->setDeleted(true);
615 /* Detach framebuffer from Display: */
616 CDisplay display = session().GetConsole().GetDisplay();
617 display.SetFramebuffer(i, CFramebuffer(NULL));
618 /* Release the reference: */
619 pFb->Release();
620 }
621 }
622#endif
623}
624
625void UISession::powerUp()
626{
627 /* Do nothing if we had started already: */
628 if (isRunning() || isPaused())
629 return;
630
631 /* Prepare powerup: */
632 preparePowerUp();
633
634 /* Get current machine/console: */
635 CMachine machine = session().GetMachine();
636 CConsole console = session().GetConsole();
637
638 /* Power UP machine: */
639 CProgress progress = vboxGlobal().isStartPausedEnabled() || vboxGlobal().isDebuggerAutoShowEnabled() ?
640 console.PowerUpPaused() : console.PowerUp();
641
642 /* Check for immediate failure: */
643 if (!console.isOk())
644 {
645 if (vboxGlobal().showStartVMErrors())
646 vboxProblem().cannotStartMachine(console);
647 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
648 return;
649 }
650
651 /* Guard progressbar warnings from auto-closing: */
652 if (uimachine()->machineLogic())
653 uimachine()->machineLogic()->setPreventAutoClose(true);
654
655 /* Show "Starting/Restoring" progress dialog: */
656 if (isSaved())
657 vboxProblem().showModalProgressDialog(progress, machine.GetName(), mainMachineWindow(), 0);
658 else
659 vboxProblem().showModalProgressDialog(progress, machine.GetName(), mainMachineWindow());
660
661 /* Allow further auto-closing: */
662 if (uimachine()->machineLogic())
663 uimachine()->machineLogic()->setPreventAutoClose(false);
664
665 /* Check for a progress failure: */
666 if (progress.GetResultCode() != 0)
667 {
668 if (vboxGlobal().showStartVMErrors())
669 vboxProblem().cannotStartMachine(progress);
670 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
671 return;
672 }
673
674 /* Check if we missed a really quick termination after successful startup, and process it if we did: */
675 if (isTurnedOff())
676 {
677 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
678 return;
679 }
680
681 /* Check if the required virtualization features are active. We get this
682 * info only when the session is active. */
683 bool fIs64BitsGuest = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetIs64Bit();
684 bool fRecommendVirtEx = vboxGlobal().virtualBox().GetGuestOSType(console.GetGuest().GetOSTypeId()).GetRecommendedVirtEx();
685 AssertMsg(!fIs64BitsGuest || fRecommendVirtEx, ("Virtualization support missed for 64bit guest!\n"));
686 bool fIsVirtEnabled = console.GetDebugger().GetHWVirtExEnabled();
687 if (fRecommendVirtEx && !fIsVirtEnabled)
688 {
689 bool fShouldWeClose;
690
691 bool fVTxAMDVSupported = vboxGlobal().virtualBox().GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx);
692
693 QApplication::processEvents();
694 setPause(true);
695
696 if (fIs64BitsGuest)
697 fShouldWeClose = vboxProblem().warnAboutVirtNotEnabled64BitsGuest(fVTxAMDVSupported);
698 else
699 fShouldWeClose = vboxProblem().warnAboutVirtNotEnabledGuestRequired(fVTxAMDVSupported);
700
701 if (fShouldWeClose)
702 {
703 /* At this point the console is powered up. So we have to close
704 * this session again. */
705 CProgress progress = console.PowerDown();
706 if (console.isOk())
707 {
708 /* Guard progressbar warnings from auto-closing: */
709 if (uimachine()->machineLogic())
710 uimachine()->machineLogic()->setPreventAutoClose(true);
711 /* Show the power down progress dialog */
712 vboxProblem().showModalProgressDialog(progress, machine.GetName(), mainMachineWindow());
713 if (progress.GetResultCode() != 0)
714 vboxProblem().cannotStopMachine(progress);
715 /* Allow further auto-closing: */
716 if (uimachine()->machineLogic())
717 uimachine()->machineLogic()->setPreventAutoClose(false);
718 }
719 else
720 vboxProblem().cannotStopMachine(console);
721 /* Now signal the destruction of the rest. */
722 QTimer::singleShot(0, this, SLOT(sltCloseVirtualSession()));
723 return;
724 }
725 else
726 setPause(false);
727 }
728
729#if 0 // TODO: Rework debugger logic!
730# ifdef VBOX_WITH_DEBUGGER_GUI
731 /* Open the debugger in "full screen" mode requested by the user. */
732 else if (vboxGlobal().isDebuggerAutoShowEnabled())
733 {
734 /* console in upper left corner of the desktop. */
735 QRect rct (0, 0, 0, 0);
736 QDesktopWidget *desktop = QApplication::desktop();
737 if (desktop)
738 rct = desktop->availableGeometry(pos());
739 move (QPoint (rct.x(), rct.y()));
740
741 if (vboxGlobal().isDebuggerAutoShowStatisticsEnabled())
742 sltShowDebugStatistics();
743 if (vboxGlobal().isDebuggerAutoShowCommandLineEnabled())
744 sltShowDebugCommandLine();
745
746 if (!vboxGlobal().isStartPausedEnabled())
747 machineWindowWrapper()->machineView()->pause (false);
748 }
749# endif
750#endif
751
752 /* Warn listeners about machine was started: */
753 emit sigMachineStarted();
754}
755
756UIActionsPool* UISession::actionsPool() const
757{
758 return m_pMachine->actionsPool();
759}
760
761QWidget* UISession::mainMachineWindow() const
762{
763 return uimachine()->machineLogic()->mainMachineWindow()->machineWindow();
764}
765
766UIMachineLogic* UISession::machineLogic() const
767{
768 return uimachine()->machineLogic();
769}
770
771QMenu* UISession::newMenu(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
772{
773 /* Create new menu: */
774 QMenu *pMenu = m_pMenuPool->createMenu(actionsPool(), fOptions);
775
776 /* Re-init menu pool for the case menu were recreated: */
777 reinitMenuPool();
778
779 /* Return newly created menu: */
780 return pMenu;
781}
782
783QMenuBar* UISession::newMenuBar(UIMainMenuType fOptions /* = UIMainMenuType_ALL */)
784{
785 /* Create new menubar: */
786 QMenuBar *pMenuBar = m_pMenuPool->createMenuBar(actionsPool(), fOptions);
787
788 /* Re-init menu pool for the case menu were recreated: */
789 reinitMenuPool();
790
791 /* Return newly created menubar: */
792 return pMenuBar;
793}
794
795bool UISession::setPause(bool fOn)
796{
797 /* Commenting it out as isPaused() could reflect
798 * quite obsolete state due to synchronization: */
799 //if (isPaused() == fOn)
800 // return true;
801
802 CConsole console = session().GetConsole();
803
804 if (fOn)
805 console.Pause();
806 else
807 console.Resume();
808
809 bool ok = console.isOk();
810 if (!ok)
811 {
812 if (fOn)
813 vboxProblem().cannotPauseMachine(console);
814 else
815 vboxProblem().cannotResumeMachine(console);
816 }
817
818 return ok;
819}
820
821void UISession::sltInstallGuestAdditionsFrom(const QString &strSource)
822{
823 CMachine machine = session().GetMachine();
824 CVirtualBox vbox = vboxGlobal().virtualBox();
825 QString strUuid;
826
827 CMedium image = vbox.FindDVDImage(strSource);
828 if (image.isNull())
829 {
830 image = vbox.OpenDVDImage(strSource, strUuid);
831 if (vbox.isOk())
832 strUuid = image.GetId();
833 }
834 else
835 strUuid = image.GetId();
836
837 if (!vbox.isOk())
838 {
839 vboxProblem().cannotOpenMedium(0, vbox, VBoxDefs::MediumType_DVD, strSource);
840 return;
841 }
842
843 AssertMsg(!strUuid.isNull(), ("Guest Additions image UUID should be valid!\n"));
844
845 QString strCntName;
846 LONG iCntPort = -1, iCntDevice = -1;
847 /* Searching for the first suitable slot */
848 {
849 CStorageControllerVector controllers = machine.GetStorageControllers();
850 int i = 0;
851 while (i < controllers.size() && strCntName.isNull())
852 {
853 CStorageController controller = controllers[i];
854 CMediumAttachmentVector attachments = machine.GetMediumAttachmentsOfController(controller.GetName());
855 int j = 0;
856 while (j < attachments.size() && strCntName.isNull())
857 {
858 CMediumAttachment attachment = attachments[j];
859 if (attachment.GetType() == KDeviceType_DVD)
860 {
861 strCntName = controller.GetName();
862 iCntPort = attachment.GetPort();
863 iCntDevice = attachment.GetDevice();
864 }
865 ++ j;
866 }
867 ++ i;
868 }
869 }
870
871 if (!strCntName.isNull())
872 {
873 bool fIsMounted = false;
874
875 /* Mount medium to the predefined port/device */
876 machine.MountMedium(strCntName, iCntPort, iCntDevice, strUuid, false /* force */);
877 if (machine.isOk())
878 fIsMounted = true;
879 else
880 {
881 /* Ask for force mounting */
882 if (vboxProblem().cannotRemountMedium(0, machine, VBoxMedium(image, VBoxDefs::MediumType_DVD),
883 true /* mount? */, true /* retry? */) == QIMessageBox::Ok)
884 {
885 /* Force mount medium to the predefined port/device */
886 machine.MountMedium(strCntName, iCntPort, iCntDevice, strUuid, true /* force */);
887 if (machine.isOk())
888 fIsMounted = true;
889 else
890 vboxProblem().cannotRemountMedium(0, machine, VBoxMedium(image, VBoxDefs::MediumType_DVD),
891 true /* mount? */, false /* retry? */);
892 }
893 }
894 }
895 else
896 vboxProblem().cannotMountGuestAdditions(machine.GetName());
897}
898
899void UISession::sltCloseVirtualSession()
900{
901 m_pMachine->closeVirtualMachine();
902}
903
904bool UISession::event(QEvent *pEvent)
905{
906 switch (pEvent->type())
907 {
908 case UIConsoleEventType_MousePointerShapeChange:
909 {
910 /* Convert to mouse shape change event: */
911 UIMousePointerShapeChangeEvent *pConsoleEvent = static_cast<UIMousePointerShapeChangeEvent*>(pEvent);
912
913 /* In case of shape data is present: */
914 if (pConsoleEvent->shapeData())
915 {
916 /* We are ignoring visibility flag: */
917 m_fIsHidingHostPointer = false;
918
919 /* And updating current cursor shape: */
920 setPointerShape(pConsoleEvent->shapeData(), pConsoleEvent->hasAlpha(),
921 pConsoleEvent->xHot(), pConsoleEvent->yHot(),
922 pConsoleEvent->width(), pConsoleEvent->height());
923 }
924 /* In case of shape data is NOT present: */
925 else
926 {
927 /* Remember if we should hide the cursor: */
928 m_fIsHidingHostPointer = !pConsoleEvent->isVisible();
929 }
930
931 /* Notify listeners about mouse capability changed: */
932 emit sigMousePointerShapeChange();
933
934 /* Accept event: */
935 pEvent->accept();
936 return true;
937 }
938
939 case UIConsoleEventType_MouseCapabilityChange:
940 {
941 /* Convert to mouse capability event: */
942 UIMouseCapabilityChangeEvent *pConsoleEvent = static_cast<UIMouseCapabilityChangeEvent*>(pEvent);
943
944 /* Check if something had changed: */
945 if (m_fIsMouseSupportsAbsolute != pConsoleEvent->supportsAbsolute() ||
946 m_fIsMouseSupportsRelative != pConsoleEvent->supportsRelative() ||
947 m_fIsMouseHostCursorNeeded != pConsoleEvent->needsHostCursor())
948 {
949 /* Store new data: */
950 m_fIsMouseSupportsAbsolute = pConsoleEvent->supportsAbsolute();
951 m_fIsMouseSupportsRelative = pConsoleEvent->supportsRelative();
952 m_fIsMouseHostCursorNeeded = pConsoleEvent->needsHostCursor();
953
954 /* Notify listeners about mouse capability changed: */
955 emit sigMouseCapabilityChange();
956 }
957
958 /* Accept event: */
959 pEvent->accept();
960 return true;
961 }
962
963 case UIConsoleEventType_KeyboardLedsChange:
964 {
965 /* Convert to keyboard LEDs change event: */
966 UIKeyboardLedsChangeEvent *pConsoleEvent = static_cast<UIKeyboardLedsChangeEvent*>(pEvent);
967
968 /* Check if something had changed: */
969 if (m_fNumLock != pConsoleEvent->numLock() ||
970 m_fCapsLock != pConsoleEvent->capsLock() ||
971 m_fScrollLock != pConsoleEvent->scrollLock())
972 {
973 /* Store new num lock data: */
974 if (m_fNumLock != pConsoleEvent->numLock())
975 {
976 m_fNumLock = pConsoleEvent->numLock();
977 m_uNumLockAdaptionCnt = 2;
978 }
979
980 /* Store new caps lock data: */
981 if (m_fCapsLock != pConsoleEvent->capsLock())
982 {
983 m_fCapsLock = pConsoleEvent->capsLock();
984 m_uCapsLockAdaptionCnt = 2;
985 }
986
987 /* Store new scroll lock data: */
988 if (m_fScrollLock != pConsoleEvent->scrollLock())
989 {
990 m_fScrollLock = pConsoleEvent->scrollLock();
991 }
992
993 /* Notify listeners about mouse capability changed: */
994 emit sigKeyboardLedsChange();
995 }
996
997 /* Accept event: */
998 pEvent->accept();
999 return true;
1000 }
1001
1002 case UIConsoleEventType_StateChange:
1003 {
1004 /* Convert to machine state event: */
1005 UIStateChangeEvent *pConsoleEvent = static_cast<UIStateChangeEvent*>(pEvent);
1006
1007 /* Check if something had changed: */
1008 if (m_machineState != pConsoleEvent->machineState())
1009 {
1010 /* Store new data: */
1011 m_machineState = pConsoleEvent->machineState();
1012
1013 /* Notify listeners about machine state changed: */
1014 emit sigMachineStateChange();
1015 }
1016
1017 /* Accept event: */
1018 pEvent->accept();
1019 return true;
1020 }
1021
1022 case UIConsoleEventType_AdditionsStateChange:
1023 {
1024 /* Get our guest: */
1025 CGuest guest = session().GetConsole().GetGuest();
1026
1027 /* Variable flags: */
1028 bool fIsGuestAdditionsActive = guest.GetAdditionsActive();
1029 bool fIsGuestSupportsGraphics = guest.GetSupportsGraphics();
1030 bool fIsGuestSupportsSeamless = guest.GetSupportsSeamless();
1031
1032 /* Check if something had changed: */
1033 if (m_fIsGuestAdditionsActive != fIsGuestAdditionsActive ||
1034 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
1035 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
1036 {
1037 /* Store new data: */
1038 m_fIsGuestAdditionsActive = fIsGuestAdditionsActive;
1039 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
1040 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
1041
1042 /* Notify listeners about guest additions state changed: */
1043 emit sigAdditionsStateChange();
1044 }
1045
1046 /* Accept event: */
1047 pEvent->accept();
1048 return true;
1049 }
1050
1051 case UIConsoleEventType_NetworkAdapterChange:
1052 {
1053 UINetworkAdapterChangeEvent *pConsoleEvent = static_cast<UINetworkAdapterChangeEvent*>(pEvent);
1054 emit sigNetworkAdapterChange(pConsoleEvent->networkAdapter());
1055 return true;
1056 }
1057
1058 /* Not used:
1059 case UIConsoleEventType_SerialPortChange:
1060 {
1061 UISerialPortChangeEvent *pConsoleEvent = static_cast<UISerialPortChangeEvent*>(pEvent);
1062 emit sigSerialPortChange(pConsoleEvent->serialPort());
1063 return true;
1064 }
1065 */
1066
1067 /* Not used:
1068 case UIConsoleEventType_ParallelPortChange:
1069 {
1070 UIParallelPortChangeEvent *pConsoleEvent = static_cast<UIParallelPortChangeEvent*>(pEvent);
1071 emit sigParallelPortChange(pConsoleEvent->parallelPort());
1072 return true;
1073 }
1074 */
1075
1076 /* Not used:
1077 case UIConsoleEventType_StorageControllerChange:
1078 {
1079 emit sigStorageControllerChange();
1080 return true;
1081 }
1082 */
1083
1084 case UIConsoleEventType_MediumChange:
1085 {
1086 UIMediumChangeEvent *pConsoleEvent = static_cast<UIMediumChangeEvent*>(pEvent);
1087 emit sigMediumChange(pConsoleEvent->mediumAttachment());
1088 return true;
1089 }
1090
1091 /* Not used:
1092 case UIConsoleEventType_CPUChange:
1093 {
1094 UICPUChangeEvent *pConsoleEvent = static_cast<UICPUChangeEvent*>(pEvent);
1095 emit sigCPUChange(pConsoleEvent->cpu(), pConsoleEvent->remove());
1096 return true;
1097 }
1098 */
1099
1100 /* Not used:
1101 case UIConsoleEventType_VRDPServerChange:
1102 {
1103 emit sigVRDPServerChange();
1104 return true;
1105 }
1106 */
1107
1108 /* Not used:
1109 case UIConsoleEventType_RemoteDisplayInfoChange:
1110 {
1111 emit sigRemoteDisplayInfoChange();
1112 return true;
1113 }
1114 */
1115
1116 case UIConsoleEventType_USBControllerChange:
1117 {
1118 emit sigUSBControllerChange();
1119 return true;
1120 }
1121
1122 case UIConsoleEventType_USBDeviceStateChange:
1123 {
1124 UIUSBDeviceUIStateChangeEvent *pConsoleEvent = static_cast<UIUSBDeviceUIStateChangeEvent*>(pEvent);
1125 emit sigUSBDeviceStateChange(pConsoleEvent->device(), pConsoleEvent->attached(), pConsoleEvent->error());
1126 return true;
1127 }
1128
1129 case UIConsoleEventType_SharedFolderChange:
1130 {
1131 emit sigSharedFolderChange();
1132 return true;
1133 }
1134
1135 case UIConsoleEventType_RuntimeError:
1136 {
1137 UIRuntimeErrorEvent *pConsoleEvent = static_cast<UIRuntimeErrorEvent*>(pEvent);
1138 emit sigRuntimeError(pConsoleEvent->fatal(), pConsoleEvent->errorID(), pConsoleEvent->message());
1139 return true;
1140 }
1141
1142#ifdef Q_WS_MAC
1143 case UIConsoleEventType_ShowWindow:
1144 {
1145 emit sigShowWindows();
1146 /* Accept event: */
1147 pEvent->accept();
1148 return true;
1149 }
1150#endif
1151
1152 default:
1153 break;
1154 }
1155 return QObject::event(pEvent);
1156}
1157
1158void UISession::prepareMenuPool()
1159{
1160 m_pMenuPool = new UIMachineMenuBar;
1161}
1162
1163void UISession::loadSessionSettings()
1164{
1165 /* Get uisession machine: */
1166 CMachine machine = session().GetConsole().GetMachine();
1167
1168 /* Availability settings: */
1169 {
1170 /* VRDP Stuff: */
1171 CVRDPServer vrdpServer = machine.GetVRDPServer();
1172 if (vrdpServer.isNull())
1173 {
1174 /* Hide VRDP Action: */
1175 uimachine()->actionsPool()->action(UIActionIndex_Toggle_VRDP)->setVisible(false);
1176 }
1177 }
1178
1179 /* Load extra-data settings: */
1180 {
1181 /* Temporary: */
1182 QString strSettings;
1183
1184 /* Is there shoul be First RUN Wizard? */
1185 strSettings = machine.GetExtraData(VBoxDefs::GUI_FirstRun);
1186 if (strSettings == "yes")
1187 m_fIsFirstTimeStarted = true;
1188
1189 /* Ignore mediums mounted at runtime? */
1190 strSettings = machine.GetExtraData(VBoxDefs::GUI_SaveMountedAtRuntime);
1191 if (strSettings == "no")
1192 m_fIsIgnoreRuntimeMediumsChanging = true;
1193
1194 /* Should guest autoresize? */
1195 strSettings = machine.GetExtraData(VBoxDefs::GUI_AutoresizeGuest);
1196 QAction *pGuestAutoresizeSwitch = uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize);
1197 pGuestAutoresizeSwitch->blockSignals(true);
1198 pGuestAutoresizeSwitch->setChecked(strSettings != "off");
1199 pGuestAutoresizeSwitch->blockSignals(false);
1200 }
1201}
1202
1203void UISession::saveSessionSettings()
1204{
1205 /* Get uisession machine: */
1206 CMachine machine = session().GetConsole().GetMachine();
1207
1208 /* Save extra-data settings: */
1209 {
1210 /* Disable First RUN Wizard for the since now: */
1211 machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString());
1212
1213 /* Remember if guest should autoresize: */
1214 machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest,
1215 uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->isChecked() ?
1216 QString() : "off");
1217
1218 // TODO: Move to fullscreen/seamless logic:
1219 //machine.SetExtraData(VBoxDefs::GUI_MiniToolBarAutoHide, mMiniToolBar->isAutoHide() ? "on" : "off");
1220 }
1221}
1222
1223void UISession::cleanupMenuPool()
1224{
1225 delete m_pMenuPool;
1226 m_pMenuPool = 0;
1227}
1228
1229WId UISession::winId() const
1230{
1231 return mainMachineWindow()->winId();
1232}
1233
1234void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
1235 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
1236{
1237 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
1238
1239 m_fIsValidPointerShapePresent = false;
1240 const uchar *srcAndMaskPtr = pShapeData;
1241 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
1242 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
1243 uint srcShapePtrScan = uWidth * 4;
1244
1245#if defined (Q_WS_WIN)
1246
1247 BITMAPV5HEADER bi;
1248 HBITMAP hBitmap;
1249 void *lpBits;
1250
1251 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
1252 bi.bV5Size = sizeof(BITMAPV5HEADER);
1253 bi.bV5Width = uWidth;
1254 bi.bV5Height = - (LONG)uHeight;
1255 bi.bV5Planes = 1;
1256 bi.bV5BitCount = 32;
1257 bi.bV5Compression = BI_BITFIELDS;
1258 bi.bV5RedMask = 0x00FF0000;
1259 bi.bV5GreenMask = 0x0000FF00;
1260 bi.bV5BlueMask = 0x000000FF;
1261 if (fHasAlpha)
1262 bi.bV5AlphaMask = 0xFF000000;
1263 else
1264 bi.bV5AlphaMask = 0;
1265
1266 HDC hdc = GetDC(NULL);
1267
1268 /* Create the DIB section with an alpha channel: */
1269 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
1270
1271 ReleaseDC(NULL, hdc);
1272
1273 HBITMAP hMonoBitmap = NULL;
1274 if (fHasAlpha)
1275 {
1276 /* Create an empty mask bitmap: */
1277 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
1278 }
1279 else
1280 {
1281 /* Word aligned AND mask. Will be allocated and created if necessary. */
1282 uint8_t *pu8AndMaskWordAligned = NULL;
1283
1284 /* Width in bytes of the original AND mask scan line. */
1285 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
1286
1287 if (cbAndMaskScan & 1)
1288 {
1289 /* Original AND mask is not word aligned. */
1290
1291 /* Allocate memory for aligned AND mask. */
1292 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
1293
1294 Assert(pu8AndMaskWordAligned);
1295
1296 if (pu8AndMaskWordAligned)
1297 {
1298 /* According to MSDN the padding bits must be 0.
1299 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
1300 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
1301 Assert(u32PaddingBits < 8);
1302 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
1303
1304 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
1305 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
1306
1307 uint8_t *src = (uint8_t *)srcAndMaskPtr;
1308 uint8_t *dst = pu8AndMaskWordAligned;
1309
1310 unsigned i;
1311 for (i = 0; i < uHeight; i++)
1312 {
1313 memcpy(dst, src, cbAndMaskScan);
1314
1315 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
1316
1317 src += cbAndMaskScan;
1318 dst += cbAndMaskScan + 1;
1319 }
1320 }
1321 }
1322
1323 /* Create the AND mask bitmap: */
1324 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
1325 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
1326
1327 if (pu8AndMaskWordAligned)
1328 {
1329 RTMemTmpFree(pu8AndMaskWordAligned);
1330 }
1331 }
1332
1333 Assert(hBitmap);
1334 Assert(hMonoBitmap);
1335 if (hBitmap && hMonoBitmap)
1336 {
1337 DWORD *dstShapePtr = (DWORD *) lpBits;
1338
1339 for (uint y = 0; y < uHeight; y ++)
1340 {
1341 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
1342 srcShapePtr += srcShapePtrScan;
1343 dstShapePtr += uWidth;
1344 }
1345
1346 ICONINFO ii;
1347 ii.fIcon = FALSE;
1348 ii.xHotspot = uXHot;
1349 ii.yHotspot = uYHot;
1350 ii.hbmMask = hMonoBitmap;
1351 ii.hbmColor = hBitmap;
1352
1353 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
1354 Assert(hAlphaCursor);
1355 if (hAlphaCursor)
1356 {
1357 /* Set the new cursor: */
1358 m_cursor = QCursor(hAlphaCursor);
1359 if (m_alphaCursor)
1360 DestroyIcon(m_alphaCursor);
1361 m_alphaCursor = hAlphaCursor;
1362 m_fIsValidPointerShapePresent = true;
1363 }
1364 }
1365
1366 if (hMonoBitmap)
1367 DeleteObject(hMonoBitmap);
1368 if (hBitmap)
1369 DeleteObject(hBitmap);
1370
1371#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
1372
1373 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
1374 Assert(img);
1375 if (img)
1376 {
1377 img->xhot = uXHot;
1378 img->yhot = uYHot;
1379
1380 XcursorPixel *dstShapePtr = img->pixels;
1381
1382 for (uint y = 0; y < uHeight; y ++)
1383 {
1384 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
1385
1386 if (!fHasAlpha)
1387 {
1388 /* Convert AND mask to the alpha channel: */
1389 uchar byte = 0;
1390 for (uint x = 0; x < uWidth; x ++)
1391 {
1392 if (!(x % 8))
1393 byte = *(srcAndMaskPtr ++);
1394 else
1395 byte <<= 1;
1396
1397 if (byte & 0x80)
1398 {
1399 /* Linux doesn't support inverted pixels (XOR ops,
1400 * to be exact) in cursor shapes, so we detect such
1401 * pixels and always replace them with black ones to
1402 * make them visible at least over light colors */
1403 if (dstShapePtr [x] & 0x00FFFFFF)
1404 dstShapePtr [x] = 0xFF000000;
1405 else
1406 dstShapePtr [x] = 0x00000000;
1407 }
1408 else
1409 dstShapePtr [x] |= 0xFF000000;
1410 }
1411 }
1412
1413 srcShapePtr += srcShapePtrScan;
1414 dstShapePtr += uWidth;
1415 }
1416
1417 /* Set the new cursor: */
1418 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
1419 m_fIsValidPointerShapePresent = true;
1420
1421 XcursorImageDestroy(img);
1422 }
1423
1424#elif defined(Q_WS_MAC)
1425
1426 /* Create a ARGB image out of the shape data. */
1427 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
1428 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
1429 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
1430 for (unsigned int y = 0; y < uHeight; ++y)
1431 {
1432 for (unsigned int x = 0; x < uWidth; ++x)
1433 {
1434 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
1435 /* If the alpha channel isn't in the shape data, we have to
1436 * create them from the and-mask. This is a bit field where 1
1437 * represent transparency & 0 opaque respectively. */
1438 if (!fHasAlpha)
1439 {
1440 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
1441 color |= 0xff000000;
1442 else
1443 {
1444 /* This isn't quite right, but it's the best we can do I think... */
1445 if (color & 0x00ffffff)
1446 color = 0xff000000;
1447 else
1448 color = 0x00000000;
1449 }
1450 }
1451 image.setPixel (x, y, color);
1452 }
1453 /* Move one scanline forward. */
1454 pbSrcMask += cbSrcMaskLine;
1455 }
1456
1457 /* Set the new cursor: */
1458 m_cursor = QCursor(QPixmap::fromImage(image), uXHot, uYHot);
1459 m_fIsValidPointerShapePresent = true;
1460 NOREF(srcShapePtrScan);
1461
1462#else
1463
1464# warning "port me"
1465
1466#endif
1467}
1468
1469void UISession::reinitMenuPool()
1470{
1471 /* Get uisession machine: */
1472 const CMachine &machine = session().GetConsole().GetMachine();
1473
1474 /* Availability settings: */
1475 {
1476 /* USB Stuff: */
1477 const CUSBController &usbController = machine.GetUSBController();
1478 if ( usbController.isNull()
1479 || !usbController.GetEnabled()
1480 || !usbController.GetProxyAvailable())
1481 {
1482 /* Hide USB menu if controller is NULL or no USB proxy available: */
1483 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setVisible(false);
1484 }
1485 else
1486 {
1487 /* Enable/Disable USB menu depending on USB controller: */
1488 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setEnabled(usbController.GetEnabled());
1489 }
1490 }
1491
1492 /* Prepare some initial settings: */
1493 {
1494 /* Initialize CD/FD menus: */
1495 int iDevicesCountCD = 0;
1496 int iDevicesCountFD = 0;
1497 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
1498 foreach (const CMediumAttachment &attachment, attachments)
1499 {
1500 if (attachment.GetType() == KDeviceType_DVD)
1501 ++ iDevicesCountCD;
1502 if (attachment.GetType() == KDeviceType_Floppy)
1503 ++ iDevicesCountFD;
1504 }
1505 QAction *pOpticalDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices);
1506 QAction *pFloppyDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_FloppyDevices);
1507 pOpticalDevicesMenu->setData(iDevicesCountCD);
1508 pOpticalDevicesMenu->setVisible(iDevicesCountCD);
1509 pFloppyDevicesMenu->setData(iDevicesCountFD);
1510 pFloppyDevicesMenu->setVisible(iDevicesCountFD);
1511 }
1512}
1513
1514void UISession::preparePowerUp()
1515{
1516#ifdef VBOX_WITH_UPDATE_REQUEST
1517 /* Check for updates if necessary: */
1518 vboxGlobal().showUpdateDialog(false /* force request? */);
1519#endif
1520
1521 /* Notify user about mouse&keyboard auto-capturing: */
1522 if (vboxGlobal().settings().autoCapture())
1523 vboxProblem().remindAboutAutoCapture();
1524
1525 /* Shows first run wizard if necessary: */
1526 if (isFirstTimeStarted())
1527 {
1528 UIFirstRunWzd wzd(mainMachineWindow(), session().GetMachine());
1529 wzd.exec();
1530 }
1531}
1532
1533#ifdef VBOX_WITH_VIDEOHWACCEL
1534UIFrameBuffer* UISession::frameBuffer(ulong screenId) const
1535{
1536 Assert(screenId < (ulong)m_FrameBufferVector.size());
1537 return m_FrameBufferVector.value((int)screenId, NULL);
1538}
1539
1540int UISession::setFrameBuffer(ulong screenId, UIFrameBuffer* pFrameBuffer)
1541{
1542 Assert(screenId < (ulong)m_FrameBufferVector.size());
1543 if (screenId < (ulong)m_FrameBufferVector.size())
1544 {
1545 m_FrameBufferVector[(int)screenId] = pFrameBuffer;
1546 return VINF_SUCCESS;
1547 }
1548 return VERR_INVALID_PARAMETER;
1549}
1550#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