提交 48fbfa54 编写于 作者: A anthony

6693253: Security Warning appearance requires enhancements

6779717: A Window does not show applet security warning icon on X platforms
6785058: Parent dn't get the focus after dialog is closed if security warning is applied
Summary: Forward-port from 6u10-6u14
Reviewed-by: art, dcherepanov
上级 f410e946
...@@ -71,6 +71,7 @@ STUBFILES = \ ...@@ -71,6 +71,7 @@ STUBFILES = \
$(STUBDIR)/Ole2.h \ $(STUBDIR)/Ole2.h \
$(STUBDIR)/Zmouse.h \ $(STUBDIR)/Zmouse.h \
$(STUBDIR)/cderr.h \ $(STUBDIR)/cderr.h \
$(STUBDIR)/commctrl.h \
$(STUBDIR)/commdlg.h \ $(STUBDIR)/commdlg.h \
$(STUBDIR)/direct.h \ $(STUBDIR)/direct.h \
$(STUBDIR)/d3dcom.h \ $(STUBDIR)/d3dcom.h \
......
...@@ -200,5 +200,6 @@ FILES_cpp = \ ...@@ -200,5 +200,6 @@ FILES_cpp = \
ShellFolder2.cpp \ ShellFolder2.cpp \
ThemeReader.cpp \ ThemeReader.cpp \
ComCtl32Util.cpp \ ComCtl32Util.cpp \
DllUtil.cpp \
initIDs.cpp \ initIDs.cpp \
MouseInfo.cpp MouseInfo.cpp
...@@ -6,11 +6,9 @@ runtime, it will probably work with other versions of that compiler. ...@@ -6,11 +6,9 @@ runtime, it will probably work with other versions of that compiler.
Included in this project is a generated file, make.depend, which lists Included in this project is a generated file, make.depend, which lists
all interdependencies of the source files. This file is generated *on all interdependencies of the source files. This file is generated *on
Solaris* with the following commands: Solaris or Linux* with the following command:
% sccs edit make.depend
% gnumake -f Depend.mak % gnumake -f Depend.mak
% sccs delget make.depend
This step only needs to be run when new files are added to the project, This step only needs to be run when new files are added to the project,
or include statements are changed. or include statements are changed.
......
此差异已折叠。
...@@ -78,4 +78,5 @@ FILES_c = \ ...@@ -78,4 +78,5 @@ FILES_c = \
awt_Plugin.c \ awt_Plugin.c \
gtk2_interface.c \ gtk2_interface.c \
swing_GTKEngine.c \ swing_GTKEngine.c \
swing_GTKStyle.c swing_GTKStyle.c \
rect.c
...@@ -79,6 +79,7 @@ vpath %.c $(SHARE_SRC)/native/sun/java2d ...@@ -79,6 +79,7 @@ vpath %.c $(SHARE_SRC)/native/sun/java2d
vpath %.c $(SHARE_SRC)/native/sun/java2d/loops vpath %.c $(SHARE_SRC)/native/sun/java2d/loops
vpath %.c $(SHARE_SRC)/native/sun/java2d/pipe vpath %.c $(SHARE_SRC)/native/sun/java2d/pipe
vpath %.c $(SHARE_SRC)/native/sun/awt/medialib vpath %.c $(SHARE_SRC)/native/sun/awt/medialib
vpath %.c $(SHARE_SRC)/native/sun/awt/utility
vpath %.cpp $(SHARE_SRC)/native/sun/image vpath %.cpp $(SHARE_SRC)/native/sun/image
vpath %.c $(SHARE_SRC)/native/sun/font vpath %.c $(SHARE_SRC)/native/sun/font
vpath %.c $(PLATFORM_SRC)/native/sun/awt/robot_child vpath %.c $(PLATFORM_SRC)/native/sun/awt/robot_child
...@@ -274,6 +275,23 @@ ICONS = \ ...@@ -274,6 +275,23 @@ ICONS = \
$(ICONS_PATH_PREFIX)/classes/sun/awt/X11/java-icon32.png \ $(ICONS_PATH_PREFIX)/classes/sun/awt/X11/java-icon32.png \
$(ICONS_PATH_PREFIX)/classes/sun/awt/X11/java-icon48.png $(ICONS_PATH_PREFIX)/classes/sun/awt/X11/java-icon48.png
ICONPATH=$(PLATFORM_SRC)/classes/sun/awt/X11
ICONS += \
$(ICONPATH)/security-icon-bw16.png \
$(ICONPATH)/security-icon-interim16.png \
$(ICONPATH)/security-icon-yellow16.png \
$(ICONPATH)/security-icon-bw24.png \
$(ICONPATH)/security-icon-interim24.png \
$(ICONPATH)/security-icon-yellow24.png \
$(ICONPATH)/security-icon-bw32.png \
$(ICONPATH)/security-icon-interim32.png \
$(ICONPATH)/security-icon-yellow32.png \
$(ICONPATH)/security-icon-bw48.png \
$(ICONPATH)/security-icon-interim48.png \
$(ICONPATH)/security-icon-yellow48.png
TEMPDIR_CLASSES = $(TEMPDIR)/classes TEMPDIR_CLASSES = $(TEMPDIR)/classes
$(TEMPDIR_CLASSES)/sun/awt/X11/ToBin.class: ToBin.java $(TEMPDIR_CLASSES)/sun/awt/X11/ToBin.class: ToBin.java
......
...@@ -93,6 +93,8 @@ SUNWprivate_1.1 { ...@@ -93,6 +93,8 @@ SUNWprivate_1.1 {
Java_sun_awt_X11_XlibWrapper_XGetWMHints; Java_sun_awt_X11_XlibWrapper_XGetWMHints;
Java_sun_awt_X11_XlibWrapper_XShapeQueryExtension; Java_sun_awt_X11_XlibWrapper_XShapeQueryExtension;
Java_sun_awt_X11_XlibWrapper_SetRectangularShape; Java_sun_awt_X11_XlibWrapper_SetRectangularShape;
Java_sun_awt_X11_XlibWrapper_SetBitmapShape;
Java_sun_awt_X11_XlibWrapper_XConfigureWindow;
Java_sun_awt_X11_XlibWrapper_SetZOrder; Java_sun_awt_X11_XlibWrapper_SetZOrder;
Java_sun_awt_X11_XToolkit_initIDs; Java_sun_awt_X11_XToolkit_initIDs;
Java_sun_awt_X11_XWindow_getNativeColor; Java_sun_awt_X11_XWindow_getNativeColor;
......
/*
* 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 com.sun.awt;
import java.awt.*;
import java.awt.geom.*;
import sun.awt.AWTAccessor;
/**
* Security Warning control interface.
*
* This class provides a couple of methods that help a developer relocate
* the AWT security warning to an appropriate position relative to the current
* window size. A "top-level window" is an instance of the {@code Window}
* class (or its descendant, such as {@code JFrame}). The security warning
* is applied to all windows created by an untrusted code. All such windows
* have a non-null "warning string" (see {@link Window#getWarningString()}).
* <p>
* <b>WARNING</b>: This class is an implementation detail and only meant
* for limited use outside of the core platform. This API may change
* drastically between update release, and it may even be
* removed or be moved to some other packages or classes.
*/
public final class SecurityWarning {
/**
* The SecurityWarning class should not be instantiated
*/
private SecurityWarning() {
}
/**
* Gets the size of the security warning.
*
* The returned value is not valid until the peer has been created. Before
* invoking this method a developer must call the {@link Window#pack()},
* {@link Window#setVisible()}, or some other method that creates the peer.
*
* @param window the window to get the security warning size for
*
* @throws NullPointerException if the window argument is null
* @throws IllegalArgumentException if the window is trusted (i.e.
* the {@code getWarningString()} returns null)
*/
public static Dimension getSize(Window window) {
if (window == null) {
throw new NullPointerException(
"The window argument should not be null.");
}
if (window.getWarningString() == null) {
throw new IllegalArgumentException(
"The window must have a non-null warning string.");
}
// We don't check for a non-null peer since it may be destroyed
// after assigning a valid value to the security warning size.
return AWTAccessor.getWindowAccessor().getSecurityWarningSize(window);
}
/**
* Sets the position of the security warning.
* <p>
* The {@code alignmentX} and {@code alignmentY} arguments specify the
* origin of the coordinate system used to calculate the position of the
* security warning. The values must be in the range [0.0f...1.0f]. The
* {@code 0.0f} value represents the left (top) edge of the rectangular
* bounds of the window. The {@code 1.0f} value represents the right
* (bottom) edge of the bounds. Whenever the size of the window changes,
* the origin of the coordinate system gets relocated accordingly. For
* convenience a developer may use the {@code Component.*_ALIGNMENT}
* constants to pass predefined values for these arguments.
* <p>
* The {@code point} argument specifies the location of the security
* warning in the coordinate system described above. If both {@code x} and
* {@code y} coordinates of the point are equal to zero, the warning will
* be located right in the origin of the coordinate system. On the other
* hand, if both {@code alignmentX} and {@code alignmentY} are equal to
* zero (i.e. the origin of the coordinate system is placed at the top-left
* corner of the window), then the {@code point} argument represents the
* absolute location of the security warning relative to the location of
* the window. The "absolute" in this case means that the position of the
* security warning is not effected by resizing of the window.
* <p>
* Note that the security warning managment code guarantees that:
* <ul>
* <li>The security warning cannot be located farther than two pixels from
* the rectangular bounds of the window (see {@link Window#getBounds}), and
* <li>The security warning is always visible on the screen.
* </ul>
* If either of the conditions is violated, the calculated position of the
* security warning is adjusted by the system to meet both these
* conditions.
* <p>
* The default position of the security warning is in the upper-right
* corner of the window, two pixels to the right from the right edge. This
* corresponds to the following arguments passed to this method:
* <ul>
* <li>{@code alignmentX = Component.RIGHT_ALIGNMENT}
* <li>{@code alignmentY = Component.TOP_ALIGNMENT}
* <li>{@code point = (2, 0)}
* </ul>
*
* @param window the window to set the position of the security warning for
* @param alignmentX the horizontal origin of the coordinate system
* @param alignmentY the vertical origin of the coordinate system
* @param point the position of the security warning in the specified
* coordinate system
*
* @throws NullPointerException if the window argument is null
* @throws NullPointerException if the point argument is null
* @throws IllegalArgumentException if the window is trusted (i.e.
* the {@code getWarningString()} returns null
* @throws IllegalArgumentException if the alignmentX or alignmentY
* arguments are not within the range [0.0f ... 1.0f]
*/
public static void setPosition(Window window, Point2D point,
float alignmentX, float alignmentY)
{
if (window == null) {
throw new NullPointerException(
"The window argument should not be null.");
}
if (window.getWarningString() == null) {
throw new IllegalArgumentException(
"The window must have a non-null warning string.");
}
if (point == null) {
throw new NullPointerException(
"The point argument must not be null");
}
if (alignmentX < 0.0f || alignmentX > 1.0f) {
throw new IllegalArgumentException(
"alignmentX must be in the range [0.0f ... 1.0f].");
}
if (alignmentY < 0.0f || alignmentY > 1.0f) {
throw new IllegalArgumentException(
"alignmentY must be in the range [0.0f ... 1.0f].");
}
AWTAccessor.getWindowAccessor().setSecurityWarningPosition(window,
point, alignmentX, alignmentY);
}
}
...@@ -857,6 +857,10 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -857,6 +857,10 @@ public abstract class Component implements ImageObserver, MenuContainer,
public boolean canBeFocusOwner(Component comp) { public boolean canBeFocusOwner(Component comp) {
return comp.canBeFocusOwner(); return comp.canBeFocusOwner();
} }
public boolean isVisible_NoClientCode(Component comp) {
return comp.isVisible_NoClientCode();
}
}); });
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.awt; package java.awt;
import java.awt.event.*; import java.awt.event.*;
import java.awt.geom.Point2D;
import java.awt.im.InputContext; import java.awt.im.InputContext;
import java.awt.image.BufferStrategy; import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
...@@ -326,6 +327,23 @@ public class Window extends Container implements Accessible { ...@@ -326,6 +327,23 @@ public class Window extends Container implements Accessible {
transient boolean isTrayIconWindow = false; transient boolean isTrayIconWindow = false;
/**
* These fields are initialized in the native peer code
* or via AWTAccessor's WindowAccessor.
*/
private transient volatile int securityWarningWidth = 0;
private transient volatile int securityWarningHeight = 0;
/**
* These fields represent the desired location for the security
* warning if this window is untrusted.
* See com.sun.awt.SecurityWarning for more details.
*/
private transient double securityWarningPointX = 2.0;
private transient double securityWarningPointY = 0.0;
private transient float securityWarningAlignmentX = RIGHT_ALIGNMENT;
private transient float securityWarningAlignmentY = TOP_ALIGNMENT;
static { static {
/* ensure that the necessary native libraries are loaded */ /* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries(); Toolkit.loadLibraries();
...@@ -2881,6 +2899,13 @@ public class Window extends Container implements Accessible { ...@@ -2881,6 +2899,13 @@ public class Window extends Container implements Accessible {
shape = (Shape)f.get("shape", null); shape = (Shape)f.get("shape", null);
opacity = (Float)f.get("opacity", 1.0f); opacity = (Float)f.get("opacity", 1.0f);
this.securityWarningWidth = 0;
this.securityWarningHeight = 0;
this.securityWarningPointX = 2.0;
this.securityWarningPointY = 0.0;
this.securityWarningAlignmentX = RIGHT_ALIGNMENT;
this.securityWarningAlignmentY = TOP_ALIGNMENT;
deserializeResources(s); deserializeResources(s);
} }
...@@ -3568,6 +3593,18 @@ public class Window extends Container implements Accessible { ...@@ -3568,6 +3593,18 @@ public class Window extends Container implements Accessible {
// ****************** END OF MIXING CODE ******************************** // ****************** END OF MIXING CODE ********************************
// This method gets the window location/size as reported by the native
// system since the locally cached values may represent outdated data.
// NOTE: this method is invoked on the toolkit thread, and therefore
// is not supposed to become public/user-overridable.
private Point2D calculateSecurityWarningPosition(double x, double y,
double w, double h)
{
return new Point2D.Double(
x + w * securityWarningAlignmentX + securityWarningPointX,
y + h * securityWarningAlignmentY + securityWarningPointY);
}
static { static {
AWTAccessor.setWindowAccessor(new AWTAccessor.WindowAccessor() { AWTAccessor.setWindowAccessor(new AWTAccessor.WindowAccessor() {
public float getOpacity(Window window) { public float getOpacity(Window window) {
...@@ -3601,6 +3638,39 @@ public class Window extends Container implements Accessible { ...@@ -3601,6 +3638,39 @@ public class Window extends Container implements Accessible {
public void updateWindow(Window window, BufferedImage backBuffer) { public void updateWindow(Window window, BufferedImage backBuffer) {
window.updateWindow(backBuffer); window.updateWindow(backBuffer);
} }
public Dimension getSecurityWarningSize(Window window) {
return new Dimension(window.securityWarningWidth,
window.securityWarningHeight);
}
public void setSecurityWarningSize(Window window, int width, int height)
{
window.securityWarningWidth = width;
window.securityWarningHeight = height;
}
public void setSecurityWarningPosition(Window window,
Point2D point, float alignmentX, float alignmentY)
{
window.securityWarningPointX = point.getX();
window.securityWarningPointY = point.getY();
window.securityWarningAlignmentX = alignmentX;
window.securityWarningAlignmentY = alignmentY;
synchronized (window.getTreeLock()) {
WindowPeer peer = (WindowPeer)window.getPeer();
if (peer != null) {
peer.repositionSecurityWarning();
}
}
}
public Point2D calculateSecurityWarningPosition(Window window,
double x, double y, double w, double h)
{
return window.calculateSecurityWarningPosition(x, y, w, h);
}
}); // WindowAccessor }); // WindowAccessor
} // static } // static
......
...@@ -116,4 +116,9 @@ public interface WindowPeer extends ContainerPeer { ...@@ -116,4 +116,9 @@ public interface WindowPeer extends ContainerPeer {
* @see Window#setBackground(Color) * @see Window#setBackground(Color)
*/ */
void updateWindow(BufferedImage backBuffer); void updateWindow(BufferedImage backBuffer);
/**
* Instructs the peer to update the position of the security warning.
*/
void repositionSecurityWarning();
} }
...@@ -92,6 +92,12 @@ public final class AWTAccessor { ...@@ -92,6 +92,12 @@ public final class AWTAccessor {
* Determines if the component can gain focus. * Determines if the component can gain focus.
*/ */
boolean canBeFocusOwner(Component comp); boolean canBeFocusOwner(Component comp);
/**
* Returns whether the component is visible without invoking
* any client code.
*/
boolean isVisible_NoClientCode(Component comp);
} }
/* /*
...@@ -127,6 +133,26 @@ public final class AWTAccessor { ...@@ -127,6 +133,26 @@ public final class AWTAccessor {
* Update the image of a non-opaque (translucent) window. * Update the image of a non-opaque (translucent) window.
*/ */
void updateWindow(Window window, BufferedImage backBuffer); void updateWindow(Window window, BufferedImage backBuffer);
/** Get the size of the security warning.
*/
Dimension getSecurityWarningSize(Window w);
/**
* Set the size of the security warning.
*/
void setSecurityWarningSize(Window w, int width, int height);
/** Set the position of the security warning.
*/
void setSecurityWarningPosition(Window w, Point2D point,
float alignmentX, float alignmentY);
/** Request to recalculate the new position of the security warning for
* the given window size/location as reported by the native system.
*/
Point2D calculateSecurityWarningPosition(Window window,
double x, double y, double w, double h);
} }
/* /*
......
...@@ -592,5 +592,7 @@ public abstract class EmbeddedFrame extends Frame ...@@ -592,5 +592,7 @@ public abstract class EmbeddedFrame extends Frame
} }
public void updateWindow(BufferedImage backBuffer) { public void updateWindow(BufferedImage backBuffer) {
} }
public void repositionSecurityWarning() {
}
} }
} // class EmbeddedFrame } // class EmbeddedFrame
/*
* 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.X11;
import java.awt.*;
import java.awt.event.*;
import java.awt.peer.TrayIconPeer;
import sun.awt.*;
import java.awt.image.*;
import java.text.BreakIterator;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.concurrent.ArrayBlockingQueue;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.lang.reflect.InvocationTargetException;
/**
* An utility window class. This is a base class for Tooltip and Balloon.
*/
public abstract class InfoWindow extends Window {
private Container container;
private Closer closer;
protected InfoWindow(Frame parent, Color borderColor) {
super(parent);
container = new Container() {
@Override
public Insets getInsets() {
return new Insets(1, 1, 1, 1);
}
};
setLayout(new BorderLayout());
setBackground(borderColor);
add(container, BorderLayout.CENTER);
container.setLayout(new BorderLayout());
closer = new Closer();
}
public Component add(Component c) {
container.add(c, BorderLayout.CENTER);
return c;
}
protected void setCloser(Runnable action, int time) {
closer.set(action, time);
}
// Must be executed on EDT.
protected void show(Point corner, int indent) {
assert SunToolkit.isDispatchThreadForAppContext(this);
pack();
Dimension size = getSize();
// TODO: When 6356322 is fixed we should get screen bounds in
// this way: eframe.getGraphicsConfiguration().getBounds().
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
if (corner.x < scrSize.width/2 && corner.y < scrSize.height/2) { // 1st square
setLocation(corner.x + indent, corner.y + indent);
} else if (corner.x >= scrSize.width/2 && corner.y < scrSize.height/2) { // 2nd square
setLocation(corner.x - indent - size.width, corner.y + indent);
} else if (corner.x < scrSize.width/2 && corner.y >= scrSize.height/2) { // 3rd square
setLocation(corner.x + indent, corner.y - indent - size.height);
} else if (corner.x >= scrSize.width/2 && corner.y >= scrSize.height/2) { // 4th square
setLocation(corner.x - indent - size.width, corner.y - indent - size.height);
}
super.show();
closer.schedule();
}
public void hide() {
closer.close();
}
private class Closer implements Runnable {
Runnable action;
int time;
public void run() {
doClose();
}
void set(Runnable action, int time) {
this.action = action;
this.time = time;
}
void schedule() {
XToolkit.schedule(this, time);
}
void close() {
XToolkit.remove(this);
doClose();
}
// WARNING: this method may be executed on Toolkit thread.
private void doClose() {
SunToolkit.executeOnEventHandlerThread(InfoWindow.this, new Runnable() {
public void run() {
InfoWindow.super.hide();
invalidate();
if (action != null) {
action.run();
}
}
});
}
}
private interface LiveArguments {
/** Whether the target of the InfoWindow is disposed. */
boolean isDisposed();
/** The bounds of the target of the InfoWindow. */
Rectangle getBounds();
}
public static class Tooltip extends InfoWindow {
public interface LiveArguments extends InfoWindow.LiveArguments {
/** The tooltip to be displayed. */
String getTooltipString();
}
private final Object target;
private final LiveArguments liveArguments;
private final Label textLabel = new Label("");
private final Runnable starter = new Runnable() {
public void run() {
display();
}};
private final static int TOOLTIP_SHOW_TIME = 10000;
private final static int TOOLTIP_START_DELAY_TIME = 1000;
private final static int TOOLTIP_MAX_LENGTH = 64;
private final static int TOOLTIP_MOUSE_CURSOR_INDENT = 5;
private final static Color TOOLTIP_BACKGROUND_COLOR = new Color(255, 255, 220);
private final static Font TOOLTIP_TEXT_FONT = XWindow.getDefaultFont();
public Tooltip(Frame parent, Object target,
LiveArguments liveArguments)
{
super(parent, Color.black);
this.target = target;
this.liveArguments = liveArguments;
XTrayIconPeer.suppressWarningString(this);
setCloser(null, TOOLTIP_SHOW_TIME);
textLabel.setBackground(TOOLTIP_BACKGROUND_COLOR);
textLabel.setFont(TOOLTIP_TEXT_FONT);
add(textLabel);
}
/*
* WARNING: this method is executed on Toolkit thread!
*/
private void display() {
String tooltipString = liveArguments.getTooltipString();
if (tooltipString == null) {
return;
} else if (tooltipString.length() > TOOLTIP_MAX_LENGTH) {
textLabel.setText(tooltipString.substring(0, TOOLTIP_MAX_LENGTH));
} else {
textLabel.setText(tooltipString);
}
// Execute on EDT to avoid deadlock (see 6280857).
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
if (liveArguments.isDisposed()) {
return;
}
Point pointer = (Point)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
if (!isPointerOverTrayIcon(liveArguments.getBounds())) {
return null;
}
return MouseInfo.getPointerInfo().getLocation();
}
});
if (pointer == null) {
return;
}
show(new Point(pointer.x, pointer.y), TOOLTIP_MOUSE_CURSOR_INDENT);
}
});
}
public void enter() {
XToolkit.schedule(starter, TOOLTIP_START_DELAY_TIME);
}
public void exit() {
XToolkit.remove(starter);
if (isVisible()) {
hide();
}
}
private boolean isPointerOverTrayIcon(Rectangle trayRect) {
Point p = MouseInfo.getPointerInfo().getLocation();
return !(p.x < trayRect.x || p.x > (trayRect.x + trayRect.width) ||
p.y < trayRect.y || p.y > (trayRect.y + trayRect.height));
}
}
public static class Balloon extends InfoWindow {
public interface LiveArguments extends InfoWindow.LiveArguments {
/** The action to be performed upon clicking the baloon. */
String getActionCommand();
}
private final LiveArguments liveArguments;
private final Object target;
private final static int BALLOON_SHOW_TIME = 10000;
private final static int BALLOON_TEXT_MAX_LENGTH = 256;
private final static int BALLOON_WORD_LINE_MAX_LENGTH = 16;
private final static int BALLOON_WORD_LINE_MAX_COUNT = 4;
private final static int BALLOON_ICON_WIDTH = 32;
private final static int BALLOON_ICON_HEIGHT = 32;
private final static int BALLOON_TRAY_ICON_INDENT = 0;
private final static Color BALLOON_CAPTION_BACKGROUND_COLOR = new Color(200, 200 ,255);
private final static Font BALLOON_CAPTION_FONT = new Font(Font.DIALOG, Font.BOLD, 12);
private Panel mainPanel = new Panel();
private Panel captionPanel = new Panel();
private Label captionLabel = new Label("");
private Button closeButton = new Button("X");
private Panel textPanel = new Panel();
private XTrayIconPeer.IconCanvas iconCanvas = new XTrayIconPeer.IconCanvas(BALLOON_ICON_WIDTH, BALLOON_ICON_HEIGHT);
private Label[] lineLabels = new Label[BALLOON_WORD_LINE_MAX_COUNT];
private ActionPerformer ap = new ActionPerformer();
private Image iconImage;
private Image errorImage;
private Image warnImage;
private Image infoImage;
private boolean gtkImagesLoaded;
private Displayer displayer = new Displayer();
public Balloon(Frame parent, Object target, LiveArguments liveArguments) {
super(parent, new Color(90, 80 ,190));
this.liveArguments = liveArguments;
this.target = target;
XTrayIconPeer.suppressWarningString(this);
setCloser(new Runnable() {
public void run() {
if (textPanel != null) {
textPanel.removeAll();
textPanel.setSize(0, 0);
iconCanvas.setSize(0, 0);
XToolkit.awtLock();
try {
displayer.isDisplayed = false;
XToolkit.awtLockNotifyAll();
} finally {
XToolkit.awtUnlock();
}
}
}
}, BALLOON_SHOW_TIME);
add(mainPanel);
captionLabel.setFont(BALLOON_CAPTION_FONT);
captionLabel.addMouseListener(ap);
captionPanel.setLayout(new BorderLayout());
captionPanel.add(captionLabel, BorderLayout.WEST);
captionPanel.add(closeButton, BorderLayout.EAST);
captionPanel.setBackground(BALLOON_CAPTION_BACKGROUND_COLOR);
captionPanel.addMouseListener(ap);
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
hide();
}
});
mainPanel.setLayout(new BorderLayout());
mainPanel.setBackground(Color.white);
mainPanel.add(captionPanel, BorderLayout.NORTH);
mainPanel.add(iconCanvas, BorderLayout.WEST);
mainPanel.add(textPanel, BorderLayout.CENTER);
iconCanvas.addMouseListener(ap);
for (int i = 0; i < BALLOON_WORD_LINE_MAX_COUNT; i++) {
lineLabels[i] = new Label();
lineLabels[i].addMouseListener(ap);
lineLabels[i].setBackground(Color.white);
}
displayer.start();
}
public void display(String caption, String text, String messageType) {
if (!gtkImagesLoaded) {
loadGtkImages();
}
displayer.display(caption, text, messageType);
}
private void _display(String caption, String text, String messageType) {
captionLabel.setText(caption);
BreakIterator iter = BreakIterator.getWordInstance();
if (text != null) {
iter.setText(text);
int start = iter.first(), end;
int nLines = 0;
do {
end = iter.next();
if (end == BreakIterator.DONE ||
text.substring(start, end).length() >= 50)
{
lineLabels[nLines].setText(text.substring(start, end == BreakIterator.DONE ?
iter.last() : end));
textPanel.add(lineLabels[nLines++]);
start = end;
}
if (nLines == BALLOON_WORD_LINE_MAX_COUNT) {
if (end != BreakIterator.DONE) {
lineLabels[nLines - 1].setText(
new String(lineLabels[nLines - 1].getText() + " ..."));
}
break;
}
} while (end != BreakIterator.DONE);
textPanel.setLayout(new GridLayout(nLines, 1));
}
if ("ERROR".equals(messageType)) {
iconImage = errorImage;
} else if ("WARNING".equals(messageType)) {
iconImage = warnImage;
} else if ("INFO".equals(messageType)) {
iconImage = infoImage;
} else {
iconImage = null;
}
if (iconImage != null) {
Dimension tpSize = textPanel.getSize();
iconCanvas.setSize(BALLOON_ICON_WIDTH, (BALLOON_ICON_HEIGHT > tpSize.height ?
BALLOON_ICON_HEIGHT : tpSize.height));
iconCanvas.validate();
}
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
if (liveArguments.isDisposed()) {
return;
}
Point parLoc = getParent().getLocationOnScreen();
Dimension parSize = getParent().getSize();
show(new Point(parLoc.x + parSize.width/2, parLoc.y + parSize.height/2),
BALLOON_TRAY_ICON_INDENT);
if (iconImage != null) {
iconCanvas.updateImage(iconImage); // call it after the show(..) above
}
}
});
}
public void dispose() {
displayer.interrupt();
super.dispose();
}
private void loadGtkImages() {
if (!gtkImagesLoaded) {
errorImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
"gtk.icon.gtk-dialog-error.6.rtl");
warnImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
"gtk.icon.gtk-dialog-warning.6.rtl");
infoImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
"gtk.icon.gtk-dialog-info.6.rtl");
gtkImagesLoaded = true;
}
}
private class ActionPerformer extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
// hide the balloon by any click
hide();
if (e.getButton() == MouseEvent.BUTTON1) {
ActionEvent aev = new ActionEvent(target, ActionEvent.ACTION_PERFORMED,
liveArguments.getActionCommand(),
e.getWhen(), e.getModifiers());
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(aev);
}
}
}
private class Displayer extends Thread {
final int MAX_CONCURRENT_MSGS = 10;
ArrayBlockingQueue<Message> messageQueue = new ArrayBlockingQueue<Message>(MAX_CONCURRENT_MSGS);
boolean isDisplayed;
Displayer() {
setDaemon(true);
}
public void run() {
while (true) {
Message msg = null;
try {
msg = (Message)messageQueue.take();
} catch (InterruptedException e) {
return;
}
/*
* Wait till the previous message is displayed if any
*/
XToolkit.awtLock();
try {
while (isDisplayed) {
try {
XToolkit.awtLockWait();
} catch (InterruptedException e) {
return;
}
}
isDisplayed = true;
} finally {
XToolkit.awtUnlock();
}
_display(msg.caption, msg.text, msg.messageType);
}
}
void display(String caption, String text, String messageType) {
messageQueue.offer(new Message(caption, text, messageType));
}
}
private static class Message {
String caption, text, messageType;
Message(String caption, String text, String messageType) {
this.caption = caption;
this.text = text;
this.messageType = messageType;
}
}
}
}
...@@ -451,7 +451,7 @@ abstract class XDecoratedPeer extends XWindowPeer { ...@@ -451,7 +451,7 @@ abstract class XDecoratedPeer extends XWindowPeer {
public Insets getInsets() { public Insets getInsets() {
Insets in = copy(getRealInsets()); Insets in = copy(getRealInsets());
in.top += getMenuBarHeight() + getWarningWindowHeight(); in.top += getMenuBarHeight();
if (insLog.isLoggable(Level.FINEST)) { if (insLog.isLoggable(Level.FINEST)) {
insLog.log(Level.FINEST, "Get insets returns {0}", new Object[] {in}); insLog.log(Level.FINEST, "Get insets returns {0}", new Object[] {in});
} }
...@@ -802,6 +802,8 @@ abstract class XDecoratedPeer extends XWindowPeer { ...@@ -802,6 +802,8 @@ abstract class XDecoratedPeer extends XWindowPeer {
} }
reconfigureContentWindow(newDimensions); reconfigureContentWindow(newDimensions);
updateChildrenSizes(); updateChildrenSizes();
repositionSecurityWarning();
} }
private void checkShellRectSize(Rectangle shellRect) { private void checkShellRectSize(Rectangle shellRect) {
......
...@@ -83,8 +83,25 @@ public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { ...@@ -83,8 +83,25 @@ public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
public static void setCurrentNativeFocusedWindow(Window win) { public static void setCurrentNativeFocusedWindow(Window win) {
if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Setting current native focused window " + win); if (focusLog.isLoggable(Level.FINER)) focusLog.finer("Setting current native focused window " + win);
XWindowPeer from = null, to = null;
synchronized(lock) { synchronized(lock) {
if (currentFocusedWindow != null) {
from = (XWindowPeer)currentFocusedWindow.getPeer();
}
currentFocusedWindow = win; currentFocusedWindow = win;
if (currentFocusedWindow != null) {
to = (XWindowPeer)currentFocusedWindow.getPeer();
}
}
if (from != null) {
from.updateSecurityWarningVisibility();
}
if (to != null) {
to.updateSecurityWarningVisibility();
} }
} }
......
...@@ -169,6 +169,34 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt ...@@ -169,6 +169,34 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt
return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol(); return ((layer == LAYER_ALWAYS_ON_TOP) || (layer == LAYER_NORMAL)) && doLayerProtocol();
} }
public void requestState(XWindow window, XAtom state, boolean isAdd) {
XClientMessageEvent req = new XClientMessageEvent();
try {
req.set_type((int)XConstants.ClientMessage);
req.set_window(window.getWindow());
req.set_message_type(XA_NET_WM_STATE.getAtom());
req.set_format(32);
req.set_data(0, isAdd ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE);
req.set_data(1, state.getAtom());
// Fix for 6735584: req.data[2] must be set to 0 when only one property is changed
req.set_data(2, 0);
log.log(Level.FINE, "Setting _NET_STATE atom {0} on {1} for {2}", new Object[] {state, window, Boolean.valueOf(isAdd)});
XToolkit.awtLock();
try {
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()),
false,
XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask,
req.pData);
}
finally {
XToolkit.awtUnlock();
}
} finally {
req.dispose();
}
}
/** /**
* Helper function to set/reset one state in NET_WM_STATE * Helper function to set/reset one state in NET_WM_STATE
* If window is showing then it uses ClientMessage, otherwise adjusts NET_WM_STATE list * If window is showing then it uses ClientMessage, otherwise adjusts NET_WM_STATE list
...@@ -181,31 +209,7 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt ...@@ -181,31 +209,7 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt
new Object[] {Boolean.valueOf(window.isWithdrawn()), Boolean.valueOf(window.isVisible()), new Object[] {Boolean.valueOf(window.isWithdrawn()), Boolean.valueOf(window.isVisible()),
Boolean.valueOf(window.isMapped()), Boolean.valueOf(window.isShowing())}); Boolean.valueOf(window.isMapped()), Boolean.valueOf(window.isShowing())});
if (window.isShowing()) { if (window.isShowing()) {
XClientMessageEvent req = new XClientMessageEvent(); requestState(window, state, set);
try {
req.set_type((int)XConstants.ClientMessage);
req.set_window(window.getWindow());
req.set_message_type(XA_NET_WM_STATE.getAtom());
req.set_format(32);
req.set_data(0, (!set) ? _NET_WM_STATE_REMOVE : _NET_WM_STATE_ADD);
req.set_data(1, state.getAtom());
// Fix for 6735584: req.data[2] must be set to 0 when only one property is changed
req.set_data(2, 0);
log.log(Level.FINE, "Setting _NET_STATE atom {0} on {1} for {2}", new Object[] {state, window, Boolean.valueOf(set)});
XToolkit.awtLock();
try {
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
XlibWrapper.RootWindow(XToolkit.getDisplay(), window.getScreenNumber()),
false,
XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask,
req.pData);
}
finally {
XToolkit.awtUnlock();
}
} finally {
req.dispose();
}
} else { } else {
XAtomList net_wm_state = window.getNETWMState(); XAtomList net_wm_state = window.getNETWMState();
log.log(Level.FINE, "Current state on {0} is {1}", new Object[] {window, net_wm_state}); log.log(Level.FINE, "Current state on {0} is {1}", new Object[] {window, net_wm_state});
......
...@@ -38,15 +38,18 @@ import java.security.AccessController; ...@@ -38,15 +38,18 @@ import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
public class XTrayIconPeer implements TrayIconPeer { public class XTrayIconPeer implements TrayIconPeer,
InfoWindow.Balloon.LiveArguments,
InfoWindow.Tooltip.LiveArguments
{
private static final Logger ctrLog = Logger.getLogger("sun.awt.X11.XTrayIconPeer.centering"); private static final Logger ctrLog = Logger.getLogger("sun.awt.X11.XTrayIconPeer.centering");
TrayIcon target; TrayIcon target;
TrayIconEventProxy eventProxy; TrayIconEventProxy eventProxy;
XTrayIconEmbeddedFrame eframe; XTrayIconEmbeddedFrame eframe;
TrayIconCanvas canvas; TrayIconCanvas canvas;
Balloon balloon; InfoWindow.Balloon balloon;
Tooltip tooltip; InfoWindow.Tooltip tooltip;
PopupMenu popup; PopupMenu popup;
String tooltipString; String tooltipString;
boolean isTrayIconDisplayed; boolean isTrayIconDisplayed;
...@@ -255,8 +258,8 @@ public class XTrayIconPeer implements TrayIconPeer { ...@@ -255,8 +258,8 @@ public class XTrayIconPeer implements TrayIconPeer {
eframe.setVisible(true); eframe.setVisible(true);
updateImage(); updateImage();
balloon = new Balloon(this, eframe); balloon = new InfoWindow.Balloon(eframe, target, this);
tooltip = new Tooltip(this, eframe); tooltip = new InfoWindow.Tooltip(eframe, target, this);
addListeners(); addListeners();
} }
...@@ -300,6 +303,10 @@ public class XTrayIconPeer implements TrayIconPeer { ...@@ -300,6 +303,10 @@ public class XTrayIconPeer implements TrayIconPeer {
tooltipString = tooltip; tooltipString = tooltip;
} }
public String getTooltipString() {
return tooltipString;
}
public void updateImage() { public void updateImage() {
Runnable r = new Runnable() { Runnable r = new Runnable() {
public void run() { public void run() {
...@@ -385,7 +392,7 @@ public class XTrayIconPeer implements TrayIconPeer { ...@@ -385,7 +392,7 @@ public class XTrayIconPeer implements TrayIconPeer {
return eframe.getLocationOnScreen(); return eframe.getLocationOnScreen();
} }
private Rectangle getBounds() { public Rectangle getBounds() {
Point loc = getLocationOnScreen(); Point loc = getLocationOnScreen();
return new Rectangle(loc.x, loc.y, loc.x + TRAY_ICON_WIDTH, loc.y + TRAY_ICON_HEIGHT); return new Rectangle(loc.x, loc.y, loc.x + TRAY_ICON_WIDTH, loc.y + TRAY_ICON_HEIGHT);
} }
...@@ -399,10 +406,14 @@ public class XTrayIconPeer implements TrayIconPeer { ...@@ -399,10 +406,14 @@ public class XTrayIconPeer implements TrayIconPeer {
return ((XEmbeddedFramePeer)eframe.getPeer()).getWindow(); return ((XEmbeddedFramePeer)eframe.getPeer()).getWindow();
} }
boolean isDisposed() { public boolean isDisposed() {
return isDisposed; return isDisposed;
} }
public String getActionCommand() {
return target.getActionCommand();
}
static class TrayIconEventProxy implements MouseListener, MouseMotionListener { static class TrayIconEventProxy implements MouseListener, MouseMotionListener {
XTrayIconPeer xtiPeer; XTrayIconPeer xtiPeer;
...@@ -474,8 +485,8 @@ public class XTrayIconPeer implements TrayIconPeer { ...@@ -474,8 +485,8 @@ public class XTrayIconPeer implements TrayIconPeer {
} }
static boolean isTrayIconStuffWindow(Window w) { static boolean isTrayIconStuffWindow(Window w) {
return (w instanceof Tooltip) || return (w instanceof InfoWindow.Tooltip) ||
(w instanceof Balloon) || (w instanceof InfoWindow.Balloon) ||
(w instanceof XTrayIconEmbeddedFrame); (w instanceof XTrayIconEmbeddedFrame);
} }
...@@ -530,7 +541,7 @@ public class XTrayIconPeer implements TrayIconPeer { ...@@ -530,7 +541,7 @@ public class XTrayIconPeer implements TrayIconPeer {
} }
} }
static class IconCanvas extends Canvas { public static class IconCanvas extends Canvas {
volatile Image image; volatile Image image;
IconObserver observer; IconObserver observer;
int width, height; int width, height;
...@@ -608,429 +619,4 @@ public class XTrayIconPeer implements TrayIconPeer { ...@@ -608,429 +619,4 @@ public class XTrayIconPeer implements TrayIconPeer {
} }
} }
} }
// ***************************************
// Classes for toolitp and balloon windows
// ***************************************
static class Tooltip extends InfoWindow {
XTrayIconPeer xtiPeer;
Label textLabel = new Label("");
Runnable starter = new Runnable() {
public void run() {
display();
}};
final static int TOOLTIP_SHOW_TIME = 10000;
final static int TOOLTIP_START_DELAY_TIME = 1000;
final static int TOOLTIP_MAX_LENGTH = 64;
final static int TOOLTIP_MOUSE_CURSOR_INDENT = 5;
final static Color TOOLTIP_BACKGROUND_COLOR = new Color(255, 255, 220);
final static Font TOOLTIP_TEXT_FONT = XWindow.getDefaultFont();
Tooltip(XTrayIconPeer xtiPeer, Frame parent) {
super(parent, Color.black);
this.xtiPeer = xtiPeer;
suppressWarningString(this);
setCloser(null, TOOLTIP_SHOW_TIME);
textLabel.setBackground(TOOLTIP_BACKGROUND_COLOR);
textLabel.setFont(TOOLTIP_TEXT_FONT);
add(textLabel);
}
/*
* WARNING: this method is executed on Toolkit thread!
*/
void display() {
String tip = xtiPeer.tooltipString;
if (tip == null) {
return;
} else if (tip.length() > TOOLTIP_MAX_LENGTH) {
textLabel.setText(tip.substring(0, TOOLTIP_MAX_LENGTH));
} else {
textLabel.setText(tip);
}
// Execute on EDT to avoid deadlock (see 6280857).
SunToolkit.executeOnEventHandlerThread(xtiPeer.target, new Runnable() {
public void run() {
if (xtiPeer.isDisposed()) {
return;
}
Point pointer = (Point)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
if (!isPointerOverTrayIcon(xtiPeer.getBounds())) {
return null;
}
return MouseInfo.getPointerInfo().getLocation();
}
});
if (pointer == null) {
return;
}
show(new Point(pointer.x, pointer.y), TOOLTIP_MOUSE_CURSOR_INDENT);
}
});
}
void enter() {
XToolkit.schedule(starter, TOOLTIP_START_DELAY_TIME);
}
void exit() {
XToolkit.remove(starter);
if (isVisible()) {
hide();
}
}
boolean isPointerOverTrayIcon(Rectangle trayRect) {
Point p = MouseInfo.getPointerInfo().getLocation();
return !(p.x < trayRect.x || p.x > (trayRect.x + trayRect.width) ||
p.y < trayRect.y || p.y > (trayRect.y + trayRect.height));
}
}
static class Balloon extends InfoWindow {
final static int BALLOON_SHOW_TIME = 10000;
final static int BALLOON_TEXT_MAX_LENGTH = 256;
final static int BALLOON_WORD_LINE_MAX_LENGTH = 16;
final static int BALLOON_WORD_LINE_MAX_COUNT = 4;
final static int BALLOON_ICON_WIDTH = 32;
final static int BALLOON_ICON_HEIGHT = 32;
final static int BALLOON_TRAY_ICON_INDENT = 0;
final static Color BALLOON_CAPTION_BACKGROUND_COLOR = new Color(200, 200 ,255);
final static Font BALLOON_CAPTION_FONT = new Font(Font.DIALOG, Font.BOLD, 12);
XTrayIconPeer xtiPeer;
Panel mainPanel = new Panel();
Panel captionPanel = new Panel();
Label captionLabel = new Label("");
Button closeButton = new Button("X");
Panel textPanel = new Panel();
IconCanvas iconCanvas = new IconCanvas(BALLOON_ICON_WIDTH, BALLOON_ICON_HEIGHT);
Label[] lineLabels = new Label[BALLOON_WORD_LINE_MAX_COUNT];
ActionPerformer ap = new ActionPerformer();
Image iconImage;
Image errorImage;
Image warnImage;
Image infoImage;
boolean gtkImagesLoaded;
Displayer displayer = new Displayer();
Balloon(final XTrayIconPeer xtiPeer, Frame parent) {
super(parent, new Color(90, 80 ,190));
this.xtiPeer = xtiPeer;
suppressWarningString(this);
setCloser(new Runnable() {
public void run() {
if (textPanel != null) {
textPanel.removeAll();
textPanel.setSize(0, 0);
iconCanvas.setSize(0, 0);
XToolkit.awtLock();
try {
displayer.isDisplayed = false;
XToolkit.awtLockNotifyAll();
} finally {
XToolkit.awtUnlock();
}
}
}
}, BALLOON_SHOW_TIME);
add(mainPanel);
captionLabel.setFont(BALLOON_CAPTION_FONT);
captionLabel.addMouseListener(ap);
captionPanel.setLayout(new BorderLayout());
captionPanel.add(captionLabel, BorderLayout.WEST);
captionPanel.add(closeButton, BorderLayout.EAST);
captionPanel.setBackground(BALLOON_CAPTION_BACKGROUND_COLOR);
captionPanel.addMouseListener(ap);
closeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
hide();
}
});
mainPanel.setLayout(new BorderLayout());
mainPanel.setBackground(Color.white);
mainPanel.add(captionPanel, BorderLayout.NORTH);
mainPanel.add(iconCanvas, BorderLayout.WEST);
mainPanel.add(textPanel, BorderLayout.CENTER);
iconCanvas.addMouseListener(ap);
for (int i = 0; i < BALLOON_WORD_LINE_MAX_COUNT; i++) {
lineLabels[i] = new Label();
lineLabels[i].addMouseListener(ap);
lineLabels[i].setBackground(Color.white);
}
displayer.start();
}
void display(String caption, String text, String messageType) {
if (!gtkImagesLoaded) {
loadGtkImages();
}
displayer.display(caption, text, messageType);
}
private void _display(String caption, String text, String messageType) {
captionLabel.setText(caption);
BreakIterator iter = BreakIterator.getWordInstance();
if (text != null) {
iter.setText(text);
int start = iter.first(), end;
int nLines = 0;
do {
end = iter.next();
if (end == BreakIterator.DONE ||
text.substring(start, end).length() >= 50)
{
lineLabels[nLines].setText(text.substring(start, end == BreakIterator.DONE ?
iter.last() : end));
textPanel.add(lineLabels[nLines++]);
start = end;
}
if (nLines == BALLOON_WORD_LINE_MAX_COUNT) {
if (end != BreakIterator.DONE) {
lineLabels[nLines - 1].setText(
new String(lineLabels[nLines - 1].getText() + " ..."));
}
break;
}
} while (end != BreakIterator.DONE);
textPanel.setLayout(new GridLayout(nLines, 1));
}
if ("ERROR".equals(messageType)) {
iconImage = errorImage;
} else if ("WARNING".equals(messageType)) {
iconImage = warnImage;
} else if ("INFO".equals(messageType)) {
iconImage = infoImage;
} else {
iconImage = null;
}
if (iconImage != null) {
Dimension tpSize = textPanel.getSize();
iconCanvas.setSize(BALLOON_ICON_WIDTH, (BALLOON_ICON_HEIGHT > tpSize.height ?
BALLOON_ICON_HEIGHT : tpSize.height));
iconCanvas.validate();
}
SunToolkit.executeOnEventHandlerThread(xtiPeer.target, new Runnable() {
public void run() {
if (xtiPeer.isDisposed()) {
return;
}
Point parLoc = getParent().getLocationOnScreen();
Dimension parSize = getParent().getSize();
show(new Point(parLoc.x + parSize.width/2, parLoc.y + parSize.height/2),
BALLOON_TRAY_ICON_INDENT);
if (iconImage != null) {
iconCanvas.updateImage(iconImage); // call it after the show(..) above
}
}
});
}
public void dispose() {
displayer.interrupt();
super.dispose();
}
void loadGtkImages() {
if (!gtkImagesLoaded) {
errorImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
"gtk.icon.gtk-dialog-error.6.rtl");
warnImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
"gtk.icon.gtk-dialog-warning.6.rtl");
infoImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
"gtk.icon.gtk-dialog-info.6.rtl");
gtkImagesLoaded = true;
}
}
class ActionPerformer extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
// hide the balloon by any click
hide();
if (e.getButton() == MouseEvent.BUTTON1) {
ActionEvent aev = new ActionEvent(xtiPeer.target, ActionEvent.ACTION_PERFORMED,
xtiPeer.target.getActionCommand(),
e.getWhen(), e.getModifiers());
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(aev);
}
}
}
class Displayer extends Thread {
final int MAX_CONCURRENT_MSGS = 10;
ArrayBlockingQueue<Message> messageQueue = new ArrayBlockingQueue<Message>(MAX_CONCURRENT_MSGS);
boolean isDisplayed;
Displayer() {
setDaemon(true);
}
public void run() {
while (true) {
Message msg = null;
try {
msg = (Message)messageQueue.take();
} catch (InterruptedException e) {
return;
}
/*
* Wait till the previous message is displayed if any
*/
XToolkit.awtLock();
try {
while (isDisplayed) {
try {
XToolkit.awtLockWait();
} catch (InterruptedException e) {
return;
}
}
isDisplayed = true;
} finally {
XToolkit.awtUnlock();
}
_display(msg.caption, msg.text, msg.messageType);
}
}
void display(String caption, String text, String messageType) {
messageQueue.offer(new Message(caption, text, messageType));
}
}
class Message {
String caption, text, messageType;
Message(String caption, String text, String messageType) {
this.caption = caption;
this.text = text;
this.messageType = messageType;
}
}
}
static class InfoWindow extends Window {
Container container;
Closer closer;
InfoWindow(Frame parent, Color borderColor) {
super(parent);
container = new Container() {
public Insets getInsets() {
return new Insets(1, 1, 1, 1);
}
};
setLayout(new BorderLayout());
setBackground(borderColor);
add(container, BorderLayout.CENTER);
container.setLayout(new BorderLayout());
closer = new Closer();
}
public Component add(Component c) {
container.add(c, BorderLayout.CENTER);
return c;
}
void setCloser(Runnable action, int time) {
closer.set(action, time);
}
// Must be executed on EDT.
protected void show(Point corner, int indent) {
assert SunToolkit.isDispatchThreadForAppContext(InfoWindow.this);
pack();
Dimension size = getSize();
// TODO: When 6356322 is fixed we should get screen bounds in
// this way: eframe.getGraphicsConfiguration().getBounds().
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
if (corner.x < scrSize.width/2 && corner.y < scrSize.height/2) { // 1st square
setLocation(corner.x + indent, corner.y + indent);
} else if (corner.x >= scrSize.width/2 && corner.y < scrSize.height/2) { // 2nd square
setLocation(corner.x - indent - size.width, corner.y + indent);
} else if (corner.x < scrSize.width/2 && corner.y >= scrSize.height/2) { // 3rd square
setLocation(corner.x + indent, corner.y - indent - size.height);
} else if (corner.x >= scrSize.width/2 && corner.y >= scrSize.height/2) { // 4th square
setLocation(corner.x - indent - size.width, corner.y - indent - size.height);
}
InfoWindow.super.show();
InfoWindow.this.closer.schedule();
}
public void hide() {
closer.close();
}
class Closer implements Runnable {
Runnable action;
int time;
public void run() {
doClose();
}
void set(Runnable action, int time) {
this.action = action;
this.time = time;
}
void schedule() {
XToolkit.schedule(this, time);
}
void close() {
XToolkit.remove(this);
doClose();
}
// WARNING: this method may be executed on Toolkit thread.
private void doClose() {
SunToolkit.executeOnEventHandlerThread(InfoWindow.this, new Runnable() {
public void run() {
InfoWindow.super.hide();
invalidate();
if (action != null) {
action.run();
}
}
});
}
}
}
} }
...@@ -896,7 +896,7 @@ final class XWM ...@@ -896,7 +896,7 @@ final class XWM
/* /*
* Set MWM decorations. Set MWM functions depending on resizability. * Set MWM decorations. Set MWM functions depending on resizability.
*/ */
static void setMotifDecor(XWindowPeer window, boolean resizable, int decorations, int functions) { static void setMotifDecor(XWindow window, boolean resizable, int decorations, int functions) {
/* Apparently some WMs don't implement MWM_*_ALL semantic correctly */ /* Apparently some WMs don't implement MWM_*_ALL semantic correctly */
if ((decorations & MWMConstants.MWM_DECOR_ALL) != 0 if ((decorations & MWMConstants.MWM_DECOR_ALL) != 0
&& (decorations != MWMConstants.MWM_DECOR_ALL)) && (decorations != MWMConstants.MWM_DECOR_ALL))
......
...@@ -25,16 +25,194 @@ ...@@ -25,16 +25,194 @@
package sun.awt.X11; package sun.awt.X11;
import java.awt.*; import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.lang.ref.WeakReference;
import sun.java2d.SunGraphics2D;
import sun.java2d.pipe.Region;
import sun.awt.AWTAccessor;
import sun.awt.SunToolkit;
class XWarningWindow extends XWindow { class XWarningWindow extends XWindow {
final static int defaultHeight = 27; private final static int showingDelay = 330;
private final static int hidingDelay = 2000;
Window ownerWindow; private final Window ownerWindow;
XWarningWindow(Window ownerWindow, long parentWindow) { private WeakReference<XWindowPeer> ownerPeer;
super(ownerWindow, parentWindow);
public final Window getOwnerWindow() {
return ownerWindow;
}
private long parentWindow;
private final static String OWNER = "OWNER";
private static XIconInfo[][] icons;
private InfoWindow.Tooltip tooltip;
private static synchronized XIconInfo getSecurityIconInfo(int size, int num) {
if (icons == null) {
icons = new XIconInfo[4][3];
if (XlibWrapper.dataModel == 32) {
icons[0][0] = new XIconInfo(XAWTIcon32_security_icon_bw16_png.security_icon_bw16_png);
icons[0][1] = new XIconInfo(XAWTIcon32_security_icon_interim16_png.security_icon_interim16_png);
icons[0][2] = new XIconInfo(XAWTIcon32_security_icon_yellow16_png.security_icon_yellow16_png);
icons[1][0] = new XIconInfo(XAWTIcon32_security_icon_bw24_png.security_icon_bw24_png);
icons[1][1] = new XIconInfo(XAWTIcon32_security_icon_interim24_png.security_icon_interim24_png);
icons[1][2] = new XIconInfo(XAWTIcon32_security_icon_yellow24_png.security_icon_yellow24_png);
icons[2][0] = new XIconInfo(XAWTIcon32_security_icon_bw32_png.security_icon_bw32_png);
icons[2][1] = new XIconInfo(XAWTIcon32_security_icon_interim32_png.security_icon_interim32_png);
icons[2][2] = new XIconInfo(XAWTIcon32_security_icon_yellow32_png.security_icon_yellow32_png);
icons[3][0] = new XIconInfo(XAWTIcon32_security_icon_bw48_png.security_icon_bw48_png);
icons[3][1] = new XIconInfo(XAWTIcon32_security_icon_interim48_png.security_icon_interim48_png);
icons[3][2] = new XIconInfo(XAWTIcon32_security_icon_yellow48_png.security_icon_yellow48_png);
} else {
icons[0][0] = new XIconInfo(XAWTIcon64_security_icon_bw16_png.security_icon_bw16_png);
icons[0][1] = new XIconInfo(XAWTIcon64_security_icon_interim16_png.security_icon_interim16_png);
icons[0][2] = new XIconInfo(XAWTIcon64_security_icon_yellow16_png.security_icon_yellow16_png);
icons[1][0] = new XIconInfo(XAWTIcon64_security_icon_bw24_png.security_icon_bw24_png);
icons[1][1] = new XIconInfo(XAWTIcon64_security_icon_interim24_png.security_icon_interim24_png);
icons[1][2] = new XIconInfo(XAWTIcon64_security_icon_yellow24_png.security_icon_yellow24_png);
icons[2][0] = new XIconInfo(XAWTIcon64_security_icon_bw32_png.security_icon_bw32_png);
icons[2][1] = new XIconInfo(XAWTIcon64_security_icon_interim32_png.security_icon_interim32_png);
icons[2][2] = new XIconInfo(XAWTIcon64_security_icon_yellow32_png.security_icon_yellow32_png);
icons[3][0] = new XIconInfo(XAWTIcon64_security_icon_bw48_png.security_icon_bw48_png);
icons[3][1] = new XIconInfo(XAWTIcon64_security_icon_interim48_png.security_icon_interim48_png);
icons[3][2] = new XIconInfo(XAWTIcon64_security_icon_yellow48_png.security_icon_yellow48_png);
}
}
final int sizeIndex = size % icons.length;
return icons[sizeIndex][num % icons[sizeIndex].length];
}
private volatile int currentIcon = 0;
/* -1 - uninitialized yet
* 0 - 16x16
* 1 - 24x24
* 2 - 32x32
* 3 - 48x48
*/
private volatile int currentSize = -1;
/** Indicates whether the shape of the window must be updated
*/
private volatile boolean sizeUpdated = true;
private synchronized boolean updateIconSize() {
int newSize = currentSize;
if (ownerWindow != null) {
Insets insets = ownerWindow.getInsets();
int max = Math.max(insets.top, Math.max(insets.bottom,
Math.max(insets.left, insets.right)));
if (max < 24) {
newSize = 0;
} else if (max < 32) {
newSize = 1;
} else if (max < 48) {
newSize = 2;
} else {
newSize = 3;
}
}
if (newSize != currentSize) {
currentSize = newSize;
sizeUpdated = true;
}
return sizeUpdated;
}
private synchronized XIconInfo getSecurityIconInfo() {
updateIconSize();
return getSecurityIconInfo(currentSize, currentIcon);
}
XWarningWindow(final Window ownerWindow, long parentWindow, XWindowPeer ownerPeer) {
super(new XCreateWindowParams(new Object[] {
TARGET, ownerWindow,
OWNER, Long.valueOf(parentWindow)
}));
this.ownerWindow = ownerWindow; this.ownerWindow = ownerWindow;
xSetVisible(true); this.parentWindow = parentWindow;
toFront(); this.tooltip = new InfoWindow.Tooltip(null, getTarget(),
new InfoWindow.Tooltip.LiveArguments() {
public boolean isDisposed() {
return XWarningWindow.this.isDisposed();
}
public Rectangle getBounds() {
return XWarningWindow.this.getBounds();
}
public String getTooltipString() {
return XWarningWindow.this.ownerWindow.getWarningString();
}
});
this.ownerPeer = new WeakReference<XWindowPeer>(ownerPeer);
}
private void requestNoTaskbar() {
XNETProtocol netProtocol = XWM.getWM().getNETProtocol();
if (netProtocol != null) {
netProtocol.requestState(this, netProtocol.XA_NET_WM_STATE_SKIP_TASKBAR, true);
}
}
@Override
void postInit(XCreateWindowParams params) {
super.postInit(params);
XToolkit.awtLock();
try {
XWM.setMotifDecor(this, false, 0, 0);
XWM.setOLDecor(this, false, 0);
long parentWindow = ((Long)params.get(OWNER)).longValue();
XlibWrapper.XSetTransientFor(XToolkit.getDisplay(),
getWindow(), parentWindow);
XWMHints hints = getWMHints();
hints.set_flags(hints.get_flags() | (int)XUtilConstants.InputHint | (int)XUtilConstants.StateHint);
hints.set_input(false);
hints.set_initial_state(XUtilConstants.NormalState);
XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
initWMProtocols();
requestNoTaskbar();
} finally {
XToolkit.awtUnlock();
}
}
private void updateWarningWindowBounds() {
XWindowPeer peer = ownerPeer.get();
if (peer != null) {
synchronized (this) {
if (updateIconSize()) {
XIconInfo ico = getSecurityIconInfo();
XToolkit.awtLock();
try {
XlibWrapper.SetBitmapShape(XToolkit.getDisplay(), getWindow(),
ico.getWidth(), ico.getHeight(), ico.getIntData());
} finally {
XToolkit.awtUnlock();
}
sizeUpdated = false;
AWTAccessor.getWindowAccessor().setSecurityWarningSize(
ownerWindow, ico.getWidth(), ico.getHeight());
}
}
peer.repositionSecurityWarning();
}
}
/**
* @param x,y,w,h coordinates of the untrusted window
*/
public void reposition(int x, int y, int w, int h) {
Point2D point = AWTAccessor.getWindowAccessor().
calculateSecurityWarningPosition(ownerWindow,
x, y, w, h);
reshape((int)point.getX(), (int)point.getY(), getWidth(), getHeight());
} }
protected String getWMName() { protected String getWMName() {
...@@ -49,33 +227,19 @@ class XWarningWindow extends XWindow { ...@@ -49,33 +227,19 @@ class XWarningWindow extends XWindow {
getFont()); getFont());
} }
void paint(Graphics g, int x, int y, int width, int height) { void paint(Graphics g, int x, int y, int width, int height) {
String warningString = getWarningString(); g.drawImage(getSecurityIconInfo().getImage(), 0, 0, null);
Rectangle bounds = getBounds();
bounds.x = 0;
bounds.y = 0;
Rectangle updateRect = new Rectangle(x, y, width, height);
if (updateRect.intersects(bounds)) {
Rectangle updateArea = updateRect.intersection(bounds);
g.setClip(updateArea);
g.setColor(getBackground());
g.fillRect(updateArea.x, updateArea.y, updateArea.width, updateArea.height);
g.setColor(getColor());
g.setFont(getFont());
FontMetrics fm = g.getFontMetrics();
int warningWidth = fm.stringWidth(warningString);
int w_x = (bounds.width - warningWidth)/2;
int w_y = (bounds.height + fm.getMaxAscent() - fm.getMaxDescent())/2;
g.drawString(warningString, w_x, w_y);
g.drawLine(bounds.x, bounds.y+bounds.height-1, bounds.x+bounds.width-1, bounds.y+bounds.height-1);
}
} }
String getWarningString() { String getWarningString() {
return ownerWindow.getWarningString(); return ownerWindow.getWarningString();
} }
int getWidth() {
return getSecurityIconInfo().getWidth();
}
int getHeight() { int getHeight() {
return defaultHeight; // should implement depending on Font return getSecurityIconInfo().getHeight();
} }
Color getBackground() { Color getBackground() {
...@@ -97,6 +261,7 @@ class XWarningWindow extends XWindow { ...@@ -97,6 +261,7 @@ class XWarningWindow extends XWindow {
} }
} }
@Override
public void handleExposeEvent(XEvent xev) { public void handleExposeEvent(XEvent xev) {
super.handleExposeEvent(xev); super.handleExposeEvent(xev);
...@@ -105,18 +270,156 @@ class XWarningWindow extends XWindow { ...@@ -105,18 +270,156 @@ class XWarningWindow extends XWindow {
final int y = xe.get_y(); final int y = xe.get_y();
final int width = xe.get_width(); final int width = xe.get_width();
final int height = xe.get_height(); final int height = xe.get_height();
EventQueue.invokeLater(new Runnable() { SunToolkit.executeOnEventHandlerThread(target,
public void run() { new Runnable() {
Graphics g = getGraphics(); public void run() {
try { Graphics g = getGraphics();
paint(g, x, y, width, height); try {
} finally { paint(g, x, y, width, height);
g.dispose(); } finally {
} g.dispose();
} }
}); }
});
} }
@Override
protected boolean isEventDisabled(XEvent e) { protected boolean isEventDisabled(XEvent e) {
return true; return true;
} }
/** Send a synthetic UnmapNotify in order to withdraw the window.
*/
private void withdraw() {
XEvent req = new XEvent();
try {
long root;
XToolkit.awtLock();
try {
root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
}
finally {
XToolkit.awtUnlock();
}
req.set_type(XConstants.UnmapNotify);
XUnmapEvent umev = req.get_xunmap();
umev.set_event(root);
umev.set_window(getWindow());
umev.set_from_configure(false);
XToolkit.awtLock();
try {
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
root,
false,
XConstants.SubstructureRedirectMask | XConstants.SubstructureNotifyMask,
req.pData);
}
finally {
XToolkit.awtUnlock();
}
} finally {
req.dispose();
}
}
@Override
protected void stateChanged(long time, int oldState, int newState) {
if (newState == XUtilConstants.IconicState) {
super.xSetVisible(false);
withdraw();
}
}
@Override
protected void setMouseAbove(boolean above) {
super.setMouseAbove(above);
XWindowPeer p = ownerPeer.get();
if (p != null) {
p.updateSecurityWarningVisibility();
}
}
@Override
protected void enterNotify(long window) {
super.enterNotify(window);
if (window == getWindow()) {
tooltip.enter();
}
}
@Override
protected void leaveNotify(long window) {
super.leaveNotify(window);
if (window == getWindow()) {
tooltip.exit();
}
}
@Override
public void xSetVisible(boolean visible) {
super.xSetVisible(visible);
// The _NET_WM_STATE_SKIP_TASKBAR got reset upon hiding/showing,
// so we request it every time whenever we change the visibility.
requestNoTaskbar();
}
private final Runnable hidingTask = new Runnable() {
public void run() {
xSetVisible(false);
}
};
private final Runnable showingTask = new Runnable() {
public void run() {
new Thread() {
public void run() {
if (!isVisible()) {
xSetVisible(true);
updateWarningWindowBounds();
}
repaint();
if (currentIcon > 0) {
currentIcon--;
XToolkit.schedule(showingTask, showingDelay);
}
}}.start();
}
};
public void setSecurityWarningVisible(boolean visible) {
setSecurityWarningVisible(visible, true);
}
public void setSecurityWarningVisible(boolean visible, boolean doSchedule) {
if (visible) {
XToolkit.remove(hidingTask);
XToolkit.remove(showingTask);
if (isVisible()) {
currentIcon = 0;
} else {
currentIcon = 3;
}
if (doSchedule) {
XToolkit.schedule(showingTask, 1);
} else {
showingTask.run();
}
} else {
XToolkit.remove(showingTask);
XToolkit.remove(hidingTask);
if (!isVisible()) {
return;
}
if (doSchedule) {
XToolkit.schedule(hidingTask, hidingDelay);
} else {
hidingTask.run();
}
}
}
} }
...@@ -68,6 +68,15 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { ...@@ -68,6 +68,15 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
int oldWidth = -1; int oldWidth = -1;
int oldHeight = -1; int oldHeight = -1;
protected PropMwmHints mwm_hints;
protected static XAtom wm_protocols;
protected static XAtom wm_delete_window;
protected static XAtom wm_take_focus;
private boolean stateChanged; // Indicates whether the value on savedState is valid
private int savedState; // Holds last known state of the top-level window
XWindowAttributesData winAttr;
protected X11GraphicsConfig graphicsConfig; protected X11GraphicsConfig graphicsConfig;
protected AwtGraphicsConfigData graphicsConfigData; protected AwtGraphicsConfigData graphicsConfigData;
...@@ -218,6 +227,20 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { ...@@ -218,6 +227,20 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
} }
params.putIfNull(BACKING_STORE, XToolkit.getBackingStoreType()); params.putIfNull(BACKING_STORE, XToolkit.getBackingStoreType());
XToolkit.awtLock();
try {
if (wm_protocols == null) {
wm_protocols = XAtom.get("WM_PROTOCOLS");
wm_delete_window = XAtom.get("WM_DELETE_WINDOW");
wm_take_focus = XAtom.get("WM_TAKE_FOCUS");
}
}
finally {
XToolkit.awtUnlock();
}
winAttr = new XWindowAttributesData();
savedState = XUtilConstants.WithdrawnState;
} }
void postInit(XCreateWindowParams params) { void postInit(XCreateWindowParams params) {
...@@ -832,12 +855,42 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { ...@@ -832,12 +855,42 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
public native boolean x11inputMethodLookupString(long event, long [] keysymArray); public native boolean x11inputMethodLookupString(long event, long [] keysymArray);
native boolean haveCurrentX11InputMethodInstance(); native boolean haveCurrentX11InputMethodInstance();
private boolean mouseAboveMe;
public boolean isMouseAbove() {
synchronized (getStateLock()) {
return mouseAboveMe;
}
}
protected void setMouseAbove(boolean above) {
synchronized (getStateLock()) {
mouseAboveMe = above;
}
}
protected void enterNotify(long window) {
if (window == getWindow()) {
setMouseAbove(true);
}
}
protected void leaveNotify(long window) {
if (window == getWindow()) {
setMouseAbove(false);
}
}
public void handleXCrossingEvent(XEvent xev) { public void handleXCrossingEvent(XEvent xev) {
super.handleXCrossingEvent(xev); super.handleXCrossingEvent(xev);
XCrossingEvent xce = xev.get_xcrossing(); XCrossingEvent xce = xev.get_xcrossing();
if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString()); if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xce.toString());
if (xce.get_type() == XConstants.EnterNotify) {
enterNotify(xce.get_window());
} else { // LeaveNotify:
leaveNotify(xce.get_window());
}
// Skip event If it was caused by a grab // Skip event If it was caused by a grab
// This is needed because on displays with focus-follows-mouse on MousePress X system generates // This is needed because on displays with focus-follows-mouse on MousePress X system generates
// two XCrossing events with mode != NormalNotify. First of them notifies that the mouse has left // two XCrossing events with mode != NormalNotify. First of them notifies that the mouse has left
...@@ -1133,6 +1186,55 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { ...@@ -1133,6 +1186,55 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
} }
/*
* XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
* unreliable, since mapping changes can happen for a virtual desktop
* switch or MacOS style shading that became quite popular under X as
* well. Yes, it probably should not be this way, as it violates
* ICCCM, but reality is that quite a lot of window managers abuse
* mapping state.
*/
int getWMState() {
if (stateChanged) {
stateChanged = false;
WindowPropertyGetter getter =
new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false,
XWM.XA_WM_STATE);
try {
int status = getter.execute();
if (status != XConstants.Success || getter.getData() == 0) {
return savedState = XUtilConstants.WithdrawnState;
}
if (getter.getActualType() != XWM.XA_WM_STATE.getAtom() && getter.getActualFormat() != 32) {
return savedState = XUtilConstants.WithdrawnState;
}
savedState = (int)Native.getCard32(getter.getData());
} finally {
getter.dispose();
}
}
return savedState;
}
/**
* Override this methods to get notifications when top-level window state changes. The state is
* meant in terms of ICCCM: WithdrawnState, IconicState, NormalState
*/
protected void stateChanged(long time, int oldState, int newState) {
}
@Override
public void handlePropertyNotify(XEvent xev) {
super.handlePropertyNotify(xev);
XPropertyEvent ev = xev.get_xproperty();
if (ev.get_atom() == XWM.XA_WM_STATE.getAtom()) {
// State has changed, invalidate saved value
stateChanged = true;
stateChanged(ev.get_time(), savedState, getWMState());
}
}
public void reshape(Rectangle bounds) { public void reshape(Rectangle bounds) {
reshape(bounds.x, bounds.y, bounds.width, bounds.height); reshape(bounds.x, bounds.y, bounds.width, bounds.height);
} }
...@@ -1293,4 +1395,40 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer { ...@@ -1293,4 +1395,40 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
static native int getAWTKeyCodeForKeySym(int keysym); static native int getAWTKeyCodeForKeySym(int keysym);
static native int getKeySymForAWTKeyCode(int keycode); static native int getKeySymForAWTKeyCode(int keycode);
/* These two methods are actually applicable to toplevel windows only.
* However, the functionality is required by both the XWindowPeer and
* XWarningWindow, both of which have the XWindow as a common ancestor.
* See XWM.setMotifDecor() for details.
*/
public PropMwmHints getMWMHints() {
if (mwm_hints == null) {
mwm_hints = new PropMwmHints();
if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS)) {
mwm_hints.zero();
}
}
return mwm_hints;
}
public void setMWMHints(PropMwmHints hints) {
mwm_hints = hints;
if (hints != null) {
XWM.XA_MWM_HINTS.setAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS);
}
}
protected final void initWMProtocols() {
wm_protocols.setAtomListProperty(this, getWMProtocols());
}
/**
* Returns list of protocols which should be installed on this window.
* Descendants can override this method to add class-specific protocols
*/
protected XAtomList getWMProtocols() {
// No protocols on simple window
return new XAtomList();
}
} }
...@@ -67,16 +67,11 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -67,16 +67,11 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
// should be synchronized on awtLock // should be synchronized on awtLock
private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>(); private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
static XAtom wm_protocols;
static XAtom wm_delete_window;
static XAtom wm_take_focus;
XWindowAttributesData winAttr;
private boolean cachedFocusableWindow; private boolean cachedFocusableWindow;
XWarningWindow warningWindow; XWarningWindow warningWindow;
private boolean alwaysOnTop; private boolean alwaysOnTop;
PropMwmHints mwm_hints;
private boolean locationByPlatform; private boolean locationByPlatform;
Dialog modalBlocker; Dialog modalBlocker;
...@@ -93,8 +88,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -93,8 +88,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
private boolean grab = false; // Whether to do a grab during showing private boolean grab = false; // Whether to do a grab during showing
private boolean isMapped = false; // Is this window mapped or not private boolean isMapped = false; // Is this window mapped or not
private boolean stateChanged; // Indicates whether the value on savedState is valid
private int savedState; // Holds last known state of the top-level window
private boolean mustControlStackPosition = false; // Am override-redirect not on top private boolean mustControlStackPosition = false; // Am override-redirect not on top
private XEventDispatcher rootPropertyEventDispatcher = null; private XEventDispatcher rootPropertyEventDispatcher = null;
...@@ -141,25 +134,18 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -141,25 +134,18 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
super.preInit(params); super.preInit(params);
params.putIfNull(BIT_GRAVITY, Integer.valueOf(XConstants.NorthWestGravity)); params.putIfNull(BIT_GRAVITY, Integer.valueOf(XConstants.NorthWestGravity));
savedState = XUtilConstants.WithdrawnState; long eventMask = 0;
if (params.containsKey(EVENT_MASK)) {
eventMask = ((Long)params.get(EVENT_MASK));
}
eventMask |= XConstants.VisibilityChangeMask;
params.put(EVENT_MASK, eventMask);
XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE"); XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");
winAttr = new XWindowAttributesData();
params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect())); params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect()));
SunToolkit.awtLock();
try {
windows.add(this);
if (wm_protocols == null) {
wm_protocols = XAtom.get("WM_PROTOCOLS");
wm_delete_window = XAtom.get("WM_DELETE_WINDOW");
wm_take_focus = XAtom.get("WM_TAKE_FOCUS");
}
}
finally {
SunToolkit.awtUnlock();
}
cachedFocusableWindow = isFocusableWindow(); cachedFocusableWindow = isFocusableWindow();
Font f = target.getFont(); Font f = target.getFont();
...@@ -192,20 +178,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -192,20 +178,6 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
params.put(BOUNDS, constrainBounds(bounds.x, bounds.y, bounds.width, bounds.height)); params.put(BOUNDS, constrainBounds(bounds.x, bounds.y, bounds.width, bounds.height));
} }
private void initWMProtocols() {
wm_protocols.setAtomListProperty(this, getWMProtocols());
}
/**
* Returns list of protocols which should be installed on this window.
* Descendants can override this method to add class-specific protocols
*/
protected XAtomList getWMProtocols() {
// No protocols on simple window
return new XAtomList();
}
protected String getWMName() { protected String getWMName() {
String name = target.getName(); String name = target.getName();
if (name == null || name.trim().equals("")) { if (name == null || name.trim().equals("")) {
...@@ -259,7 +231,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -259,7 +231,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
// accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip // accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip
// and TrayIcon balloon windows without a warning window. // and TrayIcon balloon windows without a warning window.
if (!WindowAccessor.isTrayIconWindow((Window)target)) { if (!WindowAccessor.isTrayIconWindow((Window)target)) {
warningWindow = new XWarningWindow((Window)target, getWindow()); warningWindow = new XWarningWindow((Window)target, getWindow(), this);
} }
} }
...@@ -539,10 +511,15 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -539,10 +511,15 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
} }
if (!bounds.getSize().equals(oldBounds.getSize())) { boolean isResized = !bounds.getSize().equals(oldBounds.getSize());
boolean isMoved = !bounds.getLocation().equals(oldBounds.getLocation());
if (isMoved || isResized) {
repositionSecurityWarning();
}
if (isResized) {
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED)); postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED));
} }
if (!bounds.getLocation().equals(oldBounds.getLocation())) { if (isMoved) {
postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED)); postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED));
} }
} finally { } finally {
...@@ -565,7 +542,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -565,7 +542,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
} }
public Insets getInsets() { public Insets getInsets() {
return new Insets(getWarningWindowHeight(), 0, 0, 0); return new Insets(0, 0, 0, 0);
} }
// NOTE: This method may be called by privileged threads. // NOTE: This method may be called by privileged threads.
...@@ -780,6 +757,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -780,6 +757,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
* Overridden to check if we need to update our GraphicsDevice/Config * Overridden to check if we need to update our GraphicsDevice/Config
* Added for 4934052. * Added for 4934052.
*/ */
@Override
public void handleConfigureNotifyEvent(XEvent xev) { public void handleConfigureNotifyEvent(XEvent xev) {
// TODO: We create an XConfigureEvent every time we override // TODO: We create an XConfigureEvent every time we override
// handleConfigureNotify() - too many! // handleConfigureNotify() - too many!
...@@ -793,8 +771,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -793,8 +771,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
// there could be a race condition in which a ComponentListener could // there could be a race condition in which a ComponentListener could
// see the old screen. // see the old screen.
super.handleConfigureNotifyEvent(xev); super.handleConfigureNotifyEvent(xev);
// for 5085647: no applet warning window visible repositionSecurityWarning();
updateChildrenSizes();
} }
final void requestXFocus(long time) { final void requestXFocus(long time) {
...@@ -1072,6 +1049,9 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -1072,6 +1049,9 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
} }
updateFocusability(); updateFocusability();
promoteDefaultPosition(); promoteDefaultPosition();
if (!vis && warningWindow != null) {
warningWindow.setSecurityWarningVisible(false, false);
}
super.setVisible(vis); super.setVisible(vis);
if (!vis && !isWithdrawn()) { if (!vis && !isWithdrawn()) {
// ICCCM, 4.1.4. Changing Window State: // ICCCM, 4.1.4. Changing Window State:
...@@ -1101,6 +1081,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -1101,6 +1081,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
if (isOverrideRedirect() && vis) { if (isOverrideRedirect() && vis) {
updateChildrenSizes(); updateChildrenSizes();
} }
repositionSecurityWarning();
} }
protected void suppressWmTakeFocus(boolean doSuppress) { protected void suppressWmTakeFocus(boolean doSuppress) {
...@@ -1118,21 +1099,64 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -1118,21 +1099,64 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
return 0; return 0;
} }
// The height of area used to display Applet's warning about securit
int getWarningWindowHeight() {
if (warningWindow != null) {
return warningWindow.getHeight();
} else {
return 0;
}
}
// Called when shell changes its size and requires children windows // Called when shell changes its size and requires children windows
// to update their sizes appropriately // to update their sizes appropriately
void updateChildrenSizes() { void updateChildrenSizes() {
}
public void repositionSecurityWarning() {
// NOTE: On KWin if the window/border snapping option is enabled,
// the Java window may be swinging while it's being moved.
// This doesn't make the application unusable though looks quite ugly.
// Probobly we need to find some hint to assign to our Security
// Warning window in order to exclude it from the snapping option.
// We are not currently aware of existance of such a property.
if (warningWindow != null) { if (warningWindow != null) {
warningWindow.reshape(0, getMenuBarHeight(), getSize().width, warningWindow.getHeight()); // We can't use the coordinates stored in the XBaseWindow since
// they are zeros for decorated frames.
int x = ComponentAccessor.getX(target);
int y = ComponentAccessor.getY(target);
int width = ComponentAccessor.getWidth(target);
int height = ComponentAccessor.getHeight(target);
warningWindow.reposition(x, y, width, height);
}
}
@Override
protected void setMouseAbove(boolean above) {
super.setMouseAbove(above);
updateSecurityWarningVisibility();
}
public void updateSecurityWarningVisibility() {
if (warningWindow == null) {
return;
}
boolean show = false;
int state = getWMState();
if (!isVisible()) {
return; // The warning window should already be hidden.
}
// getWMState() always returns 0 (Withdrawn) for simple windows. Hence
// we ignore the state for such windows.
if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) {
if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() ==
getTarget())
{
show = true;
}
if (isMouseAbove() || warningWindow.isMouseAbove())
{
show = true;
}
} }
warningWindow.setSecurityWarningVisible(show);
} }
boolean isOverrideRedirect() { boolean isOverrideRedirect() {
...@@ -1184,16 +1208,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -1184,16 +1208,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
// if (ve.get_state() == XlibWrapper.VisibilityUnobscured) { // if (ve.get_state() == XlibWrapper.VisibilityUnobscured) {
// // raiseInputMethodWindow // // raiseInputMethodWindow
// } // }
} repositionSecurityWarning();
public void handlePropertyNotify(XEvent xev) {
super.handlePropertyNotify(xev);
XPropertyEvent ev = xev.get_xproperty();
if (ev.get_atom() == XWM.XA_WM_STATE.getAtom()) {
// State has changed, invalidate saved value
stateChanged = true;
stateChanged(ev.get_time(), savedState, getWMState());
}
} }
void handleRootPropertyNotify(XEvent xev) { void handleRootPropertyNotify(XEvent xev) {
...@@ -1294,6 +1309,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -1294,6 +1309,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
* Override this methods to get notifications when top-level window state changes. The state is * Override this methods to get notifications when top-level window state changes. The state is
* meant in terms of ICCCM: WithdrawnState, IconicState, NormalState * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState
*/ */
@Override
protected void stateChanged(long time, int oldState, int newState) { protected void stateChanged(long time, int oldState, int newState) {
// Fix for 6401700, 6412803 // Fix for 6401700, 6412803
// If this window is modal blocked, it is put into the transient_for // If this window is modal blocked, it is put into the transient_for
...@@ -1307,38 +1323,8 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, ...@@ -1307,38 +1323,8 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) { for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
topLevelListenerTmp.stateChangedICCCM(oldState, newState); topLevelListenerTmp.stateChangedICCCM(oldState, newState);
} }
}
/* updateSecurityWarningVisibility();
* XmNiconic and Map/UnmapNotify (that XmNiconic relies on) are
* unreliable, since mapping changes can happen for a virtual desktop
* switch or MacOS style shading that became quite popular under X as
* well. Yes, it probably should not be this way, as it violates
* ICCCM, but reality is that quite a lot of window managers abuse
* mapping state.
*/
int getWMState() {
if (stateChanged) {
stateChanged = false;
WindowPropertyGetter getter =
new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false,
XWM.XA_WM_STATE);
try {
int status = getter.execute();
if (status != XConstants.Success || getter.getData() == 0) {
return savedState = XUtilConstants.WithdrawnState;
}
if (getter.getActualType() != XWM.XA_WM_STATE.getAtom() && getter.getActualFormat() != 32) {
return savedState = XUtilConstants.WithdrawnState;
}
savedState = (int)Native.getCard32(getter.getData());
} finally {
getter.dispose();
}
}
return savedState;
} }
boolean isWithdrawn() { boolean isWithdrawn() {
......
...@@ -156,6 +156,8 @@ Window w; ...@@ -156,6 +156,8 @@ Window w;
static native void XLowerWindow(long display, long window); static native void XLowerWindow(long display, long window);
static native void XRestackWindows(long display, long windows, int length); static native void XRestackWindows(long display, long windows, int length);
static native void XConfigureWindow(long display, long window,
long value_mask, long values);
static native void XSetInputFocus(long display, long window); static native void XSetInputFocus(long display, long window);
static native void XSetInputFocus2(long display, long window, long time); static native void XSetInputFocus2(long display, long window, long time);
static native long XGetInputFocus(long display); static native long XGetInputFocus(long display);
...@@ -533,6 +535,12 @@ static native String XSetLocaleModifiers(String modifier_list); ...@@ -533,6 +535,12 @@ static native String XSetLocaleModifiers(String modifier_list);
static native void SetRectangularShape(long display, long window, static native void SetRectangularShape(long display, long window,
int lox, int loy, int hix, int hiy, int lox, int loy, int hix, int hiy,
sun.java2d.pipe.Region region); sun.java2d.pipe.Region region);
/** Each int in the bitmap array is one pixel with a 32-bit color:
* R, G, B, and Alpha.
*/
static native void SetBitmapShape(long display, long window,
int width, int height, int[] bitmap);
static native void SetZOrder(long display, long window, long above); static native void SetZOrder(long display, long window, long above);
/* Global memory area used for X lib parameter passing */ /* Global memory area used for X lib parameter passing */
......
...@@ -43,4 +43,15 @@ typedef XRectangle RECT_T; ...@@ -43,4 +43,15 @@ typedef XRectangle RECT_T;
#define RECT_INC_HEIGHT(r) (r).height++ #define RECT_INC_HEIGHT(r) (r).height++
#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 #endif // _AWT_RECT_H
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <jvm.h> #include <jvm.h>
#include <Region.h> #include <Region.h>
#include "utility/rect.h"
#if defined(DEBUG) || defined(INTERNAL_BUILD) #if defined(DEBUG) || defined(INTERNAL_BUILD)
static jmethodID lockIsHeldMID = NULL; static jmethodID lockIsHeldMID = NULL;
...@@ -303,6 +304,20 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XRestackWindows ...@@ -303,6 +304,20 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XRestackWindows
} }
/*
* Class: XlibWrapper
* Method: XConfigureWindow
* Signature: (JJJJ)V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XConfigureWindow
(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong value_mask,
jlong values)
{
AWT_CHECK_HAVE_LOCK();
XConfigureWindow((Display*)jlong_to_ptr(display), (Window)window,
(unsigned int)value_mask, (XWindowChanges*)jlong_to_ptr(values));
}
/* /*
* Class: XlibWrapper * Class: XlibWrapper
* Method: XSetInputFocus * Method: XSetInputFocus
...@@ -1973,3 +1988,49 @@ Java_sun_awt_X11_XlibWrapper_SetZOrder ...@@ -1973,3 +1988,49 @@ Java_sun_awt_X11_XlibWrapper_SetZOrder
(Window)jlong_to_ptr(window), (Window)jlong_to_ptr(window),
value_mask, &wc ); value_mask, &wc );
} }
/*
* Class: XlibWrapper
* Method: SetBitmapShape
*/
JNIEXPORT void JNICALL
Java_sun_awt_X11_XlibWrapper_SetBitmapShape
(JNIEnv *env, jclass clazz, jlong display, jlong window,
jint width, jint height, jintArray bitmap)
{
jsize len;
jint *values;
jboolean isCopy = JNI_FALSE;
size_t worstBufferSize = (size_t)((width / 2 + 1) * height);
RECT_T * pRect;
AWT_CHECK_HAVE_LOCK();
len = (*env)->GetArrayLength(env, bitmap);
if (len == 0 || len < width * height) {
return;
}
values = (*env)->GetIntArrayElements(env, bitmap, &isCopy);
if (JNU_IsNull(env, values)) {
return;
}
pRect = (RECT_T *)malloc(worstBufferSize * sizeof(RECT_T));
/* Note: the values[0] and values[1] are supposed to contain the width
* and height (see XIconInfo.getIntData() for details). So, we do +2.
*/
int numrects = BitmapToYXBandedRectangles(32, (int)width, (int)height,
(unsigned char *)(values + 2), pRect);
XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window),
ShapeClip, 0, 0, pRect, numrects, ShapeSet, YXBanded);
XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window),
ShapeBounding, 0, 0, pRect, numrects, ShapeSet, YXBanded);
free(pRect);
(*env)->ReleaseIntArrayElements(env, bitmap, values, JNI_ABORT);
}
...@@ -547,8 +547,10 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, ...@@ -547,8 +547,10 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
private volatile int sysH = 0; private volatile int sysH = 0;
Rectangle constrainBounds(int x, int y, int width, int height) { 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. // 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); return new Rectangle(x, y, width, height);
} }
...@@ -557,24 +559,24 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, ...@@ -557,24 +559,24 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
int newW = width; int newW = width;
int newH = height; int newH = height;
GraphicsConfiguration gc = ((Window)target).getGraphicsConfiguration();
Rectangle sB = gc.getBounds(); 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 screenW = sB.width - sIn.left - sIn.right;
int screenH = sB.height - sIn.top - sIn.bottom; int screenH = sB.height - sIn.top - sIn.bottom;
// If it's undecorated or is not currently visible // 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 // Now check each point is within the visible part of the screen
int screenX = sB.x + sIn.left; int screenX = sB.x + sIn.left;
int screenY = sB.y + sIn.top; 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) { if (newW > screenW) {
newW = screenW; newW = screenW;
} }
if (newH > screenH) { if (newH > screenH) {
newH = screenH; newH = screenH;
} }
...@@ -585,7 +587,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, ...@@ -585,7 +587,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
} else if (newX + newW > screenX + screenW) { } else if (newX + newW > screenX + screenW) {
newX = screenX + screenW - newW; newX = screenX + screenW - newW;
} }
if (newY < screenY) { if (newY < screenY) {
newY = screenY; newY = screenY;
} else if (newY + newH > screenY + screenH) { } else if (newY + newH > screenY + screenH) {
...@@ -600,7 +601,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, ...@@ -600,7 +601,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
if (newW > maxW) { if (newW > maxW) {
newW = maxW; newW = maxW;
} }
if (newH > maxH) { if (newH > maxH) {
newH = maxH; newH = maxH;
} }
...@@ -609,6 +609,8 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, ...@@ -609,6 +609,8 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
return new Rectangle(newX, newY, newW, newH); return new Rectangle(newX, newY, newW, newH);
} }
public native void repositionSecurityWarning();
@Override @Override
public void setBounds(int x, int y, int width, int height, int op) { public void setBounds(int x, int y, int width, int height, int op) {
Rectangle newBounds = constrainBounds(x, y, width, height); Rectangle newBounds = constrainBounds(x, y, width, height);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "ComCtl32Util.h" #include "ComCtl32Util.h"
ComCtl32Util::ComCtl32Util() { ComCtl32Util::ComCtl32Util() {
m_bToolTipControlInitialized = FALSE;
} }
ComCtl32Util::~ComCtl32Util() { ComCtl32Util::~ComCtl32Util() {
...@@ -36,7 +37,8 @@ void ComCtl32Util::InitLibraries() { ...@@ -36,7 +37,8 @@ void ComCtl32Util::InitLibraries() {
INITCOMMONCONTROLSEX iccex; INITCOMMONCONTROLSEX iccex;
memset(&iccex, 0, sizeof(INITCOMMONCONTROLSEX)); memset(&iccex, 0, sizeof(INITCOMMONCONTROLSEX));
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX); iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
::InitCommonControlsEx(&iccex); iccex.dwICC = ICC_TAB_CLASSES;
m_bToolTipControlInitialized = ::InitCommonControlsEx(&iccex);
} }
WNDPROC ComCtl32Util::SubclassHWND(HWND hwnd, WNDPROC _WindowProc) { WNDPROC ComCtl32Util::SubclassHWND(HWND hwnd, WNDPROC _WindowProc) {
......
...@@ -40,6 +40,10 @@ class ComCtl32Util ...@@ -40,6 +40,10 @@ class ComCtl32Util
void InitLibraries(); void InitLibraries();
INLINE BOOL IsToolTipControlInitialized() {
return m_bToolTipControlInitialized;
}
WNDPROC SubclassHWND(HWND hwnd, WNDPROC _WindowProc); WNDPROC SubclassHWND(HWND hwnd, WNDPROC _WindowProc);
// DefWindowProc is the same as returned from SubclassHWND // DefWindowProc is the same as returned from SubclassHWND
void UnsubclassHWND(HWND hwnd, WNDPROC _WindowProc, WNDPROC _DefWindowProc); void UnsubclassHWND(HWND hwnd, WNDPROC _WindowProc, WNDPROC _DefWindowProc);
...@@ -50,6 +54,8 @@ class ComCtl32Util ...@@ -50,6 +54,8 @@ class ComCtl32Util
ComCtl32Util(); ComCtl32Util();
~ComCtl32Util(); ~ComCtl32Util();
BOOL m_bToolTipControlInitialized;
// comctl32.dll version 6 window proc // comctl32.dll version 6 window proc
static LRESULT CALLBACK SharedWindowProc(HWND hwnd, UINT message, static LRESULT CALLBACK SharedWindowProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam, WPARAM wParam, LPARAM lParam,
......
/*
* 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();
}
/*
* 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
...@@ -35,6 +35,13 @@ HAND_CURSOR CURSOR DISCARDABLE "hand.cur" ...@@ -35,6 +35,13 @@ HAND_CURSOR CURSOR DISCARDABLE "hand.cur"
AWT_ICON ICON DISCARDABLE "awt.ico" AWT_ICON ICON DISCARDABLE "awt.ico"
CHECK_BITMAP BITMAP DISCARDABLE "check.bmp" 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 // Version
......
...@@ -260,8 +260,7 @@ AwtComponent::~AwtComponent() ...@@ -260,8 +260,7 @@ AwtComponent::~AwtComponent()
* the native one anymore. So we can safely destroy component's * the native one anymore. So we can safely destroy component's
* handle. * handle.
*/ */
AwtToolkit::DestroyComponentHWND(m_hwnd); DestroyHWnd();
m_hwnd = NULL;
if (sm_getComponentCache == this) { if (sm_getComponentCache == this) {
sm_getComponentCache = NULL; sm_getComponentCache = NULL;
...@@ -575,6 +574,17 @@ AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title, ...@@ -575,6 +574,17 @@ AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title,
env->DeleteLocalRef(bkgrd); env->DeleteLocalRef(bkgrd);
} }
/*
* 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 * Returns hwnd for target on non Toolkit thread
*/ */
...@@ -4470,7 +4480,7 @@ ret: ...@@ -4470,7 +4480,7 @@ ret:
void* AwtComponent::GetNativeFocusedWindow() { void* AwtComponent::GetNativeFocusedWindow() {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
AwtComponent *comp = AwtComponent *comp =
AwtComponent::GetComponent(AwtComponent::sm_focusedWindow); AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL; return (comp != NULL) ? comp->GetTargetAsGlobalRef(env) : NULL;
} }
...@@ -4571,7 +4581,7 @@ AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when, ...@@ -4571,7 +4581,7 @@ AwtComponent::SendKeyEventToFocusOwner(jint id, jlong when,
* if focus owner is null, but focused window isn't * if focus owner is null, but focused window isn't
* we will send key event to focused window * 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()) { if (hwndTarget == GetHWnd()) {
SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, msg); SendKeyEvent(id, when, raw, cooked, modifiers, keyLocation, msg);
...@@ -5993,6 +6003,14 @@ void AwtComponent::PostUngrabEvent() { ...@@ -5993,6 +6003,14 @@ void AwtComponent::PostUngrabEvent() {
} }
} }
void AwtComponent::SetFocusedWindow(HWND window)
{
HWND old = sm_focusedWindow;
sm_focusedWindow = window;
AwtWindow::FocusedWindowChanged(old, window);
}
/************************************************************************ /************************************************************************
* Component native methods * Component native methods
*/ */
......
...@@ -137,12 +137,13 @@ public: ...@@ -137,12 +137,13 @@ public:
virtual void RegisterClass(); virtual void RegisterClass();
virtual void UnregisterClass(); virtual void UnregisterClass();
void CreateHWnd(JNIEnv *env, LPCWSTR title, virtual void CreateHWnd(JNIEnv *env, LPCWSTR title,
DWORD windowStyle, DWORD windowExStyle, DWORD windowStyle, DWORD windowExStyle,
int x, int y, int w, int h, int x, int y, int w, int h,
HWND hWndParent, HMENU hMenu, HWND hWndParent, HMENU hMenu,
COLORREF colorForeground, COLORREF colorBackground, COLORREF colorForeground, COLORREF colorBackground,
jobject peer); jobject peer);
virtual void DestroyHWnd();
void InitPeerGraphicsConfig(JNIEnv *env, jobject peer); void InitPeerGraphicsConfig(JNIEnv *env, jobject peer);
virtual void Dispose(); virtual void Dispose();
...@@ -670,8 +671,14 @@ public: ...@@ -670,8 +671,14 @@ public:
static void _SetZOrder(void *param); static void _SetZOrder(void *param);
static HWND sm_focusOwner; static HWND sm_focusOwner;
private:
static HWND sm_focusedWindow; static HWND sm_focusedWindow;
public:
static inline HWND GetFocusedWindow() { return sm_focusedWindow; }
static void SetFocusedWindow(HWND window);
static void _SetFocus(void *param); static void _SetFocus(void *param);
static void *SetNativeFocusOwner(void *self); static void *SetNativeFocusOwner(void *self);
......
...@@ -310,15 +310,20 @@ void AwtDialog::PopupOneDialog(HWND dialog, HWND blocker, BOOL isModalHook, HWND ...@@ -310,15 +310,20 @@ void AwtDialog::PopupOneDialog(HWND dialog, HWND blocker, BOOL isModalHook, HWND
// no beep/flash if the mouse was clicked in the taskbar menu // no beep/flash if the mouse was clicked in the taskbar menu
// or the dialog is currently inactive // or the dialog is currently inactive
if (!isModalHook && !onTaskbar && (dialog == prevFGWindow)) { if (!isModalHook && !onTaskbar && (dialog == prevFGWindow)) {
::MessageBeep(MB_OK); AnimateModalBlocker(dialog);
// some heuristics: 3 times x 64 milliseconds
AwtWindow::FlashWindowEx(dialog, 3, 64, FLASHW_CAPTION);
} }
::BringWindowToTop(dialog); ::BringWindowToTop(dialog);
::SetForegroundWindow(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, LRESULT CALLBACK AwtDialog::MouseHookProc_NonTT(int nCode,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
......
...@@ -76,7 +76,7 @@ public: ...@@ -76,7 +76,7 @@ public:
* Thus we don't have to perform any transitive (a blocker of a blocker) checks. * Thus we don't have to perform any transitive (a blocker of a blocker) checks.
*/ */
INLINE virtual BOOL IsFocusedWindowModalBlocker() { 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 // finds and activates some window after the modal dialog is hidden
...@@ -132,6 +132,8 @@ public: ...@@ -132,6 +132,8 @@ public:
// example on browser's thread when running in Java Plugin // example on browser's thread when running in Java Plugin
static LRESULT CALLBACK MouseHookProc_NonTT(int code, static LRESULT CALLBACK MouseHookProc_NonTT(int code,
WPARAM wParam, LPARAM lParam); WPARAM wParam, LPARAM lParam);
static void AnimateModalBlocker(HWND window);
}; };
#endif /* AWT_DIALOG_H */ #endif /* AWT_DIALOG_H */
...@@ -361,8 +361,8 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message, ...@@ -361,8 +361,8 @@ LRESULT CALLBACK AwtFrame::ProxyWindowProc(HWND hwnd, UINT message,
AwtWindow::SynthesizeWmActivate(FALSE, parent->GetHWnd(), NULL); AwtWindow::SynthesizeWmActivate(FALSE, parent->GetHWnd(), NULL);
} else if (sm_restoreFocusAndActivation) { } else if (sm_restoreFocusAndActivation) {
if (sm_focusedWindow != NULL) { if (AwtComponent::GetFocusedWindow() != NULL) {
AwtWindow *focusedWindow = (AwtWindow*)GetComponent(sm_focusedWindow); AwtWindow *focusedWindow = (AwtWindow*)GetComponent(AwtComponent::GetFocusedWindow());
if (focusedWindow != NULL) { if (focusedWindow != NULL) {
// Will just silently restore native focus & activation. // Will just silently restore native focus & activation.
focusedWindow->AwtSetActiveWindow(); focusedWindow->AwtSetActiveWindow();
...@@ -607,11 +607,6 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) { ...@@ -607,11 +607,6 @@ MsgRouting AwtFrame::WmNcMouseDown(WPARAM hitTest, int x, int y, int button) {
return AwtWindow::WmNcMouseDown(hitTest, x, y, button); return AwtWindow::WmNcMouseDown(hitTest, x, y, button);
} }
MsgRouting AwtFrame::WmWindowPosChanged(LPARAM windowPos) {
return mrDoDefault;
}
// Override AwtWindow::Reshape() to handle minimized/maximized // Override AwtWindow::Reshape() to handle minimized/maximized
// frames (see 6525850, 4065534) // frames (see 6525850, 4065534)
void AwtFrame::Reshape(int x, int y, int width, int height) void AwtFrame::Reshape(int x, int y, int width, int height)
...@@ -848,6 +843,11 @@ MsgRouting AwtFrame::WmGetMinMaxInfo(LPMINMAXINFO lpmmi) ...@@ -848,6 +843,11 @@ MsgRouting AwtFrame::WmGetMinMaxInfo(LPMINMAXINFO lpmmi)
MsgRouting AwtFrame::WmSize(UINT type, int w, int h) MsgRouting AwtFrame::WmSize(UINT type, int w, int h)
{ {
currentWmSizeState = type;
if (currentWmSizeState == SIZE_MINIMIZED) {
UpdateSecurityWarningVisibility();
}
if (m_ignoreWmSize) { if (m_ignoreWmSize) {
return mrDoDefault; return mrDoDefault;
} }
...@@ -941,7 +941,7 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) ...@@ -941,7 +941,7 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
return mrConsume; return mrConsume;
} }
type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS; type = java_awt_event_WindowEvent_WINDOW_GAINED_FOCUS;
sm_focusedWindow = GetHWnd(); AwtComponent::SetFocusedWindow(GetHWnd());
} else { } else {
if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) { if (!::IsWindow(AwtWindow::GetModalBlocker(opposite))) {
...@@ -967,7 +967,7 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite) ...@@ -967,7 +967,7 @@ MsgRouting AwtFrame::WmActivate(UINT nState, BOOL fMinimized, HWND opposite)
CheckRetainActualFocusedWindow(opposite); CheckRetainActualFocusedWindow(opposite);
type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS; type = java_awt_event_WindowEvent_WINDOW_LOST_FOCUS;
sm_focusedWindow = NULL; AwtComponent::SetFocusedWindow(NULL);
sm_focusOwner = NULL; sm_focusOwner = NULL;
} }
} }
...@@ -992,9 +992,9 @@ BOOL AwtFrame::CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd) ...@@ -992,9 +992,9 @@ BOOL AwtFrame::CheckActivateActualFocusedWindow(HWND deactivatedOpositeHWnd)
void AwtFrame::CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd) void AwtFrame::CheckRetainActualFocusedWindow(HWND activatedOpositeHWnd)
{ {
// If actual focused window is not this Frame // If actual focused window is not this Frame
if (sm_focusedWindow != GetHWnd()) { if (AwtComponent::GetFocusedWindow() != GetHWnd()) {
// Make sure the actual focused window is an owned window of this frame // Make sure the actual focused window is an owned window of this frame
AwtWindow *focusedWindow = (AwtWindow *)AwtComponent::GetComponent(sm_focusedWindow); AwtWindow *focusedWindow = (AwtWindow *)AwtComponent::GetComponent(AwtComponent::GetFocusedWindow());
if (focusedWindow != NULL && focusedWindow->GetOwningFrameOrDialog() == this) { if (focusedWindow != NULL && focusedWindow->GetOwningFrameOrDialog() == this) {
// Check that the opposite window is not this frame, nor an owned window of this frame // Check that the opposite window is not this frame, nor an owned window of this frame
......
...@@ -108,7 +108,6 @@ public: ...@@ -108,7 +108,6 @@ public:
MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button); MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
MsgRouting WmNcMouseUp(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 WmGetIcon(WPARAM iconType, LRESULT& retVal);
MsgRouting WmWindowPosChanged(LPARAM windowPos);
MsgRouting WmShowWindow(BOOL show, UINT status); MsgRouting WmShowWindow(BOOL show, UINT status);
virtual MsgRouting WmSysCommand(UINT uCmdType, int xPos, int yPos); virtual MsgRouting WmSysCommand(UINT uCmdType, int xPos, int yPos);
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include "debug_mem.h" #include "debug_mem.h"
#include "ComCtl32Util.h" #include "ComCtl32Util.h"
#include "DllUtil.h"
#include "D3DPipelineManager.h" #include "D3DPipelineManager.h"
...@@ -334,6 +335,8 @@ AwtToolkit::AwtToolkit() { ...@@ -334,6 +335,8 @@ AwtToolkit::AwtToolkit() {
m_mouseDown = FALSE; m_mouseDown = FALSE;
m_hGetMessageHook = 0; m_hGetMessageHook = 0;
m_hMouseLLHook = 0;
m_lastWindowUnderMouse = NULL;
m_timer = 0; m_timer = 0;
m_cmdIDs = new AwtCmdIDList(); m_cmdIDs = new AwtCmdIDList();
...@@ -483,6 +486,7 @@ BOOL AwtToolkit::Dispose() { ...@@ -483,6 +486,7 @@ BOOL AwtToolkit::Dispose() {
tk.UnregisterClass(); tk.UnregisterClass();
::UnhookWindowsHookEx(tk.m_hGetMessageHook); ::UnhookWindowsHookEx(tk.m_hGetMessageHook);
UninstallMouseLowLevelHook();
tk.m_mainThreadId = 0; tk.m_mainThreadId = 0;
...@@ -960,6 +964,79 @@ LRESULT CALLBACK AwtToolkit::GetMessageFilter(int code, ...@@ -960,6 +964,79 @@ LRESULT CALLBACK AwtToolkit::GetMessageFilter(int code,
CATCH_BAD_ALLOC_RET(0); 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 * The main message loop
*/ */
...@@ -1376,6 +1453,47 @@ HICON AwtToolkit::GetAwtIconSm() ...@@ -1376,6 +1453,47 @@ HICON AwtToolkit::GetAwtIconSm()
return defaultIconSm; 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) { void AwtToolkit::SetHeapCheck(long flag) {
if (flag) { if (flag) {
printf("heap checking not supported with this build\n"); printf("heap checking not supported with this build\n");
...@@ -1428,6 +1546,49 @@ JNIEnv* AwtToolkit::GetEnv() { ...@@ -1428,6 +1546,49 @@ JNIEnv* AwtToolkit::GetEnv() {
(JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2) : m_env; (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 * Toolkit native methods
*/ */
...@@ -1756,7 +1917,6 @@ Java_sun_awt_windows_WToolkit_getScreenHeight(JNIEnv *env, jobject self) ...@@ -1756,7 +1917,6 @@ Java_sun_awt_windows_WToolkit_getScreenHeight(JNIEnv *env, jobject self)
CATCH_BAD_ALLOC_RET(0); CATCH_BAD_ALLOC_RET(0);
} }
/* /*
* Class: sun_awt_windows_WToolkit * Class: sun_awt_windows_WToolkit
* Method: getSreenInsets * Method: getSreenInsets
...@@ -1768,34 +1928,17 @@ Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv *env, ...@@ -1768,34 +1928,17 @@ Java_sun_awt_windows_WToolkit_getScreenInsets(JNIEnv *env,
jint screen) jint screen)
{ {
jobject insets = NULL; jobject insets = NULL;
RECT rRW; RECT rect;
LPMONITORINFO miInfo;
TRY; TRY;
/* if primary display */ if (AwtToolkit::GetScreenInsets(screen, &rect)) {
if (screen == 0) { insets = env->NewObject(env->FindClass("java/awt/Insets"),
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"),
AwtToolkit::insetsMID, AwtToolkit::insetsMID,
miInfo->rcWork.top - miInfo->rcMonitor.top, rect.top,
miInfo->rcWork.left - miInfo->rcMonitor.left, rect.left,
miInfo->rcMonitor.bottom - miInfo->rcWork.bottom, rect.bottom,
miInfo->rcMonitor.right - miInfo->rcWork.right); rect.right);
}
} }
if (safe_ExceptionOccurred(env)) { if (safe_ExceptionOccurred(env)) {
......
...@@ -210,6 +210,8 @@ public: ...@@ -210,6 +210,8 @@ public:
LPARAM lParam); LPARAM lParam);
static LRESULT CALLBACK ForegroundIdleFilter(int code, WPARAM wParam, static LRESULT CALLBACK ForegroundIdleFilter(int code, WPARAM wParam,
LPARAM lParam); LPARAM lParam);
static LRESULT CALLBACK MouseLowLevelHook(int code, WPARAM wParam,
LPARAM lParam);
INLINE static AwtToolkit& GetInstance() { return theInstance; } INLINE static AwtToolkit& GetInstance() { return theInstance; }
INLINE void SetPeer(JNIEnv *env, jobject wToolkit) { INLINE void SetPeer(JNIEnv *env, jobject wToolkit) {
...@@ -311,6 +313,30 @@ public: ...@@ -311,6 +313,30 @@ public:
HICON GetAwtIcon(); HICON GetAwtIcon();
HICON GetAwtIconSm(); 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. */ /* Turns on/off dialog modality for the system. */
INLINE AwtDialog* SetModal(AwtDialog* frame) { INLINE AwtDialog* SetModal(AwtDialog* frame) {
AwtDialog* previousDialog = m_pModalDialog; AwtDialog* previousDialog = m_pModalDialog;
...@@ -368,6 +394,7 @@ private: ...@@ -368,6 +394,7 @@ private:
BOOL m_mouseDown; BOOL m_mouseDown;
HHOOK m_hGetMessageHook; HHOOK m_hGetMessageHook;
HHOOK m_hMouseLLHook;
UINT_PTR m_timer; UINT_PTR m_timer;
class AwtCmdIDList* m_cmdIDs; class AwtCmdIDList* m_cmdIDs;
...@@ -411,6 +438,24 @@ public: ...@@ -411,6 +438,24 @@ public:
public: public:
static void SetEnv(JNIEnv *env); static void SetEnv(JNIEnv *env);
static JNIEnv* GetEnv(); 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();
}; };
/* /*
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "awt_Win32GraphicsDevice.h" #include "awt_Win32GraphicsDevice.h"
#include "Devices.h" #include "Devices.h"
#include "WindowsFlags.h" #include "WindowsFlags.h"
#include "DllUtil.h"
BOOL DWMIsCompositionEnabled(); BOOL DWMIsCompositionEnabled();
...@@ -89,13 +90,8 @@ void DWMResetCompositionEnabled() { ...@@ -89,13 +90,8 @@ void DWMResetCompositionEnabled() {
/** /**
* Returns true if dwm composition is enabled, false if it is not applicable * Returns true if dwm composition is enabled, false if it is not applicable
* (if the OS is not Vista) or dwm composition is disabled. * (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() { BOOL DWMIsCompositionEnabled() {
typedef HRESULT (WINAPI DwmIsCompositionEnabledFunc)(BOOL*);
// cheaper to check than whether it's vista or not // cheaper to check than whether it's vista or not
if (dwmIsCompositionEnabled != DWM_COMP_UNDEFINED) { if (dwmIsCompositionEnabled != DWM_COMP_UNDEFINED) {
return (BOOL)dwmIsCompositionEnabled; return (BOOL)dwmIsCompositionEnabled;
...@@ -107,32 +103,22 @@ BOOL DWMIsCompositionEnabled() { ...@@ -107,32 +103,22 @@ BOOL DWMIsCompositionEnabled() {
} }
BOOL bRes = FALSE; BOOL bRes = FALSE;
HMODULE hDwmApiDll = ::LoadLibrary(TEXT("dwmapi.dll"));
try {
if (hDwmApiDll != NULL) { BOOL bEnabled;
DwmIsCompositionEnabledFunc *lpDwmIsCompEnabled = HRESULT res = DwmAPI::DwmIsCompositionEnabled(&bEnabled);
(DwmIsCompositionEnabledFunc*) if (SUCCEEDED(res)) {
GetProcAddress(hDwmApiDll, "DwmIsCompositionEnabled"); bRes = bEnabled;
if (lpDwmIsCompEnabled != NULL) { J2dTraceLn1(J2D_TRACE_VERBOSE, " composition enabled: %d",bRes);
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);
}
} else { } else {
J2dTraceLn(J2D_TRACE_ERROR, J2dTraceLn1(J2D_TRACE_ERROR,
"IsDWMCompositionEnabled: no DwmIsCompositionEnabled() "\ "IsDWMCompositionEnabled: error %x when detecting"\
"in dwmapi.dll"); "if composition is enabled", res);
} }
::FreeLibrary(hDwmApiDll); } catch (const DllUtil::Exception &) {
} else {
J2dTraceLn(J2D_TRACE_ERROR, J2dTraceLn(J2D_TRACE_ERROR,
"IsDWMCompositionEnabled: error opening dwmapi.dll"); "IsDWMCompositionEnabled: no DwmIsCompositionEnabled() "\
"in dwmapi.dll or dwmapi.dll cannot be loaded");
} }
dwmIsCompositionEnabled = bRes; dwmIsCompositionEnabled = bRes;
......
...@@ -54,6 +54,8 @@ public: ...@@ -54,6 +54,8 @@ public:
static jfieldID locationByPlatformID; static jfieldID locationByPlatformID;
static jfieldID screenID; /* screen number passed over from WindowPeer */ static jfieldID screenID; /* screen number passed over from WindowPeer */
static jfieldID autoRequestFocusID; static jfieldID autoRequestFocusID;
static jfieldID securityWarningWidthID;
static jfieldID securityWarningHeightID;
// The coordinates at the peer. // The coordinates at the peer.
static jfieldID sysXID; static jfieldID sysXID;
...@@ -61,6 +63,9 @@ public: ...@@ -61,6 +63,9 @@ public:
static jfieldID sysWID; static jfieldID sysWID;
static jfieldID sysHID; static jfieldID sysHID;
static jmethodID getWarningStringMID;
static jmethodID calculateSecurityWarningPositionMID;
AwtWindow(); AwtWindow();
virtual ~AwtWindow(); virtual ~AwtWindow();
...@@ -150,6 +155,8 @@ public: ...@@ -150,6 +155,8 @@ public:
static void SetModalBlocker(HWND window, HWND blocker); static void SetModalBlocker(HWND window, HWND blocker);
static void SetAndActivateModalBlocker(HWND window, HWND blocker); static void SetAndActivateModalBlocker(HWND window, HWND blocker);
static HWND GetTopmostModalBlocker(HWND window);
/* /*
* Windows message handler functions * Windows message handler functions
*/ */
...@@ -166,13 +173,13 @@ public: ...@@ -166,13 +173,13 @@ public:
virtual MsgRouting WmSettingChange(UINT wFlag, LPCTSTR pszSection); virtual MsgRouting WmSettingChange(UINT wFlag, LPCTSTR pszSection);
virtual MsgRouting WmNcCalcSize(BOOL fCalcValidRects, virtual MsgRouting WmNcCalcSize(BOOL fCalcValidRects,
LPNCCALCSIZE_PARAMS lpncsp, LRESULT& retVal); LPNCCALCSIZE_PARAMS lpncsp, LRESULT& retVal);
virtual MsgRouting WmNcPaint(HRGN hrgn);
virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal); virtual MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT& retVal);
virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button); virtual MsgRouting WmNcMouseDown(WPARAM hitTest, int x, int y, int button);
virtual MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal); virtual MsgRouting WmGetIcon(WPARAM iconType, LRESULT& retVal);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual MsgRouting WmWindowPosChanging(LPARAM windowPos); virtual MsgRouting WmWindowPosChanging(LPARAM windowPos);
virtual MsgRouting WmWindowPosChanged(LPARAM windowPos); virtual MsgRouting WmWindowPosChanged(LPARAM windowPos);
virtual MsgRouting WmTimer(UINT_PTR timerID);
virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic); virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic);
virtual void WindowResized(); virtual void WindowResized();
...@@ -221,11 +228,22 @@ public: ...@@ -221,11 +228,22 @@ public:
static void _SetOpacity(void* param); static void _SetOpacity(void* param);
static void _SetOpaque(void* param); static void _SetOpaque(void* param);
static void _UpdateWindow(void* param); static void _UpdateWindow(void* param);
static void _RepositionSecurityWarning(void* param);
inline static BOOL IsResizing() { inline static BOOL IsResizing() {
return sm_resizing; 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: private:
static int ms_instanceCounter; static int ms_instanceCounter;
static HHOOK ms_hCBTFilter; static HHOOK ms_hCBTFilter;
...@@ -267,9 +285,56 @@ private: ...@@ -267,9 +285,56 @@ private:
UINT contentWidth; UINT contentWidth;
UINT contentHeight; UINT contentHeight;
void RedrawWindow();
void SetTranslucency(BYTE opacity, BOOL opaque); void SetTranslucency(BYTE opacity, BOOL opaque);
void UpdateWindow(int width, int height, HBITMAP hBitmap);
void UpdateWindowImpl(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: protected:
BOOL m_isResizable; BOOL m_isResizable;
...@@ -284,6 +349,12 @@ protected: ...@@ -284,6 +349,12 @@ protected:
virtual void FillBackground(HDC hMemoryDC, SIZE &size); virtual void FillBackground(HDC hMemoryDC, SIZE &size);
virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha); virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);
inline BOOL IsUntrusted() {
return warningString != NULL;
}
UINT currentWmSizeState;
private: private:
int m_screenNum; int m_screenNum;
......
/*
* 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.
*
* 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.
*/
/*
@test
@bug 6785058
@summary Tests that an owner is activated on closing its owned dialog with the warning icon.
@author Anton Tarasov: area=awt.focus
@library ../../regtesthelpers
@build Util
@run main/othervm/policy=java.policy -Djava.security.manager CloseDialogActivateOwnerTest
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.lang.reflect.InvocationTargetException;
import test.java.awt.regtesthelpers.Util;
public class CloseDialogActivateOwnerTest extends Applet {
Robot robot;
public static void main(String[] args) {
CloseDialogActivateOwnerTest app = new CloseDialogActivateOwnerTest();
app.init();
app.start();
}
public void init() {
robot = Util.createRobot();
}
public void start() {
final Frame frame = new Frame("Owner Frame");
final Dialog dialog = new Dialog(frame, "Owned Dialog");
frame.setSize(100, 100);
dialog.setSize(100, 100);
// Show the owner. Check that it's focused.
if (!Util.trackWindowGainedFocus(frame, new Runnable() {
public void run() {
frame.setVisible(true);
}
}, 2000, false))
{
throw new TestErrorException("the owner frame hasn't been activated on show");
}
// Show the owned dialog. Check that it's focused.
if (!Util.trackWindowGainedFocus(dialog, new Runnable() {
public void run() {
dialog.setVisible(true);
}
}, 2000, true))
{
throw new TestErrorException("the owned dialog hasn't been activated on show");
}
robot.delay(2000); // wait for the warning icon is shown
// Close the dialog. Check that the owner is activated.
if (!Util.trackWindowGainedFocus(frame, new Runnable() {
public void run() {
dialog.dispose();
}
}, 2000, false))
{
throw new TestFailedException("the owner hasn't been activated on closing the owned dialog");
}
System.out.println("Test passed.");
}
}
/**
* Thrown when the behavior being verified is found wrong.
*/
class TestFailedException extends RuntimeException {
TestFailedException(String msg) {
super("Test failed: " + msg);
}
}
/**
* Thrown when an error not related to the behavior being verified is encountered.
*/
class TestErrorException extends Error {
TestErrorException(String msg) {
super("Unexpected error: " + msg);
}
}
grant {
permission java.awt.AWTPermission "createRobot";
};
/*
* 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.
*
* 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.
*/
/*
@test
@bug 6542975
@summary Tests that switching focus from an owned window doesn't crash.
@author anton.tarasov@sun.com: area=awt-focus
@library ../../regtesthelpers
@build Util
@run main OwnedWindowFocusIMECrashTest
*/
import java.awt.*;
import javax.swing.*;
import test.java.awt.regtesthelpers.Util;
public class OwnedWindowFocusIMECrashTest {
Robot robot;
JFrame owner = new JFrame("Owner Frame");
JFrame frame = new JFrame("Other Frame");
JWindow window = new JWindow(owner);
JButton button = new JButton("Button");
public static void main(String[] args) {
OwnedWindowFocusIMECrashTest app = new OwnedWindowFocusIMECrashTest();
app.init();
app.start();
}
public void init() {
robot = Util.createRobot();
}
public void start() {
owner.setBounds(100, 100, 200, 100);
window.setBounds(100, 250, 200, 100);
frame.setBounds(350, 100, 200, 100);
window.add(button);
owner.setVisible(true);
frame.setVisible(true);
window.setVisible(true);
Util.waitForIdle(robot);
test();
System.out.println("Test passed");
}
void test() {
Util.clickOnComp(button, robot);
if (!button.hasFocus()) {
throw new TestErrorException("the button couldn't be focused by click");
}
Util.clickOnTitle(frame, robot); // here there was a crash
}
}
/**
* Thrown when an error not related to the behavior being verified is encountered.
*/
class TestErrorException extends RuntimeException {
TestErrorException(String msg) {
super("Unexpected error: " + msg);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册