1 /*
   2  * Copyright (c) 1999, 2010, 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 #include "awt.h"
  27 #include "mmsystem.h"
  28 #include "jlong.h"
  29 #include "awt_DesktopProperties.h"
  30 #include "awt_Toolkit.h"
  31 #include "sun_awt_windows_WDesktopProperties.h"
  32 #include "java_awt_Font.h"
  33 #include "awtmsg.h"
  34 #include "zmouse.h"
  35 #include <shellapi.h>
  36 #include <shlobj.h>
  37 
  38 // WDesktopProperties fields
  39 jfieldID AwtDesktopProperties::pDataID = 0;
  40 jmethodID AwtDesktopProperties::setBooleanPropertyID = 0;
  41 jmethodID AwtDesktopProperties::setIntegerPropertyID = 0;
  42 jmethodID AwtDesktopProperties::setStringPropertyID = 0;
  43 jmethodID AwtDesktopProperties::setColorPropertyID = 0;
  44 jmethodID AwtDesktopProperties::setFontPropertyID = 0;
  45 jmethodID AwtDesktopProperties::setSoundPropertyID = 0;
  46 
  47 AwtDesktopProperties::AwtDesktopProperties(jobject self) {
  48     this->self = GetEnv()->NewGlobalRef(self);
  49     GetEnv()->SetLongField( self, AwtDesktopProperties::pDataID,
  50                             ptr_to_jlong(this) );
  51 }
  52 
  53 AwtDesktopProperties::~AwtDesktopProperties() {
  54     GetEnv()->DeleteGlobalRef(self);
  55 }
  56 
  57 //
  58 // Reads Windows parameters and sets the corresponding values
  59 // in WDesktopProperties
  60 //
  61 void AwtDesktopProperties::GetWindowsParameters() {
  62     if (GetEnv()->EnsureLocalCapacity(MAX_PROPERTIES) < 0) {
  63         DASSERT(0);
  64         return;
  65     }
  66     // this number defines the set of properties available, it is incremented
  67     // whenever more properties are added (in a public release of course)
  68     // for example, version 1 defines the properties available in Java SDK version 1.3.
  69     SetIntegerProperty( TEXT("win.properties.version"), AWT_DESKTOP_PROPERTIES_VERSION);
  70     GetNonClientParameters();
  71     GetIconParameters();
  72     GetColorParameters();
  73     GetOtherParameters();
  74     GetSoundEvents();
  75     GetSystemProperties();
  76     if (IS_WINXP) {
  77         GetXPStyleProperties();
  78     }
  79 }
  80 
  81 void AwtDesktopProperties::GetSystemProperties() {
  82     HDC dc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  83 
  84     if (dc != NULL) {
  85         SetFontProperty(dc, ANSI_FIXED_FONT, TEXT("win.ansiFixed.font"));
  86         SetFontProperty(dc, ANSI_VAR_FONT, TEXT("win.ansiVar.font"));
  87         SetFontProperty(dc, DEVICE_DEFAULT_FONT, TEXT("win.deviceDefault.font"));
  88         SetFontProperty(dc, DEFAULT_GUI_FONT, TEXT("win.defaultGUI.font"));
  89         SetFontProperty(dc, OEM_FIXED_FONT, TEXT("win.oemFixed.font"));
  90         SetFontProperty(dc, SYSTEM_FONT, TEXT("win.system.font"));
  91         SetFontProperty(dc, SYSTEM_FIXED_FONT, TEXT("win.systemFixed.font"));
  92         DeleteDC(dc);
  93     }
  94 }
  95 
  96 
  97 // Does the actual lookup for shell dialog font (MS Shell Dlg).  fontName
  98 // contains the name to lookup (either MS Shell Dlg or MS Shell Dlg 2) and
  99 // handle contains a reference toe the registry entry to look in.
 100 // This will return NULL or a pointer to the resolved name.
 101 // Note that it uses malloc() and returns the pointer to allocated
 102 // memory, so remember to use free() when you are done with its
 103 // result.
 104 static LPTSTR resolveShellDialogFont(LPTSTR fontName, HKEY handle) {
 105     DWORD valueType, valueSize;
 106     if (RegQueryValueEx((HKEY)handle, fontName, NULL,
 107                         &valueType, NULL, &valueSize) != 0) {
 108         // Couldn't find it
 109         return NULL;
 110     }
 111     if (valueType != REG_SZ) {
 112         // Not the expected type
 113         return NULL;
 114     }
 115     LPTSTR buffer = (LPTSTR)safe_Malloc(valueSize);
 116     if (RegQueryValueEx((HKEY)handle, fontName, NULL,
 117                         &valueType, (unsigned char *)buffer, &valueSize) != 0) {
 118         // Error fetching
 119         free(buffer);
 120         return NULL;
 121     }
 122     return buffer;
 123 }
 124 
 125 // Determines what the font MS Shell Dlg maps to.
 126 // Note that it uses malloc() and returns the pointer to allocated
 127 // memory, so remember to use free() when you are done with its
 128 // result.
 129 static LPTSTR resolveShellDialogFont() {
 130     LPTSTR subKey = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
 131 
 132     HKEY handle;
 133     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &handle) != 0) {
 134         return NULL;
 135     }
 136     // Prefer MS Shell Dlg 2.
 137     LPTSTR font = resolveShellDialogFont(TEXT("MS Shell Dlg 2"), handle);
 138     if (font == NULL) {
 139         font = resolveShellDialogFont(TEXT("MS Shell Dlg"), handle);
 140     }
 141     RegCloseKey(handle);
 142     return font;
 143 }
 144 
 145 // Local function for getting values from the Windows registry
 146 // Note that it uses malloc() and returns the pointer to allocated
 147 // memory, so remember to use free() when you are done with its
 148 // result.
 149 static LPTSTR getWindowsPropFromReg(LPTSTR subKey, LPTSTR valueName, DWORD *valueType) {
 150     HKEY handle;
 151     if (RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &handle) != 0) {
 152         return NULL;
 153     }
 154     // valueSize is in bytes, while valueChar is in characters.
 155     DWORD valueSize, valueChar;
 156     if (RegQueryValueEx((HKEY)handle, valueName, NULL,
 157                         valueType, NULL, &valueSize) != 0) {
 158         RegCloseKey(handle);
 159         return NULL;
 160     }
 161     LPTSTR buffer = (LPTSTR)safe_Malloc(valueSize);
 162     if (RegQueryValueEx((HKEY)handle, valueName, NULL,
 163                         valueType, (unsigned char *)buffer, &valueSize) != 0) {
 164         free(buffer);
 165         RegCloseKey(handle);
 166         return NULL;
 167     }
 168     RegCloseKey(handle);
 169 
 170     if (*valueType == REG_EXPAND_SZ) {
 171         // Pending: buffer must be null-terminated at this point
 172         valueChar = ExpandEnvironmentStrings(buffer, NULL, 0);
 173         LPTSTR buffer2 = (LPTSTR)safe_Malloc(valueChar*sizeof(TCHAR));
 174         ExpandEnvironmentStrings(buffer, buffer2, valueChar);
 175         free(buffer);
 176         return buffer2;
 177     } else if (*valueType == REG_SZ) {
 178         return buffer;
 179     } else if (*valueType == REG_DWORD) {
 180         return buffer;
 181     } else {
 182         free(buffer);
 183         return NULL;
 184     }
 185 }
 186 
 187 static LPTSTR getXPStylePropFromReg(LPTSTR valueName) {
 188     DWORD valueType;
 189     return getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager"),
 190                                  valueName, &valueType);
 191 }
 192 
 193 
 194 // Used in AwtMenuItem to determine the color of top menus,
 195 // since they depend on XP style. ThemeActive property is
 196 // '1' for XP Style, '0' for Windows classic style.
 197 BOOL AwtDesktopProperties::IsXPStyle() {
 198     LPTSTR style = getXPStylePropFromReg(TEXT("ThemeActive"));
 199     BOOL result = (style != NULL && *style == _T('1'));
 200     free(style);
 201     return result;
 202 }
 203 
 204 void AwtDesktopProperties::GetXPStyleProperties() {
 205     LPTSTR value;
 206 
 207     value = getXPStylePropFromReg(TEXT("ThemeActive"));
 208     SetBooleanProperty(TEXT("win.xpstyle.themeActive"), (value != NULL && *value == _T('1')));
 209     if (value != NULL) {
 210         free(value);
 211     }
 212     value = getXPStylePropFromReg(TEXT("DllName"));
 213     if (value != NULL) {
 214         SetStringProperty(TEXT("win.xpstyle.dllName"), value);
 215         free(value);
 216     }
 217     value = getXPStylePropFromReg(TEXT("SizeName"));
 218     if (value != NULL) {
 219         SetStringProperty(TEXT("win.xpstyle.sizeName"), value);
 220         free(value);
 221     }
 222     value = getXPStylePropFromReg(TEXT("ColorName"));
 223     if (value != NULL) {
 224         SetStringProperty(TEXT("win.xpstyle.colorName"), value);
 225         free(value);
 226     }
 227 }
 228 
 229 
 230 void AwtDesktopProperties::GetNonClientParameters() {
 231     //
 232     // general window properties
 233     //
 234     NONCLIENTMETRICS    ncmetrics;
 235 
 236     // Fix for 6944516: specify correct size for ncmetrics on WIN2K/XP
 237     // Microsoft recommend to subtract the size of  'iPaddedBorderWidth' field
 238     // when running on XP. However this can't be referenced at compile time
 239     // with the older SDK, so there use 'lfMessageFont' plus its size.
 240     if (!IS_WINVISTA) {
 241 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
 242         ncmetrics.cbSize = offsetof(NONCLIENTMETRICS, iPaddedBorderWidth);
 243 #else
 244         ncmetrics.cbSize = offsetof(NONCLIENTMETRICS,lfMessageFont) + sizeof(LOGFONT);
 245 #endif
 246     } else {
 247         ncmetrics.cbSize = sizeof(ncmetrics);
 248     }
 249     VERIFY( SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncmetrics.cbSize, &ncmetrics, FALSE) );
 250 
 251     SetFontProperty( TEXT("win.frame.captionFont"), ncmetrics.lfCaptionFont );
 252     SetIntegerProperty( TEXT("win.frame.captionHeight"), ncmetrics.iCaptionHeight );
 253     SetIntegerProperty( TEXT("win.frame.captionButtonWidth"), ncmetrics.iCaptionWidth );
 254     SetIntegerProperty( TEXT("win.frame.captionButtonHeight"), ncmetrics.iCaptionHeight );
 255     SetFontProperty( TEXT("win.frame.smallCaptionFont"), ncmetrics.lfSmCaptionFont );
 256     SetIntegerProperty( TEXT("win.frame.smallCaptionHeight"), ncmetrics.iSmCaptionHeight );
 257     SetIntegerProperty( TEXT("win.frame.smallCaptionButtonWidth"), ncmetrics.iSmCaptionWidth );
 258     SetIntegerProperty( TEXT("win.frame.smallCaptionButtonHeight"), ncmetrics.iSmCaptionHeight );
 259     SetIntegerProperty( TEXT("win.frame.sizingBorderWidth"), ncmetrics.iBorderWidth );
 260 
 261     // menu properties
 262     SetFontProperty( TEXT("win.menu.font"), ncmetrics.lfMenuFont );
 263     SetIntegerProperty( TEXT("win.menu.height"), ncmetrics.iMenuHeight );
 264     SetIntegerProperty( TEXT("win.menu.buttonWidth"), ncmetrics.iMenuWidth );
 265 
 266     // scrollbar properties
 267     SetIntegerProperty( TEXT("win.scrollbar.width"), ncmetrics.iScrollWidth );
 268     SetIntegerProperty( TEXT("win.scrollbar.height"), ncmetrics.iScrollHeight );
 269 
 270     // status bar and tooltip properties
 271     SetFontProperty( TEXT("win.status.font"), ncmetrics.lfStatusFont );
 272     SetFontProperty( TEXT("win.tooltip.font"), ncmetrics.lfStatusFont );
 273 
 274     // message box properties
 275     SetFontProperty( TEXT("win.messagebox.font"), ncmetrics.lfMessageFont );
 276 }
 277 
 278 void AwtDesktopProperties::GetIconParameters() {
 279     //
 280     // icon properties
 281     //
 282     ICONMETRICS iconmetrics;
 283 
 284     iconmetrics.cbSize = sizeof(iconmetrics);
 285     VERIFY( SystemParametersInfo(SPI_GETICONMETRICS, iconmetrics.cbSize, &iconmetrics, FALSE) );
 286 
 287     SetIntegerProperty(TEXT("win.icon.hspacing"), iconmetrics.iHorzSpacing);
 288     SetIntegerProperty(TEXT("win.icon.vspacing"), iconmetrics.iVertSpacing);
 289     SetBooleanProperty(TEXT("win.icon.titleWrappingOn"), iconmetrics.iTitleWrap != 0);
 290     SetFontProperty(TEXT("win.icon.font"), iconmetrics.lfFont);
 291 }
 292 /*
 293  Windows settings for these are also in the registry
 294  They exist as system wide HKLM: HKEY_LOCAL_MACHINE and
 295  HKCU: HKEY_CURRENT_USER.
 296  HKCU\Control Panel\Desktop\FontSmoothing :  "0=OFF",  "2=ON"
 297  HKCU\Control Panel\Desktop\FontSmoothingType: 1=Standard, 2=LCD
 298  HKCU\Control Panel\Desktop\FontSmoothingGamma: 1000->2200
 299  HKCU\Control Panel\Desktop\FontSmoothingOrientation: 0=BGR, 1=RGB
 300 
 301  SystemParametersInfo supplies the first three of these but does not
 302  however expose the Orientation. That has to come from the registry.
 303 
 304  We go to some small lengths in here to not make queries we don't need.
 305  Eg if we previously were using standard font smoothing and we still are
 306  then its unlikely that any change in gamma will have occurred except
 307  by a program which changed it, and even if it did, we don't need to pick
 308  it up until someone turns on the LCD option.
 309  To do: this loop is called once per top-level window so an app with
 310  N windows will get notified N times. It would save us a small amount of
 311  redundant work if I could identify the message as being one already processed
 312  for another window.
 313  Also presumably a repaint that specifies only a partially damaged window
 314  isn't one that needs this checking.
 315 */
 316 
 317 #define FONTSMOOTHING_OFF 0
 318 #define FONTSMOOTHING_ON  1
 319 #define FONTSMOOTHING_STANDARD 1
 320 #define FONTSMOOTHING_LCD 2
 321 #define LCD_RGB_ORDER 1
 322 #define LCD_BGR_ORDER 0
 323 
 324 
 325 int GetLCDSubPixelOrder() {
 326     LONG order=99;
 327     LONG bufferSize = 4;
 328     HKEY hkeyDesktop;
 329     static LPCTSTR DESKTOPKEY = TEXT("Control Panel\\Desktop");
 330     LONG ret = RegOpenKeyEx(HKEY_CURRENT_USER,
 331                             DESKTOPKEY, 0L, KEY_READ, &hkeyDesktop);
 332     if (ret != ERROR_SUCCESS) {
 333         return LCD_RGB_ORDER;
 334     }
 335     ret = RegQueryValueEx(hkeyDesktop, TEXT("FontSmoothingOrientation"),
 336                           NULL, NULL, (LPBYTE)&order, (LPDWORD)&bufferSize);
 337     RegCloseKey(hkeyDesktop);
 338     if (ret != ERROR_SUCCESS) {
 339         return LCD_RGB_ORDER;
 340     } else {
 341         return (int)order;
 342     }
 343 }
 344 
 345 void CheckFontSmoothingSettings(HWND hWnd) {
 346     static BOOL firstTime = TRUE;
 347     static BOOL lastFontSmoothing = FALSE;
 348     static UINT lastFontSmoothingType = FONTSMOOTHING_ON;
 349     static UINT lastFontSmoothingContrast = 1400;
 350     static UINT lastSubpixelOrder = LCD_RGB_ORDER;
 351 
 352     /* If we are called with a window handle it is because there is a
 353      * message to repaint at least some part of the window which typically
 354      * is not because of the desktop font settings change. Much more likely
 355      * its a normal repaint event. If it is because of the rare settings
 356      * change in that case the update region will be the entire window.
 357      * Try to as cheaply as possible determine if this is not a call
 358      * to repaint the whole window by assuming that all such calls will
 359      * have an update region whose origin is 0,0. Only in that case will
 360      * we take the hit of checking the settings.
 361      * Thus we avoid taking the hit of the other calls for most partial
 362      * expose events, which will never be the result of changes to desktop
 363      * font settings.
 364      */
 365     if (hWnd != NULL) {
 366         RECT r;
 367         if (!::GetUpdateRect(hWnd, &r, FALSE) || r.top != 0 || r.left != 0) {
 368             return;
 369         }
 370     }
 371 
 372     BOOL fontSmoothing = FALSE, settingsChanged;
 373     UINT fontSmoothingType=0, fontSmoothingContrast=0, subPixelOrder;
 374 
 375     if (firstTime) {
 376         SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0);
 377         if (IS_WINXP) {
 378             SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0,
 379                                  &fontSmoothingType, 0);
 380             SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0,
 381                                  &fontSmoothingContrast, 0);
 382         }
 383         lastFontSmoothing = fontSmoothing;
 384         lastFontSmoothingType = fontSmoothingType;
 385         lastFontSmoothingContrast = fontSmoothingContrast;
 386         firstTime = FALSE;
 387         return;
 388     } else {
 389         SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0);
 390         settingsChanged = fontSmoothing != lastFontSmoothing;
 391         if (!settingsChanged && fontSmoothing == FONTSMOOTHING_OFF) {
 392             /* no need to check the other settings in this case. */
 393             return;
 394         }
 395         if (IS_WINXP) {
 396             SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0,
 397                                  &fontSmoothingType, 0);
 398             settingsChanged |= fontSmoothingType != lastFontSmoothingType;
 399             if (!settingsChanged &&
 400                 fontSmoothingType == FONTSMOOTHING_STANDARD) {
 401                 /* No need to check any LCD specific settings */
 402                 return;
 403             } else {
 404                 SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0,
 405                                      &fontSmoothingContrast, 0);
 406                 settingsChanged |=
 407                     fontSmoothingContrast != lastFontSmoothingContrast;
 408                 if (fontSmoothingType == FONTSMOOTHING_LCD) {
 409                     // Order is a registry entry so more expensive to check.x
 410                     subPixelOrder = GetLCDSubPixelOrder();
 411                     settingsChanged |= subPixelOrder != lastSubpixelOrder;
 412                 }
 413             }
 414         } else {
 415             if (settingsChanged && fontSmoothing == FONTSMOOTHING_ON) {
 416                 fontSmoothingType = FONTSMOOTHING_STANDARD;
 417             }
 418         }
 419     }
 420     if (settingsChanged) {
 421         /* Some of these values may not have been queried, but it shouldn't
 422          * matter as what's important is to track changes in values we are
 423          * actually using. The up-call we make here will cause the actual
 424          * values for everything to get queried and set into the desktop
 425          * properties.
 426          */
 427         lastFontSmoothing = fontSmoothing;
 428         lastFontSmoothingType = fontSmoothingType;
 429         lastFontSmoothingContrast = fontSmoothingContrast;
 430         lastSubpixelOrder = subPixelOrder;
 431 
 432         jobject peer = AwtToolkit::GetInstance().GetPeer();
 433         if (peer != NULL) {
 434             AwtToolkit::GetEnv()->CallVoidMethod(peer,
 435                                      AwtToolkit::windowsSettingChangeMID);
 436         }
 437     }
 438 }
 439 
 440 void AwtDesktopProperties::GetColorParameters() {
 441 
 442     SetColorProperty(TEXT("win.frame.activeCaptionGradientColor"),
 443                      GetSysColor(COLOR_GRADIENTACTIVECAPTION));
 444     SetColorProperty(TEXT("win.frame.inactiveCaptionGradientColor"),
 445                      GetSysColor(COLOR_GRADIENTINACTIVECAPTION));
 446     SetColorProperty(TEXT("win.item.hotTrackedColor"),
 447                      GetSysColor(COLOR_HOTLIGHT));
 448     SetColorProperty(TEXT("win.3d.darkShadowColor"), GetSysColor(COLOR_3DDKSHADOW));
 449     SetColorProperty(TEXT("win.3d.backgroundColor"), GetSysColor(COLOR_3DFACE));
 450     SetColorProperty(TEXT("win.3d.highlightColor"), GetSysColor(COLOR_3DHIGHLIGHT));
 451     SetColorProperty(TEXT("win.3d.lightColor"), GetSysColor(COLOR_3DLIGHT));
 452     SetColorProperty(TEXT("win.3d.shadowColor"), GetSysColor(COLOR_3DSHADOW));
 453     SetColorProperty(TEXT("win.button.textColor"), GetSysColor(COLOR_BTNTEXT));
 454     SetColorProperty(TEXT("win.desktop.backgroundColor"), GetSysColor(COLOR_DESKTOP));
 455     SetColorProperty(TEXT("win.frame.activeCaptionColor"), GetSysColor(COLOR_ACTIVECAPTION));
 456     SetColorProperty(TEXT("win.frame.activeBorderColor"), GetSysColor(COLOR_ACTIVEBORDER));
 457 
 458     // ?? ?? ??
 459     SetColorProperty(TEXT("win.frame.color"), GetSysColor(COLOR_WINDOWFRAME)); // ?? WHAT THE HECK DOES THIS MEAN ??
 460     // ?? ?? ??
 461 
 462     SetColorProperty(TEXT("win.frame.backgroundColor"), GetSysColor(COLOR_WINDOW));
 463     SetColorProperty(TEXT("win.frame.captionTextColor"), GetSysColor(COLOR_CAPTIONTEXT));
 464     SetColorProperty(TEXT("win.frame.inactiveBorderColor"), GetSysColor(COLOR_INACTIVEBORDER));
 465     SetColorProperty(TEXT("win.frame.inactiveCaptionColor"), GetSysColor(COLOR_INACTIVECAPTION));
 466     SetColorProperty(TEXT("win.frame.inactiveCaptionTextColor"), GetSysColor(COLOR_INACTIVECAPTIONTEXT));
 467     SetColorProperty(TEXT("win.frame.textColor"), GetSysColor(COLOR_WINDOWTEXT));
 468     SetColorProperty(TEXT("win.item.highlightColor"), GetSysColor(COLOR_HIGHLIGHT));
 469     SetColorProperty(TEXT("win.item.highlightTextColor"), GetSysColor(COLOR_HIGHLIGHTTEXT));
 470     SetColorProperty(TEXT("win.mdi.backgroundColor"), GetSysColor(COLOR_APPWORKSPACE));
 471     SetColorProperty(TEXT("win.menu.backgroundColor"), GetSysColor(COLOR_MENU));
 472     SetColorProperty(TEXT("win.menu.textColor"), GetSysColor(COLOR_MENUTEXT));
 473     // COLOR_MENUBAR is only defined on WindowsXP. Our binaries are
 474     // built on NT, hence the below ifdef.
 475 #ifndef COLOR_MENUBAR
 476 #define COLOR_MENUBAR 30
 477 #endif
 478     SetColorProperty(TEXT("win.menubar.backgroundColor"),
 479                                 GetSysColor(IS_WINXP ? COLOR_MENUBAR : COLOR_MENU));
 480     SetColorProperty(TEXT("win.scrollbar.backgroundColor"), GetSysColor(COLOR_SCROLLBAR));
 481     SetColorProperty(TEXT("win.text.grayedTextColor"), GetSysColor(COLOR_GRAYTEXT));
 482     SetColorProperty(TEXT("win.tooltip.backgroundColor"), GetSysColor(COLOR_INFOBK));
 483     SetColorProperty(TEXT("win.tooltip.textColor"), GetSysColor(COLOR_INFOTEXT));
 484 }
 485 
 486 void AwtDesktopProperties::GetOtherParameters() {
 487     // TODO BEGIN: On NT4, some setttings don't trigger WM_SETTINGCHANGE --
 488     // check whether this has been fixed on Windows 2000 and Windows 98
 489     // ECH 10/6/2000 seems to be fixed on NT4 SP5, but not on 98
 490     SetBooleanProperty(TEXT("win.frame.fullWindowDragsOn"), GetBooleanParameter(SPI_GETDRAGFULLWINDOWS));
 491     SetBooleanProperty(TEXT("win.text.fontSmoothingOn"), GetBooleanParameter(SPI_GETFONTSMOOTHING));
 492     // TODO END
 493 
 494     if (IS_WINXP) {
 495         SetIntegerProperty(TEXT("win.text.fontSmoothingType"),
 496                            GetIntegerParameter(SPI_GETFONTSMOOTHINGTYPE));
 497         SetIntegerProperty(TEXT("win.text.fontSmoothingContrast"),
 498                            GetIntegerParameter(SPI_GETFONTSMOOTHINGCONTRAST));
 499         SetIntegerProperty(TEXT("win.text.fontSmoothingOrientation"),
 500                            GetLCDSubPixelOrder());
 501     }
 502 
 503     int cxdrag = GetSystemMetrics(SM_CXDRAG);
 504     int cydrag = GetSystemMetrics(SM_CYDRAG);
 505     SetIntegerProperty(TEXT("win.drag.width"), cxdrag);
 506     SetIntegerProperty(TEXT("win.drag.height"), cydrag);
 507     SetIntegerProperty(TEXT("DnD.gestureMotionThreshold"), max(cxdrag, cydrag)/2);
 508     SetIntegerProperty(TEXT("awt.mouse.numButtons"), AwtToolkit::GetNumberOfButtons());
 509 
 510     SetIntegerProperty(TEXT("awt.multiClickInterval"), GetDoubleClickTime());
 511 
 512     // BEGIN cross-platform properties
 513     // Note that these are cross-platform properties, but are being stuck into
 514     // WDesktopProperties.  WToolkit.lazilyLoadDesktopProperty() can find them,
 515     // but if a Toolkit subclass uses the desktopProperties
 516     // member, these properties won't be there. -bchristi, echawkes
 517     // This property is called "win.frame.fullWindowDragsOn" above
 518     // This is one of the properties that don't trigger WM_SETTINGCHANGE
 519     SetBooleanProperty(TEXT("awt.dynamicLayoutSupported"), GetBooleanParameter(SPI_GETDRAGFULLWINDOWS));
 520     SetBooleanProperty(TEXT("awt.wheelMousePresent"),
 521                        ::GetSystemMetrics(SM_MOUSEWHEELPRESENT));
 522 
 523     // END cross-platform properties
 524 
 525     //DWORD   menuShowDelay;
 526     //SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &menuShowDelay, 0);
 527     // SetIntegerProperty(TEXT("win.menu.showDelay"), menuShowDelay);
 528     SetBooleanProperty(TEXT("win.frame.captionGradientsOn"), GetBooleanParameter(SPI_GETGRADIENTCAPTIONS));
 529     SetBooleanProperty(TEXT("win.item.hotTrackingOn"), GetBooleanParameter(SPI_GETHOTTRACKING));
 530 
 531     SetBooleanProperty(TEXT("win.menu.keyboardCuesOn"), GetBooleanParameter(SPI_GETKEYBOARDCUES));
 532 
 533     // High contrast accessibility property
 534     HIGHCONTRAST contrast;
 535     contrast.cbSize = sizeof(HIGHCONTRAST);
 536     if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST),
 537                              &contrast, 0) != 0 &&
 538               (contrast.dwFlags & HCF_HIGHCONTRASTON) == HCF_HIGHCONTRASTON) {
 539       SetBooleanProperty(TEXT("win.highContrast.on"), TRUE);
 540     }
 541     else {
 542       SetBooleanProperty(TEXT("win.highContrast.on"), FALSE);
 543     }
 544 
 545     SHELLFLAGSTATE sfs;
 546     ::SHGetSettings(&sfs, SSF_SHOWALLOBJECTS | SSF_SHOWATTRIBCOL);
 547     if (sfs.fShowAllObjects) {
 548         SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), TRUE);
 549     }
 550     else {
 551         SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), FALSE);
 552     }
 553     if (sfs.fShowAttribCol) {
 554         SetBooleanProperty(TEXT("awt.file.showAttribCol"), TRUE);
 555     }
 556     else {
 557         SetBooleanProperty(TEXT("awt.file.showAttribCol"), FALSE);
 558     }
 559 
 560     LPTSTR value;
 561     DWORD valueType;
 562 
 563     // Shell Icon BPP - only honored on platforms before XP
 564     value = getWindowsPropFromReg(TEXT("Control Panel\\Desktop\\WindowMetrics"),
 565                                   TEXT("Shell Icon BPP"), &valueType);
 566     if (value != NULL) {
 567         if (valueType == REG_SZ) {
 568             SetStringProperty(TEXT("win.icon.shellIconBPP"), value);
 569         }
 570         free(value);
 571     }
 572 
 573 
 574     // The following registry settings control the file chooser places bar
 575     // under the Windows L&F. These settings are not present by default, but
 576     // can be enabled using the TweakUI tool from Microsoft. For more info,
 577     // see http://msdn.microsoft.com/msdnmag/issues/1100/Registry/
 578 
 579     // NoPlacesBar is a REG_DWORD, with values 0 or 1
 580     value = getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32"),
 581                                   TEXT("NoPlacesBar"), &valueType);
 582     if (value != NULL) {
 583         if (valueType == REG_DWORD) {
 584             SetBooleanProperty(TEXT("win.comdlg.noPlacesBar"), (BOOL)((int)*value != 0));
 585         }
 586         free(value);
 587     }
 588 
 589     LPTSTR valueName = TEXT("PlaceN");
 590     LPTSTR valueNameBuf = (LPTSTR)safe_Malloc((lstrlen(valueName) + 1) * sizeof(TCHAR));
 591     lstrcpy(valueNameBuf, valueName);
 592 
 593     LPTSTR propKey = TEXT("win.comdlg.placesBarPlaceN");
 594     LPTSTR propKeyBuf = (LPTSTR)safe_Malloc((lstrlen(propKey) + 1) * sizeof(TCHAR));
 595     lstrcpy(propKeyBuf, propKey);
 596 
 597     int i = 0;
 598     do {
 599         valueNameBuf[5] = _T('0' + i++);
 600         propKeyBuf[25] = valueNameBuf[5];
 601 
 602         LPTSTR key = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar");
 603         if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) {
 604             if (valueType == REG_DWORD) {
 605                 // Value is a CSIDL
 606                 SetIntegerProperty(propKeyBuf, (int)*value);
 607             } else {
 608                 // Value is a path
 609                 SetStringProperty(propKeyBuf, value);
 610             }
 611             free(value);
 612         }
 613     } while (value != NULL);
 614 
 615     free(valueNameBuf);
 616     free(propKeyBuf);
 617 }
 618 
 619 void AwtDesktopProperties::GetSoundEvents() {
 620     /////
 621     SetSoundProperty(TEXT("win.sound.default"), TEXT(".Default"));
 622     SetSoundProperty(TEXT("win.sound.close"), TEXT("Close"));
 623     SetSoundProperty(TEXT("win.sound.maximize"), TEXT("Maximize"));
 624     SetSoundProperty(TEXT("win.sound.minimize"), TEXT("Minimize"));
 625     SetSoundProperty(TEXT("win.sound.menuCommand"), TEXT("MenuCommand"));
 626     SetSoundProperty(TEXT("win.sound.menuPopup"), TEXT("MenuPopup"));
 627     SetSoundProperty(TEXT("win.sound.open"), TEXT("Open"));
 628     SetSoundProperty(TEXT("win.sound.restoreDown"), TEXT("RestoreDown"));
 629     SetSoundProperty(TEXT("win.sound.restoreUp"), TEXT("RestoreUp"));
 630     /////
 631     SetSoundProperty(TEXT("win.sound.asterisk"), TEXT("SystemAsterisk"));
 632     SetSoundProperty(TEXT("win.sound.exclamation"), TEXT("SystemExclamation"));
 633     SetSoundProperty(TEXT("win.sound.exit"), TEXT("SystemExit"));
 634     SetSoundProperty(TEXT("win.sound.hand"), TEXT("SystemHand"));
 635     SetSoundProperty(TEXT("win.sound.question"), TEXT("SystemQuestion"));
 636     SetSoundProperty(TEXT("win.sound.start"), TEXT("SystemStart"));
 637 }
 638 
 639 BOOL AwtDesktopProperties::GetBooleanParameter(UINT spi) {
 640     BOOL        flag;
 641     SystemParametersInfo(spi, 0, &flag, 0);
 642     DASSERT(flag == TRUE || flag == FALSE); // should be simple boolean value
 643     return flag;
 644 }
 645 
 646 UINT AwtDesktopProperties::GetIntegerParameter(UINT spi) {
 647     UINT retValue;
 648     SystemParametersInfo(spi, 0, &retValue, 0);
 649     return retValue;
 650 }
 651 
 652 void AwtDesktopProperties::SetStringProperty(LPCTSTR propName, LPTSTR value) {
 653     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 654     GetEnv()->CallVoidMethod(self,
 655                              AwtDesktopProperties::setStringPropertyID,
 656                              key, JNU_NewStringPlatform(GetEnv(), value));
 657     GetEnv()->DeleteLocalRef(key);
 658 }
 659 
 660 void AwtDesktopProperties::SetIntegerProperty(LPCTSTR propName, int value) {
 661     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 662     GetEnv()->CallVoidMethod(self,
 663                              AwtDesktopProperties::setIntegerPropertyID,
 664                              key, (jint)value);
 665     GetEnv()->DeleteLocalRef(key);
 666 }
 667 
 668 void AwtDesktopProperties::SetBooleanProperty(LPCTSTR propName, BOOL value) {
 669     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 670     GetEnv()->CallVoidMethod(self,
 671                              AwtDesktopProperties::setBooleanPropertyID,
 672                              key, value ? JNI_TRUE : JNI_FALSE);
 673     GetEnv()->DeleteLocalRef(key);
 674 }
 675 
 676 void AwtDesktopProperties::SetColorProperty(LPCTSTR propName, DWORD value) {
 677     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 678     GetEnv()->CallVoidMethod(self,
 679                              AwtDesktopProperties::setColorPropertyID,
 680                              key, GetRValue(value), GetGValue(value),
 681                              GetBValue(value));
 682     GetEnv()->DeleteLocalRef(key);
 683 }
 684 
 685 void AwtDesktopProperties::SetFontProperty(HDC dc, int fontID,
 686                                            LPCTSTR propName) {
 687     HGDIOBJ font = GetStockObject(fontID);
 688     if (font != NULL && SelectObject(dc, font) != NULL) {
 689         int length = GetTextFace(dc, 0, NULL);
 690 
 691         if (length > 0) {
 692             LPTSTR face = new TCHAR[length];
 693 
 694             if (GetTextFace(dc, length, face) > 0) {
 695                 TEXTMETRIC metrics;
 696 
 697                 if (GetTextMetrics(dc, &metrics) > 0) {
 698                     jstring fontName = NULL;
 699                     if (!wcscmp(face, L"MS Shell Dlg")) {
 700                         // MS Shell Dlg is an indirect font name, find the
 701                         // real face name from the registry.
 702                         LPTSTR shellDialogFace = resolveShellDialogFont();
 703                         if (shellDialogFace != NULL) {
 704                             fontName = JNU_NewStringPlatform(GetEnv(),
 705                                                              shellDialogFace);
 706                             free(shellDialogFace);
 707                         }
 708                         else {
 709                             // Couldn't determine mapping for MS Shell Dlg,
 710                             // fall back to Microsoft Sans Serif
 711                             fontName = JNU_NewStringPlatform(GetEnv(),
 712                                                     L"Microsoft Sans Serif");
 713                         }
 714                     }
 715                     else {
 716                         fontName = JNU_NewStringPlatform(GetEnv(), face);
 717                     }
 718                     jint pointSize = metrics.tmHeight -
 719                                      metrics.tmInternalLeading;
 720                     jint style = java_awt_Font_PLAIN;
 721 
 722                     if (metrics.tmWeight >= FW_BOLD) {
 723                         style =  java_awt_Font_BOLD;
 724                     }
 725                     if (metrics.tmItalic ) {
 726                         style |= java_awt_Font_ITALIC;
 727                     }
 728 
 729                     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 730                     GetEnv()->CallVoidMethod(self,
 731                               AwtDesktopProperties::setFontPropertyID,
 732                               key, fontName, style, pointSize);
 733                     GetEnv()->DeleteLocalRef(fontName);
 734                     GetEnv()->DeleteLocalRef(key);
 735                 }
 736             }
 737             delete[] face;
 738         }
 739     }
 740 }
 741 
 742 void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & font) {
 743     jstring fontName;
 744     jint pointSize;
 745     jint style;
 746 
 747     fontName = JNU_NewStringPlatform(GetEnv(), font.lfFaceName);
 748 
 749 #if 0
 750     HDC         hdc;
 751     int         pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
 752     // convert font size specified in pixels to font size in points
 753     hdc = GetDC(NULL);
 754     pointSize = (-font.lfHeight)*72/pixelsPerInch;
 755     ReleaseDC(NULL, hdc);
 756 #endif
 757     // Java uses point sizes, but assumes 1 pixel = 1 point
 758     pointSize = -font.lfHeight;
 759 
 760     // convert Windows font style to Java style
 761     style = java_awt_Font_PLAIN;
 762     DTRACE_PRINTLN1("weight=%d", font.lfWeight);
 763     if ( font.lfWeight >= FW_BOLD ) {
 764         style =  java_awt_Font_BOLD;
 765     }
 766     if ( font.lfItalic ) {
 767         style |= java_awt_Font_ITALIC;
 768     }
 769 
 770     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 771     GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID,
 772                              key, fontName, style, pointSize);
 773 
 774     GetEnv()->DeleteLocalRef(fontName);
 775     GetEnv()->DeleteLocalRef(key);
 776 }
 777 
 778 void AwtDesktopProperties::SetSoundProperty(LPCTSTR propName, LPCTSTR winEventName) {
 779     jstring key = JNU_NewStringPlatform(GetEnv(), propName);
 780     jstring event = JNU_NewStringPlatform(GetEnv(), winEventName);
 781     GetEnv()->CallVoidMethod(self,
 782                              AwtDesktopProperties::setSoundPropertyID,
 783                              key, event);
 784 
 785     GetEnv()->DeleteLocalRef(key);
 786     GetEnv()->DeleteLocalRef(event);
 787 }
 788 
 789 void AwtDesktopProperties::PlayWindowsSound(LPCTSTR event) {
 790     // stop any currently playing sounds
 791     ::PlaySound(NULL, NULL, SND_PURGE);
 792     // play the sound for the given event name
 793     ::PlaySound(event, NULL, SND_ASYNC|SND_ALIAS|SND_NODEFAULT);
 794 }
 795 
 796 ///////////////////////////////////////////////////////////////////////////////////////////////////
 797 
 798 static AwtDesktopProperties * GetCppThis(JNIEnv *env, jobject self) {
 799     jlong longProps = env->GetLongField(self, AwtDesktopProperties::pDataID);
 800     AwtDesktopProperties * props =
 801         (AwtDesktopProperties *)jlong_to_ptr(longProps);
 802     DASSERT( !IsBadReadPtr(props, sizeof(*props)) );
 803     return props;
 804 }
 805 
 806 JNIEXPORT void JNICALL
 807 Java_sun_awt_windows_WDesktopProperties_initIDs(JNIEnv *env, jclass cls) {
 808     TRY;
 809 
 810     AwtDesktopProperties::pDataID = env->GetFieldID(cls, "pData", "J");
 811     DASSERT(AwtDesktopProperties::pDataID != 0);
 812 
 813     AwtDesktopProperties::setBooleanPropertyID = env->GetMethodID(cls, "setBooleanProperty", "(Ljava/lang/String;Z)V");
 814     DASSERT(AwtDesktopProperties::setBooleanPropertyID != 0);
 815 
 816     AwtDesktopProperties::setIntegerPropertyID = env->GetMethodID(cls, "setIntegerProperty", "(Ljava/lang/String;I)V");
 817     DASSERT(AwtDesktopProperties::setIntegerPropertyID != 0);
 818 
 819     AwtDesktopProperties::setStringPropertyID = env->GetMethodID(cls, "setStringProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
 820     DASSERT(AwtDesktopProperties::setStringPropertyID != 0);
 821 
 822     AwtDesktopProperties::setColorPropertyID = env->GetMethodID(cls, "setColorProperty", "(Ljava/lang/String;III)V");
 823     DASSERT(AwtDesktopProperties::setColorPropertyID != 0);
 824 
 825     AwtDesktopProperties::setFontPropertyID = env->GetMethodID(cls, "setFontProperty", "(Ljava/lang/String;Ljava/lang/String;II)V");
 826     DASSERT(AwtDesktopProperties::setFontPropertyID != 0);
 827 
 828     AwtDesktopProperties::setSoundPropertyID = env->GetMethodID(cls, "setSoundProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
 829     DASSERT(AwtDesktopProperties::setSoundPropertyID != 0);
 830 
 831     CATCH_BAD_ALLOC;
 832 }
 833 
 834 JNIEXPORT void JNICALL
 835 Java_sun_awt_windows_WDesktopProperties_init(JNIEnv *env, jobject self) {
 836     TRY;
 837 
 838     new AwtDesktopProperties(self);
 839 
 840     CATCH_BAD_ALLOC;
 841 }
 842 
 843 JNIEXPORT void JNICALL
 844 Java_sun_awt_windows_WDesktopProperties_getWindowsParameters(JNIEnv *env, jobject self) {
 845     TRY;
 846 
 847     GetCppThis(env, self)->GetWindowsParameters();
 848 
 849     CATCH_BAD_ALLOC;
 850 }
 851 
 852 JNIEXPORT void JNICALL
 853 Java_sun_awt_windows_WDesktopProperties_playWindowsSound(JNIEnv *env, jobject self, jstring event) {
 854     TRY;
 855 
 856     LPCTSTR winEventName;
 857     winEventName = JNU_GetStringPlatformChars(env, event, NULL);
 858     if ( winEventName == NULL ) {
 859         return;
 860     }
 861     GetCppThis(env, self)->PlayWindowsSound(winEventName);
 862     JNU_ReleaseStringPlatformChars(env, event, winEventName);
 863 
 864     CATCH_BAD_ALLOC;
 865 }