1 /* 2 * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.awt.windows; 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.Dimension; 34 import java.awt.Font; 35 import java.awt.FontMetrics; 36 import java.awt.Graphics; 37 import java.awt.GraphicsConfiguration; 38 import java.awt.GraphicsDevice; 39 import java.awt.Image; 40 import java.awt.Point; 41 import java.awt.Rectangle; 42 import java.awt.SystemColor; 43 import java.awt.Window; 44 import java.awt.dnd.DropTarget; 45 import java.awt.dnd.peer.DropTargetPeer; 46 import java.awt.event.FocusEvent; 47 import java.awt.event.InputEvent; 48 import java.awt.event.InvocationEvent; 49 import java.awt.event.KeyEvent; 50 import java.awt.event.MouseEvent; 51 import java.awt.event.MouseWheelEvent; 52 import java.awt.event.PaintEvent; 53 import java.awt.geom.AffineTransform; 54 import java.awt.image.BufferedImage; 55 import java.awt.image.ColorModel; 56 import java.awt.image.VolatileImage; 57 import java.awt.peer.ComponentPeer; 58 import java.awt.peer.ContainerPeer; 59 60 import sun.awt.AWTAccessor; 61 import sun.awt.PaintEventDispatcher; 62 import sun.awt.RepaintArea; 63 import sun.awt.SunToolkit; 64 import sun.awt.Win32GraphicsConfig; 65 import sun.awt.Win32GraphicsEnvironment; 66 import sun.awt.event.IgnorePaintEvent; 67 import sun.awt.image.SunVolatileImage; 68 import sun.java2d.InvalidPipeException; 69 import sun.java2d.ScreenUpdateManager; 70 import sun.java2d.SurfaceData; 71 import sun.java2d.d3d.D3DSurfaceData; 72 import sun.java2d.opengl.OGLSurfaceData; 73 import sun.java2d.pipe.Region; 74 import sun.util.logging.PlatformLogger; 75 76 public abstract class WComponentPeer extends WObjectPeer 77 implements ComponentPeer, DropTargetPeer 78 { 79 /** 80 * Handle to native window 81 */ 82 protected volatile long hwnd; 83 84 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WComponentPeer"); 85 private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.windows.shape.WComponentPeer"); 86 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.windows.focus.WComponentPeer"); 87 88 // ComponentPeer implementation 89 SurfaceData surfaceData; 90 91 private RepaintArea paintArea; 92 93 protected Win32GraphicsConfig winGraphicsConfig; 94 95 boolean isLayouting = false; 96 boolean paintPending = false; 97 int oldWidth = -1; 98 int oldHeight = -1; 99 private int numBackBuffers = 0; 100 private VolatileImage backBuffer = null; 101 private BufferCapabilities backBufferCaps = null; 102 103 // foreground, background and color are cached to avoid calling back 104 // into the Component. 105 private Color foreground; 106 private Color background; 107 private Font font; 108 109 @Override 110 public native boolean isObscured(); 111 @Override 112 public boolean canDetermineObscurity() { return true; } 113 114 // DropTarget support 115 116 int nDropTargets; 117 long nativeDropTargetContext; // native pointer 118 119 private synchronized native void pShow(); 120 synchronized native void hide(); 121 synchronized native void enable(); 122 synchronized native void disable(); 123 124 public long getHWnd() { 125 return hwnd; 126 } 127 128 /* New 1.1 API */ 129 @Override 130 public native Point getLocationOnScreen(); 131 132 /* New 1.1 API */ 133 @Override 134 public void setVisible(boolean b) { 135 if (b) { 136 show(); 137 } else { 138 hide(); 139 } 140 } 141 142 public void show() { 143 Dimension s = ((Component)target).getSize(); 144 oldHeight = s.height; 145 oldWidth = s.width; 146 pShow(); 147 } 148 149 /* New 1.1 API */ 150 @Override 151 public void setEnabled(boolean b) { 152 if (b) { 153 enable(); 154 } else { 155 disable(); 156 } 157 } 158 159 public int serialNum = 0; 160 161 private native void reshapeNoCheck(int x, int y, int width, int height); 162 163 /* New 1.1 API */ 164 @Override 165 public void setBounds(int x, int y, int width, int height, int op) { 166 // Should set paintPending before reahape to prevent 167 // thread race between paint events 168 // Native components do redraw after resize 169 paintPending = (width != oldWidth) || (height != oldHeight); 170 171 if ( (op & NO_EMBEDDED_CHECK) != 0 ) { 172 reshapeNoCheck(x, y, width, height); 173 } else { 174 reshape(x, y, width, height); 175 } 176 if ((width != oldWidth) || (height != oldHeight)) { 177 // Only recreate surfaceData if this setBounds is called 178 // for a resize; a simple move should not trigger a recreation 179 try { 180 replaceSurfaceData(); 181 } catch (InvalidPipeException e) { 182 // REMIND : what do we do if our surface creation failed? 183 } 184 oldWidth = width; 185 oldHeight = height; 186 } 187 188 serialNum++; 189 } 190 191 /* 192 * Called from native code (on Toolkit thread) in order to 193 * dynamically layout the Container during resizing 194 */ 195 void dynamicallyLayoutContainer() { 196 // If we got the WM_SIZING, this must be a Container, right? 197 // In fact, it must be the top-level Container. 198 if (log.isLoggable(PlatformLogger.Level.FINE)) { 199 Container parent = WToolkit.getNativeContainer((Component)target); 200 if (parent != null) { 201 log.fine("Assertion (parent == null) failed"); 202 } 203 } 204 final Container cont = (Container)target; 205 206 WToolkit.executeOnEventHandlerThread(cont, new Runnable() { 207 @Override 208 public void run() { 209 // Discarding old paint events doesn't seem to be necessary. 210 cont.invalidate(); 211 cont.validate(); 212 213 if (surfaceData instanceof D3DSurfaceData.D3DWindowSurfaceData || 214 surfaceData instanceof OGLSurfaceData) 215 { 216 // When OGL or D3D is enabled, it is necessary to 217 // replace the SurfaceData for each dynamic layout 218 // request so that the viewport stays in sync 219 // with the window bounds. 220 try { 221 replaceSurfaceData(); 222 } catch (InvalidPipeException e) { 223 // REMIND: this is unlikely to occur for OGL, but 224 // what do we do if surface creation fails? 225 } 226 } 227 228 // Forcing a paint here doesn't seem to be necessary. 229 // paintDamagedAreaImmediately(); 230 } 231 }); 232 } 233 234 /* 235 * Paints any portion of the component that needs updating 236 * before the call returns (similar to the Win32 API UpdateWindow) 237 */ 238 void paintDamagedAreaImmediately() { 239 // force Windows to send any pending WM_PAINT events so 240 // the damage area is updated on the Java side 241 updateWindow(); 242 // make sure paint events are transferred to main event queue 243 // for coalescing 244 SunToolkit.flushPendingEvents(); 245 // paint the damaged area 246 paintArea.paint(target, shouldClearRectBeforePaint()); 247 } 248 249 synchronized native void updateWindow(); 250 251 @Override 252 public void paint(Graphics g) { 253 ((Component)target).paint(g); 254 } 255 256 public void repaint(long tm, int x, int y, int width, int height) { 257 } 258 259 private static final double BANDING_DIVISOR = 4.0; 260 private native int[] createPrintedPixels(int srcX, int srcY, 261 int srcW, int srcH, 262 int alpha); 263 @Override 264 public void print(Graphics g) { 265 266 Component comp = (Component)target; 267 268 // To conserve memory usage, we will band the image. 269 270 int totalW = comp.getWidth(); 271 int totalH = comp.getHeight(); 272 273 int hInc = (int)(totalH / BANDING_DIVISOR); 274 if (hInc == 0) { 275 hInc = totalH; 276 } 277 278 for (int startY = 0; startY < totalH; startY += hInc) { 279 int endY = startY + hInc - 1; 280 if (endY >= totalH) { 281 endY = totalH - 1; 282 } 283 int h = endY - startY + 1; 284 285 Color bgColor = comp.getBackground(); 286 int[] pix = createPrintedPixels(0, startY, totalW, h, 287 bgColor == null ? 255 : bgColor.getAlpha()); 288 if (pix != null) { 289 BufferedImage bim = new BufferedImage(totalW, h, 290 BufferedImage.TYPE_INT_ARGB); 291 bim.setRGB(0, 0, totalW, h, pix, 0, totalW); 292 g.drawImage(bim, 0, startY, null); 293 bim.flush(); 294 } 295 } 296 297 comp.print(g); 298 } 299 300 @Override 301 public void coalescePaintEvent(PaintEvent e) { 302 Rectangle r = e.getUpdateRect(); 303 if (!(e instanceof IgnorePaintEvent)) { 304 paintArea.add(r, e.getID()); 305 } 306 307 if (log.isLoggable(PlatformLogger.Level.FINEST)) { 308 switch(e.getID()) { 309 case PaintEvent.UPDATE: 310 log.finest("coalescePaintEvent: UPDATE: add: x = " + 311 r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height); 312 return; 313 case PaintEvent.PAINT: 314 log.finest("coalescePaintEvent: PAINT: add: x = " + 315 r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height); 316 return; 317 } 318 } 319 } 320 321 public synchronized native void reshape(int x, int y, int width, int height); 322 323 // returns true if the event has been handled and shouldn't be propagated 324 // though handleEvent method chain - e.g. WTextFieldPeer returns true 325 // on handling '\n' to prevent it from being passed to native code 326 public boolean handleJavaKeyEvent(KeyEvent e) { return false; } 327 328 public void handleJavaMouseEvent(MouseEvent e) { 329 switch (e.getID()) { 330 case MouseEvent.MOUSE_PRESSED: 331 // Note that Swing requests focus in its own mouse event handler. 332 if (target == e.getSource() && 333 !((Component)target).isFocusOwner() && 334 WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target)) 335 { 336 WKeyboardFocusManagerPeer.requestFocusFor((Component)target, 337 FocusEvent.Cause.MOUSE_EVENT); 338 } 339 break; 340 } 341 } 342 343 native void nativeHandleEvent(AWTEvent e); 344 345 @Override 346 @SuppressWarnings("fallthrough") 347 public void handleEvent(AWTEvent e) { 348 int id = e.getID(); 349 350 if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && 351 ((Component)target).isEnabled()) 352 { 353 if (e instanceof MouseEvent && !(e instanceof MouseWheelEvent)) { 354 handleJavaMouseEvent((MouseEvent) e); 355 } else if (e instanceof KeyEvent) { 356 if (handleJavaKeyEvent((KeyEvent)e)) { 357 return; 358 } 359 } 360 } 361 362 switch(id) { 363 case PaintEvent.PAINT: 364 // Got native painting 365 paintPending = false; 366 // Fallthrough to next statement 367 case PaintEvent.UPDATE: 368 // Skip all painting while layouting and all UPDATEs 369 // while waiting for native paint 370 if (!isLayouting && ! paintPending) { 371 paintArea.paint(target,shouldClearRectBeforePaint()); 372 } 373 return; 374 case FocusEvent.FOCUS_LOST: 375 case FocusEvent.FOCUS_GAINED: 376 handleJavaFocusEvent((FocusEvent)e); 377 default: 378 break; 379 } 380 381 // Call the native code 382 nativeHandleEvent(e); 383 } 384 385 void handleJavaFocusEvent(FocusEvent fe) { 386 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 387 focusLog.finer(fe.toString()); 388 } 389 setFocus(fe.getID() == FocusEvent.FOCUS_GAINED); 390 } 391 392 native void setFocus(boolean doSetFocus); 393 394 @Override 395 public Dimension getMinimumSize() { 396 return ((Component)target).getSize(); 397 } 398 399 @Override 400 public Dimension getPreferredSize() { 401 return getMinimumSize(); 402 } 403 404 // Do nothing for heavyweight implementation 405 @Override 406 public void layout() {} 407 408 public Rectangle getBounds() { 409 return ((Component)target).getBounds(); 410 } 411 412 @Override 413 public boolean isFocusable() { 414 return false; 415 } 416 417 /* 418 * Return the GraphicsConfiguration associated with this peer, either 419 * the locally stored winGraphicsConfig, or that of the target Component. 420 */ 421 @Override 422 public GraphicsConfiguration getGraphicsConfiguration() { 423 if (winGraphicsConfig != null) { 424 return winGraphicsConfig; 425 } 426 else { 427 // we don't need a treelock here, since 428 // Component.getGraphicsConfiguration() gets it itself. 429 return ((Component)target).getGraphicsConfiguration(); 430 } 431 } 432 433 public SurfaceData getSurfaceData() { 434 return surfaceData; 435 } 436 437 /** 438 * Creates new surfaceData object and invalidates the previous 439 * surfaceData object. 440 * Replacing the surface data should never lock on any resources which are 441 * required by other threads which may have them and may require 442 * the tree-lock. 443 * This is a degenerate version of replaceSurfaceData(numBackBuffers), so 444 * just call that version with our current numBackBuffers. 445 */ 446 public void replaceSurfaceData() { 447 replaceSurfaceData(this.numBackBuffers, this.backBufferCaps); 448 } 449 450 public void createScreenSurface(boolean isResize) 451 { 452 Win32GraphicsConfig gc = (Win32GraphicsConfig)getGraphicsConfiguration(); 453 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); 454 455 surfaceData = mgr.createScreenSurface(gc, this, numBackBuffers, isResize); 456 } 457 458 459 /** 460 * Multi-buffer version of replaceSurfaceData. This version is called 461 * by createBuffers(), which needs to acquire the same locks in the same 462 * order, but also needs to perform additional functions inside the 463 * locks. 464 */ 465 public void replaceSurfaceData(int newNumBackBuffers, 466 BufferCapabilities caps) 467 { 468 SurfaceData oldData = null; 469 VolatileImage oldBB = null; 470 synchronized(((Component)target).getTreeLock()) { 471 synchronized(this) { 472 if (pData == 0) { 473 return; 474 } 475 numBackBuffers = newNumBackBuffers; 476 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); 477 oldData = surfaceData; 478 mgr.dropScreenSurface(oldData); 479 createScreenSurface(true); 480 if (oldData != null) { 481 oldData.invalidate(); 482 } 483 484 oldBB = backBuffer; 485 if (numBackBuffers > 0) { 486 // set the caps first, they're used when creating the bb 487 backBufferCaps = caps; 488 Win32GraphicsConfig gc = 489 (Win32GraphicsConfig)getGraphicsConfiguration(); 490 backBuffer = gc.createBackBuffer(this); 491 } else if (backBuffer != null) { 492 backBufferCaps = null; 493 backBuffer = null; 494 } 495 } 496 } 497 // it would be better to do this before we create new ones, 498 // but then we'd run into deadlock issues 499 if (oldData != null) { 500 oldData.flush(); 501 // null out the old data to make it collected faster 502 oldData = null; 503 } 504 if (oldBB != null) { 505 oldBB.flush(); 506 // null out the old data to make it collected faster 507 oldData = null; 508 } 509 } 510 511 public void replaceSurfaceDataLater() { 512 Runnable r = new Runnable() { 513 @Override 514 public void run() { 515 // Shouldn't do anything if object is disposed in meanwhile 516 // No need for sync as disposeAction in Window is performed 517 // on EDT 518 if (!isDisposed()) { 519 try { 520 replaceSurfaceData(); 521 } catch (InvalidPipeException e) { 522 // REMIND : what do we do if our surface creation failed? 523 } 524 } 525 } 526 }; 527 Component c = (Component)target; 528 // Fix 6255371. 529 if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) { 530 postEvent(new InvocationEvent(c, r)); 531 } 532 } 533 534 @Override 535 public boolean updateGraphicsData(GraphicsConfiguration gc) { 536 var old = getGraphicsConfiguration().getDefaultTransform(); 537 winGraphicsConfig = (Win32GraphicsConfig)gc; 538 if (gc != null && !old.equals(gc.getDefaultTransform())) { 539 syncBounds(); // the bound of the peer depends on the DPI 540 } 541 try { 542 replaceSurfaceData(); 543 } catch (InvalidPipeException e) { 544 // REMIND : what do we do if our surface creation failed? 545 } 546 return false; 547 } 548 549 /** 550 * Make sure that the native peer's coordinates are in sync with the target. 551 */ 552 void syncBounds(){ 553 Rectangle r = ((Component)target).getBounds(); 554 setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS); 555 } 556 557 //This will return null for Components not yet added to a Container 558 @Override 559 public ColorModel getColorModel() { 560 GraphicsConfiguration gc = getGraphicsConfiguration(); 561 if (gc != null) { 562 return gc.getColorModel(); 563 } 564 else { 565 return null; 566 } 567 } 568 569 //This will return null for Components not yet added to a Container 570 public ColorModel getDeviceColorModel() { 571 Win32GraphicsConfig gc = 572 (Win32GraphicsConfig)getGraphicsConfiguration(); 573 if (gc != null) { 574 return gc.getDeviceColorModel(); 575 } 576 else { 577 return null; 578 } 579 } 580 581 //Returns null for Components not yet added to a Container 582 public ColorModel getColorModel(int transparency) { 583 // return WToolkit.config.getColorModel(transparency); 584 GraphicsConfiguration gc = getGraphicsConfiguration(); 585 if (gc != null) { 586 return gc.getColorModel(transparency); 587 } 588 else { 589 return null; 590 } 591 } 592 593 // fallback default font object 594 static final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); 595 596 @Override 597 public Graphics getGraphics() { 598 if (isDisposed()) { 599 return null; 600 } 601 602 Component target = (Component)getTarget(); 603 Window window = SunToolkit.getContainingWindow(target); 604 if (window != null) { 605 final WWindowPeer wpeer = AWTAccessor.getComponentAccessor() 606 .getPeer(window); 607 if (wpeer != null) { 608 Graphics g = wpeer.getTranslucentGraphics(); 609 // getTranslucentGraphics() returns non-null value for non-opaque windows only 610 if (g != null) { 611 // Non-opaque windows do not support heavyweight children. 612 // Redirect all painting to the Window's Graphics instead. 613 // The caller is responsible for calling the 614 // WindowPeer.updateWindow() after painting has finished. 615 int x = 0, y = 0; 616 for (Component c = target; c != window; c = c.getParent()) { 617 x += c.getX(); 618 y += c.getY(); 619 } 620 621 g.translate(x, y); 622 g.clipRect(0, 0, target.getWidth(), target.getHeight()); 623 624 return g; 625 } 626 } 627 } 628 629 SurfaceData surfaceData = this.surfaceData; 630 if (surfaceData != null) { 631 /* Fix for bug 4746122. Color and Font shouldn't be null */ 632 Color bgColor = background; 633 if (bgColor == null) { 634 bgColor = SystemColor.window; 635 } 636 Color fgColor = foreground; 637 if (fgColor == null) { 638 fgColor = SystemColor.windowText; 639 } 640 Font font = this.font; 641 if (font == null) { 642 font = defaultFont; 643 } 644 ScreenUpdateManager mgr = 645 ScreenUpdateManager.getInstance(); 646 return mgr.createGraphics(surfaceData, this, fgColor, 647 bgColor, font); 648 } 649 return null; 650 } 651 @Override 652 public FontMetrics getFontMetrics(Font font) { 653 return WFontMetrics.getFontMetrics(font); 654 } 655 656 private synchronized native void _dispose(); 657 @Override 658 protected void disposeImpl() { 659 SurfaceData oldData = surfaceData; 660 surfaceData = null; 661 ScreenUpdateManager.getInstance().dropScreenSurface(oldData); 662 oldData.invalidate(); 663 // remove from updater before calling targetDisposedPeer 664 WToolkit.targetDisposedPeer(target, this); 665 _dispose(); 666 } 667 668 public void disposeLater() { 669 postEvent(new InvocationEvent(target, new Runnable() { 670 @Override 671 public void run() { 672 dispose(); 673 } 674 })); 675 } 676 677 @Override 678 public synchronized void setForeground(Color c) { 679 foreground = c; 680 _setForeground(c.getRGB()); 681 } 682 683 @Override 684 public synchronized void setBackground(Color c) { 685 background = c; 686 _setBackground(c.getRGB()); 687 } 688 689 /** 690 * This method is intentionally not synchronized as it is called while 691 * holding other locks. 692 * 693 * @see sun.java2d.d3d.D3DScreenUpdateManager#validate 694 */ 695 public Color getBackgroundNoSync() { 696 return background; 697 } 698 699 private native void _setForeground(int rgb); 700 private native void _setBackground(int rgb); 701 702 @Override 703 public synchronized void setFont(Font f) { 704 font = f; 705 _setFont(f); 706 } 707 synchronized native void _setFont(Font f); 708 @Override 709 public void updateCursorImmediately() { 710 WGlobalCursorManager.getCursorManager().updateCursorImmediately(); 711 } 712 713 // TODO: consider moving it to KeyboardFocusManagerPeerImpl 714 @Override 715 public boolean requestFocus(Component lightweightChild, boolean temporary, 716 boolean focusedWindowChangeAllowed, long time, 717 FocusEvent.Cause cause) 718 { 719 if (WKeyboardFocusManagerPeer. 720 processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary, 721 focusedWindowChangeAllowed, time)) 722 { 723 return true; 724 } 725 726 int result = WKeyboardFocusManagerPeer 727 .shouldNativelyFocusHeavyweight((Component)target, lightweightChild, 728 temporary, focusedWindowChangeAllowed, 729 time, cause); 730 731 switch (result) { 732 case WKeyboardFocusManagerPeer.SNFH_FAILURE: 733 return false; 734 case WKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED: 735 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 736 focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target); 737 } 738 Window parentWindow = SunToolkit.getContainingWindow((Component)target); 739 if (parentWindow == null) { 740 return rejectFocusRequestHelper("WARNING: Parent window is null"); 741 } 742 final WWindowPeer wpeer = AWTAccessor.getComponentAccessor() 743 .getPeer(parentWindow); 744 if (wpeer == null) { 745 return rejectFocusRequestHelper("WARNING: Parent window's peer is null"); 746 } 747 boolean res = wpeer.requestWindowFocus(cause); 748 749 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 750 focusLog.finer("Requested window focus: " + res); 751 } 752 // If parent window can be made focused and has been made focused(synchronously) 753 // then we can proceed with children, otherwise we retreat. 754 if (!(res && parentWindow.isFocused())) { 755 return rejectFocusRequestHelper("Waiting for asynchronous processing of the request"); 756 } 757 return WKeyboardFocusManagerPeer.deliverFocus(lightweightChild, 758 (Component)target, 759 temporary, 760 focusedWindowChangeAllowed, 761 time, cause); 762 763 case WKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: 764 // Either lightweight or excessive request - all events are generated. 765 return true; 766 } 767 return false; 768 } 769 770 private boolean rejectFocusRequestHelper(String logMsg) { 771 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 772 focusLog.finer(logMsg); 773 } 774 WKeyboardFocusManagerPeer.removeLastFocusRequest((Component)target); 775 return false; 776 } 777 778 @Override 779 public Image createImage(int width, int height) { 780 Win32GraphicsConfig gc = 781 (Win32GraphicsConfig)getGraphicsConfiguration(); 782 return gc.createAcceleratedImage((Component)target, width, height); 783 } 784 785 @Override 786 public VolatileImage createVolatileImage(int width, int height) { 787 return new SunVolatileImage((Component)target, width, height); 788 } 789 790 // Object overrides 791 792 public String toString() { 793 return getClass().getName() + "[" + target + "]"; 794 } 795 796 // Toolkit & peer internals 797 798 private int updateX1, updateY1, updateX2, updateY2; 799 800 WComponentPeer(Component target) { 801 this.target = target; 802 this.paintArea = new RepaintArea(); 803 create(getNativeParent()); 804 // fix for 5088782: check if window object is created successfully 805 checkCreation(); 806 807 createScreenSurface(false); 808 initialize(); 809 start(); // Initialize enable/disable state, turn on callbacks 810 } 811 abstract void create(WComponentPeer parent); 812 813 /** 814 * Gets the native parent of this peer. We use the term "parent" explicitly, 815 * because we override the method in top-level window peer implementations. 816 * 817 * @return the parent container/owner of this peer. 818 */ 819 WComponentPeer getNativeParent() { 820 Container parent = SunToolkit.getNativeContainer((Component) target); 821 return (WComponentPeer) WToolkit.targetToPeer(parent); 822 } 823 824 protected void checkCreation() 825 { 826 if ((hwnd == 0) || (pData == 0)) 827 { 828 if (createError != null) 829 { 830 throw createError; 831 } 832 else 833 { 834 throw new InternalError("couldn't create component peer"); 835 } 836 } 837 } 838 839 synchronized native void start(); 840 841 void initialize() { 842 if (((Component)target).isVisible()) { 843 show(); // the wnd starts hidden 844 } 845 Color fg = ((Component)target).getForeground(); 846 if (fg != null) { 847 setForeground(fg); 848 } 849 // Set background color in C++, to avoid inheriting a parent's color. 850 Font f = ((Component)target).getFont(); 851 if (f != null) { 852 setFont(f); 853 } 854 if (! ((Component)target).isEnabled()) { 855 disable(); 856 } 857 Rectangle r = ((Component)target).getBounds(); 858 setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS); 859 } 860 861 // Callbacks for window-system events to the frame 862 863 // Invoke a update() method call on the target 864 void handleRepaint(int x, int y, int w, int h) { 865 // Repaints are posted from updateClient now... 866 } 867 868 // Invoke a paint() method call on the target, after clearing the 869 // damaged area. 870 void handleExpose(int x, int y, int w, int h) { 871 // Bug ID 4081126 & 4129709 - can't do the clearRect() here, 872 // since it interferes with the java thread working in the 873 // same window on multi-processor NT machines. 874 875 postPaintIfNecessary(x, y, w, h); 876 } 877 878 /* Invoke a paint() method call on the target, without clearing the 879 * damaged area. This is normally called by a native control after 880 * it has painted itself. 881 * 882 * NOTE: This is called on the privileged toolkit thread. Do not 883 * call directly into user code using this thread! 884 */ 885 public void handlePaint(int x, int y, int w, int h) { 886 postPaintIfNecessary(x, y, w, h); 887 } 888 889 private void postPaintIfNecessary(int x, int y, int w, int h) { 890 if ( !AWTAccessor.getComponentAccessor().getIgnoreRepaint( (Component) target) ) { 891 PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher(). 892 createPaintEvent((Component)target, x, y, w, h); 893 if (event != null) { 894 postEvent(event); 895 } 896 } 897 } 898 899 /* 900 * Post an event. Queue it for execution by the callback thread. 901 */ 902 void postEvent(AWTEvent event) { 903 preprocessPostEvent(event); 904 WToolkit.postEvent(WToolkit.targetToAppContext(target), event); 905 } 906 907 void preprocessPostEvent(AWTEvent event) {} 908 909 // Routines to support deferred window positioning. 910 public void beginLayout() { 911 // Skip all painting till endLayout 912 isLayouting = true; 913 } 914 915 public void endLayout() { 916 if(!paintArea.isEmpty() && !paintPending && 917 !((Component)target).getIgnoreRepaint()) { 918 // if not waiting for native painting repaint damaged area 919 postEvent(new PaintEvent((Component)target, PaintEvent.PAINT, 920 new Rectangle())); 921 } 922 isLayouting = false; 923 } 924 925 public native void beginValidate(); 926 public native void endValidate(); 927 928 /** 929 * register a DropTarget with this native peer 930 */ 931 932 @Override 933 public synchronized void addDropTarget(DropTarget dt) { 934 if (nDropTargets == 0) { 935 nativeDropTargetContext = addNativeDropTarget(); 936 } 937 nDropTargets++; 938 } 939 940 /** 941 * unregister a DropTarget with this native peer 942 */ 943 944 @Override 945 public synchronized void removeDropTarget(DropTarget dt) { 946 nDropTargets--; 947 if (nDropTargets == 0) { 948 removeNativeDropTarget(); 949 nativeDropTargetContext = 0; 950 } 951 } 952 953 /** 954 * add the native peer's AwtDropTarget COM object 955 * @return reference to AwtDropTarget object 956 */ 957 958 native long addNativeDropTarget(); 959 960 /** 961 * remove the native peer's AwtDropTarget COM object 962 */ 963 964 native void removeNativeDropTarget(); 965 native boolean nativeHandlesWheelScrolling(); 966 967 @Override 968 public boolean handlesWheelScrolling() { 969 // should this be cached? 970 return nativeHandlesWheelScrolling(); 971 } 972 973 // Returns true if we are inside begin/endLayout and 974 // are waiting for native painting 975 public boolean isPaintPending() { 976 return paintPending && isLayouting; 977 } 978 979 /** 980 * The following multibuffering-related methods delegate to our 981 * associated GraphicsConfig (Win or WGL) to handle the appropriate 982 * native windowing system specific actions. 983 */ 984 985 @Override 986 public void createBuffers(int numBuffers, BufferCapabilities caps) 987 throws AWTException 988 { 989 Win32GraphicsConfig gc = 990 (Win32GraphicsConfig)getGraphicsConfiguration(); 991 gc.assertOperationSupported((Component)target, numBuffers, caps); 992 993 // Re-create the primary surface with the new number of back buffers 994 try { 995 replaceSurfaceData(numBuffers - 1, caps); 996 } catch (InvalidPipeException e) { 997 throw new AWTException(e.getMessage()); 998 } 999 } 1000 1001 @Override 1002 public void destroyBuffers() { 1003 replaceSurfaceData(0, null); 1004 } 1005 1006 @Override 1007 public void flip(int x1, int y1, int x2, int y2, 1008 BufferCapabilities.FlipContents flipAction) 1009 { 1010 VolatileImage backBuffer = this.backBuffer; 1011 if (backBuffer == null) { 1012 throw new IllegalStateException("Buffers have not been created"); 1013 } 1014 Win32GraphicsConfig gc = 1015 (Win32GraphicsConfig)getGraphicsConfiguration(); 1016 gc.flip(this, (Component)target, backBuffer, x1, y1, x2, y2, flipAction); 1017 } 1018 1019 @Override 1020 public synchronized Image getBackBuffer() { 1021 Image backBuffer = this.backBuffer; 1022 if (backBuffer == null) { 1023 throw new IllegalStateException("Buffers have not been created"); 1024 } 1025 return backBuffer; 1026 } 1027 public BufferCapabilities getBackBufferCaps() { 1028 return backBufferCaps; 1029 } 1030 public int getBackBuffersNum() { 1031 return numBackBuffers; 1032 } 1033 1034 /* override and return false on components that DO NOT require 1035 a clearRect() before painting (i.e. native components) */ 1036 public boolean shouldClearRectBeforePaint() { 1037 return true; 1038 } 1039 1040 native void pSetParent(ComponentPeer newNativeParent); 1041 1042 /** 1043 * @see java.awt.peer.ComponentPeer#reparent 1044 */ 1045 @Override 1046 public void reparent(ContainerPeer newNativeParent) { 1047 pSetParent(newNativeParent); 1048 } 1049 1050 /** 1051 * @see java.awt.peer.ComponentPeer#isReparentSupported 1052 */ 1053 @Override 1054 public boolean isReparentSupported() { 1055 return true; 1056 } 1057 1058 public void setBoundsOperation(int operation) { 1059 } 1060 1061 private volatile boolean isAccelCapable = true; 1062 1063 /** 1064 * Returns whether this component is capable of being hw accelerated. 1065 * More specifically, whether rendering to this component or a 1066 * BufferStrategy's back-buffer for this component can be hw accelerated. 1067 * 1068 * Conditions which could prevent hw acceleration include the toplevel 1069 * window containing this component being 1070 * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT 1071 * PERPIXEL_TRANSLUCENT}. 1072 * 1073 * Another condition is if Xor paint mode was detected when rendering 1074 * to an on-screen accelerated surface associated with this peer. 1075 * in this case both on- and off-screen acceleration for this peer is 1076 * disabled. 1077 * 1078 * @return {@code true} if this component is capable of being hw 1079 * accelerated, {@code false} otherwise 1080 * @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT 1081 */ 1082 public boolean isAccelCapable() { 1083 if (!isAccelCapable || 1084 !isContainingTopLevelAccelCapable((Component)target)) 1085 { 1086 return false; 1087 } 1088 1089 boolean isTranslucent = 1090 SunToolkit.isContainingTopLevelTranslucent((Component)target); 1091 // D3D/OGL and translucent windows interacted poorly in Windows XP; 1092 // these problems are no longer present in Vista 1093 return !isTranslucent || Win32GraphicsEnvironment.isVistaOS(); 1094 } 1095 1096 /** 1097 * Disables acceleration for this peer. 1098 */ 1099 public void disableAcceleration() { 1100 isAccelCapable = false; 1101 } 1102 1103 1104 native void setRectangularShape(int lox, int loy, int hix, int hiy, 1105 Region region); 1106 1107 1108 // REMIND: Temp workaround for issues with using HW acceleration 1109 // in the browser on Vista when DWM is enabled. 1110 // @return true if the toplevel container is not an EmbeddedFrame or 1111 // if this EmbeddedFrame is acceleration capable, false otherwise 1112 private static final boolean isContainingTopLevelAccelCapable(Component c) { 1113 while (c != null && !(c instanceof WEmbeddedFrame)) { 1114 c = c.getParent(); 1115 } 1116 if (c == null) { 1117 return true; 1118 } 1119 final WEmbeddedFramePeer peer = AWTAccessor.getComponentAccessor() 1120 .getPeer(c); 1121 return peer.isAccelCapable(); 1122 } 1123 1124 /** 1125 * Applies the shape to the native component window. 1126 * @since 1.7 1127 */ 1128 @Override 1129 public void applyShape(Region shape) { 1130 if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) { 1131 shapeLog.finer("*** INFO: Setting shape: PEER: " + this 1132 + "; TARGET: " + target 1133 + "; SHAPE: " + shape); 1134 } 1135 1136 if (shape != null) { 1137 AffineTransform tx = winGraphicsConfig.getDefaultTransform(); 1138 double scaleX = tx.getScaleX(); 1139 double scaleY = tx.getScaleY(); 1140 if (scaleX != 1 || scaleY != 1) { 1141 shape = shape.getScaledRegion(scaleX, scaleY); 1142 } 1143 setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(), 1144 (shape.isRectangular() ? null : shape)); 1145 } else { 1146 setRectangularShape(0, 0, 0, 0, null); 1147 } 1148 } 1149 1150 /** 1151 * Lowers this component at the bottom of the above component. If the above parameter 1152 * is null then the method places this component at the top of the Z-order. 1153 */ 1154 @Override 1155 public void setZOrder(ComponentPeer above) { 1156 long aboveHWND = (above != null) ? ((WComponentPeer)above).getHWnd() : 0; 1157 1158 setZOrder(aboveHWND); 1159 } 1160 1161 private native void setZOrder(long above); 1162 1163 public boolean isLightweightFramePeer() { 1164 return false; 1165 } 1166 }