author | son |
Thu, 13 Mar 2008 17:08:15 +0300 | |
changeset 116 | 9c43d9eb1029 |
parent 2 | 90ce3da70b43 |
child 439 | 3488710b02f8 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
116
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
2 |
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Sun designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Sun in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 |
* have any questions. |
|
24 |
*/ |
|
25 |
||
26 |
package sun.awt.X11; |
|
27 |
||
28 |
import java.awt.*; |
|
29 |
import java.awt.event.*; |
|
30 |
import java.awt.peer.ComponentPeer; |
|
31 |
import java.awt.image.ColorModel; |
|
32 |
||
33 |
import java.lang.ref.WeakReference; |
|
34 |
||
35 |
import java.lang.reflect.Field; |
|
36 |
import java.lang.reflect.Method; |
|
37 |
||
38 |
import java.util.logging.Level; |
|
39 |
import java.util.logging.Logger; |
|
40 |
||
41 |
import sun.awt.*; |
|
42 |
||
43 |
import sun.awt.image.PixelConverter; |
|
44 |
||
45 |
import sun.java2d.SunGraphics2D; |
|
46 |
import sun.java2d.SurfaceData; |
|
47 |
||
48 |
public class XWindow extends XBaseWindow implements X11ComponentPeer { |
|
49 |
private static Logger log = Logger.getLogger("sun.awt.X11.XWindow"); |
|
50 |
private static Logger insLog = Logger.getLogger("sun.awt.X11.insets.XWindow"); |
|
51 |
private static Logger eventLog = Logger.getLogger("sun.awt.X11.event.XWindow"); |
|
52 |
private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XWindow"); |
|
53 |
private static Logger keyEventLog = Logger.getLogger("sun.awt.X11.kye.XWindow"); |
|
54 |
/* If a motion comes in while a multi-click is pending, |
|
55 |
* allow a smudge factor so that moving the mouse by a small |
|
56 |
* amount does not wipe out the multi-click state variables. |
|
57 |
*/ |
|
58 |
private final static int AWT_MULTICLICK_SMUDGE = 4; |
|
59 |
// ButtonXXX events stuff |
|
60 |
static int rbutton = 0; |
|
61 |
static int lastX = 0, lastY = 0; |
|
62 |
static long lastTime = 0; |
|
63 |
static long lastButton = 0; |
|
64 |
static WeakReference lastWindowRef = null; |
|
65 |
static int clickCount = 0; |
|
66 |
||
67 |
// used to check if we need to re-create surfaceData. |
|
68 |
int oldWidth = -1; |
|
69 |
int oldHeight = -1; |
|
70 |
||
71 |
||
72 |
protected X11GraphicsConfig graphicsConfig; |
|
73 |
protected AwtGraphicsConfigData graphicsConfigData; |
|
74 |
||
75 |
private boolean reparented; |
|
76 |
||
77 |
XWindow parent; |
|
78 |
||
79 |
Component target; |
|
80 |
||
81 |
private static int JAWT_LOCK_ERROR=0x00000001; |
|
82 |
private static int JAWT_LOCK_CLIP_CHANGED=0x00000002; |
|
83 |
private static int JAWT_LOCK_BOUNDS_CHANGED=0x00000004; |
|
84 |
private static int JAWT_LOCK_SURFACE_CHANGED=0x00000008; |
|
85 |
private int drawState = JAWT_LOCK_CLIP_CHANGED | |
|
86 |
JAWT_LOCK_BOUNDS_CHANGED | |
|
87 |
JAWT_LOCK_SURFACE_CHANGED; |
|
88 |
||
89 |
public static final String TARGET = "target", |
|
90 |
REPARENTED = "reparented"; // whether it is reparented by default |
|
91 |
||
92 |
SurfaceData surfaceData; |
|
93 |
||
94 |
XRepaintArea paintArea; |
|
116
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
95 |
|
2 | 96 |
// fallback default font object |
116
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
97 |
private static Font defaultFont; |
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
98 |
|
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
99 |
static synchronized Font getDefaultFont() { |
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
100 |
if (null == defaultFont) { |
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
101 |
defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); |
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
102 |
} |
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
103 |
return defaultFont; |
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
104 |
} |
2 | 105 |
|
106 |
/* |
|
107 |
* Keeps all buttons which were pressed at the time of the last mouse |
|
108 |
* drag until all buttons will be released, contains state as bit masks |
|
109 |
* Button1Mask, Button2Mask, Button3Mask |
|
110 |
*/ |
|
111 |
private int mouseDragState = 0; |
|
112 |
||
113 |
native int getNativeColor(Color clr, GraphicsConfiguration gc); |
|
114 |
native void getWMInsets(long window, long left, long top, long right, long bottom, long border); |
|
115 |
native long getTopWindow(long window, long rootWin); |
|
116 |
native void getWindowBounds(long window, long x, long y, long width, long height); |
|
117 |
private native static void initIDs(); |
|
118 |
||
119 |
private static Field isPostedField; |
|
120 |
static { |
|
121 |
initIDs(); |
|
122 |
} |
|
123 |
||
124 |
XWindow(XCreateWindowParams params) { |
|
125 |
super(params); |
|
126 |
} |
|
127 |
||
128 |
XWindow() { |
|
129 |
} |
|
130 |
||
131 |
XWindow(long parentWindow, Rectangle bounds) { |
|
132 |
super(new XCreateWindowParams(new Object[] { |
|
133 |
BOUNDS, bounds, |
|
134 |
PARENT_WINDOW, Long.valueOf(parentWindow)})); |
|
135 |
} |
|
136 |
||
137 |
XWindow(Component target, long parentWindow, Rectangle bounds) { |
|
138 |
super(new XCreateWindowParams(new Object[] { |
|
139 |
BOUNDS, bounds, |
|
140 |
PARENT_WINDOW, Long.valueOf(parentWindow), |
|
141 |
TARGET, target})); |
|
142 |
} |
|
143 |
||
144 |
XWindow(Component target, long parentWindow) { |
|
145 |
this(target, parentWindow, target.getBounds()); |
|
146 |
} |
|
147 |
||
148 |
XWindow(Component target) { |
|
149 |
this(target, (target.getParent() == null) ? 0 : getParentWindowID(target), target.getBounds()); |
|
150 |
} |
|
151 |
||
152 |
XWindow(Object target) { |
|
153 |
this(null, 0, null); |
|
154 |
} |
|
155 |
||
156 |
/* This create is used by the XEmbeddedFramePeer since it has to create the window |
|
157 |
as a child of the netscape window. This netscape window is passed in as wid */ |
|
158 |
XWindow(long parentWindow) { |
|
159 |
super(new XCreateWindowParams(new Object[] { |
|
160 |
PARENT_WINDOW, Long.valueOf(parentWindow), |
|
161 |
REPARENTED, Boolean.TRUE, |
|
162 |
EMBEDDED, Boolean.TRUE})); |
|
163 |
} |
|
164 |
||
165 |
protected void initGraphicsConfiguration() { |
|
166 |
graphicsConfig = (X11GraphicsConfig) target.getGraphicsConfiguration(); |
|
167 |
graphicsConfigData = new AwtGraphicsConfigData(graphicsConfig.getAData()); |
|
168 |
} |
|
169 |
||
170 |
void preInit(XCreateWindowParams params) { |
|
171 |
super.preInit(params); |
|
172 |
reparented = Boolean.TRUE.equals(params.get(REPARENTED)); |
|
173 |
||
174 |
target = (Component)params.get(TARGET); |
|
175 |
||
176 |
initGraphicsConfiguration(); |
|
177 |
||
178 |
AwtGraphicsConfigData gData = getGraphicsConfigurationData(); |
|
179 |
X11GraphicsConfig config = (X11GraphicsConfig) getGraphicsConfiguration(); |
|
180 |
XVisualInfo visInfo = gData.get_awt_visInfo(); |
|
181 |
params.putIfNull(EVENT_MASK, KeyPressMask | KeyReleaseMask |
|
182 |
| FocusChangeMask | ButtonPressMask | ButtonReleaseMask |
|
183 |
| EnterWindowMask | LeaveWindowMask | PointerMotionMask |
|
184 |
| ButtonMotionMask | ExposureMask | StructureNotifyMask); |
|
185 |
||
186 |
if (target != null) { |
|
187 |
params.putIfNull(BOUNDS, target.getBounds()); |
|
188 |
} else { |
|
189 |
params.putIfNull(BOUNDS, new Rectangle(0, 0, MIN_SIZE, MIN_SIZE)); |
|
190 |
} |
|
191 |
params.putIfNull(BORDER_PIXEL, Long.valueOf(0)); |
|
192 |
getColorModel(); // fix 4948833: this call forces the color map to be initialized |
|
193 |
params.putIfNull(COLORMAP, gData.get_awt_cmap()); |
|
194 |
params.putIfNull(DEPTH, gData.get_awt_depth()); |
|
195 |
params.putIfNull(VISUAL_CLASS, Integer.valueOf((int)XlibWrapper.InputOutput)); |
|
196 |
params.putIfNull(VISUAL, visInfo.get_visual()); |
|
197 |
params.putIfNull(VALUE_MASK, XlibWrapper.CWBorderPixel | XlibWrapper.CWEventMask | XlibWrapper.CWColormap); |
|
198 |
Long parentWindow = (Long)params.get(PARENT_WINDOW); |
|
199 |
if (parentWindow == null || parentWindow.longValue() == 0) { |
|
200 |
XToolkit.awtLock(); |
|
201 |
try { |
|
202 |
int screen = visInfo.get_screen(); |
|
203 |
if (screen != -1) { |
|
204 |
params.add(PARENT_WINDOW, XlibWrapper.RootWindow(XToolkit.getDisplay(), screen)); |
|
205 |
} else { |
|
206 |
params.add(PARENT_WINDOW, XToolkit.getDefaultRootWindow()); |
|
207 |
} |
|
208 |
} finally { |
|
209 |
XToolkit.awtUnlock(); |
|
210 |
} |
|
211 |
} |
|
212 |
||
213 |
paintArea = new XRepaintArea(); |
|
214 |
if (target != null) { |
|
215 |
this.parent = getParentXWindowObject(target.getParent()); |
|
216 |
} |
|
217 |
||
218 |
params.putIfNull(BACKING_STORE, XToolkit.getBackingStoreType()); |
|
219 |
} |
|
220 |
||
221 |
void postInit(XCreateWindowParams params) { |
|
222 |
super.postInit(params); |
|
223 |
||
224 |
setWMClass(getWMClass()); |
|
225 |
||
226 |
surfaceData = graphicsConfig.createSurfaceData(this); |
|
227 |
Color c; |
|
228 |
if (target != null && (c = target.getBackground()) != null) { |
|
229 |
// We need a version of setBackground that does not call repaint !! |
|
230 |
// and one that does not get overridden. The problem is that in postInit |
|
231 |
// we call setBackground and we dont have all the stuff initialized to |
|
232 |
// do a full paint for most peers. So we cannot call setBackground in postInit. |
|
233 |
// instead we need to call xSetBackground. |
|
234 |
xSetBackground(c); |
|
235 |
} |
|
236 |
} |
|
237 |
||
238 |
public GraphicsConfiguration getGraphicsConfiguration() { |
|
239 |
if (graphicsConfig == null) { |
|
240 |
initGraphicsConfiguration(); |
|
241 |
} |
|
242 |
return graphicsConfig; |
|
243 |
} |
|
244 |
||
245 |
public AwtGraphicsConfigData getGraphicsConfigurationData() { |
|
246 |
if (graphicsConfigData == null) { |
|
247 |
initGraphicsConfiguration(); |
|
248 |
} |
|
249 |
return graphicsConfigData; |
|
250 |
} |
|
251 |
||
252 |
protected String[] getWMClass() { |
|
253 |
return new String[] {XToolkit.getCorrectXIDString(getClass().getName()), XToolkit.getAWTAppClassName()}; |
|
254 |
} |
|
255 |
||
256 |
void setReparented(boolean newValue) { |
|
257 |
reparented = newValue; |
|
258 |
} |
|
259 |
||
260 |
boolean isReparented() { |
|
261 |
return reparented; |
|
262 |
} |
|
263 |
||
264 |
static long getParentWindowID(Component target) { |
|
265 |
||
266 |
ComponentPeer peer = target.getParent().getPeer(); |
|
267 |
Component temp = target.getParent(); |
|
268 |
while (!(peer instanceof XWindow)) |
|
269 |
{ |
|
270 |
temp = temp.getParent(); |
|
271 |
peer = temp.getPeer(); |
|
272 |
} |
|
273 |
||
274 |
if (peer != null && peer instanceof XWindow) |
|
275 |
return ((XWindow)peer).getContentWindow(); |
|
276 |
else return 0; |
|
277 |
} |
|
278 |
||
279 |
||
280 |
static XWindow getParentXWindowObject(Component target) { |
|
281 |
if (target == null) return null; |
|
282 |
Component temp = target.getParent(); |
|
283 |
if (temp == null) return null; |
|
284 |
ComponentPeer peer = temp.getPeer(); |
|
285 |
if (peer == null) return null; |
|
286 |
while ((peer != null) && !(peer instanceof XWindow)) |
|
287 |
{ |
|
288 |
temp = temp.getParent(); |
|
289 |
peer = temp.getPeer(); |
|
290 |
} |
|
291 |
if (peer != null && peer instanceof XWindow) |
|
292 |
return (XWindow) peer; |
|
293 |
else return null; |
|
294 |
} |
|
295 |
||
296 |
||
297 |
boolean isParentOf(XWindow win) { |
|
298 |
if (!(target instanceof Container) || win == null || win.getTarget() == null) { |
|
299 |
return false; |
|
300 |
} |
|
301 |
Container parent = ComponentAccessor.getParent_NoClientCode(win.target); |
|
302 |
while (parent != null && parent != target) { |
|
303 |
parent = ComponentAccessor.getParent_NoClientCode(parent); |
|
304 |
} |
|
305 |
return (parent == target); |
|
306 |
} |
|
307 |
||
308 |
public Object getTarget() { |
|
309 |
return target; |
|
310 |
} |
|
311 |
public Component getEventSource() { |
|
312 |
return target; |
|
313 |
} |
|
314 |
||
315 |
public ColorModel getColorModel(int transparency) { |
|
316 |
return graphicsConfig.getColorModel (transparency); |
|
317 |
} |
|
318 |
||
319 |
public ColorModel getColorModel() { |
|
320 |
if (graphicsConfig != null) { |
|
321 |
return graphicsConfig.getColorModel (); |
|
322 |
} |
|
323 |
else { |
|
324 |
return XToolkit.getStaticColorModel(); |
|
325 |
} |
|
326 |
} |
|
327 |
||
328 |
Graphics getGraphics(SurfaceData surfData, Color afore, Color aback, Font afont) { |
|
329 |
if (surfData == null) return null; |
|
330 |
||
331 |
Component target = (Component) this.target; |
|
332 |
||
333 |
/* Fix for bug 4746122. Color and Font shouldn't be null */ |
|
334 |
Color bgColor = aback; |
|
335 |
if (bgColor == null) { |
|
336 |
bgColor = SystemColor.window; |
|
337 |
} |
|
338 |
Color fgColor = afore; |
|
339 |
if (fgColor == null) { |
|
340 |
fgColor = SystemColor.windowText; |
|
341 |
} |
|
342 |
Font font = afont; |
|
343 |
if (font == null) { |
|
116
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
344 |
font = XWindow.getDefaultFont(); |
2 | 345 |
} |
346 |
return new SunGraphics2D(surfData, fgColor, bgColor, font); |
|
347 |
} |
|
348 |
||
349 |
public Graphics getGraphics() { |
|
350 |
return getGraphics(surfaceData, |
|
351 |
target.getForeground(), |
|
352 |
target.getBackground(), |
|
353 |
target.getFont()); |
|
354 |
} |
|
355 |
||
356 |
public FontMetrics getFontMetrics(Font font) { |
|
357 |
return Toolkit.getDefaultToolkit().getFontMetrics(font); |
|
358 |
} |
|
359 |
||
360 |
public Rectangle getTargetBounds() { |
|
361 |
return target.getBounds(); |
|
362 |
} |
|
363 |
||
364 |
/** |
|
365 |
* Returns true if the event has been handled and should not be |
|
366 |
* posted to Java. |
|
367 |
*/ |
|
368 |
boolean prePostEvent(AWTEvent e) { |
|
369 |
return false; |
|
370 |
} |
|
371 |
||
372 |
static Method m_sendMessage; |
|
373 |
static void sendEvent(final AWTEvent e) { |
|
374 |
if (isPostedField == null) { |
|
375 |
isPostedField = SunToolkit.getField(AWTEvent.class, "isPosted"); |
|
376 |
} |
|
377 |
PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() { |
|
378 |
public void run() { |
|
379 |
try { |
|
380 |
isPostedField.setBoolean(e, true); |
|
381 |
} catch (IllegalArgumentException e) { |
|
382 |
assert(false); |
|
383 |
} catch (IllegalAccessException e) { |
|
384 |
assert(false); |
|
385 |
} |
|
386 |
((Component)e.getSource()).dispatchEvent(e); |
|
387 |
} |
|
388 |
}, PeerEvent.ULTIMATE_PRIORITY_EVENT); |
|
389 |
if (focusLog.isLoggable(Level.FINER) && (e instanceof FocusEvent)) focusLog.finer("Sending " + e); |
|
390 |
XToolkit.postEvent(XToolkit.targetToAppContext(e.getSource()), pe); |
|
391 |
} |
|
392 |
||
393 |
||
394 |
/* |
|
395 |
* Post an event to the event queue. |
|
396 |
*/ |
|
397 |
// NOTE: This method may be called by privileged threads. |
|
398 |
// DO NOT INVOKE CLIENT CODE ON THIS THREAD! |
|
399 |
void postEvent(AWTEvent event) { |
|
400 |
XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event); |
|
401 |
} |
|
402 |
||
403 |
static void postEventStatic(AWTEvent event) { |
|
404 |
XToolkit.postEvent(XToolkit.targetToAppContext(event.getSource()), event); |
|
405 |
} |
|
406 |
||
407 |
public void postEventToEventQueue(final AWTEvent event) { |
|
408 |
//fix for 6239938 : Choice drop-down does not disappear when it loses focus, on XToolkit |
|
409 |
if (!prePostEvent(event)) { |
|
410 |
//event hasn't been handled and must be posted to EventQueue |
|
411 |
postEvent(event); |
|
412 |
} |
|
413 |
} |
|
414 |
||
415 |
// overriden in XCanvasPeer |
|
416 |
protected boolean doEraseBackground() { |
|
417 |
return true; |
|
418 |
} |
|
419 |
||
420 |
// We need a version of setBackground that does not call repaint !! |
|
421 |
// and one that does not get overridden. The problem is that in postInit |
|
422 |
// we call setBackground and we dont have all the stuff initialized to |
|
423 |
// do a full paint for most peers. So we cannot call setBackground in postInit. |
|
424 |
final public void xSetBackground(Color c) { |
|
425 |
XToolkit.awtLock(); |
|
426 |
try { |
|
427 |
winBackground(c); |
|
428 |
// fix for 6558510: handle sun.awt.noerasebackground flag, |
|
429 |
// see doEraseBackground() and preInit() methods in XCanvasPeer |
|
430 |
if (!doEraseBackground()) { |
|
431 |
return; |
|
432 |
} |
|
433 |
// 6304250: XAWT: Items in choice show a blue border on OpenGL + Solaris10 when background color is set |
|
434 |
// Note: When OGL is enabled, surfaceData.pixelFor() will not |
|
435 |
// return a pixel value appropriate for passing to |
|
436 |
// XSetWindowBackground(). Therefore, we will use the ColorModel |
|
437 |
// for this component in order to calculate a pixel value from |
|
438 |
// the given RGB value. |
|
439 |
ColorModel cm = getColorModel(); |
|
440 |
int pixel = PixelConverter.instance.rgbToPixel(c.getRGB(), cm); |
|
441 |
XlibWrapper.XSetWindowBackground(XToolkit.getDisplay(), getContentWindow(), pixel); |
|
442 |
} |
|
443 |
finally { |
|
444 |
XToolkit.awtUnlock(); |
|
445 |
} |
|
446 |
} |
|
447 |
||
448 |
public void setBackground(Color c) { |
|
449 |
xSetBackground(c); |
|
450 |
} |
|
451 |
||
452 |
Color backgroundColor; |
|
453 |
void winBackground(Color c) { |
|
454 |
backgroundColor = c; |
|
455 |
} |
|
456 |
||
457 |
public Color getWinBackground() { |
|
458 |
Color c = null; |
|
459 |
||
460 |
if (backgroundColor != null) { |
|
461 |
c = backgroundColor; |
|
462 |
} else if (parent != null) { |
|
463 |
c = parent.getWinBackground(); |
|
464 |
} |
|
465 |
||
466 |
if (c instanceof SystemColor) { |
|
467 |
c = new Color(c.getRGB()); |
|
468 |
} |
|
469 |
||
470 |
return c; |
|
471 |
} |
|
472 |
||
473 |
public boolean isEmbedded() { |
|
474 |
return embedded; |
|
475 |
} |
|
476 |
||
477 |
public void repaint(int x,int y, int width, int height) { |
|
478 |
if (!isVisible()) { |
|
479 |
return; |
|
480 |
} |
|
481 |
Graphics g = getGraphics(); |
|
482 |
if (g != null) { |
|
483 |
try { |
|
484 |
g.setClip(x,y,width,height); |
|
485 |
paint(g); |
|
486 |
} finally { |
|
487 |
g.dispose(); |
|
488 |
} |
|
489 |
} |
|
490 |
} |
|
491 |
||
492 |
public void repaint() { |
|
493 |
if (!isVisible()) { |
|
494 |
return; |
|
495 |
} |
|
496 |
Graphics g = getGraphics(); |
|
497 |
if (g != null) { |
|
498 |
try { |
|
499 |
paint(g); |
|
500 |
} finally { |
|
501 |
g.dispose(); |
|
502 |
} |
|
503 |
} |
|
504 |
} |
|
505 |
||
506 |
void paint(Graphics g) { |
|
507 |
} |
|
508 |
||
509 |
//used by Peers to avoid flickering withing paint() |
|
510 |
protected void flush(){ |
|
511 |
XToolkit.awtLock(); |
|
512 |
try { |
|
513 |
XlibWrapper.XFlush(XToolkit.getDisplay()); |
|
514 |
} finally { |
|
515 |
XToolkit.awtUnlock(); |
|
516 |
} |
|
517 |
} |
|
518 |
||
519 |
public void popup(int x, int y, int width, int height) { |
|
520 |
// TBD: grab the pointer |
|
521 |
xSetBounds(x, y, width, height); |
|
522 |
} |
|
523 |
||
524 |
public void handleExposeEvent(XEvent xev) { |
|
525 |
super.handleExposeEvent(xev); |
|
526 |
XExposeEvent xe = xev.get_xexpose(); |
|
527 |
if (isEventDisabled(xev)) { |
|
528 |
return; |
|
529 |
} |
|
530 |
int x = xe.get_x(); |
|
531 |
int y = xe.get_y(); |
|
532 |
int w = xe.get_width(); |
|
533 |
int h = xe.get_height(); |
|
534 |
||
535 |
Component target = (Component)getEventSource(); |
|
536 |
||
537 |
if (!ComponentAccessor.getIgnoreRepaint(target) |
|
538 |
&& ComponentAccessor.getWidth(target) != 0 |
|
539 |
&& ComponentAccessor.getHeight(target) != 0) |
|
540 |
{ |
|
541 |
handleExposeEvent(target, x, y, w, h); |
|
542 |
} |
|
543 |
} |
|
544 |
||
545 |
public void handleExposeEvent(Component target, int x, int y, int w, int h) { |
|
546 |
PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher(). |
|
547 |
createPaintEvent(target, x, y, w, h); |
|
548 |
if (event != null) { |
|
549 |
postEventToEventQueue(event); |
|
550 |
} |
|
551 |
} |
|
552 |
||
553 |
static int getModifiers(int state, int button, int keyCode) { |
|
554 |
int modifiers = 0; |
|
555 |
||
556 |
if (((state & XlibWrapper.ShiftMask) != 0) ^ (keyCode == KeyEvent.VK_SHIFT)) { |
|
557 |
modifiers |= InputEvent.SHIFT_DOWN_MASK; |
|
558 |
} |
|
559 |
if (((state & XlibWrapper.ControlMask) != 0) ^ (keyCode == KeyEvent.VK_CONTROL)) { |
|
560 |
modifiers |= InputEvent.CTRL_DOWN_MASK; |
|
561 |
} |
|
562 |
if (((state & XToolkit.metaMask) != 0) ^ (keyCode == KeyEvent.VK_META)) { |
|
563 |
modifiers |= InputEvent.META_DOWN_MASK; |
|
564 |
} |
|
565 |
if (((state & XToolkit.altMask) != 0) ^ (keyCode == KeyEvent.VK_ALT)) { |
|
566 |
modifiers |= InputEvent.ALT_DOWN_MASK; |
|
567 |
} |
|
568 |
if (((state & XToolkit.modeSwitchMask) != 0) ^ (keyCode == KeyEvent.VK_ALT_GRAPH)) { |
|
569 |
modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; |
|
570 |
} |
|
571 |
if (((state & XlibWrapper.Button1Mask) != 0) ^ (button == MouseEvent.BUTTON1)) { |
|
572 |
modifiers |= InputEvent.BUTTON1_DOWN_MASK; |
|
573 |
} |
|
574 |
if (((state & XlibWrapper.Button2Mask) != 0) ^ (button == MouseEvent.BUTTON2)) { |
|
575 |
modifiers |= InputEvent.BUTTON2_DOWN_MASK; |
|
576 |
} |
|
577 |
if (((state & XlibWrapper.Button3Mask) != 0) ^ (button == MouseEvent.BUTTON3)) { |
|
578 |
modifiers |= InputEvent.BUTTON3_DOWN_MASK; |
|
579 |
} |
|
580 |
return modifiers; |
|
581 |
} |
|
582 |
||
583 |
static int getXModifiers(AWTKeyStroke stroke) { |
|
584 |
int mods = stroke.getModifiers(); |
|
585 |
int res = 0; |
|
586 |
if ((mods & (InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK)) != 0) { |
|
587 |
res |= XToolkit.ShiftMask; |
|
588 |
} |
|
589 |
if ((mods & (InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK)) != 0) { |
|
590 |
res |= XToolkit.ControlMask; |
|
591 |
} |
|
592 |
if ((mods & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_MASK)) != 0) { |
|
593 |
res |= XToolkit.altMask; |
|
594 |
} |
|
595 |
if ((mods & (InputEvent.META_DOWN_MASK | InputEvent.META_MASK)) != 0) { |
|
596 |
res |= XToolkit.metaMask; |
|
597 |
} |
|
598 |
if ((mods & (InputEvent.ALT_GRAPH_DOWN_MASK | InputEvent.ALT_GRAPH_MASK)) != 0) { |
|
599 |
res |= XToolkit.modeSwitchMask; |
|
600 |
} |
|
601 |
return res; |
|
602 |
} |
|
603 |
||
604 |
private static int getButtonMask(long mouseButton) { |
|
605 |
if (mouseButton == XlibWrapper.Button1) { |
|
606 |
return XlibWrapper.Button1Mask; |
|
607 |
} else if (mouseButton == XlibWrapper.Button2) { |
|
608 |
return XlibWrapper.Button2Mask; |
|
609 |
} else if (mouseButton == XlibWrapper.Button3) { |
|
610 |
return XlibWrapper.Button3Mask; |
|
611 |
} |
|
612 |
return 0; |
|
613 |
} |
|
614 |
||
615 |
/** |
|
616 |
* Returns true if this event is disabled and shouldn't be passed to Java. |
|
617 |
* Default implementation returns false for all events. |
|
618 |
*/ |
|
619 |
static int getRightButtonNumber() { |
|
620 |
if (rbutton == 0) { // not initialized yet |
|
621 |
XToolkit.awtLock(); |
|
622 |
try { |
|
623 |
rbutton = XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), XlibWrapper.ibuffer, 3); |
|
624 |
} |
|
625 |
finally { |
|
626 |
XToolkit.awtUnlock(); |
|
627 |
} |
|
628 |
} |
|
629 |
return rbutton; |
|
630 |
} |
|
631 |
||
632 |
static int getMouseMovementSmudge() { |
|
633 |
//TODO: It's possible to read corresponding settings |
|
634 |
return AWT_MULTICLICK_SMUDGE; |
|
635 |
} |
|
636 |
||
637 |
public void handleButtonPressRelease(XEvent xev) { |
|
638 |
super.handleButtonPressRelease(xev); |
|
639 |
XButtonEvent xbe = xev.get_xbutton(); |
|
640 |
if (isEventDisabled(xev)) { |
|
641 |
return; |
|
642 |
} |
|
643 |
if (eventLog.isLoggable(Level.FINE)) eventLog.fine(xbe.toString()); |
|
644 |
long when; |
|
645 |
int modifiers; |
|
646 |
boolean popupTrigger = false; |
|
647 |
int button=0; |
|
648 |
boolean wheel_mouse = false; |
|
649 |
long lbutton = xbe.get_button(); |
|
650 |
int type = xev.get_type(); |
|
651 |
when = xbe.get_time(); |
|
652 |
long jWhen = XToolkit.nowMillisUTC_offset(when); |
|
653 |
||
654 |
int x = xbe.get_x(); |
|
655 |
int y = xbe.get_y(); |
|
656 |
if (xev.get_xany().get_window() != window) { |
|
657 |
Point localXY = toLocal(xbe.get_x_root(), xbe.get_y_root()); |
|
658 |
x = localXY.x; |
|
659 |
y = localXY.y; |
|
660 |
} |
|
661 |
||
662 |
if (type == XlibWrapper.ButtonPress) { |
|
663 |
XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null); |
|
664 |
/* |
|
665 |
multiclick checking |
|
666 |
*/ |
|
667 |
if (eventLog.isLoggable(Level.FINEST)) eventLog.finest("lastWindow = " + lastWindow + ", lastButton " |
|
668 |
+ lastButton + ", lastTime " + lastTime + ", multiClickTime " |
|
669 |
+ XToolkit.getMultiClickTime()); |
|
670 |
if (lastWindow == this && lastButton == lbutton && (when - lastTime) < XToolkit.getMultiClickTime()) { |
|
671 |
clickCount++; |
|
672 |
} else { |
|
673 |
clickCount = 1; |
|
674 |
lastWindowRef = new WeakReference(this); |
|
675 |
lastButton = lbutton; |
|
676 |
lastX = x; |
|
677 |
lastY = y; |
|
678 |
} |
|
679 |
lastTime = when; |
|
680 |
||
681 |
||
682 |
/* |
|
683 |
Check for popup trigger !! |
|
684 |
*/ |
|
685 |
if (lbutton == getRightButtonNumber() || lbutton > 2) { |
|
686 |
popupTrigger = true; |
|
687 |
} else { |
|
688 |
popupTrigger = false; |
|
689 |
} |
|
690 |
} |
|
691 |
||
692 |
if (lbutton == XlibWrapper.Button1) |
|
693 |
button = MouseEvent.BUTTON1; |
|
694 |
else if (lbutton == XlibWrapper.Button2 ) |
|
695 |
button = MouseEvent.BUTTON2; |
|
696 |
else if (lbutton == XlibWrapper.Button3) |
|
697 |
button = MouseEvent.BUTTON3; |
|
698 |
else if (lbutton == XlibWrapper.Button4) { |
|
699 |
button = 4; |
|
700 |
wheel_mouse = true; |
|
701 |
} else if (lbutton == XlibWrapper.Button5) { |
|
702 |
button = 5; |
|
703 |
wheel_mouse = true; |
|
704 |
} |
|
705 |
||
706 |
modifiers = getModifiers(xbe.get_state(),button,0); |
|
707 |
||
708 |
if (!wheel_mouse) { |
|
709 |
MouseEvent me = new MouseEvent((Component)getEventSource(), |
|
710 |
type == XlibWrapper.ButtonPress ? MouseEvent.MOUSE_PRESSED : MouseEvent.MOUSE_RELEASED, |
|
711 |
jWhen,modifiers, x, y, |
|
712 |
xbe.get_x_root(), |
|
713 |
xbe.get_y_root(), |
|
714 |
clickCount,popupTrigger,button); |
|
715 |
||
716 |
postEventToEventQueue(me); |
|
717 |
||
718 |
if (((mouseDragState & getButtonMask(lbutton)) == 0) && // No up-button in the drag-state |
|
719 |
(type == XlibWrapper.ButtonRelease)) |
|
720 |
{ |
|
721 |
postEventToEventQueue(me = new MouseEvent((Component)getEventSource(), |
|
722 |
MouseEvent.MOUSE_CLICKED, |
|
723 |
jWhen, |
|
724 |
modifiers, |
|
725 |
x, y, |
|
726 |
xbe.get_x_root(), |
|
727 |
xbe.get_y_root(), |
|
728 |
clickCount, |
|
729 |
false, button)); |
|
730 |
} |
|
731 |
||
732 |
} |
|
733 |
else { |
|
734 |
if (xev.get_type() == XlibWrapper.ButtonPress) { |
|
735 |
MouseWheelEvent mwe = new MouseWheelEvent((Component)getEventSource(),MouseEvent.MOUSE_WHEEL, jWhen, |
|
736 |
modifiers, |
|
737 |
x, y, |
|
738 |
xbe.get_x_root(), |
|
739 |
xbe.get_y_root(), |
|
740 |
clickCount,false,MouseWheelEvent.WHEEL_UNIT_SCROLL, |
|
741 |
3,button==4 ? -1 : 1); |
|
742 |
postEventToEventQueue(mwe); |
|
743 |
} |
|
744 |
} |
|
745 |
||
746 |
mouseDragState &= ~getButtonMask(lbutton); // Exclude the up-button from the drag-state |
|
747 |
} |
|
748 |
||
749 |
public void handleMotionNotify(XEvent xev) { |
|
750 |
super.handleMotionNotify(xev); |
|
751 |
XMotionEvent xme = xev.get_xmotion(); |
|
752 |
if (isEventDisabled(xev)) { |
|
753 |
return; |
|
754 |
} |
|
755 |
||
756 |
int mouseKeyState = (xme.get_state() & (Button1Mask | Button2Mask | Button3Mask)); |
|
757 |
boolean isDragging = (mouseKeyState != 0); |
|
758 |
int mouseEventType = 0; |
|
759 |
||
760 |
if (isDragging) { |
|
761 |
mouseEventType = MouseEvent.MOUSE_DRAGGED; |
|
762 |
} else { |
|
763 |
mouseEventType = MouseEvent.MOUSE_MOVED; |
|
764 |
} |
|
765 |
||
766 |
/* |
|
767 |
Fix for 6176814 . Add multiclick checking. |
|
768 |
*/ |
|
769 |
int x = xme.get_x(); |
|
770 |
int y = xme.get_y(); |
|
771 |
XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null); |
|
772 |
||
773 |
if (!(lastWindow == this && |
|
774 |
(xme.get_time() - lastTime) < XToolkit.getMultiClickTime() && |
|
775 |
(Math.abs(lastX - x) < AWT_MULTICLICK_SMUDGE && |
|
776 |
Math.abs(lastY - y) < AWT_MULTICLICK_SMUDGE))) { |
|
777 |
clickCount = 0; |
|
778 |
lastWindowRef = null; |
|
779 |
mouseDragState = mouseKeyState; |
|
780 |
lastTime = 0; |
|
781 |
lastX = 0; |
|
782 |
lastY = 0; |
|
783 |
} |
|
784 |
||
785 |
long jWhen = XToolkit.nowMillisUTC_offset(xme.get_time()); |
|
786 |
int modifiers = getModifiers(xme.get_state(), 0, 0); |
|
787 |
boolean popupTrigger = false; |
|
788 |
||
789 |
Component source = (Component)getEventSource(); |
|
790 |
||
791 |
if (xme.get_window() != window) { |
|
792 |
Point localXY = toLocal(xme.get_x_root(), xme.get_y_root()); |
|
793 |
x = localXY.x; |
|
794 |
y = localXY.y; |
|
795 |
} |
|
796 |
/* Fix for 5039416. |
|
797 |
* According to canvas.c we shouldn't post any MouseEvent if mouse is dragging and clickCount!=0. |
|
798 |
*/ |
|
799 |
if ((isDragging && clickCount == 0) || !isDragging) { |
|
800 |
MouseEvent mme = new MouseEvent(source, mouseEventType, jWhen, |
|
801 |
modifiers, x, y, xme.get_x_root(), xme.get_y_root(), |
|
802 |
clickCount, popupTrigger, MouseEvent.NOBUTTON); |
|
803 |
postEventToEventQueue(mme); |
|
804 |
} |
|
805 |
} |
|
806 |
||
807 |
||
808 |
// REMIND: need to implement looking for disabled events |
|
809 |
public native boolean x11inputMethodLookupString(long event, long [] keysymArray); |
|
810 |
native boolean haveCurrentX11InputMethodInstance(); |
|
811 |
||
812 |
public void handleXCrossingEvent(XEvent xev) { |
|
813 |
super.handleXCrossingEvent(xev); |
|
814 |
XCrossingEvent xce = xev.get_xcrossing(); |
|
815 |
||
816 |
if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString()); |
|
817 |
||
818 |
// Skip event If it was caused by a grab |
|
819 |
// This is needed because on displays with focus-follows-mouse on MousePress X system generates |
|
820 |
// two XCrossing events with mode != NormalNotify. First of them notifies that the mouse has left |
|
821 |
// current component. Second one notifies that it has entered into the same component. |
|
822 |
// This looks like the window under the mouse has actually changed and Java handle these events |
|
823 |
// accordingly. This leads to impossibility to make a double click on Component (6404708) |
|
824 |
XWindowPeer toplevel = getToplevelXWindow(); |
|
825 |
if (toplevel != null && !toplevel.isModalBlocked()){ |
|
826 |
if (xce.get_mode() != NotifyNormal) { |
|
827 |
// 6404708 : need update cursor in accordance with skipping Leave/EnterNotify event |
|
828 |
// whereas it doesn't need to handled further. |
|
829 |
if (xce.get_type() == EnterNotify) { |
|
830 |
XAwtState.setComponentMouseEntered(getEventSource()); |
|
831 |
XGlobalCursorManager.nativeUpdateCursor(getEventSource()); |
|
832 |
} else { // LeaveNotify: |
|
833 |
XAwtState.setComponentMouseEntered(null); |
|
834 |
} |
|
835 |
return; |
|
836 |
} |
|
837 |
} |
|
838 |
// X sends XCrossing to all hierarchy so if the edge of child equals to |
|
839 |
// ancestor and mouse enters child, the ancestor will get an event too. |
|
840 |
// From java point the event is bogus as ancestor is obscured, so if |
|
841 |
// the child can get java event itself, we skip it on ancestor. |
|
842 |
long childWnd = xce.get_subwindow(); |
|
843 |
if (childWnd != None) { |
|
844 |
XBaseWindow child = XToolkit.windowToXWindow(childWnd); |
|
845 |
if (child != null && child instanceof XWindow && |
|
846 |
!child.isEventDisabled(xev)) |
|
847 |
{ |
|
848 |
return; |
|
849 |
} |
|
850 |
} |
|
851 |
||
852 |
// Remember old component with mouse to have the opportunity to send it MOUSE_EXITED. |
|
853 |
final Component compWithMouse = XAwtState.getComponentMouseEntered(); |
|
854 |
if (toplevel != null) { |
|
855 |
if(!toplevel.isModalBlocked()){ |
|
856 |
if (xce.get_type() == EnterNotify) { |
|
857 |
// Change XAwtState's component mouse entered to the up-to-date one before requesting |
|
858 |
// to update the cursor since XAwtState.getComponentMouseEntered() is used when the |
|
859 |
// cursor is updated (in XGlobalCursorManager.findHeavyweightUnderCursor()). |
|
860 |
XAwtState.setComponentMouseEntered(getEventSource()); |
|
861 |
XGlobalCursorManager.nativeUpdateCursor(getEventSource()); |
|
862 |
} else { // LeaveNotify: |
|
863 |
XAwtState.setComponentMouseEntered(null); |
|
864 |
} |
|
865 |
} else { |
|
866 |
((XComponentPeer) ComponentAccessor.getPeer(target)) |
|
867 |
.pSetCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
|
868 |
} |
|
869 |
} |
|
870 |
||
871 |
if (isEventDisabled(xev)) { |
|
872 |
return; |
|
873 |
} |
|
874 |
||
875 |
long jWhen = XToolkit.nowMillisUTC_offset(xce.get_time()); |
|
876 |
int modifiers = getModifiers(xce.get_state(),0,0); |
|
877 |
int clickCount = 0; |
|
878 |
boolean popupTrigger = false; |
|
879 |
int x = xce.get_x(); |
|
880 |
int y = xce.get_y(); |
|
881 |
if (xce.get_window() != window) { |
|
882 |
Point localXY = toLocal(xce.get_x_root(), xce.get_y_root()); |
|
883 |
x = localXY.x; |
|
884 |
y = localXY.y; |
|
885 |
} |
|
886 |
||
887 |
// This code tracks boundary crossing and ensures MOUSE_ENTER/EXIT |
|
888 |
// are posted in alternate pairs |
|
889 |
if (compWithMouse != null) { |
|
890 |
MouseEvent me = new MouseEvent(compWithMouse, |
|
891 |
MouseEvent.MOUSE_EXITED, jWhen, modifiers, xce.get_x(), |
|
892 |
xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount, popupTrigger, |
|
893 |
MouseEvent.NOBUTTON); |
|
894 |
postEventToEventQueue(me); |
|
895 |
eventLog.finest("Clearing last window ref"); |
|
896 |
lastWindowRef = null; |
|
897 |
} |
|
898 |
if (xce.get_type() == EnterNotify) { |
|
899 |
MouseEvent me = new MouseEvent(getEventSource(), MouseEvent.MOUSE_ENTERED, |
|
900 |
jWhen, modifiers, xce.get_x(), xce.get_y(), xce.get_x_root(), xce.get_y_root(), clickCount, |
|
901 |
popupTrigger, MouseEvent.NOBUTTON); |
|
902 |
postEventToEventQueue(me); |
|
903 |
} |
|
904 |
} |
|
905 |
||
906 |
public void doLayout(int x, int y, int width, int height) {} |
|
907 |
||
908 |
public void handleConfigureNotifyEvent(XEvent xev) { |
|
909 |
Rectangle oldBounds = getBounds(); |
|
910 |
||
911 |
super.handleConfigureNotifyEvent(xev); |
|
912 |
insLog.log(Level.FINER, "Configure, {0}, event disabled: {1}", |
|
116
9c43d9eb1029
6645856: static field XWindowPeer.defaultFont hides XWindow.defaultFont
son
parents:
2
diff
changeset
|
913 |
new Object[] {xev.get_xconfigure(), isEventDisabled(xev)}); |
2 | 914 |
if (isEventDisabled(xev)) { |
915 |
return; |
|
916 |
} |
|
917 |
||
918 |
// if ( Check if it's a resize, a move, or a stacking order change ) |
|
919 |
// { |
|
920 |
Rectangle bounds = getBounds(); |
|
921 |
if (!bounds.getSize().equals(oldBounds.getSize())) { |
|
922 |
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED)); |
|
923 |
} |
|
924 |
if (!bounds.getLocation().equals(oldBounds.getLocation())) { |
|
925 |
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED)); |
|
926 |
} |
|
927 |
// } |
|
928 |
} |
|
929 |
||
930 |
public void handleMapNotifyEvent(XEvent xev) { |
|
931 |
super.handleMapNotifyEvent(xev); |
|
932 |
log.log(Level.FINE, "Mapped {0}", new Object[] {this}); |
|
933 |
if (isEventDisabled(xev)) { |
|
934 |
return; |
|
935 |
} |
|
936 |
ComponentEvent ce; |
|
937 |
||
938 |
ce = new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_SHOWN); |
|
939 |
postEventToEventQueue(ce); |
|
940 |
} |
|
941 |
||
942 |
public void handleUnmapNotifyEvent(XEvent xev) { |
|
943 |
super.handleUnmapNotifyEvent(xev); |
|
944 |
if (isEventDisabled(xev)) { |
|
945 |
return; |
|
946 |
} |
|
947 |
ComponentEvent ce; |
|
948 |
||
949 |
ce = new ComponentEvent(target, ComponentEvent.COMPONENT_HIDDEN); |
|
950 |
postEventToEventQueue(ce); |
|
951 |
} |
|
952 |
||
953 |
private void dumpKeysymArray(XKeyEvent ev) { |
|
954 |
keyEventLog.fine(" "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 0))+ |
|
955 |
"\n "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 1))+ |
|
956 |
"\n "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 2))+ |
|
957 |
"\n "+Long.toHexString(XlibWrapper.XKeycodeToKeysym(XToolkit.getDisplay(), ev.get_keycode(), 3))); |
|
958 |
} |
|
959 |
/** |
|
960 |
Return unicode character or 0 if no correspondent character found. |
|
961 |
Parameter is a keysym basically from keysymdef.h |
|
962 |
XXX: how about vendor keys? Is there some with Unicode value and not in the list? |
|
963 |
*/ |
|
964 |
char keysymToUnicode( long keysym, int state ) { |
|
965 |
return XKeysym.convertKeysym( keysym, state ); |
|
966 |
} |
|
967 |
int keyEventType2Id( int xEventType ) { |
|
968 |
return xEventType == XConstants.KeyPress ? java.awt.event.KeyEvent.KEY_PRESSED : |
|
969 |
xEventType == XConstants.KeyRelease ? java.awt.event.KeyEvent.KEY_RELEASED : 0; |
|
970 |
} |
|
971 |
static private long xkeycodeToKeysym(XKeyEvent ev) { |
|
972 |
return XKeysym.getKeysym( ev ); |
|
973 |
} |
|
974 |
void logIncomingKeyEvent(XKeyEvent ev) { |
|
975 |
keyEventLog.fine("--XWindow.java:handleKeyEvent:"+ev); |
|
976 |
dumpKeysymArray(ev); |
|
977 |
keyEventLog.fine("XXXXXXXXXXXXXX javakeycode will be most probably:0x"+ Integer.toHexString(XKeysym.getJavaKeycodeOnly(ev))); |
|
978 |
} |
|
979 |
public void handleKeyPress(XEvent xev) { |
|
980 |
super.handleKeyPress(xev); |
|
981 |
XKeyEvent ev = xev.get_xkey(); |
|
982 |
if (eventLog.isLoggable(Level.FINE)) eventLog.fine(ev.toString()); |
|
983 |
if (isEventDisabled(xev)) { |
|
984 |
return; |
|
985 |
} |
|
986 |
handleKeyPress(ev); |
|
987 |
} |
|
988 |
// called directly from this package, unlike handleKeyRelease. |
|
989 |
// un-final it if you need to override it in a subclass. |
|
990 |
final void handleKeyPress(XKeyEvent ev) { |
|
991 |
long keysym[] = new long[2]; |
|
992 |
char unicodeKey = 0; |
|
993 |
keysym[0] = NoSymbol; |
|
994 |
||
995 |
if (keyEventLog.isLoggable(Level.FINE)) { |
|
996 |
logIncomingKeyEvent( ev ); |
|
997 |
} |
|
998 |
if ( //TODO check if there's an active input method instance |
|
999 |
// without calling a native method. Is it necessary though? |
|
1000 |
haveCurrentX11InputMethodInstance()) { |
|
1001 |
if (x11inputMethodLookupString(ev.pData, keysym)) { |
|
1002 |
if (keyEventLog.isLoggable(Level.FINE)) { |
|
1003 |
keyEventLog.fine("--XWindow.java XIM did process event; return; dec keysym processed:"+(keysym[0])+ |
|
1004 |
"; hex keysym processed:"+Long.toHexString(keysym[0]) |
|
1005 |
); |
|
1006 |
} |
|
1007 |
return; |
|
1008 |
}else { |
|
1009 |
unicodeKey = keysymToUnicode( keysym[0], ev.get_state() ); |
|
1010 |
if (keyEventLog.isLoggable(Level.FINE)) { |
|
1011 |
keyEventLog.fine("--XWindow.java XIM did NOT process event, hex keysym:"+Long.toHexString(keysym[0])+"\n"+ |
|
1012 |
" unicode key:"+Integer.toHexString((int)unicodeKey)); |
|
1013 |
} |
|
1014 |
} |
|
1015 |
}else { |
|
1016 |
// No input method instance found. For example, there's a Java Input Method. |
|
1017 |
// Produce do-it-yourself keysym and perhaps unicode character. |
|
1018 |
keysym[0] = xkeycodeToKeysym(ev); |
|
1019 |
unicodeKey = keysymToUnicode( keysym[0], ev.get_state() ); |
|
1020 |
if (keyEventLog.isLoggable(Level.FINE)) { |
|
1021 |
keyEventLog.fine("--XWindow.java XIM is absent; hex keysym:"+Long.toHexString(keysym[0])+"\n"+ |
|
1022 |
" unicode key:"+Integer.toHexString((int)unicodeKey)); |
|
1023 |
} |
|
1024 |
} |
|
1025 |
// Keysym should be converted to Unicode, if possible and necessary, |
|
1026 |
// and Java KeyEvent keycode should be calculated. |
|
1027 |
// For press we should post pressed & typed Java events. |
|
1028 |
// |
|
1029 |
// Press event might be not processed to this time because |
|
1030 |
// (1) either XIM could not handle it or |
|
1031 |
// (2) it was Latin 1:1 mapping. |
|
1032 |
// |
|
1033 |
XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev); |
|
1034 |
if( jkc == null ) { |
|
1035 |
jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN); |
|
1036 |
} |
|
1037 |
if (keyEventLog.isLoggable(Level.FINE)) { |
|
1038 |
keyEventLog.fine(">>>Fire Event:"+ |
|
1039 |
(ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+ |
|
1040 |
"jkeycode:decimal="+jkc.getJavaKeycode()+ |
|
1041 |
", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; " |
|
1042 |
); |
|
1043 |
} |
|
1044 |
postKeyEvent( java.awt.event.KeyEvent.KEY_PRESSED, |
|
1045 |
ev.get_time(), |
|
1046 |
jkc.getJavaKeycode(), |
|
1047 |
(unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey), |
|
1048 |
jkc.getKeyLocation(), |
|
1049 |
ev.get_state(),ev.getPData(), XKeyEvent.getSize()); |
|
1050 |
if( unicodeKey > 0 ) { |
|
1051 |
keyEventLog.fine("fire _TYPED on "+unicodeKey); |
|
1052 |
postKeyEvent( java.awt.event.KeyEvent.KEY_TYPED, |
|
1053 |
ev.get_time(), |
|
1054 |
java.awt.event.KeyEvent.VK_UNDEFINED, |
|
1055 |
unicodeKey, |
|
1056 |
java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN, |
|
1057 |
ev.get_state(),ev.getPData(), XKeyEvent.getSize()); |
|
1058 |
} |
|
1059 |
||
1060 |
||
1061 |
} |
|
1062 |
||
1063 |
public void handleKeyRelease(XEvent xev) { |
|
1064 |
super.handleKeyRelease(xev); |
|
1065 |
XKeyEvent ev = xev.get_xkey(); |
|
1066 |
if (eventLog.isLoggable(Level.FINE)) eventLog.fine(ev.toString()); |
|
1067 |
if (isEventDisabled(xev)) { |
|
1068 |
return; |
|
1069 |
} |
|
1070 |
handleKeyRelease(ev); |
|
1071 |
} |
|
1072 |
// un-private it if you need to call it from elsewhere |
|
1073 |
private void handleKeyRelease(XKeyEvent ev) { |
|
1074 |
long keysym[] = new long[2]; |
|
1075 |
char unicodeKey = 0; |
|
1076 |
keysym[0] = NoSymbol; |
|
1077 |
||
1078 |
if (keyEventLog.isLoggable(Level.FINE)) { |
|
1079 |
logIncomingKeyEvent( ev ); |
|
1080 |
} |
|
1081 |
// Keysym should be converted to Unicode, if possible and necessary, |
|
1082 |
// and Java KeyEvent keycode should be calculated. |
|
1083 |
// For release we should post released event. |
|
1084 |
// |
|
1085 |
XKeysym.Keysym2JavaKeycode jkc = XKeysym.getJavaKeycode(ev); |
|
1086 |
if( jkc == null ) { |
|
1087 |
jkc = new XKeysym.Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN); |
|
1088 |
} |
|
1089 |
if (keyEventLog.isLoggable(Level.FINE)) { |
|
1090 |
keyEventLog.fine(">>>Fire Event:"+ |
|
1091 |
(ev.get_type() == XConstants.KeyPress ? "KEY_PRESSED; " : "KEY_RELEASED; ")+ |
|
1092 |
"jkeycode:decimal="+jkc.getJavaKeycode()+ |
|
1093 |
", hex=0x"+Integer.toHexString(jkc.getJavaKeycode())+"; " |
|
1094 |
); |
|
1095 |
} |
|
1096 |
// We obtain keysym from IM and derive unicodeKey from it for KeyPress only. |
|
1097 |
// We used to cache that value and retrieve it on KeyRelease, |
|
1098 |
// but in case for example of a dead key+vowel pair, a vowel after a deadkey |
|
1099 |
// might never be cached before. |
|
1100 |
// Also, switching between keyboard layouts, we might cache a wrong letter. |
|
1101 |
// That's why we use the same procedure as if there was no IM instance: do-it-yourself unicode. |
|
1102 |
unicodeKey = keysymToUnicode( xkeycodeToKeysym(ev), ev.get_state() ); |
|
1103 |
||
1104 |
postKeyEvent( java.awt.event.KeyEvent.KEY_RELEASED, |
|
1105 |
ev.get_time(), |
|
1106 |
jkc.getJavaKeycode(), |
|
1107 |
(unicodeKey == 0 ? java.awt.event.KeyEvent.CHAR_UNDEFINED : unicodeKey), |
|
1108 |
jkc.getKeyLocation(), |
|
1109 |
ev.get_state(),ev.getPData(), XKeyEvent.getSize()); |
|
1110 |
||
1111 |
} |
|
1112 |
||
1113 |
public void reshape(Rectangle bounds) { |
|
1114 |
reshape(bounds.x, bounds.y, bounds.width, bounds.height); |
|
1115 |
} |
|
1116 |
||
1117 |
public void reshape(int x, int y, int width, int height) { |
|
1118 |
if (width <= 0) { |
|
1119 |
width = 1; |
|
1120 |
} |
|
1121 |
if (height <= 0) { |
|
1122 |
height = 1; |
|
1123 |
} |
|
1124 |
this.x = x; |
|
1125 |
this.y = y; |
|
1126 |
this.width = width; |
|
1127 |
this.height = height; |
|
1128 |
xSetBounds(x, y, width, height); |
|
1129 |
// Fixed 6322593, 6304251, 6315137: |
|
1130 |
// XWindow's SurfaceData should be invalidated and recreated as part |
|
1131 |
// of the process of resizing the window |
|
1132 |
// see the evaluation of the bug 6304251 for more information |
|
1133 |
validateSurface(); |
|
1134 |
layout(); |
|
1135 |
} |
|
1136 |
||
1137 |
public void layout() {} |
|
1138 |
||
1139 |
boolean isShowing() { |
|
1140 |
return visible; |
|
1141 |
} |
|
1142 |
||
1143 |
boolean isResizable() { |
|
1144 |
return true; |
|
1145 |
} |
|
1146 |
||
1147 |
boolean isLocationByPlatform() { |
|
1148 |
return false; |
|
1149 |
} |
|
1150 |
||
1151 |
void updateSizeHints() { |
|
1152 |
updateSizeHints(x, y, width, height); |
|
1153 |
} |
|
1154 |
||
1155 |
void updateSizeHints(int x, int y, int width, int height) { |
|
1156 |
long flags = XlibWrapper.PSize | (isLocationByPlatform() ? 0 : (XlibWrapper.PPosition | XlibWrapper.USPosition)); |
|
1157 |
if (!isResizable()) { |
|
1158 |
log.log(Level.FINER, "Window {0} is not resizable", new Object[] {this}); |
|
1159 |
flags |= XlibWrapper.PMinSize | XlibWrapper.PMaxSize; |
|
1160 |
} else { |
|
1161 |
log.log(Level.FINER, "Window {0} is resizable", new Object[] {this}); |
|
1162 |
} |
|
1163 |
setSizeHints(flags, x, y, width, height); |
|
1164 |
} |
|
1165 |
||
1166 |
void updateSizeHints(int x, int y) { |
|
1167 |
long flags = isLocationByPlatform() ? 0 : (XlibWrapper.PPosition | XlibWrapper.USPosition); |
|
1168 |
if (!isResizable()) { |
|
1169 |
log.log(Level.FINER, "Window {0} is not resizable", new Object[] {this}); |
|
1170 |
flags |= XlibWrapper.PMinSize | XlibWrapper.PMaxSize | XlibWrapper.PSize; |
|
1171 |
} else { |
|
1172 |
log.log(Level.FINER, "Window {0} is resizable", new Object[] {this}); |
|
1173 |
} |
|
1174 |
setSizeHints(flags, x, y, width, height); |
|
1175 |
} |
|
1176 |
||
1177 |
void validateSurface() { |
|
1178 |
if ((width != oldWidth) || (height != oldHeight)) { |
|
1179 |
SurfaceData oldData = surfaceData; |
|
1180 |
if (oldData != null) { |
|
1181 |
surfaceData = graphicsConfig.createSurfaceData(this); |
|
1182 |
oldData.invalidate(); |
|
1183 |
} |
|
1184 |
oldWidth = width; |
|
1185 |
oldHeight = height; |
|
1186 |
} |
|
1187 |
} |
|
1188 |
||
1189 |
public SurfaceData getSurfaceData() { |
|
1190 |
return surfaceData; |
|
1191 |
} |
|
1192 |
||
1193 |
public void dispose() { |
|
1194 |
SurfaceData oldData = surfaceData; |
|
1195 |
surfaceData = null; |
|
1196 |
if (oldData != null) { |
|
1197 |
oldData.invalidate(); |
|
1198 |
} |
|
1199 |
XToolkit.targetDisposedPeer(target, this); |
|
1200 |
destroy(); |
|
1201 |
} |
|
1202 |
||
1203 |
public Point getLocationOnScreen() { |
|
1204 |
synchronized (target.getTreeLock()) { |
|
1205 |
Component comp = target; |
|
1206 |
||
1207 |
while (comp != null && !(comp instanceof Window)) { |
|
1208 |
comp = ComponentAccessor.getParent_NoClientCode(comp); |
|
1209 |
} |
|
1210 |
||
1211 |
// applets, embedded, etc - translate directly |
|
1212 |
// XXX: override in subclass? |
|
1213 |
if (comp == null || comp instanceof sun.awt.EmbeddedFrame) { |
|
1214 |
return toGlobal(0, 0); |
|
1215 |
} |
|
1216 |
||
1217 |
XToolkit.awtLock(); |
|
1218 |
try { |
|
1219 |
Object wpeer = XToolkit.targetToPeer(comp); |
|
1220 |
if (wpeer == null |
|
1221 |
|| !(wpeer instanceof XDecoratedPeer) |
|
1222 |
|| ((XDecoratedPeer)wpeer).configure_seen) |
|
1223 |
{ |
|
1224 |
return toGlobal(0, 0); |
|
1225 |
} |
|
1226 |
||
1227 |
// wpeer is an XDecoratedPeer not yet fully adopted by WM |
|
1228 |
Point pt = toOtherWindow(getContentWindow(), |
|
1229 |
((XDecoratedPeer)wpeer).getContentWindow(), |
|
1230 |
0, 0); |
|
1231 |
||
1232 |
if (pt == null) { |
|
1233 |
pt = new Point(((XBaseWindow)wpeer).getAbsoluteX(), ((XBaseWindow)wpeer).getAbsoluteY()); |
|
1234 |
} |
|
1235 |
pt.x += comp.getX(); |
|
1236 |
pt.y += comp.getY(); |
|
1237 |
return pt; |
|
1238 |
} finally { |
|
1239 |
XToolkit.awtUnlock(); |
|
1240 |
} |
|
1241 |
} |
|
1242 |
} |
|
1243 |
||
1244 |
||
1245 |
static Field bdata; |
|
1246 |
static void setBData(KeyEvent e, byte[] data) { |
|
1247 |
try { |
|
1248 |
if (bdata == null) { |
|
1249 |
bdata = SunToolkit.getField(java.awt.AWTEvent.class, "bdata"); |
|
1250 |
} |
|
1251 |
bdata.set(e, data); |
|
1252 |
} catch (IllegalAccessException ex) { |
|
1253 |
assert false; |
|
1254 |
} |
|
1255 |
} |
|
1256 |
||
1257 |
public void postKeyEvent(int id, long when, int keyCode, char keyChar, |
|
1258 |
int keyLocation, int state, long event, int eventSize) |
|
1259 |
{ |
|
1260 |
long jWhen = XToolkit.nowMillisUTC_offset(when); |
|
1261 |
int modifiers = getModifiers(state, 0, keyCode); |
|
1262 |
KeyEvent ke = new KeyEvent((Component)getEventSource(), id, jWhen, |
|
1263 |
modifiers, keyCode, keyChar, keyLocation); |
|
1264 |
if (event != 0) { |
|
1265 |
byte[] data = Native.toBytes(event, eventSize); |
|
1266 |
setBData(ke, data); |
|
1267 |
} |
|
1268 |
postEventToEventQueue(ke); |
|
1269 |
} |
|
1270 |
||
1271 |
static native int getAWTKeyCodeForKeySym(int keysym); |
|
1272 |
static native int getKeySymForAWTKeyCode(int keycode); |
|
1273 |
} |