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