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