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