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