1 /* 2 * Copyright (c) 1996, 2016, 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 package sun.awt.windows; 26 27 import java.awt.*; 28 import java.awt.peer.*; 29 import sun.awt.AWTAccessor; 30 import sun.awt.im.InputMethodManager; 31 import java.security.AccessController; 32 import sun.security.action.GetPropertyAction; 33 34 class WFramePeer extends WWindowPeer implements FramePeer { 35 36 static { 37 initIDs(); 38 } 39 40 // initialize JNI field and method IDs 41 private static native void initIDs(); 42 43 // FramePeer implementation 44 @Override 45 public native void setState(int state); 46 @Override 47 public native int getState(); 48 49 // sync target and peer 50 public void setExtendedState(int state) { 51 AWTAccessor.getFrameAccessor().setExtendedState((Frame)target, state); 52 } 53 public int getExtendedState() { 54 return AWTAccessor.getFrameAccessor().getExtendedState((Frame)target); 55 } 56 57 // Convenience methods to save us from trouble of extracting 58 // Rectangle fields in native code. 59 private native void setMaximizedBounds(int x, int y, int w, int h); 60 private native void clearMaximizedBounds(); 61 62 private static final boolean keepOnMinimize = "true".equals( 63 AccessController.doPrivileged( 64 new GetPropertyAction( 65 "sun.awt.keepWorkingSetOnMinimize"))); 66 67 @Override 68 public void setMaximizedBounds(Rectangle b) { 69 if (b == null) { 70 clearMaximizedBounds(); 71 } else { 72 Rectangle adjBounds = adjustMaximizedBounds(b); 73 setMaximizedBounds(adjBounds.x, adjBounds.y, adjBounds.width, adjBounds.height); 74 } 75 } 76 77 /** 78 * The incoming bounds describe the maximized size and position of the 79 * window on the monitor that displays the window. But the window manager 80 * expects that the bounds are based on the size and position of the 81 * primary monitor, even if the window ultimately maximizes onto a 82 * secondary monitor. And the window manager adjusts these values to 83 * compensate for differences between the primary monitor and the monitor 84 * that displays the window. 85 * The method translates the incoming bounds to the values acceptable 86 * by the window manager. For more details, please refer to 6699851. 87 */ 88 private Rectangle adjustMaximizedBounds(Rectangle b) { 89 GraphicsConfiguration currentDevGC = getGraphicsConfiguration(); 90 91 GraphicsDevice primaryDev = GraphicsEnvironment 92 .getLocalGraphicsEnvironment().getDefaultScreenDevice(); 93 GraphicsConfiguration primaryDevGC = primaryDev.getDefaultConfiguration(); 94 95 double scaleX = 1.0; 96 double scaleY = 1.0; 97 98 int ht = primaryDev.getDisplayMode().getHeight(); 99 int wt = primaryDev.getDisplayMode().getWidth(); 100 // Rectangle fbc = currentDev.getFullScreenWindow().getBounds(); 101 102 if (currentDevGC != null && currentDevGC != primaryDevGC) { 103 Rectangle currentDevBounds = currentDevGC.getBounds(); 104 Rectangle primaryDevBounds = primaryDevGC.getBounds(); 105 106 //scale the bounds for proper comparisions. 107 scaleX = currentDevGC.getDefaultTransform().getScaleX(); 108 scaleY = currentDevGC.getDefaultTransform().getScaleY(); 109 currentDevBounds = scaleBounds(currentDevBounds, scaleX, scaleY); 110 b = scaleBounds(b, scaleX, scaleY); 111 Rectangle scaledPrimaryDevBounds = scaleBounds(primaryDevBounds, primaryDevGC.getDefaultTransform().getScaleX(), 112 primaryDevGC.getDefaultTransform().getScaleY()); 113 114 //due to floating point operations, it could be possible in some 115 //scenarios, that the width and height are slightly larger 116 //than the maximum permissible values. 117 if (b.width > currentDevBounds.width) { 118 b.width = currentDevBounds.width; 119 } 120 121 if (b.height > currentDevBounds.height) { 122 b.height = currentDevBounds.height; 123 } 124 125 //To maximize a window onto secondary screen, we still need to 126 //provide the primary screen coordinates, and set the width 127 //and height equal to primary screen bounds. 128 if (scaledPrimaryDevBounds.width < currentDevBounds.width && 129 b.width == currentDevBounds.width) { 130 b.width = primaryDevBounds.width; 131 } 132 133 if (scaledPrimaryDevBounds.height < currentDevBounds.height && 134 b.height == currentDevBounds.height) { 135 b.height = primaryDevBounds.height; 136 } 137 138 if (b.x == currentDevBounds.x) { 139 b.x = primaryDevBounds.x; 140 } 141 142 if (b.y == currentDevBounds.y) { 143 b.y = primaryDevBounds.y; 144 } 145 146 return b; 147 } else { 148 scaleX = primaryDevGC.getDefaultTransform().getScaleX(); 149 scaleY = primaryDevGC.getDefaultTransform().getScaleY(); 150 return scaleBounds(b, scaleX, scaleY); 151 } 152 } 153 154 private Rectangle scaleBounds(Rectangle source, double scaleX, double scaleY) { 155 Rectangle res = (Rectangle)source.clone(); 156 157 if (scaleX > 1.0) { 158 res.x = (int)(Math.ceil(source.x * scaleX)); 159 res.width =(int)(Math.ceil(source.width * scaleX)); 160 } 161 162 if (scaleY > 1.0) { 163 res.y = (int)(Math.ceil(source.y * scaleY)); 164 res.height = (int)(Math.ceil(source.height * scaleY)); 165 } 166 167 return res; 168 } 169 170 @Override 171 public boolean updateGraphicsData(GraphicsConfiguration gc) { 172 boolean result = super.updateGraphicsData(gc); 173 Rectangle bounds = AWTAccessor.getFrameAccessor(). 174 getMaximizedBounds((Frame)target); 175 if (bounds != null) { 176 setMaximizedBounds(bounds); 177 } 178 return result; 179 } 180 181 @Override 182 boolean isTargetUndecorated() { 183 return ((Frame)target).isUndecorated(); 184 } 185 186 @Override 187 public void reshape(int x, int y, int width, int height) { 188 if (((Frame)target).isUndecorated()) { 189 super.reshape(x, y, width, height); 190 } else { 191 reshapeFrame(x, y, width, height); 192 } 193 } 194 195 @Override 196 public Dimension getMinimumSize() { 197 Dimension d = new Dimension(); 198 if (!((Frame)target).isUndecorated()) { 199 d.setSize(getSysMinWidth(), getSysMinHeight()); 200 } 201 if (((Frame)target).getMenuBar() != null) { 202 d.height += getSysMenuHeight(); 203 } 204 return d; 205 } 206 207 // Note: Because this method calls resize(), which may be overridden 208 // by client code, this method must not be executed on the toolkit 209 // thread. 210 @Override 211 public void setMenuBar(MenuBar mb) { 212 WMenuBarPeer mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); 213 if (mbPeer != null) { 214 if (mbPeer.framePeer != this) { 215 mb.removeNotify(); 216 mb.addNotify(); 217 mbPeer = (WMenuBarPeer) WToolkit.targetToPeer(mb); 218 if (mbPeer != null && mbPeer.framePeer != this) { 219 throw new IllegalStateException("Wrong parent peer"); 220 } 221 } 222 if (mbPeer != null) { 223 addChildPeer(mbPeer); 224 } 225 } 226 setMenuBar0(mbPeer); 227 updateInsets(insets_); 228 } 229 230 // Note: Because this method calls resize(), which may be overridden 231 // by client code, this method must not be executed on the toolkit 232 // thread. 233 private native void setMenuBar0(WMenuBarPeer mbPeer); 234 235 // Toolkit & peer internals 236 237 WFramePeer(Frame target) { 238 super(target); 239 240 InputMethodManager imm = InputMethodManager.getInstance(); 241 String menuString = imm.getTriggerMenuString(); 242 if (menuString != null) 243 { 244 pSetIMMOption(menuString); 245 } 246 } 247 248 native void createAwtFrame(WComponentPeer parent); 249 @Override 250 void create(WComponentPeer parent) { 251 preCreate(parent); 252 createAwtFrame(parent); 253 } 254 255 @Override 256 void initialize() { 257 super.initialize(); 258 259 Frame target = (Frame)this.target; 260 261 if (target.getTitle() != null) { 262 setTitle(target.getTitle()); 263 } 264 setResizable(target.isResizable()); 265 setState(target.getExtendedState()); 266 } 267 268 private static native int getSysMenuHeight(); 269 270 native void pSetIMMOption(String option); 271 void notifyIMMOptionChange(){ 272 InputMethodManager.getInstance().notifyChangeRequest((Component)target); 273 } 274 275 @Override 276 public void setBoundsPrivate(int x, int y, int width, int height) { 277 setBounds(x, y, width, height, SET_BOUNDS); 278 } 279 @Override 280 public Rectangle getBoundsPrivate() { 281 return getBounds(); 282 } 283 284 // TODO: implement it in peers. WLightweightFramePeer may implement lw version. 285 @Override 286 public void emulateActivation(boolean activate) { 287 synthesizeWmActivate(activate); 288 } 289 290 private native void synthesizeWmActivate(boolean activate); 291 }