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