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