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.getGCDeviceBounds; 42 import static sun.java2d.SunGraphicsEnvironment.toDeviceSpaceAbs; 43 import static sun.java2d.SunGraphicsEnvironment.toUserSpace; 44 45 class WFramePeer extends WWindowPeer implements FramePeer { 46 47 static { 48 initIDs(); 49 } 50 51 // initialize JNI field and method IDs 52 private static native void initIDs(); 53 54 // FramePeer implementation 55 @Override 56 public native void setState(int state); 57 @Override 58 public native int getState(); 59 60 // sync target and peer 61 public void setExtendedState(int state) { 62 AWTAccessor.getFrameAccessor().setExtendedState((Frame)target, state); 63 } 64 public int getExtendedState() { 65 return AWTAccessor.getFrameAccessor().getExtendedState((Frame)target); 66 } 67 68 // Convenience methods to save us from trouble of extracting 69 // Rectangle fields in native code. 70 private native void setMaximizedBounds(int x, int y, int w, int h); 71 private native void clearMaximizedBounds(); 72 73 private static final boolean keepOnMinimize = "true".equals( 74 AccessController.doPrivileged( 75 new GetPropertyAction( 76 "sun.awt.keepWorkingSetOnMinimize"))); 77 78 @Override 79 public final void setMaximizedBounds(Rectangle b) { 80 if (b == null) { 81 clearMaximizedBounds(); 82 } else { 83 b = adjustMaximizedBounds(b); 84 setMaximizedBounds(b.x, b.y, b.width, b.height); 85 } 86 } 87 88 /** 89 * The incoming bounds describe the maximized size and position of the 90 * window in the virtual coordinate system. But the window manager expects 91 * that the bounds are based on the size of the primary monitor and 92 * position is based on the actual window monitor, even if the window 93 * ultimately maximizes onto a secondary monitor. And the window manager 94 * adjusts these values to compensate for differences between the primary 95 * monitor and the monitor that displays the window. 96 * <p> 97 * The method translates the incoming bounds to the values acceptable 98 * by the window manager. For more details, please refer to 6699851. 99 */ 100 private Rectangle adjustMaximizedBounds(Rectangle bounds) { 101 // All calculations should be done in the device space 102 bounds = toDeviceSpaceAbs(bounds); 103 GraphicsConfiguration gc = getGraphicsConfiguration(); 104 Rectangle currentDevBounds = getGCDeviceBounds(gc); 105 // Prepare data for WM_GETMINMAXINFO message. 106 // ptMaxPosition should be in coordinate system of the current monitor, 107 // not the main monitor, or monitor on which we maximize the window. 108 bounds.x -= currentDevBounds.x; 109 bounds.y -= currentDevBounds.y; 110 // ptMaxSize will be used as-is if the size is smaller than the main 111 // monitor. If the size is larger than the main monitor then the 112 // window manager adjusts the size, like this: 113 // result = bounds.w + (current.w - main.w); =>> wrong size 114 // We can try to compensate for this adjustment like this: 115 // result = bounds.w - (current.w - main.w); 116 // but this can result to the size smaller than the main screen, so no 117 // adjustment will be done by the window manager =>> wrong size. 118 // So we skip compensation here and cut the adjustment on 119 // WM_WINDOWPOSCHANGING event. 120 // Note that the result does not depend on the monitor on which we 121 // maximize the window. 122 return bounds; 123 } 124 125 @Override 126 public boolean updateGraphicsData(GraphicsConfiguration gc) { 127 boolean result = super.updateGraphicsData(gc); 128 Rectangle bounds = AWTAccessor.getFrameAccessor(). 129 getMaximizedBounds((Frame)target); 130 if (bounds != null) { 131 setMaximizedBounds(bounds); 132 } 133 return result; 134 } 135 136 @Override 137 boolean isTargetUndecorated() { 138 return ((Frame)target).isUndecorated(); 139 } 140 141 @Override 142 public void reshape(int x, int y, int width, int height) { 143 if (((Frame)target).isUndecorated()) { 144 super.reshape(x, y, width, height); 145 } else { 146 reshapeFrame(x, y, width, height); 147 } 148 } 149 150 @Override 151 public final Dimension getMinimumSize() { 152 GraphicsConfiguration gc = getGraphicsConfiguration(); 153 Dimension d = new Dimension(); 154 if (!((Frame)target).isUndecorated()) { 155 d.setSize(toUserSpace(gc, getSysMinWidth(), getSysMinHeight())); 156 } 157 if (((Frame) target).getMenuBar() != null) { 158 d.height += toUserSpace(gc, 0, getSysMenuHeight()).height; 159 } 160 return d; 161 } 162 163 // Note: Because this method calls resize(), which may be overridden 164 // by client code, this method must not be executed on the toolkit 165 // thread. 166 @Override 167 public void setMenuBar(MenuBar mb) { 168 WMenuBarPeer mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); 169 if (mbPeer != null) { 170 if (mbPeer.framePeer != this) { 171 mb.removeNotify(); 172 mb.addNotify(); 173 mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); 174 if (mbPeer != null && mbPeer.framePeer != this) { 175 throw new IllegalStateException("Wrong parent peer"); 176 } 177 } 178 if (mbPeer != null) { 179 addChildPeer(mbPeer); 180 } 181 } 182 setMenuBar0(mbPeer); 183 updateInsets(insets_); 184 } 185 186 // Note: Because this method calls resize(), which may be overridden 187 // by client code, this method must not be executed on the toolkit 188 // thread. 189 private native void setMenuBar0(WMenuBarPeer mbPeer); 190 191 // Toolkit & peer internals 192 193 WFramePeer(Frame target) { 194 super(target); 195 196 InputMethodManager imm = InputMethodManager.getInstance(); 197 String menuString = imm.getTriggerMenuString(); 198 if (menuString != null) 199 { 200 pSetIMMOption(menuString); 201 } 202 } 203 204 native void createAwtFrame(WComponentPeer parent); 205 @Override 206 void create(WComponentPeer parent) { 207 preCreate(parent); 208 createAwtFrame(parent); 209 } 210 211 @Override 212 void initialize() { 213 super.initialize(); 214 215 Frame target = (Frame)this.target; 216 217 if (target.getTitle() != null) { 218 setTitle(target.getTitle()); 219 } 220 setResizable(target.isResizable()); 221 setState(target.getExtendedState()); 222 } 223 224 private static native int getSysMenuHeight(); 225 226 native void pSetIMMOption(String option); 227 void notifyIMMOptionChange(){ 228 InputMethodManager.getInstance().notifyChangeRequest((Component)target); 229 } 230 231 @Override 232 public void setBoundsPrivate(int x, int y, int width, int height) { 233 setBounds(x, y, width, height, SET_BOUNDS); 234 } 235 @Override 236 public Rectangle getBoundsPrivate() { 237 return getBounds(); 238 } 239 240 // TODO: implement it in peers. WLightweightFramePeer may implement lw version. 241 @Override 242 public void emulateActivation(boolean activate) { 243 synthesizeWmActivate(activate); 244 } 245 246 private native void synthesizeWmActivate(boolean activate); 247 }