1 /*
2 * Copyright (c) 1999, 2011, 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 <sun_awt_Win32GraphicsEnvironment.h>
28 #include <sun_awt_Win32FontManager.h>
29 #include "awt_Canvas.h"
30 #include "awt_Win32GraphicsDevice.h"
31 #include "Devices.h"
32 #include "WindowsFlags.h"
33 #include "DllUtil.h"
34
35 BOOL DWMIsCompositionEnabled();
36
initScreens(JNIEnv * env)37 void initScreens(JNIEnv *env) {
38
39 if (!Devices::UpdateInstance(env)) {
40 JNU_ThrowInternalError(env, "Could not update the devices array.");
41 return;
42 }
43 }
44
45 /**
46 * This function attempts to make a Win32 API call to
47 * BOOL SetProcessDPIAware(VOID);
48 * which is only present on Windows Vista, and which instructs the
49 * Vista Windows Display Manager that this application is High DPI Aware
50 * and does not need to be scaled by the WDM and lied about the
51 * actual system dpi.
52 */
53 static void
SetProcessDPIAwareProperty()54 SetProcessDPIAwareProperty()
55 {
56 typedef BOOL (WINAPI SetProcessDPIAwareFunc)(void);
57 static BOOL bAlreadySet = FALSE;
58
59 // setHighDPIAware is set in WindowsFlags.cpp
60 if (!setHighDPIAware || bAlreadySet) {
61 return;
62 }
63
64 bAlreadySet = TRUE;
65
66 HMODULE hLibUser32Dll = JDK_LoadSystemLibrary("user32.dll");
67
68 if (hLibUser32Dll != NULL) {
69 SetProcessDPIAwareFunc *lpSetProcessDPIAware =
70 (SetProcessDPIAwareFunc*)GetProcAddress(hLibUser32Dll,
71 "SetProcessDPIAware");
72 if (lpSetProcessDPIAware != NULL) {
73 lpSetProcessDPIAware();
74 }
75 ::FreeLibrary(hLibUser32Dll);
76 }
77 }
78
79 #define DWM_COMP_UNDEFINED (~(TRUE|FALSE))
80 static int dwmIsCompositionEnabled = DWM_COMP_UNDEFINED;
81
82 /**
83 * This function is called from toolkit event handling code when
84 * WM_DWMCOMPOSITIONCHANGED event is received
85 */
DWMResetCompositionEnabled()86 void DWMResetCompositionEnabled() {
87 dwmIsCompositionEnabled = DWM_COMP_UNDEFINED;
88 (void)DWMIsCompositionEnabled();
89 }
90
91 /**
92 * Returns true if dwm composition is enabled, false if it is not applicable
93 * (if the OS is not Vista) or dwm composition is disabled.
94 */
DWMIsCompositionEnabled()95 BOOL DWMIsCompositionEnabled() {
96 // cheaper to check than whether it's vista or not
97 if (dwmIsCompositionEnabled != DWM_COMP_UNDEFINED) {
98 return (BOOL)dwmIsCompositionEnabled;
99 }
100
101 if (!IS_WINVISTA) {
102 dwmIsCompositionEnabled = FALSE;
103 return FALSE;
104 }
105
106 BOOL bRes = FALSE;
107
108 try {
109 BOOL bEnabled;
110 HRESULT res = DwmAPI::DwmIsCompositionEnabled(&bEnabled);
111 if (SUCCEEDED(res)) {
112 bRes = bEnabled;
113 J2dTraceLn1(J2D_TRACE_VERBOSE, " composition enabled: %d",bRes);
114 } else {
115 J2dTraceLn1(J2D_TRACE_ERROR,
116 "IsDWMCompositionEnabled: error %x when detecting"\
117 "if composition is enabled", res);
118 }
119 } catch (const DllUtil::Exception &) {
120 J2dTraceLn(J2D_TRACE_ERROR,
121 "IsDWMCompositionEnabled: no DwmIsCompositionEnabled() "\
122 "in dwmapi.dll or dwmapi.dll cannot be loaded");
123 }
124
125 dwmIsCompositionEnabled = bRes;
126
127 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
128 JNU_CallStaticMethodByName(env, NULL,
129 "sun/awt/Win32GraphicsEnvironment",
130 "dwmCompositionChanged", "(Z)V", (jboolean)bRes);
131 return bRes;
132 }
133
134 /*
135 * Class: sun_awt_Win32GraphicsEnvironment
136 * Method: initDisplay
137 * Signature: ()V
138 */
139 JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsEnvironment_initDisplay(JNIEnv * env,jclass thisClass)140 Java_sun_awt_Win32GraphicsEnvironment_initDisplay(JNIEnv *env,
141 jclass thisClass)
142 {
143 // This method needs to be called prior to any display-related activity
144 SetProcessDPIAwareProperty();
145
146 DWMIsCompositionEnabled();
147
148 initScreens(env);
149 }
150
151 /*
152 * Class: sun_awt_Win32GraphicsEnvironment
153 * Method: getNumScreens
154 * Signature: ()I
155 */
156 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getNumScreens(JNIEnv * env,jobject thisobj)157 Java_sun_awt_Win32GraphicsEnvironment_getNumScreens(JNIEnv *env,
158 jobject thisobj)
159 {
160 Devices::InstanceAccess devices;
161 return devices->GetNumDevices();
162 }
163
164 /*
165 * Class: sun_awt_Win32GraphicsEnvironment
166 * Method: getDefaultScreen
167 * Signature: ()I
168 */
169 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getDefaultScreen(JNIEnv * env,jobject thisobj)170 Java_sun_awt_Win32GraphicsEnvironment_getDefaultScreen(JNIEnv *env,
171 jobject thisobj)
172 {
173 return AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
174 }
175
176 /*
177 * Class: sun_awt_Win32FontManager
178 * Method: registerFontWithPlatform
179 * Signature: (Ljava/lang/String;)V
180 */
181 JNIEXPORT void JNICALL
Java_sun_awt_Win32FontManager_registerFontWithPlatform(JNIEnv * env,jclass cl,jstring fontName)182 Java_sun_awt_Win32FontManager_registerFontWithPlatform(JNIEnv *env,
183 jclass cl,
184 jstring fontName)
185 {
186 LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE);
187 if (file) {
188 ::AddFontResourceEx(file, FR_PRIVATE, NULL);
189 JNU_ReleaseStringPlatformChars(env, fontName, file);
190 }
191 }
192
193
194 /*
195 * Class: sun_awt_Win32FontManagerEnvironment
196 * Method: deRegisterFontWithPlatform
197 * Signature: (Ljava/lang/String;)V
198 *
199 * This method intended for future use.
200 */
201 JNIEXPORT void JNICALL
Java_sun_awt_Win32FontManager_deRegisterFontWithPlatform(JNIEnv * env,jclass cl,jstring fontName)202 Java_sun_awt_Win32FontManager_deRegisterFontWithPlatform(JNIEnv *env,
203 jclass cl,
204 jstring fontName)
205 {
206 LPTSTR file = (LPTSTR)JNU_GetStringPlatformChars(env, fontName, JNI_FALSE);
207 if (file) {
208 ::RemoveFontResourceEx(file, FR_PRIVATE, NULL);
209 JNU_ReleaseStringPlatformChars(env, fontName, file);
210 }
211 }
212
213 #define EUDCKEY_JA_JP L"EUDC\\932"
214 #define EUDCKEY_ZH_CN L"EUDC\\936"
215 #define EUDCKEY_ZH_TW L"EUDC\\950"
216 #define EUDCKEY_KO_KR L"EUDC\\949"
217 #define EUDCKEY_EN_US L"EUDC\\1252"
218 #define LANGID_JA_JP 0x411
219 #define LANGID_ZH_CN 0x0804
220 #define LANGID_ZH_SG 0x1004
221 #define LANGID_ZH_TW 0x0404
222 #define LANGID_ZH_HK 0x0c04
223 #define LANGID_ZH_MO 0x1404
224 #define LANGID_KO_KR 0x0412
225 #define LANGID_EN_US 0x0409
226
227
228 JNIEXPORT jstring JNICALL
Java_sun_awt_Win32FontManager_getEUDCFontFile(JNIEnv * env,jclass cl)229 Java_sun_awt_Win32FontManager_getEUDCFontFile(JNIEnv *env, jclass cl) {
230 int rc;
231 HKEY key;
232 DWORD type;
233 WCHAR fontPathBuf[MAX_PATH + 1];
234 unsigned long fontPathLen = MAX_PATH + 1;
235 WCHAR tmpPath[MAX_PATH + 1];
236 LPWSTR fontPath = fontPathBuf;
237 LPWSTR eudcKey = NULL;
238
239 LANGID langID = GetSystemDefaultLangID();
240 //lookup for encoding ID, EUDC only supported in
241 //codepage 932, 936, 949, 950 (and unicode)
242 // On Windows 7, at least for me, it shows up in Cp1252 if
243 // I create a custom font. Might as well support that as it makes
244 // verification easier.
245 if (langID == LANGID_JA_JP) {
246 eudcKey = EUDCKEY_JA_JP;
247 } else if (langID == LANGID_ZH_CN || langID == LANGID_ZH_SG) {
248 eudcKey = EUDCKEY_ZH_CN;
249 } else if (langID == LANGID_ZH_HK || langID == LANGID_ZH_TW ||
250 langID == LANGID_ZH_MO) {
251 eudcKey = EUDCKEY_ZH_TW;
252 } else if (langID == LANGID_KO_KR) {
253 eudcKey = EUDCKEY_KO_KR;
254 } else if (langID == LANGID_EN_US) {
255 eudcKey = EUDCKEY_EN_US;
256 } else {
257 return NULL;
258 }
259
260 rc = RegOpenKeyEx(HKEY_CURRENT_USER, eudcKey, 0, KEY_READ, &key);
261 if (rc != ERROR_SUCCESS) {
262 return NULL;
263 }
264 rc = RegQueryValueEx(key,
265 L"SystemDefaultEUDCFont",
266 0,
267 &type,
268 (LPBYTE)fontPath,
269 &fontPathLen);
270 RegCloseKey(key);
271 if (rc != ERROR_SUCCESS || type != REG_SZ) {
272 return NULL;
273 }
274 fontPath[fontPathLen] = L'\0';
275 if (wcsstr(fontPath, L"%SystemRoot%")) {
276 //if the fontPath includes %SystemRoot%
277 LPWSTR systemRoot = _wgetenv(L"SystemRoot");
278 if (systemRoot != NULL
279 && swprintf(tmpPath, MAX_PATH, L"%s%s", systemRoot, fontPath + 12) != -1) {
280 fontPath = tmpPath;
281 }
282 else {
283 return NULL;
284 }
285 } else if (wcscmp(fontPath, L"EUDC.TTE") == 0) {
286 //else to see if it only inludes "EUDC.TTE"
287 WCHAR systemRoot[MAX_PATH + 1];
288 if (GetWindowsDirectory(systemRoot, MAX_PATH + 1) != 0) {
289 swprintf(tmpPath, MAX_PATH, L"%s\\FONTS\\EUDC.TTE", systemRoot);
290 fontPath = tmpPath;
291 }
292 else {
293 return NULL;
294 }
295 }
296 return JNU_NewStringPlatform(env, fontPath);
297 }
298
299 /*
300 * Class: sun_awt_Win32GraphicsEnvironment
301 * Method: getXResolution
302 * Signature: ()I
303 */
304 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getXResolution(JNIEnv * env,jobject wge)305 Java_sun_awt_Win32GraphicsEnvironment_getXResolution(JNIEnv *env, jobject wge)
306 {
307 TRY;
308
309 HWND hWnd = ::GetDesktopWindow();
310 HDC hDC = ::GetDC(hWnd);
311 jint result = ::GetDeviceCaps(hDC, LOGPIXELSX);
312 ::ReleaseDC(hWnd, hDC);
313 return result;
314
315 CATCH_BAD_ALLOC_RET(0);
316 }
317
318 /*
319 * Class: sun_awt_Win32GraphicsEnvironment
320 * Method: getYResolution
321 * Signature: ()I
322 */
323 JNIEXPORT jint JNICALL
Java_sun_awt_Win32GraphicsEnvironment_getYResolution(JNIEnv * env,jobject wge)324 Java_sun_awt_Win32GraphicsEnvironment_getYResolution(JNIEnv *env, jobject wge)
325 {
326 TRY;
327
328 HWND hWnd = ::GetDesktopWindow();
329 HDC hDC = ::GetDC(hWnd);
330 jint result = ::GetDeviceCaps(hDC, LOGPIXELSY);
331 ::ReleaseDC(hWnd, hDC);
332 return result;
333
334 CATCH_BAD_ALLOC_RET(0);
335 }
336
337 /*
338 * Class: sun_awt_Win32GraphicsEnvironment
339 * Method: isVistaOS
340 * Signature: ()Z
341 */
Java_sun_awt_Win32GraphicsEnvironment_isVistaOS(JNIEnv * env,jclass wgeclass)342 JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsEnvironment_isVistaOS
343 (JNIEnv *env, jclass wgeclass)
344 {
345 return IS_WINVISTA;
346 }
347