diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index c039a717984..88a196918ed 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -147,6 +147,51 @@ import sun.util.logging.PlatformLogger; */ public class Window extends Container implements Accessible { + /** + * Enumeration of available window types. + * + * A window type defines the generic visual appearance and behavior of a + * top-level window. For example, the type may affect the kind of + * decorations of a decorated {@code Frame} or {@code Dialog} instance. + *

+ * Some platforms may not fully support a certain window type. Depending on + * the level of support, some properties of the window type may be + * disobeyed. + * + * @see #getType + * @see #setType + * @since 1.7 + */ + public static enum Type { + /** + * Represents a normal window. + * + * This is the default type for objects of the {@code Window} class or + * its descendants. Use this type for regular top-level windows. + */ + NORMAL, + + /** + * Represents a utility window. + * + * A utility window is usually a small window such as a toolbar or a + * palette. The native system may render the window with smaller + * title-bar if the window is either a {@code Frame} or a {@code + * Dialog} object, and if it has its decorations enabled. + */ + UTILITY, + + /** + * Represents a popup window. + * + * A popup window is a temporary window such as a drop-down menu or a + * tooltip. On some platforms, windows of that type may be forcibly + * made undecorated even if they are instances of the {@code Frame} or + * {@code Dialog} class, and have decorations enabled. + */ + POPUP + } + /** * This represents the warning message that is * to be displayed in a non secure window. ie : @@ -2717,6 +2762,52 @@ public class Window extends Container implements Accessible { removeFromWindowList(appContext, weakThis); } + /** + * Window type. + * + * Synchronization: ObjectLock + */ + private Type type = Type.NORMAL; + + /** + * Sets the type of the window. + * + * This method can only be called while the window is not displayable. + * + * @throws IllegalComponentStateException if the window + * is displayable. + * @throws IllegalArgumentException if the type is {@code null} + * @see Component#isDisplayable + * @see #getType + * @since 1.7 + */ + public void setType(Type type) { + if (type == null) { + throw new IllegalArgumentException("type should not be null."); + } + synchronized (getTreeLock()) { + if (isDisplayable()) { + throw new IllegalComponentStateException( + "The window is displayable."); + } + synchronized (getObjectLock()) { + this.type = type; + } + } + } + + /** + * Returns the type of the window. + * + * @see #setType + * @since 1.7 + */ + public Type getType() { + synchronized (getObjectLock()) { + return type; + } + } + /** * The window serialized data version. * diff --git a/jdk/src/share/classes/javax/swing/Popup.java b/jdk/src/share/classes/javax/swing/Popup.java index 0d1f2d53f19..bd6e6fff8b5 100644 --- a/jdk/src/share/classes/javax/swing/Popup.java +++ b/jdk/src/share/classes/javax/swing/Popup.java @@ -227,12 +227,8 @@ public class Popup { HeavyWeightWindow(Window parent) { super(parent); setFocusableWindowState(false); - Toolkit tk = Toolkit.getDefaultToolkit(); - if (tk instanceof SunToolkit) { - // all the short-lived windows like Popups should be - // OverrideRedirect on X11 platforms - ((SunToolkit)tk).setOverrideRedirect(this); - } + setType(Window.Type.POPUP); + // Popups are typically transient and most likely won't benefit // from true double buffering. Turn it off here. getRootPane().setUseTrueDoubleBuffering(false); diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 14f8f9dc2a2..3c7f16dff27 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -800,14 +800,6 @@ public abstract class SunToolkit extends Toolkit } - /** - * Makes the window OverrideRedirect, on X11 platforms. See - * ICCCM specification for more details about OverrideRedirect - * windows. Implemented in XToolkit, no-op in WToolkit. - */ - public void setOverrideRedirect(Window target) { - } - static SoftCache imgCache = new SoftCache(); static synchronized Image getImageFromHash(Toolkit tk, URL url) { diff --git a/jdk/src/solaris/classes/sun/awt/X11/InfoWindow.java b/jdk/src/solaris/classes/sun/awt/X11/InfoWindow.java index d0abaa0a97a..c5deb685813 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/InfoWindow.java +++ b/jdk/src/solaris/classes/sun/awt/X11/InfoWindow.java @@ -45,6 +45,7 @@ public abstract class InfoWindow extends Window { protected InfoWindow(Frame parent, Color borderColor) { super(parent); + setType(Window.Type.POPUP); container = new Container() { @Override public Insets getInsets() { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java index a855ade0464..be9599ce332 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java @@ -1099,9 +1099,9 @@ abstract class XDecoratedPeer extends XWindowPeer { return false; } + @Override boolean isOverrideRedirect() { -// return false; - return ((XToolkit)Toolkit.getDefaultToolkit()).isOverrideRedirect((Window)target); + return Window.Type.POPUP.equals(getWindowType()); } public boolean requestWindowFocus(long time, boolean timeProvided) { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XNETProtocol.java b/jdk/src/solaris/classes/sun/awt/X11/XNETProtocol.java index 86252721be5..a06f24ff62d 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XNETProtocol.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XNETProtocol.java @@ -252,8 +252,11 @@ final class XNETProtocol extends XProtocol implements XStateProtocol, XLayerProt XAtom XA_NET_WM_STATE_SKIP_TASKBAR = XAtom.get("_NET_WM_STATE_SKIP_TASKBAR"); XAtom XA_NET_WM_STATE_SKIP_PAGER = XAtom.get("_NET_WM_STATE_SKIP_PAGER"); - XAtom XA_NET_WM_WINDOW_TYPE = XAtom.get("_NET_WM_WINDOW_TYPE"); - XAtom XA_NET_WM_WINDOW_TYPE_DIALOG = XAtom.get("_NET_WM_WINDOW_TYPE_DIALOG"); + public final XAtom XA_NET_WM_WINDOW_TYPE = XAtom.get("_NET_WM_WINDOW_TYPE"); + public final XAtom XA_NET_WM_WINDOW_TYPE_NORMAL = XAtom.get("_NET_WM_WINDOW_TYPE_NORMAL"); + public final XAtom XA_NET_WM_WINDOW_TYPE_DIALOG = XAtom.get("_NET_WM_WINDOW_TYPE_DIALOG"); + public final XAtom XA_NET_WM_WINDOW_TYPE_UTILITY = XAtom.get("_NET_WM_WINDOW_TYPE_UTILITY"); + public final XAtom XA_NET_WM_WINDOW_TYPE_POPUP_MENU = XAtom.get("_NET_WM_WINDOW_TYPE_POPUP_MENU"); XAtom XA_NET_WM_WINDOW_OPACITY = XAtom.get("_NET_WM_WINDOW_OPACITY"); diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java index 1103ee6cdb9..f1ec8004264 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -109,11 +109,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable { static int awt_multiclick_time; static boolean securityWarningEnabled; - // WeakSet should be used here, but there is no such class - // in JDK (at least in JDK6 and earlier versions) - private WeakHashMap overrideRedirectWindows = - new WeakHashMap(); - private static int screenWidth = -1, screenHeight = -1; // Dimensions of default screen static long awt_defaultFg; // Pixel private static XMouseInfoPeer xPeer; @@ -1316,19 +1311,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } } - @Override - public void setOverrideRedirect(Window target) { - synchronized (overrideRedirectWindows) { - overrideRedirectWindows.put(target, true); - } - } - - public boolean isOverrideRedirect(Window target) { - synchronized (overrideRedirectWindows) { - return overrideRedirectWindows.containsKey(target); - } - } - static void dumpPeers() { if (log.isLoggable(PlatformLogger.FINE)) { log.fine("Mapped windows:"); diff --git a/jdk/src/solaris/classes/sun/awt/X11/XTrayIconPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XTrayIconPeer.java index da4a6b0d43d..64ab4c268b0 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XTrayIconPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XTrayIconPeer.java @@ -483,12 +483,6 @@ public class XTrayIconPeer implements TrayIconPeer, } } - static boolean isTrayIconStuffWindow(Window w) { - return (w instanceof InfoWindow.Tooltip) || - (w instanceof InfoWindow.Balloon) || - (w instanceof XTrayIconEmbeddedFrame); - } - // *************************************** // Special embedded frame for tray icon // *************************************** diff --git a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java index b580bda3c8a..b7957dd8f92 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java @@ -53,7 +53,6 @@ import sun.util.logging.PlatformLogger; import sun.awt.AWTAccessor; import sun.awt.ComponentAccessor; import sun.awt.WindowAccessor; -import sun.awt.AWTAccessor; import sun.awt.DisplayChangedListener; import sun.awt.SunToolkit; import sun.awt.X11GraphicsDevice; @@ -106,6 +105,18 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between // setVisible(true) & handleMapNotify(). + /** + * The type of the window. + * + * The type is supposed to be immutable while the peer object exists. + * The value gets initialized in the preInit() method. + */ + private Window.Type windowType = Window.Type.NORMAL; + + public final Window.Type getWindowType() { + return windowType; + } + // It need to be accessed from XFramePeer. protected Vector toplevelStateListeners = new Vector(); XWindowPeer(XCreateWindowParams params) { @@ -137,6 +148,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, void preInit(XCreateWindowParams params) { target = (Component)params.get(TARGET); + windowType = ((Window)target).getType(); params.put(REPARENTED, Boolean.valueOf(isOverrideRedirect() || isSimpleWindow())); super.preInit(params); @@ -1128,9 +1140,8 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, } boolean isOverrideRedirect() { - return (XWM.getWMID() == XWM.OPENLOOK_WM ? true : false) || - ((XToolkit)Toolkit.getDefaultToolkit()).isOverrideRedirect((Window)target) || - XTrayIconPeer.isTrayIconStuffWindow((Window)target); + return XWM.getWMID() == XWM.OPENLOOK_WM || + Window.Type.POPUP.equals(getWindowType()); } final boolean isOLWMDecorBug() { @@ -1826,12 +1837,49 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, void setActualFocusedWindow(XWindowPeer actualFocusedWindow) { } + /** + * Applies the current window type. + */ + private void applyWindowType() { + XNETProtocol protocol = XWM.getWM().getNETProtocol(); + if (protocol == null) { + return; + } + + XAtom typeAtom = null; + + switch (getWindowType()) + { + case NORMAL: + typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_NORMAL; + break; + case UTILITY: + typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_UTILITY; + break; + case POPUP: + typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_POPUP_MENU; + break; + } + + if (typeAtom != null) { + XAtomList wtype = new XAtomList(); + wtype.add(typeAtom); + protocol.XA_NET_WM_WINDOW_TYPE. + setAtomListProperty(getWindow(), wtype); + } else { + protocol.XA_NET_WM_WINDOW_TYPE. + DeleteProperty(getWindow()); + } + } + + @Override public void xSetVisible(boolean visible) { if (log.isLoggable(PlatformLogger.FINE)) log.fine("Setting visible on " + this + " to " + visible); XToolkit.awtLock(); try { this.visible = visible; if (visible) { + applyWindowType(); XlibWrapper.XMapRaised(XToolkit.getDisplay(), getWindow()); } else { XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow()); diff --git a/jdk/src/windows/classes/sun/awt/windows/WDialogPeer.java b/jdk/src/windows/classes/sun/awt/windows/WDialogPeer.java index 4424f1cc813..703edd0fdc5 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WDialogPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WDialogPeer.java @@ -53,7 +53,12 @@ class WDialogPeer extends WWindowPeer implements DialogPeer { } } - native void create(WComponentPeer parent); + native void createAwtDialog(WComponentPeer parent); + void create(WComponentPeer parent) { + preCreate(parent); + createAwtDialog(parent); + } + native void showModal(); native void endModal(); diff --git a/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java b/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java index 86bde26582b..c89d154132a 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WFramePeer.java @@ -136,6 +136,7 @@ class WFramePeer extends WWindowPeer implements FramePeer { native void createAwtFrame(WComponentPeer parent); void create(WComponentPeer parent) { + preCreate(parent); createAwtFrame(parent); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java index 6189738da20..9a39d509f2b 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java @@ -199,7 +199,17 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, } native void createAwtWindow(WComponentPeer parent); + + private volatile Window.Type windowType = Window.Type.NORMAL; + + // This method must be called for Window, Dialog, and Frame before creating + // the hwnd + void preCreate(WComponentPeer parent) { + windowType = ((Window)target).getType(); + } + void create(WComponentPeer parent) { + preCreate(parent); createAwtWindow(parent); } diff --git a/jdk/src/windows/native/sun/windows/awt_Dialog.cpp b/jdk/src/windows/native/sun/windows/awt_Dialog.cpp index c0637237da4..4d21489d2eb 100644 --- a/jdk/src/windows/native/sun/windows/awt_Dialog.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Dialog.cpp @@ -760,7 +760,7 @@ extern "C" { * Signature: (Lsun/awt/windows/WComponentPeer;)V */ JNIEXPORT void JNICALL -Java_sun_awt_windows_WDialogPeer_create(JNIEnv *env, jobject self, +Java_sun_awt_windows_WDialogPeer_createAwtDialog(JNIEnv *env, jobject self, jobject parent) { TRY; diff --git a/jdk/src/windows/native/sun/windows/awt_Window.cpp b/jdk/src/windows/native/sun/windows/awt_Window.cpp index 8bb5c900219..c03420d3522 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp @@ -163,9 +163,11 @@ jfieldID AwtWindow::sysXID; jfieldID AwtWindow::sysYID; jfieldID AwtWindow::sysWID; jfieldID AwtWindow::sysHID; +jfieldID AwtWindow::windowTypeID; jmethodID AwtWindow::getWarningStringMID; jmethodID AwtWindow::calculateSecurityWarningPositionMID; +jmethodID AwtWindow::windowTypeNameMID; int AwtWindow::ms_instanceCounter = 0; HHOOK AwtWindow::ms_hCBTFilter; @@ -216,6 +218,8 @@ AwtWindow::AwtWindow() { hContentBitmap = NULL; ::InitializeCriticalSection(&contentBitmapCS); + + m_windowType = Type::NORMAL; } AwtWindow::~AwtWindow() @@ -475,6 +479,9 @@ void AwtWindow::CreateHWnd(JNIEnv *env, LPCWSTR title, } env->DeleteLocalRef(target); + InitType(env, peer); + TweakStyle(windowStyle, windowExStyle); + AwtCanvas::CreateHWnd(env, title, windowStyle, windowExStyle, @@ -982,6 +989,50 @@ void AwtWindow::_RepositionSecurityWarning(void* param) delete rsws; } +void AwtWindow::InitType(JNIEnv *env, jobject peer) +{ + jobject type = env->GetObjectField(peer, windowTypeID); + if (type == NULL) { + return; + } + + jstring value = (jstring)env->CallObjectMethod(type, windowTypeNameMID); + if (value == NULL) { + env->DeleteLocalRef(type); + return; + } + + const char* valueNative = env->GetStringUTFChars(value, 0); + if (valueNative == NULL) { + env->DeleteLocalRef(value); + env->DeleteLocalRef(type); + return; + } + + if (strcmp(valueNative, "UTILITY") == 0) { + m_windowType = Type::UTILITY; + } else if (strcmp(valueNative, "POPUP") == 0) { + m_windowType = Type::POPUP; + } + + env->ReleaseStringUTFChars(value, valueNative); + env->DeleteLocalRef(value); + env->DeleteLocalRef(type); +} + +void AwtWindow::TweakStyle(DWORD & style, DWORD & exStyle) +{ + switch (GetType()) { + case Type::UTILITY: + exStyle |= WS_EX_TOOLWINDOW; + break; + case Type::POPUP: + style &= ~WS_OVERLAPPED; + style |= WS_POPUP; + break; + } +} + /* Create a new AwtWindow object and window. */ AwtWindow* AwtWindow::Create(jobject self, jobject parent) { @@ -3008,6 +3059,11 @@ Java_java_awt_Window_initIDs(JNIEnv *env, jclass cls) AwtWindow::calculateSecurityWarningPositionMID = env->GetMethodID(cls, "calculateSecurityWarningPosition", "(DDDD)Ljava/awt/geom/Point2D;"); + jclass windowTypeClass = env->FindClass("java/awt/Window$Type"); + AwtWindow::windowTypeNameMID = + env->GetMethodID(windowTypeClass, "name", "()Ljava/lang/String;"); + env->DeleteLocalRef(windowTypeClass); + CATCH_BAD_ALLOC; } @@ -3035,6 +3091,9 @@ Java_sun_awt_windows_WWindowPeer_initIDs(JNIEnv *env, jclass cls) AwtWindow::sysWID = env->GetFieldID(cls, "sysW", "I"); AwtWindow::sysHID = env->GetFieldID(cls, "sysH", "I"); + AwtWindow::windowTypeID = env->GetFieldID(cls, "windowType", + "Ljava/awt/Window$Type;"); + CATCH_BAD_ALLOC; } diff --git a/jdk/src/windows/native/sun/windows/awt_Window.h b/jdk/src/windows/native/sun/windows/awt_Window.h index 001062835e3..fa611b481c7 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.h +++ b/jdk/src/windows/native/sun/windows/awt_Window.h @@ -63,8 +63,11 @@ public: static jfieldID sysWID; static jfieldID sysHID; + static jfieldID windowTypeID; + static jmethodID getWarningStringMID; static jmethodID calculateSecurityWarningPositionMID; + static jmethodID windowTypeNameMID; AwtWindow(); virtual ~AwtWindow(); @@ -362,10 +365,24 @@ protected: void EnableTranslucency(BOOL enable); + // Native representation of the java.awt.Window.Type enum + enum Type { + NORMAL, UTILITY, POPUP + }; + + inline Type GetType() { return m_windowType; } + private: int m_screenNum; void InitOwner(AwtWindow *owner); + + Type m_windowType; + void InitType(JNIEnv *env, jobject peer); + + // Tweak the style according to the type of the window + void TweakStyle(DWORD & style, DWORD & exStyle); + }; #endif /* AWT_WINDOW_H */ diff --git a/jdk/test/java/awt/Window/WindowType/WindowType.java b/jdk/test/java/awt/Window/WindowType/WindowType.java new file mode 100644 index 00000000000..9f277973fa5 --- /dev/null +++ b/jdk/test/java/awt/Window/WindowType/WindowType.java @@ -0,0 +1,61 @@ +/* + * 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. + * + * 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 6402325 + @summary Test showing windows of different types + @author anthony.petrov@sun.com: area=awt.toplevel + @library ../../regtesthelpers + @build Util + @run main WindowType +*/ + +import java.awt.*; +import test.java.awt.regtesthelpers.Util; + +/** + * WindowType.java + * Summary: Test showing windows of different types. + */ +public class WindowType { + private static void test(Window window, Window.Type type) { + window.setType(type); + + window.setVisible(true); + Util.waitForIdle(null); + window.setVisible(false); + } + + private static void test(Window.Type type) { + test(new Window((Frame)null), type); + test(new Frame(), type); + test(new Dialog((Frame)null), type); + } + + public static void main(String[] args) { + test(Window.Type.NORMAL); + test(Window.Type.UTILITY); + test(Window.Type.POPUP); + } +}