VirtualBox

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

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

FE/Qt4-2D/3D: fix mode switching when both 2D and 3D is enabled

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