1 /* 2 * Copyright (c) 1999, 2007, 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 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.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.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.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.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.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.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.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 public void run() { 214 WDesktopProperties.this.playWindowsSound(winEventName); 215 } 216 217 public String toString() { 218 return "WinPlaySound("+winEventName+")"; 219 } 220 221 public boolean equals(Object o) { 222 if (o == this) { 223 return true; 224 } 225 try { 226 return winEventName.equals(((WinPlaySound)o).winEventName); 227 } catch (Exception e) { 228 return false; 229 } 230 } 231 232 public int hashCode() { 233 return winEventName.hashCode(); 234 } 235 } 236 237 /* 238 * Called by WToolkit when Windows settings change-- we (re)load properties and 239 * set new values. 240 */ 241 @SuppressWarnings("unchecked") 242 synchronized Map<String, Object> getProperties() { 243 ThemeReader.flush(); 244 245 // load the changed properties into a new hashmap 246 map = new HashMap<String, Object>(); 247 getWindowsParameters(); 248 map.put(SunToolkit.DESKTOPFONTHINTS, SunToolkit.getDesktopFontHints()); 249 map.put(PROP_NAMES, getKeyNames()); 250 // DnD uses one value for x and y drag diff, but Windows provides 251 // separate ones. For now, just use the x value - rnk 252 map.put("DnD.Autoscroll.cursorHysteresis", map.get("win.drag.x")); 253 254 return (Map<String, Object>) map.clone(); 255 } 256 257 /* 258 * This returns the value for the desktop property "awt.font.desktophints" 259 * It builds this using the Windows desktop properties to return 260 * them as platform independent hints. 261 * This requires that the Windows properties have already been gathered 262 * and placed in "map" 263 */ 264 synchronized RenderingHints getDesktopAAHints() { 265 266 /* Equate "DEFAULT" to "OFF", which it is in our implementation. 267 * Doing this prevents unnecessary pipeline revalidation where 268 * the value OFF is detected as a distinct value by SunGraphics2D 269 */ 270 Object fontSmoothingHint = VALUE_TEXT_ANTIALIAS_DEFAULT; 271 Integer fontSmoothingContrast = null; 272 273 Boolean smoothingOn = (Boolean)map.get("win.text.fontSmoothingOn"); 274 275 if (smoothingOn != null && smoothingOn.equals(Boolean.TRUE)) { 276 Integer typeID = (Integer)map.get("win.text.fontSmoothingType"); 277 /* "1" is GASP/Standard but we'll also use that if the return 278 * value is anything other than "2" for LCD. 279 */ 280 if (typeID == null || typeID.intValue() <= 1 || 281 typeID.intValue() > 2) { 282 fontSmoothingHint = VALUE_TEXT_ANTIALIAS_GASP; 283 } else { 284 /* Recognise 0 as BGR and everything else as RGB - note 285 * that 1 is the expected value for RGB. 286 */ 287 Integer orientID = (Integer) 288 map.get("win.text.fontSmoothingOrientation"); 289 /* 0 is BGR, 1 is RGB. Other values, assume RGB */ 290 if (orientID == null || orientID.intValue() != 0) { 291 fontSmoothingHint = VALUE_TEXT_ANTIALIAS_LCD_HRGB; 292 } else { 293 fontSmoothingHint = VALUE_TEXT_ANTIALIAS_LCD_HBGR; 294 } 295 296 fontSmoothingContrast = (Integer) 297 map.get("win.text.fontSmoothingContrast"); 298 if (fontSmoothingContrast == null) { 299 fontSmoothingContrast = Integer.valueOf(140); 300 } else { 301 /* Windows values are scaled 10x those of Java 2D */ 302 fontSmoothingContrast = 303 Integer.valueOf(fontSmoothingContrast.intValue()/10); 304 } 305 } 306 } 307 308 RenderingHints hints = new RenderingHints(null); 309 hints.put(KEY_TEXT_ANTIALIASING, fontSmoothingHint); 310 if (fontSmoothingContrast != null) { 311 hints.put(KEY_TEXT_LCD_CONTRAST, fontSmoothingContrast); 312 } 313 return hints; 314 } 315 }