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