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 }