diff options
author | lana <none@none> | 2009-04-09 13:12:58 -0700 |
---|---|---|
committer | lana <none@none> | 2009-04-09 13:12:58 -0700 |
commit | eb3b76ea51e2441625f57b66bb7b5814d9abb341 (patch) | |
tree | c3297c6d46ecd0d9570ca67090122aa0299a286f /src/windows | |
parent | 016dd007e21e20d9b59186ffbd4857acbf430237 (diff) | |
parent | 9ef44fa316c87f58aabdb936a5a3c9eb89f89099 (diff) |
Merge
Diffstat (limited to 'src/windows')
69 files changed, 4200 insertions, 1844 deletions
diff --git a/src/windows/classes/sun/awt/Win32GraphicsConfig.java b/src/windows/classes/sun/awt/Win32GraphicsConfig.java index d24ce0eb1..2eefb33f1 100644 --- a/src/windows/classes/sun/awt/Win32GraphicsConfig.java +++ b/src/windows/classes/sun/awt/Win32GraphicsConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-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 @@ -331,4 +331,12 @@ public class Win32GraphicsConfig extends GraphicsConfiguration } // the rest of the flip actions are not supported } + + /* + @Override + */ + public boolean isTranslucencyCapable() { + //XXX: worth checking if 8-bit? Anyway, it doesn't hurt. + return true; + } } diff --git a/src/windows/classes/sun/awt/Win32GraphicsDevice.java b/src/windows/classes/sun/awt/Win32GraphicsDevice.java index ba4769813..1da339ce9 100644 --- a/src/windows/classes/sun/awt/Win32GraphicsDevice.java +++ b/src/windows/classes/sun/awt/Win32GraphicsDevice.java @@ -380,7 +380,6 @@ public class Win32GraphicsDevice extends GraphicsDevice implements // fix for 4868278 peer.updateGC(); - peer.resetTargetGC(); } } diff --git a/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java b/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java index 73b73dbb0..69723c113 100644 --- a/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java +++ b/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-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 @@ -398,4 +398,11 @@ public class Win32GraphicsEnvironment public boolean isDisplayLocal() { return true; } + + /** + * Used to find out if the OS is Windows Vista or later. + * + * @return {@code true} if the OS is Vista or later, {@code false} otherwise + */ + public static native boolean isVistaOS(); } diff --git a/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java b/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java new file mode 100644 index 000000000..9f8193f99 --- /dev/null +++ b/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java @@ -0,0 +1,398 @@ +/* + * Copyright 2008-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.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Window; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.awt.image.VolatileImage; +import java.lang.ref.WeakReference; +import java.security.AccessController; +import sun.awt.image.BufImgSurfaceData; +import sun.java2d.DestSurfaceProvider; +import sun.java2d.InvalidPipeException; +import sun.java2d.Surface; +import sun.java2d.pipe.RenderQueue; +import sun.java2d.pipe.hw.AccelGraphicsConfig; +import sun.java2d.pipe.hw.AccelSurface; +import sun.security.action.GetPropertyAction; + +import static java.awt.image.VolatileImage.*; +import static java.awt.Transparency.*; +import static sun.java2d.pipe.hw.AccelSurface.*; +import static sun.java2d.pipe.hw.ContextCapabilities.*; + +/** + * This class handles the updates of the non-opaque windows. + * The window associated with the peer is updated either given an image or + * the window is repainted to an internal buffer which is then used to update + * the window. + * + * Note: this class does not attempt to be thread safe, it is expected to be + * called from a single thread (EDT). + */ +public abstract class TranslucentWindowPainter { + + protected Window window; + protected WWindowPeer peer; + + // REMIND: we probably would want to remove this later + private static final boolean forceOpt = + Boolean.valueOf(AccessController.doPrivileged( + new GetPropertyAction("sun.java2d.twp.forceopt", "false"))); + private static final boolean forceSW = + Boolean.valueOf(AccessController.doPrivileged( + new GetPropertyAction("sun.java2d.twp.forcesw", "false"))); + + /** + * Creates an instance of the painter for particular peer. + */ + public static TranslucentWindowPainter createInstance(WWindowPeer peer) { + GraphicsConfiguration gc = peer.getGraphicsConfiguration(); + if (!forceSW && gc instanceof AccelGraphicsConfig) { + String gcName = gc.getClass().getSimpleName(); + AccelGraphicsConfig agc = (AccelGraphicsConfig)gc; + // this is a heuristic to check that we have a pcix board + // (those have higher transfer rate from gpu to cpu) + if ((agc.getContextCapabilities().getCaps() & CAPS_PS30) != 0 || + forceOpt) + { + // we check for name to avoid loading classes unnecessarily if + // a pipeline isn't enabled + if (gcName.startsWith("D3D")) { + return new VIOptD3DWindowPainter(peer); + } else if (forceOpt && gcName.startsWith("WGL")) { + // on some boards (namely, ATI, even on pcix bus) ogl is + // very slow reading pixels back so for now it is disabled + // unless forced + return new VIOptWGLWindowPainter(peer); + } + } + } + return new BIWindowPainter(peer); + } + + protected TranslucentWindowPainter(WWindowPeer peer) { + this.peer = peer; + this.window = (Window)peer.getTarget(); + } + + /** + * Creates (if needed), clears and returns the buffer for this painter. + */ + protected abstract Image getBackBuffer(); + + /** + * Updates the the window associated with this painter with the contents + * of the passed image. + * The image can not be null, and NPE will be thrown if it is. + */ + protected abstract boolean update(Image bb); + + /** + * Flushes the resources associated with the painter. They will be + * recreated as needed. + */ + public abstract void flush(); + + /** + * Updates the window associated with the painter given the passed image. + * If the passed image is null the painter will use its own buffer for + * rendering the contents of the window into it and updating the window. + * + * If the passed buffer has dimensions different from the window, it is + * copied into the internal buffer first and the latter is used to update + * the window. + * + * @param bb the image to update the non opaque window with, or null. + * If not null, the image must be of ARGB_PRE type. + */ + public void updateWindow(Image bb) { + boolean done = false; + if (bb != null && (window.getWidth() != bb.getWidth(null) || + window.getHeight() != bb.getHeight(null))) + { + Image ourBB = getBackBuffer(); + Graphics2D g = (Graphics2D)ourBB.getGraphics(); + g.drawImage(bb, 0, 0, null); + g.dispose(); + bb = ourBB; + } + do { + if (bb == null) { + bb = getBackBuffer(); + Graphics2D g = (Graphics2D)bb.getGraphics(); + try { + window.paintAll(g); + } finally { + g.dispose(); + } + } + + peer.paintAppletWarning((Graphics2D)bb.getGraphics(), + bb.getWidth(null), bb.getHeight(null)); + + done = update(bb); + // in case they passed us a lost VI, next time around we'll use our + // own bb because we can not validate and restore the contents of + // their VI + if (!done) { + bb = null; + } + } while (!done); + } + + private static final Image clearImage(Image bb) { + Graphics2D g = (Graphics2D)bb.getGraphics(); + int w = bb.getWidth(null); + int h = bb.getHeight(null); + + g.setComposite(AlphaComposite.Src); + g.setColor(new Color(0, 0, 0, 0)); + g.fillRect(0, 0, w, h); + + return bb; + } + + /** + * A painter which uses BufferedImage as the internal buffer. The window + * is painted into this buffer, and the contents then are uploaded + * into the layered window. + * + * This painter handles all types of images passed to its paint(Image) + * method (VI, BI, regular Images). + */ + private static class BIWindowPainter extends TranslucentWindowPainter { + private WeakReference<BufferedImage> biRef; + + protected BIWindowPainter(WWindowPeer peer) { + super(peer); + } + + private BufferedImage getBIBackBuffer() { + int w = window.getWidth(); + int h = window.getHeight(); + BufferedImage bb = biRef == null ? null : biRef.get(); + if (bb == null || bb.getWidth() != w || bb.getHeight() != h) { + if (bb != null) { + bb.flush(); + bb = null; + } + bb = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); + biRef = new WeakReference<BufferedImage>(bb); + } + return (BufferedImage)clearImage(bb); + } + + @Override + protected Image getBackBuffer() { + return getBIBackBuffer(); + } + + @Override + protected boolean update(Image bb) { + VolatileImage viBB = null; + + if (bb instanceof BufferedImage) { + BufferedImage bi = (BufferedImage)bb; + int data[] = + ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight()); + return true; + } else if (bb instanceof VolatileImage) { + viBB = (VolatileImage)bb; + if (bb instanceof DestSurfaceProvider) { + Surface s = ((DestSurfaceProvider)bb).getDestSurface(); + if (s instanceof BufImgSurfaceData) { + // the image is probably lost, upload the data from the + // backup surface to avoid creating another heap-based + // image (the parent's buffer) + int w = viBB.getWidth(); + int h = viBB.getHeight(); + BufImgSurfaceData bisd = (BufImgSurfaceData)s; + int data[] = ((DataBufferInt)bisd.getRaster(0,0,w,h). + getDataBuffer()).getData(); + peer.updateWindowImpl(data, w, h); + return true; + } + } + } + + // copy the passed image into our own buffer, then upload + BufferedImage bi = getBIBackBuffer(); + Graphics2D g = (Graphics2D)bi.getGraphics(); + g.setComposite(AlphaComposite.Src); + g.drawImage(bb, 0, 0, null); + + int data[] = + ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); + peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight()); + + return (viBB != null ? !viBB.contentsLost() : true); + } + + public void flush() { + if (biRef != null) { + biRef.clear(); + } + } + } + + /** + * A version of the painter which uses VolatileImage as the internal buffer. + * The window is painted into this VI and then copied into the parent's + * Java heap-based buffer (which is then uploaded to the layered window) + */ + private static class VIWindowPainter extends BIWindowPainter { + private WeakReference<VolatileImage> viRef; + + protected VIWindowPainter(WWindowPeer peer) { + super(peer); + } + + @Override + protected Image getBackBuffer() { + int w = window.getWidth(); + int h = window.getHeight(); + GraphicsConfiguration gc = peer.getGraphicsConfiguration(); + + VolatileImage viBB = viRef == null ? null : viRef.get(); + + if (viBB == null || viBB.getWidth() != w || viBB.getHeight() != h || + viBB.validate(gc) == IMAGE_INCOMPATIBLE) + { + if (viBB != null) { + viBB.flush(); + viBB = null; + } + + if (gc instanceof AccelGraphicsConfig) { + AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc); + viBB = agc.createCompatibleVolatileImage(w, h, + TRANSLUCENT, + RT_PLAIN); + } + if (viBB == null) { + viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT); + } + viBB.validate(gc); + viRef = new WeakReference<VolatileImage>(viBB); + } + + return clearImage(viBB); + } + + @Override + public void flush() { + if (viRef != null) { + VolatileImage viBB = viRef.get(); + if (viBB != null) { + viBB.flush(); + viBB = null; + } + viRef.clear(); + } + } + } + + /** + * Optimized version of hw painter. Uses VolatileImages for the + * buffer, and uses an optimized path to pull the data from those into + * the layered window, bypassing Java heap-based image. + */ + private abstract static class VIOptWindowPainter extends VIWindowPainter { + + protected VIOptWindowPainter(WWindowPeer peer) { + super(peer); + } + + protected abstract boolean updateWindowAccel(long psdops, int w, int h); + + @Override + protected boolean update(Image bb) { + if (bb instanceof DestSurfaceProvider) { + Surface s = ((DestSurfaceProvider)bb).getDestSurface(); + if (s instanceof AccelSurface) { + final int w = bb.getWidth(null); + final int h = bb.getHeight(null); + final boolean arr[] = { false }; + final AccelSurface as = (AccelSurface)s; + RenderQueue rq = as.getContext().getRenderQueue(); + rq.lock(); + try { + as.getContext().validateContext(as); + rq.flushAndInvokeNow(new Runnable() { + public void run() { + long psdops = as.getNativeOps(); + arr[0] = updateWindowAccel(psdops, w, h); + } + }); + } catch (InvalidPipeException e) { + // ignore, false will be returned + } finally { + rq.unlock(); + } + return arr[0]; + } + } + return super.update(bb); + } + } + + private static class VIOptD3DWindowPainter extends VIOptWindowPainter { + + protected VIOptD3DWindowPainter(WWindowPeer peer) { + super(peer); + } + + @Override + protected boolean updateWindowAccel(long psdops, int w, int h) { + // note: this method is executed on the toolkit thread, no sync is + // necessary at the native level, and a pointer to peer can be used + return sun.java2d.d3d.D3DSurfaceData. + updateWindowAccelImpl(psdops, peer.getData(), w, h); + } + } + + private static class VIOptWGLWindowPainter extends VIOptWindowPainter { + + protected VIOptWGLWindowPainter(WWindowPeer peer) { + super(peer); + } + + @Override + protected boolean updateWindowAccel(long psdops, int w, int h) { + // note: part of this method which deals with GDI will be on the + // toolkit thread + return sun.java2d.opengl.WGLSurfaceData. + updateWindowAccelImpl(psdops, peer, w, h); + } + } +} diff --git a/src/windows/classes/sun/awt/windows/WCanvasPeer.java b/src/windows/classes/sun/awt/windows/WCanvasPeer.java index 5d88a0c37..b97a3787b 100644 --- a/src/windows/classes/sun/awt/windows/WCanvasPeer.java +++ b/src/windows/classes/sun/awt/windows/WCanvasPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -28,6 +28,7 @@ import java.awt.*; import java.awt.peer.*; import java.lang.ref.WeakReference; import java.lang.reflect.Method; +import sun.awt.AWTAccessor; import sun.awt.ComponentAccessor; import sun.awt.SunToolkit; import sun.awt.Win32GraphicsDevice; @@ -37,44 +38,12 @@ class WCanvasPeer extends WComponentPeer implements CanvasPeer { private boolean eraseBackground; - Method resetGCMethod; - // Toolkit & peer internals WCanvasPeer(Component target) { super(target); } - /* - * From the DisplayChangedListener interface. - * - * Overrides WComponentPeer version because Canvases can be created with - * a non-defulat GraphicsConfiguration, which is no longer valid. - * Up-called for other windows peer instances (WPanelPeer, WWindowPeer). - */ - public void displayChanged() { - clearLocalGC(); - resetTargetGC(); - super.displayChanged(); - } - - /* - * Reset the graphicsConfiguration member of our target Component. - * Component.resetGC() is a package-private method, so we have to call it - * through reflection. - */ - public void resetTargetGC() { - ComponentAccessor.resetGC((Component)target); - } - - /* - * Clears the peer's winGraphicsConfig member. - * Overridden by WWindowPeer, which shouldn't have a null winGraphicsConfig. - */ - void clearLocalGC() { - winGraphicsConfig = null; - } - native void create(WComponentPeer parent); void initialize() { @@ -110,16 +79,20 @@ class WCanvasPeer extends WComponentPeer implements CanvasPeer { } public void print(Graphics g) { - Dimension d = ((Component)target).getSize(); - if (g instanceof Graphics2D || - g instanceof sun.awt.Graphics2Delegate) { - // background color is setup correctly, so just use clearRect - g.clearRect(0, 0, d.width, d.height); - } else { - // emulate clearRect - g.setColor(((Component)target).getBackground()); - g.fillRect(0, 0, d.width, d.height); - g.setColor(((Component)target).getForeground()); + if (!(target instanceof Window) || + AWTAccessor.getWindowAccessor().isOpaque((Window)target)) + { + Dimension d = ((Component)target).getSize(); + if (g instanceof Graphics2D || + g instanceof sun.awt.Graphics2Delegate) { + // background color is setup correctly, so just use clearRect + g.clearRect(0, 0, d.width, d.height); + } else { + // emulate clearRect + g.setColor(((Component)target).getBackground()); + g.fillRect(0, 0, d.width, d.height); + g.setColor(((Component)target).getForeground()); + } } super.print(g); } @@ -147,4 +120,10 @@ class WCanvasPeer extends WComponentPeer implements CanvasPeer { */ private native void setNativeBackgroundErase(boolean doErase, boolean doEraseOnResize); + + public GraphicsConfiguration getAppropriateGraphicsConfiguration( + GraphicsConfiguration gc) + { + return gc; + } } diff --git a/src/windows/classes/sun/awt/windows/WChoicePeer.java b/src/windows/classes/sun/awt/windows/WChoicePeer.java index 20ab610ff..b72e6f741 100644 --- a/src/windows/classes/sun/awt/windows/WChoicePeer.java +++ b/src/windows/classes/sun/awt/windows/WChoicePeer.java @@ -27,6 +27,10 @@ package sun.awt.windows; import java.awt.*; import java.awt.peer.*; import java.awt.event.ItemEvent; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.awt.event.WindowAdapter; +import sun.awt.SunToolkit; class WChoicePeer extends WComponentPeer implements ChoicePeer { @@ -70,6 +74,8 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer { public synchronized native void reshape(int x, int y, int width, int height); + private WindowListener windowListener; + // Toolkit & peer internals WChoicePeer(Choice target) { @@ -91,9 +97,38 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer { select(opt.getSelectedIndex()); } } + + Window parentWindow = SunToolkit.getContainingWindow((Component)target); + if (parentWindow != null) { + WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer(); + if (wpeer != null) { + windowListener = new WindowAdapter() { + public void windowIconified(WindowEvent e) { + closeList(); + } + public void windowClosing(WindowEvent e) { + closeList(); + } + }; + wpeer.addWindowListener(windowListener); + } + } super.initialize(); } + protected void disposeImpl() { + // TODO: we should somehow reset the listener when the choice + // is moved to another toplevel without destroying its peer. + Window parentWindow = SunToolkit.getContainingWindow((Component)target); + if (parentWindow != null) { + WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer(); + if (wpeer != null) { + wpeer.removeWindowListener(windowListener); + } + } + super.disposeImpl(); + } + // native callbacks void handleAction(final int index) { @@ -121,4 +156,5 @@ class WChoicePeer extends WComponentPeer implements ChoicePeer { return getMinimumSize(); } + native void closeList(); } diff --git a/src/windows/classes/sun/awt/windows/WComponentPeer.java b/src/windows/classes/sun/awt/windows/WComponentPeer.java index afbd170cc..6ad608452 100644 --- a/src/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/src/windows/classes/sun/awt/windows/WComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -38,27 +38,32 @@ 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.d3d.D3DScreenUpdateManager; -import static sun.java2d.d3d.D3DSurfaceData.*; 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, DisplayChangedListener + implements ComponentPeer, DropTargetPeer { /** * Handle to native window @@ -67,6 +72,7 @@ public abstract class WComponentPeer extends WObjectPeer 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; @@ -186,7 +192,7 @@ public abstract class WComponentPeer extends WObjectPeer cont.invalidate(); cont.validate(); - if (surfaceData instanceof D3DWindowSurfaceData || + if (surfaceData instanceof D3DSurfaceData.D3DWindowSurfaceData || surfaceData instanceof OGLSurfaceData) { // When OGL or D3D is enabled, it is necessary to @@ -258,7 +264,7 @@ public abstract class WComponentPeer extends WObjectPeer int[] pix = createPrintedPixels(0, startY, totalW, h); if (pix != null) { BufferedImage bim = new BufferedImage(totalW, h, - BufferedImage.TYPE_INT_RGB); + BufferedImage.TYPE_INT_ARGB); bim.setRGB(0, 0, totalW, h, pix, 0, totalW); g.drawImage(bim, 0, startY, null); bim.flush(); @@ -295,14 +301,35 @@ public abstract class WComponentPeer extends WObjectPeer // 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 (((Component)target).isEnabled() && (e instanceof KeyEvent) && !((KeyEvent)e).isConsumed()) { - if (handleJavaKeyEvent((KeyEvent)e)) { - return; + 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; + } } } @@ -318,6 +345,9 @@ public abstract class WComponentPeer extends WObjectPeer paintArea.paint(target,shouldClearRectBeforePaint()); } return; + case FocusEvent.FOCUS_LOST: + case FocusEvent.FOCUS_GAINED: + handleJavaFocusEvent((FocusEvent)e); default: break; } @@ -326,6 +356,13 @@ public abstract class WComponentPeer extends WObjectPeer 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(); } @@ -451,15 +488,8 @@ public abstract class WComponentPeer extends WObjectPeer } } - /** - * From the DisplayChangedListener interface. - * - * Called after a change in the display mode. This event - * triggers replacing the surfaceData object (since that object - * reflects the current display depth information, which has - * just changed). - */ - public void displayChanged() { + public void updateGraphicsData(GraphicsConfiguration gc) { + winGraphicsConfig = (Win32GraphicsConfig)gc; try { replaceSurfaceData(); } catch (InvalidPipeException e) { @@ -467,13 +497,6 @@ public abstract class WComponentPeer extends WObjectPeer } } - /** - * Part of the DisplayChangedListener interface: components - * do not need to react to this event - */ - public void paletteChanged() { - } - //This will return null for Components not yet added to a Container public ColorModel getColorModel() { GraphicsConfiguration gc = getGraphicsConfiguration(); @@ -585,22 +608,64 @@ public abstract class WComponentPeer extends WObjectPeer WGlobalCursorManager.getCursorManager().updateCursorImmediately(); } - native static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant, - boolean temporary, boolean focusedWindowChangeAllowed, - long time); - public boolean requestFocus - (Component lightweightChild, boolean temporary, - boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) { - if (processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary, - focusedWindowChangeAllowed, time)) { + // 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; - } else { - return _requestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time, cause); } + + 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 native boolean _requestFocus - (Component lightweightChild, boolean temporary, - boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause); public Image createImage(ImageProducer producer) { return new ToolkitImage(producer); @@ -713,7 +778,7 @@ public abstract class WComponentPeer extends WObjectPeer * NOTE: This is called on the privileged toolkit thread. Do not * call directly into user code using this thread! */ - void handlePaint(int x, int y, int w, int h) { + public void handlePaint(int x, int y, int w, int h) { postPaintIfNecessary(x, y, w, h); } @@ -731,9 +796,12 @@ public abstract class WComponentPeer extends WObjectPeer * 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 @@ -895,25 +963,6 @@ public abstract class WComponentPeer extends WObjectPeer public void setBoundsOperation(int operation) { } - - native void setRectangularShape(int lox, int loy, int hix, int hiy, - sun.java2d.pipe.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(); - } - /** * Returns whether this component is capable of being hw accelerated. * More specifically, whether rendering to this component or a @@ -928,28 +977,36 @@ public abstract class WComponentPeer extends WObjectPeer * @see com.sun.awt.AWTUtilities.Translucency#TRANSLUCENT */ public boolean isAccelCapable() { - // REMIND: Temp workaround for issues with using HW acceleration - // in the browser on Vista when DWM is enabled - if (!isContainingTopLevelAccelCapable((Component)target)) { - return false; - } - - // REMIND: translucent windows support-related -/* 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(); -*/ - return true; + } + + 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(sun.java2d.pipe.Region shape) { + public void applyShape(Region shape) { if (shapeLog.isLoggable(Level.FINER)) { shapeLog.finer( "*** INFO: Setting shape: PEER: " + this @@ -965,4 +1022,15 @@ public abstract class WComponentPeer extends WObjectPeer } } + /** + * 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); } diff --git a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java index 548dc3d41..1c90ae2e5 100644 --- a/src/windows/classes/sun/awt/windows/WFileDialogPeer.java +++ b/src/windows/classes/sun/awt/windows/WFileDialogPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -231,17 +231,9 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { */ private static native void initIDs(); - /** - * WFileDialogPeer doesn't have native pData so we don't do restack on it - * @see java.awt.peer.ContainerPeer#restack - */ - public void restack() { - } - - /** - * @see java.awt.peer.ContainerPeer#isRestackSupported - */ - public boolean isRestackSupported() { - return false; - } + // The effects are not supported for system dialogs. + public void applyShape(sun.java2d.pipe.Region shape) {} + public void setOpacity(float opacity) {} + public void setOpaque(boolean isOpaque) {} + public void updateWindow(java.awt.image.BufferedImage backBuffer) {} } diff --git a/src/windows/classes/sun/awt/windows/WFramePeer.java b/src/windows/classes/sun/awt/windows/WFramePeer.java index 2353daf3d..79bf6b77e 100644 --- a/src/windows/classes/sun/awt/windows/WFramePeer.java +++ b/src/windows/classes/sun/awt/windows/WFramePeer.java @@ -25,27 +25,46 @@ package sun.awt.windows; import java.util.Vector; + import java.awt.*; import java.awt.peer.*; import java.awt.image.ImageObserver; -import sun.awt.image.ImageRepresentation; -import sun.awt.image.IntegerComponentRaster; -import sun.awt.image.ToolkitImage; + import java.awt.image.Raster; import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.image.BufferedImage; -import sun.awt.im.*; -import sun.awt.Win32GraphicsDevice; + import java.awt.image.ColorModel; +import sun.awt.image.ImageRepresentation; +import sun.awt.image.IntegerComponentRaster; +import sun.awt.image.ToolkitImage; +import sun.awt.im.*; +import sun.awt.Win32GraphicsDevice; +import sun.awt.AWTAccessor; class WFramePeer extends WWindowPeer implements FramePeer { + static { + initIDs(); + } + + // initialize JNI field and method IDs + private static native void initIDs(); + // FramePeer implementation public native void setState(int state); public native int getState(); + // sync target and peer + public void setExtendedState(int state) { + AWTAccessor.getFrameAccessor().setExtendedState((Frame)target, state); + } + public int getExtendedState() { + return AWTAccessor.getFrameAccessor().getExtendedState((Frame)target); + } + // Convenience methods to save us from trouble of extracting // Rectangle fields in native code. private native void setMaximizedBounds(int x, int y, int w, int h); diff --git a/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java b/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java new file mode 100644 index 000000000..892899603 --- /dev/null +++ b/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java @@ -0,0 +1,75 @@ +/* + * Copyright 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.KeyboardFocusManager; +import java.awt.Window; +import java.awt.Component; +import java.awt.peer.ComponentPeer; +import sun.awt.KeyboardFocusManagerPeerImpl; +import sun.awt.CausedFocusEvent; + +class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { + static native void setNativeFocusOwner(ComponentPeer peer); + static native Component getNativeFocusOwner(); + static native Window getNativeFocusedWindow(); + + WKeyboardFocusManagerPeer(KeyboardFocusManager manager) { + super(manager); + } + + @Override + public void setCurrentFocusOwner(Component comp) { + setNativeFocusOwner(comp != null ? comp.getPeer() : null); + } + + @Override + public Component getCurrentFocusOwner() { + return getNativeFocusOwner(); + } + + @Override + public Window getCurrentFocusedWindow() { + return getNativeFocusedWindow(); + } + + public static boolean deliverFocus(Component lightweightChild, + Component target, + boolean temporary, + boolean focusedWindowChangeAllowed, + long time, + CausedFocusEvent.Cause cause) + { + // TODO: do something to eliminate this forwarding + return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild, + target, + temporary, + focusedWindowChangeAllowed, + time, + cause, + getNativeFocusOwner()); + } +} diff --git a/src/windows/classes/sun/awt/windows/WPanelPeer.java b/src/windows/classes/sun/awt/windows/WPanelPeer.java index 8a0d7ffbc..10ca42314 100644 --- a/src/windows/classes/sun/awt/windows/WPanelPeer.java +++ b/src/windows/classes/sun/awt/windows/WPanelPeer.java @@ -100,34 +100,6 @@ class WPanelPeer extends WCanvasPeer implements PanelPeer { return getInsets(); } - /* - * From the DisplayChangedListener interface. Often is - * up-called from a WWindowPeer instance. - */ - public void displayChanged() { - super.displayChanged(); - displayChanged((Container)target); - } - - /* - * Recursively iterates through all the HW and LW children - * of the container and calls displayChanged() for HW peers. - * Iteration through children peers only is not enough as the - * displayChanged notification may not be propagated to HW - * components inside LW containers, see 4452373 for details. - */ - private static void displayChanged(Container target) { - Component children[] = ((Container)target).getComponents(); - for (Component child : children) { - ComponentPeer cpeer = child.getPeer(); - if (cpeer instanceof WComponentPeer) { - ((WComponentPeer)cpeer).displayChanged(); - } else if (child instanceof Container) { - displayChanged((Container)child); - } - } - } - private native void pRestack(Object[] peers); private void restack(Container cont, Vector peers) { for (int i = 0; i < cont.getComponentCount(); i++) { diff --git a/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java b/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java index c1e06f53c..90ca88279 100644 --- a/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java +++ b/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-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 @@ -143,17 +143,9 @@ public class WPrintDialogPeer extends WWindowPeer implements DialogPeer { */ private static native void initIDs(); - /** - * WPrintDialogPeer doesn't have native pData so we don't do restack on it - * @see java.awt.peer.ContainerPeer#restack - */ - public void restack() { - } - - /** - * @see java.awt.peer.ContainerPeer#isRestackSupported - */ - public boolean isRestackSupported() { - return false; - } + // The effects are not supported for system dialogs. + public void applyShape(sun.java2d.pipe.Region shape) {} + public void setOpacity(float opacity) {} + public void setOpaque(boolean isOpaque) {} + public void updateWindow(java.awt.image.BufferedImage backBuffer) {} } diff --git a/src/windows/classes/sun/awt/windows/WScrollPanePeer.java b/src/windows/classes/sun/awt/windows/WScrollPanePeer.java index 70b3725cf..2e8c5e60b 100644 --- a/src/windows/classes/sun/awt/windows/WScrollPanePeer.java +++ b/src/windows/classes/sun/awt/windows/WScrollPanePeer.java @@ -269,10 +269,4 @@ class WScrollPanePeer extends WPanelPeer implements ScrollPanePeer { } } - /** - * @see java.awt.peer.ContainerPeer#restack - */ - public void restack() { - // Since ScrollPane can only have one child its restacking does nothing. - } } diff --git a/src/windows/classes/sun/awt/windows/WToolkit.java b/src/windows/classes/sun/awt/windows/WToolkit.java index 55c1dde09..62011b9b8 100644 --- a/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/src/windows/classes/sun/awt/windows/WToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -494,6 +494,12 @@ public class WToolkit extends SunToolkit implements Runnable { return true; } + public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) + throws HeadlessException + { + return new WKeyboardFocusManagerPeer(manager); + } + protected native void setDynamicLayoutNative(boolean b); public void setDynamicLayout(boolean b) { @@ -975,4 +981,34 @@ public class WToolkit extends SunToolkit implements Runnable { public boolean areExtraMouseButtonsEnabled() throws HeadlessException { return areExtraMouseButtonsEnabled; } + + @Override + public boolean isWindowOpacitySupported() { + // supported in Win2K and later + return true; + } + + @Override + public boolean isWindowShapingSupported() { + return true; + } + + @Override + public boolean isWindowTranslucencySupported() { + // supported in Win2K and later + return true; + } + + @Override + public boolean isTranslucencyCapable(GraphicsConfiguration gc) { + //XXX: worth checking if 8-bit? Anyway, it doesn't hurt. + return true; + } + + // On MS Windows one must use the peer.updateWindow() to implement + // non-opaque windows. + @Override + public boolean needUpdateWindow() { + return true; + } } diff --git a/src/windows/classes/sun/awt/windows/WWindowPeer.java b/src/windows/classes/sun/awt/windows/WWindowPeer.java index 6afdb2be6..3c6240209 100644 --- a/src/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/src/windows/classes/sun/awt/windows/WWindowPeer.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -31,19 +31,19 @@ import java.awt.peer.*; import java.beans.*; -import java.lang.ref.*; import java.lang.reflect.*; -import java.security.*; - import java.util.*; import java.util.List; import java.util.logging.*; import sun.awt.*; -import sun.awt.image.*; -public class WWindowPeer extends WPanelPeer implements WindowPeer { +import sun.java2d.pipe.Region; + +public class WWindowPeer extends WPanelPeer implements WindowPeer, + DisplayChangedListener +{ private static final Logger log = Logger.getLogger("sun.awt.windows.WWindowPeer"); private static final Logger screenLog = Logger.getLogger("sun.awt.windows.screen.WWindowPeer"); @@ -52,6 +52,10 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { // extends WWindowPeer, not WDialogPeer private WWindowPeer modalBlocker = null; + private boolean isOpaque; + + private volatile TranslucentWindowPainter painter; + /* * A key used for storing a list of active windows in AppContext. The value * is a list of windows, sorted by the time of activation: later a window is @@ -73,6 +77,12 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { private final static PropertyChangeListener guiDisposedListener = new GuiDisposedListener(); + /* + * Called (on the Toolkit thread) before the appropriate + * WindowStateEvent is posted to the EventQueue. + */ + private WindowListener windowListener; + /** * Initialize JNI field IDs */ @@ -91,9 +101,18 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { l.remove(this); } } + // Remove ourself from the Map of DisplayChangeListeners GraphicsConfiguration gc = getGraphicsConfiguration(); ((Win32GraphicsDevice)gc.getDevice()).removeDisplayChangedListener(this); + + TranslucentWindowPainter currentPainter = painter; + if (currentPainter != null) { + currentPainter.flush(); + // don't set the current one to null here; reduces the chances of + // MT issues (like NPEs) + } + super.disposeImpl(); } @@ -158,6 +177,10 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { initActiveWindowsTracking((Window)target); updateIconImages(); + + updateShape(); + updateOpacity(); + updateOpaque(); } native void createAwtWindow(WComponentPeer parent); @@ -183,7 +206,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { // super.displayChanged() in WWindowPeer.displayChanged() regardless of whether // GraphicsDevice was really changed, or not. So we need to track it here. updateGC(); - resetTargetGC(); realShow(); updateMinimumSize(); @@ -191,6 +213,8 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { if (((Window)target).isAlwaysOnTopSupported() && alwaysOnTop) { setAlwaysOnTop(alwaysOnTop); } + + updateWindow(null); } // Synchronize the insets members (here & in helper) with actual window @@ -214,27 +238,64 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { int[] smallIconRaster, int smw, int smh); synchronized native void reshapeFrame(int x, int y, int width, int height); - public boolean requestWindowFocus() { - // Win32 window doesn't need this - return false; + + public boolean requestWindowFocus(CausedFocusEvent.Cause cause) { + if (!focusAllowedFor()) { + return false; + } + return requestWindowFocus(cause == CausedFocusEvent.Cause.MOUSE_EVENT); } + public native boolean requestWindowFocus(boolean isMouseEventCause); public boolean focusAllowedFor() { - Window target = (Window)this.target; - if (!target.isVisible() || - !target.isEnabled() || - !target.isFocusable()) + Window window = (Window)this.target; + if (!window.isVisible() || + !window.isEnabled() || + !window.isFocusableWindow()) { return false; } - if (isModalBlocked()) { return false; } - return true; } + public void hide() { + WindowListener listener = windowListener; + if (listener != null) { + // We're not getting WINDOW_CLOSING from the native code when hiding + // the window programmatically. So, create it and notify the listener. + listener.windowClosing(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING)); + } + super.hide(); + } + + // WARNING: it's called on the Toolkit thread! + void preprocessPostEvent(AWTEvent event) { + if (event instanceof WindowEvent) { + WindowListener listener = windowListener; + if (listener != null) { + switch(event.getID()) { + case WindowEvent.WINDOW_CLOSING: + listener.windowClosing((WindowEvent)event); + break; + case WindowEvent.WINDOW_ICONIFIED: + listener.windowIconified((WindowEvent)event); + break; + } + } + } + } + + synchronized void addWindowListener(WindowListener l) { + windowListener = AWTEventMulticaster.add(windowListener, l); + } + + synchronized void removeWindowListener(WindowListener l) { + windowListener = AWTEventMulticaster.remove(windowListener, l); + } + public void updateMinimumSize() { Dimension minimumSize = null; if (((Component)target).isMinimumSizeSet()) { @@ -273,6 +334,31 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { } } + private void updateShape() { + // Shape shape = ((Window)target).getShape(); + Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target); + if (shape != null) { + applyShape(Region.getInstance(shape, null)); + } + } + + private void updateOpacity() { + // float opacity = ((Window)target).getOpacity(); + float opacity = AWTAccessor.getWindowAccessor().getOpacity((Window)target); + if (opacity < 1.0f) { + setOpacity(opacity); + } + } + + private void updateOpaque() { + this.isOpaque = true; + // boolean opaque = ((Window)target).isOpaque(); + boolean opaque = AWTAccessor.getWindowAccessor().isOpaque((Window)target); + if (!opaque) { + setOpaque(opaque); + } + } + native void setMinSize(int width, int height); /* @@ -358,14 +444,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { }); } - - /* - * Called from WCanvasPeer.displayChanged(). - * Override to do nothing - Window and WWindowPeer GC must never be set to - * null! - */ - void clearLocalGC() {} - public void updateGC() { int scrn = getScreenImOn(); if (screenLog.isLoggable(Level.FINER)) { @@ -404,18 +482,36 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { oldDev.removeDisplayChangedListener(this); newDev.addDisplayChangedListener(this); } + + SunToolkit.executeOnEventHandlerThread((Component)target, + new Runnable() { + public void run() { + AWTAccessor.getComponentAccessor(). + setGraphicsConfiguration((Component)target, winGraphicsConfig); + } + }); } - /* - * From the DisplayChangedListener interface + /** + * From the DisplayChangedListener interface. * * This method handles a display change - either when the display settings * are changed, or when the window has been dragged onto a different * display. + * Called after a change in the display mode. This event + * triggers replacing the surfaceData object (since that object + * reflects the current display depth information, which has + * just changed). */ public void displayChanged() { updateGC(); - super.displayChanged(); + } + + /** + * Part of the DisplayChangedListener interface: components + * do not need to react to this event + */ + public void paletteChanged() { } private native int getScreenImOn(); @@ -451,8 +547,10 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { private volatile int sysH = 0; Rectangle constrainBounds(int x, int y, int width, int height) { + GraphicsConfiguration gc = this.winGraphicsConfig; + // We don't restrict the setBounds() operation if the code is trusted. - if (!hasWarningWindow()) { + if (!hasWarningWindow() || gc == null) { return new Rectangle(x, y, width, height); } @@ -461,24 +559,24 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { int newW = width; int newH = height; - GraphicsConfiguration gc = ((Window)target).getGraphicsConfiguration(); Rectangle sB = gc.getBounds(); - Insets sIn = ((Window)target).getToolkit().getScreenInsets(gc); + Insets sIn = Toolkit.getDefaultToolkit().getScreenInsets(gc); int screenW = sB.width - sIn.left - sIn.right; int screenH = sB.height - sIn.top - sIn.bottom; // If it's undecorated or is not currently visible - if (!((Window)target).isVisible() || isTargetUndecorated()) { + if (!AWTAccessor.getComponentAccessor().isVisible_NoClientCode( + (Component)target) || isTargetUndecorated()) + { // Now check each point is within the visible part of the screen int screenX = sB.x + sIn.left; int screenY = sB.y + sIn.top; - // First make sure the size is withing the visible part of the screen + // First make sure the size is within the visible part of the screen if (newW > screenW) { newW = screenW; } - if (newH > screenH) { newH = screenH; } @@ -489,7 +587,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { } else if (newX + newW > screenX + screenW) { newX = screenX + screenW - newW; } - if (newY < screenY) { newY = screenY; } else if (newY + newH > screenY + screenH) { @@ -504,7 +601,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { if (newW > maxW) { newW = maxW; } - if (newH > maxH) { newH = maxH; } @@ -513,6 +609,8 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { return new Rectangle(newX, newY, newW, newH); } + public native void repositionSecurityWarning(); + @Override public void setBounds(int x, int y, int width, int height, int op) { Rectangle newBounds = constrainBounds(x, y, width, height); @@ -525,6 +623,135 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer { super.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height, op); } + @Override + public void print(Graphics g) { + // We assume we print the whole frame, + // so we expect no clip was set previously + Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target); + if (shape != null) { + g.setClip(shape); + } + super.print(g); + } + + private void replaceSurfaceDataRecursively(Component c) { + if (c instanceof Container) { + for (Component child : ((Container)c).getComponents()) { + replaceSurfaceDataRecursively(child); + } + } + ComponentPeer cp = c.getPeer(); + if (cp instanceof WComponentPeer) { + ((WComponentPeer)cp).replaceSurfaceDataLater(); + } + } + + private native void setOpacity(int iOpacity); + + public void setOpacity(float opacity) { + if (!((SunToolkit)((Window)target).getToolkit()). + isWindowOpacitySupported()) + { + return; + } + + replaceSurfaceDataRecursively((Component)getTarget()); + + final int maxOpacity = 0xff; + int iOpacity = (int)(opacity * maxOpacity); + if (iOpacity < 0) { + iOpacity = 0; + } + if (iOpacity > maxOpacity) { + iOpacity = maxOpacity; + } + + setOpacity(iOpacity); + updateWindow(null); + } + + private native void setOpaqueImpl(boolean isOpaque); + + public void setOpaque(boolean isOpaque) { + Window target = (Window)getTarget(); + + SunToolkit sunToolkit = (SunToolkit)target.getToolkit(); + if (!sunToolkit.isWindowTranslucencySupported() || + !sunToolkit.isTranslucencyCapable(target.getGraphicsConfiguration())) + { + return; + } + + boolean opaqueChanged = this.isOpaque != isOpaque; + boolean isVistaOS = Win32GraphicsEnvironment.isVistaOS(); + + if (opaqueChanged && !isVistaOS){ + // non-Vista OS: only replace the surface data if the opacity + // status changed (see WComponentPeer.isAccelCapable() for more) + replaceSurfaceDataRecursively(target); + } + + this.isOpaque = isOpaque; + + setOpaqueImpl(isOpaque); + + if (opaqueChanged) { + if (isOpaque) { + TranslucentWindowPainter currentPainter = painter; + if (currentPainter != null) { + currentPainter.flush(); + painter = null; + } + } else { + painter = TranslucentWindowPainter.createInstance(this); + } + } + + if (opaqueChanged && isVistaOS) { + // On Vista: setting the window non-opaque makes the window look + // rectangular, though still catching the mouse clicks within + // its shape only. To restore the correct visual appearance + // of the window (i.e. w/ the correct shape) we have to reset + // the shape. + Shape shape = AWTAccessor.getWindowAccessor().getShape(target); + if (shape != null) { + AWTAccessor.getWindowAccessor().setShape(target, shape); + } + } + + updateWindow(null); + } + + public native void updateWindowImpl(int[] data, int width, int height); + + public void updateWindow(BufferedImage backBuffer) { + if (isOpaque) { + return; + } + + TranslucentWindowPainter currentPainter = painter; + if (currentPainter != null) { + currentPainter.updateWindow(backBuffer); + } else if (log.isLoggable(Level.FINER)) { + log.log(Level.FINER, + "Translucent window painter is null in updateWindow"); + } + } + + /** + * Paints the Applet Warning into the passed Graphics2D. This method is + * called by the TranslucentWindowPainter before updating the layered + * window. + * + * @param g Graphics context to paint the warning to + * @param w the width of the area + * @param h the height of the area + * @see TranslucentWindowPainter + */ + public void paintAppletWarning(Graphics2D g, int w, int h) { + // REMIND: the applet warning needs to be painted here + } + /* * The method maps the list of the active windows to the window's AppContext, * then the method registers ActiveWindowListener, GuiDisposedListener listeners; diff --git a/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java index b3b0fa8d5..53ae895dd 100644 --- a/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java +++ b/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-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 @@ -37,6 +37,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import sun.awt.SunToolkit; +import sun.awt.AWTAccessor; import sun.awt.Win32GraphicsConfig; import sun.awt.windows.WComponentPeer; import sun.java2d.InvalidPipeException; @@ -284,14 +285,12 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager * @param peer for which target's the repaint should be issued */ private void repaintPeerTarget(WComponentPeer peer) { - // we don't want to call user code on our priveleged - // thread, delegate to EDT - final Component target = (Component)peer.getTarget(); - SunToolkit.executeOnEventHandlerThread(target, new Runnable() { - public void run() { - target.repaint(); - } - }); + Component target = (Component)peer.getTarget(); + Rectangle bounds = AWTAccessor.getComponentAccessor().getBounds(target); + // the system-level painting operations should call the handlePaint() + // method of the WComponentPeer class to repaint the component; + // calling repaint() forces AWT to make call to update() + peer.handlePaint(0, 0, bounds.width, bounds.height); } /** diff --git a/src/windows/classes/sun/java2d/opengl/WGLSurfaceData.java b/src/windows/classes/sun/java2d/opengl/WGLSurfaceData.java index 27997aa8c..4164264a1 100644 --- a/src/windows/classes/sun/java2d/opengl/WGLSurfaceData.java +++ b/src/windows/classes/sun/java2d/opengl/WGLSurfaceData.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-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 @@ -72,9 +72,8 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { // the OGL pipeline can render directly to the screen and interfere // with layered windows, which is why we don't allow accelerated // surfaces in this case - if (!peer.isAccelCapable()) - // REMIND: commented until toplevel translucency is implemented -// || !SunToolkit.isContainingTopLevelOpaque((Component)peer.getTarget())) + if (!peer.isAccelCapable() || + !SunToolkit.isContainingTopLevelOpaque((Component)peer.getTarget())) { return null; } @@ -93,9 +92,8 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { // the OGL pipeline can render directly to the screen and interfere // with layered windows, which is why we don't allow accelerated // surfaces in this case - if (!peer.isAccelCapable()) - // REMIND: commented until toplevel translucency is implemented -// || !SunToolkit.isContainingTopLevelOpaque((Component)peer.getTarget())) + if (!peer.isAccelCapable() || + !SunToolkit.isContainingTopLevelOpaque((Component)peer.getTarget())) { return null; } diff --git a/src/windows/native/sun/awt/utility/rect.h b/src/windows/native/sun/awt/utility/rect.h index bc250e2ac..a8e9fc28b 100644 --- a/src/windows/native/sun/awt/utility/rect.h +++ b/src/windows/native/sun/awt/utility/rect.h @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-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 @@ -43,5 +43,15 @@ typedef RECT RECT_T; #define RECT_INC_HEIGHT(r) (r).bottom++ +#if defined(__cplusplus) +extern "C" { +#endif + +int BitmapToYXBandedRectangles(int bitsPerPixel, int width, int height, + unsigned char * buf, RECT_T * outBuf); + +#if defined(__cplusplus) +} +#endif #endif // _AWT_RECT_H diff --git a/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp b/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp index 9c865dc97..c6d4bb1b3 100644 --- a/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp +++ b/src/windows/native/sun/java2d/d3d/D3DSurfaceData.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2007-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 @@ -613,17 +613,15 @@ JNICALL Java_sun_java2d_d3d_D3DSurfaceData_updateWindowAccelImpl res = pTmpSurface->LockRect(&lockedRect, NULL, D3DLOCK_NOSYSLOCK); if (SUCCEEDED(res)) { - // REMIND: commented until translucent window support is integrated -// hBitmap = -// BitmapUtil::CreateBitmapFromARGBPre(w, h, -// lockedRect.Pitch, -// (int*)lockedRect.pBits); + hBitmap = + BitmapUtil::CreateBitmapFromARGBPre(w, h, + lockedRect.Pitch, + (int*)lockedRect.pBits); pTmpSurface->UnlockRect(); } RETURN_STATUS_IF_NULL(hBitmap, JNI_FALSE); - // REMIND: commented until translucent window support is integrated -// window->UpdateWindow(env, NULL, w, h, hBitmap); + window->UpdateWindow(env, NULL, w, h, hBitmap); // hBitmap is released in UpdateWindow diff --git a/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c b/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c index 71d5e8764..3c3e09cec 100644 --- a/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c +++ b/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-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 @@ -625,17 +625,15 @@ JNIEXPORT jboolean JNICALL j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4); // the pixels read from the surface are already premultiplied - // REMIND: commented until translucent window support is integrated -// hBitmap = BitmapUtil_CreateBitmapFromARGBPre(w, h, scanStride, -// (int*)pDst); + hBitmap = BitmapUtil_CreateBitmapFromARGBPre(w, h, scanStride, + (int*)pDst); free(pDst); if (hBitmap == NULL) { return JNI_FALSE; } - // REMIND: commented until translucent window support is integrated - // AwtWindow_UpdateWindow(env, peer, w, h, hBitmap); + AwtWindow_UpdateWindow(env, peer, w, h, hBitmap); // hBitmap is released in UpdateWindow diff --git a/src/windows/native/sun/windows/ComCtl32Util.cpp b/src/windows/native/sun/windows/ComCtl32Util.cpp index ac69cf3af..8ac9d764a 100644 --- a/src/windows/native/sun/windows/ComCtl32Util.cpp +++ b/src/windows/native/sun/windows/ComCtl32Util.cpp @@ -27,6 +27,7 @@ #include "ComCtl32Util.h" ComCtl32Util::ComCtl32Util() { + m_bToolTipControlInitialized = FALSE; } ComCtl32Util::~ComCtl32Util() { @@ -36,7 +37,8 @@ void ComCtl32Util::InitLibraries() { INITCOMMONCONTROLSEX iccex; memset(&iccex, 0, sizeof(INITCOMMONCONTROLSEX)); iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); - ::InitCommonControlsEx(&iccex); + iccex.dwICC = ICC_TAB_CLASSES; + m_bToolTipControlInitialized = ::InitCommonControlsEx(&iccex); } WNDPROC ComCtl32Util::SubclassHWND(HWND hwnd, WNDPROC _WindowProc) { diff --git a/src/windows/native/sun/windows/ComCtl32Util.h b/src/windows/native/sun/windows/ComCtl32Util.h index e137b43d0..642667709 100644 --- a/src/windows/native/sun/windows/ComCtl32Util.h +++ b/src/windows/native/sun/windows/ComCtl32Util.h @@ -40,6 +40,10 @@ class ComCtl32Util void InitLibraries(); + INLINE BOOL IsToolTipControlInitialized() { + return m_bToolTipControlInitialized; + } + WNDPROC SubclassHWND(HWND hwnd, WNDPROC _WindowProc); // DefWindowProc is the same as returned from SubclassHWND void UnsubclassHWND(HWND hwnd, WNDPROC _WindowProc, WNDPROC _DefWindowProc); @@ -50,6 +54,8 @@ class ComCtl32Util ComCtl32Util(); ~ComCtl32Util(); + BOOL m_bToolTipControlInitialized; + // comctl32.dll version 6 window proc static LRESULT CALLBACK SharedWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, diff --git a/src/windows/native/sun/windows/DllUtil.cpp b/src/windows/native/sun/windows/DllUtil.cpp new file mode 100644 index 000000000..0c7077144 --- /dev/null +++ b/src/windows/native/sun/windows/DllUtil.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 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. + */ + + +#include "DllUtil.h" + +// Disable warning about using this in the initializer list. +#pragma warning( disable : 4355) + +DllUtil::~DllUtil() +{ + if (module != NULL) { + ::FreeLibrary(module); + module = NULL; + } +} + +HMODULE DllUtil::GetModule() +{ + if (!module) { + module = ::LoadLibrary(name); + } + return module; +} + +FARPROC DllUtil::GetProcAddress(LPCSTR name) +{ + if (GetModule()) { + return ::GetProcAddress(GetModule(), name); + } + throw LibraryUnavailableException(); +} + +DwmAPI & DwmAPI::GetInstance() +{ + static DwmAPI dll; + return dll; +} + +DwmAPI::DwmAPI() : + DllUtil(_T("DWMAPI.DLL")), + DwmIsCompositionEnabledFunction((DllUtil*)this, "DwmIsCompositionEnabled"), + DwmGetWindowAttributeFunction((DllUtil*)this, "DwmGetWindowAttribute") +{ +} + +HRESULT DwmAPI::DwmIsCompositionEnabled(BOOL * pfEnabled) +{ + if (GetInstance().DwmIsCompositionEnabledFunction()) { + return GetInstance().DwmIsCompositionEnabledFunction()(pfEnabled); + } + throw FunctionUnavailableException(); +} + +HRESULT DwmAPI::DwmGetWindowAttribute(HWND hwnd, DWORD dwAttribute, + PVOID pvAttribute, DWORD cbAttribute) +{ + if (GetInstance().DwmGetWindowAttributeFunction()) { + return GetInstance().DwmGetWindowAttributeFunction()(hwnd, dwAttribute, + pvAttribute, cbAttribute); + } + throw FunctionUnavailableException(); +} + + diff --git a/src/windows/native/sun/windows/DllUtil.h b/src/windows/native/sun/windows/DllUtil.h new file mode 100644 index 000000000..307d93d2b --- /dev/null +++ b/src/windows/native/sun/windows/DllUtil.h @@ -0,0 +1,97 @@ +/* + * Copyright 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. + */ + +#ifndef DLLUTIL_H +#define DLLUTIL_H + +#include <tchar.h> +#include <windows.h> + +/** + * Utility class to handle dynamically loadable libraries. + * + * NOTE: THIS CLASS IS NOT THREAD-SAFE! + */ +class DllUtil { + public: + class Exception {}; + class LibraryUnavailableException : public Exception {}; + class FunctionUnavailableException : public Exception {}; + + FARPROC GetProcAddress(LPCSTR name); + + protected: + DllUtil(const TCHAR * name) : name(name), module(NULL) {} + virtual ~DllUtil(); + + HMODULE GetModule(); + + template <class FunctionType> class Function { + public: + Function(DllUtil * dll, LPCSTR name) : + dll(dll), name(name), function(NULL) {} + + inline FunctionType operator () () { + if (!function) { + function = (FunctionType)dll->GetProcAddress(name); + } + return function; + } + + private: + DllUtil * const dll; + LPCSTR name; + + FunctionType function; + }; + + private: + const TCHAR * const name; + HMODULE module; +}; + +class DwmAPI : public DllUtil { + public: + // See DWMWINDOWATTRIBUTE enum in dwmapi.h + static const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9; + + static HRESULT DwmIsCompositionEnabled(BOOL * pfEnabled); + static HRESULT DwmGetWindowAttribute(HWND hwnd, DWORD dwAttribute, + PVOID pvAttribute, DWORD cbAttribute); + + private: + static DwmAPI & GetInstance(); + DwmAPI(); + + typedef HRESULT (WINAPI *DwmIsCompositionEnabledType)(BOOL*); + Function<DwmIsCompositionEnabledType> DwmIsCompositionEnabledFunction; + + typedef HRESULT (WINAPI *DwmGetWindowAttributeType)(HWND hwnd, DWORD dwAttribute, + PVOID pvAttribute, DWORD cbAttribute); + Function<DwmGetWindowAttributeType> DwmGetWindowAttributeFunction; +}; + +#endif // DLLUTIL_H + diff --git a/src/windows/native/sun/windows/awt.rc b/src/windows/native/sun/windows/awt.rc index c9c3f1721..7eb4d41af 100644 --- a/src/windows/native/sun/windows/awt.rc +++ b/src/windows/native/sun/windows/awt.rc @@ -35,6 +35,13 @@ HAND_CURSOR CURSOR DISCARDABLE "hand.cur" AWT_ICON ICON DISCARDABLE "awt.ico" CHECK_BITMAP BITMAP DISCARDABLE "check.bmp" +// Note: the number of icons used is specified in the +// securityWarningIconCounter constant in awt_Toolkit.cpp. +SECURITY_WARNING_0 ICON DISCARDABLE "security_warning_bw.ico" +SECURITY_WARNING_1 ICON DISCARDABLE "security_warning_int.ico" +SECURITY_WARNING_2 ICON DISCARDABLE "security_warning.ico" + + ///////////////////////////////////////////////////////////////////////////// // // Version diff --git a/src/windows/native/sun/windows/awt_BitmapUtil.cpp b/src/windows/native/sun/windows/awt_BitmapUtil.cpp index 64c52e2f8..10e71b3e6 100644 --- a/src/windows/native/sun/windows/awt_BitmapUtil.cpp +++ b/src/windows/native/sun/windows/awt_BitmapUtil.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-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 @@ -28,9 +28,14 @@ #include <windowsx.h> #include <zmouse.h> +#include "GraphicsPrimitiveMgr.h" + #include "awt.h" #include "awt_BitmapUtil.h" +// Platform-dependent RECT_[EQ | SET | INC_HEIGHT] macros +#include "utility/rect.h" + HBITMAP BitmapUtil::CreateTransparencyMaskFromARGB(int width, int height, int* imageData) { //Scan lines should be aligned to word boundary @@ -148,3 +153,222 @@ HBITMAP BitmapUtil::CreateV4BitmapFromARGB(int width, int height, int* imageData ::GdiFlush(); return hBitmap; } + +/* + * Creates 32-bit premultiplied ARGB bitmap from specified ARGBPre data. + * This function may not work on OS prior to Win95. + * See MSDN articles for CreateDIBitmap, BITMAPINFOHEADER, + * BITMAPV4HEADER, BITMAPV5HEADER for additional info. + */ +HBITMAP BitmapUtil::CreateBitmapFromARGBPre(int width, int height, + int srcStride, + int* imageData) +{ + BITMAPINFOHEADER bmi; + void *bitmapBits = NULL; + + ZeroMemory(&bmi, sizeof(bmi)); + bmi.biSize = sizeof(bmi); + bmi.biWidth = width; + bmi.biHeight = -height; + bmi.biPlanes = 1; + bmi.biBitCount = 32; + bmi.biCompression = BI_RGB; + + HBITMAP hBitmap = + ::CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS, + &bitmapBits, NULL, 0); + + if (!bitmapBits) { + return NULL; + } + + int dstStride = width * 4; + + if (srcStride == dstStride) { + memcpy(bitmapBits, (void*)imageData, srcStride * height); + } else if (height > 0) { + void *pSrcPixels = (void*)imageData; + void *pDstPixels = bitmapBits; + do { + memcpy(pDstPixels, pSrcPixels, dstStride); + pSrcPixels = PtrAddBytes(pSrcPixels, srcStride); + pDstPixels = PtrAddBytes(pDstPixels, dstStride); + } while (--height > 0); + } + + return hBitmap; +} + +extern "C" { + +/** + * This method is called from the WGL pipeline when it needs to create a bitmap + * needed to update the layered window. + */ +HBITMAP BitmapUtil_CreateBitmapFromARGBPre(int width, int height, + int srcStride, + int* imageData) +{ + return BitmapUtil::CreateBitmapFromARGBPre(width, height, + srcStride, imageData); + +} + +} /* extern "C" */ + + +/** + * Transforms the given bitmap into an HRGN representing the transparency + * of the bitmap. The bitmap MUST BE 32bpp. Alpha value == 0 is considered + * transparent, alpha > 0 - opaque. + */ +HRGN BitmapUtil::BitmapToRgn(HBITMAP hBitmap) +{ + HDC hdc = ::CreateCompatibleDC(NULL); + ::SelectObject(hdc, hBitmap); + + BITMAPINFOEX bi; + ::ZeroMemory(&bi, sizeof(bi)); + + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + BOOL r = ::GetDIBits(hdc, hBitmap, 0, 0, NULL, + reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS); + + if (!r || bi.bmiHeader.biBitCount != 32) + { + ::DeleteDC(hdc); + return NULL; + } + + UINT width = bi.bmiHeader.biWidth; + UINT height = abs(bi.bmiHeader.biHeight); + + BYTE * buf = (BYTE*)safe_Malloc(bi.bmiHeader.biSizeImage); + bi.bmiHeader.biHeight = -height; + ::GetDIBits(hdc, hBitmap, 0, height, buf, + reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS); + + /* reserving memory for the worst case */ + RGNDATA * pRgnData = (RGNDATA *) safe_Malloc(sizeof(RGNDATAHEADER) + + sizeof(RECT) * (width / 2 + 1) * height); + RGNDATAHEADER * pRgnHdr = (RGNDATAHEADER *) pRgnData; + pRgnHdr->dwSize = sizeof(RGNDATAHEADER); + pRgnHdr->iType = RDH_RECTANGLES; + pRgnHdr->nRgnSize = 0; + pRgnHdr->rcBound.top = 0; + pRgnHdr->rcBound.left = 0; + pRgnHdr->rcBound.bottom = height; + pRgnHdr->rcBound.right = width; + + pRgnHdr->nCount = BitmapToYXBandedRectangles(32, width, height, buf, + (RECT_T *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER))); + + HRGN rgn = ::ExtCreateRegion(NULL, + sizeof(RGNDATAHEADER) + sizeof(RECT_T) * pRgnHdr->nCount, + pRgnData); + + free(pRgnData); + ::DeleteDC(hdc); + free(buf); + + return rgn; +} + +/** + * Makes a copy of the given bitmap. Blends every pixel of the source + * with the given blendColor and alpha. If alpha == 0, the function + * simply makes a plain copy of the source without any blending. + */ +HBITMAP BitmapUtil::BlendCopy(HBITMAP hSrcBitmap, COLORREF blendColor, + BYTE alpha) +{ + HDC hdc = ::CreateCompatibleDC(NULL); + HBITMAP oldBitmap = (HBITMAP)::SelectObject(hdc, hSrcBitmap); + + BITMAPINFOEX bi; + ::ZeroMemory(&bi, sizeof(bi)); + + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + BOOL r = ::GetDIBits(hdc, hSrcBitmap, 0, 0, NULL, + reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS); + + if (!r || bi.bmiHeader.biBitCount != 32) + { + ::DeleteDC(hdc); + return NULL; + } + + UINT width = bi.bmiHeader.biWidth; + UINT height = abs(bi.bmiHeader.biHeight); + + BYTE * buf = (BYTE*)safe_Malloc(bi.bmiHeader.biSizeImage); + bi.bmiHeader.biHeight = -height; + ::GetDIBits(hdc, hSrcBitmap, 0, height, buf, + reinterpret_cast<BITMAPINFO*>(&bi), DIB_RGB_COLORS); + + UINT widthBytes = width * bi.bmiHeader.biBitCount / 8; + UINT alignedWidth = (((widthBytes - 1) / 4) + 1) * 4; + UINT i, j; + + for (j = 0; j < height; j++) { + BYTE *pSrc = (BYTE *) buf + j * alignedWidth; + for (i = 0; i < width; i++, pSrc += 4) { + // Note: if the current alpha is zero, the other three color + // components may (theoretically) contain some uninitialized + // data. The developer does not expect to display them, + // hence we handle this situation differently. + if (pSrc[3] == 0) { + pSrc[0] = GetBValue(blendColor) * alpha / 255; + pSrc[1] = GetGValue(blendColor) * alpha / 255; + pSrc[2] = GetRValue(blendColor) * alpha / 255; + pSrc[3] = alpha; + } else { + pSrc[0] = (GetBValue(blendColor) * alpha / 255) + + (pSrc[0] * (255 - alpha) / 255); + pSrc[1] = (GetGValue(blendColor) * alpha / 255) + + (pSrc[1] * (255 - alpha) / 255); + pSrc[2] = (GetRValue(blendColor) * alpha / 255) + + (pSrc[2] * (255 - alpha) / 255); + pSrc[3] = (alpha * alpha / 255) + + (pSrc[3] * (255 - alpha) / 255); + } + } + } + + HBITMAP hDstBitmap = ::CreateDIBitmap(hdc, + reinterpret_cast<BITMAPINFOHEADER*>(&bi), + CBM_INIT, + buf, + reinterpret_cast<BITMAPINFO*>(&bi), + DIB_RGB_COLORS + ); + + ::SelectObject(hdc, oldBitmap); + ::DeleteDC(hdc); + free(buf); + + return hDstBitmap; +} + +/** + * Creates a 32 bit ARGB bitmap. Returns the bitmap handle. The *bitmapBits + * contains the pointer to the bitmap data or NULL if an error occured. + */ +HBITMAP BitmapUtil::CreateARGBBitmap(int width, int height, void ** bitmapBitsPtr) +{ + BITMAPINFOHEADER bmi; + + ::ZeroMemory(&bmi, sizeof(bmi)); + bmi.biSize = sizeof(BITMAPINFOHEADER); + bmi.biWidth = width; + bmi.biHeight = -height; + bmi.biPlanes = 1; + bmi.biBitCount = 32; + bmi.biCompression = BI_RGB; + + return ::CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS, + bitmapBitsPtr, NULL, 0); +} diff --git a/src/windows/native/sun/windows/awt_BitmapUtil.h b/src/windows/native/sun/windows/awt_BitmapUtil.h index b32f3fe0a..2c039232f 100644 --- a/src/windows/native/sun/windows/awt_BitmapUtil.h +++ b/src/windows/native/sun/windows/awt_BitmapUtil.h @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-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 @@ -45,6 +45,32 @@ public: */ static HBITMAP CreateV4BitmapFromARGB(int width, int height, int* imageData); + /** + * Creates 32-bit premultiplied ARGB V4 Bitmap (Win95-compatible) from + * specified ARGB Pre input data. + */ + static HBITMAP CreateBitmapFromARGBPre(int width, int height, + int srcStride, + int* imageData); + + /** + * Transforms the given bitmap into an HRGN representing the transparency + * of the bitmap. + */ + static HRGN BitmapToRgn(HBITMAP hBitmap); + + /** + * Makes a copy of the given bitmap. Blends every pixel of the source + * with the given blendColor and alpha. If alpha == 0, the function + * simply makes a plain copy of the source without any blending. + */ + static HBITMAP BlendCopy(HBITMAP hSrcBitmap, COLORREF blendColor, BYTE alpha); + + /** + * Creates a 32 bit ARGB bitmap. Returns the bitmap handle. + * The pointer to the bitmap data is stored into bitmapBitsPtr. + */ + static HBITMAP CreateARGBBitmap(int width, int height, void ** bitmapBitsPtr); }; #endif diff --git a/src/windows/native/sun/windows/awt_Button.cpp b/src/windows/native/sun/windows/awt_Button.cpp index 3764655cb..2fb620fcd 100644 --- a/src/windows/native/sun/windows/awt_Button.cpp +++ b/src/windows/native/sun/windows/awt_Button.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -30,7 +30,6 @@ #include "awt_Button.h" #include "awt_Canvas.h" #include "awt_Window.h" -#include "awt_KeyboardFocusManager.h" /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. */ @@ -143,19 +142,6 @@ done: return c; } -BOOL AwtButton::ActMouseMessage(MSG * pMsg) { - if (!IsFocusingMessage(pMsg->message)) { - return FALSE; - } - - if (pMsg->message == WM_LBUTTONDOWN) { - SendMessage(BM_SETSTATE, TRUE, 0); - } else if (pMsg->message == WM_LBUTTONUP) { - SendMessage(BM_SETSTATE, FALSE, 0); - } - return TRUE; -} - MsgRouting AwtButton::WmMouseDown(UINT flags, int x, int y, int button) { @@ -204,23 +190,6 @@ AwtButton::NotifyListeners() (jint)AwtComponent::GetJavaModifiers()); } -/* 4531849 fix. Previous to 1.4, mouse clicks and typing space bar on a - * Button would notify ActionListeners via WM_COMMAND/WmNotify(). In 1.4, mouse - * grabs are done for all presses in order to correctly send drag and release - * events. However, WM_COMMAND message aren't sent when the mouse is grabbed, - * so ActionListeners for mouse clicks are sent via WmMouseUp/WmNotify(). - * For some reason, if the right mouse button is held down when left-clicking - * on a Button, WM_COMMAND _IS_ sent. This resulted in two ActionEvents being - * sent in this case. To fix the problem, we handle typing space bar similar to - * left clicks - in WmKeyUp(), and do nothing for WM_COMMAND. -bchristi - */ -MsgRouting -AwtButton::WmKeyUp(UINT wkey, UINT repCnt, UINT flags, BOOL system) -{ - MsgRouting mrResult = AwtComponent::WmKeyUp(wkey, repCnt, flags, system); - return mrResult; -} - MsgRouting AwtButton::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo) { @@ -293,18 +262,26 @@ MsgRouting AwtButton::WmPaint(HDC) return mrDoDefault; } +BOOL AwtButton::IsFocusingMouseMessage(MSG *pMsg) { + return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP; +} + +BOOL AwtButton::IsFocusingKeyMessage(MSG *pMsg) { + return (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) && + pMsg->wParam == VK_SPACE; +} + MsgRouting AwtButton::HandleEvent(MSG *msg, BOOL synthetic) { - if (AwtComponent::sm_focusOwner != GetHWnd() && - (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK)) - { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); + if (IsFocusingMouseMessage(msg)) { + SendMessage(BM_SETSTATE, msg->message == WM_LBUTTONDOWN ? TRUE : FALSE, 0); + delete msg; + return mrConsume; + } + if (IsFocusingKeyMessage(msg)) { + SendMessage(BM_SETSTATE, msg->message == WM_KEYDOWN ? TRUE : FALSE, 0); + delete msg; + return mrConsume; } return AwtComponent::HandleEvent(msg, synthetic); } diff --git a/src/windows/native/sun/windows/awt_Button.h b/src/windows/native/sun/windows/awt_Button.h index 795fbf9b5..5e6d2754a 100644 --- a/src/windows/native/sun/windows/awt_Button.h +++ b/src/windows/native/sun/windows/awt_Button.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -50,13 +50,13 @@ public: /* Windows message handler functions */ MsgRouting WmMouseDown(UINT flags, int x, int y, int button); MsgRouting WmMouseUp(UINT flags, int x, int y, int button); - MsgRouting WmKeyUp(UINT vkey, UINT repCnt, UINT flags, BOOL system); MsgRouting OwnerDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo); MsgRouting WmPaint(HDC hDC); MsgRouting HandleEvent(MSG *msg, BOOL synthetic); - BOOL ActMouseMessage(MSG * pMsg); + BOOL IsFocusingMouseMessage(MSG *pMsg); + BOOL IsFocusingKeyMessage(MSG *pMsg); // called on Toolkit thread from JNI static void _SetLabel(void *param); diff --git a/src/windows/native/sun/windows/awt_Canvas.cpp b/src/windows/native/sun/windows/awt_Canvas.cpp index 4988152b8..b03a79817 100644 --- a/src/windows/native/sun/windows/awt_Canvas.cpp +++ b/src/windows/native/sun/windows/awt_Canvas.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -26,7 +26,6 @@ #include "awt_Toolkit.h" #include "awt_Canvas.h" #include "awt_Win32GraphicsConfig.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Window.h" /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. @@ -176,27 +175,9 @@ MsgRouting AwtCanvas::WmPaint(HDC) MsgRouting AwtCanvas::HandleEvent(MSG *msg, BOOL synthetic) { - if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { - /* - * Fix for BugTraq ID 4041703: keyDown not being invoked. - * Give the focus to a Canvas or Panel if it doesn't have heavyweight - * subcomponents so that they will behave the same way as on Solaris - * providing a possibility of giving keyboard focus to an empty Applet. - * Since ScrollPane doesn't receive focus on mouse press on Solaris, - * HandleEvent() is overriden there to do nothing with focus. - */ - if (AwtComponent::sm_focusOwner != GetHWnd() && - ::GetWindow(GetHWnd(), GW_CHILD) == NULL) - { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); - AwtSetFocus(); - } + if (IsFocusingMouseMessage(msg)) { + delete msg; + return mrConsume; } return AwtComponent::HandleEvent(msg, synthetic); } diff --git a/src/windows/native/sun/windows/awt_Checkbox.cpp b/src/windows/native/sun/windows/awt_Checkbox.cpp index 2e8cf9923..2830e5681 100644 --- a/src/windows/native/sun/windows/awt_Checkbox.cpp +++ b/src/windows/native/sun/windows/awt_Checkbox.cpp @@ -26,7 +26,6 @@ #include "awt.h" #include "awt_Toolkit.h" #include "awt_Checkbox.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" #include "awt_Window.h" @@ -143,17 +142,6 @@ done: return checkbox; } -BOOL AwtCheckbox::ActMouseMessage(MSG* pMsg) { - if (!IsFocusingMessage(pMsg->message)) { - return FALSE; - } - - if (pMsg->message == WM_LBUTTONDOWN) { - SendMessage(BM_SETSTATE, ~SendMessage(BM_GETSTATE, 0, 0), 0); - } - return TRUE; -} - MsgRouting AwtCheckbox::WmMouseUp(UINT flags, int x, int y, int button) { @@ -329,18 +317,32 @@ MsgRouting AwtCheckbox::WmPaint(HDC) return mrDoDefault; } +BOOL AwtCheckbox::IsFocusingMouseMessage(MSG *pMsg) { + return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP; +} + +BOOL AwtCheckbox::IsFocusingKeyMessage(MSG *pMsg) { + return (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) && + pMsg->wParam == VK_SPACE; +} + MsgRouting AwtCheckbox::HandleEvent(MSG *msg, BOOL synthetic) { - if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd() && - (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK)) - { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); + if (IsFocusingMouseMessage(msg)) { + SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_LBUTTONDOWN ? TRUE : FALSE)); + delete msg; + return mrConsume; + } + if (IsFocusingKeyMessage(msg)) { + SendMessage(BM_SETSTATE, (WPARAM)(msg->message == WM_KEYDOWN ? TRUE : FALSE)); + if (msg->message == WM_KEYDOWN) { + m_fLButtonDowned = TRUE; + } else if (m_fLButtonDowned == TRUE) { + WmNotify(BN_CLICKED); + m_fLButtonDowned = TRUE; + } + delete msg; + return mrConsume; } return AwtComponent::HandleEvent(msg, synthetic); } diff --git a/src/windows/native/sun/windows/awt_Checkbox.h b/src/windows/native/sun/windows/awt_Checkbox.h index 581afcd65..4d913da00 100644 --- a/src/windows/native/sun/windows/awt_Checkbox.h +++ b/src/windows/native/sun/windows/awt_Checkbox.h @@ -69,7 +69,8 @@ public: MsgRouting HandleEvent(MSG *msg, BOOL synthetic); - BOOL ActMouseMessage(MSG* pMsg); + BOOL IsFocusingMouseMessage(MSG *pMsg); + BOOL IsFocusingKeyMessage(MSG *pMsg); // called on Toolkit thread from JNI static void _SetLabel(void *param); diff --git a/src/windows/native/sun/windows/awt_Choice.cpp b/src/windows/native/sun/windows/awt_Choice.cpp index ca7adb0ed..03fdde96f 100644 --- a/src/windows/native/sun/windows/awt_Choice.cpp +++ b/src/windows/native/sun/windows/awt_Choice.cpp @@ -23,14 +23,17 @@ * have any questions. */ +#include <windowsx.h> + #include "awt_Toolkit.h" #include "awt_Choice.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" #include "awt_Dimension.h" #include "awt_Container.h" +#include "ComCtl32Util.h" + #include <java_awt_Toolkit.h> #include <java_awt_FontMetrics.h> #include <java_awt_event_InputEvent.h> @@ -71,18 +74,31 @@ BOOL AwtChoice::mouseCapture = FALSE; /* Bug #4338368: consume the spurious MouseUp when the choice loses focus */ BOOL AwtChoice::skipNextMouseUp = FALSE; + +BOOL AwtChoice::sm_isMouseMoveInList = FALSE; + +static const UINT MINIMUM_NUMBER_OF_VISIBLE_ITEMS = 8; + /************************************************************************* * AwtChoice class methods */ AwtChoice::AwtChoice() { - killFocusRouting = mrPassAlong; + m_hList = NULL; + m_listDefWindowProc = NULL; } LPCTSTR AwtChoice::GetClassName() { return TEXT("COMBOBOX"); /* System provided combobox class */ } +void AwtChoice::Dispose() { + if (m_hList != NULL && m_listDefWindowProc != NULL) { + ComCtl32Util::GetInstance().UnsubclassHWND(m_hList, ListWindowProc, m_listDefWindowProc); + } + AwtComponent::Dispose(); +} + AwtChoice* AwtChoice::Create(jobject peer, jobject parent) { @@ -162,6 +178,10 @@ AwtChoice* AwtChoice::Create(jobject peer, jobject parent) { env->SetIntField(target, AwtComponent::widthID, (jint) rc.right); env->SetIntField(target, AwtComponent::heightID, (jint) rc.bottom); + if (IS_WINXP) { + ::SendMessage(c->GetHWnd(), CB_SETMINVISIBLE, (WPARAM) MINIMUM_NUMBER_OF_VISIBLE_ITEMS, 0); + } + env->DeleteLocalRef(dimension); } } catch (...) { @@ -175,24 +195,13 @@ done: return c; } -BOOL AwtChoice::ActMouseMessage(MSG* pMsg) { - if (!IsFocusingMessage(pMsg->message)) { - return FALSE; - } - - if (pMsg->message == WM_LBUTTONDOWN) { - SendMessage(CB_SHOWDROPDOWN, ~SendMessage(CB_GETDROPPEDSTATE, 0, 0), 0); - } - return TRUE; -} - // calculate height of drop-down list part of the combobox // to show all the items up to a maximum of eight int AwtChoice::GetDropDownHeight() { int itemHeight =(int)::SendMessage(GetHWnd(), CB_GETITEMHEIGHT, (UINT)0,0); int numItemsToShow = (int)::SendMessage(GetHWnd(), CB_GETCOUNT, 0,0); - numItemsToShow = numItemsToShow > 8 ? 8 : numItemsToShow; + numItemsToShow = min(MINIMUM_NUMBER_OF_VISIBLE_ITEMS, numItemsToShow); // drop-down height snaps to nearest line, so add a // fudge factor of 1/2 line to ensure last line shows return itemHeight*numItemsToShow + itemHeight/2; @@ -253,6 +262,7 @@ void AwtChoice::SetDragCapture(UINT flags) } return; } + // don't want to interfere with other controls if (::GetCapture() == NULL) { ::SetCapture(GetHWnd()); @@ -370,6 +380,58 @@ void AwtChoice::SetFont(AwtFont* font) env->DeleteLocalRef(target); } +static int lastClickX = -1; +static int lastClickY = -1; + +LRESULT CALLBACK AwtChoice::ListWindowProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + /* + * We don't pass the choice WM_LBUTTONDOWN message. As the result the choice's list + * doesn't forward mouse messages it captures. Below we do forward what we need. + */ + + TRY; + + DASSERT(::IsWindow(hwnd)); + + switch (message) { + case WM_LBUTTONDOWN: { + DWORD curPos = ::GetMessagePos(); + lastClickX = GET_X_LPARAM(curPos); + lastClickY = GET_Y_LPARAM(curPos); + break; + } + case WM_MOUSEMOVE: { + RECT rect; + ::GetClientRect(hwnd, &rect); + + POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; + if (::PtInRect(&rect, pt)) { + sm_isMouseMoveInList = TRUE; + } + + POINT lastPt = {lastClickX, lastClickY}; + ::ScreenToClient(hwnd, &lastPt); + if (::PtInRect(&rect, lastPt)) { + break; // ignore when dragging inside the list + } + } + case WM_LBUTTONUP: { + lastClickX = -1; + lastClickY = -1; + + AwtChoice *c = (AwtChoice *)::GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (c != NULL) { + // forward the msg to the choice + c->WindowProc(message, wParam, lParam); + } + } + } + return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam); + + CATCH_BAD_ALLOC_RET(0); +} MsgRouting AwtChoice::WmNotify(UINT notifyCode) @@ -379,15 +441,24 @@ MsgRouting AwtChoice::WmNotify(UINT notifyCode) if (itemSelect != CB_ERR){ DoCallback("handleAction", "(I)V", itemSelect); } - } else if (notifyCode == CBN_DROPDOWN && !IsFocusable()) { - // While non-focusable Choice is shown all WM_KILLFOCUS messages should be consumed. - killFocusRouting = mrConsume; - } else if (notifyCode == CBN_CLOSEUP && !IsFocusable()) { - // When non-focusable Choice is about to close, send it synthetic WM_KILLFOCUS - // message that should be processed by the native widget only. This will allow - // the native widget to properly process WM_KILLFOCUS that was earlier consumed. - killFocusRouting = mrDoDefault; - ::PostMessage(GetHWnd(), WM_KILLFOCUS, (LPARAM)sm_focusOwner, 0); + } else if (notifyCode == CBN_DROPDOWN) { + + if (m_hList == NULL) { + COMBOBOXINFO cbi; + cbi.cbSize = sizeof(COMBOBOXINFO); + ::GetComboBoxInfo(GetHWnd(), &cbi); + m_hList = cbi.hwndList; + m_listDefWindowProc = ComCtl32Util::GetInstance().SubclassHWND(m_hList, ListWindowProc); + DASSERT(::GetWindowLongPtr(m_hList, GWLP_USERDATA) == NULL); + ::SetWindowLongPtr(m_hList, GWLP_USERDATA, (LONG_PTR)this); + } + sm_isMouseMoveInList = FALSE; + + // Clicking in the dropdown list steals focus from the proxy. + // So, set the focus-restore flag up. + SetRestoreFocus(TRUE); + } else if (notifyCode == CBN_CLOSEUP) { + SetRestoreFocus(FALSE); } return mrDoDefault; } @@ -414,19 +485,7 @@ MsgRouting AwtChoice::WmKillFocus(HWND hWndGotFocus) { skipNextMouseUp = TRUE; - - switch (killFocusRouting) { - case mrConsume: - return mrConsume; - case mrDoDefault: - killFocusRouting = mrPassAlong; - return mrDoDefault; - case mrPassAlong: - return AwtComponent::WmKillFocus(hWndGotFocus); - } - - DASSERT(false); // must never reach here - return mrDoDefault; + return AwtComponent::WmKillFocus(hWndGotFocus); } MsgRouting @@ -441,27 +500,17 @@ AwtChoice::WmMouseUp(UINT flags, int x, int y, int button) MsgRouting AwtChoice::HandleEvent(MSG *msg, BOOL synthetic) { - /* - * 6366006 - * Note: the event can be sent in two cases: - * 1) The Choice is closed and user clicks on it to drop it down. - * 2) The Choice is non-focusable, it's droped down, user - * clicks on it (or outside) to close it. - * So, if the Choice is in droped down state, we shouldn't call - * heavyweightButtonDown() method. Otherwise it will set a typeahead marker - * that won't be removed, because no focus events will be generated. - */ - if (AwtComponent::sm_focusOwner != GetHWnd() && - (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) && - !IsChoiceOpened()) + if (IsFocusingMouseMessage(msg)) { + SendMessage(CB_SHOWDROPDOWN, ~SendMessage(CB_GETDROPPEDSTATE, 0, 0), 0); + delete msg; + return mrConsume; + } + // To simulate the native behavior, we close the list on WM_LBUTTONUP if + // WM_MOUSEMOVE has been dedected on the list since it has been dropped down. + if (msg->message == WM_LBUTTONUP && SendMessage(CB_GETDROPPEDSTATE, 0, 0) && + sm_isMouseMoveInList) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); + SendMessage(CB_SHOWDROPDOWN, FALSE, 0); } return AwtComponent::HandleEvent(msg, synthetic); } @@ -618,6 +667,26 @@ done: env->DeleteGlobalRef(choice); } +void AwtChoice::_CloseList(void *param) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + jobject choice = (jobject)param; + + AwtChoice *c = NULL; + + PDATA pData; + JNI_CHECK_PEER_GOTO(choice, done); + + c = (AwtChoice *)pData; + if (::IsWindow(c->GetHWnd()) && c->SendMessage(CB_GETDROPPEDSTATE, 0, 0)) { + c->SendMessage(CB_SHOWDROPDOWN, FALSE, 0); + } + +done: + env->DeleteGlobalRef(choice); +} + /************************************************************************ * WChoicePeer native methods */ @@ -752,6 +821,23 @@ Java_sun_awt_windows_WChoicePeer_create(JNIEnv *env, jobject self, CATCH_BAD_ALLOC; } +/* + * Class: sun_awt_windows_WChoicePeer + * Method: closeList + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WChoicePeer_closeList(JNIEnv *env, jobject self) +{ + TRY; + + jobject selfGlobalRef = env->NewGlobalRef(self); + + AwtToolkit::GetInstance().SyncCall(AwtChoice::_CloseList, (void *)selfGlobalRef); + // global ref is deleted in _CloseList + + CATCH_BAD_ALLOC; +} } /* extern "C" */ diff --git a/src/windows/native/sun/windows/awt_Choice.h b/src/windows/native/sun/windows/awt_Choice.h index 075cb0c5e..35e917474 100644 --- a/src/windows/native/sun/windows/awt_Choice.h +++ b/src/windows/native/sun/windows/awt_Choice.h @@ -43,6 +43,8 @@ public: virtual LPCTSTR GetClassName(); static AwtChoice* Create(jobject peer, jobject hParent); + virtual void Dispose(); + virtual void Reshape(int x, int y, int w, int h); void ResetDropDownHeight(); int GetDropDownHeight(); @@ -75,9 +77,6 @@ public: virtual void SetDragCapture(UINT flags); virtual void ReleaseDragCapture(UINT flags); - BOOL ActMouseMessage(MSG * pMsg); - INLINE BOOL AwtChoice::IsChoiceOpened() {return SendMessage(CB_GETDROPPEDSTATE, 0, 0);} - static BOOL mouseCapture; static BOOL skipNextMouseUp; @@ -87,11 +86,16 @@ public: static void _AddItems(void *param); static void _Remove(void *param); static void _RemoveAll(void *param); + static void _CloseList(void *param); private: int GetFieldHeight(); int GetTotalHeight(); - MsgRouting killFocusRouting; + static BOOL sm_isMouseMoveInList; + HWND m_hList; + WNDPROC m_listDefWindowProc; + static LRESULT CALLBACK ListWindowProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); }; #endif /* AWT_CHOICE_H */ diff --git a/src/windows/native/sun/windows/awt_Component.cpp b/src/windows/native/sun/windows/awt_Component.cpp index 6f0df2e44..9db8ec4b8 100644 --- a/src/windows/native/sun/windows/awt_Component.cpp +++ b/src/windows/native/sun/windows/awt_Component.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -38,7 +38,6 @@ #include "awt_InputTextInfor.h" #include "awt_Insets.h" #include "awt_KeyEvent.h" -#include "awt_KeyboardFocusManager.h" #include "awt_MenuItem.h" #include "awt_MouseEvent.h" #include "awt_Palette.h" @@ -58,7 +57,6 @@ #include <java_awt_Event.h> #include <java_awt_event_KeyEvent.h> #include <java_awt_Insets.h> -#include <java_awt_KeyboardFocusManager.h> #include <sun_awt_windows_WPanelPeer.h> #include <java_awt_event_InputEvent.h> #include <java_awt_event_InputMethodEvent.h> @@ -94,12 +92,13 @@ extern "C" { BOOL g_bUserHasChangedInputLang = FALSE; } -BOOL AwtComponent::sm_suppressFocusAndActivation; -HWND AwtComponent::sm_focusOwner; -HWND AwtComponent::sm_focusedWindow; -HWND AwtComponent::sm_realFocusOpposite; +BOOL AwtComponent::sm_suppressFocusAndActivation = FALSE; +BOOL AwtComponent::sm_restoreFocusAndActivation = FALSE; +HWND AwtComponent::sm_focusOwner = NULL; +HWND AwtComponent::sm_focusedWindow = NULL; BOOL AwtComponent::sm_bMenuLoop = FALSE; AwtComponent* AwtComponent::sm_getComponentCache = NULL; +BOOL AwtComponent::sm_inSynthesizeFocus = FALSE; /************************************************************************/ // Struct for _Reshape() and ReshapeNoCheck() methods @@ -123,15 +122,6 @@ struct SetFontStruct { jobject component; jobject font; }; -// Struct for _RequestFocus() method -struct RequestFocusStruct { - jobject component; - jobject lightweightChild; - jboolean temporary; - jboolean focusedWindowChangeAllowed; - jlong time; - jobject cause; -}; // Struct for _CreatePrintedPixels() method struct CreatePrintedPixelsStruct { jobject component; @@ -149,6 +139,16 @@ struct GetInsetsStruct { jobject window; RECT *insets; }; +// Struct for _SetZOrder function +struct SetZOrderStruct { + jobject component; + jlong above; +}; +// Struct for _SetFocus function +struct SetFocusStruct { + jobject component; + jboolean doSetFocus; +}; /************************************************************************/ ////////////////////////////////////////////////////////////////////////// @@ -199,8 +199,7 @@ BOOL AwtComponent::sm_rtl = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC || BOOL AwtComponent::sm_rtlReadingOrder = PRIMARYLANGID(GetInputLanguage()) == LANG_ARABIC; -UINT AwtComponent::sm_95WheelMessage = WM_NULL; -UINT AwtComponent::sm_95WheelSupport = WM_NULL; +BOOL AwtComponent::sm_PrimaryDynamicTableBuilt = FALSE; HWND AwtComponent::sm_cursorOn; BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE; @@ -208,8 +207,6 @@ BOOL AwtComponent::m_QueryNewPaletteCalled = FALSE; CriticalSection windowMoveLock; BOOL windowMoveLockHeld = FALSE; -int AwtComponent::sm_wheelRotationAmount = 0; - /************************************************************************ * AwtComponent methods */ @@ -237,7 +234,6 @@ AwtComponent::AwtComponent() m_InputMethod = NULL; m_useNativeCompWindow = TRUE; m_PendingLeadByte = 0; - m_skipNextSetFocus = FALSE; m_bitsCandType = 0; windowMoveLockPosX = 0; @@ -250,6 +246,12 @@ AwtComponent::AwtComponent() m_bSubclassed = FALSE; m_MessagesProcessing = 0; + m_wheelRotationAmount = 0; + if (!sm_PrimaryDynamicTableBuilt) { + // do it once. + AwtComponent::BuildPrimaryDynamicTable(); + sm_PrimaryDynamicTableBuilt = TRUE; + } } AwtComponent::~AwtComponent() @@ -265,8 +267,7 @@ AwtComponent::~AwtComponent() * the native one anymore. So we can safely destroy component's * handle. */ - AwtToolkit::DestroyComponentHWND(m_hwnd); - m_hwnd = NULL; + DestroyHWnd(); if (sm_getComponentCache == this) { sm_getComponentCache = NULL; @@ -275,15 +276,8 @@ AwtComponent::~AwtComponent() void AwtComponent::Dispose() { - if (sm_focusOwner == GetHWnd()) { - ::SetFocus(NULL); - } - if (sm_focusedWindow == GetHWnd()) { - sm_focusedWindow = NULL; - } - if (sm_realFocusOpposite == GetHWnd()) { - sm_realFocusOpposite = NULL; - } + // NOTE: in case the component/toplevel was focused, Java should + // have already taken care of proper transfering it or clearing. if (m_hdwp != NULL) { // end any deferred window positioning, regardless @@ -588,6 +582,17 @@ AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title, } /* + * Destroy this window's HWND + */ +void AwtComponent::DestroyHWnd() { + if (m_hwnd != NULL) { + AwtToolkit::DestroyComponentHWND(m_hwnd); + //AwtToolkit::DestroyComponent(this); + m_hwnd = NULL; + } +} + +/* * Returns hwnd for target on non Toolkit thread */ HWND @@ -888,27 +893,8 @@ void AwtComponent::Show() void AwtComponent::Hide() { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject peer = GetPeer(env); - BOOL oldValue = sm_suppressFocusAndActivation; m_visible = false; - - // On disposal the focus owner actually loses focus at the moment of hiding. - // So, focus change suppression (if requested) should be made here. - if (GetHWnd() == sm_focusOwner && - !JNU_CallMethodByName(env, NULL, peer, "isAutoFocusTransferOnDisposal", "()Z").z) - { - sm_suppressFocusAndActivation = TRUE; - // The native system may autotransfer focus on hiding to the parent - // of the component. Nevertheless this focus change won't be posted - // to the Java level, we're better to avoid this. Anyway, after - // the disposal focus should be requested to the right component. - ::SetFocus(NULL); - sm_focusOwner = NULL; - } ::ShowWindow(GetHWnd(), SW_HIDE); - - sm_suppressFocusAndActivation = oldValue; } BOOL @@ -1252,6 +1238,7 @@ void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) { WIN_MSG(WM_AWT_COMPONENT_SHOW) WIN_MSG(WM_AWT_COMPONENT_HIDE) WIN_MSG(WM_AWT_COMPONENT_SETFOCUS) + WIN_MSG(WM_AWT_WINDOW_SETACTIVE) WIN_MSG(WM_AWT_LIST_SETMULTISELECT) WIN_MSG(WM_AWT_HANDLE_EVENT) WIN_MSG(WM_AWT_PRINT_COMPONENT) @@ -1503,67 +1490,54 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) sm_bMenuLoop = FALSE; break; + // We don't expect any focus messages on non-proxy component, + // except those that came from Java. case WM_SETFOCUS: - mr = (!sm_suppressFocusAndActivation && !m_skipNextSetFocus) - ? WmSetFocus((HWND)wParam) : mrConsume; - m_skipNextSetFocus = FALSE; + if (sm_inSynthesizeFocus) { + mr = WmSetFocus((HWND)wParam); + } else { + mr = mrConsume; + } break; case WM_KILLFOCUS: - mr = (!sm_suppressFocusAndActivation) - ? WmKillFocus((HWND)wParam) : mrConsume; + if (sm_inSynthesizeFocus) { + mr = WmKillFocus((HWND)wParam); + } else { + mr = mrConsume; + } break; - case WM_ACTIVATE: - { + case WM_ACTIVATE: { UINT nState = LOWORD(wParam); BOOL fMinimized = (BOOL)HIWORD(wParam); + mr = mrConsume; + if (!sm_suppressFocusAndActivation && (!fMinimized || (nState == WA_INACTIVE))) { mr = WmActivate(nState, fMinimized, (HWND)lParam); - m_skipNextSetFocus = FALSE; + // When the window is deactivated, send WM_IME_ENDCOMPOSITION // message to deactivate the composition window so that // it won't receive keyboard input focus. if (ImmGetContext() != NULL) { DefWindowProc(WM_IME_ENDCOMPOSITION, 0, 0); } - } else { - if (!sm_suppressFocusAndActivation - && fMinimized && (nState != WA_INACTIVE)) - { - m_skipNextSetFocus = TRUE; - } - mr = mrConsume; } + break; + } + case WM_MOUSEACTIVATE: { + AwtWindow *window = GetContainer(); + if (window && window->IsFocusableWindow()) { + // AWT/Swing will later request focus to a proper component + // on handling the Java mouse event. Anyway, we have to + // activate the window here as it works both for AWT & Swing. + // Do it in our own fassion, + window->AwtSetActiveWindow(TRUE, LOWORD(lParam)/*hittest*/); + } + mr = mrConsume; + retValue = MA_NOACTIVATE; + break; } - break; - case WM_MOUSEACTIVATE: { - AwtWindow * window = (AwtWindow*)GetComponent((HWND)wParam); - if (window != NULL) { - if (!window->IsFocusableWindow()) { - // if it is non-focusable window we can return - // MA_NOACTIVATExxx and it will not be activated. We - // return NOACTIVATE for a client part of the window so we - // receive mouse event responsible for activation. We - // return NOACTIVEA for Frame's non-client so user be able - // to resize and move frames by title and borders. We - // return NOACTIVATEANDEAT for Window non-client area as - // there is noone to listen for this event. - mr = mrConsume; - if ((window == this) && LOWORD(lParam) != HTCLIENT ) { - if (window->IsSimpleWindow()) { - retValue = MA_NOACTIVATEANDEAT; - } else { - retValue = MA_NOACTIVATE; - } - } else { - retValue = MA_NOACTIVATE; - } - } - } - break; - } - case WM_CTLCOLORMSGBOX: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: @@ -1920,7 +1894,15 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) break; case WM_AWT_COMPONENT_SETFOCUS: - retValue = (LRESULT)WmComponentSetFocus((WmComponentSetFocusData *)wParam); + if ((BOOL)wParam) { + retValue = SynthesizeWmSetFocus(GetHWnd(), NULL); + } else { + retValue = SynthesizeWmKillFocus(GetHWnd(), NULL); + } + mr = mrConsume; + break; + case WM_AWT_WINDOW_SETACTIVE: + retValue = (LRESULT)((AwtWindow*)this)->AwtSetActiveWindow((BOOL)wParam); mr = mrConsume; break; @@ -2048,188 +2030,16 @@ MsgRouting AwtComponent::WmShowWindow(BOOL show, UINT status) MsgRouting AwtComponent::WmSetFocus(HWND hWndLostFocus) { - if (sm_focusOwner == GetHWnd()) { - sm_realFocusOpposite = NULL; - return mrConsume; - } - - HWND toplevelHWnd = AwtComponent::GetTopLevelParentForWindow(GetHWnd()); - AwtComponent *comp = AwtComponent::GetComponent(toplevelHWnd); - - if (comp && comp->IsEmbeddedFrame() && - !((AwtFrame*)comp)->activateEmbeddedFrameOnSetFocus(hWndLostFocus)) - { - // Fix for 6562716. - // In order that AwtSetFocus() returns FALSE. - sm_suppressFocusAndActivation = TRUE; - ::SetFocus(NULL); - sm_suppressFocusAndActivation = FALSE; - - return mrConsume; - } - - sm_focusOwner = GetHWnd(); - sm_focusedWindow = toplevelHWnd; - - if (sm_realFocusOpposite != NULL) { - hWndLostFocus = sm_realFocusOpposite; - sm_realFocusOpposite = NULL; - } - - sm_wheelRotationAmount = 0; - - SendFocusEvent(java_awt_event_FocusEvent_FOCUS_GAINED, hWndLostFocus); - + m_wheelRotationAmount = 0; return mrDoDefault; } MsgRouting AwtComponent::WmKillFocus(HWND hWndGotFocus) { - if (sm_focusOwner != NULL && sm_focusOwner == hWndGotFocus) { - return mrConsume; - } - - if (sm_focusOwner != GetHWnd()) { - if (sm_focusOwner != NULL) { - if (hWndGotFocus != NULL && - AwtComponent::GetComponent(hWndGotFocus) != NULL) - { - sm_realFocusOpposite = sm_focusOwner; - } - ::SendMessage(sm_focusOwner, WM_KILLFOCUS, (WPARAM)hWndGotFocus, - 0); - } - return mrConsume; - } - - AwtComponent *comp = AwtComponent::GetComponent(sm_focusedWindow); - - if (comp && comp->IsEmbeddedFrame()) { - ((AwtFrame*)comp)->deactivateEmbeddedFrameOnKillFocus(hWndGotFocus); - } - - sm_focusOwner = NULL; - sm_wheelRotationAmount = 0; - - SendFocusEvent(java_awt_event_FocusEvent_FOCUS_LOST, hWndGotFocus); + m_wheelRotationAmount = 0; return mrDoDefault; } -jboolean -AwtComponent::WmComponentSetFocus(WmComponentSetFocusData *data) -{ - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - if (env->EnsureLocalCapacity(1) < 0) { - env->DeleteGlobalRef(data->lightweightChild); - delete data; - return JNI_FALSE; - } - - jboolean result = JNI_FALSE; - - BOOL setSuppressFocusAndActivation = FALSE; - - /* - * This is a fix for 4628933. - * If sm_suppressFocusAndActivation is TRUE here then - * this means that we dispatch WM_COMPONENT_SET_FOCUS inside - * dispatching bounce activation, this unlikely but possible. - * So we reset sm_suppressFocusAndActivation to give a chance - * to dispatch focus events which will generate due this focus - * request to Java. - * - * son@sparc.spb.su - */ - if (sm_suppressFocusAndActivation) { - sm_suppressFocusAndActivation = FALSE; - setSuppressFocusAndActivation = TRUE; - } - - jobject heavyweight = GetTarget(env); - jint retval = env->CallStaticIntMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID, - heavyweight, data->lightweightChild, data->temporary, - data->focusedWindowChangeAllowed, data->time, data->cause); - - if (retval == java_awt_KeyboardFocusManager_SNFH_SUCCESS_HANDLED) { - result = JNI_TRUE; - } else if (retval == java_awt_KeyboardFocusManager_SNFH_SUCCESS_PROCEED) { - result = (AwtSetFocus()) ? JNI_TRUE : JNI_FALSE; - if (result == JNI_FALSE) { - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::removeLastFocusRequestMID, - heavyweight); - } - } else { - DASSERT(retval == java_awt_KeyboardFocusManager_SNFH_FAILURE); - result = JNI_FALSE; - } - env->DeleteLocalRef(heavyweight); - - /* - * Set sm_suppressFocusAndActivation back to TRUE if needed. - * Fix for 4628933 (son@sparc.spb.su) - */ - if (setSuppressFocusAndActivation) { - sm_suppressFocusAndActivation = TRUE; - } - - env->DeleteGlobalRef(data->lightweightChild); - delete data; - return result; -} - -BOOL -AwtComponent::AwtSetFocus() -{ - HWND hwnd = GetHWnd(); - - if (sm_focusOwner == hwnd) { - return TRUE; - } - - HWND fgWindow = ::GetForegroundWindow(); - if (NULL != fgWindow) { - DWORD fgProcessID; - ::GetWindowThreadProcessId(fgWindow, &fgProcessID); - - if (fgProcessID != ::GetCurrentProcessId() - && !AwtToolkit::GetInstance().IsEmbedderProcessId(fgProcessID)) - { - // fix for 6458497. we shouldn't request focus if it is out of both - // our and embedder process. - return FALSE; - } - } - - AwtWindow *pCont = GetContainer(); - AwtFrame *owner = pCont ? pCont->GetOwningFrameOrDialog() : NULL; - - if (owner == NULL) { - ::SetFocus(hwnd); - if (::GetFocus() != hwnd) { - return FALSE; - } - } else { - HWND oldFocusOwner = sm_focusOwner; - if (oldFocusOwner != NULL) { - ::SendMessage(oldFocusOwner, WM_KILLFOCUS, (WPARAM)hwnd, 0); - } - - sm_suppressFocusAndActivation = TRUE; - ::SetActiveWindow(owner->GetHWnd()); - ::SetFocus(owner->GetProxyFocusOwner()); - sm_suppressFocusAndActivation = FALSE; - - sm_focusedWindow = GetTopLevelParentForWindow(GetHWnd()); - ::SendMessage(hwnd, WM_SETFOCUS, (WPARAM)oldFocusOwner, 0); - } - - return TRUE; -} - MsgRouting AwtComponent::WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush) { @@ -2524,7 +2334,6 @@ MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button) AwtWindow::GetGrabbedWindow()->Ungrab(); } } - return mrConsume; } @@ -2638,11 +2447,11 @@ MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y, BOOL result; UINT platformLines; - sm_wheelRotationAmount += wheelRotation; + m_wheelRotationAmount += wheelRotation; // AWT interprets wheel rotation differently than win32, so we need to // decode wheel amount. - jint roundedWheelRotation = sm_wheelRotationAmount / (-1 * WHEEL_DELTA); + jint roundedWheelRotation = m_wheelRotationAmount / (-1 * WHEEL_DELTA); jdouble preciseWheelRotation = (jdouble) wheelRotation / (-1 * WHEEL_DELTA); MSG msg; @@ -2668,7 +2477,9 @@ MsgRouting AwtComponent::WmMouseWheel(UINT flags, int x, int y, eventPt.x, eventPt.y, GetJavaModifiers(), 0, 0, scrollType, scrollLines, roundedWheelRotation, preciseWheelRotation, &msg); - sm_wheelRotationAmount %= WHEEL_DELTA; + m_wheelRotationAmount %= WHEEL_DELTA; + // this message could be propagated up to the parent chain + // by the mouse message post processors return mrConsume; } @@ -3088,6 +2899,19 @@ static const CharToVKEntry charToDeadVKTable[] = { {0,0} }; +// The full map of the current keyboard state including +// windows virtual key, scancode, java virtual key, and unicode +// for this key sans modifiers. +// All but first element may be 0. +// XXX in the update releases this is an addition to the unchanged existing code +struct DynPrimaryKeymapEntry { + UINT wkey; + UINT scancode; + UINT jkey; + WCHAR unicode; +}; + +static DynPrimaryKeymapEntry dynPrimaryKeymap[256]; void AwtComponent::InitDynamicKeyMapTable() @@ -3096,6 +2920,8 @@ AwtComponent::InitDynamicKeyMapTable() if (!kbdinited) { AwtComponent::BuildDynamicKeyMapTable(); + // We cannot build it here since JNI is not available yet: + //AwtComponent::BuildPrimaryDynamicTable(); kbdinited = TRUE; } } @@ -3321,7 +3147,11 @@ UINT AwtComponent::WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers) for (int j = 0; dynamicKeyMapTable[j].windowsKey != 0; j++) { if (dynamicKeyMapTable[j].windowsKey == windowsKey) { - return dynamicKeyMapTable[j].javaKey; + if (dynamicKeyMapTable[j].javaKey != java_awt_event_KeyEvent_VK_UNDEFINED) { + return dynamicKeyMapTable[j].javaKey; + }else{ + break; + } } } @@ -3398,6 +3228,122 @@ BOOL AwtComponent::IsNumPadKey(UINT vkey, BOOL extended) return FALSE; } +static void +resetKbdState( BYTE kstate[256]) { + BYTE tmpState[256]; + WCHAR wc[2]; + memmove(tmpState, kstate, sizeof(kstate)); + tmpState[VK_SHIFT] = 0; + tmpState[VK_CONTROL] = 0; + tmpState[VK_MENU] = 0; + + ::ToUnicodeEx(VK_SPACE,::MapVirtualKey(VK_SPACE, 0), tmpState, wc, 2, 0, GetKeyboardLayout(0)); +} + +// XXX in the update releases this is an addition to the unchanged existing code +// After the call, a table will have a unicode associated with a windows virtual keycode +// sans modifiers. With some further simplification, one can +// derive java keycode from it, and anyway we will pass this unicode value +// all the way up in a comment to a KeyEvent. +void +AwtComponent::BuildPrimaryDynamicTable() { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + // XXX: how about that? + //CriticalSection::Lock l(GetLock()); + //if (GetPeer(env) == NULL) { + // /* event received during termination. */ + // return; + //} + + HKL hkl = GetKeyboardLayout(); + UINT sc = 0; + BYTE kbdState[AwtToolkit::KB_STATE_SIZE]; + memset(kbdState, 0, sizeof (kbdState)); + + // Use JNI call to obtain java key code. We should keep a list + // of currently available keycodes in a single place. + static jclass extKeyCodesCls; + if( extKeyCodesCls == NULL) { + jclass extKeyCodesClsLocal = env->FindClass("sun/awt/ExtendedKeyCodes"); + DASSERT(extKeyCodesClsLocal); + if (extKeyCodesClsLocal == NULL) { + /* exception already thrown */ + return; + } + extKeyCodesCls = (jclass)env->NewGlobalRef(extKeyCodesClsLocal); + env->DeleteLocalRef(extKeyCodesClsLocal); + } + static jmethodID getExtendedKeyCodeForChar; + if (getExtendedKeyCodeForChar == NULL) { + getExtendedKeyCodeForChar = + env->GetStaticMethodID(extKeyCodesCls, "getExtendedKeyCodeForChar", "(I)I"); + DASSERT(getExtendedKeyCodeForChar); + } + jint extJKC; //extended Java key code + + for (UINT i = 0; i < 256; i++) { + dynPrimaryKeymap[i].wkey = i; + dynPrimaryKeymap[i].jkey = java_awt_event_KeyEvent_VK_UNDEFINED; + dynPrimaryKeymap[i].unicode = 0; + + if ((sc = MapVirtualKey (i, 0)) == 0) { + dynPrimaryKeymap[i].scancode = 0; + continue; + } + dynPrimaryKeymap[i].scancode = sc; + + // XXX process cases like VK_SHIFT etc. + kbdState[i] = 0x80; // "key pressed". + WCHAR wc[16]; + int k = ::ToUnicodeEx(i, sc, kbdState, wc, 16, 0, hkl); + if (k == 1) { + // unicode + dynPrimaryKeymap[i].unicode = wc[0]; + if (dynPrimaryKeymap[i].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) { + // Convert unicode to java keycode. + //dynPrimaryKeymap[i].jkey = ((UINT)(wc[0]) + 0x01000000); + // + //XXX If this key in on the keypad, we should force a special value equal to + //XXX an old java keycode: but how to say if it is a keypad key? + //XXX We'll do it in WmKeyUp/Down. + extJKC = env->CallStaticIntMethod(extKeyCodesCls, + getExtendedKeyCodeForChar, (jint)(wc[0])); + dynPrimaryKeymap[i].jkey = extJKC; + } + }else if (k == -1) { + // dead key: use charToDeadVKTable + dynPrimaryKeymap[i].unicode = wc[0]; + resetKbdState( kbdState ); + for (const CharToVKEntry *map = charToDeadVKTable; map->c != 0; ++map) { + if (wc[0] == map->c) { + dynPrimaryKeymap[i].jkey = map->javaKey; + break; + } + } + } else if (k == 0) { + // reset + resetKbdState( kbdState ); + }else { + printf ("++++Whats that? wkey 0x%x (%d)\n", i,i); + } + kbdState[i] = 0; // "key unpressed" + } +} +void +AwtComponent::UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers) +{ + if( wkey && wkey < 256 ) { + if(keyLocation == java_awt_event_KeyEvent_KEY_LOCATION_NUMPAD) { + // At the creation time, + // dynPrimaryKeymap cannot distinguish between e.g. "/" and "NumPad /" + dynPrimaryKeymap[wkey].jkey = jkeyLegacy; + } + if(dynPrimaryKeymap[wkey].jkey == java_awt_event_KeyEvent_VK_UNDEFINED) { + // E.g. it is non-unicode key + dynPrimaryKeymap[wkey].jkey = jkeyLegacy; + } + } +} UINT AwtComponent::WindowsKeyToJavaChar(UINT wkey, UINT modifiers, TransOps ops) { @@ -3554,10 +3500,12 @@ MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt, jint keyLocation = GetKeyLocation(wkey, flags); UINT jkey = WindowsKeyToJavaKey(wkey, modifiers); UINT character = WindowsKeyToJavaChar(wkey, modifiers, SAVE); + UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); + SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED, TimeHelper::windowsToUTC(msg.time), jkey, character, - modifiers, keyLocation, &msg); + modifiers, keyLocation, (jlong)wkey, &msg); // bugid 4724007: Windows does not create a WM_CHAR for the Del key // for some reason, so we need to create the KEY_TYPED event on the @@ -3569,7 +3517,7 @@ MsgRouting AwtComponent::WmKeyDown(UINT wkey, UINT repCnt, TimeHelper::windowsToUTC(msg.time), java_awt_event_KeyEvent_VK_UNDEFINED, character, modifiers, - java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN); + java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0); } return mrConsume; @@ -3594,10 +3542,11 @@ MsgRouting AwtComponent::WmKeyUp(UINT wkey, UINT repCnt, jint keyLocation = GetKeyLocation(wkey, flags); UINT jkey = WindowsKeyToJavaKey(wkey, modifiers); UINT character = WindowsKeyToJavaChar(wkey, modifiers, LOAD); + UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers); SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED, TimeHelper::windowsToUTC(msg.time), jkey, character, - modifiers, keyLocation, &msg); + modifiers, keyLocation, (jlong)wkey, &msg); return mrConsume; } @@ -3613,6 +3562,7 @@ MsgRouting AwtComponent::WmInputLangChange(UINT charset, HKL hKeyboardLayout) m_idLang = LOWORD(hKeyboardLayout); // lower word of HKL is LANGID m_CodePage = LangToCodePage(m_idLang); BuildDynamicKeyMapTable(); // compute new mappings for VK_OEM + BuildPrimaryDynamicTable(); return mrConsume; // do not propagate to children } @@ -3643,7 +3593,7 @@ MsgRouting AwtComponent::WmIMEChar(UINT character, UINT repCnt, UINT flags, BOOL TimeHelper::windowsToUTC(msg.time), java_awt_event_KeyEvent_VK_UNDEFINED, unicodeChar, modifiers, - java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, + java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, &msg); return mrConsume; } @@ -3712,7 +3662,7 @@ MsgRouting AwtComponent::WmChar(UINT character, UINT repCnt, UINT flags, TimeHelper::windowsToUTC(msg.time), java_awt_event_KeyEvent_VK_UNDEFINED, unicodeChar, modifiers, - java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, + java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, &msg); return mrConsume; } @@ -4033,14 +3983,15 @@ HIMC AwtComponent::ImmAssociateContext(HIMC himc) HWND AwtComponent::GetProxyFocusOwner() { - AwtWindow * window = GetContainer(); + AwtWindow *window = GetContainer(); if (window != 0) { - AwtFrame * owner = window->GetOwningFrameOrDialog(); + AwtFrame *owner = window->GetOwningFrameOrDialog(); if (owner != 0) { return owner->GetProxyFocusOwner(); + } else if (!window->IsSimpleWindow()) { // isn't an owned simple window + return ((AwtFrame*)window)->GetProxyFocusOwner(); } } - return (HWND)NULL; } @@ -4562,6 +4513,25 @@ HDC AwtComponent::GetDCFromComponent() return hdc; } +void AwtComponent::FillBackground(HDC hMemoryDC, SIZE &size) +{ + RECT eraseR = { 0, 0, size.cx, size.cy }; + VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush())); +} + +void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha) +{ + if (bitmapBits) { + DWORD* dest = (DWORD*)bitmapBits; + //XXX: might be optimized to use one loop (cy*cx -> 0). + for (int i = 0; i < size.cy; i++ ) { + for (int j = 0; j < size.cx; j++ ) { + ((BYTE*)(dest++))[3] = alpha; + } + } + } +} + jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -4619,26 +4589,53 @@ jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size) { return pixelArray; } -void * -AwtComponent::GetNativeFocusOwner() { +void* AwtComponent::SetNativeFocusOwner(void *self) { + if (self == NULL) { + // It means that the KFM wants to set focus to null + sm_focusOwner = NULL; + return NULL; + } + + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + AwtComponent *c = NULL; + jobject peer = (jobject)self; + + PDATA pData; + JNI_CHECK_NULL_GOTO(peer, "peer", ret); + pData = JNI_GET_PDATA(peer); + if (pData == NULL) { + goto ret; + } + c = (AwtComponent *)pData; + +ret: + if (c && ::IsWindow(c->GetHWnd())) { + sm_focusOwner = c->GetHWnd(); + AwtFrame *owner = (AwtFrame*)GetComponent(c->GetProxyToplevelContainer()); + if (owner) { + owner->SetLastProxiedFocusOwner(sm_focusOwner); + } + } else { + sm_focusOwner = NULL; + } + env->DeleteGlobalRef(peer); + return NULL; +} + +void* AwtComponent::GetNativeFocusedWindow() { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); AwtComponent *comp = - AwtComponent::GetComponent(AwtComponent::sm_focusOwner); + AwtComponent::GetComponent(AwtComponent::GetFocusedWindow()); return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL; } -void * -AwtComponent::GetNativeFocusedWindow() { + +void* AwtComponent::GetNativeFocusOwner() { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); AwtComponent *comp = - AwtComponent::GetComponent(AwtComponent::sm_focusedWindow); + AwtComponent::GetComponent(AwtComponent::sm_focusOwner); return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL; } -void -AwtComponent::ClearGlobalFocusOwner() { - if (AwtComponent::sm_focusOwner != NULL) { - ::SetFocus(NULL); - } -} AwtComponent* AwtComponent::SearchChild(UINT id) { ChildListItem* child; @@ -4674,7 +4671,7 @@ void AwtComponent::RemoveChild(UINT id) { } void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked, - jint modifiers, jint keyLocation, MSG *pMsg) + jint modifiers, jint keyLocation, jlong nativeCode, MSG *pMsg) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); CriticalSection::Lock l(GetLock()); @@ -4711,6 +4708,18 @@ void AwtComponent::SendKeyEvent(jint id, jlong when, jint raw, jint cooked, if (safe_ExceptionOccurred(env)) env->ExceptionDescribe(); DASSERT(!safe_ExceptionOccurred(env)); DASSERT(keyEvent != NULL); + env->SetLongField(keyEvent, AwtKeyEvent::rawCodeID, nativeCode); + if( nativeCode && nativeCode < 256 ) { + env->SetLongField(keyEvent, AwtKeyEvent::primaryLevelUnicodeID, (jlong)(dynPrimaryKeymap[nativeCode].unicode)); + env->SetLongField(keyEvent, AwtKeyEvent::extendedKeyCodeID, (jlong)(dynPrimaryKeymap[nativeCode].jkey)); + if( nativeCode < 255 ) { + env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(dynPrimaryKeymap[nativeCode].scancode)); + }else if( pMsg != NULL ) { + // unknown key with virtual keycode 0xFF. + // Its scancode is not in the table, pickup it from the message. + env->SetLongField(keyEvent, AwtKeyEvent::scancodeID, (jlong)(HIWORD(pMsg->lParam) & 0xFF)); + } + } if (pMsg != NULL) { AwtAWTEvent::saveMSG(env, pMsg, keyEvent); } @@ -4724,16 +4733,17 @@ void AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when, jint raw, jint cooked, jint modifiers, jint keyLocation, + jlong nativeCode, MSG *msg) { /* * if focus owner is null, but focused window isn't * we will send key event to focused window */ - HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : sm_focusedWindow); + HWND hwndTarget = ((sm_focusOwner != NULL) ? sm_focusOwner : AwtComponent::GetFocusedWindow()); if (hwndTarget == GetHWnd()) { - SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, msg); + SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, nativeCode, msg); } else { AwtComponent *target = NULL; if (hwndTarget != NULL) { @@ -4744,7 +4754,7 @@ AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when, } if (target != NULL) { target->SendKeyEvent(id, when, raw, cooked, modifiers, - keyLocation, msg); + keyLocation, nativeCode, msg); } } } @@ -5158,14 +5168,7 @@ void AwtComponent::SynthesizeMouseMessage(JNIEnv *env, jobject mouseEvent) jint x = (env)->GetIntField(mouseEvent, AwtMouseEvent::xID); jint y = (env)->GetIntField(mouseEvent, AwtMouseEvent::yID); MSG* msg = CreateMessage(message, wParam, MAKELPARAM(x, y), x, y); - // If the window is not focusable but if this is a focusing - // message we should skip it then and perform our own actions. - AwtWindow *pCont = GetContainer(); - if ((pCont && pCont->IsFocusableWindow()) || !ActMouseMessage(msg)) { - PostHandleEventMessage(msg, TRUE); - } else { - delete msg; - } + PostHandleEventMessage(msg, TRUE); } BOOL AwtComponent::InheritsNativeMouseWheelBehavior() {return false;} @@ -5251,15 +5254,14 @@ void AwtComponent::UnlinkObjects() void AwtComponent::Enable(BOOL bEnable) { - sm_suppressFocusAndActivation = TRUE; - if (bEnable && IsTopLevel()) { // we should not enable blocked toplevels bEnable = !::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())); } + // Shouldn't trigger native focus change + // (only the proxy may be the native focus owner). ::EnableWindow(GetHWnd(), bEnable); - sm_suppressFocusAndActivation = FALSE; CriticalSection::Lock l(GetLock()); VerifyState(); } @@ -5286,23 +5288,12 @@ void AwtComponent::DestroyDropTarget() { } } -/** - * Special procedure responsible for performing the actions which - * usually happen with component when mouse buttons are being - * pressed. It is required in case of non-focusable components - we - * don't pass mouse messages directly to the windows because otherwise - * it will try to focus component first which we don't want. This - * function receives MSG and should return TRUE if it processed the - * message and no furhter processing is allowed, FALSE otherwise. - * Default implementation returns TRUE it is the message on which - * Windows try to focus the component. Descendant components write - * their own implementation of this procedure. - */ -BOOL AwtComponent::ActMouseMessage(MSG * pMsg) { - if (IsFocusingMessage(pMsg->message)) { - return TRUE; - } - return FALSE; +BOOL AwtComponent::IsFocusingMouseMessage(MSG *pMsg) { + return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK; +} + +BOOL AwtComponent::IsFocusingKeyMessage(MSG *pMsg) { + return pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_SPACE; } void AwtComponent::_Show(void *param) @@ -5640,22 +5631,12 @@ void AwtComponent::_NativeHandleEvent(void *param) return; } - /* Post the message directly to the subclassed component. */ - if (self && (pData = JNI_GET_PDATA(self))) { - AwtComponent* p = (AwtComponent*)pData; - // If the window is not focusable but if this is a focusing - // message we should skip it then and perform our own actions. - AwtWindow *pCont = (AwtWindow*)(p->GetContainer()); - if ((pCont && pCont->IsFocusableWindow()) || - !p->ActMouseMessage(&msg)) - { - // Create copy for local msg - MSG* pCopiedMsg = new MSG; - memmove(pCopiedMsg, &msg, sizeof(MSG)); - // Event handler deletes msg - p->PostHandleEventMessage(pCopiedMsg, FALSE); - } - } + // Create copy for local msg + MSG* pCopiedMsg = new MSG; + memmove(pCopiedMsg, &msg, sizeof(MSG)); + // Event handler deletes msg + p->PostHandleEventMessage(pCopiedMsg, FALSE); + env->DeleteGlobalRef(self); env->DeleteGlobalRef(event); delete nhes; @@ -5777,19 +5758,15 @@ ret: delete sfs; } -jboolean AwtComponent::_RequestFocus(void *param) +// Sets or kills focus for a component. +void AwtComponent::_SetFocus(void *param) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - RequestFocusStruct *rfs = (RequestFocusStruct *)param; - jobject self = rfs->component; - jobject lightweightChild = rfs->lightweightChild; - jboolean temporary = rfs->temporary; - jboolean focusedWindowChangeAllowed = rfs->focusedWindowChangeAllowed; - jlong time = rfs->time; - jobject cause = rfs->cause; + SetFocusStruct *sfs = (SetFocusStruct *)param; + jobject self = sfs->component; + jboolean doSetFocus = sfs->doSetFocus; - jboolean result = JNI_FALSE; AwtComponent *c = NULL; PDATA pData; @@ -5801,25 +5778,13 @@ jboolean AwtComponent::_RequestFocus(void *param) } c = (AwtComponent *)pData; - if (::IsWindow(c->GetHWnd())) - { - WmComponentSetFocusData *data = new WmComponentSetFocusData; - data->lightweightChild = env->NewGlobalRef(lightweightChild); - data->temporary = temporary; - data->focusedWindowChangeAllowed = focusedWindowChangeAllowed; - data->time = time; - data->cause = cause; - result = (jboolean)c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)data, 0); - // data and global ref in it are deleted in WmComponentSetFocus + if (::IsWindow(c->GetHWnd())) { + c->SendMessage(WM_AWT_COMPONENT_SETFOCUS, (WPARAM)doSetFocus, 0); } ret: env->DeleteGlobalRef(self); - env->DeleteGlobalRef(lightweightChild); - env->DeleteGlobalRef(cause); - delete rfs; - - return result; + delete sfs; } void AwtComponent::_Start(void *param) @@ -6082,9 +6047,9 @@ void AwtComponent::SetParent(void * param) { HWND selfWnd = comps[0]->GetHWnd(); HWND parentWnd = comps[1]->GetHWnd(); if (::IsWindow(selfWnd) && ::IsWindow(parentWnd)) { - sm_suppressFocusAndActivation = TRUE; + // Shouldn't trigger native focus change + // (only the proxy may be the native focus owner). ::SetParent(selfWnd, parentWnd); - sm_suppressFocusAndActivation = FALSE; } } delete[] comps; @@ -6107,15 +6072,12 @@ void AwtComponent::_SetRectangularShape(void *param) AwtComponent *c = NULL; - - PDATA pData; JNI_CHECK_PEER_GOTO(self, ret); + c = (AwtComponent *)pData; - if (::IsWindow(c->GetHWnd())) - { + if (::IsWindow(c->GetHWnd())) { HRGN hRgn = NULL; - if (region || x1 || x2 || y1 || y2) { // If all the params are zeros, the shape must be simply reset. // Otherwise, convert it into a region. @@ -6157,6 +6119,33 @@ ret: delete data; } +void AwtComponent::_SetZOrder(void *param) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + SetZOrderStruct *data = (SetZOrderStruct *)param; + jobject self = data->component; + HWND above = HWND_TOP; + if (data->above != 0) { + above = reinterpret_cast<HWND>(data->above); + } + + AwtComponent *c = NULL; + + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + + c = (AwtComponent *)pData; + if (::IsWindow(c->GetHWnd())) { + ::SetWindowPos(c->GetHWnd(), above, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS); + } + +ret: + env->DeleteGlobalRef(self); + + delete data; +} + void AwtComponent::PostUngrabEvent() { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject target = GetTarget(env); @@ -6173,6 +6162,14 @@ void AwtComponent::PostUngrabEvent() { } } +void AwtComponent::SetFocusedWindow(HWND window) +{ + HWND old = sm_focusedWindow; + sm_focusedWindow = window; + + AwtWindow::FocusedWindowChanged(old, window); +} + /************************************************************************ * Component native methods */ @@ -6587,31 +6584,25 @@ Java_sun_awt_windows_WComponentPeer__1setFont(JNIEnv *env, jobject self, /* * Class: sun_awt_windows_WComponentPeer - * Method: requestFocus - * Signature: (Ljava/awt/Component;ZZJ)Z + * Method: focusGained + * Signature: (Z) */ -JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WComponentPeer__1requestFocus - (JNIEnv *env, jobject self, jobject lightweightChild, jboolean temporary, - jboolean focusedWindowChangeAllowed, jlong time, jobject cause) +JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_setFocus + (JNIEnv *env, jobject self, jboolean doSetFocus) { TRY; jobject selfGlobalRef = env->NewGlobalRef(self); - jobject lightweightChildGlobalRef = env->NewGlobalRef(lightweightChild); - RequestFocusStruct *rfs = new RequestFocusStruct; - rfs->component = selfGlobalRef; - rfs->lightweightChild = lightweightChildGlobalRef; - rfs->temporary = temporary; - rfs->focusedWindowChangeAllowed = focusedWindowChangeAllowed; - rfs->time = time; - rfs->cause = env->NewGlobalRef(cause); + SetFocusStruct *sfs = new SetFocusStruct; + sfs->component = selfGlobalRef; + sfs->doSetFocus = doSetFocus; - return (jboolean)AwtToolkit::GetInstance().SyncCall( - (void*(*)(void*))AwtComponent::_RequestFocus, rfs); - // global refs and rfs are deleted in _RequestFocus + AwtToolkit::GetInstance().SyncCall( + (void*(*)(void*))AwtComponent::_SetFocus, sfs); + // global refs and self are deleted in _SetFocus - CATCH_BAD_ALLOC_RET(JNI_FALSE); + CATCH_BAD_ALLOC; } /* @@ -6823,25 +6814,6 @@ Java_sun_awt_windows_WComponentPeer_isObscured(JNIEnv* env, CATCH_BAD_ALLOC_RET(NULL); } -JNIEXPORT jboolean JNICALL -Java_sun_awt_windows_WComponentPeer_processSynchronousLightweightTransfer(JNIEnv *env, jclass cls, - jobject heavyweight, - jobject descendant, - jboolean temporary, - jboolean focusedWindowChangeAllowed, - jlong time) -{ - TRY; - - return env->CallStaticBooleanMethod(AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::processSynchronousTransfer, - heavyweight, descendant, temporary, - focusedWindowChangeAllowed, - time); - - CATCH_BAD_ALLOC_RET(JNI_TRUE); -} - JNIEXPORT void JNICALL Java_sun_awt_windows_WComponentPeer_pSetParent(JNIEnv* env, jobject self, jobject parent) { TRY; @@ -6883,6 +6855,21 @@ Java_sun_awt_windows_WComponentPeer_setRectangularShape(JNIEnv* env, jobject sel CATCH_BAD_ALLOC; } +JNIEXPORT void JNICALL +Java_sun_awt_windows_WComponentPeer_setZOrder(JNIEnv* env, jobject self, jlong above) +{ + TRY; + + SetZOrderStruct * data = new SetZOrderStruct; + data->component = env->NewGlobalRef(self); + data->above = above; + + AwtToolkit::GetInstance().SyncCall(AwtComponent::_SetZOrder, data); + // global refs and data are deleted in _SetLower + + CATCH_BAD_ALLOC; +} + } /* extern "C" */ diff --git a/src/windows/native/sun/windows/awt_Component.h b/src/windows/native/sun/windows/awt_Component.h index 0c18961ed..8eec52be8 100644 --- a/src/windows/native/sun/windows/awt_Component.h +++ b/src/windows/native/sun/windows/awt_Component.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -78,8 +78,6 @@ class AwtPopupMenu; class AwtDropTarget; -struct WmComponentSetFocusData; - /* * Message routing codes */ @@ -139,12 +137,13 @@ public: virtual void RegisterClass(); virtual void UnregisterClass(); - void CreateHWnd(JNIEnv *env, LPCWSTR title, + virtual void CreateHWnd(JNIEnv *env, LPCWSTR title, DWORD windowStyle, DWORD windowExStyle, int x, int y, int w, int h, HWND hWndParent, HMENU hMenu, COLORREF colorForeground, COLORREF colorBackground, jobject peer); + virtual void DestroyHWnd(); void InitPeerGraphicsConfig(JNIEnv *env, jobject peer); virtual void Dispose(); @@ -221,17 +220,10 @@ public: virtual BOOL IsContainer() { return FALSE;} // Plain components can't /** - * Perform some actions which by default are being performed by Default Window procedure of - * this window class - * For detailed comments see implementation in awt_Component.cpp - */ - virtual BOOL ActMouseMessage(MSG * pMsg); - /** - * Returns TRUE if this message will this component to become focused. Returns FALSE otherwise. + * Returns TRUE if this message will trigger native focus change, FALSE otherwise. */ - inline BOOL IsFocusingMessage(UINT message) { - return message == WM_LBUTTONDOWN || message == WM_LBUTTONUP || message == WM_LBUTTONDBLCLK; - } + virtual BOOL IsFocusingKeyMessage(MSG *pMsg); + virtual BOOL IsFocusingMouseMessage(MSG *pMsg); BOOL IsFocusable(); @@ -373,7 +365,7 @@ public: } void SendKeyEventToFocusOwner(jint id, jlong when, jint raw, jint cooked, - jint modifiers, jint keyLocation, + jint modifiers, jint keyLocation, jlong nativeCode, MSG *msg = NULL); /* * Allocate and initialize a new java.awt.event.KeyEvent, and @@ -381,7 +373,7 @@ public: * from the target. */ void SendKeyEvent(jint id, jlong when, jint raw, jint cooked, - jint modifiers, jint keyLocation, + jint modifiers, jint keyLocation, jlong nativeCode, MSG *msg = NULL); /* @@ -431,13 +423,6 @@ public: */ virtual BOOL InheritsNativeMouseWheelBehavior(); - /* Functions for MouseWheel support on Windows95 - * These should only be called if running on 95 - */ - static void Wheel95Init(); - INLINE static UINT Wheel95GetMsg() {return sm_95WheelMessage;} - static UINT Wheel95GetScrLines(); - /* Determines whether the component is obscured by another window */ // Called on Toolkit thread static jboolean _IsObscured(void *param); @@ -457,6 +442,7 @@ public: static UINT GetButtonMK(int mouseButton); static UINT WindowsKeyToJavaKey(UINT windowsKey, UINT modifiers); static void JavaKeyToWindowsKey(UINT javaKey, UINT *windowsKey, UINT *modifiers, UINT originalWindowsKey); + static void UpdateDynPrimaryKeymap(UINT wkey, UINT jkeyLegacy, jint keyLocation, UINT modifiers); INLINE static void AwtComponent::JavaKeyToWindowsKey(UINT javaKey, UINT *windowsKey, UINT *modifiers) @@ -480,6 +466,12 @@ public: HIMC ImmGetContext(); HIMC ImmAssociateContext(HIMC himc); HWND GetProxyFocusOwner(); + + INLINE HWND GetProxyToplevelContainer() { + HWND proxyHWnd = GetProxyFocusOwner(); + return ::GetAncestor(proxyHWnd, GA_ROOT); // a browser in case of EmbeddedFrame + } + void CallProxyDefWindowProc(UINT message, WPARAM wParam, LPARAM lParam, @@ -517,11 +509,6 @@ public: virtual MsgRouting WmShowWindow(BOOL show, UINT status); virtual MsgRouting WmSetFocus(HWND hWndLost); virtual MsgRouting WmKillFocus(HWND hWndGot); - jboolean WmComponentSetFocus(WmComponentSetFocusData *data); - // Use instead of ::SetFocus to maintain special focusing semantics for - // Windows which are not Frames/Dialogs. - BOOL AwtSetFocus(); - virtual MsgRouting WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush); virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar); @@ -611,10 +598,6 @@ public: jintArray CreatePrintedPixels(SIZE &loc, SIZE &size); - static void * GetNativeFocusOwner(); - static void * GetNativeFocusedWindow(); - static void ClearGlobalFocusOwner(); - /* * HWND, AwtComponent and Java Peer interaction * @@ -673,7 +656,6 @@ public: static void _SetForeground(void *param); static void _SetBackground(void *param); static void _SetFont(void *param); - static jboolean _RequestFocus(void *param); static void _Start(void *param); static void _BeginValidate(void *param); static void _EndValidate(void *param); @@ -683,10 +665,40 @@ public: static jintArray _CreatePrintedPixels(void *param); static jboolean _NativeHandlesWheelScrolling(void *param); static void _SetRectangularShape(void *param); + static void _SetZOrder(void *param); static HWND sm_focusOwner; + +private: static HWND sm_focusedWindow; +public: + static inline HWND GetFocusedWindow() { return sm_focusedWindow; } + static void SetFocusedWindow(HWND window); + + static void _SetFocus(void *param); + + static void *SetNativeFocusOwner(void *self); + static void *GetNativeFocusedWindow(); + static void *GetNativeFocusOwner(); + + static BOOL sm_inSynthesizeFocus; + + // Execute on Toolkit only. + INLINE static LRESULT SynthesizeWmSetFocus(HWND targetHWnd, HWND oppositeHWnd) { + sm_inSynthesizeFocus = TRUE; + LRESULT res = ::SendMessage(targetHWnd, WM_SETFOCUS, (WPARAM)oppositeHWnd, 0); + sm_inSynthesizeFocus = FALSE; + return res; + } + // Execute on Toolkit only. + INLINE static LRESULT SynthesizeWmKillFocus(HWND targetHWnd, HWND oppositeHWnd) { + sm_inSynthesizeFocus = TRUE; + LRESULT res = ::SendMessage(targetHWnd, WM_KILLFOCUS, (WPARAM)oppositeHWnd, 0); + sm_inSynthesizeFocus = FALSE; + return res; + } + static BOOL sm_bMenuLoop; static INLINE BOOL isMenuLoopActive() { return sm_bMenuLoop; @@ -710,14 +722,25 @@ protected: BOOL m_visible; /* copy of Component.visible */ static BOOL sm_suppressFocusAndActivation; - static HWND sm_realFocusOpposite; + static BOOL sm_restoreFocusAndActivation; + + /* + * The function sets the focus-restore flag ON/OFF. + * When the flag is ON, focus is restored immidiately after the proxy loses it. + * All focus messages are suppressed. It's also assumed that sm_focusedWindow and + * sm_focusOwner don't change after the flag is set ON and before it's set OFF. + */ + static INLINE void SetRestoreFocus(BOOL doSet) { + sm_suppressFocusAndActivation = doSet; + sm_restoreFocusAndActivation = doSet; + } virtual void SetDragCapture(UINT flags); virtual void ReleaseDragCapture(UINT flags); - // 95 support for mouse wheel - static UINT sm_95WheelMessage; - static UINT sm_95WheelSupport; + //These functions are overridden in AwtWindow to handle non-opaque windows. + virtual void FillBackground(HDC hMemoryDC, SIZE &size); + virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha); private: /* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON @@ -761,6 +784,8 @@ private: static BOOL sm_rtl; static BOOL sm_rtlReadingOrder; + static BOOL sm_PrimaryDynamicTableBuilt; + jobject m_InputMethod; BOOL m_useNativeCompWindow; LPARAM m_bitsCandType; @@ -780,8 +805,6 @@ private: static BOOL m_QueryNewPaletteCalled; - BOOL m_skipNextSetFocus; - static AwtComponent* sm_getComponentCache; // a cache for the GetComponent(..) method. int windowMoveLockPosX; @@ -790,7 +813,7 @@ private: int windowMoveLockPosCY; // 6524352: support finer-resolution - static int sm_wheelRotationAmount; + int m_wheelRotationAmount; /* * The association list of children's IDs and corresponding components. @@ -826,6 +849,7 @@ private: AwtComponent* SearchChild(UINT id); void RemoveChild(UINT id) ; static BOOL IsNavigationKey(UINT wkey); + static void BuildPrimaryDynamicTable(); ChildListItem* m_childList; @@ -876,14 +900,6 @@ public: void RealizePalettes(int screen); }; -struct WmComponentSetFocusData { - jobject lightweightChild; - jboolean temporary; - jboolean focusedWindowChangeAllowed; - jlong time; - jobject cause; -}; - void ReleaseDCList(HWND hwnd, DCList &list); void MoveDCToPassiveList(HDC hDC); diff --git a/src/windows/native/sun/windows/awt_Dialog.cpp b/src/windows/native/sun/windows/awt_Dialog.cpp index ecf74549d..147bcf711 100644 --- a/src/windows/native/sun/windows/awt_Dialog.cpp +++ b/src/windows/native/sun/windows/awt_Dialog.cpp @@ -230,25 +230,8 @@ LRESULT CALLBACK AwtDialog::ModalFilterProc(int code, if (::IsIconic(hWnd)) { ::ShowWindow(hWnd, SW_RESTORE); } - HWND topMostBlocker = blocker; - HWND toolkitHWnd = AwtToolkit::GetInstance().GetHWnd(); - while (::IsWindow(blocker)) { - topMostBlocker = blocker; - // fix for 6494032: restore the blocker if it was minimized - // together with its parent frame; in such cases the check - // ::IsIconic() for the blocker returns false, so we use - // ::IsWindowVisible() instead - if (!::IsWindowVisible(topMostBlocker) && - (topMostBlocker != toolkitHWnd)) - { - ::ShowWindow(topMostBlocker, SW_SHOWNA); - } - ::BringWindowToTop(blocker); - blocker = AwtWindow::GetModalBlocker(blocker); - } - if (topMostBlocker != toolkitHWnd) { - ::SetForegroundWindow(topMostBlocker); - } + PopupAllDialogs(blocker, TRUE, ::GetForegroundWindow(), FALSE); + // return 1 to prevent the system from allowing the operation return 1; } return CallNextHookEx(0, code, wParam, lParam); @@ -271,30 +254,11 @@ LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode, (wParam == WM_NCRBUTTONDOWN)) { HWND blocker = AwtWindow::GetModalBlocker(AwtComponent::GetTopLevelParentForWindow(hWnd)); - HWND topMostBlocker = blocker; - HWND prevForegroundWindow = ::GetForegroundWindow(); if (::IsWindow(blocker)) { - ::BringWindowToTop(hWnd); - } - while (::IsWindow(blocker)) { - topMostBlocker = blocker; - ::BringWindowToTop(blocker); - blocker = AwtWindow::GetModalBlocker(blocker); - } - if (::IsWindow(topMostBlocker)) { - // no beep/flash if the mouse was clicked in the taskbar menu - // or the dialog is currently inactive - if ((::WindowFromPoint(mhs->pt) == hWnd) && - (prevForegroundWindow == topMostBlocker)) - { - ::MessageBeep(MB_OK); - // some heuristics: 3 times x 64 milliseconds - AwtWindow::FlashWindowEx(topMostBlocker, 3, 64, FLASHW_CAPTION); - } - if (topMostBlocker != AwtToolkit::GetInstance().GetHWnd()) { - ::BringWindowToTop(topMostBlocker); - ::SetForegroundWindow(topMostBlocker); - } + BOOL onTaskbar = !(::WindowFromPoint(mhs->pt) == hWnd); + PopupAllDialogs(hWnd, FALSE, ::GetForegroundWindow(), onTaskbar); + // return a nonzero value to prevent the system from passing + // the message to the target window procedure return 1; } } @@ -303,6 +267,63 @@ LRESULT CALLBACK AwtDialog::MouseHookProc(int nCode, return CallNextHookEx(0, nCode, wParam, lParam); } +/* + * The function goes through the heirarchy of the blocker dialogs and + * popups all the dialogs. Note that the function starts from the top + * blocker dialog and goes down to the dialog which is the bottom dialog. + * Using another traversal may cause to the flickering issue as a bottom + * dialog will cover a top dialog for some period of time. + */ +void AwtDialog::PopupAllDialogs(HWND dialog, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar) +{ + HWND blocker = AwtWindow::GetModalBlocker(dialog); + BOOL isBlocked = ::IsWindow(blocker); + if (isBlocked) { + PopupAllDialogs(blocker, isModalHook, prevFGWindow, onTaskbar); + } + PopupOneDialog(dialog, blocker, isModalHook, prevFGWindow, onTaskbar); +} + +/* + * The function popups the dialog, it distinguishes non-blocked dialogs + * and activates the dialogs (sets as foreground window). If the dialog is + * blocked, then it changes the Z-order of the dialog. + */ +void AwtDialog::PopupOneDialog(HWND dialog, HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar) +{ + if (dialog == AwtToolkit::GetInstance().GetHWnd()) { + return; + } + + // fix for 6494032 + if (isModalHook && !::IsWindowVisible(dialog)) { + ::ShowWindow(dialog, SW_SHOWNA); + } + + BOOL isBlocked = ::IsWindow(blocker); + UINT flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; + + if (isBlocked) { + ::SetWindowPos(dialog, blocker, 0, 0, 0, 0, flags); + } else { + ::SetWindowPos(dialog, HWND_TOP, 0, 0, 0, 0, flags); + // no beep/flash if the mouse was clicked in the taskbar menu + // or the dialog is currently inactive + if (!isModalHook && !onTaskbar && (dialog == prevFGWindow)) { + AnimateModalBlocker(dialog); + } + ::BringWindowToTop(dialog); + ::SetForegroundWindow(dialog); + } +} + +void AwtDialog::AnimateModalBlocker(HWND window) +{ + ::MessageBeep(MB_OK); + // some heuristics: 3 times x 64 milliseconds + AwtWindow::FlashWindowEx(window, 3, 64, FLASHW_CAPTION); +} + LRESULT CALLBACK AwtDialog::MouseHookProc_NonTT(int nCode, WPARAM wParam, LPARAM lParam) { diff --git a/src/windows/native/sun/windows/awt_Dialog.h b/src/windows/native/sun/windows/awt_Dialog.h index 41ab6ad05..a697a8c9b 100644 --- a/src/windows/native/sun/windows/awt_Dialog.h +++ b/src/windows/native/sun/windows/awt_Dialog.h @@ -76,7 +76,7 @@ public: * Thus we don't have to perform any transitive (a blocker of a blocker) checks. */ INLINE virtual BOOL IsFocusedWindowModalBlocker() { - return (sm_focusedWindow != NULL) && (GetModalBlocker(sm_focusedWindow) == GetHWnd()); + return (AwtComponent::GetFocusedWindow() != NULL) && (GetModalBlocker(AwtComponent::GetFocusedWindow()) == GetHWnd()); } // finds and activates some window after the modal dialog is hidden @@ -113,6 +113,9 @@ private: */ static void ModalPerformActivation(HWND hWnd); + static void PopupAllDialogs(HWND dialog, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar); + static void PopupOneDialog(HWND dialog, HWND blocker, BOOL isModalHook, HWND prevFGWindow, BOOL onTaskbar); + public: // WH_CBT hook procedure used in modality, prevents modal @@ -129,6 +132,8 @@ public: // example on browser's thread when running in Java Plugin static LRESULT CALLBACK MouseHookProc_NonTT(int code, WPARAM wParam, LPARAM lParam); + + static void AnimateModalBlocker(HWND window); }; #endif /* AWT_DIALOG_H */ diff --git a/src/windows/native/sun/windows/awt_FileDialog.cpp b/src/windows/native/sun/windows/awt_FileDialog.cpp index 84339e40e..080e8d427 100644 --- a/src/windows/native/sun/windows/awt_FileDialog.cpp +++ b/src/windows/native/sun/windows/awt_FileDialog.cpp @@ -101,7 +101,8 @@ LRESULT CALLBACK FileDialogWndProc(HWND hWnd, UINT message, } } - return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam); + WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp)); + return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam); } static UINT_PTR CALLBACK @@ -135,16 +136,19 @@ FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) } // subclass dialog's parent to receive additional messages - ComCtl32Util::GetInstance().SubclassHWND(parent, - FileDialogWndProc); + WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(parent, + FileDialogWndProc); + ::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc)); break; } case WM_DESTROY: { + WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(parent, NativeDialogWndProcProp)); ComCtl32Util::GetInstance().UnsubclassHWND(parent, FileDialogWndProc, - NULL); + lpfnWndProc); ::RemoveProp(parent, ModalDialogPeerProp); + ::RemoveProp(parent, NativeDialogWndProcProp); break; } case WM_NOTIFY: { diff --git a/src/windows/native/sun/windows/awt_Frame.cpp b/src/windows/native/sun/windows/awt_Frame.cpp index 60738e693..50f41d102 100644 --- a/src/windows/native/sun/windows/awt_Frame.cpp +++ b/src/windows/native/sun/windows/awt_Frame.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -39,8 +39,6 @@ #include <sun_awt_windows_WEmbeddedFramePeer.h> -BOOL isAppActive = FALSE; - /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. */ @@ -90,8 +88,10 @@ struct BlockedThreadStruct { */ jfieldID AwtFrame::handleID; -jfieldID AwtFrame::stateID; + jfieldID AwtFrame::undecoratedID; +jmethodID AwtFrame::getExtendedStateMID; +jmethodID AwtFrame::setExtendedStateMID; jmethodID AwtFrame::activateEmbeddingTopLevelMID; @@ -110,6 +110,7 @@ AwtFrame::AwtFrame() { m_isInputMethodWindow = FALSE; m_isUndecorated = FALSE; m_proxyFocusOwner = NULL; + m_lastProxiedFocusOwner = NULL; m_actualFocusedWindow = NULL; m_iconic = FALSE; m_zoomed = FALSE; @@ -232,7 +233,7 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) frame->InitPeerGraphicsConfig(env, self); AwtToolkit::GetInstance().RegisterEmbedderProcessId(hwndParent); } else { - jint state = env->GetIntField(target, AwtFrame::stateID); + jint state = env->CallIntMethod(self, AwtFrame::getExtendedStateMID); DWORD exStyle; DWORD style; @@ -285,7 +286,6 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) ::GetSysColor(COLOR_WINDOWTEXT), ::GetSysColor(COLOR_WINDOWFRAME), self); - /* * Reshape here instead of during create, so that a * WM_NCCALCSIZE is sent. @@ -319,12 +319,13 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message, AwtComponent::GetComponentImpl(::GetParent(hwnd)); if (!parent || parent->GetProxyFocusOwner() != hwnd || - message == AwtComponent::WmAwtIsComponent) + message == AwtComponent::WmAwtIsComponent || + message == WM_GETOBJECT) { return ComCtl32Util::GetInstance().DefWindowProc(NULL, hwnd, message, wParam, lParam); } - AwtComponent *p = NULL; + AwtComponent *focusOwner = NULL; // IME and input language related messages need to be sent to a window // which has the Java input focus switch (message) { @@ -342,16 +343,37 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message, case WM_IME_KEYUP: case WM_INPUTLANGCHANGEREQUEST: case WM_INPUTLANGCHANGE: - p = AwtComponent::GetComponent(sm_focusOwner); - if (p != NULL) { - return p->WindowProc(message, wParam, lParam); + // TODO: when a Choice's list is dropped down and we're scrolling in + // the list WM_MOUSEWHEEL messages come to the poxy, not to the list. Why? + case WM_MOUSEWHEEL: + focusOwner = AwtComponent::GetComponent(parent->GetLastProxiedFocusOwner()); + if (focusOwner != NULL) { + return focusOwner->WindowProc(message, wParam, lParam); } break; + case WM_SETFOCUS: + if (!sm_suppressFocusAndActivation && parent->IsEmbeddedFrame()) { + parent->AwtSetActiveWindow(); + } + return 0; + case WM_KILLFOCUS: + if (!sm_suppressFocusAndActivation && parent->IsEmbeddedFrame()) { + AwtWindow::SynthesizeWmActivate(FALSE, parent->GetHWnd(), NULL); + + } else if (sm_restoreFocusAndActivation) { + if (AwtComponent::GetFocusedWindow() != NULL) { + AwtWindow *focusedWindow = (AwtWindow*)GetComponent(AwtComponent::GetFocusedWindow()); + if (focusedWindow != NULL) { + // Will just silently restore native focus & activation. + focusedWindow->AwtSetActiveWindow(); + } + } + } + return 0; case 0x0127: // WM_CHANGEUISTATE case 0x0128: // WM_UPDATEUISTATE return 0; } - return parent->WindowProc(message, wParam, lParam); CATCH_BAD_ALLOC_RET(0); @@ -554,7 +576,6 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) { if (m_grabbedWindow != NULL/* && !m_grabbedWindow->IsOneOfOwnersOf(this)*/) { m_grabbedWindow->Ungrab(); } - if (!IsFocusableWindow() && (button & LEFT_BUTTON)) { switch (hitTest) { case HTTOP: @@ -586,11 +607,6 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) { return AwtWindow::WmNcMouseDown(hitTest, x, y, button); } -MsgRouting AwtFrame::WmWindowPosChanged(LPARAM windowPos) { - return mrDoDefault; -} - - // Override AwtWindow::Reshape() to handle minimized/maximized // frames (see 6525850, 4065534) void AwtFrame::Reshape(int x, int y, int width, int height) @@ -827,6 +843,11 @@ MsgRouting AwtFrame::WmGetMinMaxInfo(LPMINMAXINFO lpmmi) MsgRouting AwtFrame::WmSize(UINT type, int w, int h) { + currentWmSizeState = type; + if (currentWmSizeState == SIZE_MINIMIZED) { + UpdateSecurityWarningVisibility(); + } + if (m_ignoreWmSize) { return mrDoDefault; } @@ -883,6 +904,11 @@ MsgRouting AwtFrame::WmSize(UINT type, int w, int h) if (changed != 0) { DTRACE_PRINTLN2("AwtFrame::WmSize: reporting state change %x -> %x", oldState, newState); + + // sync target with peer + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + env->CallVoidMethod(GetPeer(env), AwtFrame::setExtendedStateMID, newState); + // report (de)iconification to old clients if (changed & java_awt_Frame_ICONIFIED) { if (newState & java_awt_Frame_ICONIFIED) { @@ -907,33 +933,16 @@ MsgRouting AwtFrame::WmSize(UINT type, int w, int h) MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) { jint type; - BOOL doActivateFrame = TRUE; if (nState != WA_INACTIVE) { - if (!::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) { - ::SetFocus(NULL); // The KeyboardFocusManager will set focus later - type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; - isAppActive = TRUE; - sm_focusedWindow = GetHWnd(); - - /* - * Fix for 4823903. - * If the window to be focused is actually not this Frame - * and it's visible then send it WM_ACTIVATE. - */ - if (m_actualFocusedWindow != NULL) { - HWND hwnd = m_actualFocusedWindow->GetHWnd(); - - if (hwnd != NULL && ::IsWindowVisible(hwnd)) { - - ::SendMessage(hwnd, WM_ACTIVATE, MAKEWPARAM(nState, fMinimized), (LPARAM)opposite); - doActivateFrame = FALSE; - } - m_actualFocusedWindow = NULL; - } - } else { - doActivateFrame = FALSE; + if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd())) || + CheckActivateActualFocusedWindow(opposite)) + { + return mrConsume; } + type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; + AwtComponent::SetFocusedWindow(GetHWnd()); + } else { if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) { // If deactivation happens because of press on grabbing @@ -955,37 +964,63 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) } } } + CheckRetainActualFocusedWindow(opposite); - // If actual focused window is not this Frame - if (sm_focusedWindow != GetHWnd()) { + type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; + AwtComponent::SetFocusedWindow(NULL); + sm_focusOwner = NULL; + } + } - // Check that the Frame is going to be really inactive (i.e. the opposite is not its owned window) - if (opposite != NULL) { - AwtWindow *wOpposite = (AwtWindow *)AwtComponent::GetComponent(opposite); + SendWindowEvent(type, opposite); + return mrConsume; +} - if (wOpposite != NULL && - wOpposite->GetOwningFrameOrDialog() != this) - { - AwtWindow *window = (AwtWindow *)AwtComponent::GetComponent(sm_focusedWindow); +BOOL AwtFrame::CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd) +{ + if (m_actualFocusedWindow != NULL) { + HWND hwnd = m_actualFocusedWindow->GetHWnd(); + if (hwnd != NULL && ::IsWindowVisible(hwnd)) { + SynthesizeWmActivate(TRUE, hwnd, deactivatedOpositeHWnd); + return TRUE; + } + m_actualFocusedWindow = NULL; + } + return FALSE; +} - // If actual focused window is one of Frame's owned windows - if (window != NULL && window->GetOwningFrameOrDialog() == this) { - m_actualFocusedWindow = window; - } - } +void AwtFrame::CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd) +{ + // If actual focused window is not this Frame + if (AwtComponent::GetFocusedWindow() != GetHWnd()) { + // Make sure the actual focused window is an owned window of this frame + AwtWindow *focusedWindow = (AwtWindow *)AwtComponent::GetComponent(AwtComponent::GetFocusedWindow()); + if (focusedWindow != NULL && focusedWindow->GetOwningFrameOrDialog() == this) { + + // Check that the opposite window is not this frame, nor an owned window of this frame + if (activatedOpositeHWnd != NULL) { + AwtWindow *oppositeWindow = (AwtWindow *)AwtComponent::GetComponent(activatedOpositeHWnd); + if (oppositeWindow && oppositeWindow != this && + oppositeWindow->GetOwningFrameOrDialog() != this) + { + m_actualFocusedWindow = focusedWindow; } + } else { + m_actualFocusedWindow = focusedWindow; } - - type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; - isAppActive = FALSE; - sm_focusedWindow = NULL; } } +} - if (doActivateFrame) { - SendWindowEvent(type, opposite); +BOOL AwtFrame::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest) +{ + if (hittest == HTCLIENT) { + // Don't let the actualFocusedWindow to steal focus if: + // a) the frame is clicked in its client area; + // b) focus is requested to some of the frame's child. + m_actualFocusedWindow = NULL; } - return mrConsume; + return AwtWindow::AwtSetActiveWindow(isMouseEventCause); } MsgRouting AwtFrame::WmEnterMenuLoop(BOOL isTrackPopupMenu) @@ -1161,60 +1196,6 @@ LRESULT AwtFrame::WinThreadExecProc(ExecuteArgs * args) return 0L; } -/* - * hWndLostFocus - the opposite component - * Returns TRUE if WM_SETFOCUS may be processed further, otherwise FALSE. - */ -BOOL AwtFrame::activateEmbeddedFrameOnSetFocus(HWND hWndLostFocus) { - - // If the EmbeddedFrame is not yet active, then this is either: - // - requesting focus on smth in the EmbeddedFrame, or - // - Alt hitting in IE while its menu is active (see 6374321). - // In both these cases we get WM_SETFOCUS without WM_ACTIVATE - // on the EmbeddedFrame. - if (sm_focusedWindow != GetHWnd()) { - HWND oppositeToplevelHWnd = AwtComponent::GetTopLevelParentForWindow(hWndLostFocus); - - // As we get WM_SETFOCUS from the native system we expect - // the native toplevel be set to the active window. - HWND activeWindowHWnd = ::GetActiveWindow(); - DASSERT(activeWindowHWnd == ::GetAncestor(GetHWnd(), GA_ROOT)); - - // See 6538154. - ::BringWindowToTop(activeWindowHWnd); - ::SetForegroundWindow(activeWindowHWnd); - - SynthesizeWmActivate(TRUE, oppositeToplevelHWnd); - - return FALSE; - } - // If the EmbeddedFrame is already active, then this is a mouse click - // or activation (by Alt-Tab, start etc). - return TRUE; -} - -/* - * hWndGotFocus - the opposite component - * Returns TRUE if WM_KILLFOCUS may be processed further, otherwise FALSE. - */ -BOOL AwtFrame::deactivateEmbeddedFrameOnKillFocus(HWND hWndGotFocus) { - HWND oppositeToplevelHWnd = AwtComponent::GetTopLevelParentForWindow(hWndGotFocus); - - if (oppositeToplevelHWnd != sm_focusedWindow) { - SynthesizeWmActivate(FALSE, oppositeToplevelHWnd); - } - return TRUE; -} - -/* - * Execute on Toolkit only. - */ -void AwtFrame::SynthesizeWmActivate(BOOL doActivate, HWND opposite) { - if (::IsWindowVisible(GetHWnd())) { - ::SendMessage(GetHWnd(), WM_ACTIVATE, MAKEWPARAM(doActivate ? WA_ACTIVE : WA_INACTIVE, FALSE), (LPARAM) opposite); - } -} - void AwtFrame::_SynthesizeWmActivate(void *param) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -1229,7 +1210,7 @@ void AwtFrame::_SynthesizeWmActivate(void *param) JNI_CHECK_PEER_GOTO(self, ret); frame = (AwtFrame *)pData; - frame->SynthesizeWmActivate(doActivate, NULL); + SynthesizeWmActivate(doActivate, frame->GetHWnd(), NULL); ret: env->DeleteGlobalRef(self); @@ -1594,7 +1575,7 @@ void AwtFrame::_NotifyModalBlocked(void *param) extern "C" { /* - * Class: sun_awt_windows_WFramePeer + * Class: java_awt_Frame * Method: initIDs * Signature: ()V */ @@ -1603,9 +1584,6 @@ Java_java_awt_Frame_initIDs(JNIEnv *env, jclass cls) { TRY; - AwtFrame::stateID = env->GetFieldID(cls, "state", "I"); - DASSERT(AwtFrame::stateID != NULL); - AwtFrame::undecoratedID = env->GetFieldID(cls,"undecorated","Z"); DASSERT(AwtFrame::undecoratedID != NULL); @@ -1614,6 +1592,25 @@ Java_java_awt_Frame_initIDs(JNIEnv *env, jclass cls) /* * Class: sun_awt_windows_WFramePeer + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WFramePeer_initIDs(JNIEnv *env, jclass cls) +{ + TRY; + + AwtFrame::setExtendedStateMID = env->GetMethodID(cls, "setExtendedState", "(I)V"); + AwtFrame::getExtendedStateMID = env->GetMethodID(cls, "getExtendedState", "()I"); + + DASSERT(AwtFrame::setExtendedStateMID); + DASSERT(AwtFrame::getExtendedStateMID); + + CATCH_BAD_ALLOC; +} + +/* + * Class: sun_awt_windows_WFramePeer * Method: setState * Signature: (I)V */ diff --git a/src/windows/native/sun/windows/awt_Frame.h b/src/windows/native/sun/windows/awt_Frame.h index 3634f9592..a5821329e 100644 --- a/src/windows/native/sun/windows/awt_Frame.h +++ b/src/windows/native/sun/windows/awt_Frame.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -48,14 +48,14 @@ public: FRAME_SETMENUBAR }; - /* int handle field for sun.awt.windows.WEmbeddedFrame */ + /* java.awt.Frame fields and method IDs */ + static jfieldID undecoratedID; + + /* sun.awt.windows.WEmbeddedFrame fields and method IDs */ static jfieldID handleID; - /* int state field for java.awt.Frame */ - static jfieldID stateID; - - /* boolean undecorated field for java.awt.Frame */ - static jfieldID undecoratedID; + static jmethodID setExtendedStateMID; + static jmethodID getExtendedStateMID; /* method id for WEmbeddedFrame.requestActivate() method */ static jmethodID activateEmbeddingTopLevelMID; @@ -108,7 +108,6 @@ public: MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button); MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button); MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal); - MsgRouting WmWindowPosChanged(LPARAM windowPos); MsgRouting WmShowWindow(BOOL show, UINT status); virtual MsgRouting WmSysCommand(UINT uCmdType, int xPos, int yPos); @@ -133,11 +132,6 @@ public: // adjusts the IME candidate window position if needed void AdjustCandidateWindowPos(); - void SynthesizeWmActivate(BOOL doActivate, HWND opposite); - - BOOL activateEmbeddedFrameOnSetFocus(HWND hWndLostFocus); - BOOL deactivateEmbeddedFrameOnKillFocus(HWND hWndGotFocus); - // invoked on Toolkit thread static jobject _GetBoundsPrivate(void *param); @@ -153,6 +147,14 @@ public: virtual void Reshape(int x, int y, int width, int height); + virtual BOOL AwtSetActiveWindow(BOOL isMouseEventCause = FALSE, UINT hittest = HTCLIENT); + + void CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd); + BOOL CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd); + + INLINE HWND GetLastProxiedFocusOwner() { return m_lastProxiedFocusOwner; } + INLINE void SetLastProxiedFocusOwner(HWND hwnd) { m_lastProxiedFocusOwner = hwnd; } + protected: /* The frame is undecorated. */ BOOL m_isUndecorated; @@ -189,6 +191,10 @@ private: or an AwtDialog (or one of its children) has the logical input focus. */ HWND m_proxyFocusOwner; + /* Retains the last/current sm_focusOwner proxied. Actually, it should be + * a component of an owned window last/currently active. */ + HWND m_lastProxiedFocusOwner; + /* * Fix for 4823903. * Retains a focus proxied window to set the focus correctly diff --git a/src/windows/native/sun/windows/awt_InputMethod.cpp b/src/windows/native/sun/windows/awt_InputMethod.cpp index bd78cdaf3..f23e1e1f6 100644 --- a/src/windows/native/sun/windows/awt_InputMethod.cpp +++ b/src/windows/native/sun/windows/awt_InputMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-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 @@ -176,7 +176,7 @@ Java_sun_awt_windows_WInputMethod_handleNativeIMEEvent(JNIEnv *env, jobject self java_awt_event_KeyEvent_CHAR_UNDEFINED, unicodeChar, modifiers, - java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, + java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0, &msg); } else { MSG* pCopiedMsg = new MSG; diff --git a/src/windows/native/sun/windows/awt_KeyEvent.cpp b/src/windows/native/sun/windows/awt_KeyEvent.cpp index cc795cfc8..0559741d4 100644 --- a/src/windows/native/sun/windows/awt_KeyEvent.cpp +++ b/src/windows/native/sun/windows/awt_KeyEvent.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-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 @@ -32,6 +32,10 @@ jfieldID AwtKeyEvent::keyCodeID; jfieldID AwtKeyEvent::keyCharID; +jfieldID AwtKeyEvent::rawCodeID; +jfieldID AwtKeyEvent::primaryLevelUnicodeID; +jfieldID AwtKeyEvent::scancodeID; +jfieldID AwtKeyEvent::extendedKeyCodeID; /************************************************************************ * AwtKeyEvent native methods @@ -45,9 +49,18 @@ Java_java_awt_event_KeyEvent_initIDs(JNIEnv *env, jclass cls) { AwtKeyEvent::keyCodeID = env->GetFieldID(cls, "keyCode", "I"); AwtKeyEvent::keyCharID = env->GetFieldID(cls, "keyChar", "C"); + AwtKeyEvent::rawCodeID = env->GetFieldID(cls, "rawCode", "J"); + AwtKeyEvent::primaryLevelUnicodeID = env->GetFieldID(cls, "primaryLevelUnicode", "J"); + AwtKeyEvent::scancodeID = env->GetFieldID(cls, "scancode", "J"); + AwtKeyEvent::extendedKeyCodeID = env->GetFieldID(cls, "extendedKeyCode", "J"); + DASSERT(AwtKeyEvent::keyCodeID != NULL); DASSERT(AwtKeyEvent::keyCharID != NULL); + DASSERT(AwtKeyEvent::rawCodeID != NULL); + DASSERT(AwtKeyEvent::primaryLevelUnicodeID != NULL); + DASSERT(AwtKeyEvent::scancodeID != NULL); + DASSERT(AwtKeyEvent::extendedKeyCodeID != NULL); CATCH_BAD_ALLOC; } diff --git a/src/windows/native/sun/windows/awt_KeyEvent.h b/src/windows/native/sun/windows/awt_KeyEvent.h index 2489051ea..0e47eacec 100644 --- a/src/windows/native/sun/windows/awt_KeyEvent.h +++ b/src/windows/native/sun/windows/awt_KeyEvent.h @@ -39,7 +39,10 @@ public: /* java.awt.KeyEvent field ids */ static jfieldID keyCodeID; static jfieldID keyCharID; - + static jfieldID rawCodeID; + static jfieldID primaryLevelUnicodeID; + static jfieldID scancodeID; + static jfieldID extendedKeyCodeID; }; #endif // AWT_KEYEVENT_H diff --git a/src/windows/native/sun/windows/awt_KeyboardFocusManager.cpp b/src/windows/native/sun/windows/awt_KeyboardFocusManager.cpp index 907f0a303..146dd0398 100644 --- a/src/windows/native/sun/windows/awt_KeyboardFocusManager.cpp +++ b/src/windows/native/sun/windows/awt_KeyboardFocusManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-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 @@ -24,30 +24,20 @@ */ #include "awt.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Component.h" #include "awt_Toolkit.h" #include <java_awt_KeyboardFocusManager.h> - -jclass AwtKeyboardFocusManager::keyboardFocusManagerCls; -jmethodID AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID; -jmethodID AwtKeyboardFocusManager::heavyweightButtonDownMID; -jmethodID AwtKeyboardFocusManager::markClearGlobalFocusOwnerMID; -jmethodID AwtKeyboardFocusManager::removeLastFocusRequestMID; -jfieldID AwtKeyboardFocusManager::isProxyActive; -jmethodID AwtKeyboardFocusManager::processSynchronousTransfer; +#include <jni.h> static jobject getNativeFocusState(JNIEnv *env, void*(*ftn)()) { - jobject lFocusState = NULL; + jobject gFocusState = (jobject)AwtToolkit::GetInstance().SyncCall(ftn); - jobject gFocusState = reinterpret_cast<jobject>(AwtToolkit::GetInstance(). - InvokeFunction(ftn)); if (gFocusState != NULL) { - lFocusState = env->NewLocalRef(gFocusState); + jobject lFocusState = env->NewLocalRef(gFocusState); env->DeleteGlobalRef(gFocusState); + return lFocusState; } - - return lFocusState; + return NULL; } extern "C" { @@ -61,53 +51,35 @@ JNIEXPORT void JNICALL Java_java_awt_KeyboardFocusManager_initIDs (JNIEnv *env, jclass cls) { - TRY; - - AwtKeyboardFocusManager::keyboardFocusManagerCls = (jclass) - env->NewGlobalRef(cls); - AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID = - env->GetStaticMethodID(cls, "shouldNativelyFocusHeavyweight", - "(Ljava/awt/Component;Ljava/awt/Component;ZZJLsun/awt/CausedFocusEvent$Cause;)I"); - AwtKeyboardFocusManager::heavyweightButtonDownMID = - env->GetStaticMethodID(cls, "heavyweightButtonDown", - "(Ljava/awt/Component;J)V"); - AwtKeyboardFocusManager::markClearGlobalFocusOwnerMID = - env->GetStaticMethodID(cls, "markClearGlobalFocusOwner", - "()Ljava/awt/Window;"); - AwtKeyboardFocusManager::removeLastFocusRequestMID = - env->GetStaticMethodID(cls, "removeLastFocusRequest", - "(Ljava/awt/Component;)V"); - - AwtKeyboardFocusManager::processSynchronousTransfer = - env->GetStaticMethodID(cls, "processSynchronousLightweightTransfer", - "(Ljava/awt/Component;Ljava/awt/Component;ZZJ)Z"); +} - jclass keyclass = env->FindClass("java/awt/event/KeyEvent"); - DASSERT (keyclass != NULL); +/* + * Class: sun_awt_windows_WKeyboardFocusManagerPeer + * Method: setNativeFocusOwner + * Signature: (Lsun/awt/windows/WComponentPeer) + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WKeyboardFocusManagerPeer_setNativeFocusOwner + (JNIEnv *env, jclass cls, jobject compPeer) +{ + TRY; - AwtKeyboardFocusManager::isProxyActive = - env->GetFieldID(keyclass, "isProxyActive", "Z"); + jobject peerGlobalRef = env->NewGlobalRef(compPeer); - env->DeleteLocalRef(keyclass); + AwtToolkit::GetInstance().SyncCall(AwtComponent::SetNativeFocusOwner, + (void*)peerGlobalRef); + // peerGlobalRef is deleted in SetNativeFocusOwner - DASSERT(AwtKeyboardFocusManager::keyboardFocusManagerCls != NULL); - DASSERT(AwtKeyboardFocusManager::shouldNativelyFocusHeavyweightMID != - NULL); - DASSERT(AwtKeyboardFocusManager::heavyweightButtonDownMID != NULL); - DASSERT(AwtKeyboardFocusManager::markClearGlobalFocusOwnerMID != NULL); - DASSERT(AwtKeyboardFocusManager::removeLastFocusRequestMID != NULL); - DASSERT(AwtKeyboardFocusManager::processSynchronousTransfer != NULL); CATCH_BAD_ALLOC; } - /* - * Class: sun_awt_KeyboardFocusManagerPeerImpl + * Class: sun_awt_windows_WKeyboardFocusManagerPeer * Method: getNativeFocusOwner - * Signature: ()Ljava/awt/Component; + * Signature: (Lsun/awt/windows/WComponentPeer) */ JNIEXPORT jobject JNICALL -Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusOwner +Java_sun_awt_windows_WKeyboardFocusManagerPeer_getNativeFocusOwner (JNIEnv *env, jclass cls) { TRY; @@ -118,12 +90,12 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusOwner } /* - * Class: sun_awt_KeyboardFocusManagerPeerImpl + * Class: sun_awt_windows_WKeyboardFocusManagerPeer * Method: getNativeFocusedWindow * Signature: ()Ljava/awt/Window; */ JNIEXPORT jobject JNICALL -Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusedWindow +Java_sun_awt_windows_WKeyboardFocusManagerPeer_getNativeFocusedWindow (JNIEnv *env, jclass cls) { TRY; @@ -132,21 +104,4 @@ Java_sun_awt_KeyboardFocusManagerPeerImpl_getNativeFocusedWindow CATCH_BAD_ALLOC_RET(NULL); } - -/* - * Class: sun_awt_KeyboardFocusManagerPeerImpl - * Method: clearNativeGlobalFocusOwner - * Signature: (Ljava/awt/Window;)V - */ -JNIEXPORT void JNICALL -Java_sun_awt_KeyboardFocusManagerPeerImpl_clearNativeGlobalFocusOwner - (JNIEnv *env, jobject self, jobject activeWindow) -{ - TRY; - - AwtToolkit::GetInstance().InvokeFunction - ((void*(*)(void))AwtComponent::ClearGlobalFocusOwner); - - CATCH_BAD_ALLOC; -} } diff --git a/src/windows/native/sun/windows/awt_KeyboardFocusManager.h b/src/windows/native/sun/windows/awt_KeyboardFocusManager.h deleted file mode 100644 index 26087c21a..000000000 --- a/src/windows/native/sun/windows/awt_KeyboardFocusManager.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2001-2002 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. - */ - -#ifndef AWT_KEYBOARDFOCUSMANAGER_H -#define AWT_KEYBOARDFOCUSMANAGER_H - -#include <jni.h> - -class AwtKeyboardFocusManager { -public: - - static jclass keyboardFocusManagerCls; - static jmethodID shouldNativelyFocusHeavyweightMID; - static jmethodID heavyweightButtonDownMID; - static jmethodID markClearGlobalFocusOwnerMID; - static jmethodID removeLastFocusRequestMID; - static jfieldID isProxyActive; - static jmethodID processSynchronousTransfer; -}; - -#endif // AWT_KEYBOARDFOCUSMANAGER_H diff --git a/src/windows/native/sun/windows/awt_List.cpp b/src/windows/native/sun/windows/awt_List.cpp index 20844de78..453025ec9 100644 --- a/src/windows/native/sun/windows/awt_List.cpp +++ b/src/windows/native/sun/windows/awt_List.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -24,7 +24,6 @@ */ #include "awt_List.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" #include "awt_Dimension.h" #include "awt_Toolkit.h" @@ -154,28 +153,6 @@ done: return c; } -BOOL AwtList::ActMouseMessage(MSG * pMsg) { - if (!IsFocusingMessage(pMsg->message)) { - return FALSE; - } - - if (pMsg->message == WM_LBUTTONDOWN) { - LONG item = static_cast<LONG>(SendListMessage(LB_ITEMFROMPOINT, 0, pMsg->lParam)); - if (item != LB_ERR) { - if (isMultiSelect) { - if (IsItemSelected(item)) { - Deselect(item); - } else { - Select(item); - } - } else { - Select(item); - } - } - } - return TRUE; -} - void AwtList::SetDragCapture(UINT flags) { // don't want to interfere with other controls @@ -473,17 +450,11 @@ AwtList::WmMouseDown(UINT flags, int x, int y, int button) } /* - * Fix for 6240202. List being inside a non-focusable Window (or non-focusable List - * being a single component inside a focusable Window) won't trigger ActionEvent by - * double click. All focus events will be filtered (in the AWT focus hook) for such - * a Window containing the List. In such a case OS Windows won't generate WM_COMMAND - * (and no WmNotify() will be called for the List). Here we call WmCommand() - * synthetically. + * As we consume WM_LBUTONDOWN the list won't trigger ActionEvent by double click. + * We trigger it ourselves. (see also 6240202) */ int clickCount = GetClickCount(); - if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0 && - !GetContainer()->IsFocusableWindow()) - { + if (button == LEFT_BUTTON && clickCount >= 2 && clickCount % 2 == 0) { WmCommand(0, GetListHandle(), LBN_DBLCLK); } return mrResult; @@ -500,67 +471,32 @@ AwtList::WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush) return mrConsume; } -// Override WmSetFocus and WmKillFocus so that they operate on the List handle -// instead of the wrapper handle. Otherwise, the methods are the same as their -// AwtComponent counterparts. - -MsgRouting AwtList::WmSetFocus(HWND hWndLostFocus) { - if (sm_focusOwner == GetListHandle()) { - sm_realFocusOpposite = NULL; - return mrConsume; - } - - sm_focusOwner = GetListHandle(); - - if (sm_realFocusOpposite != NULL) { - hWndLostFocus = sm_realFocusOpposite; - sm_realFocusOpposite = NULL; - } - - SendFocusEvent(java_awt_event_FocusEvent_FOCUS_GAINED, hWndLostFocus); - - return mrDoDefault; +BOOL AwtList::IsFocusingMouseMessage(MSG *pMsg) +{ + return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK; } -MsgRouting AwtList::WmKillFocus(HWND hWndGotFocus) { - if (sm_focusOwner != NULL && sm_focusOwner == hWndGotFocus) { - return mrConsume; - } - - if (sm_focusOwner != GetListHandle()) { - if (sm_focusOwner != NULL) { - if (hWndGotFocus != NULL && - AwtComponent::GetComponent(hWndGotFocus) != NULL) - { - sm_realFocusOpposite = sm_focusOwner; +MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic) +{ + if (IsFocusingMouseMessage(msg)) { + LONG item = static_cast<LONG>(SendListMessage(LB_ITEMFROMPOINT, 0, msg->lParam)); + if (item != LB_ERR) { + if (isMultiSelect) { + if (IsItemSelected(item)) { + Deselect(item); + } else { + Select(item); } - ::SendMessage(sm_focusOwner, WM_KILLFOCUS, (WPARAM)hWndGotFocus, - 0); + } else { + Select(item); + } } + delete msg; return mrConsume; } - - sm_focusOwner = NULL; - - SendFocusEvent(java_awt_event_FocusEvent_FOCUS_LOST, hWndGotFocus); - - return mrDoDefault; -} - -MsgRouting AwtList::HandleEvent(MSG *msg, BOOL synthetic) -{ - if (AwtComponent::sm_focusOwner != GetListHandle() && - (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK)) - { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); + if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN) { + WmNotify(LBN_DBLCLK); } - return AwtComponent::HandleEvent(msg, synthetic); } @@ -607,15 +543,6 @@ AwtList::WmNotify(UINT notifyCode) return mrDoDefault; } -MsgRouting -AwtList::WmKeyDown(UINT wkey, UINT repCnt, UINT flags, BOOL system) -{ - if (wkey == VK_RETURN) { - WmNotify(LBN_DBLCLK); - } - return AwtComponent::WmKeyDown(wkey, repCnt, flags, system); -} - BOOL AwtList::InheritsNativeMouseWheelBehavior() {return true;} jint AwtList::_GetMaxWidth(void *param) diff --git a/src/windows/native/sun/windows/awt_List.h b/src/windows/native/sun/windows/awt_List.h index 832e41c2c..5389c6334 100644 --- a/src/windows/native/sun/windows/awt_List.h +++ b/src/windows/native/sun/windows/awt_List.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -97,8 +97,6 @@ public: } } - BOOL ActMouseMessage(MSG* pMsg); - // Netscape : Change the font on the list and redraw the // items nicely. virtual void SetFont(AwtFont *pFont); @@ -116,7 +114,6 @@ public: MsgRouting WmMouseDown(UINT flags, int x, int y, int button); MsgRouting WmMouseUp(UINT flags, int x, int y, int button); MsgRouting WmNotify(UINT notifyCode); - MsgRouting WmKeyDown(UINT vkey, UINT repCnt, UINT flags, BOOL system); /* for multifont list */ MsgRouting OwnerDrawItem(UINT ctrlId, DRAWITEMSTRUCT& drawInfo); @@ -127,8 +124,6 @@ public: MsgRouting WmCtlColor(HDC hDC, HWND hCtrl, UINT ctlColor, HBRUSH& retBrush); - MsgRouting WmSetFocus(HWND hWndLostFocus); - MsgRouting WmKillFocus(HWND hWndGotFocus); MsgRouting HandleEvent(MSG *msg, BOOL synthetic); @@ -170,6 +165,8 @@ public: virtual BOOL InheritsNativeMouseWheelBehavior(); + virtual BOOL IsFocusingMouseMessage(MSG *pMsg); + // some methods called on Toolkit thread static jint _GetMaxWidth(void *param); static void _UpdateMaxItemWidth(void *param); diff --git a/src/windows/native/sun/windows/awt_Panel.cpp b/src/windows/native/sun/windows/awt_Panel.cpp index 62c90bf54..5f0e42673 100644 --- a/src/windows/native/sun/windows/awt_Panel.cpp +++ b/src/windows/native/sun/windows/awt_Panel.cpp @@ -34,70 +34,6 @@ jfieldID AwtPanel::insets_ID; -static char* AWTPANEL_RESTACK_MSG_1 = "Peers array is null"; -static char* AWTPANEL_RESTACK_MSG_2 = "Peer null in JNI"; -static char* AWTPANEL_RESTACK_MSG_3 = "Native resources unavailable"; -static char* AWTPANEL_RESTACK_MSG_4 = "Child peer is null"; - -void* AwtPanel::Restack(void * param) { - TRY; - - JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobjectArray peers = (jobjectArray)param; - - int peerCount = env->GetArrayLength(peers); - if (peerCount < 1) { - env->DeleteGlobalRef(peers); - return AWTPANEL_RESTACK_MSG_1; - } - - jobject self = env->GetObjectArrayElement(peers, 0); - // It's entirely possible that our native resources have been destroyed - // before our java peer - if we're dispose()d, for instance. - // Alert caller w/ IllegalComponentStateException. - if (self == NULL) { - env->DeleteGlobalRef(peers); - return AWTPANEL_RESTACK_MSG_2; - } - PDATA pData = JNI_GET_PDATA(self); - if (pData == NULL) { - env->DeleteGlobalRef(peers); - env->DeleteLocalRef(self); - return AWTPANEL_RESTACK_MSG_3; - } - - AwtPanel* panel = (AwtPanel*)pData; - - HWND prevWindow = 0; - - for (int i = 1; i < peerCount; i++) { - jobject peer = env->GetObjectArrayElement(peers, i); - if (peer == NULL) { - // Nonsense - env->DeleteGlobalRef(peers); - env->DeleteLocalRef(self); - return AWTPANEL_RESTACK_MSG_4; - } - PDATA child_pData = JNI_GET_PDATA(peer); - if (child_pData == NULL) { - env->DeleteLocalRef(peer); - env->DeleteGlobalRef(peers); - env->DeleteLocalRef(self); - return AWTPANEL_RESTACK_MSG_3; - } - AwtComponent* child_comp = (AwtComponent*)child_pData; - ::SetWindowPos(child_comp->GetHWnd(), prevWindow, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS); - prevWindow = child_comp->GetHWnd(); - env->DeleteLocalRef(peer); - } - env->DeleteGlobalRef(peers); - env->DeleteLocalRef(self); - - CATCH_BAD_ALLOC_RET("Allocation error"); - return NULL; -} - /************************************************************************ * AwtPanel native methods */ @@ -116,18 +52,4 @@ Java_sun_awt_windows_WPanelPeer_initIDs(JNIEnv *env, jclass cls) { CATCH_BAD_ALLOC; } -JNIEXPORT void JNICALL -Java_sun_awt_windows_WPanelPeer_pRestack(JNIEnv *env, jobject self, jobjectArray peers) { - - TRY; - - const char * error = (const char*)AwtToolkit::GetInstance().InvokeFunction(AwtPanel::Restack, env->NewGlobalRef(peers)); - if (error != NULL) { - JNU_ThrowByName(env, "java/awt/IllegalComponentStateException", error); - } - - CATCH_BAD_ALLOC; -} - - } /* extern "C" */ diff --git a/src/windows/native/sun/windows/awt_Panel.h b/src/windows/native/sun/windows/awt_Panel.h index 2e9ed6649..93084c716 100644 --- a/src/windows/native/sun/windows/awt_Panel.h +++ b/src/windows/native/sun/windows/awt_Panel.h @@ -35,11 +35,8 @@ class AwtPanel { public: - static void* Restack(void * param); - /* java.awt.Panel field ids */ static jfieldID insets_ID; - }; #endif // AWT_PANEL_H diff --git a/src/windows/native/sun/windows/awt_PrintDialog.cpp b/src/windows/native/sun/windows/awt_PrintDialog.cpp index 762ae2673..14c7750cb 100644 --- a/src/windows/native/sun/windows/awt_PrintDialog.cpp +++ b/src/windows/native/sun/windows/awt_PrintDialog.cpp @@ -65,7 +65,8 @@ LRESULT CALLBACK PrintDialogWndProc(HWND hWnd, UINT message, } } - return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam); + WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp)); + return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam); } static UINT_PTR CALLBACK @@ -87,7 +88,7 @@ PrintDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) DWORD style = ::GetClassLong(hdlg, GCL_STYLE); ::SetClassLong(hdlg,GCL_STYLE, style & ~CS_SAVEBITS); - ::SetFocus(hdlg); + ::SetFocus(hdlg); // will not break synthetic focus as hdlg is a native toplevel // set appropriate icon for parentless dialogs jobject awtParent = env->GetObjectField(peer, AwtPrintDialog::parentID); @@ -99,16 +100,19 @@ PrintDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) } // subclass dialog's parent to receive additional messages - ComCtl32Util::GetInstance().SubclassHWND(hdlg, - PrintDialogWndProc); + WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(hdlg, + PrintDialogWndProc); + ::SetProp(hdlg, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc)); break; } case WM_DESTROY: { + WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hdlg, NativeDialogWndProcProp)); ComCtl32Util::GetInstance().UnsubclassHWND(hdlg, PrintDialogWndProc, - NULL); + lpfnWndProc); ::RemoveProp(hdlg, ModalDialogPeerProp); + ::RemoveProp(hdlg, NativeDialogWndProcProp); break; } } diff --git a/src/windows/native/sun/windows/awt_PrintJob.cpp b/src/windows/native/sun/windows/awt_PrintJob.cpp index 9136b7864..c33397786 100644 --- a/src/windows/native/sun/windows/awt_PrintJob.cpp +++ b/src/windows/native/sun/windows/awt_PrintJob.cpp @@ -2885,7 +2885,8 @@ LRESULT CALLBACK PageDialogWndProc(HWND hWnd, UINT message, } } - return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam); + WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp)); + return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam); } /** @@ -2919,16 +2920,19 @@ static UINT CALLBACK pageDlgHook(HWND hDlg, UINT msg, } // subclass dialog's parent to receive additional messages - ComCtl32Util::GetInstance().SubclassHWND(hDlg, - PageDialogWndProc); + WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(hDlg, + PageDialogWndProc); + ::SetProp(hDlg, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc)); break; } case WM_DESTROY: { + WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hDlg, NativeDialogWndProcProp)); ComCtl32Util::GetInstance().UnsubclassHWND(hDlg, PageDialogWndProc, - NULL); + lpfnWndProc); ::RemoveProp(hDlg, ModalDialogPeerProp); + ::RemoveProp(hDlg, NativeDialogWndProcProp); break; } } diff --git a/src/windows/native/sun/windows/awt_ScrollPane.cpp b/src/windows/native/sun/windows/awt_ScrollPane.cpp index 4d41e0b0c..bf11ecca3 100644 --- a/src/windows/native/sun/windows/awt_ScrollPane.cpp +++ b/src/windows/native/sun/windows/awt_ScrollPane.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -361,13 +361,6 @@ void AwtScrollPane::PostScrollEvent(int orient, int scrollCode, int pos) { DASSERT(!safe_ExceptionOccurred(env)); } -BOOL AwtScrollPane::ActMouseMessage(MSG* pMsg) { - if (!IsFocusingMessage(pMsg->message)) { - return FALSE; - } - return TRUE; -} - MsgRouting AwtScrollPane::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) { @@ -412,13 +405,10 @@ MsgRouting AwtScrollPane::WmHScroll(UINT scrollCode, UINT pos, HWND hScrollPane) return mrConsume; } -/* - * Fix for BugTraq ID 4041703: keyDown not being invoked. - * This method overrides AwtCanvas::HandleEvent() since we - * don't want ScrollPanel to receive focus on mouse press. - */ MsgRouting AwtScrollPane::HandleEvent(MSG *msg, BOOL synthetic) { + // SunAwtScrollPane control doesn't cause activation on mouse/key events, + // so we can safely (for synthetic focus) pass them to the system proc. return AwtComponent::HandleEvent(msg, synthetic); } diff --git a/src/windows/native/sun/windows/awt_ScrollPane.h b/src/windows/native/sun/windows/awt_ScrollPane.h index c58363969..326e7fa75 100644 --- a/src/windows/native/sun/windows/awt_ScrollPane.h +++ b/src/windows/native/sun/windows/awt_ScrollPane.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -65,7 +65,6 @@ public: virtual void Reshape(int x, int y, int w, int h); virtual void BeginValidate() {} virtual void EndValidate() {} - BOOL ActMouseMessage(MSG* pMsg); /* * Fix for bug 4046446 diff --git a/src/windows/native/sun/windows/awt_Scrollbar.cpp b/src/windows/native/sun/windows/awt_Scrollbar.cpp index 879c1847f..27b1b5ddb 100644 --- a/src/windows/native/sun/windows/awt_Scrollbar.cpp +++ b/src/windows/native/sun/windows/awt_Scrollbar.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -27,7 +27,6 @@ #include "awt_Scrollbar.h" #include "awt_Canvas.h" #include "awt_Window.h" -#include "awt_KeyboardFocusManager.h" /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. */ @@ -61,7 +60,6 @@ AwtScrollbar::AwtScrollbar() { m_orientation = SB_HORZ; m_lineIncr = 0; m_pageIncr = 0; - m_ignoreFocusEvents = FALSE; m_prevCallback = NULL; m_prevCallbackPos = 0; ms_instanceCounter++; @@ -221,7 +219,6 @@ AwtScrollbar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) return retValue; } - MsgRouting AwtScrollbar::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) { @@ -265,17 +262,10 @@ AwtScrollbar::WmMouseDown(UINT flags, int x, int y, int button) MsgRouting AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic) { - if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { - if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd()) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); - AwtSetFocus(); - } + // SCROLLBAR control doesn't cause activation on mouse/key events, + // so we can safely (for synthetic focus) pass them to the system proc. + + if (IsFocusingMouseMessage(msg)) { // Left button press was already routed to default window // procedure in the WmMouseDown above. Propagating synthetic // press seems like a bad idea as internal message loop @@ -283,54 +273,19 @@ AwtScrollbar::HandleEvent(MSG *msg, BOOL synthetic) delete msg; return mrConsume; } - else { - return AwtComponent::HandleEvent(msg, synthetic); - } + return AwtComponent::HandleEvent(msg, synthetic); } - // Work around a windows bug descrbed in KB article Q73839. Reset // focus on scrollbars to update focus indicator. The article advises -// to disable/enable the scrollbar, but simply resetting the focus is -// sufficient. +// to disable/enable the scrollbar. void AwtScrollbar::UpdateFocusIndicator() { if (IsFocusable()) { - m_ignoreFocusEvents = TRUE; - ::SetFocus(NULL); - AwtSetFocus(); - m_ignoreFocusEvents = FALSE; - } -} - -MsgRouting -AwtScrollbar::WmKillFocus(HWND hWndGot) -{ - if (m_ignoreFocusEvents) { - // We are voluntary giving up focus and will get it back - // immediately. This is necessary to force windows to update - // the focus indicator. - sm_focusOwner = NULL; - return mrDoDefault; - } - else { - return AwtComponent::WmKillFocus(hWndGot); - } -} - -MsgRouting -AwtScrollbar::WmSetFocus(HWND hWndLost) -{ - if (m_ignoreFocusEvents) { - // We have voluntary gave up focus and are getting it back - // now. This is necessary to force windows to update the - // focus indicator. - sm_focusOwner = GetHWnd(); - return mrDoDefault; - } - else { - return AwtComponent::WmSetFocus(hWndLost); + // todo: doesn't work + SendMessage((WPARAM)ESB_DISABLE_BOTH); + SendMessage((WPARAM)ESB_ENABLE_BOTH); } } diff --git a/src/windows/native/sun/windows/awt_Scrollbar.h b/src/windows/native/sun/windows/awt_Scrollbar.h index 4fcac523c..44763cd23 100644 --- a/src/windows/native/sun/windows/awt_Scrollbar.h +++ b/src/windows/native/sun/windows/awt_Scrollbar.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -69,10 +69,6 @@ public: virtual MsgRouting WmHScroll(UINT scrollCode, UINT pos, HWND hScrollBar); virtual MsgRouting WmVScroll(UINT scrollCode, UINT pos, HWND hScrollBar); - // Work around KB Q73839 bug. - virtual MsgRouting WmSetFocus(HWND hWndLost); - virtual MsgRouting WmKillFocus(HWND hWndGot); - // Prevent KB Q102552 race. virtual MsgRouting WmMouseDown(UINT flags, int x, int y, int button); virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); @@ -91,7 +87,6 @@ private: int m_pageIncr; // Work around KB Q73839 bug. - BOOL m_ignoreFocusEvents; void UpdateFocusIndicator(); // Don't do redundant callbacks. diff --git a/src/windows/native/sun/windows/awt_TextArea.cpp b/src/windows/native/sun/windows/awt_TextArea.cpp index e0d4c6158..b99de8d23 100644 --- a/src/windows/native/sun/windows/awt_TextArea.cpp +++ b/src/windows/native/sun/windows/awt_TextArea.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -26,9 +26,9 @@ #include "awt_Toolkit.h" #include "awt_TextArea.h" #include "awt_TextComponent.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" #include "awt_Window.h" +#include "awt_Frame.h" /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. */ @@ -362,13 +362,6 @@ AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { DASSERT(::IsWindow(::GetParent(hWnd))); switch (message) { - case WM_SETFOCUS: - ::SendMessage(::GetParent(hWnd), EM_HIDESELECTION, FALSE, 0); - break; - case WM_KILLFOCUS: - ::SendMessage(::GetParent(hWnd), EM_HIDESELECTION, TRUE, 0); - break; - case WM_UNDO: case WM_CUT: case WM_COPY: @@ -400,7 +393,6 @@ AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { MsgRouting AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) { - /* Use the system provided edit control class to generate context menu. */ if (m_hEditCtrl == NULL) { DWORD dwStyle = WS_CHILD; @@ -494,22 +486,11 @@ AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) { VERIFY(::ClientToScreen(GetHWnd(), &p)); } - ::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, - MAKELPARAM(p.x, p.y)); - /* - * After the context menu is dismissed focus is owned by the edit contol. - * Return focus to parent. - */ - if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd()) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, TimeHelper::getMessageTimeUTC()); - env->DeleteLocalRef(target); - AwtSetFocus(); - } + // The context menu steals focus from the proxy. + // So, set the focus-restore flag up. + SetRestoreFocus(TRUE); + ::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, MAKELPARAM(p.x, p.y)); + SetRestoreFocus(FALSE); return mrConsume; } @@ -558,20 +539,11 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) * By consuming WM_MOUSEMOVE messages we also don't give * the RichEdit control a chance to recognize a drag gesture * and initiate its own drag-n-drop operation. + * + * The workaround also allows us to implement synthetic focus mechanism. + * */ - if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { - - if (IsFocusable() && AwtComponent::sm_focusOwner != GetHWnd()) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); - AwtSetFocus(); - } - + if (IsFocusingMouseMessage(msg)) { CHARRANGE cr; LONG lCurPos = EditGetCharFromPos(msg->pt); @@ -717,6 +689,7 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) p.x = -1; p.y = -1; } + if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(), MAKELPARAM(p.x, p.y))) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -724,6 +697,8 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) env->ExceptionDescribe(); env->ExceptionClear(); } + delete msg; + return mrConsume; } else if (msg->message == WM_MOUSEWHEEL) { // 4417236: If there is an old version of RichEd32.dll which // does not provide the mouse wheel scrolling we have to diff --git a/src/windows/native/sun/windows/awt_TextComponent.cpp b/src/windows/native/sun/windows/awt_TextComponent.cpp index 9920b9252..e0a7af74d 100644 --- a/src/windows/native/sun/windows/awt_TextComponent.cpp +++ b/src/windows/native/sun/windows/awt_TextComponent.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -25,7 +25,6 @@ #include "awt_Toolkit.h" #include "awt_TextComponent.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" #include "jni.h" @@ -62,9 +61,9 @@ jfieldID AwtTextComponent::canAccessClipboardID; AwtTextComponent::AwtTextComponent() { m_synthetic = FALSE; - m_lStartPos = -1; - m_lEndPos = -1; - m_lLastPos = -1; + m_lStartPos = -1; + m_lEndPos = -1; + m_lLastPos = -1; m_isLFonly = FALSE; m_EOLchecked = FALSE; // javaEventsMask = 0; // accessibility support @@ -74,10 +73,6 @@ LPCTSTR AwtTextComponent::GetClassName() { return TEXT("EDIT"); /* System provided edit control class */ } -BOOL AwtTextComponent::ActMouseMessage(MSG* pMsg) { - return FALSE; -} - /* Set a suitable font to IME against the component font. */ void AwtTextComponent::SetFont(AwtFont* font) { @@ -143,23 +138,16 @@ AwtTextComponent::WmNotify(UINT notifyCode) return mrDoDefault; } +BOOL AwtTextComponent::IsFocusingMouseMessage(MSG *pMsg) +{ + return pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK; +} + MsgRouting AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic) { MsgRouting returnVal; - if (AwtComponent::sm_focusOwner != GetHWnd() && IsFocusable() && - (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK)) - { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject target = GetTarget(env); - env->CallStaticVoidMethod - (AwtKeyboardFocusManager::keyboardFocusManagerCls, - AwtKeyboardFocusManager::heavyweightButtonDownMID, - target, ((jlong)msg->time) & 0xFFFFFFFF); - env->DeleteLocalRef(target); - } - /* * Store the 'synthetic' parameter so that the WM_PASTE security check * happens only for synthetic events. diff --git a/src/windows/native/sun/windows/awt_TextComponent.h b/src/windows/native/sun/windows/awt_TextComponent.h index 32a430baf..c6068b523 100644 --- a/src/windows/native/sun/windows/awt_TextComponent.h +++ b/src/windows/native/sun/windows/awt_TextComponent.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -69,8 +69,6 @@ public: // called on Toolkit thread from JNI static jstring _GetText(void *param); - BOOL ActMouseMessage(MSG* pMsg); - void SetFont(AwtFont* font); /* @@ -80,6 +78,8 @@ public: MsgRouting HandleEvent(MSG *msg, BOOL synthetic); MsgRouting WmPaste(); + virtual BOOL IsFocusingMouseMessage(MSG *pMsg); + /* To be fully implemented in a future release MsgRouting WmKeyDown(UINT wkey, UINT repCnt, @@ -125,7 +125,6 @@ private: LONG m_lEndPos; LONG m_lLastPos; - HFONT m_hFont; //im --- end diff --git a/src/windows/native/sun/windows/awt_TextField.cpp b/src/windows/native/sun/windows/awt_TextField.cpp index 975fd20bc..49095d3e3 100644 --- a/src/windows/native/sun/windows/awt_TextField.cpp +++ b/src/windows/native/sun/windows/awt_TextField.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -26,7 +26,6 @@ #include "awt_Toolkit.h" #include "awt_TextField.h" #include "awt_TextComponent.h" -#include "awt_KeyboardFocusManager.h" #include "awt_Canvas.h" /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. @@ -150,135 +149,130 @@ AwtTextField::HandleEvent(MSG *msg, BOOL synthetic) * By consuming WM_MOUSEMOVE messages we also don't give * the RichEdit control a chance to recognize a drag gesture * and initiate its own drag-n-drop operation. + * + * The workaround also allows us to implement synthetic focus mechanism. */ - /** - * In non-focusable mode we don't pass mouse messages to native window thus making user unable - * to select the text. Below is the code from awt_TextArea.cpp which implements selection - * functionality. For safety this code is only being executed in non-focusable mode. - */ - if (!IsFocusable()) { - if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONDBLCLK) { + if (IsFocusingMouseMessage(msg)) { + CHARRANGE cr; + + LONG lCurPos = EditGetCharFromPos(msg->pt); + + EditGetSel(cr); + /* + * NOTE: Plain EDIT control always clears selection on mouse + * button press. We are clearing the current selection only if + * the mouse pointer is not over the selected region. + * In this case we sacrifice backward compatibility + * to allow dnd of the current selection. + */ + if (msg->message == WM_LBUTTONDBLCLK) { + SetStartSelectionPos(static_cast<LONG>(SendMessage( + EM_FINDWORDBREAK, WB_MOVEWORDLEFT, lCurPos))); + SetEndSelectionPos(static_cast<LONG>(SendMessage( + EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, lCurPos))); + } else { + SetStartSelectionPos(lCurPos); + SetEndSelectionPos(lCurPos); + } + cr.cpMin = GetStartSelectionPos(); + cr.cpMax = GetEndSelectionPos(); + EditSetSel(cr); + + delete msg; + return mrConsume; + } else if (msg->message == WM_LBUTTONUP) { + + /* + * If the left mouse button is pressed on the selected region + * we don't clear the current selection. We clear it on button + * release instead. This is to allow dnd of the current selection. + */ + if (GetStartSelectionPos() == -1 && GetEndSelectionPos() == -1) { CHARRANGE cr; LONG lCurPos = EditGetCharFromPos(msg->pt); - EditGetSel(cr); - /* - * NOTE: Plain EDIT control always clears selection on mouse - * button press. We are clearing the current selection only if - * the mouse pointer is not over the selected region. - * In this case we sacrifice backward compatibility - * to allow dnd of the current selection. - */ - if (msg->message == WM_LBUTTONDBLCLK) { - SetStartSelectionPos(static_cast<LONG>(SendMessage( - EM_FINDWORDBREAK, WB_MOVEWORDLEFT, lCurPos))); - SetEndSelectionPos(static_cast<LONG>(SendMessage( - EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, lCurPos))); - } else { - SetStartSelectionPos(lCurPos); - SetEndSelectionPos(lCurPos); - } - cr.cpMin = GetStartSelectionPos(); - cr.cpMax = GetEndSelectionPos(); + cr.cpMin = lCurPos; + cr.cpMax = lCurPos; EditSetSel(cr); + } - delete msg; - return mrConsume; - } else if (msg->message == WM_LBUTTONUP) { + /* + * Cleanup the state variables when left mouse button is released. + * These state variables are designed to reflect the selection state + * while the left mouse button is pressed and be set to -1 otherwise. + */ + SetStartSelectionPos(-1); + SetEndSelectionPos(-1); + SetLastSelectionPos(-1); + + delete msg; + return mrConsume; + } else if (msg->message == WM_MOUSEMOVE && (msg->wParam & MK_LBUTTON)) { + + /* + * We consume WM_MOUSEMOVE while the left mouse button is pressed, + * so we have to simulate autoscrolling when mouse is moved outside + * of the client area. + */ + POINT p; + RECT r; + BOOL bScrollLeft = FALSE; + BOOL bScrollRight = FALSE; + BOOL bScrollUp = FALSE; + BOOL bScrollDown = FALSE; + + p.x = msg->pt.x; + p.y = msg->pt.y; + VERIFY(::GetClientRect(GetHWnd(), &r)); + + if (p.x < 0) { + bScrollLeft = TRUE; + p.x = 0; + } else if (p.x > r.right) { + bScrollRight = TRUE; + p.x = r.right - 1; + } + LONG lCurPos = EditGetCharFromPos(p); - /* - * If the left mouse button is pressed on the selected region - * we don't clear the current selection. We clear it on button - * release instead. This is to allow dnd of the current selection. - */ - if (GetStartSelectionPos() == -1 && GetEndSelectionPos() == -1) { - CHARRANGE cr; + if (GetStartSelectionPos() != -1 && + GetEndSelectionPos() != -1 && + lCurPos != GetLastSelectionPos()) { - LONG lCurPos = EditGetCharFromPos(msg->pt); + CHARRANGE cr; - cr.cpMin = lCurPos; - cr.cpMax = lCurPos; - EditSetSel(cr); - } + SetLastSelectionPos(lCurPos); - /* - * Cleanup the state variables when left mouse button is released. - * These state variables are designed to reflect the selection state - * while the left mouse button is pressed and be set to -1 otherwise. - */ - SetStartSelectionPos(-1); - SetEndSelectionPos(-1); - SetLastSelectionPos(-1); + cr.cpMin = GetStartSelectionPos(); + cr.cpMax = GetLastSelectionPos(); - delete msg; - return mrConsume; - } else if (msg->message == WM_MOUSEMOVE && (msg->wParam & MK_LBUTTON)) { + EditSetSel(cr); + } + if (bScrollLeft == TRUE || bScrollRight == TRUE) { + SCROLLINFO si; + memset(&si, 0, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + + VERIFY(::GetScrollInfo(GetHWnd(), SB_HORZ, &si)); + if (bScrollLeft == TRUE) { + si.nPos = si.nPos - si.nPage / 2; + si.nPos = max(si.nMin, si.nPos); + } else if (bScrollRight == TRUE) { + si.nPos = si.nPos + si.nPage / 2; + si.nPos = min(si.nPos, si.nMax); + } /* - * We consume WM_MOUSEMOVE while the left mouse button is pressed, - * so we have to simulate autoscrolling when mouse is moved outside - * of the client area. + * Okay to use 16-bit position since RichEdit control adjusts + * its scrollbars so that their range is always 16-bit. */ - POINT p; - RECT r; - BOOL bScrollLeft = FALSE; - BOOL bScrollRight = FALSE; - BOOL bScrollUp = FALSE; - BOOL bScrollDown = FALSE; - - p.x = msg->pt.x; - p.y = msg->pt.y; - VERIFY(::GetClientRect(GetHWnd(), &r)); - - if (p.x < 0) { - bScrollLeft = TRUE; - p.x = 0; - } else if (p.x > r.right) { - bScrollRight = TRUE; - p.x = r.right - 1; - } - LONG lCurPos = EditGetCharFromPos(p); - - if (GetStartSelectionPos() != -1 && - GetEndSelectionPos() != -1 && - lCurPos != GetLastSelectionPos()) { - - CHARRANGE cr; - - SetLastSelectionPos(lCurPos); - - cr.cpMin = GetStartSelectionPos(); - cr.cpMax = GetLastSelectionPos(); - - EditSetSel(cr); - } - - if (bScrollLeft == TRUE || bScrollRight == TRUE) { - SCROLLINFO si; - memset(&si, 0, sizeof(si)); - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - - VERIFY(::GetScrollInfo(GetHWnd(), SB_HORZ, &si)); - if (bScrollLeft == TRUE) { - si.nPos = si.nPos - si.nPage / 2; - si.nPos = max(si.nMin, si.nPos); - } else if (bScrollRight == TRUE) { - si.nPos = si.nPos + si.nPage / 2; - si.nPos = min(si.nPos, si.nMax); - } - /* - * Okay to use 16-bit position since RichEdit control adjusts - * its scrollbars so that their range is always 16-bit. - */ - DASSERT(abs(si.nPos) < 0x8000); - SendMessage(WM_HSCROLL, - MAKEWPARAM(SB_THUMBPOSITION, LOWORD(si.nPos))); - } - delete msg; - return mrConsume; + DASSERT(abs(si.nPos) < 0x8000); + SendMessage(WM_HSCROLL, + MAKEWPARAM(SB_THUMBPOSITION, LOWORD(si.nPos))); } + delete msg; + return mrConsume; } /* * Store the 'synthetic' parameter so that the WM_PASTE security check diff --git a/src/windows/native/sun/windows/awt_Toolkit.cpp b/src/windows/native/sun/windows/awt_Toolkit.cpp index c4292826a..4a7cc16c5 100644 --- a/src/windows/native/sun/windows/awt_Toolkit.cpp +++ b/src/windows/native/sun/windows/awt_Toolkit.cpp @@ -56,6 +56,7 @@ #include "debug_mem.h" #include "ComCtl32Util.h" +#include "DllUtil.h" #include "D3DPipelineManager.h" @@ -334,6 +335,8 @@ AwtToolkit::AwtToolkit() { m_mouseDown = FALSE; m_hGetMessageHook = 0; + m_hMouseLLHook = 0; + m_lastWindowUnderMouse = NULL; m_timer = 0; m_cmdIDs = new AwtCmdIDList(); @@ -483,6 +486,7 @@ BOOL AwtToolkit::Dispose() { tk.UnregisterClass(); ::UnhookWindowsHookEx(tk.m_hGetMessageHook); + UninstallMouseLowLevelHook(); tk.m_mainThreadId = 0; @@ -960,6 +964,79 @@ LRESULT CALLBACK AwtToolkit::GetMessageFilter(int code, CATCH_BAD_ALLOC_RET(0); } +void AwtToolkit::InstallMouseLowLevelHook() +{ + // We need the low-level hook since we need to process mouse move + // messages outside of our windows. + m_hMouseLLHook = ::SetWindowsHookEx(WH_MOUSE_LL, + (HOOKPROC)MouseLowLevelHook, + GetModuleHandle(), NULL); + + // Reset the old value + m_lastWindowUnderMouse = NULL; +} + +void AwtToolkit::UninstallMouseLowLevelHook() +{ + if (m_hMouseLLHook != 0) { + ::UnhookWindowsHookEx(m_hMouseLLHook); + m_hMouseLLHook = 0; + } +} + +LRESULT CALLBACK AwtToolkit::MouseLowLevelHook(int code, + WPARAM wParam, LPARAM lParam) +{ + TRY; + + if (code >= 0 && wParam == WM_MOUSEMOVE) { + POINT pt = ((MSLLHOOKSTRUCT*)lParam)->pt; + + // We can't use GA_ROOTOWNER since in this case we'll go up to + // the root Java toplevel, not the actual owned toplevel. + HWND hwnd = ::GetAncestor(::WindowFromPoint(pt), GA_ROOT); + + AwtToolkit& tk = AwtToolkit::GetInstance(); + + if (tk.m_lastWindowUnderMouse != hwnd) { + AwtWindow *fw = NULL, *tw = NULL; + + if (tk.m_lastWindowUnderMouse) { + fw = (AwtWindow*) + AwtComponent::GetComponent(tk.m_lastWindowUnderMouse); + } + if (hwnd) { + tw = (AwtWindow*)AwtComponent::GetComponent(hwnd); + } + + tk.m_lastWindowUnderMouse = hwnd; + + if (fw) { + fw->UpdateSecurityWarningVisibility(); + } + // ... however, because we use GA_ROOT, we may find the warningIcon + // which is not a Java windows. + if (AwtWindow::IsWarningWindow(hwnd)) { + hwnd = ::GetParent(hwnd); + if (hwnd) { + tw = (AwtWindow*)AwtComponent::GetComponent(hwnd); + } + tk.m_lastWindowUnderMouse = hwnd; + } + if (tw) { + tw->UpdateSecurityWarningVisibility(); + } + + + } + } + + return ::CallNextHookEx(AwtToolkit::GetInstance().m_hMouseLLHook, code, + wParam, lParam); + + CATCH_BAD_ALLOC_RET(0); +} + /* * The main message loop */ @@ -1376,6 +1453,47 @@ HICON AwtToolkit::GetAwtIconSm() return defaultIconSm; } +HICON AwtToolkit::GetSecurityWarningIcon(UINT index, UINT w, UINT h) +{ + //Note: should not exceed 10 because of the current implementation. + static const int securityWarningIconCounter = 3; + + static HICON securityWarningIcon[securityWarningIconCounter] = {NULL, NULL, NULL};; + static UINT securityWarningIconWidth[securityWarningIconCounter] = {0, 0, 0}; + static UINT securityWarningIconHeight[securityWarningIconCounter] = {0, 0, 0}; + + index = AwtToolkit::CalculateWave(index, securityWarningIconCounter); + + if (securityWarningIcon[index] == NULL || + w != securityWarningIconWidth[index] || + h != securityWarningIconHeight[index]) + { + if (securityWarningIcon[index] != NULL) + { + ::DestroyIcon(securityWarningIcon[index]); + } + + static const wchar_t securityWarningIconName[] = L"SECURITY_WARNING_"; + wchar_t iconResourceName[sizeof(securityWarningIconName) + 2]; + ::ZeroMemory(iconResourceName, sizeof(iconResourceName)); + wcscpy(iconResourceName, securityWarningIconName); + + wchar_t strIndex[2]; + ::ZeroMemory(strIndex, sizeof(strIndex)); + strIndex[0] = L'0' + index; + + wcscat(iconResourceName, strIndex); + + securityWarningIcon[index] = (HICON)::LoadImage(GetModuleHandle(), + iconResourceName, + IMAGE_ICON, w, h, LR_DEFAULTCOLOR); + securityWarningIconWidth[index] = w; + securityWarningIconHeight[index] = h; + } + + return securityWarningIcon[index]; +} + void AwtToolkit::SetHeapCheck(long flag) { if (flag) { printf("heap checking not supported with this build\n"); @@ -1428,6 +1546,49 @@ JNIEnv* AwtToolkit::GetEnv() { (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2) : m_env; } +BOOL AwtToolkit::GetScreenInsets(int screenNum, RECT * rect) +{ + /* if primary display */ + if (screenNum == 0) { + RECT rRW; + if (::SystemParametersInfo(SPI_GETWORKAREA,0,(void *) &rRW,0) == TRUE) { + rect->top = rRW.top; + rect->left = rRW.left; + rect->bottom = ::GetSystemMetrics(SM_CYSCREEN) - rRW.bottom; + rect->right = ::GetSystemMetrics(SM_CXSCREEN) - rRW.right; + return TRUE; + } + } + /* if additional display */ + else { + MONITORINFO *miInfo; + miInfo = AwtWin32GraphicsDevice::GetMonitorInfo(screenNum); + if (miInfo) { + rect->top = miInfo->rcWork.top - miInfo->rcMonitor.top; + rect->left = miInfo->rcWork.left - miInfo->rcMonitor.left; + rect->bottom = miInfo->rcMonitor.bottom - miInfo->rcWork.bottom; + rect->right = miInfo->rcMonitor.right - miInfo->rcWork.right; + return TRUE; + } + } + return FALSE; +} + + +void AwtToolkit::GetWindowRect(HWND hWnd, LPRECT lpRect) +{ + try { + if (S_OK == DwmAPI::DwmGetWindowAttribute(hWnd, + DwmAPI::DWMWA_EXTENDED_FRAME_BOUNDS, + lpRect, sizeof(*lpRect))) + { + return; + } + } catch (const DllUtil::Exception &) {} + + ::GetWindowRect(hWnd, lpRect); +} + /************************************************************************ * Toolkit native methods */ @@ -1756,7 +1917,6 @@ Java_sun_awt_windows_WToolkit_getScreenHeight(JNIEnv *env, jobject self) CATCH_BAD_ALLOC_RET(0); } - /* * Class: sun_awt_windows_WToolkit * Method: getSreenInsets @@ -1768,34 +1928,17 @@ Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv *env, jint screen) { jobject insets = NULL; - RECT rRW; - LPMONITORINFO miInfo; + RECT rect; TRY; -/* if primary display */ - if (screen == 0) { - if (::SystemParametersInfo(SPI_GETWORKAREA,0,(void *) &rRW,0) == TRUE) { - insets = env->NewObject(env->FindClass("java/awt/Insets"), - AwtToolkit::insetsMID, - rRW.top, - rRW.left, - ::GetSystemMetrics(SM_CYSCREEN) - rRW.bottom, - ::GetSystemMetrics(SM_CXSCREEN) - rRW.right); - } - } - -/* if additional display */ - else { - miInfo = AwtWin32GraphicsDevice::GetMonitorInfo(screen); - if (miInfo) { - insets = env->NewObject(env->FindClass("java/awt/Insets"), + if (AwtToolkit::GetScreenInsets(screen, &rect)) { + insets = env->NewObject(env->FindClass("java/awt/Insets"), AwtToolkit::insetsMID, - miInfo->rcWork.top - miInfo->rcMonitor.top, - miInfo->rcWork.left - miInfo->rcMonitor.left, - miInfo->rcMonitor.bottom - miInfo->rcWork.bottom, - miInfo->rcMonitor.right - miInfo->rcWork.right); - } + rect.top, + rect.left, + rect.bottom, + rect.right); } if (safe_ExceptionOccurred(env)) { diff --git a/src/windows/native/sun/windows/awt_Toolkit.h b/src/windows/native/sun/windows/awt_Toolkit.h index d76546fa4..3bb07712a 100644 --- a/src/windows/native/sun/windows/awt_Toolkit.h +++ b/src/windows/native/sun/windows/awt_Toolkit.h @@ -210,6 +210,8 @@ public: LPARAM lParam); static LRESULT CALLBACK ForegroundIdleFilter(int code, WPARAM wParam, LPARAM lParam); + static LRESULT CALLBACK MouseLowLevelHook(int code, WPARAM wParam, + LPARAM lParam); INLINE static AwtToolkit& GetInstance() { return theInstance; } INLINE void SetPeer(JNIEnv *env, jobject wToolkit) { @@ -311,6 +313,30 @@ public: HICON GetAwtIcon(); HICON GetAwtIconSm(); + // Calculate a wave-like value out of the integer 'value' and + // the specified period. + // The argument 'value' is an integer 0, 1, 2, ... *infinity*. + // + // Examples: + // Period == 3 + // Generated sequence: 0 1 2 1 0 ..... + // + // Period == 4 + // Generated sequence: 0 1 2 3 2 1 0 ..... + static inline UINT CalculateWave(UINT value, const UINT period) { + if (period < 2) { + return 0; + } + // -2 is necessary to avoid repeating extreme values (0 and period-1) + value %= period * 2 -2; + if (value >= period) { + value = period * 2 -2 - value; + } + return value; + } + + HICON GetSecurityWarningIcon(UINT index, UINT w, UINT h); + /* Turns on/off dialog modality for the system. */ INLINE AwtDialog* SetModal(AwtDialog* frame) { AwtDialog* previousDialog = m_pModalDialog; @@ -368,6 +394,7 @@ private: BOOL m_mouseDown; HHOOK m_hGetMessageHook; + HHOOK m_hMouseLLHook; UINT_PTR m_timer; class AwtCmdIDList* m_cmdIDs; @@ -411,6 +438,24 @@ public: public: static void SetEnv(JNIEnv *env); static JNIEnv* GetEnv(); + + static BOOL GetScreenInsets(int screenNum, RECT * rect); + + // If the DWM is active, this function uses + // DwmGetWindowAttribute()/DWMWA_EXTENDED_FRAME_BOUNDS. + // Otherwise, fall back to regular ::GetWindowRect(). + // See 6711576 for more details. + static void GetWindowRect(HWND hWnd, LPRECT lpRect); + + private: + // The window handle of a toplevel window last seen under the mouse cursor. + // See MouseLowLevelHook() for details. + HWND m_lastWindowUnderMouse; + public: + HWND GetWindowUnderMouse() { return m_lastWindowUnderMouse; } + + void InstallMouseLowLevelHook(); + void UninstallMouseLowLevelHook(); }; /* diff --git a/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp b/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp index 1617d54e6..150ff8f07 100644 --- a/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp +++ b/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp @@ -29,6 +29,7 @@ #include "awt_Win32GraphicsDevice.h" #include "Devices.h" #include "WindowsFlags.h" +#include "DllUtil.h" BOOL DWMIsCompositionEnabled(); @@ -89,13 +90,8 @@ void DWMResetCompositionEnabled() { /** * Returns true if dwm composition is enabled, false if it is not applicable * (if the OS is not Vista) or dwm composition is disabled. - * - * Note: since DWM composition state changes are very rare we load/unload the - * dll on every change. */ BOOL DWMIsCompositionEnabled() { - typedef HRESULT (WINAPI DwmIsCompositionEnabledFunc)(BOOL*); - // cheaper to check than whether it's vista or not if (dwmIsCompositionEnabled != DWM_COMP_UNDEFINED) { return (BOOL)dwmIsCompositionEnabled; @@ -107,32 +103,22 @@ BOOL DWMIsCompositionEnabled() { } BOOL bRes = FALSE; - HMODULE hDwmApiDll = ::LoadLibrary(TEXT("dwmapi.dll")); - - if (hDwmApiDll != NULL) { - DwmIsCompositionEnabledFunc *lpDwmIsCompEnabled = - (DwmIsCompositionEnabledFunc*) - GetProcAddress(hDwmApiDll, "DwmIsCompositionEnabled"); - if (lpDwmIsCompEnabled != NULL) { - BOOL bEnabled; - HRESULT res = lpDwmIsCompEnabled(&bEnabled); - if (SUCCEEDED(res)) { - bRes = bEnabled; - J2dTraceLn1(J2D_TRACE_VERBOSE, " composition enabled: %d",bRes); - } else { - J2dTraceLn1(J2D_TRACE_ERROR, - "IsDWMCompositionEnabled: error %x when detecting"\ - "if composition is enabled", res); - } + + try { + BOOL bEnabled; + HRESULT res = DwmAPI::DwmIsCompositionEnabled(&bEnabled); + if (SUCCEEDED(res)) { + bRes = bEnabled; + J2dTraceLn1(J2D_TRACE_VERBOSE, " composition enabled: %d",bRes); } else { - J2dTraceLn(J2D_TRACE_ERROR, - "IsDWMCompositionEnabled: no DwmIsCompositionEnabled() "\ - "in dwmapi.dll"); + J2dTraceLn1(J2D_TRACE_ERROR, + "IsDWMCompositionEnabled: error %x when detecting"\ + "if composition is enabled", res); } - ::FreeLibrary(hDwmApiDll); - } else { + } catch (const DllUtil::Exception &) { J2dTraceLn(J2D_TRACE_ERROR, - "IsDWMCompositionEnabled: error opening dwmapi.dll"); + "IsDWMCompositionEnabled: no DwmIsCompositionEnabled() "\ + "in dwmapi.dll or dwmapi.dll cannot be loaded"); } dwmIsCompositionEnabled = bRes; diff --git a/src/windows/native/sun/windows/awt_Window.cpp b/src/windows/native/sun/windows/awt_Window.cpp index 0c9bce121..88bcd8ecc 100644 --- a/src/windows/native/sun/windows/awt_Window.cpp +++ b/src/windows/native/sun/windows/awt_Window.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -25,9 +25,12 @@ #include "awt.h" +#include <jlong.h> + #include "awt_Component.h" #include "awt_Container.h" #include "awt_Frame.h" +#include "awt_Dialog.h" #include "awt_Insets.h" #include "awt_Panel.h" #include "awt_Toolkit.h" @@ -35,6 +38,7 @@ #include "awt_Win32GraphicsDevice.h" #include "awt_BitmapUtil.h" #include "awt_IconCursor.h" +#include "ComCtl32Util.h" #include "java_awt_Insets.h" #include <java_awt_Container.h> @@ -88,7 +92,6 @@ struct ReshapeFrameStruct { jint x, y; jint w, h; }; - // struct for _SetIconImagesData struct SetIconImagesDataStruct { jobject window; @@ -97,7 +100,6 @@ struct SetIconImagesDataStruct { jintArray smallIconRaster; jint smw, smh; }; - // struct for _SetMinSize() method // and other methods setting sizes struct SizeStruct { @@ -114,6 +116,34 @@ struct ModalDisableStruct { jobject window; jlong blockerHWnd; }; +// struct for _SetOpacity() method +struct OpacityStruct { + jobject window; + jint iOpacity; +}; +// struct for _SetOpaque() method +struct OpaqueStruct { + jobject window; + jboolean isOpaque; +}; +// struct for _UpdateWindow() method +struct UpdateWindowStruct { + jobject window; + jintArray data; + HBITMAP hBitmap; + jint width, height; +}; +// Struct for _RequestWindowFocus() method +struct RequestWindowFocusStruct { + jobject component; + jboolean isMouseEventCause; +}; +// struct for _RepositionSecurityWarning() method +struct RepositionSecurityWarningStruct { + jobject window; +}; + + /************************************************************************ * AwtWindow fields */ @@ -121,17 +151,23 @@ struct ModalDisableStruct { jfieldID AwtWindow::warningStringID; jfieldID AwtWindow::locationByPlatformID; jfieldID AwtWindow::autoRequestFocusID; +jfieldID AwtWindow::securityWarningWidthID; +jfieldID AwtWindow::securityWarningHeightID; jfieldID AwtWindow::sysXID; jfieldID AwtWindow::sysYID; jfieldID AwtWindow::sysWID; jfieldID AwtWindow::sysHID; +jmethodID AwtWindow::getWarningStringMID; +jmethodID AwtWindow::calculateSecurityWarningPositionMID; + int AwtWindow::ms_instanceCounter = 0; HHOOK AwtWindow::ms_hCBTFilter; AwtWindow * AwtWindow::m_grabbedWindow = NULL; HWND AwtWindow::sm_retainingHierarchyZOrderInShow = NULL; BOOL AwtWindow::sm_resizing = FALSE; +UINT AwtWindow::untrustedWindowsCounter = 0; /************************************************************************ * AwtWindow class methods @@ -162,10 +198,34 @@ AwtWindow::AwtWindow() { ::SetWindowsHookEx(WH_CBT, (HOOKPROC)AwtWindow::CBTFilter, 0, AwtToolkit::MainThread()); } + + m_opaque = TRUE; + m_opacity = 0xff; + + + warningString = NULL; + warningWindow = NULL; + securityTooltipWindow = NULL; + securityWarningAnimationStage = 0; + currentWmSizeState = SIZE_RESTORED; + + hContentBitmap = NULL; + + ::InitializeCriticalSection(&contentBitmapCS); } AwtWindow::~AwtWindow() { + if (warningString != NULL) { + delete [] warningString; + } + ::EnterCriticalSection(&contentBitmapCS); + if (hContentBitmap != NULL) { + ::DeleteObject(hContentBitmap); + hContentBitmap = NULL; + } + ::LeaveCriticalSection(&contentBitmapCS); + ::DeleteCriticalSection(&contentBitmapCS); } void AwtWindow::Dispose() @@ -204,10 +264,10 @@ AwtWindow::Grab() { } m_grabbed = TRUE; m_grabbedWindow = this; - if (sm_focusedWindow == NULL && IsFocusableWindow()) { + if (AwtComponent::GetFocusedWindow() == NULL && IsFocusableWindow()) { // we shouldn't perform grab in this case (see 4841881 & 6539458) Ungrab(); - } else if (GetHWnd() != sm_focusedWindow) { + } else if (GetHWnd() != AwtComponent::GetFocusedWindow()) { _ToFront(env->NewGlobalRef(GetPeer(env))); // Global ref was deleted in _ToFront } @@ -301,12 +361,40 @@ MsgRouting AwtWindow::WmWindowPosChanging(LPARAM windowPos) { return mrDoDefault; } +void AwtWindow::RepositionSecurityWarning(JNIEnv *env) +{ + RECT rect; + CalculateWarningWindowBounds(env, &rect); + + ::SetWindowPos(warningWindow, HWND_NOTOPMOST, + rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOZORDER + ); +} + MsgRouting AwtWindow::WmWindowPosChanged(LPARAM windowPos) { - if (IsRetainingHierarchyZOrder() && ((WINDOWPOS *)windowPos)->flags & SWP_SHOWWINDOW) { + WINDOWPOS * wp = (WINDOWPOS *)windowPos; + + if (IsRetainingHierarchyZOrder() && wp->flags & SWP_SHOWWINDOW) { // By this time all the windows from the hierarchy are already notified about z-order change. // Thus we may and we should reset the trigger in order not to affect other changes. sm_retainingHierarchyZOrderInShow = NULL; } + + // Reposition the warning window + if (IsUntrusted() && warningWindow != NULL) { + if (wp->flags & SWP_HIDEWINDOW) { + UpdateSecurityWarningVisibility(); + } + + RepositionSecurityWarning((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)); + + if (wp->flags & SWP_SHOWWINDOW) { + UpdateSecurityWarningVisibility(); + } + } + return mrDoDefault; } @@ -326,21 +414,597 @@ void AwtWindow::FillClassInfo(WNDCLASSEX *lpwc) lpwc->cbWndExtra = DLGWINDOWEXTRA; } +bool AwtWindow::IsWarningWindow(HWND hWnd) +{ + const UINT len = 128; + TCHAR windowClassName[len]; + + ::RealGetWindowClass(hWnd, windowClassName, len); + return 0 == _tcsncmp(windowClassName, + AwtWindow::GetWarningWindowClassName(), len); +} + LRESULT CALLBACK AwtWindow::CBTFilter(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode == HCBT_ACTIVATE || nCode == HCBT_SETFOCUS) { - AwtComponent *comp = AwtComponent::GetComponent((HWND)wParam); + HWND hWnd = (HWND)wParam; + AwtComponent *comp = AwtComponent::GetComponent(hWnd); + + if (comp == NULL) { + // Check if it's a security warning icon + // See: 5091224, 6181725, 6732583 + if (AwtWindow::IsWarningWindow(hWnd)) { + return 1; + } + } else { + if (comp->IsTopLevel()) { + AwtWindow* win = (AwtWindow*)comp; - if (comp != NULL && comp->IsTopLevel()) { - AwtWindow* win = (AwtWindow*)comp; - if (!win->IsFocusableWindow() || win->m_filterFocusAndActivation) { - return 1; // Don't change focus/activation. + if (!win->IsFocusableWindow() || + win->m_filterFocusAndActivation) + { + return 1; // Don't change focus/activation. + } } } } return ::CallNextHookEx(AwtWindow::ms_hCBTFilter, nCode, wParam, lParam); } +void AwtWindow::InitSecurityWarningSize(JNIEnv *env) +{ + warningWindowWidth = ::GetSystemMetrics(SM_CXSMICON); + warningWindowHeight = ::GetSystemMetrics(SM_CYSMICON); + + jobject target = GetTarget(env); + + env->SetIntField(target, AwtWindow::securityWarningWidthID, + warningWindowWidth); + env->SetIntField(target, AwtWindow::securityWarningHeightID, + warningWindowHeight); + + env->DeleteLocalRef(target); +} + +void AwtWindow::CreateHWnd(JNIEnv *env, LPCWSTR title, + DWORD windowStyle, + DWORD windowExStyle, + int x, int y, int w, int h, + HWND hWndParent, HMENU hMenu, + COLORREF colorForeground, + COLORREF colorBackground, + jobject peer) +{ + // Retrieve the warning string + // Note: we need to get it before CreateHWnd() happens because + // the isUntrusted() method may be invoked while the HWND + // is being created in response to some window messages. + jobject target = env->GetObjectField(peer, AwtObject::targetID); + jstring javaWarningString = + (jstring)env->CallObjectMethod(target, AwtWindow::getWarningStringMID); + + if (javaWarningString != NULL) { + size_t length = env->GetStringLength(javaWarningString) + 1; + warningString = new WCHAR[length]; + env->GetStringRegion(javaWarningString, 0, + static_cast<jsize>(length - 1), warningString); + warningString[length-1] = L'\0'; + + env->DeleteLocalRef(javaWarningString); + } + env->DeleteLocalRef(target); + + AwtCanvas::CreateHWnd(env, title, + windowStyle, + windowExStyle, + x, y, w, h, + hWndParent, hMenu, + colorForeground, + colorBackground, + peer); + + // Now we need to create the warning window. + CreateWarningWindow(env); +} + +void AwtWindow::CreateWarningWindow(JNIEnv *env) +{ + if (!IsUntrusted()) { + return; + } + + if (++AwtWindow::untrustedWindowsCounter == 1) { + AwtToolkit::GetInstance().InstallMouseLowLevelHook(); + } + + InitSecurityWarningSize(env); + + RECT rect; + CalculateWarningWindowBounds(env, &rect); + + RegisterWarningWindowClass(); + warningWindow = ::CreateWindowEx( + WS_EX_NOACTIVATE | WS_EX_LAYERED, + GetWarningWindowClassName(), + warningString, + WS_POPUP, + rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, + GetHWnd(), // owner + NULL, // menu + AwtToolkit::GetInstance().GetModuleHandle(), + NULL // lParam + ); + if (warningWindow == NULL) { + //XXX: actually this is bad... We didn't manage to create the widow. + return; + } + + HICON hIcon = GetSecurityWarningIcon(); + + ICONINFO ii; + ::GetIconInfo(hIcon, &ii); + + //Note: we assume that every security icon has exactly the same shape. + HRGN rgn = BitmapUtil::BitmapToRgn(ii.hbmColor); + if (rgn) { + ::SetWindowRgn(warningWindow, rgn, TRUE); + } + + // Now we need to create the tooltip control for this window. + if (!ComCtl32Util::GetInstance().IsToolTipControlInitialized()) { + return; + } + + securityTooltipWindow = ::CreateWindowEx( + WS_EX_TOPMOST, + TOOLTIPS_CLASS, + NULL, + WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + warningWindow, + NULL, + AwtToolkit::GetInstance().GetModuleHandle(), + NULL + ); + + ::SetWindowPos(securityTooltipWindow, + HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + + // We currently don't expect changing the size of the window, + // hence we may not care of updating the TOOL position/size. + ::GetClientRect(warningWindow, &rect); + + TOOLINFO ti; + + ti.cbSize = sizeof(ti); + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = warningWindow; + ti.hinst = AwtToolkit::GetInstance().GetModuleHandle(); + ti.uId = 0; + ti.lpszText = warningString; + ti.rect.left = rect.left; + ti.rect.top = rect.top; + ti.rect.right = rect.right; + ti.rect.bottom = rect.bottom; + + ::SendMessage(securityTooltipWindow, TTM_ADDTOOL, + 0, (LPARAM) (LPTOOLINFO) &ti); +} + +void AwtWindow::DestroyWarningWindow() +{ + if (!IsUntrusted()) { + return; + } + if (--AwtWindow::untrustedWindowsCounter == 0) { + AwtToolkit::GetInstance().UninstallMouseLowLevelHook(); + } + if (warningWindow != NULL) { + // Note that the warningWindow is an owned window, and hence + // it would be destroyed automatically. However, the window + // class may only be unregistered if there's no any single + // window left using this class. Thus, we're destroying the + // warning window manually. Note that the tooltip window + // will be destroyed automatically because it's an owned + // window as well. + ::DestroyWindow(warningWindow); + warningWindow = NULL; + securityTooltipWindow = NULL; + UnregisterWarningWindowClass(); + } +} + +void AwtWindow::DestroyHWnd() +{ + DestroyWarningWindow(); + AwtCanvas::DestroyHWnd(); +} + +LPCTSTR AwtWindow::GetWarningWindowClassName() +{ + return TEXT("SunAwtWarningWindow"); +} + +void AwtWindow::FillWarningWindowClassInfo(WNDCLASS *lpwc) +{ + lpwc->style = 0L; + lpwc->lpfnWndProc = (WNDPROC)WarningWindowProc; + lpwc->cbClsExtra = 0; + lpwc->cbWndExtra = 0; + lpwc->hInstance = AwtToolkit::GetInstance().GetModuleHandle(), + lpwc->hIcon = AwtToolkit::GetInstance().GetAwtIcon(); + lpwc->hCursor = ::LoadCursor(NULL, IDC_ARROW); + lpwc->hbrBackground = NULL; + lpwc->lpszMenuName = NULL; + lpwc->lpszClassName = AwtWindow::GetWarningWindowClassName(); +} + +void AwtWindow::RegisterWarningWindowClass() +{ + WNDCLASS wc; + + ::ZeroMemory(&wc, sizeof(wc)); + + if (!::GetClassInfo(AwtToolkit::GetInstance().GetModuleHandle(), + AwtWindow::GetWarningWindowClassName(), &wc)) + { + AwtWindow::FillWarningWindowClassInfo(&wc); + ATOM atom = ::RegisterClass(&wc); + DASSERT(atom != 0); + } +} + +void AwtWindow::UnregisterWarningWindowClass() +{ + ::UnregisterClass(AwtWindow::GetWarningWindowClassName(), AwtToolkit::GetInstance().GetModuleHandle()); +} + +HICON AwtWindow::GetSecurityWarningIcon() +{ + HICON ico = AwtToolkit::GetInstance().GetSecurityWarningIcon(securityWarningAnimationStage, + warningWindowWidth, warningWindowHeight); + return ico; +} + +// This function calculates the bounds of the warning window and stores them +// into the RECT structure pointed by the argument rect. +void AwtWindow::CalculateWarningWindowBounds(JNIEnv *env, LPRECT rect) +{ + RECT windowBounds; + AwtToolkit::GetWindowRect(GetHWnd(), &windowBounds); + + jobject target = GetTarget(env); + jobject point2D = env->CallObjectMethod(target, + calculateSecurityWarningPositionMID, + (jdouble)windowBounds.left, (jdouble)windowBounds.top, + (jdouble)(windowBounds.right - windowBounds.left), + (jdouble)(windowBounds.bottom - windowBounds.top)); + env->DeleteLocalRef(target); + + static jclass point2DClassID = NULL; + static jmethodID point2DGetXMID = NULL; + static jmethodID point2DGetYMID = NULL; + + if (point2DClassID == NULL) { + jclass point2DClassIDLocal = env->FindClass("java/awt/geom/Point2D"); + point2DClassID = (jclass)env->NewGlobalRef(point2DClassIDLocal); + env->DeleteLocalRef(point2DClassIDLocal); + } + + if (point2DGetXMID == NULL) { + point2DGetXMID = env->GetMethodID(point2DClassID, "getX", "()D"); + } + if (point2DGetYMID == NULL) { + point2DGetYMID = env->GetMethodID(point2DClassID, "getY", "()D"); + } + + + int x = (int)env->CallDoubleMethod(point2D, point2DGetXMID); + int y = (int)env->CallDoubleMethod(point2D, point2DGetYMID); + + env->DeleteLocalRef(point2D); + + //Make sure the warning is not far from the window bounds + x = max(x, windowBounds.left - (int)warningWindowWidth - 2); + x = min(x, windowBounds.right + (int)warningWindowWidth + 2); + + y = max(y, windowBounds.top - (int)warningWindowHeight - 2); + y = min(y, windowBounds.bottom + (int)warningWindowHeight + 2); + + // Now make sure the warning window is visible on the screen + HMONITOR hmon = MonitorFromWindow(GetHWnd(), MONITOR_DEFAULTTOPRIMARY); + DASSERT(hmon != NULL); + + RECT monitorBounds; + RECT monitorInsets; + + MonitorBounds(hmon, &monitorBounds); + if (!AwtToolkit::GetScreenInsets(m_screenNum, &monitorInsets)) { + ::ZeroMemory(&monitorInsets, sizeof(monitorInsets)); + } + + x = max(x, monitorBounds.left + monitorInsets.left); + x = min(x, monitorBounds.right - monitorInsets.right - (int)warningWindowWidth); + + y = max(y, monitorBounds.top + monitorInsets.top); + y = min(y, monitorBounds.bottom - monitorInsets.bottom - (int)warningWindowHeight); + + rect->left = x; + rect->top = y; + rect->right = rect->left + warningWindowWidth; + rect->bottom = rect->top + warningWindowHeight; +} + +LRESULT CALLBACK AwtWindow::WarningWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_PAINT: + PaintWarningWindow(hwnd); + return 0; + + case WM_MOUSEACTIVATE: + { + // Retrive the owner of the warning window. + HWND javaWindow = ::GetParent(hwnd); + if (javaWindow) { + // If the window is blocked by a modal dialog, substitute + // its handle with the topmost blocker. + HWND topmostBlocker = GetTopmostModalBlocker(javaWindow); + if (::IsWindow(topmostBlocker)) { + javaWindow = topmostBlocker; + } + + ::BringWindowToTop(javaWindow); + + AwtWindow * window = + (AwtWindow*)AwtComponent::GetComponent(javaWindow); + if (window == NULL) { + // Quite unlikely to go into here, but it's way better + // than getting a crash. + ::SetForegroundWindow(javaWindow); + } else { + // Activate the window if it is focusable and inactive + if (window->IsFocusableWindow() && + javaWindow != ::GetActiveWindow()) { + ::SetForegroundWindow(javaWindow); + } else { + // ...otherwise just start the animation. + window->StartSecurityAnimation(akShow); + } + } + + // In every case if there's a top-most blocker, we need to + // enable modal animation. + if (::IsWindow(topmostBlocker)) { + AwtDialog::AnimateModalBlocker(topmostBlocker); + } + } + return MA_NOACTIVATEANDEAT; + } + } + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +void AwtWindow::PaintWarningWindow(HWND warningWindow) +{ + RECT updateRect; + + if (!::GetUpdateRect(warningWindow, &updateRect, FALSE)) { + // got nothing to update + return; + } + + PAINTSTRUCT ps; + HDC hdc = ::BeginPaint(warningWindow, &ps); + if (hdc == NULL) { + // indicates an error + return; + } + + PaintWarningWindow(warningWindow, hdc); + + ::EndPaint(warningWindow, &ps); +} + +void AwtWindow::PaintWarningWindow(HWND warningWindow, HDC hdc) +{ + HWND javaWindow = ::GetParent(warningWindow); + + AwtWindow * window = (AwtWindow*)AwtComponent::GetComponent(javaWindow); + if (window == NULL) { + return; + } + + ::DrawIconEx(hdc, 0, 0, window->GetSecurityWarningIcon(), + window->warningWindowWidth, window->warningWindowHeight, + 0, NULL, DI_NORMAL); +} + +static const UINT_PTR IDT_AWT_SECURITYANIMATION = 0x102; + +// Approximately 6 times a second. 0.75 seconds total. +static const UINT securityAnimationTimerElapse = 150; +static const UINT securityAnimationMaxIterations = 5; + +void AwtWindow::RepaintWarningWindow() +{ + HDC hdc = ::GetDC(warningWindow); + PaintWarningWindow(warningWindow, hdc); + ::ReleaseDC(warningWindow, hdc); +} + +void AwtWindow::StartSecurityAnimation(AnimationKind kind) +{ + if (!IsUntrusted()) { + return; + } + if (warningWindow == NULL) { + return; + } + + securityAnimationKind = kind; + + securityWarningAnimationStage = 1; + ::SetTimer(GetHWnd(), IDT_AWT_SECURITYANIMATION, + securityAnimationTimerElapse, NULL); + + if (securityAnimationKind == akShow) { + ::SetWindowPos(warningWindow, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | + SWP_SHOWWINDOW); + + ::SetLayeredWindowAttributes(warningWindow, RGB(0, 0, 0), + 0xFF, LWA_ALPHA); + ::RedrawWindow(warningWindow, NULL, NULL, + RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); + } +} + +void AwtWindow::StopSecurityAnimation() +{ + if (!IsUntrusted()) { + return; + } + if (warningWindow == NULL) { + return; + } + + securityWarningAnimationStage = 0; + ::KillTimer(GetHWnd(), IDT_AWT_SECURITYANIMATION); + + switch (securityAnimationKind) { + case akHide: + case akPreHide: + ::SetWindowPos(warningWindow, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | + SWP_HIDEWINDOW); + break; + case akShow: + RepaintWarningWindow(); + break; + } + + securityAnimationKind = akNone; +} + +MsgRouting AwtWindow::WmTimer(UINT_PTR timerID) +{ + if (timerID != IDT_AWT_SECURITYANIMATION) { + return mrPassAlong; + } + + if (securityWarningAnimationStage == 0) { + return mrConsume; + } + + securityWarningAnimationStage++; + if (securityWarningAnimationStage >= securityAnimationMaxIterations) { + if (securityAnimationKind == akPreHide) { + // chain real hiding + StartSecurityAnimation(akHide); + } else { + StopSecurityAnimation(); + } + } else { + switch (securityAnimationKind) { + case akHide: + { + BYTE opacity = ((int)0xFF * + (securityAnimationMaxIterations - + securityWarningAnimationStage)) / + securityAnimationMaxIterations; + ::SetLayeredWindowAttributes(warningWindow, + RGB(0, 0, 0), opacity, LWA_ALPHA); + } + break; + case akShow: + case akNone: // quite unlikely, but quite safe + RepaintWarningWindow(); + break; + } + } + + return mrConsume; +} + +// The security warning is visible if: +// 1. The window has the keyboard window focus, OR +// 2. The mouse pointer is located within the window bounds, +// or within the security warning icon. +void AwtWindow::UpdateSecurityWarningVisibility() +{ + if (!IsUntrusted()) { + return; + } + if (warningWindow == NULL) { + return; + } + + bool show = false; + + if (IsVisible() && currentWmSizeState != SIZE_MINIMIZED) { + if (AwtComponent::GetFocusedWindow() == GetHWnd()) { + show = true; + } + + HWND hwnd = AwtToolkit::GetInstance().GetWindowUnderMouse(); + if (hwnd == GetHWnd()) { + show = true; + } + if (hwnd == warningWindow) { + show = true; + } + } + + if (show && (!::IsWindowVisible(warningWindow) || + securityAnimationKind == akHide || + securityAnimationKind == akPreHide)) { + StartSecurityAnimation(akShow); + } + if (!show && ::IsWindowVisible(warningWindow)) { + StartSecurityAnimation(akPreHide); + } +} + +void AwtWindow::FocusedWindowChanged(HWND from, HWND to) +{ + AwtWindow * fw = (AwtWindow *)AwtComponent::GetComponent(from); + AwtWindow * tw = (AwtWindow *)AwtComponent::GetComponent(to); + + if (fw != NULL) { + fw->UpdateSecurityWarningVisibility(); + } + if (tw != NULL) { + tw->UpdateSecurityWarningVisibility(); + + // Flash on receiving the keyboard focus even if the warning + // has already been shown (e.g. by hovering with the mouse) + tw->StartSecurityAnimation(akShow); + } +} + +void AwtWindow::_RepositionSecurityWarning(void* param) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + RepositionSecurityWarningStruct *rsws = + (RepositionSecurityWarningStruct *)param; + jobject self = rsws->window; + + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + AwtWindow *window = (AwtWindow *)pData; + + window->RepositionSecurityWarning(env); + + ret: + env->DeleteGlobalRef(self); + delete rsws; +} + /* Create a new AwtWindow object and window. */ AwtWindow* AwtWindow::Create(jobject self, jobject parent) { @@ -372,7 +1036,7 @@ AwtWindow* AwtWindow::Create(jobject self, jobject parent) window->m_isRetainingHierarchyZOrder = TRUE; } DWORD style = WS_CLIPCHILDREN | WS_POPUP; - DWORD exStyle = 0; + DWORD exStyle = WS_EX_NOACTIVATE; if (GetRTL()) { exStyle |= WS_EX_RIGHT | WS_EX_LEFTSCROLLBAR; if (GetRTLReadingOrder()) @@ -620,23 +1284,6 @@ BOOL AwtWindow::UpdateInsets(jobject insets) ::GetClientRect(GetHWnd(), &inside); ::GetWindowRect(GetHWnd(), &outside); - jobject target = GetTarget(env); - jstring warningString = - (jstring)(env)->GetObjectField(target, AwtWindow::warningStringID); - if (warningString != NULL) { - ::CopyRect(&inside, &outside); - DefWindowProc(WM_NCCALCSIZE, FALSE, (LPARAM)&inside); - /* - * Fix for BugTraq ID 4304024. - * Calculate client rectangle in client coordinates. - */ - VERIFY(::OffsetRect(&inside, -inside.left, -inside.top)); - extraBottomInsets = ::GetSystemMetrics(SM_CYCAPTION) + - ((GetStyle() & WS_THICKFRAME) ? 2 : -2); - } - env->DeleteLocalRef(target); - env->DeleteLocalRef(warningString); - /* Update our inset member */ if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) { ::MapWindowPoints(GetHWnd(), 0, (LPPOINT)&inside, 2); @@ -863,45 +1510,93 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, env->DeleteLocalRef(event); } +BOOL AwtWindow::AwtSetActiveWindow(BOOL isMouseEventCause, UINT hittest) +{ + // Fix for 6458497. + // Retreat if current foreground window is out of both our and embedder process. + // The exception is when activation is requested due to a mouse event. + if (!isMouseEventCause) { + HWND fgWindow = ::GetForegroundWindow(); + if (NULL != fgWindow) { + DWORD fgProcessID; + ::GetWindowThreadProcessId(fgWindow, &fgProcessID); + if (fgProcessID != ::GetCurrentProcessId() + && !AwtToolkit::GetInstance().IsEmbedderProcessId(fgProcessID)) + { + return FALSE; + } + } + } + + HWND proxyContainerHWnd = GetProxyToplevelContainer(); + HWND proxyHWnd = GetProxyFocusOwner(); + + if (proxyContainerHWnd == NULL || proxyHWnd == NULL) { + return FALSE; + } + + // Activate the proxy toplevel container + if (::GetActiveWindow() != proxyContainerHWnd) { + sm_suppressFocusAndActivation = TRUE; + ::BringWindowToTop(proxyContainerHWnd); + ::SetForegroundWindow(proxyContainerHWnd); + sm_suppressFocusAndActivation = FALSE; + + if (::GetActiveWindow() != proxyContainerHWnd) { + return FALSE; // activation has been rejected + } + } + + // Focus the proxy itself + if (::GetFocus() != proxyHWnd) { + sm_suppressFocusAndActivation = TRUE; + ::SetFocus(proxyHWnd); + sm_suppressFocusAndActivation = FALSE; + + if (::GetFocus() != proxyHWnd) { + return FALSE; // focus has been rejected (that is unlikely) + } + } + + const HWND focusedWindow = AwtComponent::GetFocusedWindow(); + if (focusedWindow != GetHWnd()) { + if (focusedWindow != NULL) { + // Deactivate the old focused window + AwtWindow::SynthesizeWmActivate(FALSE, focusedWindow, GetHWnd()); + } + // Activate the new focused window. + AwtWindow::SynthesizeWmActivate(TRUE, GetHWnd(), focusedWindow); + } + return TRUE; +} + MsgRouting AwtWindow::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) { jint type; if (nState != WA_INACTIVE) { - ::SetFocus((sm_focusOwner == NULL || - AwtComponent::GetTopLevelParentForWindow(sm_focusOwner) != - GetHWnd()) ? NULL : sm_focusOwner); type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; - AwtToolkit::GetInstance(). - InvokeFunctionLater(BounceActivation, this); - sm_focusedWindow = GetHWnd(); + AwtComponent::SetFocusedWindow(GetHWnd()); } else { + // The owner is not necassarily getting WM_ACTIVATE(WA_INACTIVE). + // So, initiate retaining the actualFocusedWindow. + AwtFrame *owner = GetOwningFrameOrDialog(); + if (owner) { + owner->CheckRetainActualFocusedWindow(opposite); + } + if (m_grabbedWindow != NULL && !m_grabbedWindow->IsOneOfOwnersOf(this)) { m_grabbedWindow->Ungrab(); } type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; - sm_focusedWindow = NULL; + AwtComponent::SetFocusedWindow(NULL); + sm_focusOwner = NULL; } SendWindowEvent(type, opposite); return mrConsume; } -void AwtWindow::BounceActivation(void *self) { - AwtWindow *wSelf = (AwtWindow *)self; - - if (::GetActiveWindow() == wSelf->GetHWnd()) { - AwtFrame *owner = wSelf->GetOwningFrameOrDialog(); - - if (owner != NULL) { - sm_suppressFocusAndActivation = TRUE; - ::SetActiveWindow(owner->GetHWnd()); - ::SetFocus(owner->GetProxyFocusOwner()); - sm_suppressFocusAndActivation = FALSE; - } - } -} - MsgRouting AwtWindow::WmCreate() { return mrDoDefault; @@ -925,17 +1620,20 @@ MsgRouting AwtWindow::WmShowWindow(BOOL show, UINT status) { /* * Original fix for 4810575. Modified for 6386592. - * If an owned window (not frame/dialog) gets disposed we should synthesize + * If a simple window gets disposed we should synthesize * WM_ACTIVATE for its nearest owner. This is not performed by default because * the owner frame/dialog is natively active. */ HWND hwndSelf = GetHWnd(); - HWND hwndParent = ::GetParent(hwndSelf); + HWND hwndOwner = ::GetParent(hwndSelf); - if (!show && IsSimpleWindow() && hwndSelf == sm_focusedWindow && - hwndParent != NULL && ::IsWindowVisible(hwndParent)) + if (!show && IsSimpleWindow() && hwndSelf == AwtComponent::GetFocusedWindow() && + hwndOwner != NULL && ::IsWindowVisible(hwndOwner)) { - ::PostMessage(hwndParent, WM_ACTIVATE, (WPARAM)WA_ACTIVE, (LPARAM)hwndSelf); + AwtFrame *owner = (AwtFrame*)AwtComponent::GetComponent(hwndOwner); + if (owner != NULL) { + owner->AwtSetActiveWindow(); + } } //Fixed 4842599: REGRESSION: JPopupMenu not Hidden Properly After Iconified and Deiconified @@ -1034,7 +1732,10 @@ MsgRouting AwtWindow::WmSizing() */ MsgRouting AwtWindow::WmSize(UINT type, int w, int h) { + currentWmSizeState = type; + if (type == SIZE_MINIMIZED) { + UpdateSecurityWarningVisibility(); return mrDoDefault; } @@ -1098,103 +1799,18 @@ MsgRouting AwtWindow::WmNcCalcSize(BOOL fCalcValidRects, if (env->EnsureLocalCapacity(2) < 0) { return mrConsume; } - jobject target = GetTarget(env); - jstring warningString = - (jstring)(env)->GetObjectField(target, AwtWindow::warningStringID); - if (warningString != NULL) { - RECT r; - ::CopyRect(&r, &lpncsp->rgrc[0]); - retVal = static_cast<UINT>(DefWindowProc(WM_NCCALCSIZE, fCalcValidRects, - reinterpret_cast<LPARAM>(lpncsp))); - - /* Adjust non-client area for warning banner space. */ - m_warningRect.left = lpncsp->rgrc[0].left; - m_warningRect.right = lpncsp->rgrc[0].right; - m_warningRect.bottom = lpncsp->rgrc[0].bottom; - m_warningRect.top = - m_warningRect.bottom - ::GetSystemMetrics(SM_CYCAPTION); - if (GetStyle() & WS_THICKFRAME) { - m_warningRect.top -= 2; - } else { - m_warningRect.top += 2; - } - - lpncsp->rgrc[0].bottom = (m_warningRect.top >= lpncsp->rgrc[0].top) - ? m_warningRect.top - : lpncsp->rgrc[0].top; - - /* Convert to window-relative coordinates. */ - ::OffsetRect(&m_warningRect, -r.left, -r.top); - - /* Notify target of Insets change. */ - if (HasValidRect()) { - UpdateInsets(NULL); - } - - mrRetVal = mrConsume; - } else { - // WM_NCCALCSIZE is usually in response to a resize, but - // also can be triggered by SetWindowPos(SWP_FRAMECHANGED), - // which means the insets will have changed - rnk 4/7/1998 - retVal = static_cast<UINT>(DefWindowProc( - WM_NCCALCSIZE, fCalcValidRects, reinterpret_cast<LPARAM>(lpncsp))); - if (HasValidRect()) { - UpdateInsets(NULL); - } - mrRetVal = mrConsume; + // WM_NCCALCSIZE is usually in response to a resize, but + // also can be triggered by SetWindowPos(SWP_FRAMECHANGED), + // which means the insets will have changed - rnk 4/7/1998 + retVal = static_cast<UINT>(DefWindowProc( + WM_NCCALCSIZE, fCalcValidRects, reinterpret_cast<LPARAM>(lpncsp))); + if (HasValidRect()) { + UpdateInsets(NULL); } - env->DeleteLocalRef(target); - env->DeleteLocalRef(warningString); + mrRetVal = mrConsume; return mrRetVal; } -MsgRouting AwtWindow::WmNcPaint(HRGN hrgn) -{ - DefWindowProc(WM_NCPAINT, (WPARAM)hrgn, 0); - - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - if (env->EnsureLocalCapacity(2) < 0) { - return mrConsume; - } - jobject target = GetTarget(env); - jstring warningString = - (jstring)(env)->GetObjectField(target, AwtWindow::warningStringID); - if (warningString != NULL) { - RECT r; - ::CopyRect(&r, &m_warningRect); - HDC hDC = ::GetWindowDC(GetHWnd()); - DASSERT(hDC); - int iSaveDC = ::SaveDC(hDC); - VERIFY(::SelectClipRgn(hDC, NULL) != NULL); - VERIFY(::FillRect(hDC, &m_warningRect, (HBRUSH)::GetStockObject(BLACK_BRUSH))); - - if (GetStyle() & WS_THICKFRAME) { - /* draw edge */ - VERIFY(::DrawEdge(hDC, &r, EDGE_RAISED, BF_TOP)); - r.top += 2; - VERIFY(::DrawEdge(hDC, &r, EDGE_SUNKEN, BF_RECT)); - ::InflateRect(&r, -2, -2); - } - - /* draw warning text */ - LPCWSTR text = JNU_GetStringPlatformChars(env, warningString, NULL); - VERIFY(::SetBkColor(hDC, ::GetSysColor(COLOR_BTNFACE)) != CLR_INVALID); - VERIFY(::SetTextColor(hDC, ::GetSysColor(COLOR_BTNTEXT)) != CLR_INVALID); - VERIFY(::SelectObject(hDC, ::GetStockObject(DEFAULT_GUI_FONT)) != NULL); - VERIFY(::SetTextAlign(hDC, TA_LEFT | TA_BOTTOM) != GDI_ERROR); - VERIFY(::ExtTextOut(hDC, r.left+2, r.bottom-1, - ETO_CLIPPED | ETO_OPAQUE, - &r, text, static_cast<UINT>(wcslen(text)), NULL)); - VERIFY(::RestoreDC(hDC, iSaveDC)); - ::ReleaseDC(GetHWnd(), hDC); - JNU_ReleaseStringPlatformChars(env, warningString, text); - } - - env->DeleteLocalRef(target); - env->DeleteLocalRef(warningString); - return mrConsume; -} - MsgRouting AwtWindow::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) { // If this window is blocked by modal dialog, return HTCLIENT for any point of it. @@ -1420,6 +2036,19 @@ void AwtWindow::SetAndActivateModalBlocker(HWND window, HWND blocker) { } } +HWND AwtWindow::GetTopmostModalBlocker(HWND window) +{ + HWND ret, blocker = NULL; + + do { + ret = blocker; + blocker = AwtWindow::GetModalBlocker(window); + window = blocker; + } while (::IsWindow(blocker)); + + return ret; +} + void AwtWindow::FlashWindowEx(HWND hWnd, UINT count, DWORD timeout, DWORD flags) { FLASHWINFO fi; fi.cbSize = sizeof(fi); @@ -1430,6 +2059,38 @@ void AwtWindow::FlashWindowEx(HWND hWnd, UINT count, DWORD timeout, DWORD flags) ::FlashWindowEx(&fi); } +jboolean +AwtWindow::_RequestWindowFocus(void *param) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + RequestWindowFocusStruct *rfs = (RequestWindowFocusStruct *)param; + jobject self = rfs->component; + jboolean isMouseEventCause = rfs->isMouseEventCause; + + jboolean result = JNI_FALSE; + AwtWindow *window = NULL; + + PDATA pData; + JNI_CHECK_NULL_GOTO(self, "peer", ret); + pData = JNI_GET_PDATA(self); + if (pData == NULL) { + // do nothing just return false + goto ret; + } + + window = (AwtWindow *)pData; + if (::IsWindow(window->GetHWnd())) { + result = (jboolean)window->SendMessage(WM_AWT_WINDOW_SETACTIVE, (WPARAM)isMouseEventCause, 0); + } +ret: + env->DeleteGlobalRef(self); + + delete rfs; + + return result; +} + void AwtWindow::_ToFront(void *param) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -1839,6 +2500,216 @@ void AwtWindow::DoUpdateIcon() //Does nothing for windows, is overriden for frames and dialogs } +void AwtWindow::RedrawWindow() +{ + if (isOpaque()) { + ::RedrawWindow(GetHWnd(), NULL, NULL, + RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); + } else { + ::EnterCriticalSection(&contentBitmapCS); + if (hContentBitmap != NULL) { + UpdateWindowImpl(contentWidth, contentHeight, hContentBitmap); + } + ::LeaveCriticalSection(&contentBitmapCS); + } +} + +void AwtWindow::SetTranslucency(BYTE opacity, BOOL opaque) +{ + BYTE old_opacity = getOpacity(); + BOOL old_opaque = isOpaque(); + + if (opacity == old_opacity && opaque == old_opaque) { + return; + } + + setOpacity(opacity); + setOpaque(opaque); + + HWND hwnd = GetHWnd(); + + LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); + + if (opaque != old_opaque) { + ::EnterCriticalSection(&contentBitmapCS); + if (hContentBitmap != NULL) { + ::DeleteObject(hContentBitmap); + hContentBitmap = NULL; + } + ::LeaveCriticalSection(&contentBitmapCS); + } + + if (opaque && opacity == 0xff) { + // Turn off all the effects + ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style & ~WS_EX_LAYERED); + // Ask the window to repaint itself and all the children + RedrawWindow(); + } else { + // We're going to enable some effects + if (!(ex_style & WS_EX_LAYERED)) { + ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED); + } else { + if ((opaque && opacity < 0xff) ^ (old_opaque && old_opacity < 0xff)) { + // _One_ of the modes uses the SetLayeredWindowAttributes. + // Need to reset the style in this case. + // If both modes are simple (i.e. just changing the opacity level), + // no need to reset the style. + ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style & ~WS_EX_LAYERED); + ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED); + } + } + + if (opaque) { + // Simple opacity mode + ::SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), opacity, LWA_ALPHA); + } + } +} + +static HBITMAP CreateBitmapFromRaster(JNIEnv* env, jintArray raster, jint w, jint h) +{ + HBITMAP image = NULL; + if (raster != NULL) { + int* rasterBuffer = NULL; + try { + rasterBuffer = (int *)env->GetPrimitiveArrayCritical(raster, 0); + JNI_CHECK_NULL_GOTO(rasterBuffer, "raster data", done); + image = BitmapUtil::CreateBitmapFromARGBPre(w, h, w*4, rasterBuffer); + } catch (...) { + if (rasterBuffer != NULL) { + env->ReleasePrimitiveArrayCritical(raster, rasterBuffer, 0); + } + throw; + } + if (rasterBuffer != NULL) { + env->ReleasePrimitiveArrayCritical(raster, rasterBuffer, 0); + } + } +done: + return image; +} + +void AwtWindow::UpdateWindowImpl(int width, int height, HBITMAP hBitmap) +{ + if (isOpaque()) { + return; + } + + HWND hWnd = GetHWnd(); + HDC hdcDst = ::GetDC(NULL); + HDC hdcSrc = ::CreateCompatibleDC(NULL); + HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hdcSrc, hBitmap); + + //XXX: this code doesn't paint the children (say, the java.awt.Button)! + //So, if we ever want to support HWs here, we need to repaint them + //in some other way... + //::SendMessage(hWnd, WM_PRINT, (WPARAM)hdcSrc, /*PRF_CHECKVISIBLE |*/ + // PRF_CHILDREN /*| PRF_CLIENT | PRF_NONCLIENT*/); + + POINT ptSrc; + ptSrc.x = ptSrc.y = 0; + + RECT rect; + POINT ptDst; + SIZE size; + + ::GetWindowRect(hWnd, &rect); + ptDst.x = rect.left; + ptDst.y = rect.top; + size.cx = width; + size.cy = height; + + BLENDFUNCTION bf; + + bf.SourceConstantAlpha = getOpacity(); + bf.AlphaFormat = AC_SRC_ALPHA; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + + ::UpdateLayeredWindow(hWnd, hdcDst, &ptDst, &size, hdcSrc, &ptSrc, + RGB(0, 0, 0), &bf, ULW_ALPHA); + + ::ReleaseDC(NULL, hdcDst); + ::SelectObject(hdcSrc, hOldBitmap); + ::DeleteDC(hdcSrc); +} + +void AwtWindow::UpdateWindow(JNIEnv* env, jintArray data, int width, int height, + HBITMAP hNewBitmap) +{ + if (isOpaque()) { + return; + } + + HBITMAP hBitmap; + if (hNewBitmap == NULL) { + if (data == NULL) { + return; + } + hBitmap = CreateBitmapFromRaster(env, data, width, height); + if (hBitmap == NULL) { + return; + } + } else { + hBitmap = hNewBitmap; + } + + ::EnterCriticalSection(&contentBitmapCS); + if (hContentBitmap != NULL) { + ::DeleteObject(hContentBitmap); + } + hContentBitmap = hBitmap; + contentWidth = width; + contentHeight = height; + UpdateWindowImpl(width, height, hBitmap); + ::LeaveCriticalSection(&contentBitmapCS); +} + +void AwtWindow::FillBackground(HDC hMemoryDC, SIZE &size) +{ + if (isOpaque()) { + AwtCanvas::FillBackground(hMemoryDC, size); + } +} + +void AwtWindow::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha) +{ + if (isOpaque()) { + AwtCanvas::FillAlpha(bitmapBits, size, alpha); + } +} + +/* + * Fixed 6353381: it's improved fix for 4792958 + * which was backed-out to avoid 5059656 + */ +BOOL AwtWindow::HasValidRect() +{ + RECT inside; + RECT outside; + + if (::IsIconic(GetHWnd())) { + return FALSE; + } + + ::GetClientRect(GetHWnd(), &inside); + ::GetWindowRect(GetHWnd(), &outside); + + BOOL isZeroClientArea = (inside.right == 0 && inside.bottom == 0); + BOOL isInvalidLocation = ((outside.left == -32000 && outside.top == -32000) || // Win2k && WinXP + (outside.left == 32000 && outside.top == 32000) || // Win95 && Win98 + (outside.left == 3000 && outside.top == 3000)); // Win95 && Win98 + + // the bounds correspond to iconic state + if (isZeroClientArea && isInvalidLocation) + { + return FALSE; + } + + return TRUE; +} + + void AwtWindow::_SetIconImagesData(void * param) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -1940,11 +2811,14 @@ void AwtWindow::_SetFocusableWindow(void *param) window->m_isFocusableWindow = isFocusableWindow; - if (!window->m_isFocusableWindow) { - LONG isPopup = window->GetStyle() & WS_POPUP; - window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | AWT_WS_EX_NOACTIVATE); - } else { - window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~AWT_WS_EX_NOACTIVATE); + // A simple window is permanently set to WS_EX_NOACTIVATE + if (!window->IsSimpleWindow()) { + if (!window->m_isFocusableWindow) { + LONG isPopup = window->GetStyle() & WS_POPUP; + window->SetStyleEx(window->GetStyleEx() | (isPopup ? 0 : WS_EX_APPWINDOW) | WS_EX_NOACTIVATE); + } else { + window->SetStyleEx(window->GetStyleEx() & ~WS_EX_APPWINDOW & ~WS_EX_NOACTIVATE); + } } ret: @@ -2009,36 +2883,68 @@ void AwtWindow::_ModalEnable(void *param) env->DeleteGlobalRef(self); } -/* - * Fixed 6353381: it's improved fix for 4792958 - * which was backed-out to avoid 5059656 - */ -BOOL AwtWindow::HasValidRect() +void AwtWindow::_SetOpacity(void* param) { - RECT inside; - RECT outside; + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - if (::IsIconic(GetHWnd())) { - return FALSE; - } + OpacityStruct *os = (OpacityStruct *)param; + jobject self = os->window; + BYTE iOpacity = (BYTE)os->iOpacity; - ::GetClientRect(GetHWnd(), &inside); - ::GetWindowRect(GetHWnd(), &outside); + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + AwtWindow *window = (AwtWindow *)pData; - BOOL isZeroClientArea = (inside.right == 0 && inside.bottom == 0); - BOOL isInvalidLocation = ((outside.left == -32000 && outside.top == -32000) || // Win2k && WinXP - (outside.left == 32000 && outside.top == 32000) || // Win95 && Win98 - (outside.left == 3000 && outside.top == 3000)); // Win95 && Win98 + window->SetTranslucency(iOpacity, window->isOpaque()); - // the bounds correspond to iconic state - if (isZeroClientArea && isInvalidLocation) - { - return FALSE; - } + ret: + env->DeleteGlobalRef(self); + delete os; +} - return TRUE; +void AwtWindow::_SetOpaque(void* param) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + OpaqueStruct *os = (OpaqueStruct *)param; + jobject self = os->window; + BOOL isOpaque = (BOOL)os->isOpaque; + + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + AwtWindow *window = (AwtWindow *)pData; + + window->SetTranslucency(window->getOpacity(), isOpaque); + + ret: + env->DeleteGlobalRef(self); + delete os; +} + +void AwtWindow::_UpdateWindow(void* param) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + UpdateWindowStruct *uws = (UpdateWindowStruct *)param; + jobject self = uws->window; + jintArray data = uws->data; + + PDATA pData; + JNI_CHECK_PEER_GOTO(self, ret); + AwtWindow *window = (AwtWindow *)pData; + + window->UpdateWindow(env, data, (int)uws->width, (int)uws->height, + uws->hBitmap); + + ret: + env->DeleteGlobalRef(self); + if (data != NULL) { + env->DeleteGlobalRef(data); + } + delete uws; } + extern "C" { /* @@ -2055,8 +2961,16 @@ Java_java_awt_Window_initIDs(JNIEnv *env, jclass cls) env->GetFieldID(cls, "warningString", "Ljava/lang/String;"); AwtWindow::locationByPlatformID = env->GetFieldID(cls, "locationByPlatform", "Z"); + AwtWindow::securityWarningWidthID = + env->GetFieldID(cls, "securityWarningWidth", "I"); + AwtWindow::securityWarningHeightID = + env->GetFieldID(cls, "securityWarningHeight", "I"); + AwtWindow::getWarningStringMID = + env->GetMethodID(cls, "getWarningString", "()Ljava/lang/String;"); AwtWindow::autoRequestFocusID = env->GetFieldID(cls, "autoRequestFocus", "Z"); + AwtWindow::calculateSecurityWarningPositionMID = + env->GetMethodID(cls, "calculateSecurityWarningPosition", "(DDDD)Ljava/awt/geom/Point2D;"); CATCH_BAD_ALLOC; } @@ -2489,4 +3403,138 @@ Java_sun_awt_windows_WWindowPeer_nativeUngrab(JNIEnv *env, jobject self) CATCH_BAD_ALLOC; } +/* + * Class: sun_awt_windows_WWindowPeer + * Method: setOpacity + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WWindowPeer_setOpacity(JNIEnv *env, jobject self, + jint iOpacity) +{ + TRY; + + OpacityStruct *os = new OpacityStruct; + os->window = env->NewGlobalRef(self); + os->iOpacity = iOpacity; + + AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetOpacity, os); + // global refs and mds are deleted in _SetMinSize + + CATCH_BAD_ALLOC; +} + +/* + * Class: sun_awt_windows_WWindowPeer + * Method: setOpaqueImpl + * Signature: (Z)V + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WWindowPeer_setOpaqueImpl(JNIEnv *env, jobject self, + jboolean isOpaque) +{ + TRY; + + OpaqueStruct *os = new OpaqueStruct; + os->window = env->NewGlobalRef(self); + os->isOpaque = isOpaque; + + AwtToolkit::GetInstance().SyncCall(AwtWindow::_SetOpaque, os); + // global refs and mds are deleted in _SetMinSize + + CATCH_BAD_ALLOC; +} + +/* + * Class: sun_awt_windows_WWindowPeer + * Method: updateWindowImpl + * Signature: ([III)V + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WWindowPeer_updateWindowImpl(JNIEnv *env, jobject self, + jintArray data, + jint width, jint height) +{ + TRY; + + UpdateWindowStruct *uws = new UpdateWindowStruct; + uws->window = env->NewGlobalRef(self); + uws->data = (jintArray)env->NewGlobalRef(data); + uws->hBitmap = NULL; + uws->width = width; + uws->height = height; + + AwtToolkit::GetInstance().InvokeFunction(AwtWindow::_UpdateWindow, uws); + // global refs and mds are deleted in _UpdateWindow + + CATCH_BAD_ALLOC; +} + +/** + * This method is called from the WGL pipeline when it needs to update + * the layered window WindowPeer's C++ level object. + */ +void AwtWindow_UpdateWindow(JNIEnv *env, jobject peer, + jint width, jint height, HBITMAP hBitmap) +{ + TRY; + + UpdateWindowStruct *uws = new UpdateWindowStruct; + uws->window = env->NewGlobalRef(peer); + uws->data = NULL; + uws->hBitmap = hBitmap; + uws->width = width; + uws->height = height; + + AwtToolkit::GetInstance().InvokeFunction(AwtWindow::_UpdateWindow, uws); + // global refs and mds are deleted in _UpdateWindow + + CATCH_BAD_ALLOC; +} + +/* + * Class: sun_awt_windows_WComponentPeer + * Method: requestFocus + * Signature: (Z)Z + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WWindowPeer_requestWindowFocus + (JNIEnv *env, jobject self, jboolean isMouseEventCause) +{ + TRY; + + jobject selfGlobalRef = env->NewGlobalRef(self); + + RequestWindowFocusStruct *rfs = new RequestWindowFocusStruct; + rfs->component = selfGlobalRef; + rfs->isMouseEventCause = isMouseEventCause; + + return (jboolean)AwtToolkit::GetInstance().SyncCall( + (void*(*)(void*))AwtWindow::_RequestWindowFocus, rfs); + // global refs and rfs are deleted in _RequestWindowFocus + + CATCH_BAD_ALLOC_RET(JNI_FALSE); +} + +/* + * Class: sun_awt_windows_WWindowPeer + * Method: repositionSecurityWarning + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_sun_awt_windows_WWindowPeer_repositionSecurityWarning(JNIEnv *env, + jobject self) +{ + TRY; + + RepositionSecurityWarningStruct *rsws = + new RepositionSecurityWarningStruct; + rsws->window = env->NewGlobalRef(self); + + AwtToolkit::GetInstance().InvokeFunction( + AwtWindow::_RepositionSecurityWarning, rsws); + // global refs and mds are deleted in _RepositionSecurityWarning + + CATCH_BAD_ALLOC; +} + } /* extern "C" */ diff --git a/src/windows/native/sun/windows/awt_Window.h b/src/windows/native/sun/windows/awt_Window.h index 9a252a25c..bf43150a7 100644 --- a/src/windows/native/sun/windows/awt_Window.h +++ b/src/windows/native/sun/windows/awt_Window.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -34,14 +34,12 @@ // property name tagging windows disabled by modality static LPCTSTR ModalBlockerProp = TEXT("SunAwtModalBlockerProp"); static LPCTSTR ModalDialogPeerProp = TEXT("SunAwtModalDialogPeerProp"); +static LPCTSTR NativeDialogWndProcProp = TEXT("SunAwtNativeDialogWndProcProp"); #ifndef WH_MOUSE_LL #define WH_MOUSE_LL 14 #endif -// WS_EX_NOACTIVATE is not defined in the headers we build with -#define AWT_WS_EX_NOACTIVATE 0x08000000L - class AwtFrame; /************************************************************************ @@ -56,6 +54,8 @@ public: static jfieldID locationByPlatformID; static jfieldID screenID; /* screen number passed over from WindowPeer */ static jfieldID autoRequestFocusID; + static jfieldID securityWarningWidthID; + static jfieldID securityWarningHeightID; // The coordinates at the peer. static jfieldID sysXID; @@ -63,6 +63,9 @@ public: static jfieldID sysWID; static jfieldID sysHID; + static jmethodID getWarningStringMID; + static jmethodID calculateSecurityWarningPositionMID; + AwtWindow(); virtual ~AwtWindow(); @@ -152,11 +155,12 @@ public: static void SetModalBlocker(HWND window, HWND blocker); static void SetAndActivateModalBlocker(HWND window, HWND blocker); + static HWND GetTopmostModalBlocker(HWND window); + /* * Windows message handler functions */ virtual MsgRouting WmActivate(UINT nState, BOOL fMinimized, HWND opposite); - static void BounceActivation(void *self); // used by WmActivate virtual MsgRouting WmCreate(); virtual MsgRouting WmClose(); virtual MsgRouting WmDestroy(); @@ -169,19 +173,36 @@ public: virtual MsgRouting WmSettingChange(UINT wFlag, LPCTSTR pszSection); virtual MsgRouting WmNcCalcSize(BOOL fCalcValidRects, LPNCCALCSIZE_PARAMS lpncsp, LRESULT& retVal); - virtual MsgRouting WmNcPaint(HRGN hrgn); virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button); virtual MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal); virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); virtual MsgRouting WmWindowPosChanging(LPARAM windowPos); virtual MsgRouting WmWindowPosChanged(LPARAM windowPos); + virtual MsgRouting WmTimer(UINT_PTR timerID); virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic); virtual void WindowResized(); + static jboolean _RequestWindowFocus(void *param); + + virtual BOOL AwtSetActiveWindow(BOOL isMouseEventCause = FALSE, UINT hittest = HTCLIENT); + + // Execute on Toolkit only. + INLINE static LRESULT SynthesizeWmActivate(BOOL doActivate, HWND targetHWnd, HWND oppositeHWnd) { + if (::IsWindowVisible(targetHWnd)) { + return ::SendMessage(targetHWnd, WM_ACTIVATE, + MAKEWPARAM(doActivate ? WA_ACTIVE : WA_INACTIVE, FALSE), + (LPARAM) oppositeHWnd); + } + return 1; // if not processed + } + void moveToDefaultLocation(); /* moves Window to X,Y specified by Window Manger */ + void UpdateWindow(JNIEnv* env, jintArray data, int width, int height, + HBITMAP hNewBitmap = NULL); + INLINE virtual BOOL IsTopLevel() { return TRUE; } static AwtWindow * GetGrabbedWindow() { return m_grabbedWindow; } @@ -204,11 +225,25 @@ public: static void _SetModalExcludedNativeProp(void *param); static void _ModalDisable(void *param); static void _ModalEnable(void *param); + static void _SetOpacity(void* param); + static void _SetOpaque(void* param); + static void _UpdateWindow(void* param); + static void _RepositionSecurityWarning(void* param); inline static BOOL IsResizing() { return sm_resizing; } + virtual void CreateHWnd(JNIEnv *env, LPCWSTR title, + DWORD windowStyle, DWORD windowExStyle, + int x, int y, int w, int h, + HWND hWndParent, HMENU hMenu, + COLORREF colorForeground, COLORREF colorBackground, + jobject peer); + virtual void DestroyHWnd(); + + static void FocusedWindowChanged(HWND from, HWND to); + private: static int ms_instanceCounter; static HHOOK ms_hCBTFilter; @@ -228,6 +263,79 @@ private: // from its hierarchy when shown. Currently applied to instances of // javax/swing/Popup$HeavyWeightWindow class. + BYTE m_opacity; // The opacity level. == 0xff by default (when opacity mode is disabled) + BOOL m_opaque; // Whether the window uses the perpixel translucency (false), or not (true). + + inline BYTE getOpacity() { + return m_opacity; + } + inline void setOpacity(BYTE opacity) { + m_opacity = opacity; + } + + inline BOOL isOpaque() { + return m_opaque; + } + inline void setOpaque(BOOL opaque) { + m_opaque = opaque; + } + + CRITICAL_SECTION contentBitmapCS; + HBITMAP hContentBitmap; + UINT contentWidth; + UINT contentHeight; + + void SetTranslucency(BYTE opacity, BOOL opaque); + void UpdateWindow(int width, int height, HBITMAP hBitmap); + void UpdateWindowImpl(int width, int height, HBITMAP hBitmap); + void RedrawWindow(); + + static UINT untrustedWindowsCounter; + + WCHAR * warningString; + + // The warning icon + HWND warningWindow; + // The tooltip that appears when hovering the icon + HWND securityTooltipWindow; + + UINT warningWindowWidth; + UINT warningWindowHeight; + void InitSecurityWarningSize(JNIEnv *env); + HICON GetSecurityWarningIcon(); + + void CreateWarningWindow(JNIEnv *env); + void DestroyWarningWindow(); + static LPCTSTR GetWarningWindowClassName(); + void FillWarningWindowClassInfo(WNDCLASS *lpwc); + void RegisterWarningWindowClass(); + void UnregisterWarningWindowClass(); + static LRESULT CALLBACK WarningWindowProc( + HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + static void PaintWarningWindow(HWND warningWindow); + static void PaintWarningWindow(HWND warningWindow, HDC hdc); + void RepaintWarningWindow(); + void CalculateWarningWindowBounds(JNIEnv *env, LPRECT rect); + + void AnimateSecurityWarning(bool enable); + UINT securityWarningAnimationStage; + + enum AnimationKind { + akNone, akShow, akPreHide, akHide + }; + + AnimationKind securityAnimationKind; + + void StartSecurityAnimation(AnimationKind kind); + void StopSecurityAnimation(); + + void RepositionSecurityWarning(JNIEnv *env); + +public: + void UpdateSecurityWarningVisibility(); + static bool IsWarningWindow(HWND hWnd); + protected: BOOL m_isResizable; static AwtWindow* m_grabbedWindow; // Current grabbing window @@ -236,6 +344,16 @@ protected: BOOL m_iconInherited; /* TRUE if icon is inherited from the owner */ BOOL m_filterFocusAndActivation; /* Used in the WH_CBT hook */ + //These are used in AwtComponent::CreatePrintedPixels. They are overridden + //here to handle non-opaque windows. + virtual void FillBackground(HDC hMemoryDC, SIZE &size); + virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha); + + inline BOOL IsUntrusted() { + return warningString != NULL; + } + + UINT currentWmSizeState; private: int m_screenNum; diff --git a/src/windows/native/sun/windows/awtmsg.h b/src/windows/native/sun/windows/awtmsg.h index 35e436b53..8c0806219 100644 --- a/src/windows/native/sun/windows/awtmsg.h +++ b/src/windows/native/sun/windows/awtmsg.h @@ -1,5 +1,5 @@ /* - * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * 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 @@ -194,6 +194,7 @@ enum { WM_AWT_COMPONENT_SHOW, WM_AWT_COMPONENT_HIDE, WM_AWT_COMPONENT_SETFOCUS, + WM_AWT_WINDOW_SETACTIVE, WM_AWT_LIST_SETMULTISELECT, WM_AWT_HANDLE_EVENT, WM_AWT_PRINT_COMPONENT, diff --git a/src/windows/native/sun/windows/security_warning.ico b/src/windows/native/sun/windows/security_warning.ico Binary files differnew file mode 100644 index 000000000..67793ed82 --- /dev/null +++ b/src/windows/native/sun/windows/security_warning.ico diff --git a/src/windows/native/sun/windows/security_warning_bw.ico b/src/windows/native/sun/windows/security_warning_bw.ico Binary files differnew file mode 100644 index 000000000..68a1824a2 --- /dev/null +++ b/src/windows/native/sun/windows/security_warning_bw.ico diff --git a/src/windows/native/sun/windows/security_warning_int.ico b/src/windows/native/sun/windows/security_warning_int.ico Binary files differnew file mode 100644 index 000000000..d773dca9e --- /dev/null +++ b/src/windows/native/sun/windows/security_warning_int.ico |