summaryrefslogtreecommitdiffstats
path: root/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/Callback.java
blob: 145d49c2f51455052da2b642d2bb6aab4b672862 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.internal;


/**
 * Instances of this class represent entry points into Java
 * which can be invoked from operating system level callback
 * routines.
 * <p>
 * IMPORTANT: A callback is only valid when invoked on the
 * thread which created it. The results are undefined (and
 * typically bad) when a callback is passed out to the 
 * operating system (or other code) in such a way that the
 * callback is called from a different thread.
 */

public class Callback {
	
	Object object;
	String method, signature;
	int argCount;
	int /*long*/ address, errorResult;
	boolean isStatic, isArrayBased;

	/* Load the SWT library */
	static {
		Library.loadLibrary ("swt"); //$NON-NLS-1$
	}

	static final int PTR_SIZEOF = PTR_sizeof();
	static final String PTR_SIGNATURE = PTR_SIZEOF == 4 ? "I" : "J"; //$NON-NLS-1$  //$NON-NLS-2$
	static final String SIGNATURE_0 = getSignature(0);
	static final String SIGNATURE_1 = getSignature(1);
	static final String SIGNATURE_2 = getSignature(2);
	static final String SIGNATURE_3 = getSignature(3);
	static final String SIGNATURE_4 = getSignature(4);
	static final String SIGNATURE_N = "(["+PTR_SIGNATURE+")"+PTR_SIGNATURE; //$NON-NLS-1$  //$NON-NLS-2$

/**
 * Constructs a new instance of this class given an object
 * to send the message to, a string naming the method to
 * invoke and an argument count. Note that, if the object
 * is an instance of <code>Class</code> it is assumed that
 * the method is a static method on that class.
 *
 * @param object the object to send the message to
 * @param method the name of the method to invoke
 * @param argCount the number of arguments that the method takes
 */
public Callback (Object object, String method, int argCount) {
	this (object, method, argCount, false);
}

/**
 * Constructs a new instance of this class given an object
 * to send the message to, a string naming the method to
 * invoke, an argument count and a flag indicating whether
 * or not the arguments will be passed in an array. Note 
 * that, if the object is an instance of <code>Class</code>
 * it is assumed that the method is a static method on that
 * class.
 *
 * @param object the object to send the message to
 * @param method the name of the method to invoke
 * @param argCount the number of arguments that the method takes
 * @param isArrayBased <code>true</code> if the arguments should be passed in an array and false otherwise
 */
public Callback (Object object, String method, int argCount, boolean isArrayBased) {
	this (object, method, argCount, isArrayBased, 0);
}

/**
 * Constructs a new instance of this class given an object
 * to send the message to, a string naming the method to
 * invoke, an argument count, a flag indicating whether
 * or not the arguments will be passed in an array and a value
 * to return when an exception happens. Note that, if
 * the object is an instance of <code>Class</code>
 * it is assumed that the method is a static method on that
 * class.
 *
 * @param object the object to send the message to
 * @param method the name of the method to invoke
 * @param argCount the number of arguments that the method takes
 * @param isArrayBased <code>true</code> if the arguments should be passed in an array and false otherwise
 * @param errorResult the return value if the java code throws an exception
 */
public Callback (Object object, String method, int argCount, boolean isArrayBased, int /*long*/ errorResult) {

	/* Set the callback fields */
	this.object = object;
	this.method = method;
	this.argCount = argCount;
	this.isStatic = object instanceof Class;
	this.isArrayBased = isArrayBased;
	this.errorResult = errorResult;
	
	/* Inline the common cases */
	if (isArrayBased) {
		signature = SIGNATURE_N;
	} else {
		switch (argCount) {
			case 0: signature = SIGNATURE_0; break; //$NON-NLS-1$
			case 1: signature = SIGNATURE_1; break; //$NON-NLS-1$
			case 2: signature = SIGNATURE_2; break; //$NON-NLS-1$
			case 3: signature = SIGNATURE_3; break; //$NON-NLS-1$
			case 4: signature = SIGNATURE_4; break; //$NON-NLS-1$
			default:
				signature = getSignature(argCount);
		}
	}
	
	/* Bind the address */
	address = bind (this, object, method, signature, argCount, isStatic, isArrayBased, errorResult);
}

static final native int PTR_sizeof ();

/**
 * Allocates the native level resources associated with the
 * callback. This method is only invoked from within the
 * constructor for the argument.
 *
 * @param callback the callback to bind
 * @param object the callback's object
 * @param method the callback's method
 * @param signature the callback's method signature
 * @param argCount the callback's method argument count
 * @param isStatic whether the callback's method is static
 * @param isArrayBased whether the callback's method is array based
 * @param errorResult the callback's error result
 */
static native synchronized int /*long*/ bind (Callback callback, Object object, String method, String signature, int argCount, boolean isStatic, boolean isArrayBased, int /*long*/ errorResult);

/**
 * Releases the native level resources associated with the callback,
 * and removes all references between the callback and
 * other objects. This helps to prevent (bad) application code
 * from accidentally holding onto extraneous garbage.
 */
public void dispose () {
	if (object == null) return;
	unbind (this);
	object = method = signature = null;
	address = 0;
}

/**
 * Returns the address of a block of machine code which will
 * invoke the callback represented by the receiver.
 *
 * @return the callback address
 */
public int /*long*/ getAddress () {
	return address;
}

/**
 * Returns the SWT platform name.
 *
 * @return the platform name of the currently running SWT
 */
public static native String getPlatform ();

/**
 * Returns the number of times the system has been recursively entered
 * through a callback.
 * <p>
 * Note: This should not be called by application code.
 * </p>
 * 
 * @return the entry count
 * 
 * @since 2.1
 */
public static native int getEntryCount ();

static String getSignature(int argCount) {
	String signature = "("; //$NON-NLS-1$
	for (int i = 0; i < argCount; i++) signature += PTR_SIGNATURE;
	signature += ")" + PTR_SIGNATURE; //$NON-NLS-1$
	return signature;
}

/**
 * Indicates whether or not callbacks which are triggered at the
 * native level should cause the messages described by the matching
 * <code>Callback</code> objects to be invoked. This method is used
 * to safely shut down SWT when it is run within environments
 * which can generate spurious events.
 * <p>
 * Note: This should not be called by application code.
 * </p>
 *
 * @param enable true if callbacks should be invoked
 */
public static final native synchronized void setEnabled (boolean enable);

/**
 * Returns whether or not callbacks which are triggered at the
 * native level should cause the messages described by the matching
 * <code>Callback</code> objects to be invoked. This method is used
 * to safely shut down SWT when it is run within environments
 * which can generate spurious events.
 * <p>
 * Note: This should not be called by application code.
 * </p>
 *
 * @return true if callbacks should not be invoked
 */
public static final native synchronized boolean getEnabled ();

/**
 * This might be called directly from native code in environments
 * which can generate spurious events. Check before removing it.
 *
 * @deprecated
 *
 * @param ignore true if callbacks should not be invoked
 */
static final void ignoreCallbacks (boolean ignore) {
	setEnabled (!ignore);
} 

/**
 * Immediately wipes out all native level state associated
 * with <em>all</em> callbacks.
 * <p>
 * <b>WARNING:</b> This operation is <em>extremely</em> dangerous,
 * and should never be performed by application code.
 * </p>
 */
public static final native synchronized void reset ();

/**
 * Releases the native level resources associated with the callback.
 *
 * @see #dispose
 */
static final native synchronized void unbind (Callback callback);

}