VirtualBox

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

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

FE/Qt4: New running VM core: cumulative patch to let uimachine to restore mouse/keyboard states when switching modes.

  • 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 26815 2010-02-26 02:43:37Z 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 /* Common flags: */
533 , m_fIsFirstTimeStarted(false)
534 , m_fIsIgnoreRutimeMediumsChanging(false)
535 /* Guest additions flags: */
536 , m_fIsGuestAdditionsActive(false)
537 , m_fIsGuestSupportsGraphics(false)
538 , m_fIsGuestSupportsSeamless(false)
539 /* Mouse flags: */
540 , m_fNumLock(false)
541 , m_fCapsLock(false)
542 , m_fScrollLock(false)
543 , m_uNumLockAdaptionCnt(2)
544 , m_uCapsLockAdaptionCnt(2)
545 /* Mouse flags: */
546 , m_fIsMouseSupportsAbsolute(false)
547 , m_fIsMouseSupportsRelative(false)
548 , m_fIsMouseHostCursorNeeded(false)
549 , m_fIsMouseCaptured(false)
550 , m_fIsMouseIntegrated(true)
551 , m_fIsHideHostPointer(true)
552{
553 /* Check CSession object */
554 AssertMsg(!m_session.isNull(), ("CSession should not be NULL!\n"));
555
556 /* Register console callback: */
557 m_session.GetConsole().RegisterCallback(m_callback);
558
559 /* Load session settings: */
560 loadSessionSettings();
561}
562
563UISession::~UISession()
564{
565 /* Save session settings: */
566 saveSessionSettings();
567
568 /* Unregister console callback: */
569 m_session.GetConsole().UnregisterCallback(m_callback);
570 delete m_pCallback;
571 m_pCallback = 0;
572}
573
574bool UISession::setPause(bool fOn)
575{
576 if (isPaused() == fOn)
577 return true;
578
579 CConsole console = session().GetConsole();
580
581 if (fOn)
582 console.Pause();
583 else
584 console.Resume();
585
586 bool ok = console.isOk();
587 if (!ok)
588 {
589 if (fOn)
590 vboxProblem().cannotPauseMachine(console);
591 else
592 vboxProblem().cannotResumeMachine(console);
593 }
594
595 return ok;
596}
597
598bool UISession::event(QEvent *pEvent)
599{
600 switch (pEvent->type())
601 {
602 case UIConsoleEventType_MousePointerShapeChange:
603 {
604 /* Convert to mouse shape change event: */
605 UIMousePointerShapeChangeEvent *pConsoleEvent = static_cast<UIMousePointerShapeChangeEvent*>(pEvent);
606
607 /* Remember if we should show cursor: */
608 m_fIsHideHostPointer = !pConsoleEvent->isVisible();
609
610 /* Cache shape dataif present: */
611 if (pConsoleEvent->shapeData())
612 setPointerShape(pConsoleEvent->shapeData(), pConsoleEvent->hasAlpha(),
613 pConsoleEvent->xHot(), pConsoleEvent->yHot(),
614 pConsoleEvent->width(), pConsoleEvent->height());
615
616 /* Notify listeners about mouse capability changed: */
617 emit sigMousePointerShapeChange();
618
619 /* Accept event: */
620 pEvent->accept();
621 return true;
622 }
623
624 case UIConsoleEventType_MouseCapabilityChange:
625 {
626 /* Convert to mouse capability event: */
627 UIMouseCapabilityChangeEvent *pConsoleEvent = static_cast<UIMouseCapabilityChangeEvent*>(pEvent);
628
629 /* Check if something had changed: */
630 if (m_fIsMouseSupportsAbsolute != pConsoleEvent->supportsAbsolute() ||
631 m_fIsMouseSupportsRelative != pConsoleEvent->supportsRelative() ||
632 m_fIsMouseHostCursorNeeded != pConsoleEvent->needsHostCursor())
633 {
634 /* Store new data: */
635 m_fIsMouseSupportsAbsolute = pConsoleEvent->supportsAbsolute();
636 m_fIsMouseSupportsRelative = pConsoleEvent->supportsRelative();
637 m_fIsMouseHostCursorNeeded = pConsoleEvent->needsHostCursor();
638
639 /* Notify listeners about mouse capability changed: */
640 emit sigMouseCapabilityChange();
641 }
642
643 /* Accept event: */
644 pEvent->accept();
645 return true;
646 }
647
648 case UIConsoleEventType_KeyboardLedsChange:
649 {
650 /* Convert to keyboard LEDs change event: */
651 UIKeyboardLedsChangeEvent *pConsoleEvent = static_cast<UIKeyboardLedsChangeEvent*>(pEvent);
652
653 /* Check if something had changed: */
654 if (m_fNumLock != pConsoleEvent->numLock() ||
655 m_fCapsLock != pConsoleEvent->capsLock() ||
656 m_fScrollLock != pConsoleEvent->scrollLock())
657 {
658 /* Store new num lock data: */
659 if (m_fNumLock != pConsoleEvent->numLock())
660 {
661 m_fNumLock = pConsoleEvent->numLock();
662 m_uNumLockAdaptionCnt = 2;
663 }
664
665 /* Store new caps lock data: */
666 if (m_fCapsLock != pConsoleEvent->capsLock())
667 {
668 m_fCapsLock = pConsoleEvent->capsLock();
669 m_uCapsLockAdaptionCnt = 2;
670 }
671
672 /* Store new scroll lock data: */
673 if (m_fScrollLock != pConsoleEvent->scrollLock())
674 {
675 m_fScrollLock = pConsoleEvent->scrollLock();
676 }
677
678 /* Notify listeners about mouse capability changed: */
679 emit sigKeyboardLedsChange();
680 }
681
682 /* Accept event: */
683 pEvent->accept();
684 return true;
685 }
686
687 case UIConsoleEventType_StateChange:
688 {
689 /* Convert to machine state event: */
690 UIStateChangeEvent *pConsoleEvent = static_cast<UIStateChangeEvent*>(pEvent);
691
692 /* Check if something had changed: */
693 if (m_machineState != pConsoleEvent->machineState())
694 {
695 /* Store new data: */
696 m_machineState = pConsoleEvent->machineState();
697
698 /* Notify listeners about machine state changed: */
699 emit sigMachineStateChange();
700 }
701
702 /* Accept event: */
703 pEvent->accept();
704 return true;
705 }
706
707 case UIConsoleEventType_AdditionsStateChange:
708 {
709 /* Get our guest: */
710 CGuest guest = session().GetConsole().GetGuest();
711
712 /* Variable flags: */
713 bool fIsGuestAdditionsActive = guest.GetAdditionsActive();
714 bool fIsGuestSupportsGraphics = guest.GetSupportsGraphics();
715 bool fIsGuestSupportsSeamless = guest.GetSupportsSeamless();
716
717 /* Check if something had changed: */
718 if (m_fIsGuestAdditionsActive != fIsGuestAdditionsActive ||
719 m_fIsGuestSupportsGraphics != fIsGuestSupportsGraphics ||
720 m_fIsGuestSupportsSeamless != fIsGuestSupportsSeamless)
721 {
722 /* Store new data: */
723 m_fIsGuestAdditionsActive = fIsGuestAdditionsActive;
724 m_fIsGuestSupportsGraphics = fIsGuestSupportsGraphics;
725 m_fIsGuestSupportsSeamless = fIsGuestSupportsSeamless;
726
727 /* Notify listeners about guest additions state changed: */
728 emit sigAdditionsStateChange();
729 }
730
731 /* Accept event: */
732 pEvent->accept();
733 return true;
734 }
735
736 case UIConsoleEventType_NetworkAdapterChange:
737 {
738 UINetworkAdapterChangeEvent *pConsoleEvent = static_cast<UINetworkAdapterChangeEvent*>(pEvent);
739 emit sigNetworkAdapterChange(pConsoleEvent->networkAdapter());
740 return true;
741 }
742
743 case UIConsoleEventType_SerialPortChange:
744 {
745 UISerialPortChangeEvent *pConsoleEvent = static_cast<UISerialPortChangeEvent*>(pEvent);
746 emit sigSerialPortChange(pConsoleEvent->serialPort());
747 return true;
748 }
749
750 case UIConsoleEventType_ParallelPortChange:
751 {
752 UIParallelPortChangeEvent *pConsoleEvent = static_cast<UIParallelPortChangeEvent*>(pEvent);
753 emit sigParallelPortChange(pConsoleEvent->parallelPort());
754 return true;
755 }
756
757 case UIConsoleEventType_StorageControllerChange:
758 {
759 emit sigStorageControllerChange();
760 return true;
761 }
762
763 case UIConsoleEventType_MediumChange:
764 {
765 UIMediumChangeEvent *pConsoleEvent = static_cast<UIMediumChangeEvent*>(pEvent);
766 emit sigMediumChange(pConsoleEvent->mediumAttahment());
767 return true;
768 }
769
770 case UIConsoleEventType_CPUChange:
771 {
772 UICPUChangeEvent *pConsoleEvent = static_cast<UICPUChangeEvent*>(pEvent);
773 emit sigCPUChange(pConsoleEvent->cpu(), pConsoleEvent->remove());
774 return true;
775 }
776
777 case UIConsoleEventType_VRDPServerChange:
778 {
779 emit sigVRDPServerChange();
780 return true;
781 }
782
783 case UIConsoleEventType_RemoteDisplayInfoChange:
784 {
785 emit sigRemoteDisplayInfoChange();
786 return true;
787 }
788
789 case UIConsoleEventType_USBControllerChange:
790 {
791 emit sigUSBControllerChange();
792 return true;
793 }
794
795 case UIConsoleEventType_USBDeviceStateChange:
796 {
797 UIUSBDeviceUIStateChangeEvent *pConsoleEvent = static_cast<UIUSBDeviceUIStateChangeEvent*>(pEvent);
798 emit sigUSBDeviceStateChange(pConsoleEvent->device(), pConsoleEvent->attached(), pConsoleEvent->error());
799 return true;
800 }
801
802 case UIConsoleEventType_SharedFolderChange:
803 {
804 emit sigSharedFolderChange();
805 return true;
806 }
807
808 case UIConsoleEventType_RuntimeError:
809 {
810 UIRuntimeErrorEvent *pConsoleEvent = static_cast<UIRuntimeErrorEvent*>(pEvent);
811 emit sigRuntimeError(pConsoleEvent->fatal(), pConsoleEvent->errorID(), pConsoleEvent->message());
812 return true;
813 }
814
815#ifdef Q_WS_MAC
816 /* posted OnShowWindow */
817 case UIConsoleEventType_ShowWindow:
818 {
819 /* Dunno what Qt3 thinks a window that has minimized to the dock
820 * should be - it is not hidden, neither is it minimized. OTOH it is
821 * marked shown and visible, but not activated. This latter isn't of
822 * much help though, since at this point nothing is marked activated.
823 * I might have overlooked something, but I'm buggered what if I know
824 * what. So, I'll just always show & activate the stupid window to
825 * make it get out of the dock when the user wishes to show a VM. */
826#if 0
827 // TODO_NEW_CORE
828 window()->show();
829 window()->activateWindow();
830#endif
831 return true;
832 }
833#endif
834
835 default:
836 break;
837 }
838 return QObject::event(pEvent);
839}
840
841void UISession::loadSessionSettings()
842{
843 /* Get machine: */
844 CMachine machine = session().GetConsole().GetMachine();
845
846 /* Availability settings: */
847 {
848 /* USB Stuff: */
849 CUSBController usbController = machine.GetUSBController();
850 if (usbController.isNull())
851 {
852 /* Hide USB menu if controller is NULL: */
853 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setVisible(false);
854 }
855 else
856 {
857 /* Enable/Disable USB menu depending on USB controller: */
858 uimachine()->actionsPool()->action(UIActionIndex_Menu_USBDevices)->setEnabled(usbController.GetEnabled());
859 }
860
861 /* VRDP Stuff: */
862 CVRDPServer vrdpServer = machine.GetVRDPServer();
863 if (vrdpServer.isNull())
864 {
865 /* Hide VRDP Action: */
866 uimachine()->actionsPool()->action(UIActionIndex_Toggle_VRDP)->setVisible(false);
867 }
868 }
869
870 /* Prepare some initial settings: */
871 {
872 /* Initialize CD/FD menus: */
873 int iDevicesCountCD = 0;
874 int iDevicesCountFD = 0;
875 const CMediumAttachmentVector &attachments = machine.GetMediumAttachments();
876 foreach (const CMediumAttachment &attachment, attachments)
877 {
878 if (attachment.GetType() == KDeviceType_DVD)
879 ++ iDevicesCountCD;
880 if (attachment.GetType() == KDeviceType_Floppy)
881 ++ iDevicesCountFD;
882 }
883 QAction *pOpticalDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_OpticalDevices);
884 QAction *pFloppyDevicesMenu = uimachine()->actionsPool()->action(UIActionIndex_Menu_FloppyDevices);
885 pOpticalDevicesMenu->setData(iDevicesCountCD);
886 pOpticalDevicesMenu->setVisible(iDevicesCountCD);
887 pFloppyDevicesMenu->setData(iDevicesCountFD);
888 pFloppyDevicesMenu->setVisible(iDevicesCountFD);
889 }
890
891 /* Load extra-data settings: */
892 {
893 /* Temporary: */
894 QString strSettings;
895
896 /* Is there shoul be First RUN Wizard? */
897 strSettings = machine.GetExtraData(VBoxDefs::GUI_FirstRun);
898 if (strSettings == "yes")
899 m_fIsFirstTimeStarted = true;
900
901 /* Ignore mediums mounted at runtime? */
902 strSettings = machine.GetExtraData(VBoxDefs::GUI_SaveMountedAtRuntime);
903 if (strSettings == "no")
904 m_fIsIgnoreRutimeMediumsChanging = true;
905
906 /* Should guest autoresize? */
907 strSettings = machine.GetExtraData(VBoxDefs::GUI_AutoresizeGuest);
908 QAction *pGuestAutoresizeSwitch = uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize);
909 pGuestAutoresizeSwitch->blockSignals(true);
910 pGuestAutoresizeSwitch->setChecked(strSettings != "off");
911 pGuestAutoresizeSwitch->blockSignals(false);
912 }
913}
914
915void UISession::saveSessionSettings()
916{
917 /* Get session machine: */
918 CMachine machine = session().GetConsole().GetMachine();
919
920 /* Save extra-data settings: */
921 {
922 /* Disable First RUN Wizard for the since now: */
923 machine.SetExtraData(VBoxDefs::GUI_FirstRun, QString());
924
925 /* Remember if guest should autoresize: */
926 machine.SetExtraData(VBoxDefs::GUI_AutoresizeGuest,
927 uimachine()->actionsPool()->action(UIActionIndex_Toggle_GuestAutoresize)->isChecked() ?
928 QString() : "off");
929
930 // TODO: Move to fullscreen/seamless logic:
931 //machine.SetExtraData(VBoxDefs::GUI_MiniToolBarAutoHide, mMiniToolBar->isAutoHide() ? "on" : "off");
932 }
933}
934
935qulonglong UISession::winId() const
936{
937 return uimachine()->machineLogic()->machineWindowWrapper()->machineWindow()->winId();
938}
939
940void UISession::setPointerShape(const uchar *pShapeData, bool fHasAlpha,
941 uint uXHot, uint uYHot, uint uWidth, uint uHeight)
942{
943 AssertMsg(pShapeData, ("Shape data must not be NULL!\n"));
944
945 const uchar *srcAndMaskPtr = pShapeData;
946 uint andMaskSize = (uWidth + 7) / 8 * uHeight;
947 const uchar *srcShapePtr = pShapeData + ((andMaskSize + 3) & ~3);
948 uint srcShapePtrScan = uWidth * 4;
949
950#if defined (Q_WS_WIN)
951
952 BITMAPV5HEADER bi;
953 HBITMAP hBitmap;
954 void *lpBits;
955
956 ::ZeroMemory(&bi, sizeof (BITMAPV5HEADER));
957 bi.bV5Size = sizeof(BITMAPV5HEADER);
958 bi.bV5Width = uWidth;
959 bi.bV5Height = - (LONG)uHeight;
960 bi.bV5Planes = 1;
961 bi.bV5BitCount = 32;
962 bi.bV5Compression = BI_BITFIELDS;
963 bi.bV5RedMask = 0x00FF0000;
964 bi.bV5GreenMask = 0x0000FF00;
965 bi.bV5BlueMask = 0x000000FF;
966 if (fHasAlpha)
967 bi.bV5AlphaMask = 0xFF000000;
968 else
969 bi.bV5AlphaMask = 0;
970
971 HDC hdc = GetDC(NULL);
972
973 /* Create the DIB section with an alpha channel: */
974 hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, (DWORD) 0);
975
976 ReleaseDC(NULL, hdc);
977
978 HBITMAP hMonoBitmap = NULL;
979 if (fHasAlpha)
980 {
981 /* Create an empty mask bitmap: */
982 hMonoBitmap = CreateBitmap(uWidth, uHeight, 1, 1, NULL);
983 }
984 else
985 {
986 /* Word aligned AND mask. Will be allocated and created if necessary. */
987 uint8_t *pu8AndMaskWordAligned = NULL;
988
989 /* Width in bytes of the original AND mask scan line. */
990 uint32_t cbAndMaskScan = (uWidth + 7) / 8;
991
992 if (cbAndMaskScan & 1)
993 {
994 /* Original AND mask is not word aligned. */
995
996 /* Allocate memory for aligned AND mask. */
997 pu8AndMaskWordAligned = (uint8_t *)RTMemTmpAllocZ((cbAndMaskScan + 1) * uHeight);
998
999 Assert(pu8AndMaskWordAligned);
1000
1001 if (pu8AndMaskWordAligned)
1002 {
1003 /* According to MSDN the padding bits must be 0.
1004 * Compute the bit mask to set padding bits to 0 in the last byte of original AND mask. */
1005 uint32_t u32PaddingBits = cbAndMaskScan * 8 - uWidth;
1006 Assert(u32PaddingBits < 8);
1007 uint8_t u8LastBytesPaddingMask = (uint8_t)(0xFF << u32PaddingBits);
1008
1009 Log(("u8LastBytesPaddingMask = %02X, aligned w = %d, width = %d, cbAndMaskScan = %d\n",
1010 u8LastBytesPaddingMask, (cbAndMaskScan + 1) * 8, uWidth, cbAndMaskScan));
1011
1012 uint8_t *src = (uint8_t *)srcAndMaskPtr;
1013 uint8_t *dst = pu8AndMaskWordAligned;
1014
1015 unsigned i;
1016 for (i = 0; i < uHeight; i++)
1017 {
1018 memcpy(dst, src, cbAndMaskScan);
1019
1020 dst[cbAndMaskScan - 1] &= u8LastBytesPaddingMask;
1021
1022 src += cbAndMaskScan;
1023 dst += cbAndMaskScan + 1;
1024 }
1025 }
1026 }
1027
1028 /* Create the AND mask bitmap: */
1029 hMonoBitmap = ::CreateBitmap(uWidth, uHeight, 1, 1,
1030 pu8AndMaskWordAligned? pu8AndMaskWordAligned: srcAndMaskPtr);
1031
1032 if (pu8AndMaskWordAligned)
1033 {
1034 RTMemTmpFree(pu8AndMaskWordAligned);
1035 }
1036 }
1037
1038 Assert(hBitmap);
1039 Assert(hMonoBitmap);
1040 if (hBitmap && hMonoBitmap)
1041 {
1042 DWORD *dstShapePtr = (DWORD *) lpBits;
1043
1044 for (uint y = 0; y < uHeight; y ++)
1045 {
1046 memcpy(dstShapePtr, srcShapePtr, srcShapePtrScan);
1047 srcShapePtr += srcShapePtrScan;
1048 dstShapePtr += uWidth;
1049 }
1050
1051 ICONINFO ii;
1052 ii.fIcon = FALSE;
1053 ii.xHotspot = uXHot;
1054 ii.yHotspot = uYHot;
1055 ii.hbmMask = hMonoBitmap;
1056 ii.hbmColor = hBitmap;
1057
1058 HCURSOR hAlphaCursor = CreateIconIndirect(&ii);
1059 Assert(hAlphaCursor);
1060 if (hAlphaCursor)
1061 {
1062 /* Set the new cursor: */
1063 m_cursor = QCursor(hAlphaCursor);
1064 if (m_alphaCursor)
1065 DestroyIcon(m_alphaCursor);
1066 m_alphaCursor = hAlphaCursor;
1067 }
1068 }
1069
1070 if (hMonoBitmap)
1071 DeleteObject(hMonoBitmap);
1072 if (hBitmap)
1073 DeleteObject(hBitmap);
1074
1075#elif defined (Q_WS_X11) && !defined (VBOX_WITHOUT_XCURSOR)
1076
1077 XcursorImage *img = XcursorImageCreate(uWidth, uHeight);
1078 Assert(img);
1079 if (img)
1080 {
1081 img->xhot = uXHot;
1082 img->yhot = uYHot;
1083
1084 XcursorPixel *dstShapePtr = img->pixels;
1085
1086 for (uint y = 0; y < uHeight; y ++)
1087 {
1088 memcpy (dstShapePtr, srcShapePtr, srcShapePtrScan);
1089
1090 if (!fHasAlpha)
1091 {
1092 /* Convert AND mask to the alpha channel: */
1093 uchar byte = 0;
1094 for (uint x = 0; x < uWidth; x ++)
1095 {
1096 if (!(x % 8))
1097 byte = *(srcAndMaskPtr ++);
1098 else
1099 byte <<= 1;
1100
1101 if (byte & 0x80)
1102 {
1103 /* Linux doesn't support inverted pixels (XOR ops,
1104 * to be exact) in cursor shapes, so we detect such
1105 * pixels and always replace them with black ones to
1106 * make them visible at least over light colors */
1107 if (dstShapePtr [x] & 0x00FFFFFF)
1108 dstShapePtr [x] = 0xFF000000;
1109 else
1110 dstShapePtr [x] = 0x00000000;
1111 }
1112 else
1113 dstShapePtr [x] |= 0xFF000000;
1114 }
1115 }
1116
1117 srcShapePtr += srcShapePtrScan;
1118 dstShapePtr += uWidth;
1119 }
1120
1121 /* Set the new cursor: */
1122 m_cursor = QCursor(XcursorImageLoadCursor(QX11Info::display(), img));
1123
1124 XcursorImageDestroy(img);
1125 }
1126
1127#elif defined(Q_WS_MAC)
1128
1129 /* Create a ARGB image out of the shape data. */
1130 QImage image (uWidth, uHeight, QImage::Format_ARGB32);
1131 const uint8_t* pbSrcMask = static_cast<const uint8_t*> (srcAndMaskPtr);
1132 unsigned cbSrcMaskLine = RT_ALIGN (uWidth, 8) / 8;
1133 for (unsigned int y = 0; y < uHeight; ++y)
1134 {
1135 for (unsigned int x = 0; x < uWidth; ++x)
1136 {
1137 unsigned int color = ((unsigned int*)srcShapePtr)[y*uWidth+x];
1138 /* If the alpha channel isn't in the shape data, we have to
1139 * create them from the and-mask. This is a bit field where 1
1140 * represent transparency & 0 opaque respectively. */
1141 if (!fHasAlpha)
1142 {
1143 if (!(pbSrcMask[x / 8] & (1 << (7 - (x % 8)))))
1144 color |= 0xff000000;
1145 else
1146 {
1147 /* This isn't quite right, but it's the best we can do I think... */
1148 if (color & 0x00ffffff)
1149 color = 0xff000000;
1150 else
1151 color = 0x00000000;
1152 }
1153 }
1154 image.setPixel (x, y, color);
1155 }
1156 /* Move one scanline forward. */
1157 pbSrcMask += cbSrcMaskLine;
1158 }
1159
1160 /* Set the new cursor: */
1161 m_cursor = cursor(QPixmap::fromImage(image), uXHot, uYHot);
1162 NOREF(srcShapePtrScan);
1163
1164#else
1165
1166# warning "port me"
1167
1168#endif
1169}
1170
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