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