~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: UICocoaApplication.mm 30154 2010-06-10 16:28:15Z vboxsync $ */
 
2
/** @file
 
3
 * UICocoaApplication - C++ interface to NSApplication for handling -sendEvent.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 2009-2010 Oracle Corporation
 
8
 *
 
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.
 
16
 */
 
17
 
 
18
/* Local includes */
 
19
#include "UICocoaApplication.h"
 
20
#include "VBoxUtils-darwin.h"
 
21
 
 
22
/* Global includes */
 
23
#import <AppKit/NSEvent.h>
 
24
#import <AppKit/NSApplication.h>
 
25
#import <Foundation/NSArray.h>
 
26
#import <AppKit/NSWindow.h>
 
27
 
 
28
#include <iprt/assert.h>
 
29
 
 
30
/** Class for tracking a callback. */
 
31
@interface CallbackData: NSObject
 
32
{
 
33
@public
 
34
    /** Mask of events to send to this callback. */
 
35
    uint32_t            fMask;
 
36
    /** The callback. */
 
37
    PFNVBOXCACALLBACK   pfnCallback;
 
38
    /** The user argument. */
 
39
    void               *pvUser;
 
40
}
 
41
- (id) initWithMask:(uint32)mask callback:(PFNVBOXCACALLBACK)callback user:(void*)user;
 
42
@end /* @interface CallbackData  */
 
43
 
 
44
@implementation CallbackData
 
45
- (id) initWithMask:(uint32)mask callback:(PFNVBOXCACALLBACK)callback user:(void*)user
 
46
{
 
47
    self = [super init];
 
48
    if (self)
 
49
    {
 
50
        fMask = mask;
 
51
        pfnCallback = callback;
 
52
        pvUser =  user;
 
53
    }
 
54
    return self;
 
55
}
 
56
@end /* @implementation CallbackData  */
 
57
 
 
58
/** Class for event handling */
 
59
@interface UICocoaApplicationPrivate: NSApplication
 
60
{
 
61
    /** The event mask for which there currently are callbacks. */
 
62
    uint32_t        m_fMask;
 
63
    /** Array of callbacks. */
 
64
    NSMutableArray *m_pCallbacks;
 
65
}
 
66
- (id)init;
 
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 */
 
71
 
 
72
@implementation UICocoaApplicationPrivate
 
73
-(id) init
 
74
{
 
75
    self = [super init];
 
76
    if (self)
 
77
        m_pCallbacks = [[NSMutableArray alloc] init];
 
78
 
 
79
    return self;
 
80
}
 
81
 
 
82
-(void) sendEvent:(NSEvent *)pEvent
 
83
{
 
84
    /*
 
85
     * Check if the type matches any of the registered callbacks.
 
86
     */
 
87
    uint32_t const fMask = m_fMask;
 
88
#if 0 /* for debugging */
 
89
    ::darwinPrintEvent("sendEvent: ", pEvent);
 
90
#endif
 
91
    if (fMask != 0)
 
92
    {
 
93
        NSEventType EvtType = [pEvent type];
 
94
        uint32_t fEvtMask = RT_LIKELY(EvtType < 32) ? RT_BIT_32(EvtType) : 0;
 
95
        if (fMask & fEvtMask)
 
96
        {
 
97
            /*
 
98
             * Do the callouts in LIFO order.
 
99
             */
 
100
            for (CallbackData *pData in [m_pCallbacks reverseObjectEnumerator])
 
101
            {
 
102
                if (pData->fMask & fEvtMask)
 
103
                {
 
104
                    if (pData->pfnCallback(pEvent, [pEvent eventRef], pData->pvUser))
 
105
                        return;
 
106
                }
 
107
 
 
108
            }
 
109
        }
 
110
    }
 
111
 
 
112
    /*
 
113
     * Get on with it.
 
114
     */
 
115
    [super sendEvent:pEvent];
 
116
}
 
117
 
 
118
/**
 
119
 * Register an event callback.
 
120
 *
 
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.
 
124
 */
 
125
-(void) setCallback: (uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser
 
126
{
 
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];
 
130
 
 
131
    /* Update the global mask */
 
132
    m_fMask |= fMask;
 
133
}
 
134
 
 
135
/**
 
136
 * Deregister an event callback.
 
137
 *
 
138
 * @param   fMask           Same as setCallback.
 
139
 * @param   pfnCallback     Same as setCallback.
 
140
 * @param   pvUser          Same as setCallback.
 
141
 */
 
142
-(void) unsetCallback: (uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser
 
143
{
 
144
    /*
 
145
     * Loop the event array LIFO fashion searching for a matching callback.
 
146
     */
 
147
    for (CallbackData *pData in [m_pCallbacks reverseObjectEnumerator])
 
148
    {
 
149
        if (   pData->pfnCallback == pfnCallback
 
150
            && pData->pvUser      == pvUser
 
151
            && pData->fMask       == fMask)
 
152
        {
 
153
            [m_pCallbacks removeObject: pData];
 
154
            break;
 
155
        }
 
156
    }
 
157
    uint32_t fNewMask = 0;
 
158
    for (CallbackData *pData in m_pCallbacks)
 
159
        fNewMask |= pData->fMask;
 
160
    m_fMask = fNewMask;
 
161
}
 
162
@end /* @implementation UICocoaApplicationPrivate */
 
163
 
 
164
/* C++ singleton for our private NSApplication object */
 
165
UICocoaApplication* UICocoaApplication::m_pInstance = 0;
 
166
 
 
167
/* static */
 
168
UICocoaApplication* UICocoaApplication::instance()
 
169
{
 
170
    if (!m_pInstance)
 
171
        m_pInstance = new UICocoaApplication();
 
172
 
 
173
    return m_pInstance;
 
174
}
 
175
 
 
176
UICocoaApplication::UICocoaApplication()
 
177
{
 
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];
 
185
}
 
186
 
 
187
UICocoaApplication::~UICocoaApplication()
 
188
{
 
189
    [m_pNative release];
 
190
    [m_pPool release];
 
191
}
 
192
 
 
193
void UICocoaApplication::registerForNativeEvents(uint32_t fMask, PFNVBOXCACALLBACK pfnCallback, void *pvUser)
 
194
{
 
195
    [m_pNative setCallback:fMask :pfnCallback :pvUser];
 
196
}
 
197
 
 
198
void UICocoaApplication::unregisterForNativeEvents(uint32_t fMask, PFNVBOXCACALLBACK pfnCallback, void *pvUser)
 
199
{
 
200
    [m_pNative unsetCallback:fMask :pfnCallback :pvUser];
 
201
}
 
202