69
70 // should be synchronized on awtLock
71 private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
72
73
74 private boolean cachedFocusableWindow;
75 XWarningWindow warningWindow;
76
77 private boolean alwaysOnTop;
78 private boolean locationByPlatform;
79
80 Dialog modalBlocker;
81 boolean delayedModalBlocking = false;
82 Dimension targetMinimumSize = null;
83
84 private XWindowPeer ownerPeer;
85
86 // used for modal blocking to keep existing z-order
87 protected XWindowPeer prevTransientFor, nextTransientFor;
88 // value of WM_TRANSIENT_FOR hint set on this window
89 private XWindowPeer curRealTransientFor;
90
91 private boolean grab = false; // Whether to do a grab during showing
92
93 private boolean isMapped = false; // Is this window mapped or not
94 private boolean mustControlStackPosition = false; // Am override-redirect not on top
95 private XEventDispatcher rootPropertyEventDispatcher = null;
96
97 private static final AtomicBoolean isStartupNotificationRemoved = new AtomicBoolean();
98
99 /*
100 * Focus related flags
101 */
102 private boolean isUnhiding = false; // Is the window unhiding.
103 private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between
104 // setVisible(true) & handleMapNotify().
105
106 /**
107 * The type of the window.
108 *
109 * The type is supposed to be immutable while the peer object exists.
1045
1046 return ret;
1047 }
1048
1049 private static boolean isDesktopWindow( long wi ) {
1050 return XWM.getWM().isDesktopWindow( wi );
1051 }
1052
1053 private void updateAlwaysOnTop() {
1054 if (log.isLoggable(PlatformLogger.Level.FINE)) {
1055 log.fine("Promoting always-on-top state {0}", Boolean.valueOf(alwaysOnTop));
1056 }
1057 XWM.getWM().setLayer(this,
1058 alwaysOnTop ?
1059 XLayerProtocol.LAYER_ALWAYS_ON_TOP :
1060 XLayerProtocol.LAYER_NORMAL);
1061 }
1062
1063 public void updateAlwaysOnTopState() {
1064 this.alwaysOnTop = ((Window) this.target).isAlwaysOnTop();
1065 updateAlwaysOnTop();
1066 }
1067
1068 boolean isLocationByPlatform() {
1069 return locationByPlatform;
1070 }
1071
1072 private void promoteDefaultPosition() {
1073 this.locationByPlatform = ((Window)target).isLocationByPlatform();
1074 if (locationByPlatform) {
1075 XToolkit.awtLock();
1076 try {
1077 Rectangle bounds = getBounds();
1078 XSizeHints hints = getHints();
1079 setSizeHints(hints.get_flags() & ~(XUtilConstants.USPosition | XUtilConstants.PPosition),
1080 bounds.x, bounds.y, bounds.width, bounds.height);
1081 } finally {
1082 XToolkit.awtUnlock();
1083 }
1084 }
1088 if (!isVisible() && vis) {
1089 isBeforeFirstMapNotify = true;
1090 winAttr.initialFocus = isAutoRequestFocus();
1091 if (!winAttr.initialFocus) {
1092 /*
1093 * It's easier and safer to temporary suppress WM_TAKE_FOCUS
1094 * protocol itself than to ignore WM_TAKE_FOCUS client message.
1095 * Because we will have to make the difference between
1096 * the message come after showing and the message come after
1097 * activation. Also, on Metacity, for some reason, we have _two_
1098 * WM_TAKE_FOCUS client messages when showing a frame/dialog.
1099 */
1100 suppressWmTakeFocus(true);
1101 }
1102 }
1103 updateFocusability();
1104 promoteDefaultPosition();
1105 if (!vis && warningWindow != null) {
1106 warningWindow.setSecurityWarningVisible(false, false);
1107 }
1108 super.setVisible(vis);
1109 if (!vis && !isWithdrawn()) {
1110 // ICCCM, 4.1.4. Changing Window State:
1111 // "Iconic -> Withdrawn - The client should unmap the window and follow it
1112 // with a synthetic UnmapNotify event as described later in this section."
1113 // The same is true for Normal -> Withdrawn
1114 XToolkit.awtLock();
1115 try {
1116 XUnmapEvent unmap = new XUnmapEvent();
1117 unmap.set_window(window);
1118 unmap.set_event(XToolkit.getDefaultRootWindow());
1119 unmap.set_type(XConstants.UnmapNotify);
1120 unmap.set_from_configure(false);
1121 XlibWrapper.XSendEvent(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
1122 false, XConstants.SubstructureNotifyMask | XConstants.SubstructureRedirectMask,
1123 unmap.pData);
1124 unmap.dispose();
1125 }
1126 finally {
1127 XToolkit.awtUnlock();
1128 }
1617 *
1618 * @param window specifies the top-level window that the hint
1619 * is to be set to
1620 * @param transientForWindow the top-level window
1621 * @param updateChain specifies if next/prevTransientFor fields are
1622 * to be updated
1623 * @param allStates if set to <code>true</code> then TRANSIENT_FOR hint
1624 * is set regardless of the state of window and transientForWindow,
1625 * otherwise it is set only if both are in the same state
1626 */
1627 static void setToplevelTransientFor(XWindowPeer window, XWindowPeer transientForWindow,
1628 boolean updateChain, boolean allStates)
1629 {
1630 if ((window == null) || (transientForWindow == null)) {
1631 return;
1632 }
1633 if (updateChain) {
1634 window.prevTransientFor = transientForWindow;
1635 transientForWindow.nextTransientFor = window;
1636 }
1637 if (window.curRealTransientFor == transientForWindow) {
1638 return;
1639 }
1640 if (!allStates && (window.getWMState() != transientForWindow.getWMState())) {
1641 return;
1642 }
1643 if (window.getScreenNumber() != transientForWindow.getScreenNumber()) {
1644 return;
1645 }
1646 long bpw = window.getWindow();
1647 while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
1648 bpw = XlibUtil.getParentWindow(bpw);
1649 }
1650 long tpw = transientForWindow.getWindow();
1651 while (!XlibUtil.isToplevelWindow(tpw) && !XlibUtil.isXAWTToplevelWindow(tpw)) {
1652 tpw = XlibUtil.getParentWindow(tpw);
1653 }
1654 XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw);
1655 window.curRealTransientFor = transientForWindow;
1656 }
1657
1658 /*
1659 * This method does nothing if this window is not blocked by any modal dialog.
1660 * For modal blocked windows this method looks up for the nearest
1661 * prevTransiendFor window that is in the same state (Normal/Iconified/Withdrawn)
1662 * as this one and makes this window transient for it. The same operation is
1663 * performed for nextTransientFor window.
1664 * Values of prevTransientFor and nextTransientFor fields are not changed.
1665 */
1666 void updateTransientFor() {
1667 int state = getWMState();
1668 XWindowPeer p = prevTransientFor;
1669 while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
1670 p = p.prevTransientFor;
1671 }
1672 if (p != null) {
1673 setToplevelTransientFor(this, p, false, false);
1674 } else {
1675 restoreTransientFor(this);
1929 }
1930
1931 // This method is to be overriden in XDecoratedPeer.
1932 void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1933 }
1934
1935 /**
1936 * Applies the current window type.
1937 */
1938 private void applyWindowType() {
1939 XNETProtocol protocol = XWM.getWM().getNETProtocol();
1940 if (protocol == null) {
1941 return;
1942 }
1943
1944 XAtom typeAtom = null;
1945
1946 switch (getWindowType())
1947 {
1948 case NORMAL:
1949 typeAtom = (ownerPeer == null) ?
1950 protocol.XA_NET_WM_WINDOW_TYPE_NORMAL :
1951 protocol.XA_NET_WM_WINDOW_TYPE_DIALOG;
1952 break;
1953 case UTILITY:
1954 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_UTILITY;
1955 break;
1956 case POPUP:
1957 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_POPUP_MENU;
1958 break;
1959 }
1960
1961 if (typeAtom != null) {
1962 XAtomList wtype = new XAtomList();
1963 wtype.add(typeAtom);
1964 protocol.XA_NET_WM_WINDOW_TYPE.
1965 setAtomListProperty(getWindow(), wtype);
1966 } else {
1967 protocol.XA_NET_WM_WINDOW_TYPE.
1968 DeleteProperty(getWindow());
1969 }
|
69
70 // should be synchronized on awtLock
71 private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
72
73
74 private boolean cachedFocusableWindow;
75 XWarningWindow warningWindow;
76
77 private boolean alwaysOnTop;
78 private boolean locationByPlatform;
79
80 Dialog modalBlocker;
81 boolean delayedModalBlocking = false;
82 Dimension targetMinimumSize = null;
83
84 private XWindowPeer ownerPeer;
85
86 // used for modal blocking to keep existing z-order
87 protected XWindowPeer prevTransientFor, nextTransientFor;
88 // value of WM_TRANSIENT_FOR hint set on this window
89 private XBaseWindow curRealTransientFor;
90
91 private boolean grab = false; // Whether to do a grab during showing
92
93 private boolean isMapped = false; // Is this window mapped or not
94 private boolean mustControlStackPosition = false; // Am override-redirect not on top
95 private XEventDispatcher rootPropertyEventDispatcher = null;
96
97 private static final AtomicBoolean isStartupNotificationRemoved = new AtomicBoolean();
98
99 /*
100 * Focus related flags
101 */
102 private boolean isUnhiding = false; // Is the window unhiding.
103 private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between
104 // setVisible(true) & handleMapNotify().
105
106 /**
107 * The type of the window.
108 *
109 * The type is supposed to be immutable while the peer object exists.
1045
1046 return ret;
1047 }
1048
1049 private static boolean isDesktopWindow( long wi ) {
1050 return XWM.getWM().isDesktopWindow( wi );
1051 }
1052
1053 private void updateAlwaysOnTop() {
1054 if (log.isLoggable(PlatformLogger.Level.FINE)) {
1055 log.fine("Promoting always-on-top state {0}", Boolean.valueOf(alwaysOnTop));
1056 }
1057 XWM.getWM().setLayer(this,
1058 alwaysOnTop ?
1059 XLayerProtocol.LAYER_ALWAYS_ON_TOP :
1060 XLayerProtocol.LAYER_NORMAL);
1061 }
1062
1063 public void updateAlwaysOnTopState() {
1064 this.alwaysOnTop = ((Window) this.target).isAlwaysOnTop();
1065 if (ownerPeer != null) {
1066 XToolkit.awtLock();
1067 try {
1068 restoreTransientFor(this);
1069 applyWindowType();
1070 }
1071 finally {
1072 XToolkit.awtUnlock();
1073 }
1074 }
1075 updateAlwaysOnTop();
1076 }
1077
1078 boolean isLocationByPlatform() {
1079 return locationByPlatform;
1080 }
1081
1082 private void promoteDefaultPosition() {
1083 this.locationByPlatform = ((Window)target).isLocationByPlatform();
1084 if (locationByPlatform) {
1085 XToolkit.awtLock();
1086 try {
1087 Rectangle bounds = getBounds();
1088 XSizeHints hints = getHints();
1089 setSizeHints(hints.get_flags() & ~(XUtilConstants.USPosition | XUtilConstants.PPosition),
1090 bounds.x, bounds.y, bounds.width, bounds.height);
1091 } finally {
1092 XToolkit.awtUnlock();
1093 }
1094 }
1098 if (!isVisible() && vis) {
1099 isBeforeFirstMapNotify = true;
1100 winAttr.initialFocus = isAutoRequestFocus();
1101 if (!winAttr.initialFocus) {
1102 /*
1103 * It's easier and safer to temporary suppress WM_TAKE_FOCUS
1104 * protocol itself than to ignore WM_TAKE_FOCUS client message.
1105 * Because we will have to make the difference between
1106 * the message come after showing and the message come after
1107 * activation. Also, on Metacity, for some reason, we have _two_
1108 * WM_TAKE_FOCUS client messages when showing a frame/dialog.
1109 */
1110 suppressWmTakeFocus(true);
1111 }
1112 }
1113 updateFocusability();
1114 promoteDefaultPosition();
1115 if (!vis && warningWindow != null) {
1116 warningWindow.setSecurityWarningVisible(false, false);
1117 }
1118 boolean refreshChildsTransientFor = isVisible() != vis;
1119 super.setVisible(vis);
1120 if (refreshChildsTransientFor) {
1121 for (Window child : ((Window) target).getOwnedWindows()) {
1122 XToolkit.awtLock();
1123 try {
1124 if(!child.isLightweight() && child.isVisible()) {
1125 ComponentPeer childPeer = AWTAccessor.
1126 getComponentAccessor().getPeer(child);
1127 if(childPeer instanceof XWindowPeer) {
1128 XWindowPeer windowPeer = (XWindowPeer) childPeer;
1129 restoreTransientFor(windowPeer);
1130 windowPeer.applyWindowType();
1131 }
1132 }
1133 }
1134 finally {
1135 XToolkit.awtUnlock();
1136 }
1137 }
1138 }
1139 if (!vis && !isWithdrawn()) {
1140 // ICCCM, 4.1.4. Changing Window State:
1141 // "Iconic -> Withdrawn - The client should unmap the window and follow it
1142 // with a synthetic UnmapNotify event as described later in this section."
1143 // The same is true for Normal -> Withdrawn
1144 XToolkit.awtLock();
1145 try {
1146 XUnmapEvent unmap = new XUnmapEvent();
1147 unmap.set_window(window);
1148 unmap.set_event(XToolkit.getDefaultRootWindow());
1149 unmap.set_type(XConstants.UnmapNotify);
1150 unmap.set_from_configure(false);
1151 XlibWrapper.XSendEvent(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
1152 false, XConstants.SubstructureNotifyMask | XConstants.SubstructureRedirectMask,
1153 unmap.pData);
1154 unmap.dispose();
1155 }
1156 finally {
1157 XToolkit.awtUnlock();
1158 }
1647 *
1648 * @param window specifies the top-level window that the hint
1649 * is to be set to
1650 * @param transientForWindow the top-level window
1651 * @param updateChain specifies if next/prevTransientFor fields are
1652 * to be updated
1653 * @param allStates if set to <code>true</code> then TRANSIENT_FOR hint
1654 * is set regardless of the state of window and transientForWindow,
1655 * otherwise it is set only if both are in the same state
1656 */
1657 static void setToplevelTransientFor(XWindowPeer window, XWindowPeer transientForWindow,
1658 boolean updateChain, boolean allStates)
1659 {
1660 if ((window == null) || (transientForWindow == null)) {
1661 return;
1662 }
1663 if (updateChain) {
1664 window.prevTransientFor = transientForWindow;
1665 transientForWindow.nextTransientFor = window;
1666 }
1667 if (!allStates && (window.getWMState() != transientForWindow.getWMState())) {
1668 return;
1669 }
1670 if (window.getScreenNumber() != transientForWindow.getScreenNumber()) {
1671 return;
1672 }
1673 long bpw = window.getWindow();
1674 while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
1675 bpw = XlibUtil.getParentWindow(bpw);
1676 }
1677 long tpw = transientForWindow.getWindow();
1678 XBaseWindow parent = transientForWindow;
1679 while (tpw != 0 && ((!XlibUtil.isToplevelWindow(tpw) &&
1680 !XlibUtil.isXAWTToplevelWindow(tpw)) || !parent.isVisible())) {
1681 tpw = XlibUtil.getParentWindow(tpw);
1682 parent = XToolkit.windowToXWindow(tpw);
1683 }
1684 XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw);
1685 window.curRealTransientFor = parent;
1686 }
1687
1688 /*
1689 * This method does nothing if this window is not blocked by any modal dialog.
1690 * For modal blocked windows this method looks up for the nearest
1691 * prevTransiendFor window that is in the same state (Normal/Iconified/Withdrawn)
1692 * as this one and makes this window transient for it. The same operation is
1693 * performed for nextTransientFor window.
1694 * Values of prevTransientFor and nextTransientFor fields are not changed.
1695 */
1696 void updateTransientFor() {
1697 int state = getWMState();
1698 XWindowPeer p = prevTransientFor;
1699 while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
1700 p = p.prevTransientFor;
1701 }
1702 if (p != null) {
1703 setToplevelTransientFor(this, p, false, false);
1704 } else {
1705 restoreTransientFor(this);
1959 }
1960
1961 // This method is to be overriden in XDecoratedPeer.
1962 void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1963 }
1964
1965 /**
1966 * Applies the current window type.
1967 */
1968 private void applyWindowType() {
1969 XNETProtocol protocol = XWM.getWM().getNETProtocol();
1970 if (protocol == null) {
1971 return;
1972 }
1973
1974 XAtom typeAtom = null;
1975
1976 switch (getWindowType())
1977 {
1978 case NORMAL:
1979 typeAtom = curRealTransientFor == null ?
1980 protocol.XA_NET_WM_WINDOW_TYPE_NORMAL :
1981 protocol.XA_NET_WM_WINDOW_TYPE_DIALOG;
1982 break;
1983 case UTILITY:
1984 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_UTILITY;
1985 break;
1986 case POPUP:
1987 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_POPUP_MENU;
1988 break;
1989 }
1990
1991 if (typeAtom != null) {
1992 XAtomList wtype = new XAtomList();
1993 wtype.add(typeAtom);
1994 protocol.XA_NET_WM_WINDOW_TYPE.
1995 setAtomListProperty(getWindow(), wtype);
1996 } else {
1997 protocol.XA_NET_WM_WINDOW_TYPE.
1998 DeleteProperty(getWindow());
1999 }
|