| /* |
| * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| package sun.awt.windows; |
| |
| import java.awt.*; |
| import java.awt.peer.*; |
| import java.awt.image.VolatileImage; |
| import sun.awt.RepaintArea; |
| import sun.awt.CausedFocusEvent; |
| import sun.awt.image.SunVolatileImage; |
| import sun.awt.image.ToolkitImage; |
| import java.awt.image.BufferedImage; |
| import java.awt.image.ImageProducer; |
| import java.awt.image.ImageObserver; |
| import java.awt.image.ColorModel; |
| import java.awt.event.PaintEvent; |
| import java.awt.event.InvocationEvent; |
| import java.awt.event.KeyEvent; |
| import java.awt.event.FocusEvent; |
| import java.awt.event.MouseEvent; |
| import java.awt.event.MouseWheelEvent; |
| import java.awt.event.InputEvent; |
| import sun.awt.Win32GraphicsConfig; |
| import sun.awt.Win32GraphicsEnvironment; |
| import sun.java2d.InvalidPipeException; |
| import sun.java2d.SurfaceData; |
| import sun.java2d.ScreenUpdateManager; |
| import sun.java2d.d3d.D3DSurfaceData; |
| import sun.java2d.opengl.OGLSurfaceData; |
| import sun.java2d.pipe.Region; |
| import sun.awt.DisplayChangedListener; |
| import sun.awt.PaintEventDispatcher; |
| import sun.awt.SunToolkit; |
| import sun.awt.event.IgnorePaintEvent; |
| |
| import java.awt.dnd.DropTarget; |
| import java.awt.dnd.peer.DropTargetPeer; |
| import sun.awt.ComponentAccessor; |
| |
| import java.util.logging.*; |
| |
| |
| public abstract class WComponentPeer extends WObjectPeer |
| implements ComponentPeer, DropTargetPeer |
| { |
| /** |
| * Handle to native window |
| */ |
| protected volatile long hwnd; |
| |
| private static final Logger log = Logger.getLogger("sun.awt.windows.WComponentPeer"); |
| private static final Logger shapeLog = Logger.getLogger("sun.awt.windows.shape.WComponentPeer"); |
| private static final Logger focusLog = Logger.getLogger("sun.awt.windows.focus.WComponentPeer"); |
| |
| // ComponentPeer implementation |
| SurfaceData surfaceData; |
| |
| private RepaintArea paintArea; |
| |
| protected Win32GraphicsConfig winGraphicsConfig; |
| |
| boolean isLayouting = false; |
| boolean paintPending = false; |
| int oldWidth = -1; |
| int oldHeight = -1; |
| private int numBackBuffers = 0; |
| private VolatileImage backBuffer = null; |
| private BufferCapabilities backBufferCaps = null; |
| |
| // foreground, background and color are cached to avoid calling back |
| // into the Component. |
| private Color foreground; |
| private Color background; |
| private Font font; |
| |
| public native boolean isObscured(); |
| public boolean canDetermineObscurity() { return true; } |
| |
| // DropTarget support |
| |
| int nDropTargets; |
| long nativeDropTargetContext; // native pointer |
| |
| public synchronized native void pShow(); |
| public synchronized native void hide(); |
| public synchronized native void enable(); |
| public synchronized native void disable(); |
| |
| public long getHWnd() { |
| return hwnd; |
| } |
| |
| /* New 1.1 API */ |
| public native Point getLocationOnScreen(); |
| |
| /* New 1.1 API */ |
| public void setVisible(boolean b) { |
| if (b) { |
| show(); |
| } else { |
| hide(); |
| } |
| } |
| |
| public void show() { |
| Dimension s = ((Component)target).getSize(); |
| oldHeight = s.height; |
| oldWidth = s.width; |
| pShow(); |
| } |
| |
| /* New 1.1 API */ |
| public void setEnabled(boolean b) { |
| if (b) { |
| enable(); |
| } else { |
| disable(); |
| } |
| } |
| |
| public int serialNum = 0; |
| |
| private native void reshapeNoCheck(int x, int y, int width, int height); |
| |
| /* New 1.1 API */ |
| public void setBounds(int x, int y, int width, int height, int op) { |
| // Should set paintPending before reahape to prevent |
| // thread race between paint events |
| // Native components do redraw after resize |
| paintPending = (width != oldWidth) || (height != oldHeight); |
| |
| if ( (op & NO_EMBEDDED_CHECK) != 0 ) { |
| reshapeNoCheck(x, y, width, height); |
| } else { |
| reshape(x, y, width, height); |
| } |
| if ((width != oldWidth) || (height != oldHeight)) { |
| // Only recreate surfaceData if this setBounds is called |
| // for a resize; a simple move should not trigger a recreation |
| try { |
| replaceSurfaceData(); |
| } catch (InvalidPipeException e) { |
| // REMIND : what do we do if our surface creation failed? |
| } |
| oldWidth = width; |
| oldHeight = height; |
| } |
| |
| serialNum++; |
| } |
| |
| /* |
| * Called from native code (on Toolkit thread) in order to |
| * dynamically layout the Container during resizing |
| */ |
| void dynamicallyLayoutContainer() { |
| // If we got the WM_SIZING, this must be a Container, right? |
| // In fact, it must be the top-level Container. |
| if (log.isLoggable(Level.FINE)) { |
| Container parent = WToolkit.getNativeContainer((Component)target); |
| if (parent != null) { |
| log.log(Level.FINE, "Assertion (parent == null) failed"); |
| } |
| } |
| final Container cont = (Container)target; |
| |
| WToolkit.executeOnEventHandlerThread(cont, new Runnable() { |
| public void run() { |
| // Discarding old paint events doesn't seem to be necessary. |
| cont.invalidate(); |
| cont.validate(); |
| |
| if (surfaceData instanceof D3DSurfaceData.D3DWindowSurfaceData || |
| surfaceData instanceof OGLSurfaceData) |
| { |
| // When OGL or D3D is enabled, it is necessary to |
| // replace the SurfaceData for each dynamic layout |
| // request so that the viewport stays in sync |
| // with the window bounds. |
| try { |
| replaceSurfaceData(); |
| } catch (InvalidPipeException e) { |
| // REMIND: this is unlikely to occur for OGL, but |
| // what do we do if surface creation fails? |
| } |
| } |
| |
| // Forcing a paint here doesn't seem to be necessary. |
| // paintDamagedAreaImmediately(); |
| } |
| }); |
| } |
| |
| /* |
| * Paints any portion of the component that needs updating |
| * before the call returns (similar to the Win32 API UpdateWindow) |
| */ |
| void paintDamagedAreaImmediately() { |
| // force Windows to send any pending WM_PAINT events so |
| // the damage area is updated on the Java side |
| updateWindow(); |
| // make sure paint events are transferred to main event queue |
| // for coalescing |
| WToolkit.getWToolkit().flushPendingEvents(); |
| // paint the damaged area |
| paintArea.paint(target, shouldClearRectBeforePaint()); |
| } |
| |
| native synchronized void updateWindow(); |
| |
| public void paint(Graphics g) { |
| ((Component)target).paint(g); |
| } |
| |
| public void repaint(long tm, int x, int y, int width, int height) { |
| } |
| |
| private static final double BANDING_DIVISOR = 4.0; |
| private native int[] createPrintedPixels(int srcX, int srcY, |
| int srcW, int srcH); |
| public void print(Graphics g) { |
| |
| Component comp = (Component)target; |
| |
| // To conserve memory usage, we will band the image. |
| |
| int totalW = comp.getWidth(); |
| int totalH = comp.getHeight(); |
| |
| int hInc = (int)(totalH / BANDING_DIVISOR); |
| if (hInc == 0) { |
| hInc = totalH; |
| } |
| |
| for (int startY = 0; startY < totalH; startY += hInc) { |
| int endY = startY + hInc - 1; |
| if (endY >= totalH) { |
| endY = totalH - 1; |
| } |
| int h = endY - startY + 1; |
| |
| int[] pix = createPrintedPixels(0, startY, totalW, h); |
| if (pix != null) { |
| BufferedImage bim = new BufferedImage(totalW, h, |
| BufferedImage.TYPE_INT_ARGB); |
| bim.setRGB(0, 0, totalW, h, pix, 0, totalW); |
| g.drawImage(bim, 0, startY, null); |
| bim.flush(); |
| } |
| } |
| |
| comp.print(g); |
| } |
| |
| public void coalescePaintEvent(PaintEvent e) { |
| Rectangle r = e.getUpdateRect(); |
| if (!(e instanceof IgnorePaintEvent)) { |
| paintArea.add(r, e.getID()); |
| } |
| |
| if (log.isLoggable(Level.FINEST)) { |
| switch(e.getID()) { |
| case PaintEvent.UPDATE: |
| log.log(Level.FINEST, "coalescePaintEvent: UPDATE: add: x = " + |
| r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height); |
| return; |
| case PaintEvent.PAINT: |
| log.log(Level.FINEST, "coalescePaintEvent: PAINT: add: x = " + |
| r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height); |
| return; |
| } |
| } |
| } |
| |
| public synchronized native void reshape(int x, int y, int width, int height); |
| |
| // returns true if the event has been handled and shouldn't be propagated |
| // though handleEvent method chain - e.g. WTextFieldPeer returns true |
| // on handling '\n' to prevent it from being passed to native code |
| public boolean handleJavaKeyEvent(KeyEvent e) { return false; } |
| |
| public void handleJavaMouseEvent(MouseEvent e) { |
| switch (e.getID()) { |
| case MouseEvent.MOUSE_PRESSED: |
| // Note that Swing requests focus in its own mouse event handler. |
| if (target == e.getSource() && |
| !((Component)target).isFocusOwner() && |
| WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target)) |
| { |
| WKeyboardFocusManagerPeer.requestFocusFor((Component)target, |
| CausedFocusEvent.Cause.MOUSE_EVENT); |
| } |
| break; |
| } |
| } |
| |
| native void nativeHandleEvent(AWTEvent e); |
| |
| public void handleEvent(AWTEvent e) { |
| int id = e.getID(); |
| |
| if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && |
| ((Component)target).isEnabled()) |
| { |
| if (e instanceof MouseEvent && !(e instanceof MouseWheelEvent)) { |
| handleJavaMouseEvent((MouseEvent) e); |
| } else if (e instanceof KeyEvent) { |
| if (handleJavaKeyEvent((KeyEvent)e)) { |
| return; |
| } |
| } |
| } |
| |
| switch(id) { |
| case PaintEvent.PAINT: |
| // Got native painting |
| paintPending = false; |
| // Fallthrough to next statement |
| case PaintEvent.UPDATE: |
| // Skip all painting while layouting and all UPDATEs |
| // while waiting for native paint |
| if (!isLayouting && ! paintPending) { |
| paintArea.paint(target,shouldClearRectBeforePaint()); |
| } |
| return; |
| case FocusEvent.FOCUS_LOST: |
| case FocusEvent.FOCUS_GAINED: |
| handleJavaFocusEvent((FocusEvent)e); |
| default: |
| break; |
| } |
| |
| // Call the native code |
| nativeHandleEvent(e); |
| } |
| |
| void handleJavaFocusEvent(FocusEvent fe) { |
| if (focusLog.isLoggable(Level.FINER)) focusLog.finer(fe.toString()); |
| setFocus(fe.getID() == FocusEvent.FOCUS_GAINED); |
| } |
| |
| native void setFocus(boolean doSetFocus); |
| |
| public Dimension getMinimumSize() { |
| return ((Component)target).getSize(); |
| } |
| |
| public Dimension getPreferredSize() { |
| return getMinimumSize(); |
| } |
| |
| // Do nothing for heavyweight implementation |
| public void layout() {} |
| |
| public Rectangle getBounds() { |
| return ((Component)target).getBounds(); |
| } |
| |
| public boolean isFocusable() { |
| return false; |
| } |
| |
| /* |
| * Return the GraphicsConfiguration associated with this peer, either |
| * the locally stored winGraphicsConfig, or that of the target Component. |
| */ |
| public GraphicsConfiguration getGraphicsConfiguration() { |
| if (winGraphicsConfig != null) { |
| return winGraphicsConfig; |
| } |
| else { |
| // we don't need a treelock here, since |
| // Component.getGraphicsConfiguration() gets it itself. |
| return ((Component)target).getGraphicsConfiguration(); |
| } |
| } |
| |
| public SurfaceData getSurfaceData() { |
| return surfaceData; |
| } |
| |
| /** |
| * Creates new surfaceData object and invalidates the previous |
| * surfaceData object. |
| * Replacing the surface data should never lock on any resources which are |
| * required by other threads which may have them and may require |
| * the tree-lock. |
| * This is a degenerate version of replaceSurfaceData(numBackBuffers), so |
| * just call that version with our current numBackBuffers. |
| */ |
| public void replaceSurfaceData() { |
| replaceSurfaceData(this.numBackBuffers, this.backBufferCaps); |
| } |
| |
| /** |
| * Multi-buffer version of replaceSurfaceData. This version is called |
| * by createBuffers(), which needs to acquire the same locks in the same |
| * order, but also needs to perform additional functions inside the |
| * locks. |
| */ |
| public void replaceSurfaceData(int newNumBackBuffers, |
| BufferCapabilities caps) |
| { |
| SurfaceData oldData = null; |
| VolatileImage oldBB = null; |
| synchronized(((Component)target).getTreeLock()) { |
| synchronized(this) { |
| if (pData == 0) { |
| return; |
| } |
| numBackBuffers = newNumBackBuffers; |
| Win32GraphicsConfig gc = |
| (Win32GraphicsConfig)getGraphicsConfiguration(); |
| ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); |
| oldData = surfaceData; |
| mgr.dropScreenSurface(oldData); |
| surfaceData = |
| mgr.createScreenSurface(gc, this, numBackBuffers, true); |
| if (oldData != null) { |
| oldData.invalidate(); |
| } |
| |
| oldBB = backBuffer; |
| if (numBackBuffers > 0) { |
| // set the caps first, they're used when creating the bb |
| backBufferCaps = caps; |
| backBuffer = gc.createBackBuffer(this); |
| } else if (backBuffer != null) { |
| backBufferCaps = null; |
| backBuffer = null; |
| } |
| } |
| } |
| // it would be better to do this before we create new ones, |
| // but then we'd run into deadlock issues |
| if (oldData != null) { |
| oldData.flush(); |
| // null out the old data to make it collected faster |
| oldData = null; |
| } |
| if (oldBB != null) { |
| oldBB.flush(); |
| // null out the old data to make it collected faster |
| oldData = null; |
| } |
| } |
| |
| public void replaceSurfaceDataLater() { |
| Runnable r = new Runnable() { |
| public void run() { |
| // Shouldn't do anything if object is disposed in meanwhile |
| // No need for sync as disposeAction in Window is performed |
| // on EDT |
| if (!isDisposed()) { |
| try { |
| replaceSurfaceData(); |
| } catch (InvalidPipeException e) { |
| // REMIND : what do we do if our surface creation failed? |
| } |
| } |
| } |
| }; |
| // Fix 6255371. |
| if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) { |
| postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r)); |
| } |
| } |
| |
| public void updateGraphicsData(GraphicsConfiguration gc) { |
| winGraphicsConfig = (Win32GraphicsConfig)gc; |
| try { |
| replaceSurfaceData(); |
| } catch (InvalidPipeException e) { |
| // REMIND : what do we do if our surface creation failed? |
| } |
| } |
| |
| //This will return null for Components not yet added to a Container |
| public ColorModel getColorModel() { |
| GraphicsConfiguration gc = getGraphicsConfiguration(); |
| if (gc != null) { |
| return gc.getColorModel(); |
| } |
| else { |
| return null; |
| } |
| } |
| |
| //This will return null for Components not yet added to a Container |
| public ColorModel getDeviceColorModel() { |
| Win32GraphicsConfig gc = |
| (Win32GraphicsConfig)getGraphicsConfiguration(); |
| if (gc != null) { |
| return gc.getDeviceColorModel(); |
| } |
| else { |
| return null; |
| } |
| } |
| |
| //Returns null for Components not yet added to a Container |
| public ColorModel getColorModel(int transparency) { |
| // return WToolkit.config.getColorModel(transparency); |
| GraphicsConfiguration gc = getGraphicsConfiguration(); |
| if (gc != null) { |
| return gc.getColorModel(transparency); |
| } |
| else { |
| return null; |
| } |
| } |
| public java.awt.Toolkit getToolkit() { |
| return Toolkit.getDefaultToolkit(); |
| } |
| |
| // fallback default font object |
| final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); |
| |
| public Graphics getGraphics() { |
| SurfaceData surfaceData = this.surfaceData; |
| if (!isDisposed() && surfaceData != null) { |
| /* Fix for bug 4746122. Color and Font shouldn't be null */ |
| Color bgColor = background; |
| if (bgColor == null) { |
| bgColor = SystemColor.window; |
| } |
| Color fgColor = foreground; |
| if (fgColor == null) { |
| fgColor = SystemColor.windowText; |
| } |
| Font font = this.font; |
| if (font == null) { |
| font = defaultFont; |
| } |
| ScreenUpdateManager mgr = |
| ScreenUpdateManager.getInstance(); |
| return mgr.createGraphics(surfaceData, this, fgColor, |
| bgColor, font); |
| } |
| return null; |
| } |
| public FontMetrics getFontMetrics(Font font) { |
| return WFontMetrics.getFontMetrics(font); |
| } |
| |
| private synchronized native void _dispose(); |
| protected void disposeImpl() { |
| SurfaceData oldData = surfaceData; |
| surfaceData = null; |
| ScreenUpdateManager.getInstance().dropScreenSurface(oldData); |
| oldData.invalidate(); |
| // remove from updater before calling targetDisposedPeer |
| WToolkit.targetDisposedPeer(target, this); |
| _dispose(); |
| } |
| |
| public synchronized void setForeground(Color c) { |
| foreground = c; |
| _setForeground(c.getRGB()); |
| } |
| |
| public synchronized void setBackground(Color c) { |
| background = c; |
| _setBackground(c.getRGB()); |
| } |
| |
| /** |
| * This method is intentionally not synchronized as it is called while |
| * holding other locks. |
| * |
| * @see sun.java2d.d3d.D3DScreenUpdateManager#validate(D3DWindowSurfaceData) |
| */ |
| public Color getBackgroundNoSync() { |
| return background; |
| } |
| |
| public native void _setForeground(int rgb); |
| public native void _setBackground(int rgb); |
| |
| public synchronized void setFont(Font f) { |
| font = f; |
| _setFont(f); |
| } |
| public synchronized native void _setFont(Font f); |
| public final void updateCursorImmediately() { |
| WGlobalCursorManager.getCursorManager().updateCursorImmediately(); |
| } |
| |
| // TODO: consider moving it to KeyboardFocusManagerPeerImpl |
| public boolean requestFocus(Component lightweightChild, boolean temporary, |
| boolean focusedWindowChangeAllowed, long time, |
| CausedFocusEvent.Cause cause) |
| { |
| if (WKeyboardFocusManagerPeer. |
| processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary, |
| focusedWindowChangeAllowed, time)) |
| { |
| return true; |
| } |
| |
| int result = WKeyboardFocusManagerPeer |
| .shouldNativelyFocusHeavyweight((Component)target, lightweightChild, |
| temporary, focusedWindowChangeAllowed, |
| time, cause); |
| |
| switch (result) { |
| case WKeyboardFocusManagerPeer.SNFH_FAILURE: |
| return false; |
| case WKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED: |
| if (focusLog.isLoggable(Level.FINER)) { |
| focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target); |
| } |
| Window parentWindow = SunToolkit.getContainingWindow((Component)target); |
| if (parentWindow == null) { |
| return rejectFocusRequestHelper("WARNING: Parent window is null"); |
| } |
| WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer(); |
| if (wpeer == null) { |
| return rejectFocusRequestHelper("WARNING: Parent window's peer is null"); |
| } |
| boolean res = wpeer.requestWindowFocus(cause); |
| |
| if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Requested window focus: " + res); |
| // If parent window can be made focused and has been made focused(synchronously) |
| // then we can proceed with children, otherwise we retreat. |
| if (!(res && parentWindow.isFocused())) { |
| return rejectFocusRequestHelper("Waiting for asynchronous processing of the request"); |
| } |
| return WKeyboardFocusManagerPeer.deliverFocus(lightweightChild, |
| (Component)target, |
| temporary, |
| focusedWindowChangeAllowed, |
| time, cause); |
| |
| case WKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: |
| // Either lightweight or excessive request - all events are generated. |
| return true; |
| } |
| return false; |
| } |
| |
| private boolean rejectFocusRequestHelper(String logMsg) { |
| if (focusLog.isLoggable(Level.FINER)) focusLog.finer(logMsg); |
| WKeyboardFocusManagerPeer.removeLastFocusRequest((Component)target); |
| return false; |
| } |
| |
| public Image createImage(ImageProducer producer) { |
| return new ToolkitImage(producer); |
| } |
| |
| public Image createImage(int width, int height) { |
| Win32GraphicsConfig gc = |
| (Win32GraphicsConfig)getGraphicsConfiguration(); |
| return gc.createAcceleratedImage((Component)target, width, height); |
| } |
| |
| public VolatileImage createVolatileImage(int width, int height) { |
| return new SunVolatileImage((Component)target, width, height); |
| } |
| |
| public boolean prepareImage(Image img, int w, int h, ImageObserver o) { |
| return getToolkit().prepareImage(img, w, h, o); |
| } |
| |
| public int checkImage(Image img, int w, int h, ImageObserver o) { |
| return getToolkit().checkImage(img, w, h, o); |
| } |
| |
| // Object overrides |
| |
| public String toString() { |
| return getClass().getName() + "[" + target + "]"; |
| } |
| |
| // Toolkit & peer internals |
| |
| private int updateX1, updateY1, updateX2, updateY2; |
| |
| WComponentPeer(Component target) { |
| this.target = target; |
| this.paintArea = new RepaintArea(); |
| Container parent = WToolkit.getNativeContainer(target); |
| WComponentPeer parentPeer = (WComponentPeer) WToolkit.targetToPeer(parent); |
| create(parentPeer); |
| // fix for 5088782: check if window object is created successfully |
| checkCreation(); |
| this.winGraphicsConfig = |
| (Win32GraphicsConfig)getGraphicsConfiguration(); |
| ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); |
| this.surfaceData = mgr.createScreenSurface(winGraphicsConfig, this, |
| numBackBuffers, false); |
| initialize(); |
| start(); // Initialize enable/disable state, turn on callbacks |
| } |
| abstract void create(WComponentPeer parent); |
| |
| protected void checkCreation() |
| { |
| if ((hwnd == 0) || (pData == 0)) |
| { |
| if (createError != null) |
| { |
| throw createError; |
| } |
| else |
| { |
| throw new InternalError("couldn't create component peer"); |
| } |
| } |
| } |
| |
| synchronized native void start(); |
| |
| void initialize() { |
| if (((Component)target).isVisible()) { |
| show(); // the wnd starts hidden |
| } |
| Color fg = ((Component)target).getForeground(); |
| if (fg != null) { |
| setForeground(fg); |
| } |
| // Set background color in C++, to avoid inheriting a parent's color. |
| Font f = ((Component)target).getFont(); |
| if (f != null) { |
| setFont(f); |
| } |
| if (! ((Component)target).isEnabled()) { |
| disable(); |
| } |
| Rectangle r = ((Component)target).getBounds(); |
| setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS); |
| } |
| |
| // Callbacks for window-system events to the frame |
| |
| // Invoke a update() method call on the target |
| void handleRepaint(int x, int y, int w, int h) { |
| // Repaints are posted from updateClient now... |
| } |
| |
| // Invoke a paint() method call on the target, after clearing the |
| // damaged area. |
| void handleExpose(int x, int y, int w, int h) { |
| // Bug ID 4081126 & 4129709 - can't do the clearRect() here, |
| // since it interferes with the java thread working in the |
| // same window on multi-processor NT machines. |
| |
| postPaintIfNecessary(x, y, w, h); |
| } |
| |
| /* Invoke a paint() method call on the target, without clearing the |
| * damaged area. This is normally called by a native control after |
| * it has painted itself. |
| * |
| * NOTE: This is called on the privileged toolkit thread. Do not |
| * call directly into user code using this thread! |
| */ |
| public void handlePaint(int x, int y, int w, int h) { |
| postPaintIfNecessary(x, y, w, h); |
| } |
| |
| private void postPaintIfNecessary(int x, int y, int w, int h) { |
| if ( !ComponentAccessor.getIgnoreRepaint( (Component) target) ) { |
| PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher(). |
| createPaintEvent((Component)target, x, y, w, h); |
| if (event != null) { |
| postEvent(event); |
| } |
| } |
| } |
| |
| /* |
| * Post an event. Queue it for execution by the callback thread. |
| */ |
| void postEvent(AWTEvent event) { |
| preprocessPostEvent(event); |
| WToolkit.postEvent(WToolkit.targetToAppContext(target), event); |
| } |
| |
| void preprocessPostEvent(AWTEvent event) {} |
| |
| // Routines to support deferred window positioning. |
| public void beginLayout() { |
| // Skip all painting till endLayout |
| isLayouting = true; |
| } |
| |
| public void endLayout() { |
| if(!paintArea.isEmpty() && !paintPending && |
| !((Component)target).getIgnoreRepaint()) { |
| // if not waiting for native painting repaint damaged area |
| postEvent(new PaintEvent((Component)target, PaintEvent.PAINT, |
| new Rectangle())); |
| } |
| isLayouting = false; |
| } |
| |
| public native void beginValidate(); |
| public native void endValidate(); |
| |
| /** |
| * DEPRECATED |
| */ |
| public Dimension minimumSize() { |
| return getMinimumSize(); |
| } |
| |
| /** |
| * DEPRECATED |
| */ |
| public Dimension preferredSize() { |
| return getPreferredSize(); |
| } |
| |
| /** |
| * register a DropTarget with this native peer |
| */ |
| |
| public synchronized void addDropTarget(DropTarget dt) { |
| if (nDropTargets == 0) { |
| nativeDropTargetContext = addNativeDropTarget(); |
| } |
| nDropTargets++; |
| } |
| |
| /** |
| * unregister a DropTarget with this native peer |
| */ |
| |
| public synchronized void removeDropTarget(DropTarget dt) { |
| nDropTargets--; |
| if (nDropTargets == 0) { |
| removeNativeDropTarget(); |
| nativeDropTargetContext = 0; |
| } |
| } |
| |
| /** |
| * add the native peer's AwtDropTarget COM object |
| * @return reference to AwtDropTarget object |
| */ |
| |
| native long addNativeDropTarget(); |
| |
| /** |
| * remove the native peer's AwtDropTarget COM object |
| */ |
| |
| native void removeNativeDropTarget(); |
| native boolean nativeHandlesWheelScrolling(); |
| |
| public boolean handlesWheelScrolling() { |
| // should this be cached? |
| return nativeHandlesWheelScrolling(); |
| } |
| |
| // Returns true if we are inside begin/endLayout and |
| // are waiting for native painting |
| public boolean isPaintPending() { |
| return paintPending && isLayouting; |
| } |
| |
| /** |
| * The following multibuffering-related methods delegate to our |
| * associated GraphicsConfig (Win or WGL) to handle the appropriate |
| * native windowing system specific actions. |
| */ |
| |
| @Override |
| public void createBuffers(int numBuffers, BufferCapabilities caps) |
| throws AWTException |
| { |
| Win32GraphicsConfig gc = |
| (Win32GraphicsConfig)getGraphicsConfiguration(); |
| gc.assertOperationSupported((Component)target, numBuffers, caps); |
| |
| // Re-create the primary surface with the new number of back buffers |
| try { |
| replaceSurfaceData(numBuffers - 1, caps); |
| } catch (InvalidPipeException e) { |
| throw new AWTException(e.getMessage()); |
| } |
| } |
| |
| @Override |
| public void destroyBuffers() { |
| replaceSurfaceData(0, null); |
| } |
| |
| @Override |
| public void flip(int x1, int y1, int x2, int y2, |
| BufferCapabilities.FlipContents flipAction) |
| { |
| VolatileImage backBuffer = this.backBuffer; |
| if (backBuffer == null) { |
| throw new IllegalStateException("Buffers have not been created"); |
| } |
| Win32GraphicsConfig gc = |
| (Win32GraphicsConfig)getGraphicsConfiguration(); |
| gc.flip(this, (Component)target, backBuffer, x1, y1, x2, y2, flipAction); |
| } |
| |
| @Override |
| public synchronized Image getBackBuffer() { |
| Image backBuffer = this.backBuffer; |
| if (backBuffer == null) { |
| throw new IllegalStateException("Buffers have not been created"); |
| } |
| return backBuffer; |
| } |
| public BufferCapabilities getBackBufferCaps() { |
| return backBufferCaps; |
| } |
| public int getBackBuffersNum() { |
| return numBackBuffers; |
| } |
| |
| /* override and return false on components that DO NOT require |
| a clearRect() before painting (i.e. native components) */ |
| public boolean shouldClearRectBeforePaint() { |
| return true; |
| } |
| |
| native void pSetParent(ComponentPeer newNativeParent); |
| |
| /** |
| * @see java.awt.peer.ComponentPeer#reparent |
| */ |
| public void reparent(ContainerPeer newNativeParent) { |
| pSetParent(newNativeParent); |
| } |
| |
| /** |
| * @see java.awt.peer.ComponentPeer#isReparentSupported |
| */ |
| public boolean isReparentSupported() { |
| return true; |
| } |
| |
| public void setBoundsOperation(int operation) { |
| } |
| |
| /** |
| * Returns whether this component is capable of being hw accelerated. |
| * More specifically, whether rendering to this component or a |
| * BufferStrategy's back-buffer for this component can be hw accelerated. |
| * |
| * Conditions which could prevent hw acceleration include the toplevel |
| * window containing this component being |
| * {@link com.sun.awt.AWTUtilities.Translucency#TRANSLUCENT TRANSLUCENT}. |
| * |
| * @return {@code true} if this component is capable of being hw |
| * accelerated, {@code false} otherwise |
| * @see com.sun.awt.AWTUtilities.Translucency#TRANSLUCENT |
| */ |
| public boolean isAccelCapable() { |
| boolean isTranslucent = |
| SunToolkit.isContainingTopLevelTranslucent((Component)target); |
| // D3D/OGL and translucent windows interacted poorly in Windows XP; |
| // these problems are no longer present in Vista |
| return !isTranslucent || Win32GraphicsEnvironment.isVistaOS(); |
| } |
| |
| native void setRectangularShape(int lox, int loy, int hix, int hiy, |
| Region region); |
| |
| |
| // REMIND: Temp workaround for issues with using HW acceleration |
| // in the browser on Vista when DWM is enabled. |
| // @return true if the toplevel container is not an EmbeddedFrame or |
| // if this EmbeddedFrame is acceleration capable, false otherwise |
| private static final boolean isContainingTopLevelAccelCapable(Component c) { |
| while (c != null && !(c instanceof WEmbeddedFrame)) { |
| c = c.getParent(); |
| } |
| if (c == null) { |
| return true; |
| } |
| return ((WEmbeddedFramePeer)c.getPeer()).isAccelCapable(); |
| } |
| |
| /** |
| * Applies the shape to the native component window. |
| * @since 1.7 |
| */ |
| public void applyShape(Region shape) { |
| if (shapeLog.isLoggable(Level.FINER)) { |
| shapeLog.finer( |
| "*** INFO: Setting shape: PEER: " + this |
| + "; TARGET: " + target |
| + "; SHAPE: " + shape); |
| } |
| |
| if (shape != null) { |
| setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(), |
| (shape.isRectangular() ? null : shape)); |
| } else { |
| setRectangularShape(0, 0, 0, 0, null); |
| } |
| } |
| |
| /** |
| * Lowers this component at the bottom of the above component. If the above parameter |
| * is null then the method places this component at the top of the Z-order. |
| */ |
| public void setZOrder(ComponentPeer above) { |
| long aboveHWND = (above != null) ? ((WComponentPeer)above).getHWnd() : 0; |
| |
| setZOrder(aboveHWND); |
| } |
| |
| private native void setZOrder(long above); |
| } |