1 /* 2 * Copyright (c) 2003, 2017, 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 "sun_awt_windows_ThemeReader.h" 27 #include <string.h> 28 29 #include "awt.h" 30 #include "awt_Toolkit.h" 31 #include "awt_Object.h" 32 #include "awt_Component.h" 33 34 #include "math.h" 35 36 // Important note about VC6 and VC7 (or XP Platform SDK) ! 37 // 38 // These type definitions have been imported from UxTheme.h 39 // They have been imported instead of including them, because 40 // currently we don't require Platform SDK for building J2SE and 41 // VC6 includes do not have UxTheme.h. When we move to VC7 42 // we should remove these imports and just include 43 // 44 // Uncomment these when we start using VC 7 (or XP Platform SDK) 45 // 46 // #include <uxtheme.h> 47 // #incldue <tmschema.h> 48 49 50 // Remove everyting inside this ifdef when we start using VC 7 (or XP Platform SDK) 51 #ifndef _UXTHEME_H_ 52 typedef HANDLE HTHEME; // handle to a section of theme data for class 53 54 typedef enum { 55 TS_MIN, 56 TS_TRUE, 57 TS_DRAW 58 } THEME_SIZE; 59 60 61 // Remove these when we start using VC 7 (or XP Platform SDK) 62 typedef struct _MARGINS 63 { 64 int cxLeftWidth; // width of left border that retains its size 65 int cxRightWidth; // width of right border that retains its size 66 int cyTopHeight; // height of top border that retains its size 67 int cyBottomHeight; // height of bottom border that retains its size 68 } MARGINS, *PMARGINS; 69 70 #define TMT_TRANSPARENT 2201 71 #endif // _UXTHEME_H_ 72 73 #if defined(_MSC_VER) && _MSC_VER >= 1800 74 # define ROUND_TO_INT(num) ((int) round(num)) 75 #else 76 # define ROUND_TO_INT(num) ((int) floor((num) + 0.5)) 77 #endif 78 79 #define ALPHA_MASK 0xff000000 80 #define RED_MASK 0xff0000 81 #define GREEN_MASK 0xff00 82 #define BLUE_MASK 0xff 83 #define ALPHA_SHIFT 24 84 #define RED_SHIFT 16 85 #define GREEN_SHIFT 8 86 87 88 typedef HRESULT(__stdcall *PFNCLOSETHEMEDATA)(HTHEME hTheme); 89 90 typedef HRESULT(__stdcall *PFNDRAWTHEMEBACKGROUND)(HTHEME hTheme, HDC hdc, 91 int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect); 92 93 typedef HTHEME(__stdcall *PFNOPENTHEMEDATA)(HWND hwnd, LPCWSTR pszClassList); 94 95 typedef HRESULT (__stdcall *PFNDRAWTHEMETEXT)(HTHEME hTheme, HDC hdc, 96 int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, 97 DWORD dwTextFlags, DWORD dwTextFlags2, const RECT *pRect); 98 99 typedef HRESULT (__stdcall *PFNGETTHEMEBACKGROUNDCONTENTRECT)(HTHEME hTheme, 100 HDC hdc, int iPartId, int iStateId, const RECT *pBoundingRect, 101 RECT *pContentRect); 102 103 typedef HRESULT (__stdcall *PFNGETTHEMEMARGINS)(HTHEME hTheme, 104 OPTIONAL HDC hdc, int iPartId, int iStateId, int iPropId, 105 OPTIONAL RECT *prc, OUT MARGINS *pMargins); 106 107 typedef BOOL (__stdcall *PFNISTHEMEPARTDEFINED)(HTHEME hTheme, int iPartId, int iStateId); 108 109 typedef HRESULT (__stdcall *PFNGETTHEMEBOOL)(HTHEME hTheme, int iPartId, 110 int iStateId, int iPropId, BOOL *pfVal); 111 112 typedef BOOL (__stdcall *PFNGETTHEMESYSBOOL)(HTHEME hTheme, int iPropId); 113 114 typedef HRESULT (__stdcall *PFNGETTHEMECOLOR)(HTHEME hTheme, int iPartId, 115 int iStateId, int iPropId, COLORREF *pColor); 116 117 typedef HRESULT (__stdcall *PFNGETTHEMEENUMVALUE)(HTHEME hTheme, int iPartId, 118 int iStateId, int iPropId, int *val); 119 typedef HRESULT (__stdcall *PFNGETTHEMEINT)(HTHEME hTheme, int iPartId, 120 int iStateId, int iPropId, int *val); 121 typedef HRESULT (__stdcall *PFNGETTHEMEPARTSIZE)(HTHEME hTheme, HDC hdc, 122 int iPartId, int iStateId, RECT *prc, THEME_SIZE eSize, SIZE *size); 123 124 typedef HRESULT (__stdcall *PFNGETTHEMEPOSITION)(HTHEME hTheme, int iPartId, 125 int iStateId, int propID, POINT *point); 126 127 typedef HRESULT(__stdcall *PFNSETWINDOWTHEME)(HWND hwnd, LPCWSTR pszSubAppName, 128 LPCWSTR pszSubIdList); 129 130 typedef HRESULT (__stdcall *PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT) 131 (HTHEME hTheme, int iPartId, int iStateId); 132 133 typedef HRESULT (__stdcall *PFNGETTHEMETRANSITIONDURATION) 134 (HTHEME hTheme, int iPartId, int iStateIdFrom, int iStateIdTo, 135 int iPropId, DWORD *pdwDuration); 136 137 static PFNOPENTHEMEDATA OpenThemeData = NULL; 138 static PFNDRAWTHEMEBACKGROUND DrawThemeBackground = NULL; 139 static PFNCLOSETHEMEDATA CloseThemeData = NULL; 140 static PFNDRAWTHEMETEXT DrawThemeText = NULL; 141 static PFNGETTHEMEBACKGROUNDCONTENTRECT GetThemeBackgroundContentRect = NULL; 142 static PFNGETTHEMEMARGINS GetThemeMargins = NULL; 143 static PFNISTHEMEPARTDEFINED IsThemePartDefined = NULL; 144 static PFNGETTHEMEBOOL GetThemeBool=NULL; 145 static PFNGETTHEMESYSBOOL GetThemeSysBool=NULL; 146 static PFNGETTHEMECOLOR GetThemeColor=NULL; 147 static PFNGETTHEMEENUMVALUE GetThemeEnumValue = NULL; 148 static PFNGETTHEMEINT GetThemeInt = NULL; 149 static PFNGETTHEMEPARTSIZE GetThemePartSize = NULL; 150 static PFNGETTHEMEPOSITION GetThemePosition = NULL; 151 static PFNSETWINDOWTHEME SetWindowTheme = NULL; 152 static PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT 153 IsThemeBackgroundPartiallyTransparent = NULL; 154 //this function might not exist on Windows XP 155 static PFNGETTHEMETRANSITIONDURATION GetThemeTransitionDuration = NULL; 156 157 158 BOOL InitThemes() { 159 static HMODULE hModThemes = NULL; 160 hModThemes = JDK_LoadSystemLibrary("UXTHEME.DLL"); 161 DTRACE_PRINTLN1("InitThemes hModThemes = %x\n", hModThemes); 162 if(hModThemes) { 163 DTRACE_PRINTLN("Loaded UxTheme.dll\n"); 164 OpenThemeData = (PFNOPENTHEMEDATA)GetProcAddress(hModThemes, 165 "OpenThemeData"); 166 DrawThemeBackground = (PFNDRAWTHEMEBACKGROUND)GetProcAddress( 167 hModThemes, "DrawThemeBackground"); 168 CloseThemeData = (PFNCLOSETHEMEDATA)GetProcAddress( 169 hModThemes, "CloseThemeData"); 170 DrawThemeText = (PFNDRAWTHEMETEXT)GetProcAddress( 171 hModThemes, "DrawThemeText"); 172 GetThemeBackgroundContentRect = (PFNGETTHEMEBACKGROUNDCONTENTRECT) 173 GetProcAddress(hModThemes, "GetThemeBackgroundContentRect"); 174 GetThemeMargins = (PFNGETTHEMEMARGINS)GetProcAddress( 175 hModThemes, "GetThemeMargins"); 176 IsThemePartDefined = (PFNISTHEMEPARTDEFINED)GetProcAddress( 177 hModThemes, "IsThemePartDefined"); 178 GetThemeBool = (PFNGETTHEMEBOOL)GetProcAddress( 179 hModThemes, "GetThemeBool"); 180 GetThemeSysBool = (PFNGETTHEMESYSBOOL)GetProcAddress(hModThemes, 181 "GetThemeSysBool"); 182 GetThemeColor = (PFNGETTHEMECOLOR)GetProcAddress(hModThemes, 183 "GetThemeColor"); 184 GetThemeEnumValue = (PFNGETTHEMEENUMVALUE)GetProcAddress(hModThemes, 185 "GetThemeEnumValue"); 186 GetThemeInt = (PFNGETTHEMEINT)GetProcAddress(hModThemes, "GetThemeInt"); 187 GetThemePosition = (PFNGETTHEMEPOSITION)GetProcAddress(hModThemes, 188 "GetThemePosition"); 189 GetThemePartSize = (PFNGETTHEMEPARTSIZE)GetProcAddress(hModThemes, 190 "GetThemePartSize"); 191 SetWindowTheme = (PFNSETWINDOWTHEME)GetProcAddress(hModThemes, 192 "SetWindowTheme"); 193 IsThemeBackgroundPartiallyTransparent = 194 (PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT)GetProcAddress(hModThemes, 195 "IsThemeBackgroundPartiallyTransparent"); 196 //this function might not exist 197 GetThemeTransitionDuration = 198 (PFNGETTHEMETRANSITIONDURATION)GetProcAddress(hModThemes, 199 "GetThemeTransitionDuration"); 200 201 if(OpenThemeData 202 && DrawThemeBackground 203 && CloseThemeData 204 && DrawThemeText 205 && GetThemeBackgroundContentRect 206 && GetThemeMargins 207 && IsThemePartDefined 208 && GetThemeBool 209 && GetThemeSysBool 210 && GetThemeColor 211 && GetThemeEnumValue 212 && GetThemeInt 213 && GetThemePartSize 214 && GetThemePosition 215 && SetWindowTheme 216 && IsThemeBackgroundPartiallyTransparent 217 ) { 218 DTRACE_PRINTLN("Loaded function pointers.\n"); 219 // We need to make sure we can load the Theme. This may not be 220 // the case on a WinXP machine with classic mode enabled. 221 HTHEME hTheme = OpenThemeData(AwtToolkit::GetInstance().GetHWnd(), L"Button"); 222 if(hTheme) { 223 DTRACE_PRINTLN("Loaded Theme data.\n"); 224 CloseThemeData(hTheme); 225 return TRUE; 226 } 227 } else { 228 FreeLibrary(hModThemes); 229 hModThemes = NULL; 230 } 231 } 232 return FALSE; 233 } 234 235 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_initThemes 236 (JNIEnv *env, jclass klass) { 237 static BOOL TryLoadingThemeLib = FALSE; 238 static BOOL Themed = FALSE; 239 if (!TryLoadingThemeLib) { 240 Themed = InitThemes(); 241 TryLoadingThemeLib = TRUE; 242 } 243 return JNI_IS_TRUE(Themed); 244 } 245 246 247 248 static void assert_result(HRESULT hres, JNIEnv *env) { 249 #ifdef _DEBUG 250 if (hres != 0) { 251 DWORD lastError = GetLastError(); 252 if (lastError != 0) { 253 LPSTR msgBuffer = NULL; 254 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | 255 FORMAT_MESSAGE_FROM_SYSTEM | 256 FORMAT_MESSAGE_IGNORE_INSERTS, 257 NULL, 258 lastError, 259 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 260 (LPSTR)&msgBuffer, 261 // it's an output parameter when allocate buffer is used 262 0, 263 NULL); 264 DTRACE_PRINTLN3("Error: hres=0x%x lastError=0x%x %s\n", hres, 265 lastError, msgBuffer); 266 } 267 } 268 #endif 269 } 270 271 272 /* 273 * Class: sun_awt_windows_ThemeReader 274 * Method: openTheme 275 * Signature: (Ljava/lang/String;)J 276 */ 277 JNIEXPORT jlong JNICALL Java_sun_awt_windows_ThemeReader_openTheme 278 (JNIEnv *env, jclass klass, jstring widget) { 279 280 LPCTSTR str = (LPCTSTR) JNU_GetStringPlatformChars(env, widget, NULL); 281 if (str == NULL) { 282 JNU_ThrowOutOfMemoryError(env, 0); 283 return 0; 284 } 285 // We need to open the Theme on a Window that will stick around. 286 // The best one for that purpose is the Toolkit window. 287 HTHEME htheme = OpenThemeData(AwtToolkit::GetInstance().GetHWnd(), str); 288 JNU_ReleaseStringPlatformChars(env, widget, str); 289 return (jlong) htheme; 290 } 291 292 /* 293 * Class: sun_awt_windows_ThemeReader 294 * Method: setWindowTheme 295 * Signature: (Ljava/lang/String;)V 296 */ 297 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_setWindowTheme 298 (JNIEnv *env, jclass klass, jstring subAppName) { 299 300 LPCTSTR str = NULL; 301 if (subAppName != NULL) { 302 str = (LPCTSTR) JNU_GetStringPlatformChars(env, subAppName, NULL); 303 } 304 // We need to set the Window theme on the same theme that we opened it with. 305 HRESULT hres = SetWindowTheme(AwtToolkit::GetInstance().GetHWnd(), str, NULL); 306 assert_result(hres, env); 307 if (subAppName != NULL) { 308 JNU_ReleaseStringPlatformChars(env, subAppName, str); 309 } 310 } 311 312 /* 313 * Class: sun_awt_windows_ThemeReader 314 * Method: closeTheme 315 * Signature: (J)V 316 */ 317 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_closeTheme 318 (JNIEnv *env, jclass klass, jlong theme) { 319 320 HRESULT hres = CloseThemeData((HTHEME)theme); 321 assert_result(hres, env); 322 } 323 324 static void copyDIBToBufferedImage(int *pDstBits, int *pSrcBits, 325 BOOL transparent, int w, int h, int stride) { 326 327 int offsetToNextLine = stride - w; 328 int *dst = pDstBits; 329 int *src = pSrcBits; 330 double alphaScale; 331 int r,g,b,a; 332 int pixel; 333 334 BOOL translucent = FALSE; 335 336 for (int i=0;i<h;i++) { 337 for (int j=0;j<w;j++) { 338 pixel = *src++; 339 a = (pixel & ALPHA_MASK) >> ALPHA_SHIFT; 340 if ((a != 0) && (a != 255)) { 341 translucent = TRUE; 342 break; 343 } 344 } 345 if (translucent) break; 346 } 347 src = pSrcBits; 348 349 if (translucent) { 350 for (int i=0;i<h;i++) { 351 for (int j=0;j<w;j++) { 352 pixel = *src++; 353 if (pixel != 0) { 354 // The UxTheme API seems to do the blending and 355 // premultiply the resulting values. 356 // so we have to divide by the alpha to get the 357 // original component values. 358 a = (pixel & ALPHA_MASK) >> ALPHA_SHIFT; 359 if ((a != 255) && (a != 0)) { 360 r = (pixel & RED_MASK) >> RED_SHIFT; 361 g = (pixel & GREEN_MASK) >> GREEN_SHIFT; 362 b = (pixel & BLUE_MASK); 363 alphaScale = 255.0 / a; 364 r = (int) ((double) r * alphaScale); 365 if (r > 255) r = 255; 366 g = (int) ((double) g * alphaScale); 367 if (g > 255) g = 255; 368 b = (int) ((double) b * alphaScale); 369 if (b > 255) b = 255; 370 pixel = (a << ALPHA_SHIFT) | (r << RED_SHIFT) | 371 (g << GREEN_SHIFT) | b ; 372 } 373 else { 374 // Frame maximize and minimize buttons 375 // have transparent pixels with alpha 376 // set to FF and nontransparent pixels have zero alpha. 377 pixel |= 0xFF000000; 378 } 379 } 380 *dst++ = pixel; 381 } 382 dst += offsetToNextLine; 383 } 384 } 385 else if (transparent) { 386 for (int i=0;i<h;i++) { 387 for (int j=0;j<w;j++) { 388 pixel = *src++; 389 if (pixel == 0) { 390 *dst++ = 0; 391 } 392 else { 393 *dst++ = 0xFF000000 | pixel; 394 } 395 } 396 dst += offsetToNextLine; 397 } 398 } 399 else { 400 for (int i=0;i<h;i++) { 401 for (int j=0;j<w;j++) { 402 pixel = *src++; 403 *dst++ = 0xFF000000 | pixel; 404 } 405 dst += offsetToNextLine; 406 } 407 } 408 409 } 410 411 412 413 /* 414 * Class: sun_awt_windows_ThemeReader 415 * Method: paintBackground 416 * Signature: ([IJIIIIIII)V 417 */ 418 JNIEXPORT void JNICALL Java_sun_awt_windows_ThemeReader_paintBackground 419 (JNIEnv *env, jclass klass, jintArray array, jlong theme, jint part, jint state, 420 jint x, jint y, jint w, jint h, jint stride) { 421 422 int *pDstBits=NULL; 423 int *pSrcBits=NULL; 424 HDC memDC,defaultDC; 425 HBITMAP hDibSection = NULL; 426 RECT rect; 427 BITMAPINFO bmi; 428 HTHEME hTheme = (HTHEME) theme; 429 430 DTRACE_PRINTLN3("Java_sun_awt_windows_ThemeReader_paintButtonBackground w=%d h=%d\n stride=%d\n",w,h,stride); 431 432 if (hTheme == NULL) { 433 JNU_ThrowInternalError(env, "HTHEME is null"); 434 return; 435 } 436 437 defaultDC = GetDC(NULL); 438 439 memDC = CreateCompatibleDC(defaultDC); 440 441 static const int BITS_PER_PIXEL = 32; 442 443 ZeroMemory(&bmi,sizeof(BITMAPINFO)); 444 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 445 bmi.bmiHeader.biWidth = w; 446 bmi.bmiHeader.biHeight = -h; 447 bmi.bmiHeader.biPlanes = 1; 448 bmi.bmiHeader.biBitCount = BITS_PER_PIXEL; 449 bmi.bmiHeader.biCompression = BI_RGB; 450 bmi.bmiHeader.biSizeImage = w * h * (BITS_PER_PIXEL>>3); 451 452 453 hDibSection = ::CreateDIBSection(memDC, (BITMAPINFO*) &bmi, 454 DIB_RGB_COLORS, (void **) &pSrcBits, 455 NULL, 0); 456 if (hDibSection == NULL) { 457 DTRACE_PRINTLN("Error creating DIB section"); 458 ReleaseDC(NULL,defaultDC); 459 return; 460 } 461 462 SelectObject(memDC,hDibSection); 463 464 rect.left = 0; 465 rect.top = 0; 466 rect.bottom = h; 467 rect.right = w; 468 469 ZeroMemory(pSrcBits,(BITS_PER_PIXEL>>3)*w*h); 470 471 HRESULT hres = DrawThemeBackground(hTheme, memDC, part, state, &rect, NULL); 472 assert_result(hres, env); 473 if (SUCCEEDED(hres)) { 474 // Make sure GDI is done. 475 GdiFlush(); 476 // Copy the resulting pixels to our Java BufferedImage. 477 pDstBits = (int *)env->GetPrimitiveArrayCritical(array, 0); 478 BOOL transparent = FALSE; 479 transparent = IsThemeBackgroundPartiallyTransparent(hTheme,part,state); 480 copyDIBToBufferedImage(pDstBits, pSrcBits, transparent, w, h, stride); 481 env->ReleasePrimitiveArrayCritical(array, pDstBits, 0); 482 } 483 484 // Delete resources. 485 DeleteObject(hDibSection); 486 DeleteDC(memDC); 487 ReleaseDC(NULL,defaultDC); 488 } 489 490 jobject newInsets(JNIEnv *env, jint top, jint left, jint bottom, jint right) { 491 if (env->EnsureLocalCapacity(2) < 0) { 492 return NULL; 493 } 494 495 static jclass insetsClassID = NULL; 496 497 if (insetsClassID == NULL) { 498 jclass insetsClassIDLocal = env->FindClass("java/awt/Insets"); 499 CHECK_NULL_RETURN(insetsClassIDLocal, NULL); 500 insetsClassID = (jclass)env->NewGlobalRef(insetsClassIDLocal); 501 env->DeleteLocalRef(insetsClassIDLocal); 502 } 503 504 jobject insets = env->NewObject(insetsClassID, 505 AwtToolkit::insetsMID, 506 top, left, bottom, right); 507 508 if (safe_ExceptionOccurred(env)) { 509 env->ExceptionDescribe(); 510 env->ExceptionClear(); 511 } 512 513 return insets; 514 } 515 516 /* 517 * Class: sun_awt_windows_ThemeReader 518 * Method: getThemeMargins 519 * Signature: (JIII)Ljava/awt/Insets; 520 */ 521 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getThemeMargins 522 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint property) { 523 MARGINS margins; 524 HTHEME hTheme = (HTHEME) theme; 525 526 if (hTheme != NULL) { 527 HRESULT hres = GetThemeMargins(hTheme, NULL, part, state, property, NULL, &margins); 528 assert_result(hres, env); 529 if (FAILED(hres)) { 530 return NULL; 531 } 532 533 return newInsets(env, 534 margins.cyTopHeight, 535 margins.cxLeftWidth, margins.cyBottomHeight, margins.cxRightWidth); 536 } 537 return NULL; 538 } 539 540 /* 541 * Class: sun_awt_windows_ThemeReader 542 * Method: isThemePartDefined 543 * Signature: (JII)Z 544 */ 545 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_isThemePartDefined 546 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state) { 547 HTHEME hTheme = (HTHEME) theme; 548 return JNI_IS_TRUE(IsThemePartDefined(hTheme, part, state)); 549 } 550 551 /* 552 * Class: sun_awt_windows_ThemeReader 553 * Method: getColor 554 * Signature: (JIII)Ljava/awt/Color; 555 */ 556 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getColor 557 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint type) { 558 559 HTHEME hTheme = (HTHEME) theme; 560 561 if (hTheme != NULL) { 562 COLORREF color=0; 563 564 if (GetThemeColor(hTheme, part, state, type, &color) != S_OK) { 565 return NULL; 566 } 567 568 if (env->EnsureLocalCapacity(1) < 0) { 569 return NULL; 570 } 571 572 static jmethodID colorMID = NULL; 573 static jclass colorClassID = NULL; 574 575 if (colorClassID == NULL) { 576 jclass colorClassIDLocal = env->FindClass("java/awt/Color"); 577 CHECK_NULL_RETURN(colorClassIDLocal, NULL); 578 colorClassID = (jclass)env->NewGlobalRef(colorClassIDLocal); 579 env->DeleteLocalRef(colorClassIDLocal); 580 } 581 582 if (colorMID == NULL) { 583 colorMID = env->GetMethodID(colorClassID, "<init>", "(III)V"); 584 CHECK_NULL_RETURN(colorMID, NULL); 585 } 586 jobject colorObj = env->NewObject(colorClassID, 587 colorMID, GetRValue(color), GetGValue(color),GetBValue(color)); 588 589 if (safe_ExceptionOccurred(env)) { 590 env->ExceptionDescribe(); 591 env->ExceptionClear(); 592 } 593 594 return colorObj; 595 } 596 return NULL; 597 } 598 599 /* 600 * Class: sun_awt_windows_ThemeReader 601 * Method: getInt 602 * Signature: (JIII)I 603 */ 604 JNIEXPORT jint JNICALL Java_sun_awt_windows_ThemeReader_getInt 605 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) { 606 607 HTHEME hTheme = (HTHEME) theme; 608 int retVal = -1; 609 if (hTheme != NULL) { 610 HRESULT hres = GetThemeInt(hTheme, part, state, prop, &retVal); 611 assert_result(hres, env); 612 } 613 return retVal; 614 } 615 616 /* 617 * Class: sun_awt_windows_ThemeReader 618 * Method: getEnum 619 * Signature: (JIII)I 620 */ 621 JNIEXPORT jint JNICALL Java_sun_awt_windows_ThemeReader_getEnum 622 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) { 623 HTHEME hTheme = (HTHEME) theme; 624 int retVal = -1; 625 if (hTheme != NULL) { 626 HRESULT hres = GetThemeEnumValue(hTheme, part, state, prop, &retVal); 627 assert_result(hres, env); 628 } 629 return retVal; 630 } 631 632 /* 633 * Class: sun_awt_windows_ThemeReader 634 * Method: getBoolean 635 * Signature: (JIII)Z 636 */ 637 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_getBoolean 638 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) { 639 HTHEME hTheme = (HTHEME) theme; 640 BOOL retVal = FALSE; 641 if (hTheme != NULL) { 642 HRESULT hres = GetThemeBool(hTheme, part, state, prop, &retVal); 643 assert_result(hres, env); 644 } 645 return JNI_IS_TRUE(retVal); 646 } 647 648 /* 649 * Class: sun_awt_windows_ThemeReader 650 * Method: getSysBoolean 651 * Signature: (JI)Z 652 */ 653 JNIEXPORT jboolean JNICALL Java_sun_awt_windows_ThemeReader_getSysBoolean 654 (JNIEnv *env, jclass klass, jlong theme, jint prop) { 655 HTHEME hTheme = (HTHEME)theme; 656 if (hTheme != NULL) { 657 return JNI_IS_TRUE(GetThemeSysBool(hTheme, prop)); 658 } 659 return JNI_FALSE; 660 } 661 662 /* 663 * Class: sun_awt_windows_ThemeReader 664 * Method: getPoint 665 * Signature: (JIII)Ljava/awt/Point; 666 */ 667 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPoint 668 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) { 669 HTHEME hTheme = (HTHEME) theme; 670 POINT point; 671 672 if (hTheme != NULL) { 673 if (GetThemePosition(hTheme, part, state, prop, &point) != S_OK) { 674 return NULL; 675 } 676 677 if (env->EnsureLocalCapacity(2) < 0) { 678 return NULL; 679 } 680 681 static jmethodID pointMID = NULL; 682 static jclass pointClassID = NULL; 683 684 if (pointClassID == NULL) { 685 jclass pointClassIDLocal = env->FindClass("java/awt/Point"); 686 CHECK_NULL_RETURN(pointClassIDLocal, NULL); 687 pointClassID = (jclass)env->NewGlobalRef(pointClassIDLocal); 688 env->DeleteLocalRef(pointClassIDLocal); 689 } 690 691 if (pointMID == NULL) { 692 pointMID = env->GetMethodID(pointClassID, "<init>", "(II)V"); 693 CHECK_NULL_RETURN(pointMID, NULL); 694 } 695 jobject pointObj = env->NewObject(pointClassID, pointMID, point.x, point.y); 696 697 if (safe_ExceptionOccurred(env)) { 698 env->ExceptionDescribe(); 699 env->ExceptionClear(); 700 } 701 702 return pointObj; 703 } 704 return NULL; 705 } 706 707 /* 708 * Class: sun_awt_windows_ThemeReader 709 * Method: getPosition 710 * Signature: (JIII)Ljava/awt/Dimension; 711 */ 712 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPosition 713 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state, jint prop) { 714 715 HTHEME hTheme = (HTHEME) theme; 716 if (hTheme != NULL) { 717 718 POINT point; 719 720 HRESULT hres = GetThemePosition(hTheme, part, state, prop, &point); 721 assert_result(hres, env); 722 if (FAILED(hres)) { 723 return NULL; 724 } 725 726 727 if (env->EnsureLocalCapacity(2) < 0) { 728 return NULL; 729 } 730 731 static jmethodID dimMID = NULL; 732 static jclass dimClassID = NULL; 733 if (dimClassID == NULL) { 734 jclass dimClassIDLocal = env->FindClass("java/awt/Dimension"); 735 CHECK_NULL_RETURN(dimClassIDLocal, NULL); 736 dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal); 737 env->DeleteLocalRef(dimClassIDLocal); 738 } 739 if (dimMID == NULL) { 740 dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V"); 741 CHECK_NULL_RETURN(dimMID, NULL); 742 } 743 jobject dimObj = env->NewObject(dimClassID, dimMID, point.x, point.y); 744 745 if (safe_ExceptionOccurred(env)) { 746 env->ExceptionDescribe(); 747 env->ExceptionClear(); 748 } 749 750 return dimObj; 751 } 752 return NULL; 753 } 754 755 void rescale(SIZE *size) { 756 static int dpiX = -1; 757 static int dpiY = -1; 758 if (dpiX == -1 || dpiY == -1) { 759 HWND hWnd = ::GetDesktopWindow(); 760 HDC hDC = ::GetDC(hWnd); 761 dpiX = ::GetDeviceCaps(hDC, LOGPIXELSX); 762 dpiY = ::GetDeviceCaps(hDC, LOGPIXELSY); 763 ::ReleaseDC(hWnd, hDC); 764 } 765 766 if (dpiX !=0 && dpiX != 96) { 767 float invScaleX = 96.0f / dpiX; 768 size->cx = ROUND_TO_INT(size->cx * invScaleX); 769 } 770 if (dpiY != 0 && dpiY != 96) { 771 float invScaleY = 96.0f / dpiY; 772 size->cy = ROUND_TO_INT(size->cy * invScaleY); 773 } 774 } 775 776 /* 777 * Class: sun_awt_windows_ThemeReader 778 * Method: getPartSize 779 * Signature: (JII)Ljava/awt/Dimension; 780 */ 781 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getPartSize 782 (JNIEnv *env, jclass klass, jlong theme, jint part, jint state) { 783 if (theme != NULL) { 784 SIZE size; 785 786 if (SUCCEEDED(GetThemePartSize((HTHEME)theme, NULL, part, state, 787 NULL, TS_TRUE, &size)) && (env->EnsureLocalCapacity(2) >= 0)) { 788 789 static jmethodID dimMID = NULL; 790 static jclass dimClassID = NULL; 791 if (dimClassID == NULL) { 792 jclass dimClassIDLocal = env->FindClass("java/awt/Dimension"); 793 CHECK_NULL_RETURN(dimClassIDLocal, NULL); 794 dimClassID = (jclass)env->NewGlobalRef(dimClassIDLocal); 795 env->DeleteLocalRef(dimClassIDLocal); 796 } 797 if (dimMID == NULL) { 798 dimMID = env->GetMethodID(dimClassID, "<init>", "(II)V"); 799 CHECK_NULL_RETURN(dimMID, NULL); 800 } 801 802 rescale(&size); 803 jobject dimObj = env->NewObject(dimClassID, dimMID, size.cx, size.cy); 804 if (safe_ExceptionOccurred(env)) { 805 env->ExceptionDescribe(); 806 env->ExceptionClear(); 807 } 808 809 return dimObj; 810 } 811 } 812 return NULL; 813 } 814 815 /* 816 * Class: sun_awt_windows_ThemeReader 817 * Method: getThemeBackgroundContentMargins 818 * Signature: (JIIII)Ljava/awt/Insets; 819 */ 820 JNIEXPORT jobject JNICALL Java_sun_awt_windows_ThemeReader_getThemeBackgroundContentMargins 821 (JNIEnv *env, jclass klass, jlong hTheme, jint part, jint state, 822 jint boundingWidth, jint boundingHeight) { 823 if (hTheme != NULL) { 824 RECT boundingRect; 825 boundingRect.left = 0; 826 boundingRect.top = 0; 827 boundingRect.right = boundingWidth; 828 boundingRect.bottom = boundingHeight; 829 RECT contentRect; 830 if (SUCCEEDED(GetThemeBackgroundContentRect((HTHEME) hTheme, NULL, part, 831 state, &boundingRect, 832 &contentRect))) { 833 return newInsets(env, 834 contentRect.top, contentRect.left, 835 boundingHeight - contentRect.bottom, 836 boundingWidth - contentRect.right); 837 } 838 } 839 return NULL; 840 } 841 842 /* 843 * Class: sun_awt_windows_ThemeReader 844 * Method: getThemeTransitionDuration 845 * Signature: (JIIII)J 846 */ 847 JNIEXPORT jlong JNICALL 848 Java_sun_awt_windows_ThemeReader_getThemeTransitionDuration 849 (JNIEnv *env, jclass klass, jlong theme, jint part, jint stateFrom, 850 jint stateTo, jint propId) { 851 jlong rv = -1; 852 if (GetThemeTransitionDuration != NULL) { 853 DWORD duration = 0; 854 if (SUCCEEDED(GetThemeTransitionDuration((HTHEME) theme, part, 855 stateFrom, stateTo, propId, &duration))) { 856 rv = duration; 857 } 858 } 859 return rv; 860 } 861 862 /* 863 * Class: sun_awt_windows_ThemeReader 864 * Method: isGetThemeTransitionDurationDefined 865 * Signature: ()Z 866 */ 867 JNIEXPORT jboolean JNICALL 868 Java_sun_awt_windows_ThemeReader_isGetThemeTransitionDurationDefined 869 (JNIEnv *env, jclass klass) { 870 return (GetThemeTransitionDuration != NULL) ? JNI_TRUE : JNI_FALSE; 871 }