1 /*
2 * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package sun.awt.X11;
26
27 import java.awt.AWTEvent;
28 import java.awt.AWTException;
29 import java.awt.BufferCapabilities;
30 import java.awt.Color;
31 import java.awt.Component;
32 import java.awt.Container;
33 import java.awt.Cursor;
34 import java.awt.Dimension;
35 import java.awt.Font;
36 import java.awt.FontMetrics;
37 import java.awt.Graphics;
38 import java.awt.GraphicsConfiguration;
39 import java.awt.Image;
40 import java.awt.Insets;
41 import java.awt.Rectangle;
42 import java.awt.SystemColor;
43 import java.awt.Toolkit;
44 import java.awt.Window;
45 import java.awt.dnd.DropTarget;
46 import java.awt.dnd.peer.DropTargetPeer;
47 import java.awt.event.FocusEvent;
48 import java.awt.event.InputEvent;
49 import java.awt.event.InputMethodEvent;
50 import java.awt.event.KeyEvent;
51 import java.awt.event.MouseEvent;
52 import java.awt.event.MouseWheelEvent;
53 import java.awt.event.PaintEvent;
54 import java.awt.event.WindowEvent;
55 import java.awt.image.ImageObserver;
56 import java.awt.image.ImageProducer;
57 import java.awt.image.VolatileImage;
58 import java.awt.peer.ComponentPeer;
59 import java.awt.peer.ContainerPeer;
60 import java.lang.reflect.*;
61 import java.security.*;
62 import java.util.Collection;
63 import java.util.Objects;
64 import java.util.Set;
65
66 import sun.awt.AWTAccessor.ComponentAccessor;
67 import sun.util.logging.PlatformLogger;
68 import sun.awt.*;
69 import sun.awt.event.IgnorePaintEvent;
70 import sun.awt.image.SunVolatileImage;
71 import sun.awt.image.ToolkitImage;
72 import sun.java2d.BackBufferCapsProvider;
73 import sun.java2d.pipe.Region;
74
75
76 public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer,
77 BackBufferCapsProvider
78 {
79 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer");
80 private static final PlatformLogger buffersLog = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer.multibuffer");
81 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XComponentPeer");
82 private static final PlatformLogger fontLog = PlatformLogger.getLogger("sun.awt.X11.font.XComponentPeer");
83 private static final PlatformLogger enableLog = PlatformLogger.getLogger("sun.awt.X11.enable.XComponentPeer");
84 private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.X11.shape.XComponentPeer");
85
86 boolean paintPending = false;
87 boolean isLayouting = false;
88 private boolean enabled;
89
90 // Actually used only by XDecoratedPeer
91 protected int boundsOperation;
92
93 Color foreground;
94 Color background;
95
96 // Colors calculated as on Motif using MotifColorUtilties.
97 // If you use these, call updateMotifColors() in the peer's Constructor and
98 // setBackground(). Examples are XCheckboxPeer and XButtonPeer.
99 Color darkShadow;
100 Color lightShadow;
101 Color selectColor;
102
103 Font font;
104 private long backBuffer = 0;
105 private VolatileImage xBackBuffer = null;
106
107 static Color[] systemColors;
108
109 XComponentPeer() {
110 }
111
112 XComponentPeer (XCreateWindowParams params) {
113 super(params);
114 }
115
116 XComponentPeer(Component target, long parentWindow, Rectangle bounds) {
117 super(target, parentWindow, bounds);
118 }
119
120 /**
121 * Standard peer constructor, with corresponding Component
122 */
123 XComponentPeer(Component target) {
124 super(target);
125 }
126
127
128 void preInit(XCreateWindowParams params) {
129 super.preInit(params);
130 boundsOperation = DEFAULT_OPERATION;
131 }
132 void postInit(XCreateWindowParams params) {
133 super.postInit(params);
134
135 pSetCursor(target.getCursor());
136
137 foreground = target.getForeground();
138 background = target.getBackground();
139 font = target.getFont();
140
141 if (isInitialReshape()) {
142 Rectangle r = target.getBounds();
143 reshape(r.x, r.y, r.width, r.height);
144 }
145
146 setEnabled(target.isEnabled());
147
148 if (target.isVisible()) {
149 setVisible(true);
150 }
151 }
152
153 protected boolean isInitialReshape() {
154 return true;
155 }
156
157 public void reparent(ContainerPeer newNativeParent) {
158 XComponentPeer newPeer = (XComponentPeer)newNativeParent;
159 XToolkit.awtLock();
160 try {
161 XlibWrapper.XReparentWindow(XToolkit.getDisplay(), getWindow(), newPeer.getContentWindow(), x, y);
162 parentWindow = newPeer;
163 } finally {
164 XToolkit.awtUnlock();
165 }
166 }
167 public boolean isReparentSupported() {
168 return System.getProperty("sun.awt.X11.XComponentPeer.reparentNotSupported", "false").equals("false");
169 }
170
171 @SuppressWarnings("deprecation")
172 public boolean isObscured() {
173 Container container = (target instanceof Container) ?
174 (Container)target : target.getParent();
175
176 if (container == null) {
177 return true;
178 }
179
180 Container parent;
181 while ((parent = container.getParent()) != null) {
182 container = parent;
183 }
184
185 if (container instanceof Window) {
186 XWindowPeer wpeer = AWTAccessor.getComponentAccessor()
187 .getPeer(container);
188 if (wpeer != null) {
189 return (wpeer.winAttr.visibilityState !=
190 XWindowAttributesData.AWT_UNOBSCURED);
191 }
192 }
193 return true;
194 }
195
196 public boolean canDetermineObscurity() {
197 return true;
198 }
199
200 /*************************************************
201 * FOCUS STUFF
202 *************************************************/
203
204 /**
205 * Keeps the track of focused state of the _NATIVE_ window
206 */
207 boolean bHasFocus = false;
208
209 /**
210 * Descendants should use this method to determine whether or not native window
211 * has focus.
212 */
213 public final boolean hasFocus() {
214 return bHasFocus;
215 }
216
217 /**
218 * Called when component receives focus
219 */
220 public void focusGained(FocusEvent e) {
221 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
222 focusLog.fine("{0}", e);
223 }
224 bHasFocus = true;
225 }
226
227 /**
228 * Called when component loses focus
229 */
230 public void focusLost(FocusEvent e) {
231 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
232 focusLog.fine("{0}", e);
233 }
234 bHasFocus = false;
235 }
236
237 public boolean isFocusable() {
238 /* should be implemented by other sub-classes */
239 return false;
240 }
241
242 private static Class<?> seClass;
243 private static Constructor<?> seCtor;
244
245 static final AWTEvent wrapInSequenced(AWTEvent event) {
246 try {
247 if (seClass == null) {
248 seClass = Class.forName("java.awt.SequencedEvent");
249 }
250
251 if (seCtor == null) {
252 seCtor = AccessController.doPrivileged(new
253 PrivilegedExceptionAction<Constructor<?>>() {
254 public Constructor<?> run() throws Exception {
255 Constructor<?> ctor = seClass.getConstructor(
256 new Class<?>[] { AWTEvent.class });
257 ctor.setAccessible(true);
258 return ctor;
259 }
260 });
261 }
262
263 return (AWTEvent) seCtor.newInstance(new Object[] { event });
264 }
265 catch (ClassNotFoundException e) {
266 throw new NoClassDefFoundError("java.awt.SequencedEvent.");
267 }
268 catch (PrivilegedActionException ex) {
269 throw new NoClassDefFoundError("java.awt.SequencedEvent.");
270 }
271 catch (InstantiationException e) {
272 assert false;
273 }
274 catch (IllegalAccessException e) {
275 assert false;
276 }
277 catch (InvocationTargetException e) {
278 assert false;
279 }
280
281 return null;
282 }
283
284 // TODO: consider moving it to KeyboardFocusManagerPeerImpl
285 @SuppressWarnings("deprecation")
286 public final boolean requestFocus(Component lightweightChild, boolean temporary,
287 boolean focusedWindowChangeAllowed, long time,
288 CausedFocusEvent.Cause cause)
289 {
290 if (XKeyboardFocusManagerPeer.
291 processSynchronousLightweightTransfer(target, lightweightChild, temporary,
292 focusedWindowChangeAllowed, time))
293 {
294 return true;
295 }
296
297 int result = XKeyboardFocusManagerPeer.
298 shouldNativelyFocusHeavyweight(target, lightweightChild,
299 temporary, focusedWindowChangeAllowed,
300 time, cause);
301
302 switch (result) {
303 case XKeyboardFocusManagerPeer.SNFH_FAILURE:
304 return false;
305 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
306 // Currently we just generate focus events like we deal with lightweight instead of calling
307 // XSetInputFocus on native window
308 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
309 focusLog.finer("Proceeding with request to " +
310 lightweightChild + " in " + target);
311 }
312 /**
313 * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight
314 * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet
315 * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record
316 * in requests list - and it breaks our requests sequence as first record on WGF should be the last
317 * focus owner which had focus before WLF. So, we should not add request record for such requests
318 * but store this component in mostRecent - and return true as before for compatibility.
319 */
320 Window parentWindow = SunToolkit.getContainingWindow(target);
321 if (parentWindow == null) {
322 return rejectFocusRequestHelper("WARNING: Parent window is null");
323 }
324 XWindowPeer wpeer = AWTAccessor.getComponentAccessor()
325 .getPeer(parentWindow);
326 if (wpeer == null) {
327 return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
328 }
329 /*
330 * Passing null 'actualFocusedWindow' as we don't want to restore focus on it
331 * when a component inside a Frame is requesting focus.
332 * See 6314575 for details.
333 */
334 boolean res = wpeer.requestWindowFocus(null);
335
336 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
337 focusLog.finer("Requested window focus: " + res);
338 }
339 // If parent window can be made focused and has been made focused(synchronously)
340 // then we can proceed with children, otherwise we retreat.
341 if (!(res && parentWindow.isFocused())) {
342 return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
343 }
344 return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
345 target,
346 temporary,
347 focusedWindowChangeAllowed,
348 time, cause);
349 // Motif compatibility code
350 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
351 // Either lightweight or excessive request - all events are generated.
352 return true;
353 }
354 return false;
355 }
356
357 private boolean rejectFocusRequestHelper(String logMsg) {
358 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
359 focusLog.finer(logMsg);
360 }
361 XKeyboardFocusManagerPeer.removeLastFocusRequest(target);
362 return false;
363 }
364
365 void handleJavaFocusEvent(AWTEvent e) {
366 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
367 focusLog.finer(e.toString());
368 }
369 if (e.getID() == FocusEvent.FOCUS_GAINED) {
370 focusGained((FocusEvent)e);
371 } else {
372 focusLost((FocusEvent)e);
373 }
374 }
375
376 void handleJavaWindowFocusEvent(AWTEvent e) {
377 }
378
379 /*************************************************
380 * END OF FOCUS STUFF
381 *************************************************/
382
383
384
385 public void setVisible(boolean b) {
386 xSetVisible(b);
387 }
388
389 public void hide() {
390 setVisible(false);
391 }
392
393 /**
394 * @see java.awt.peer.ComponentPeer
395 */
396 public void setEnabled(final boolean value) {
397 if (enableLog.isLoggable(PlatformLogger.Level.FINE)) {
398 enableLog.fine("{0}ing {1}", (value ? "Enabl" : "Disabl"), this);
399 }
400 boolean status = value;
401 // If any of our heavyweight ancestors are disable, we should be too
402 // See 6176875 for more information
403 final Container cp = SunToolkit.getNativeContainer(target);
404 final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
405 if (cp != null) {
406 status &= acc.<XComponentPeer>getPeer(cp).isEnabled();
407 }
408 synchronized (getStateLock()) {
409 if (enabled == status) {
410 return;
411 }
412 enabled = status;
413 }
414
415 if (target instanceof Container) {
416 final Component[] list = ((Container) target).getComponents();
417 for (final Component child : list) {
418 final ComponentPeer p = acc.getPeer(child);
419 if (p != null) {
420 p.setEnabled(status && child.isEnabled());
421 }
422 }
423 }
424 repaint();
425 }
426
427 //
428 // public so aw/Window can call it
429 //
430 public final boolean isEnabled() {
431 synchronized (getStateLock()) {
432 return enabled;
433 }
434 }
435
436 @Override
437 public void paint(final Graphics g) {
438 super.paint(g);
439 // allow target to change the picture
440 target.paint(g);
441 }
442
443 public Graphics getGraphics() {
444 return getGraphics(surfaceData, getPeerForeground(), getPeerBackground(), getPeerFont());
445 }
446 public void print(Graphics g) {
447 // clear rect here to emulate X clears rect before Expose
448 g.setColor(target.getBackground());
449 g.fillRect(0, 0, target.getWidth(), target.getHeight());
450 g.setColor(target.getForeground());
451 // paint peer
452 paintPeer(g);
453 // allow target to change the picture
454 target.print(g);
455 }
456
457 public void setBounds(int x, int y, int width, int height, int op) {
458 this.x = x;
459 this.y = y;
460 this.width = width;
461 this.height = height;
462 xSetBounds(x,y,width,height);
463 validateSurface();
464 layout();
465 }
466
467 public void reshape(int x, int y, int width, int height) {
468 setBounds(x, y, width, height, SET_BOUNDS);
469 }
470
471 public void coalescePaintEvent(PaintEvent e) {
472 Rectangle r = e.getUpdateRect();
473 if (!(e instanceof IgnorePaintEvent)) {
474 paintArea.add(r, e.getID());
475 }
476 if (true) {
477 switch(e.getID()) {
478 case PaintEvent.UPDATE:
479 if (log.isLoggable(PlatformLogger.Level.FINER)) {
480 log.finer("XCP coalescePaintEvent : UPDATE : add : x = " +
481 r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
482 }
483 return;
484 case PaintEvent.PAINT:
485 if (log.isLoggable(PlatformLogger.Level.FINER)) {
486 log.finer("XCP coalescePaintEvent : PAINT : add : x = " +
487 r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
488 }
489 return;
490 }
491 }
492 }
493
494 XWindowPeer getParentTopLevel() {
495 ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
496 Container parent = (target instanceof Container) ? ((Container)target) : (compAccessor.getParent(target));
497 // Search for parent window
498 while (parent != null && !(parent instanceof Window)) {
499 parent = compAccessor.getParent(parent);
500 }
501 if (parent != null) {
502 return (XWindowPeer)compAccessor.getPeer(parent);
503 } else {
504 return null;
505 }
506 }
507
508 /* This method is intended to be over-ridden by peers to perform user interaction */
509 void handleJavaMouseEvent(MouseEvent e) {
510 switch (e.getID()) {
511 case MouseEvent.MOUSE_PRESSED:
512 if (target == e.getSource() &&
513 !target.isFocusOwner() &&
514 XKeyboardFocusManagerPeer.shouldFocusOnClick(target))
515 {
516 XWindowPeer parentXWindow = getParentTopLevel();
517 Window parentWindow = ((Window)parentXWindow.getTarget());
518 // Simple windows are non-focusable in X terms but focusable in Java terms.
519 // As X-non-focusable they don't receive any focus events - we should generate them
520 // by ourselfves.
521 // if (parentXWindow.isFocusableWindow() /*&& parentXWindow.isSimpleWindow()*/ &&
522 // !(getCurrentNativeFocusedWindow() == parentWindow))
523 // {
524 // setCurrentNativeFocusedWindow(parentWindow);
525 // WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
526 // parentWindow.dispatchEvent(wfg);
527 // }
528 XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
529 }
530 break;
531 }
532 }
533
534 /* This method is intended to be over-ridden by peers to perform user interaction */
535 void handleJavaKeyEvent(KeyEvent e) {
536 }
537
538 /* This method is intended to be over-ridden by peers to perform user interaction */
539 void handleJavaMouseWheelEvent(MouseWheelEvent e) {
540 }
541
542
543 /* This method is intended to be over-ridden by peers to perform user interaction */
544 void handleJavaInputMethodEvent(InputMethodEvent e) {
545 }
546
547 void handleF10JavaKeyEvent(KeyEvent e) {
548 if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_F10) {
549 XWindowPeer winPeer = this.getToplevelXWindow();
550 if (winPeer instanceof XFramePeer) {
551 XMenuBarPeer mPeer = ((XFramePeer)winPeer).getMenubarPeer();
552 if (mPeer != null) {
553 mPeer.handleF10KeyPress(e);
554 }
555 }
556 }
557 }
558
559 @SuppressWarnings("fallthrough")
560 public void handleEvent(java.awt.AWTEvent e) {
561 if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && target.isEnabled()) {
562 if (e instanceof MouseEvent) {
563 if (e instanceof MouseWheelEvent) {
564 handleJavaMouseWheelEvent((MouseWheelEvent) e);
565 }
566 else
567 handleJavaMouseEvent((MouseEvent) e);
568 }
569 else if (e instanceof KeyEvent) {
570 handleF10JavaKeyEvent((KeyEvent)e);
571 handleJavaKeyEvent((KeyEvent)e);
572 }
573 }
574 else if (e instanceof KeyEvent && !((InputEvent)e).isConsumed()) {
575 // even if target is disabled.
576 handleF10JavaKeyEvent((KeyEvent)e);
577 }
578 else if (e instanceof InputMethodEvent) {
579 handleJavaInputMethodEvent((InputMethodEvent) e);
580 }
581
582 int id = e.getID();
583
584 switch(id) {
585 case PaintEvent.PAINT:
586 // Got native painting
587 paintPending = false;
588 // Fallthrough to next statement
589 case PaintEvent.UPDATE:
590 // Skip all painting while layouting and all UPDATEs
591 // while waiting for native paint
592 if (!isLayouting && !paintPending) {
593 paintArea.paint(target,false);
594 }
595 return;
596 case FocusEvent.FOCUS_LOST:
597 case FocusEvent.FOCUS_GAINED:
598 handleJavaFocusEvent(e);
599 break;
600 case WindowEvent.WINDOW_LOST_FOCUS:
601 case WindowEvent.WINDOW_GAINED_FOCUS:
602 handleJavaWindowFocusEvent(e);
603 break;
604 default:
605 break;
606 }
607
608 }
609
610 public Dimension getMinimumSize() {
611 return target.getSize();
612 }
613
614 public Dimension getPreferredSize() {
615 return getMinimumSize();
616 }
617
618 public void layout() {}
619
620 void updateMotifColors(Color bg) {
621 int red = bg.getRed();
622 int green = bg.getGreen();
623 int blue = bg.getBlue();
624
625 darkShadow = new Color(MotifColorUtilities.calculateBottomShadowFromBackground(red,green,blue));
626 lightShadow = new Color(MotifColorUtilities.calculateTopShadowFromBackground(red,green,blue));
627 selectColor= new Color(MotifColorUtilities.calculateSelectFromBackground(red,green,blue));
628 }
629
630 /*
631 * Draw a 3D rectangle using the Motif colors.
632 * "Normal" rectangles have shadows on the bottom.
633 * "Depressed" rectangles (such as pressed buttons) have shadows on the top,
634 * in which case true should be passed for topShadow.
635 */
636 public void drawMotif3DRect(Graphics g,
637 int x, int y, int width, int height,
638 boolean topShadow) {
639 g.setColor(topShadow ? darkShadow : lightShadow);
640 g.drawLine(x, y, x+width, y); // top
641 g.drawLine(x, y+height, x, y); // left
642
643 g.setColor(topShadow ? lightShadow : darkShadow );
644 g.drawLine(x+1, y+height, x+width, y+height); // bottom
645 g.drawLine(x+width, y+height, x+width, y+1); // right
646 }
647
648 @Override
649 public void setBackground(Color c) {
650 if (log.isLoggable(PlatformLogger.Level.FINE)) {
651 log.fine("Set background to " + c);
652 }
653 synchronized (getStateLock()) {
654 if (Objects.equals(background, c)) {
655 return;
656 }
657 background = c;
658 }
659 super.setBackground(c);
660 repaint();
661 }
662
663 @Override
664 public void setForeground(Color c) {
665 if (log.isLoggable(PlatformLogger.Level.FINE)) {
666 log.fine("Set foreground to " + c);
667 }
668 synchronized (getStateLock()) {
669 if (Objects.equals(foreground, c)) {
670 return;
671 }
672 foreground = c;
673 }
674 repaint();
675 }
676
677 /**
678 * Gets the font metrics for the specified font.
679 * @param font the font for which font metrics is to be
680 * obtained
681 * @return the font metrics for {@code font}
682 * @see #getFont
683 * @see java.awt.peer.ComponentPeer#getFontMetrics(Font)
684 * @see Toolkit#getFontMetrics(Font)
685 * @since 1.0
686 */
687 public FontMetrics getFontMetrics(Font font) {
688 if (fontLog.isLoggable(PlatformLogger.Level.FINE)) {
689 fontLog.fine("Getting font metrics for " + font);
690 }
691 return sun.font.FontDesignMetrics.getMetrics(font);
692 }
693
694 @Override
695 public void setFont(Font f) {
696 if (f == null) {
697 f = XWindow.getDefaultFont();
698 }
699 synchronized (getStateLock()) {
700 if (f.equals(font)) {
701 return;
702 }
703 font = f;
704 }
705 // as it stands currently we don't need to do layout since
706 // layout is done in the Component upon setFont.
707 //layout();
708 repaint();
709 }
710
711 public Font getFont() {
712 return font;
713 }
714
715 public void updateCursorImmediately() {
716 XGlobalCursorManager.getCursorManager().updateCursorImmediately();
717 }
718
719 public final void pSetCursor(Cursor cursor) {
720 this.pSetCursor(cursor, true);
721 }
722
723 /*
724 * The method changes the cursor.
725 * @param cursor - a new cursor to change to.
726 * @param ignoreSubComponents - if {@code true} is passed then
727 * the new cursor will be installed on window.
728 * if {@code false} is passed then
729 * subsequent components will try to handle
730 * this request and install their cursor.
731 */
732 //ignoreSubComponents not used here
733 public void pSetCursor(Cursor cursor, boolean ignoreSubComponents) {
734 XToolkit.awtLock();
735 try {
736 long xcursor = XGlobalCursorManager.getCursor(cursor);
737
738 XSetWindowAttributes xwa = new XSetWindowAttributes();
739 xwa.set_cursor(xcursor);
740
741 long valuemask = XConstants.CWCursor;
742
743 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),getWindow(),valuemask,xwa.pData);
744 XlibWrapper.XFlush(XToolkit.getDisplay());
745 xwa.dispose();
746 } finally {
747 XToolkit.awtUnlock();
748 }
749 }
750
751 public Image createImage(ImageProducer producer) {
752 return new ToolkitImage(producer);
753 }
754
755 public Image createImage(int width, int height) {
756 return graphicsConfig.createAcceleratedImage(target, width, height);
757 }
758
759 public VolatileImage createVolatileImage(int width, int height) {
760 return new SunVolatileImage(target, width, height);
761 }
762
763 public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
764 return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);
765 }
766
767 public int checkImage(Image img, int w, int h, ImageObserver o) {
768 return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);
769 }
770
771 public Dimension preferredSize() {
772 return getPreferredSize();
773 }
774
775 public Dimension minimumSize() {
776 return getMinimumSize();
777 }
778
779 public Insets getInsets() {
780 return new Insets(0, 0, 0, 0);
781 }
782
783 public void beginValidate() {
784 }
785
786 public void endValidate() {
787 }
788
789
790 /**
791 * DEPRECATED: Replaced by getInsets().
792 */
793
794 public Insets insets() {
795 return getInsets();
796 }
797
798 // Returns true if we are inside begin/endLayout and
799 // are waiting for native painting
800 public boolean isPaintPending() {
801 return paintPending && isLayouting;
802 }
803
804 public boolean handlesWheelScrolling() {
805 return false;
806 }
807
808 public void beginLayout() {
809 // Skip all painting till endLayout
810 isLayouting = true;
811
812 }
813
814 public void endLayout() {
815 if (!paintPending && !paintArea.isEmpty()
816 && !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target))
817 {
818 // if not waiting for native painting repaint damaged area
819 postEvent(new PaintEvent(target, PaintEvent.PAINT,
820 new Rectangle()));
821 }
822 isLayouting = false;
823 }
824
825 public Color getWinBackground() {
826 return getPeerBackground();
827 }
828
829 static int[] getRGBvals(Color c) {
830
831 int rgbvals[] = new int[3];
832
833 rgbvals[0] = c.getRed();
834 rgbvals[1] = c.getGreen();
835 rgbvals[2] = c.getBlue();
836
837 return rgbvals;
838 }
839
840 static final int BACKGROUND_COLOR = 0;
841 static final int HIGHLIGHT_COLOR = 1;
842 static final int SHADOW_COLOR = 2;
843 static final int FOREGROUND_COLOR = 3;
844
845 public Color[] getGUIcolors() {
846 Color c[] = new Color[4];
847 float backb, highb, shadowb, hue, saturation;
848 c[BACKGROUND_COLOR] = getWinBackground();
849 if (c[BACKGROUND_COLOR] == null) {
850 c[BACKGROUND_COLOR] = super.getWinBackground();
851 }
852 if (c[BACKGROUND_COLOR] == null) {
853 c[BACKGROUND_COLOR] = Color.lightGray;
854 }
855
856 int[] rgb = getRGBvals(c[BACKGROUND_COLOR]);
857
858 float[] hsb = Color.RGBtoHSB(rgb[0],rgb[1],rgb[2],null);
859
860 hue = hsb[0];
861 saturation = hsb[1];
862 backb = hsb[2];
863
864
865 /* Calculate Highlight Brightness */
866
867 highb = backb + 0.2f;
868 shadowb = backb - 0.4f;
869 if ((highb > 1.0) ) {
870 if ((1.0 - backb) < 0.05) {
871 highb = shadowb + 0.25f;
872 } else {
873 highb = 1.0f;
874 }
875 } else {
876 if (shadowb < 0.0) {
877 if ((backb - 0.0) < 0.25) {
878 highb = backb + 0.75f;
879 shadowb = highb - 0.2f;
880 } else {
881 shadowb = 0.0f;
882 }
883 }
884 }
885 c[HIGHLIGHT_COLOR] = Color.getHSBColor(hue,saturation,highb);
886 c[SHADOW_COLOR] = Color.getHSBColor(hue,saturation,shadowb);
887
888
889 /*
890 c[SHADOW_COLOR] = c[BACKGROUND_COLOR].darker();
891 int r2 = c[SHADOW_COLOR].getRed();
892 int g2 = c[SHADOW_COLOR].getGreen();
893 int b2 = c[SHADOW_COLOR].getBlue();
894 */
895
896 c[FOREGROUND_COLOR] = getPeerForeground();
897 if (c[FOREGROUND_COLOR] == null) {
898 c[FOREGROUND_COLOR] = Color.black;
899 }
900 /*
901 if ((c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR]))
902 && (c[BACKGROUND_COLOR].equals(c[SHADOW_COLOR]))) {
903 c[SHADOW_COLOR] = new Color(c[BACKGROUND_COLOR].getRed() + 75,
904 c[BACKGROUND_COLOR].getGreen() + 75,
905 c[BACKGROUND_COLOR].getBlue() + 75);
906 c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR].brighter();
907 } else if (c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR])) {
908 c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR];
909 c[SHADOW_COLOR] = c[SHADOW_COLOR].darker();
910 }
911 */
912 if (! isEnabled()) {
913 c[BACKGROUND_COLOR] = c[BACKGROUND_COLOR].darker();
914 // Reduce the contrast
915 // Calculate the NTSC gray (NB: REC709 L* might be better!)
916 // for foreground and background; then multiply the foreground
917 // by the average lightness
918
919
920 Color tc = c[BACKGROUND_COLOR];
921 int bg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
922
923 tc = c[FOREGROUND_COLOR];
924 int fg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
925
926 float ave = (float) ((fg + bg) / 51000.0);
927 // 255 * 100 * 2
928
929 Color newForeground = new Color((int) (tc.getRed() * ave),
930 (int) (tc.getGreen() * ave),
931 (int) (tc.getBlue() * ave));
932
933 if (newForeground.equals(c[FOREGROUND_COLOR])) {
934 // This probably means the foreground color is black or white
935 newForeground = new Color(ave, ave, ave);
936 }
937 c[FOREGROUND_COLOR] = newForeground;
938
939 }
940
941
942 return c;
943 }
944
945 /**
946 * Returns an array of Colors similar to getGUIcolors(), but using the
947 * System colors. This is useful if pieces of a Component (such as
948 * the integrated scrollbars of a List) should retain the System color
949 * instead of the background color set by Component.setBackground().
950 */
951 static Color[] getSystemColors() {
952 if (systemColors == null) {
953 systemColors = new Color[4];
954 systemColors[BACKGROUND_COLOR] = SystemColor.window;
955 systemColors[HIGHLIGHT_COLOR] = SystemColor.controlLtHighlight;
956 systemColors[SHADOW_COLOR] = SystemColor.controlShadow;
957 systemColors[FOREGROUND_COLOR] = SystemColor.windowText;
958 }
959 return systemColors;
960 }
961
962 /**
963 * Draw a 3D oval.
964 */
965 public void draw3DOval(Graphics g, Color colors[],
966 int x, int y, int w, int h, boolean raised)
967 {
968 Color c = g.getColor();
969 g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
970 g.drawArc(x, y, w, h, 45, 180);
971 g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
972 g.drawArc(x, y, w, h, 225, 180);
973 g.setColor(c);
974 }
975
976 public void draw3DRect(Graphics g, Color colors[],
977 int x, int y, int width, int height, boolean raised)
978 {
979 Color c = g.getColor();
980 g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
981 g.drawLine(x, y, x, y + height);
982 g.drawLine(x + 1, y, x + width - 1, y);
983 g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
984 g.drawLine(x + 1, y + height, x + width, y + height);
985 g.drawLine(x + width, y, x + width, y + height - 1);
986 g.setColor(c);
987 }
988
989 /*
990 * drawXXX() methods are used to print the native components by
991 * rendering the Motif look ourselves.
992 * ToDo(aim): needs to query native motif for more accurate color
993 * information.
994 */
995 void draw3DOval(Graphics g, Color bg,
996 int x, int y, int w, int h, boolean raised)
997 {
998 Color c = g.getColor();
999 Color shadow = bg.darker();
1000 Color highlight = bg.brighter();
1001
1002 g.setColor(raised ? highlight : shadow);
1003 g.drawArc(x, y, w, h, 45, 180);
1004 g.setColor(raised ? shadow : highlight);
1005 g.drawArc(x, y, w, h, 225, 180);
1006 g.setColor(c);
1007 }
1008
1009 void draw3DRect(Graphics g, Color bg,
1010 int x, int y, int width, int height,
1011 boolean raised) {
1012 Color c = g.getColor();
1013 Color shadow = bg.darker();
1014 Color highlight = bg.brighter();
1015
1016 g.setColor(raised ? highlight : shadow);
1017 g.drawLine(x, y, x, y + height);
1018 g.drawLine(x + 1, y, x + width - 1, y);
1019 g.setColor(raised ? shadow : highlight);
1020 g.drawLine(x + 1, y + height, x + width, y + height);
1021 g.drawLine(x + width, y, x + width, y + height - 1);
1022 g.setColor(c);
1023 }
1024
1025 void drawScrollbar(Graphics g, Color bg, int thickness, int length,
1026 int min, int max, int val, int vis, boolean horizontal) {
1027 Color c = g.getColor();
1028 double f = (double)(length - 2*(thickness-1)) / Math.max(1, ((max - min) + vis));
1029 int v1 = thickness + (int)(f * (val - min));
1030 int v2 = (int)(f * vis);
1031 int w2 = thickness-4;
1032 int tpts_x[] = new int[3];
1033 int tpts_y[] = new int[3];
1034
1035 if (length < 3*w2 ) {
1036 v1 = v2 = 0;
1037 if (length < 2*w2 + 2) {
1038 w2 = (length-2)/2;
1039 }
1040 } else if (v2 < 7) {
1041 // enforce a minimum handle size
1042 v1 = Math.max(0, v1 - ((7 - v2)>>1));
1043 v2 = 7;
1044 }
1045
1046 int ctr = thickness/2;
1047 int sbmin = ctr - w2/2;
1048 int sbmax = ctr + w2/2;
1049
1050 // paint the background slightly darker
1051 {
1052 Color d = new Color((int) (bg.getRed() * 0.85),
1053 (int) (bg.getGreen() * 0.85),
1054 (int) (bg.getBlue() * 0.85));
1055
1056 g.setColor(d);
1057 if (horizontal) {
1058 g.fillRect(0, 0, length, thickness);
1059 } else {
1060 g.fillRect(0, 0, thickness, length);
1061 }
1062 }
1063
1064 // paint the thumb and arrows in the normal background color
1065 g.setColor(bg);
1066 if (v1 > 0) {
1067 if (horizontal) {
1068 g.fillRect(v1, 3, v2, thickness-3);
1069 } else {
1070 g.fillRect(3, v1, thickness-3, v2);
1071 }
1072 }
1073
1074 tpts_x[0] = ctr; tpts_y[0] = 2;
1075 tpts_x[1] = sbmin; tpts_y[1] = w2;
1076 tpts_x[2] = sbmax; tpts_y[2] = w2;
1077 if (horizontal) {
1078 g.fillPolygon(tpts_y, tpts_x, 3);
1079 } else {
1080 g.fillPolygon(tpts_x, tpts_y, 3);
1081 }
1082
1083 tpts_y[0] = length-2;
1084 tpts_y[1] = length-w2;
1085 tpts_y[2] = length-w2;
1086 if (horizontal) {
1087 g.fillPolygon(tpts_y, tpts_x, 3);
1088 } else {
1089 g.fillPolygon(tpts_x, tpts_y, 3);
1090 }
1091
1092 Color highlight = bg.brighter();
1093
1094 // // // // draw the "highlighted" edges
1095 g.setColor(highlight);
1096
1097 // outline & arrows
1098 if (horizontal) {
1099 g.drawLine(1, thickness, length - 1, thickness);
1100 g.drawLine(length - 1, 1, length - 1, thickness);
1101
1102 // arrows
1103 g.drawLine(1, ctr, w2, sbmin);
1104 g.drawLine(length - w2, sbmin, length - w2, sbmax);
1105 g.drawLine(length - w2, sbmin, length - 2, ctr);
1106
1107 } else {
1108 g.drawLine(thickness, 1, thickness, length - 1);
1109 g.drawLine(1, length - 1, thickness, length - 1);
1110
1111 // arrows
1112 g.drawLine(ctr, 1, sbmin, w2);
1113 g.drawLine(sbmin, length - w2, sbmax, length - w2);
1114 g.drawLine(sbmin, length - w2, ctr, length - 2);
1115 }
1116
1117 // thumb
1118 if (v1 > 0) {
1119 if (horizontal) {
1120 g.drawLine(v1, 2, v1 + v2, 2);
1121 g.drawLine(v1, 2, v1, thickness-3);
1122 } else {
1123 g.drawLine(2, v1, 2, v1 + v2);
1124 g.drawLine(2, v1, thickness-3, v1);
1125 }
1126 }
1127
1128 Color shadow = bg.darker();
1129
1130 // // // // draw the "shadowed" edges
1131 g.setColor(shadow);
1132
1133 // outline && arrows
1134 if (horizontal) {
1135 g.drawLine(0, 0, 0, thickness);
1136 g.drawLine(0, 0, length - 1, 0);
1137
1138 // arrows
1139 g.drawLine(w2, sbmin, w2, sbmax);
1140 g.drawLine(w2, sbmax, 1, ctr);
1141 g.drawLine(length-2, ctr, length-w2, sbmax);
1142
1143 } else {
1144 g.drawLine(0, 0, thickness, 0);
1145 g.drawLine(0, 0, 0, length - 1);
1146
1147 // arrows
1148 g.drawLine(sbmin, w2, sbmax, w2);
1149 g.drawLine(sbmax, w2, ctr, 1);
1150 g.drawLine(ctr, length-2, sbmax, length-w2);
1151 }
1152
1153 // thumb
1154 if (v1 > 0) {
1155 if (horizontal) {
1156 g.drawLine(v1 + v2, 2, v1 + v2, thickness-2);
1157 g.drawLine(v1, thickness-2, v1 + v2, thickness-2);
1158 } else {
1159 g.drawLine(2, v1 + v2, thickness-2, v1 + v2);
1160 g.drawLine(thickness-2, v1, thickness-2, v1 + v2);
1161 }
1162 }
1163 g.setColor(c);
1164 }
1165
1166 /**
1167 * The following multibuffering-related methods delegate to our
1168 * associated GraphicsConfig (X11 or GLX) to handle the appropriate
1169 * native windowing system specific actions.
1170 */
1171
1172 private BufferCapabilities backBufferCaps;
1173
1174 public void createBuffers(int numBuffers, BufferCapabilities caps)
1175 throws AWTException
1176 {
1177 if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1178 buffersLog.fine("createBuffers(" + numBuffers + ", " + caps + ")");
1179 }
1180 // set the caps first, they're used when creating the bb
1181 backBufferCaps = caps;
1182 backBuffer = graphicsConfig.createBackBuffer(this, numBuffers, caps);
1183 xBackBuffer = graphicsConfig.createBackBufferImage(target,
1184 backBuffer);
1185 }
1186
1187 @Override
1188 public BufferCapabilities getBackBufferCaps() {
1189 return backBufferCaps;
1190 }
1191
1192 public void flip(int x1, int y1, int x2, int y2,
1193 BufferCapabilities.FlipContents flipAction)
1194 {
1195 if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1196 buffersLog.fine("flip(" + flipAction + ")");
1197 }
1198 if (backBuffer == 0) {
1199 throw new IllegalStateException("Buffers have not been created");
1200 }
1201 graphicsConfig.flip(this, target, xBackBuffer,
1202 x1, y1, x2, y2, flipAction);
1203 }
1204
1205 public Image getBackBuffer() {
1206 if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1207 buffersLog.fine("getBackBuffer()");
1208 }
1209 if (backBuffer == 0) {
1210 throw new IllegalStateException("Buffers have not been created");
1211 }
1212 return xBackBuffer;
1213 }
1214
1215 public void destroyBuffers() {
1216 if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1217 buffersLog.fine("destroyBuffers()");
1218 }
1219 graphicsConfig.destroyBackBuffer(backBuffer);
1220 backBuffer = 0;
1221 xBackBuffer = null;
1222 }
1223
1224 // End of multi-buffering
1225
1226 public void notifyTextComponentChange(boolean add){
1227 Container parent = AWTAccessor.getComponentAccessor().getParent(target);
1228 while(!(parent == null ||
1229 parent instanceof java.awt.Frame ||
1230 parent instanceof java.awt.Dialog)) {
1231 parent = AWTAccessor.getComponentAccessor().getParent(parent);
1232 }
1233
1234 /* FIX ME - FIX ME need to implement InputMethods
1235 if (parent instanceof java.awt.Frame ||
1236 parent instanceof java.awt.Dialog) {
1237 if (add)
1238 ((MInputMethodControl)parent.getPeer()).addTextComponent((MComponentPeer)this);
1239 else
1240 ((MInputMethodControl)parent.getPeer()).removeTextComponent((MComponentPeer)this);
1241 }
1242 */
1243 }
1244
1245 /**
1246 * Returns true if this event is disabled and shouldn't be processed by window
1247 * Currently if target component is disabled the following event will be disabled on window:
1248 * ButtonPress, ButtonRelease, KeyPress, KeyRelease, EnterNotify, LeaveNotify, MotionNotify
1249 */
1250 protected boolean isEventDisabled(XEvent e) {
1251 if (enableLog.isLoggable(PlatformLogger.Level.FINEST)) {
1252 enableLog.finest("Component is {1}, checking for disabled event {0}", e, (isEnabled()?"enabled":"disable"));
1253 }
1254 if (!isEnabled()) {
1255 switch (e.get_type()) {
1256 case XConstants.ButtonPress:
1257 case XConstants.ButtonRelease:
1258 case XConstants.KeyPress:
1259 case XConstants.KeyRelease:
1260 case XConstants.EnterNotify:
1261 case XConstants.LeaveNotify:
1262 case XConstants.MotionNotify:
1263 if (enableLog.isLoggable(PlatformLogger.Level.FINER)) {
1264 enableLog.finer("Event {0} is disable", e);
1265 }
1266 return true;
1267 }
1268 }
1269 switch(e.get_type()) {
1270 case XConstants.MapNotify:
1271 case XConstants.UnmapNotify:
1272 return true;
1273 }
1274 return super.isEventDisabled(e);
1275 }
1276
1277 Color getPeerBackground() {
1278 return background;
1279 }
1280
1281 Color getPeerForeground() {
1282 return foreground;
1283 }
1284
1285 Font getPeerFont() {
1286 return font;
1287 }
1288
1289 Dimension getPeerSize() {
1290 return new Dimension(width,height);
1291 }
1292
1293 public void setBoundsOperation(int operation) {
1294 synchronized(getStateLock()) {
1295 if (boundsOperation == DEFAULT_OPERATION) {
1296 boundsOperation = operation;
1297 } else if (operation == RESET_OPERATION) {
1298 boundsOperation = DEFAULT_OPERATION;
1299 }
1300 }
1301 }
1302
1303 static String operationToString(int operation) {
1304 switch (operation) {
1305 case SET_LOCATION:
1306 return "SET_LOCATION";
1307 case SET_SIZE:
1308 return "SET_SIZE";
1309 case SET_CLIENT_SIZE:
1310 return "SET_CLIENT_SIZE";
1311 default:
1312 case SET_BOUNDS:
1313 return "SET_BOUNDS";
1314 }
1315 }
1316
1317 /**
1318 * Lowers this component at the bottom of the above HW peer. If the above parameter
1319 * is null then the method places this component at the top of the Z-order.
1320 */
1321 public void setZOrder(ComponentPeer above) {
1322 long aboveWindow = (above != null) ? ((XComponentPeer)above).getWindow() : 0;
1323
1324 XToolkit.awtLock();
1325 try{
1326 XlibWrapper.SetZOrder(XToolkit.getDisplay(), getWindow(), aboveWindow);
1327 }finally{
1328 XToolkit.awtUnlock();
1329 }
1330 }
1331
1332 private void addTree(Collection<Long> order, Set<Long> set, Container cont) {
1333 for (int i = 0; i < cont.getComponentCount(); i++) {
1334 Component comp = cont.getComponent(i);
1335 Object peer = AWTAccessor.getComponentAccessor().getPeer(comp);
1336 if (peer instanceof XComponentPeer) {
1337 Long window = Long.valueOf(((XComponentPeer)peer).getWindow());
1338 if (!set.contains(window)) {
1339 set.add(window);
1340 order.add(window);
1341 }
1342 } else if (comp instanceof Container) {
1343 // It is lightweight container, it might contain heavyweight components attached to this
1344 // peer
1345 addTree(order, set, (Container)comp);
1346 }
1347 }
1348 }
1349
1350 /****** DropTargetPeer implementation ********************/
1351
1352 public void addDropTarget(DropTarget dt) {
1353 Component comp = target;
1354 while(!(comp == null || comp instanceof Window)) {
1355 comp = comp.getParent();
1356 }
1357
1358 if (comp instanceof Window) {
1359 XWindowPeer wpeer = AWTAccessor.getComponentAccessor().getPeer(comp);
1360 if (wpeer != null) {
1361 wpeer.addDropTarget();
1362 }
1363 }
1364 }
1365
1366 public void removeDropTarget(DropTarget dt) {
1367 Component comp = target;
1368 while(!(comp == null || comp instanceof Window)) {
1369 comp = comp.getParent();
1370 }
1371
1372 if (comp instanceof Window) {
1373 XWindowPeer wpeer = AWTAccessor.getComponentAccessor()
1374 .getPeer(comp);
1375 if (wpeer != null) {
1376 wpeer.removeDropTarget();
1377 }
1378 }
1379 }
1380
1381 /**
1382 * Applies the shape to the X-window.
1383 * @since 1.7
1384 */
1385 public void applyShape(Region shape) {
1386 if (XlibUtil.isShapingSupported()) {
1387 if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1388 shapeLog.finer(
1389 "*** INFO: Setting shape: PEER: " + this
1390 + "; WINDOW: " + getWindow()
1391 + "; TARGET: " + target
1392 + "; SHAPE: " + shape);
1393 }
1394 XToolkit.awtLock();
1395 try {
1396 if (shape != null) {
1397 XlibWrapper.SetRectangularShape(
1398 XToolkit.getDisplay(),
1399 getWindow(),
1400 shape.getLoX(), shape.getLoY(),
1401 shape.getHiX(), shape.getHiY(),
1402 (shape.isRectangular() ? null : shape)
1403 );
1404 } else {
1405 XlibWrapper.SetRectangularShape(
1406 XToolkit.getDisplay(),
1407 getWindow(),
1408 0, 0,
1409 0, 0,
1410 null
1411 );
1412 }
1413 } finally {
1414 XToolkit.awtUnlock();
1415 }
1416 } else {
1417 if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1418 shapeLog.finer("*** WARNING: Shaping is NOT supported!");
1419 }
1420 }
1421 }
1422
1423 public boolean updateGraphicsData(GraphicsConfiguration gc) {
1424 int oldVisual = -1, newVisual = -1;
1425
1426 if (graphicsConfig != null) {
1427 oldVisual = graphicsConfig.getVisual();
1428 }
1429 if (gc != null && gc instanceof X11GraphicsConfig) {
1430 newVisual = ((X11GraphicsConfig)gc).getVisual();
1431 }
1432
1433 // If the new visual differs from the old one, the peer must be
1434 // recreated because X11 does not allow changing the visual on the fly.
1435 // So we even skip the initGraphicsConfiguration() call.
1436 // The initial assignment should happen though, hence the != -1 thing.
1437 if (oldVisual != -1 && oldVisual != newVisual) {
1438 return true;
1439 }
1440
1441 initGraphicsConfiguration();
1442 doValidateSurface();
1443 return false;
1444 }
1445 }
--- EOF ---