VirtualBox

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

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

FE/Qt4: New running VM core: restoring guest size hint on exiting fullscreen/seamless modes.

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