001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Pavel Dolgov
019: * @version $Revision$
020: */package org.apache.harmony.awt.wtk.linux;
021:
022: import java.util.HashMap;
023: import java.util.Iterator;
024: import java.util.LinkedList;
025:
026: import org.apache.harmony.awt.gl.MultiRectArea;
027: import org.apache.harmony.awt.nativebridge.CLongPointer;
028: import org.apache.harmony.awt.nativebridge.linux.X11;
029: import org.apache.harmony.awt.nativebridge.linux.X11Defs;
030: import org.apache.harmony.awt.wtk.NativeEvent;
031: import org.apache.harmony.awt.wtk.NativeEventQueue;
032: import org.apache.harmony.misc.accessors.ObjectAccessor;
033: import org.apache.harmony.misc.accessors.AccessorFactory;
034:
035: public final class LinuxEventQueue extends NativeEventQueue {
036:
037: public interface Preprocessor {
038: public boolean preprocess(X11.XEvent event);
039: }
040:
041: private static final X11 x11 = X11.getInstance();
042: private static final ObjectAccessor objAccessor = AccessorFactory
043: .getObjectAccessor();
044:
045: final LinuxWindowFactory factory;
046: final long display;
047:
048: private final long performTaskAtom;
049:
050: private final LinkedList preprocessors = new LinkedList();
051: private final X11.XEvent curEvent;
052: /** Pending areas to be painted: Window ID (long) --> MultiRectArea */
053: private final HashMap accumulatedClipRegions = new HashMap();
054:
055: LinuxEventQueue(LinuxWindowFactory factory) {
056: this .factory = factory;
057: display = factory.getDisplay();
058: curEvent = x11.createXEvent(false);
059: performTaskAtom = x11.XInternAtom(display,
060: "org.apache.harmony.awt.wtk.perform_task", 0); //$NON-NLS-1$
061: }
062:
063: public boolean waitEvent() {
064: do {
065: x11.XNextEvent(display, curEvent);
066: } while (preprocessEvent(curEvent));
067:
068: return true;
069: }
070:
071: public void awake() {
072: X11.XEvent event = x11.createXEvent(false);
073:
074: event.set_type(X11Defs.MapNotify);
075: event.get_xany().set_window(getJavaWindow());
076: x11.XSendEvent(display, getJavaWindow(), 0,
077: X11Defs.StructureNotifyMask, event);
078: x11.XFlush(display);
079: }
080:
081: public long getJavaWindow() {
082: return factory.getJavaWindow();
083: }
084:
085: public void dispatchEvent() {
086: enqueue(curEvent);
087: }
088:
089: public void addPreprocessor(Preprocessor preprocessor) {
090: preprocessors.add(preprocessor);
091: }
092:
093: private void enqueue(X11.XEvent xevent) {
094: LinuxEvent event = new LinuxEvent(factory, this , xevent);
095: int eventId = event.getEventId();
096: if (eventId != NativeEvent.ID_PLATFORM) {
097: addEvent(event);
098: }
099: }
100:
101: private boolean preprocessEvent(X11.XEvent event) {
102: for (Iterator i = preprocessors.iterator(); i.hasNext();) {
103: if (((Preprocessor) i.next()).preprocess(event)) {
104: return true;
105: }
106: }
107: if (event.get_type() == X11Defs.ClientMessage) {
108: return preprocessClientEvent(event.get_xclient());
109: }
110: return false;
111: }
112:
113: MultiRectArea getAccumulatedClip(long windowId) {
114: Long id = new Long(windowId);
115: MultiRectArea clip = (MultiRectArea) accumulatedClipRegions
116: .get(id);
117: if (clip == null) {
118: clip = new MultiRectArea();
119: accumulatedClipRegions.put(id, clip);
120: }
121: return clip;
122: }
123:
124: void resetAccumulatedClip(long windowId) {
125: accumulatedClipRegions.remove(new Long(windowId));
126: }
127:
128: public void performTask(Task task) {
129: X11.XEvent e = createPerformTaskEvent(task, true);
130: synchronized (task) {
131: x11.XSendEvent(display, getJavaWindow(), 0, 0, e);
132: x11.XFlush(display);
133: try {
134: task.wait();
135: } catch (InterruptedException ex) {
136: throw new RuntimeException(ex);
137: }
138: }
139: }
140:
141: public void performLater(Task task) {
142: X11.XEvent e = createPerformTaskEvent(task, true);
143: x11.XSendEvent(display, getJavaWindow(), 0, 0, e);
144: x11.XFlush(display);
145: }
146:
147: X11.XEvent createPerformTaskEvent(Task task, boolean wait) {
148: X11.XEvent e = x11.createXEvent(false);
149: long ref = objAccessor.getGlobalReference(task);
150: e.set_type(X11Defs.ClientMessage);
151: X11.XClientMessageEvent xclient = e.get_xclient();
152: xclient.set_message_type(performTaskAtom);
153: CLongPointer data = xclient.get_l();
154: data.set(0, (ref & 0xFFFFFFFF));
155: data.set(1, (ref >> 32));
156: data.set(2, wait ? 1 : 0);
157: return e;
158: }
159:
160: private boolean preprocessClientEvent(
161: X11.XClientMessageEvent xclient) {
162: if (xclient.get_message_type() == performTaskAtom) {
163: performTask(xclient);
164: return true;
165: }
166: return false;
167: }
168:
169: private void performTask(X11.XClientMessageEvent xclient) {
170: CLongPointer data = xclient.get_l();
171:
172: long ref = (data.get(0) & 0xFFFFFFFF) | (data.get(1) << 32);
173: boolean wait = (data.get(2) != 0);
174:
175: Task t = (Task) objAccessor.getObjectFromReference(ref);
176: if (wait) {
177: synchronized (t) {
178: t.perform();
179: t.notify();
180: }
181: } else {
182: t.perform();
183: }
184: objAccessor.releaseGlobalReference(ref);
185: }
186: }
|