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