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