1
/* $Id: UICocoaApplication.mm 30154 2010-06-10 16:28:15Z vboxsync $ */
3
* UICocoaApplication - C++ interface to NSApplication for handling -sendEvent.
7
* Copyright (C) 2009-2010 Oracle Corporation
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
#include "UICocoaApplication.h"
20
#include "VBoxUtils-darwin.h"
23
#import <AppKit/NSEvent.h>
24
#import <AppKit/NSApplication.h>
25
#import <Foundation/NSArray.h>
26
#import <AppKit/NSWindow.h>
28
#include <iprt/assert.h>
30
/** Class for tracking a callback. */
31
@interface CallbackData: NSObject
34
/** Mask of events to send to this callback. */
37
PFNVBOXCACALLBACK pfnCallback;
38
/** The user argument. */
41
- (id) initWithMask:(uint32)mask callback:(PFNVBOXCACALLBACK)callback user:(void*)user;
42
@end /* @interface CallbackData */
44
@implementation CallbackData
45
- (id) initWithMask:(uint32)mask callback:(PFNVBOXCACALLBACK)callback user:(void*)user
51
pfnCallback = callback;
56
@end /* @implementation CallbackData */
58
/** Class for event handling */
59
@interface UICocoaApplicationPrivate: NSApplication
61
/** The event mask for which there currently are callbacks. */
63
/** Array of callbacks. */
64
NSMutableArray *m_pCallbacks;
67
- (void)sendEvent:(NSEvent *)theEvent;
68
- (void)setCallback:(uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser;
69
- (void)unsetCallback:(uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser;
70
@end /* @interface UICocoaApplicationPrivate */
72
@implementation UICocoaApplicationPrivate
77
m_pCallbacks = [[NSMutableArray alloc] init];
82
-(void) sendEvent:(NSEvent *)pEvent
85
* Check if the type matches any of the registered callbacks.
87
uint32_t const fMask = m_fMask;
88
#if 0 /* for debugging */
89
::darwinPrintEvent("sendEvent: ", pEvent);
93
NSEventType EvtType = [pEvent type];
94
uint32_t fEvtMask = RT_LIKELY(EvtType < 32) ? RT_BIT_32(EvtType) : 0;
98
* Do the callouts in LIFO order.
100
for (CallbackData *pData in [m_pCallbacks reverseObjectEnumerator])
102
if (pData->fMask & fEvtMask)
104
if (pData->pfnCallback(pEvent, [pEvent eventRef], pData->pvUser))
115
[super sendEvent:pEvent];
119
* Register an event callback.
121
* @param fMask The event mask for which the callback is to be invoked.
122
* @param pfnCallback The callback function.
123
* @param pvUser The user argument.
125
-(void) setCallback: (uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser
127
/* Add the callback data to the array */
128
CallbackData *pData = [[[CallbackData alloc] initWithMask: fMask callback: pfnCallback user: pvUser] autorelease];
129
[m_pCallbacks addObject: pData];
131
/* Update the global mask */
136
* Deregister an event callback.
138
* @param fMask Same as setCallback.
139
* @param pfnCallback Same as setCallback.
140
* @param pvUser Same as setCallback.
142
-(void) unsetCallback: (uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser
145
* Loop the event array LIFO fashion searching for a matching callback.
147
for (CallbackData *pData in [m_pCallbacks reverseObjectEnumerator])
149
if ( pData->pfnCallback == pfnCallback
150
&& pData->pvUser == pvUser
151
&& pData->fMask == fMask)
153
[m_pCallbacks removeObject: pData];
157
uint32_t fNewMask = 0;
158
for (CallbackData *pData in m_pCallbacks)
159
fNewMask |= pData->fMask;
162
@end /* @implementation UICocoaApplicationPrivate */
164
/* C++ singleton for our private NSApplication object */
165
UICocoaApplication* UICocoaApplication::m_pInstance = 0;
168
UICocoaApplication* UICocoaApplication::instance()
171
m_pInstance = new UICocoaApplication();
176
UICocoaApplication::UICocoaApplication()
178
/* Make sure our private NSApplication object is created */
179
m_pNative = (UICocoaApplicationPrivate*)[UICocoaApplicationPrivate sharedApplication];
180
/* Create one auto release pool which is in place for all the
181
initialization and deinitialization stuff. That is when the
182
NSApplication is not running the run loop (there is a separate auto
183
release pool defined). */
184
m_pPool = [[NSAutoreleasePool alloc] init];
187
UICocoaApplication::~UICocoaApplication()
193
void UICocoaApplication::registerForNativeEvents(uint32_t fMask, PFNVBOXCACALLBACK pfnCallback, void *pvUser)
195
[m_pNative setCallback:fMask :pfnCallback :pvUser];
198
void UICocoaApplication::unregisterForNativeEvents(uint32_t fMask, PFNVBOXCACALLBACK pfnCallback, void *pvUser)
200
[m_pNative unsetCallback:fMask :pfnCallback :pvUser];