1 /* 2 * Copyright (c) 1999, 2014, 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.Color; 29 import java.awt.Font; 30 import static java.awt.RenderingHints.*; 31 import java.awt.RenderingHints; 32 33 import java.util.Arrays; 34 import java.util.HashMap; 35 import java.util.Map; 36 37 import sun.util.logging.PlatformLogger; 38 39 import sun.awt.SunToolkit; 40 41 /* 42 * Class encapsulating Windows desktop properties.; 43 * This class exposes Windows user configuration values 44 * for things like: 45 * Window metrics 46 * Accessibility, display settings 47 * Animation effects 48 * Colors 49 * Etc, etc etc. 50 * 51 * It's primary use is so that Windows specific Java code; 52 * like the Windows Pluggable Look-and-Feel can better adapt 53 * itself when running on a Windows platform. 54 */ 55 final class WDesktopProperties { 56 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WDesktopProperties"); 57 private static final String PREFIX = "win."; 58 private static final String FILE_PREFIX = "awt.file."; 59 private static final String PROP_NAMES = "win.propNames"; 60 61 private long pData; 62 63 static { 64 initIDs(); 65 } 66 67 private WToolkit wToolkit; 68 69 private HashMap<String, Object> map = new HashMap<String, Object>(); 70 71 /** 72 * Initialize JNI field and method IDs 73 */ 74 private static native void initIDs(); 75 76 static boolean isWindowsProperty(String name) { 77 return name.startsWith(PREFIX) || name.startsWith(FILE_PREFIX) || 78 name.equals(SunToolkit.DESKTOPFONTHINTS); 79 } 80 81 WDesktopProperties(WToolkit wToolkit) { 82 this.wToolkit = wToolkit; 83 init(); 84 } 85 86 private native void init(); 87 88 /* 89 * Returns String[] containing available property names 90 */ 91 private String [] getKeyNames() { 92 Object keys[] = map.keySet().toArray(); 93 String sortedKeys[] = new String[keys.length]; 94 95 for ( int nkey = 0; nkey < keys.length; nkey++ ) { 96 sortedKeys[nkey] = keys[nkey].toString(); 97 } 98 Arrays.sort(sortedKeys); 99 return sortedKeys; 100 } 101 102 /* 103 * Reads Win32 configuration information and 104 * updates hashmap values 105 */ 106 private native void getWindowsParameters(); 107 108 /* 109 * Called from native code to set a boolean property 110 */ 111 private synchronized void setBooleanProperty(String key, boolean value) { 112 assert( key != null ); 113 if (log.isLoggable(PlatformLogger.Level.FINE)) { 114 log.fine(key + "=" + String.valueOf(value)); 115 } 116 map.put(key, Boolean.valueOf(value)); 117 } 118 119 /* 120 * Called from native code to set an integer property 121 */ 122 private synchronized void setIntegerProperty(String key, int value) { 123 assert( key != null ); 124 if (log.isLoggable(PlatformLogger.Level.FINE)) { 125 log.fine(key + "=" + String.valueOf(value)); 126 } 127 map.put(key, Integer.valueOf(value)); 128 } 129 130 /* 131 * Called from native code to set a string property 132 */ 133 private synchronized void setStringProperty(String key, String value) { 134 assert( key != null ); 135 if (log.isLoggable(PlatformLogger.Level.FINE)) { 136 log.fine(key + "=" + value); 137 } 138 map.put(key, value); 139 } 140 141 /* 142 * Called from native code to set a color property 143 */ 144 private synchronized void setColorProperty(String key, int r, int g, int b) { 145 assert( key != null && r <= 255 && g <=255 && b <= 255 ); 146 Color color = new Color(r, g, b); 147 if (log.isLoggable(PlatformLogger.Level.FINE)) { 148 log.fine(key + "=" + color); 149 } 150 map.put(key, color); 151 } 152 153 /* Map of known windows font aliases to the preferred JDK name */ 154 static HashMap<String,String> fontNameMap; 155 static { 156 fontNameMap = new HashMap<String,String>(); 157 fontNameMap.put("Courier", Font.MONOSPACED); 158 fontNameMap.put("MS Serif", "Microsoft Serif"); 159 fontNameMap.put("MS Sans Serif", "Microsoft Sans Serif"); 160 fontNameMap.put("Terminal", Font.DIALOG); 161 fontNameMap.put("FixedSys", Font.MONOSPACED); 162 fontNameMap.put("System", Font.DIALOG); 163 } 164 /* 165 * Called from native code to set a font property 166 */ 167 private synchronized void setFontProperty(String key, String name, int style, int size) { 168 assert( key != null && style <= (Font.BOLD|Font.ITALIC) && size >= 0 ); 169 170 String mappedName = fontNameMap.get(name); 171 if (mappedName != null) { 172 name = mappedName; 173 } 174 Font font = new Font(name, style, size); 175 if (log.isLoggable(PlatformLogger.Level.FINE)) { 176 log.fine(key + "=" + font); 177 } 178 map.put(key, font); 179 180 String sizeKey = key + ".height"; 181 Integer iSize = Integer.valueOf(size); 182 if (log.isLoggable(PlatformLogger.Level.FINE)) { 183 log.fine(sizeKey + "=" + iSize); 184 } 185 map.put(sizeKey, iSize); 186 } 187 188 /* 189 * Called from native code to set a sound event property 190 */ 191 private synchronized void setSoundProperty(String key, String winEventName) { 192 assert( key != null && winEventName != null ); 193 194 Runnable soundRunnable = new WinPlaySound(winEventName); 195 if (log.isLoggable(PlatformLogger.Level.FINE)) { 196 log.fine(key + "=" + soundRunnable); 197 } 198 map.put(key, soundRunnable); 199 } 200 201 /* 202 * Plays Windows sound event 203 */ 204 private native void playWindowsSound(String winEventName); 205 206 class WinPlaySound implements Runnable { 207 String winEventName; 208 209 WinPlaySound(String winEventName) { 210 this.winEventName = winEventName; 211 } 212 213 @Override 214 public void run() { 215 WDesktopProperties.this.playWindowsSound(winEventName); 216 } 217 218 public String toString() { 219 return "WinPlaySound("+winEventName+")"; 220 } 221 222 public boolean equals(Object o) { 223 if (o == this) { 224 return true; 225 } 226 try { 227 return winEventName.equals(((WinPlaySound)o).winEventName); 228 } catch (Exception e) { 229 return false; 230 } 231 } 232 233 public int hashCode() { 234 return winEventName.hashCode(); 235 } 236 } 237 238 /* 239 * Called by WToolkit when Windows settings change-- we (re)load properties and 240 * set new values. 241 */ 242 @SuppressWarnings("unchecked") 243 synchronized Map<String, Object> getProperties() { 244 ThemeReader.flush(); 245 246 // load the changed properties into a new hashmap 247 map = new HashMap<String, Object>(); 248 getWindowsParameters(); 249 map.put(SunToolkit.DESKTOPFONTHINTS, SunToolkit.getDesktopFontHints()); 250 map.put(PROP_NAMES, getKeyNames()); 251 // DnD uses one value for x and y drag diff, but Windows provides 252 // separate ones. For now, just use the x value - rnk 253 map.put("DnD.Autoscroll.cursorHysteresis", map.get("win.drag.x")); 254 255 return (Map<String, Object>) map.clone(); 256 } 257 258 /* 259 * This returns the value for the desktop property "awt.font.desktophints" 260 * It builds this using the Windows desktop properties to return 261 * them as platform independent hints. 262 * This requires that the Windows properties have already been gathered 263 * and placed in "map" 264 */ 265 synchronized RenderingHints getDesktopAAHints() { 266 267 /* Equate "DEFAULT" to "OFF", which it is in our implementation. 268 * Doing this prevents unnecessary pipeline revalidation where 269 * the value OFF is detected as a distinct value by SunGraphics2D 270 */ 271 Object fontSmoothingHint = VALUE_TEXT_ANTIALIAS_DEFAULT; 272 Integer fontSmoothingContrast = null; 273 274 Boolean smoothingOn = (Boolean)map.get("win.text.fontSmoothingOn"); 275 276 if (smoothingOn != null && smoothingOn.equals(Boolean.TRUE)) { 277 Integer typeID = (Integer)map.get("win.text.fontSmoothingType"); 278 /* "1" is GASP/Standard but we'll also use that if the return 279 * value is anything other than "2" for LCD. 280 */ 281 if (typeID == null || typeID.intValue() <= 1 || 282 typeID.intValue() > 2) { 283 fontSmoothingHint = VALUE_TEXT_ANTIALIAS_GASP; 284 } else { 285 /* Recognise 0 as BGR and everything else as RGB - note 286 * that 1 is the expected value for RGB. 287 */ 288 Integer orientID = (Integer) 289 map.get("win.text.fontSmoothingOrientation"); 290 /* 0 is BGR, 1 is RGB. Other values, assume RGB */ 291 if (orientID == null || orientID.intValue() != 0) { 292 fontSmoothingHint = VALUE_TEXT_ANTIALIAS_LCD_HRGB; 293 } else { 294 fontSmoothingHint = VALUE_TEXT_ANTIALIAS_LCD_HBGR; 295 } 296 297 fontSmoothingContrast = (Integer) 298 map.get("win.text.fontSmoothingContrast"); 299 if (fontSmoothingContrast == null) { 300 fontSmoothingContrast = Integer.valueOf(140); 301 } else { 302 /* Windows values are scaled 10x those of Java 2D */ 303 fontSmoothingContrast = 304 Integer.valueOf(fontSmoothingContrast.intValue()/10); 305 } 306 } 307 } 308 309 RenderingHints hints = new RenderingHints(null); 310 hints.put(KEY_TEXT_ANTIALIASING, fontSmoothingHint); 311 if (fontSmoothingContrast != null) { 312 hints.put(KEY_TEXT_LCD_CONTRAST, fontSmoothingContrast); 313 } 314 return hints; 315 } 316 }