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