1 /* 2 * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.windows; 27 28 import java.awt.Component; 29 import java.awt.Dimension; 30 import java.awt.Frame; 31 import java.awt.GraphicsConfiguration; 32 import java.awt.MenuBar; 33 import java.awt.Rectangle; 34 import java.awt.peer.FramePeer; 35 import java.security.AccessController; 36 37 import sun.awt.AWTAccessor; 38 import sun.awt.im.InputMethodManager; 39 import sun.security.action.GetPropertyAction; 40 41 import static sun.java2d.SunGraphicsEnvironment.convertToDeviceSpace; 42 43 class WFramePeer extends WWindowPeer implements FramePeer { 44 45 static { 46 initIDs(); 47 } 48 49 // initialize JNI field and method IDs 50 private static native void initIDs(); 51 52 // FramePeer implementation 53 @Override 54 public native void setState(int state); 55 @Override 56 public native int getState(); 57 58 // sync target and peer 59 public void setExtendedState(int state) { 60 AWTAccessor.getFrameAccessor().setExtendedState((Frame)target, state); 61 } 62 public int getExtendedState() { 63 return AWTAccessor.getFrameAccessor().getExtendedState((Frame)target); 64 } 65 66 // Convenience methods to save us from trouble of extracting 67 // Rectangle fields in native code. 68 private native void setMaximizedBounds(int x, int y, int w, int h); 69 private native void clearMaximizedBounds(); 70 71 private static final boolean keepOnMinimize = "true".equals( 72 AccessController.doPrivileged( 73 new GetPropertyAction( 74 "sun.awt.keepWorkingSetOnMinimize"))); 75 76 @Override 77 public final void setMaximizedBounds(Rectangle b) { 78 if (b == null) { 79 clearMaximizedBounds(); 80 } else { 81 b = adjustMaximizedBounds(b); 82 setMaximizedBounds(b.x, b.y, b.width, b.height); 83 } 84 } 85 86 /** 87 * The incoming bounds describe the maximized size and position of the 88 * window in the virtual coordinate system. But the window manager expects 89 * that the bounds are based on the size of the primary monitor and 90 * position is based on the actual window monitor, even if the window 91 * ultimately maximizes onto a secondary monitor. And the window manager 92 * adjusts these values to compensate for differences between the primary 93 * monitor and the monitor that displays the window. 94 * <p> 95 * The method translates the incoming bounds to the values acceptable 96 * by the window manager. For more details, please refer to 6699851. 97 */ 98 private Rectangle adjustMaximizedBounds(Rectangle bounds) { 99 // All calculations should be done in the device space 100 bounds = convertToDeviceSpace(bounds); 101 102 GraphicsConfiguration gc = getGraphicsConfiguration(); 103 Rectangle currentDevBounds = convertToDeviceSpace(gc, gc.getBounds()); 104 // Prepare data for WM_GETMINMAXINFO message. 105 // ptMaxPosition should be in coordinate system of the current monitor, 106 // not the main monitor, or monitor on which we maximize the window. 107 bounds.x -= currentDevBounds.x; 108 bounds.y -= currentDevBounds.y; 109 // ptMaxSize will be used as-is if the size is smaller than the main 110 // monitor. If the size is larger than the main monitor then the 111 // window manager adjusts the size, like this: 112 // result = bounds.w + (current.w - main.w); =>> wrong size 113 // We can try to compensate for this adjustment like this: 114 // result = bounds.w - (current.w - main.w); 115 // but this can result to the size smaller than the main screen, so no 116 // adjustment will be done by the window manager =>> wrong size. 117 // So we skip compensation here and cut the adjustment on 118 // WM_WINDOWPOSCHANGING event. 119 // Note that the result does not depend on the monitor on which we 120 // maximize the window. 121 return bounds; 122 } 123 124 @Override 125 public boolean updateGraphicsData(GraphicsConfiguration gc) { 126 boolean result = super.updateGraphicsData(gc); 127 Rectangle bounds = AWTAccessor.getFrameAccessor(). 128 getMaximizedBounds((Frame)target); 129 if (bounds != null) { 130 setMaximizedBounds(bounds); 131 } 132 return result; 133 } 134 135 @Override 136 boolean isTargetUndecorated() { 137 return ((Frame)target).isUndecorated(); 138 } 139 140 @Override 141 public void reshape(int x, int y, int width, int height) { 142 if (((Frame)target).isUndecorated()) { 143 super.reshape(x, y, width, height); 144 } else { 145 reshapeFrame(x, y, width, height); 146 } 147 } 148 149 @Override 150 public final Dimension getMinimumSize() { 151 Dimension d = new Dimension(); 152 if (!((Frame)target).isUndecorated()) { 153 d.setSize(scaleDownX(getSysMinWidth()), 154 scaleDownY(getSysMinHeight())); 155 } 156 if (((Frame)target).getMenuBar() != null) { 157 d.height += scaleDownY(getSysMenuHeight()); 158 } 159 return d; 160 } 161 162 // Note: Because this method calls resize(), which may be overridden 163 // by client code, this method must not be executed on the toolkit 164 // thread. 165 @Override 166 public void setMenuBar(MenuBar mb) { 167 WMenuBarPeer mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); 168 if (mbPeer != null) { 169 if (mbPeer.framePeer != this) { 170 mb.removeNotify(); 171 mb.addNotify(); 172 mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); 173 if (mbPeer != null && mbPeer.framePeer != this) { 174 throw new IllegalStateException("Wrong parent peer"); 175 } 176 } 177 if (mbPeer != null) { 178 addChildPeer(mbPeer); 179 } 180 } 181 setMenuBar0(mbPeer); 182 updateInsets(insets_); 183 } 184 185 // Note: Because this method calls resize(), which may be overridden 186 // by client code, this method must not be executed on the toolkit 187 // thread. 188 private native void setMenuBar0(WMenuBarPeer mbPeer); 189 190 // Toolkit & peer internals 191 192 WFramePeer(Frame target) { 193 super(target); 194 195 InputMethodManager imm = InputMethodManager.getInstance(); 196 String menuString = imm.getTriggerMenuString(); 197 if (menuString != null) 198 { 199 pSetIMMOption(menuString); 200 } 201 } 202 203 native void createAwtFrame(WComponentPeer parent); 204 @Override 205 void create(WComponentPeer parent) { 206 preCreate(parent); 207 createAwtFrame(parent); 208 } 209 210 @Override 211 void initialize() { 212 super.initialize(); 213 214 Frame target = (Frame)this.target; 215 216 if (target.getTitle() != null) { 217 setTitle(target.getTitle()); 218 } 219 setResizable(target.isResizable()); 220 setState(target.getExtendedState()); 221 } 222 223 private static native int getSysMenuHeight(); 224 225 native void pSetIMMOption(String option); 226 void notifyIMMOptionChange(){ 227 InputMethodManager.getInstance().notifyChangeRequest((Component)target); 228 } 229 230 @Override 231 public void setBoundsPrivate(int x, int y, int width, int height) { 232 setBounds(x, y, width, height, SET_BOUNDS); 233 } 234 @Override 235 public Rectangle getBoundsPrivate() { 236 return getBounds(); 237 } 238 239 // TODO: implement it in peers. WLightweightFramePeer may implement lw version. 240 @Override 241 public void emulateActivation(boolean activate) { 242 synthesizeWmActivate(activate); 243 } 244 245 private native void synthesizeWmActivate(boolean activate); 246 }