VirtualBox

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

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

FE/Qt4: New running VM core: fixing issue with pausing VM.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.6 KB
Line 
1/* $Id: UISession.cpp 26816 2010-02-26 03:21:17Z vboxsync $ */
2/** @file
3 *
4 * VBox frontends: Qt GUI ("VirtualBox"):
5 * UISession stuff implementation
6 */
7
8/*
9 * Copyright (C) 2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24/* Global inclues */
25#include <QApplication>
26#include <QWidget>
27
28/* Local includes */
29#include "UISession.h"
30#include "UIMachine.h"
31#include "UIActionsPool.h"
32#include "UIMachineLogic.h"
33#include "UIMachineWindow.h"
34#include "VBoxProblemReporter.h"
35
36#ifdef Q_WS_X11
37# include <QX11Info>
38# ifndef VBOX_WITHOUT_XCURSOR
39# include <X11/Xcursor/Xcursor.h>
40# endif
41#endif
42
43#if defined (Q_WS_MAC)
44# include "VBoxUtils.h"
45#endif
46
47/* Guest mouse pointer shape change event: */
48class UIMousePointerShapeChangeEvent : public QEvent
49{
50public:
51
52 UIMousePointerShapeChangeEvent(bool bIsVisible, bool bIsAlpha, uint uXHot, uint uYHot, uint uWidth, uint uHeight, const uchar *pShape)
53 : QEvent((QEvent::Type)UIConsoleEventType_MousePointerShapeChange)
54 , m_bIsVisible(bIsVisible), m_bIsAlpha(bIsAlpha), m_uXHot(uXHot), m_uYHot(uYHot), m_uWidth(uWidth), m_uHeight(uHeight), m_pData(0)
55 {
56 uint dataSize = ((((m_uWidth + 7) / 8 * m_uHeight) + 3) & ~3) + m_uWidth * 4 * m_uHeight;
57 if (pShape)
58 {
59 m_pData = new uchar[dataSize];
60 memcpy((void*)m_pData, (void*)pShape, dataSize);
61 }
62 }
63
64 virtual ~UIMousePointerShapeChangeEvent()
65 {
66 if (m_pData) delete[] m_pData;
67 }
68
69 bool isVisible() const { return m_bIsVisible; }
70 bool hasAlpha() const { return m_bIsAlpha; }
71 uint xHot() const { return m_uXHot; }
72 uint yHot() const { return m_uYHot; }
73 uint width() const { return m_uWidth; }
74 uint height() const { return m_uHeight; }
75 const uchar *shapeData() const { return m_pData; }
76
77private:
78
79 bool m_bIsVisible, m_bIsAlpha;
80 uint m_uXHot, m_uYHot, m_uWidth, m_uHeight;
81 const uchar *m_pData;
82};
83
84/* Guest mouse absolute positioning capability change event: */
85class UIMouseCapabilityChangeEvent : public QEvent
86{
87public:
88
89 UIMouseCapabilityChangeEvent(bool bSupportsAbsolute, bool bSupportsRelative, bool bNeedsHostCursor)
90 : QEvent((QEvent::Type)UIConsoleEventType_MouseCapabilityChange)
91 , m_bSupportsAbsolute(bSupportsAbsolute), m_bSupportsRelative(bSupportsRelative), m_bNeedsHostCursor(bNeedsHostCursor) {}
92
93 bool supportsAbsolute() const { return m_bSupportsAbsolute; }
94 bool supportsRelative() const { return m_bSupportsRelative; }
95 bool needsHostCursor() const { return m_bNeedsHostCursor; }
96
97private:
98
99 bool m_bSupportsAbsolute;
100 bool m_bSupportsRelative;
101 bool m_bNeedsHostCursor;
102};
103
104/* Keyboard LEDs change event: */
105class UIKeyboardLedsChangeEvent : public QEvent
106{
107public:
108
109 UIKeyboardLedsChangeEvent(bool bNumLock, bool bCapsLock, bool bScrollLock)
110 : QEvent((QEvent::Type)UIConsoleEventType_KeyboardLedsChange)
111 , m_bNumLock(bNumLock), m_bCapsLock(bCapsLock), m_bScrollLock(bScrollLock) {}
112
113 bool numLock() const { return m_bNumLock; }
114 bool capsLock() const { return m_bCapsLock; }
115 bool scrollLock() const { return m_bScrollLock; }
116
117private:
118
119 bool m_bNumLock;
120 bool m_bCapsLock;
121 bool m_bScrollLock;
122};
123
124/* Machine state change event: */
125class UIStateChangeEvent : public QEvent
126{
127public:
128
129 UIStateChangeEvent(KMachineState machineState)
130 : QEvent((QEvent::Type)UIConsoleEventType_StateChange)
131 , m_machineState(machineState) {}
132
133 KMachineState machineState() const { return m_machineState; }
134
135private:
136
137 KMachineState m_machineState;
138};
139
140/* Guest Additions state change event: */
141class UIAdditionsStateChangeEvent : public QEvent
142{
143public:
144
145 UIAdditionsStateChangeEvent()
146 : QEvent((QEvent::Type)UIConsoleEventType_AdditionsStateChange) {}
147};
148
149/* Network adapter change event: */
150class UINetworkAdapterChangeEvent : public QEvent
151{
152public:
153
154 UINetworkAdapterChangeEvent(const CNetworkAdapter &networkAdapter)
155 : QEvent((QEvent::Type)UIConsoleEventType_NetworkAdapterChange)
156 , m_networkAdapter(networkAdapter) {}
157
158 const CNetworkAdapter& networkAdapter() { return m_networkAdapter; }
159
160private:
161
162 const CNetworkAdapter &m_networkAdapter;
163};
164
165/* Serial port change event: */
166class UISerialPortChangeEvent : public QEvent
167{
168public:
169
170 UISerialPortChangeEvent(const CSerialPort &serialPort)
171 : QEvent((QEvent::Type)UIConsoleEventType_SerialPortChange)
172 , m_serialPort(serialPort) {}
173
174 const CSerialPort& serialPort() { return m_serialPort; }
175
176private:
177
178 const CSerialPort &m_serialPort;
179};
180
181/* Parallel port change event: */
182class UIParallelPortChangeEvent : public QEvent
183{
184public:
185
186 UIParallelPortChangeEvent(const CParallelPort &parallelPort)
187 : QEvent((QEvent::Type)UIConsoleEventType_ParallelPortChange)
188 , m_parallelPort(parallelPort) {}
189
190 const CParallelPort& parallelPort() { return m_parallelPort; }
191
192private:
193
194 const CParallelPort &m_parallelPort;
195};
196
197/* Storage controller change event: */
198class UIStorageControllerChangeEvent : public QEvent
199{
200public:
201
202 UIStorageControllerChangeEvent()
203 : QEvent((QEvent::Type)UIConsoleEventType_StorageControllerChange) {}
204};
205
206/* Storage medium change event: */
207class UIMediumChangeEvent : public QEvent
208{
209public:
210
211 UIMediumChangeEvent(const CMediumAttachment &mediumAttachment)
212 : QEvent((QEvent::Type)UIConsoleEventType_MediumChange)
213 , m_mediumAttachment(mediumAttachment) {}
214 const CMediumAttachment& mediumAttahment() { return m_mediumAttachment; }
215
216private:
217
218 const CMediumAttachment &m_mediumAttachment;
219};
220
221/* CPU change event: */
222class UICPUChangeEvent : public QEvent
223{
224public:
225
226 UICPUChangeEvent(ulong uCPU, bool bRemove)
227 : QEvent((QEvent::Type)UIConsoleEventType_CPUChange)
228 , m_uCPU(uCPU), m_bRemove(bRemove) {}
229
230 ulong cpu() const { return m_uCPU; }
231 bool remove() const { return m_bRemove; }
232
233private:
234
235 ulong m_uCPU;
236 bool m_bRemove;
237};
238
239/* VRDP server change event: */
240class UIVRDPServerChangeEvent : public QEvent
241{
242public:
243
244 UIVRDPServerChangeEvent()
245 : QEvent((QEvent::Type)UIConsoleEventType_VRDPServerChange) {}
246};
247
248/* Remote display info change event: */
249class UIRemoteDisplayInfoChangeEvent : public QEvent
250{
251public:
252
253 UIRemoteDisplayInfoChangeEvent()
254 : QEvent((QEvent::Type)UIConsoleEventType_RemoteDisplayInfoChange) {}
255};
256
257/* USB controller change event: */
258class UIUSBControllerChangeEvent : public QEvent
259{
260public:
261
262 UIUSBControllerChangeEvent()
263 : QEvent((QEvent::Type)UIConsoleEventType_USBControllerChange) {}
264};
265
266/* USB device state change event: */
267class UIUSBDeviceUIStateChangeEvent : public QEvent
268{
269public:
270
271 UIUSBDeviceUIStateChangeEvent(const CUSBDevice &device, bool bAttached, const CVirtualBoxErrorInfo &error)
272 : QEvent((QEvent::Type)UIConsoleEventType_USBDeviceStateChange)
273 , m_device(device), m_bAttached(bAttached), m_error(error) {}
274
275 const CUSBDevice& device() const { return m_device; }
276 bool attached() const { return m_bAttached; }
277 const CVirtualBoxErrorInfo& error() const { return m_error; }
278
279private:
280
281 const CUSBDevice &m_device;
282 bool m_bAttached;
283 const CVirtualBoxErrorInfo &m_error;
284};
285
286/* Shared folder change event: */
287class UISharedFolderChangeEvent : public QEvent
288{
289public:
290
291 UISharedFolderChangeEvent()
292 : QEvent((QEvent::Type)UIConsoleEventType_SharedFolderChange) {}
293};
294
295/* VM Runtime error event: */
296class UIRuntimeErrorEvent : public QEvent
297{
298public:
299
300 UIRuntimeErrorEvent(bool bFatal, const QString &strErrorID, const QString &strMessage)
301 : QEvent((QEvent::Type)UIConsoleEventType_RuntimeError)
302 , m_bFatal(bFatal), m_strErrorID(strErrorID), m_strMessage(strMessage) {}
303
304 bool fatal() const { return m_bFatal; }
305 QString errorID() const { return m_strErrorID; }
306 QString message() const { return m_strMessage; }
307
308private:
309
310 bool m_bFatal;
311 QString m_strErrorID;
312 QString m_strMessage;
313};
314
315/* Can show window event: */
316class UICanUIShowWindowEvent : public QEvent
317{
318public:
319
320 UICanUIShowWindowEvent()
321 : QEvent((QEvent::Type)UIConsoleEventType_CanShowWindow) {}
322};
323
324/* Show window event: */
325class UIShowWindowEvent : public QEvent
326{
327public:
328
329 UIShowWindowEvent()
330 : QEvent((QEvent::Type)UIConsoleEventType_ShowWindow) {}
331};
332
333class UIConsoleCallback : VBOX_SCRIPTABLE_IMPL(IConsoleCallback)
334{
335public:
336
337 UIConsoleCallback(UISession *pEventHandler)
338 : m_pEventHandler(pEventHandler)
339#if defined (Q_WS_WIN)
340 , m_iRefCount(0)
341#endif
342 {
343 }
344
345 virtual ~UIConsoleCallback()
346 {
347 }
348
349 NS_DECL_ISUPPORTS
350
351#if defined (Q_WS_WIN)
352 STDMETHOD_(ULONG, AddRef)()
353 {
354 return ::InterlockedIncrement(&m_iRefCount);
355 }
356 STDMETHOD_(ULONG, Release)()
357 {
358 long iCount = ::InterlockedDecrement(&m_iRefCount);
359 if (iCount == 0)
360 delete this;
361 return iCount;
362 }
363#endif
364
365 VBOX_SCRIPTABLE_DISPATCH_IMPL(IConsoleCallback)
366
367 STDMETHOD(OnMousePointerShapeChange)(BOOL bIsVisible, BOOL bAlpha, ULONG uXHot, ULONG uYHot, ULONG uWidth, ULONG uHeight, BYTE *pShape)
368 {
369 QApplication::postEvent(m_pEventHandler, new UIMousePointerShapeChangeEvent(bIsVisible, bAlpha, uXHot, uYHot, uWidth, uHeight, pShape));
370 return S_OK;
371 }
372
373 STDMETHOD(OnMouseCapabilityChange)(BOOL bSupportsAbsolute, BOOL bSupportsRelative, BOOL bNeedHostCursor)
374 {
375 QApplication::postEvent(m_pEventHandler, new UIMouseCapabilityChangeEvent(bSupportsAbsolute, bSupportsRelative, bNeedHostCursor));
376 return S_OK;
377 }
378
379 STDMETHOD(OnKeyboardLedsChange)(BOOL bNumLock, BOOL bCapsLock, BOOL bScrollLock)
380 {
381 QApplication::postEvent(m_pEventHandler, new UIKeyboardLedsChangeEvent(bNumLock, bCapsLock, bScrollLock));
382 return S_OK;
383 }
384
385 STDMETHOD(OnStateChange)(MachineState_T machineState)
386 {
387 QApplication::postEvent(m_pEventHandler, new UIStateChangeEvent((KMachineState)machineState));
388 return S_OK;
389 }
390
391 STDMETHOD(OnAdditionsStateChange)()
392 {
393 QApplication::postEvent(m_pEventHandler, new UIAdditionsStateChangeEvent);
394 return S_OK;
395 }
396
397 STDMETHOD(OnNetworkAdapterChange)(INetworkAdapter *pNetworkAdapter)
398 {
399 QApplication::postEvent(m_pEventHandler, new UINetworkAdapterChangeEvent(CNetworkAdapter(pNetworkAdapter)));
400 return S_OK;
401 }
402
403 STDMETHOD(OnSerialPortChange)(ISerialPort *pSerialPort)
404 {
405 QApplication::postEvent(m_pEventHandler, new UISerialPortChangeEvent(CSerialPort(pSerialPort)));
406 return S_OK;
407 }
408
409 STDMETHOD(OnParallelPortChange)(IParallelPort *pParallelPort)
410 {
411 QApplication::postEvent(m_pEventHandler, new UIParallelPortChangeEvent(CParallelPort(pParallelPort)));
412 return S_OK;
413 }
414
415 STDMETHOD(OnStorageControllerChange)()
416 {
417 QApplication::postEvent(m_pEventHandler, new UIStorageControllerChangeEvent);
418 return S_OK;
419 }
420
421 STDMETHOD(OnMediumChange)(IMediumAttachment *pMediumAttachment)
422 {
423 QApplication::postEvent(m_pEventHandler, new UIMediumChangeEvent(CMediumAttachment(pMediumAttachment)));
424 return S_OK;
425 }
426
427 STDMETHOD(OnCPUChange)(ULONG uCPU, BOOL bRemove)
428 {
429 QApplication::postEvent(m_pEventHandler, new UICPUChangeEvent(uCPU, bRemove));
430 return S_OK;
431 }
432
433 STDMETHOD(OnVRDPServerChange)()
434 {
435 QApplication::postEvent(m_pEventHandler, new UIVRDPServerChangeEvent);
436 return S_OK;
437 }
438
439 STDMETHOD(OnRemoteDisplayInfoChange)()
440 {
441 QApplication::postEvent(m_pEventHandler, new UIRemoteDisplayInfoChangeEvent);
442 return S_OK;
443 }
444
445 STDMETHOD(OnUSBControllerChange)()
446 {
447 QApplication::postEvent(m_pEventHandler, new UIUSBControllerChangeEvent);
448 return S_OK;
449 }
450
451 STDMETHOD(OnUSBDeviceStateChange)(IUSBDevice *pDevice, BOOL bAttached, IVirtualBoxErrorInfo *pError)
452 {
453 QApplication::postEvent(m_pEventHandler, new UIUSBDeviceUIStateChangeEvent(CUSBDevice(pDevice), bAttached, CVirtualBoxErrorInfo(pError)));
454 return S_OK;
455 }
456
457 STDMETHOD(OnSharedFolderChange)(Scope_T scope)
458 {
459 NOREF(scope);
460 QApplication::postEvent(m_pEventHandler, new UISharedFolderChangeEvent);
461 return S_OK;
462 }
463
464 STDMETHOD(OnRuntimeError)(BOOL bFatal, IN_BSTR strId, IN_BSTR strMessage)
465 {
466 QApplication::postEvent(m_pEventHandler, new UIRuntimeErrorEvent(bFatal, QString::fromUtf16(strId), QString::fromUtf16(strMessage)));
467 return S_OK;
468 }
469
470 STDMETHOD(OnCanShowWindow)(BOOL *pbCanShow)
471 {
472 if (!pbCanShow)
473 return E_POINTER;
474
475 *pbCanShow = TRUE;
476 return S_OK;
477 }
478
479 STDMETHOD(OnShowWindow)(ULONG64 *puWinId)
480 {
481 if (!puWinId)
482 return E_POINTER;
483
484#if defined (Q_WS_MAC)
485 /* Let's try the simple approach first - grab the focus.
486 * Getting a window out of the dock (minimized or whatever it's called)
487 * needs to be done on the GUI thread, so post it a note: */
488 *puWinId = 0;
489 if (!m_pEventHandler)
490 return S_OK;
491
492 if (::darwinSetFrontMostProcess())
493 QApplication::postEvent(m_pEventHandler, new UIShowWindowEvent);
494 else
495 {
496 /* It failed for some reason, send the other process our PSN so it can try.
497 * (This is just a precaution should Mac OS X start imposing the same sensible
498 * focus stealing restrictions that other window managers implement). */
499 *puWinId = ::darwinGetCurrentProcessId();
500 }
501#else
502 /* Return the ID of the top-level console window. */
503 *puWinId = m_pEventHandler->winId();
504#endif
505
506 return S_OK;
507 }
508
509private:
510
511 UISession *m_pEventHandler;
512
513#if defined (Q_WS_WIN)
514 long m_iRefCount;
515#endif
516};
517
518#if !defined (Q_WS_WIN)
519NS_DECL_CLASSINFO(UIConsoleCallback)
520NS_IMPL_THREADSAFE_ISUPPORTS1_CI(UIConsoleCallback, IConsoleCallback)
521#endif
522
523UISession::UISession(UIMachine *pMachine, const CSession &session)
524 : QObject(pMachine)
525 /* Base variables: */
526 , m_pMachine(pMachine)
527 , m_session(session)
528 , m_pCallback(new UIConsoleCallback(this))
529 , m_callback(CConsoleCallback(m_pCallback))
530 /* Common varibles: */
531 , m_machineState(KMachineState_Null)
532#if defined(Q_WS_WIN)
533 , m_alphaCursor(0)
534#endif
535 /* Common flags: */
536 , m_fIsFirstTimeStarted(false)
537 , m_fIsIgnoreRutimeMediumsChanging(false)
538 /* Guest additions flags: */
539 , m_fIsGuestAdditionsActive(false)
540 , m_fIsGuestSupportsGraphics(false)
541 , m_fIsGuestSupportsSeamless(false)
542 /* Mouse flags: */
543 , m_fNumLock(false)
544 , m_fCapsLock(false)
545 , m_fScrollLock(false)
546 , m_uNumLockAdaptionCnt(2)
547 , m_uCapsLockAdaptionCnt(2)
548 /* Mouse flags: */
549 , m_fIsMouseSupportsAbsolute(false)
550 , m_fIsMouseSupportsRelative(false)
551 , m_fIsMouseHostCursorNeeded(false)
552 , m_fIsMouseCaptured(false)
553 , m_fIsMouseIntegrated(true)
554 , m_fIsHideHostPointer(true)
555{
556 /* Check CSession object */
557 AssertMsg(!m_session.isNull(), ("CSession should not be NULL!\n"));
558
559 /* Register console callback: */
560 m_session.GetConsole().RegisterCallback(m_callback);
561
562 /* Load session settings: */
563 loadSessionSettings();
564}
565
566UISession::~UISession()
567{
568 /* Save session settings: */
569 saveSessionSettings();
570
571 /* Unregister console callback: */
572 m_session.GetConsole().UnregisterCallback(m_callback);
573 delete m_pCallback;
574 m_pCallback = 0;
575}
576
577bool UISession::setPause(bool fOn)
578{
579 if (isPaused() == fOn)
580 return true;
581
582 CConsole console = session().GetConsole();
583
584 if (fOn)
585 console.Pause();
586 else
587 console.Resume();
588
589 bool ok = console.isOk();
590 if (!ok)
591 {
592 if (fOn)
593 vboxProblem().cannotPauseMachine(console);
594 else
595 vboxProblem().cannotResumeMachine(console);
596 }
597
598 return ok;
599}
600
601bool UISession::event(QEvent *pEvent)
602{
603 switch (pEvent->type())
604 {
605 case UIConsoleEventType_MousePointerShapeChange:
606 {
607 /* Convert to mouse shape change event: */
608 UIMousePointerShapeChangeEvent *pConsoleEvent = static_cast<UIMousePointerShapeChangeEvent*>(pEvent);
609
610 /* Remember if we should show cursor: */
611 m_fIsHideHostPointer = !pConsoleEvent->isVisible();
612
613 /* Cache shape dataif present: */
614 if (pConsoleEvent->shapeData())
615 setPointerShape(pConsoleEvent->shapeData(), pConsoleEvent->hasAlpha(),
616 pConsoleEvent->xHot(), pConsoleEvent->yHot(),
617 pConsoleEvent->width(), pConsoleEvent->height());
618
619 /* Notify listeners about mouse capability changed: */
620 emit sigMousePointerShapeChange();
621
622 /* Accept event: */
623 pEvent->accept();
624 return true;
625 }
626
627 case UIConsoleEventType_MouseCapabilityChange:
628 {
629 /* Convert to mouse capability event: */
630 UIMouseCapabilityChangeEvent *pConsoleEvent = static_cast<UIMouseCapabilityChangeEvent*>(pEvent);
631
632 /* Check if something had changed: */
633 if (m_fIsMouseSupportsAbsolute != pConsoleEvent->supportsAbsolute() ||
634 m_fIsMouseSupportsRelative != pConsoleEvent->supportsRelative() ||
635 m_fIsMouseHostCursorNeeded != pConsoleEvent->needsHostCursor())
636 {
637 /* Store new data: */
638 m_fIsMouseSupportsAbsolute = pConsoleEvent->supportsAbsolute();
639 m_fIsMouseSupportsRelative = pConsoleEvent->supportsRelative();
640 m_fIsMouseHostCursorNeeded = pConsoleEvent->needsHostCursor();
641
642 /* Notify listeners about mouse capability changed: */
643 emit sigMouseCapabilityChange();
644 }
645
646 /* Accept event: */
647 pEvent->accept();
648 return true;
649 }
650
651 case UIConsoleEventType_KeyboardLedsChange:
652 {
653 /* Convert to keyboard LEDs change event: */
654 UIKeyboardLedsChangeEvent *pConsoleEvent = static_cast<UIKeyboardLedsChangeEvent*>(pEvent);
655
656 /* Check if something had changed: */
657 if (m_fNumLock != pConsoleEvent->numLock() ||
658 m_fCapsLock != pConsoleEvent->capsLock() ||
659 m_fScrollLock != pConsoleEvent->scrollLock())
660 {
661 /* Store new num lock data: */
662 if (m_fNumLock != pConsoleEvent->numLock())
663 {
664 m_fNumLock = pConsoleEvent->numLock();
665 m_uNumLockAdaptionCnt = 2;
666 }
667
668 /* Store new caps lock data: */
669 if (m_fCapsLock != pConsoleEvent->capsLock())
670 {
671 m_fCapsLock = pConsoleEvent->capsLock();
672 m_uCapsLockAdaptionCnt = 2;
673 }
674
675 /* Store new scroll lock data: */
676 if (m_fScrollLock != pConsoleEvent->scrollLock())
677 {
678 m_fScrollLock = pConsoleEvent->scrollLock();
679 }
680
681 /* Notify listeners about mouse capability changed: */
682 emit sigKeyboardLedsChange();
683 }
684
685 /* Accept event: */
686 pEvent->accept();
687 return true;
688 }
689
690 case UIConsoleEventType_StateChange:
691 {
692 /* Convert to machine state event: */
693 UIStateChangeEvent *pConsoleEvent = static_cast<UIStateChangeEvent*>(pEvent);
694
695 /* Check if something had changed: */
696 if (m_machineState != pConsoleEvent->machineState())
697 {
698 /* Store new data: */
699 m_machineState = pConsoleEvent->machineState();
700
701 /* Notify listeners about machine state changed: */
702 emit sigMachineStateChange();
703 }
704
705 /* Accept event: */
706 pEvent->accept();
707 return true;
708 }
709
710 case UIConsoleEventType_AdditionsStateChange:
711 {
712 /* Get our guest: */
713 CGuest guest = session().GetConsole().GetGuest();
714
715 /* Variable flags: */
716 bool fIsGuestAdditionsActive = guest.GetAdditionsActive();
717 bool fIsGuestSupportsGraphics = guest.GetSupportsGraphics();
718 bool fIsGuestSupportsSeamless = guest.GetSupportsSeamless();
719
720 /* Check if something had changed: */
721 if (m_fIsGuestAdditionsActive != fIsGuestAdditionsActive ||
722 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
723 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
724 {
725 /* Store new data: */
726 m_fIsGuestAdditionsActive = fIsGuestAdditionsActive;
727 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
728 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
729
730 /* Notify listeners about guest additions state changed: */
731 emit sigAdditionsStateChange();
732 }
733
734 /* Accept event: */
735 pEvent->accept();
736 return true;
737 }
738
739 case UIConsoleEventType_NetworkAdapterChange:
740 {
741 UINetworkAdapterChangeEvent *pConsoleEvent = static_cast<UINetworkAdapterChangeEvent*>(pEvent);
742 emit sigNetworkAdapterChange(pConsoleEvent->networkAdapter());
743 return true;
744 }
745
746 case UIConsoleEventType_SerialPortChange:
747 {
748 UISerialPortChangeEvent *pConsoleEvent = static_cast<UISerialPortChangeEvent*>(pEvent);
749 emit sigSerialPortChange(pConsoleEvent->serialPort());
750 return true;
751 }
752
753 case UIConsoleEventType_ParallelPortChange:
754 {
755 UIParallelPortChangeEvent *pConsoleEvent = static_cast<UIParallelPortChangeEvent*>(pEvent);
756 emit sigParallelPortChange(pConsoleEvent->parallelPort());
757 return true;
758 }
759
760 case UIConsoleEventType_StorageControllerChange:
761 {
762 emit sigStorageControllerChange();
763 return true;
764 }
765
766 case UIConsoleEventType_MediumChange:
767 {
768 UIMediumChangeEvent *pConsoleEvent = static_cast<UIMediumChangeEvent*>(pEvent);
769 emit sigMediumChange(pConsoleEvent->mediumAttahment());
770 return true;
771 }
772
773 case UIConsoleEventType_CPUChange:
774 {
775 UICPUChangeEvent *pConsoleEvent = static_cast<UICPUChangeEvent*>(pEvent);
776 emit sigCPUChange(pConsoleEvent->cpu(), pConsoleEvent->remove());
777 return true;
778 }
779
780 case UIConsoleEventType_VRDPServerChange:
781 {
782 emit sigVRDPServerChange();
783 return true;
784 }
785
786 case UIConsoleEventType_RemoteDisplayInfoChange:
787 {
788 emit sigRemoteDisplayInfoChange();
789 return true;
790 }
791
792 case UIConsoleEventType_USBControllerChange:
793 {
794 emit sigUSBControllerChange();
795 return true;
796 }
797
798 case UIConsoleEventType_USBDeviceStateChange:
799 {
800 UIUSBDeviceUIStateChangeEvent *pConsoleEvent = static_cast<UIUSBDeviceUIStateChangeEvent*>(pEvent);
801 emit sigUSBDeviceStateChange(pConsoleEvent->device(), pConsoleEvent->attached(), pConsoleEvent->error());
802 return true;
803 }
804
805 case UIConsoleEventType_SharedFolderChange:
806 {
807 emit sigSharedFolderChange();
808 return true;
809 }
810
811 case UIConsoleEventType_RuntimeError:
812 {
813 UIRuntimeErrorEvent *pConsoleEvent = static_cast<UIRuntimeErrorEvent*>(pEvent);
814 emit sigRuntimeError(pConsoleEvent->fatal(), pConsoleEvent->errorID(), pConsoleEvent->message());
815 return true;
816 }
817
818#ifdef Q_WS_MAC
819 /* posted OnShowWindow */
820 case UIConsoleEventType_ShowWindow:
821 {
822 /* Dunno what Qt3 thinks a window that has minimized to the dock
823 * should be - it is not hidden, neither is it minimized. OTOH it is
824 * marked shown and visible, but not activated. This latter isn't of
825 * much help though, since at this point nothing is marked activated.
826 * I might have overlooked something, but I'm buggered what if I know
827 * what. So, I'll just always show & activate the stupid window to
828 * make it get out of the dock when the user wishes to show a VM. */
829#if 0
830 // TODO_NEW_CORE
831 window()->show();
832 window()->activateWindow();
833#endif
834 return true;
835 }
836#endif
837
838 default:
839 break;
840 }
841 return QObject::event(pEvent);
842}
843
844void UISession::loadSessionSettings()
845{
846 /* Get machine: */
847 CMachine machine = session().GetConsole().GetMachine();
848
849 /* Availability settings: */
850 {
851 /* USB Stuff: */
852 CUSBController usbController = machine.GetUSBController();
853 if (usbController.isNull())
854 {
855 /* Hide USB menu if controller is NULL: */
856 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setVisible(false);
857 }
858 else
859 {
860 /* Enable/Disable USB menu depending on USB controller: */
861 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setEnabled(usbController.GetEnabled());
862 }
863
864 /* VRDP Stuff: */
865 CVRDPServer vrdpServer = machine.GetVRDPServer();
866 if (vrdpServer.isNull())
867 {
868 /* Hide VRDP Action: */
869 uimachine()->actionsPool()->action(UIActionIndex_Toggle_VRDP)->setVisible(false);
870 }
871 }
872
873 /* Prepare some initial settings: */
874 {
875 /* Initialize CD/FD menus: */
876 int iDevicesCountCD = 0;
877 int iDevicesCountFD = 0;
878 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
879 foreach (const CMediumAttachment &attachment, attachments)
880 {
881 if (attachment.GetType() == KDeviceType_DVD)
882 ++ iDevicesCountCD;
883 if (attachment.GetType() == KDeviceType_Floppy)
884 ++ iDevicesCountFD;
885 }
886 QAction *pOpticalDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices);
887 QAction *pFloppyDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_FloppyDevices);
888 pOpticalDevicesMenu->setData(iDevicesCountCD);
889 pOpticalDevicesMenu->setVisible(iDevicesCountCD);
890 pFloppyDevicesMenu->setData(iDevicesCountFD);
891 pFloppyDevicesMenu->setVisible(iDevicesCountFD);
892 }
893
894 /* Load extra-data settings: */
895 {
896 /* Temporary: */
897 QString strSettings;
898
899 /* Is there shoul be First RUN Wizard? */
900 strSettings = machine.GetExtraData(VBoxDefs::GUI_FirstRun);
901 if (strSettings == "yes")
902 m_fIsFirstTimeStarted = true;
903
904 /* Ignore mediums mounted at runtime? */
905 strSettings = machine.GetExtraData(VBoxDefs::GUI_SaveMountedAtRuntime);
906 if (strSettings == "no")
907 m_fIsIgnoreRutimeMediumsChanging = true;
908
909 /* Should guest autoresize? */
910 strSettings = machine.GetExtraData(VBoxDefs::GUI_AutoresizeGuest);
911 QAction *pGuestAutoresizeSwitch = uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize);
912 pGuestAutoresizeSwitch->blockSignals(true);
913 pGuestAutoresizeSwitch->setChecked(strSettings != "off");
914 pGuestAutoresizeSwitch->blockSignals(false);
915 }
916}
917
918void UISession::saveSessionSettings()
919{
920 /* Get session machine: */
921 CMachine machine = session().GetConsole().GetMachine();
922
923 /* Save extra-data settings: */
924 {
925 /* Disable First RUN Wizard for the since now: */
926 machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString());
927
928 /* Remember if guest should autoresize: */
929 machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest,
930 uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->isChecked() ?
931 QString() : "off");
932
933 // TODO: Move to fullscreen/seamless logic:
934 //machine.SetExtraData(VBoxDefs::GUI_MiniToolBarAutoHide, mMiniToolBar->isAutoHide() ? "on" : "off");
935 }
936}
937
938qulonglong UISession::winId() const
939{
940 return uimachine()->machineLogic()->machineWindowWrapper()->machineWindow()->winId();
941}
942
943void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
944 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
945{
946 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
947
948 const uchar *srcAndMaskPtr = pShapeData;
949 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
950 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
951 uint srcShapePtrScan = uWidth * 4;
952
953#if defined (Q_WS_WIN)
954
955 BITMAPV5HEADER bi;
956 HBITMAP hBitmap;
957 void *lpBits;
958
959 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
960 bi.bV5Size = sizeof(BITMAPV5HEADER);
961 bi.bV5Width = uWidth;
962 bi.bV5Height = - (LONG)uHeight;
963 bi.bV5Planes = 1;
964 bi.bV5BitCount = 32;
965 bi.bV5Compression = BI_BITFIELDS;
966 bi.bV5RedMask = 0x00FF0000;
967 bi.bV5GreenMask = 0x0000FF00;
968 bi.bV5BlueMask = 0x000000FF;
969 if (fHasAlpha)
970 bi.bV5AlphaMask = 0xFF000000;
971 else
972 bi.bV5AlphaMask = 0;
973
974 HDC hdc = GetDC(NULL);
975
976 /* Create the DIB section with an alpha channel: */
977 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
978
979 ReleaseDC(NULL, hdc);
980
981 HBITMAP hMonoBitmap = NULL;
982 if (fHasAlpha)
983 {
984 /* Create an empty mask bitmap: */
985 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
986 }
987 else
988 {
989 /* Word aligned AND mask. Will be allocated and created if necessary. */
990 uint8_t *pu8AndMaskWordAligned = NULL;
991
992 /* Width in bytes of the original AND mask scan line. */
993 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
994
995 if (cbAndMaskScan & 1)
996 {
997 /* Original AND mask is not word aligned. */
998
999 /* Allocate memory for aligned AND mask. */
1000 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
1001
1002 Assert(pu8AndMaskWordAligned);
1003
1004 if (pu8AndMaskWordAligned)
1005 {
1006 /* According to MSDN the padding bits must be 0.
1007 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
1008 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
1009 Assert(u32PaddingBits < 8);
1010 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
1011
1012 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
1013 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
1014
1015 uint8_t *src = (uint8_t *)srcAndMaskPtr;
1016 uint8_t *dst = pu8AndMaskWordAligned;
1017
1018 unsigned i;
1019 for (i = 0; i < uHeight; i++)
1020 {
1021 memcpy(dst, src, cbAndMaskScan);
1022
1023 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
1024
1025 src += cbAndMaskScan;
1026 dst += cbAndMaskScan + 1;
1027 }
1028 }
1029 }
1030
1031 /* Create the AND mask bitmap: */
1032 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
1033 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
1034
1035 if (pu8AndMaskWordAligned)
1036 {
1037 RTMemTmpFree(pu8AndMaskWordAligned);
1038 }
1039 }
1040
1041 Assert(hBitmap);
1042 Assert(hMonoBitmap);
1043 if (hBitmap && hMonoBitmap)
1044 {
1045 DWORD *dstShapePtr = (DWORD *) lpBits;
1046
1047 for (uint y = 0; y < uHeight; y ++)
1048 {
1049 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
1050 srcShapePtr += srcShapePtrScan;
1051 dstShapePtr += uWidth;
1052 }
1053
1054 ICONINFO ii;
1055 ii.fIcon = FALSE;
1056 ii.xHotspot = uXHot;
1057 ii.yHotspot = uYHot;
1058 ii.hbmMask = hMonoBitmap;
1059 ii.hbmColor = hBitmap;
1060
1061 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
1062 Assert(hAlphaCursor);
1063 if (hAlphaCursor)
1064 {
1065 /* Set the new cursor: */
1066 m_cursor = QCursor(hAlphaCursor);
1067 if (m_alphaCursor)
1068 DestroyIcon(m_alphaCursor);
1069 m_alphaCursor = hAlphaCursor;
1070 }
1071 }
1072
1073 if (hMonoBitmap)
1074 DeleteObject(hMonoBitmap);
1075 if (hBitmap)
1076 DeleteObject(hBitmap);
1077
1078#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
1079
1080 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
1081 Assert(img);
1082 if (img)
1083 {
1084 img->xhot = uXHot;
1085 img->yhot = uYHot;
1086
1087 XcursorPixel *dstShapePtr = img->pixels;
1088
1089 for (uint y = 0; y < uHeight; y ++)
1090 {
1091 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
1092
1093 if (!fHasAlpha)
1094 {
1095 /* Convert AND mask to the alpha channel: */
1096 uchar byte = 0;
1097 for (uint x = 0; x < uWidth; x ++)
1098 {
1099 if (!(x % 8))
1100 byte = *(srcAndMaskPtr ++);
1101 else
1102 byte <<= 1;
1103
1104 if (byte & 0x80)
1105 {
1106 /* Linux doesn't support inverted pixels (XOR ops,
1107 * to be exact) in cursor shapes, so we detect such
1108 * pixels and always replace them with black ones to
1109 * make them visible at least over light colors */
1110 if (dstShapePtr [x] & 0x00FFFFFF)
1111 dstShapePtr [x] = 0xFF000000;
1112 else
1113 dstShapePtr [x] = 0x00000000;
1114 }
1115 else
1116 dstShapePtr [x] |= 0xFF000000;
1117 }
1118 }
1119
1120 srcShapePtr += srcShapePtrScan;
1121 dstShapePtr += uWidth;
1122 }
1123
1124 /* Set the new cursor: */
1125 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
1126
1127 XcursorImageDestroy(img);
1128 }
1129
1130#elif defined(Q_WS_MAC)
1131
1132 /* Create a ARGB image out of the shape data. */
1133 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
1134 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
1135 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
1136 for (unsigned int y = 0; y < uHeight; ++y)
1137 {
1138 for (unsigned int x = 0; x < uWidth; ++x)
1139 {
1140 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
1141 /* If the alpha channel isn't in the shape data, we have to
1142 * create them from the and-mask. This is a bit field where 1
1143 * represent transparency & 0 opaque respectively. */
1144 if (!fHasAlpha)
1145 {
1146 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
1147 color |= 0xff000000;
1148 else
1149 {
1150 /* This isn't quite right, but it's the best we can do I think... */
1151 if (color & 0x00ffffff)
1152 color = 0xff000000;
1153 else
1154 color = 0x00000000;
1155 }
1156 }
1157 image.setPixel (x, y, color);
1158 }
1159 /* Move one scanline forward. */
1160 pbSrcMask += cbSrcMaskLine;
1161 }
1162
1163 /* Set the new cursor: */
1164 m_cursor = cursor(QPixmap::fromImage(image), uXHot, uYHot);
1165 NOREF(srcShapePtrScan);
1166
1167#else
1168
1169# warning "port me"
1170
1171#endif
1172}
1173
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