summaryrefslogtreecommitdiffstats
path: root/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/Callback.java
blob: 5f66ed2bdcf83e4dc74fb54efffc202cd41ac85f (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
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-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, address;
	boolean isStatic, isArrayBased;

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

/**
 * 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) {

	/* Set the callback fields */
	this.object = object;
	this.method = method;
	this.argCount = argCount;
	isStatic = object instanceof Class;
	this.isArrayBased = isArrayBased;
	
	/* Inline the common cases */
	if (isArrayBased) {
		signature = "([I)I"; //$NON-NLS-1$
	} else {
		switch (argCount) {
			case 0: signature = "()I"; break; //$NON-NLS-1$
			case 1: signature = "(I)I"; break; //$NON-NLS-1$
			case 2: signature = "(II)I"; break; //$NON-NLS-1$
			case 3: signature = "(III)I"; break; //$NON-NLS-1$
			case 4: signature = "(IIII)I"; break; //$NON-NLS-1$
			default:
				signature = "("; //$NON-NLS-1$
				for (int i=0; i<argCount; i++) signature += "I"; //$NON-NLS-1$
				signature += ")I"; //$NON-NLS-1$
		}
	}
	
	/* Bind the address */
	address = bind (this);
}

/**
 * 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
 */
static native synchronized int bind (Callback callback);

/**
 * 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 getAddress () {
	return address;
}

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

/**
 * 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 ignore true if callbacks should not 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);

}