1
1
/*
2
- * Copyright (c) 2004, 2020 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2004, 2023 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
30
30
import java .awt .Insets ;
31
31
import java .awt .Point ;
32
32
import java .util .HashMap ;
33
+ import java .util .List ;
33
34
import java .util .Map ;
34
35
import java .util .concurrent .locks .Lock ;
35
36
import java .util .concurrent .locks .ReadWriteLock ;
36
37
import java .util .concurrent .locks .ReentrantReadWriteLock ;
37
38
39
+ import static com .sun .java .swing .plaf .windows .TMSchema .Part ;
40
+
38
41
/**
39
42
* Implements Theme Support for Windows XP.
40
43
*
44
47
*/
45
48
public final class ThemeReader {
46
49
47
- private static final Map <String , Long > widgetToTheme = new HashMap <>();
50
+ private static final int defaultDPI = 96 ;
51
+
52
+ /**
53
+ * List of widgets for which we need to get the part size for the current DPI.
54
+ */
55
+ private static final List <String > partSizeWidgets =
56
+ List .of ("MENU" , "BUTTON" );
57
+
58
+ /**
59
+ * List of widget parts for which we need to get the part size for the current DPI.
60
+ */
61
+ private static final List <Integer > partSizeWidgetParts =
62
+ List .of (Part .BP_RADIOBUTTON .getValue (),
63
+ Part .BP_CHECKBOX .getValue (),
64
+ Part .MP_POPUPCHECK .getValue ());
65
+
66
+ private static final Map <Integer , Map <String , Long >> dpiAwareWidgetToTheme
67
+ = new HashMap <>();
48
68
49
69
// lock for the cache
50
70
// reading should be done with readLock
@@ -80,28 +100,30 @@ public static boolean isXPStyleEnabled() {
80
100
return xpStyleEnabled ;
81
101
}
82
102
103
+ private static Long openThemeImpl (String widget , int dpi ) {
104
+ Long theme ;
105
+ int i = widget .indexOf ("::" );
106
+ if (i > 0 ) {
107
+ // We're using the syntax "subAppName::controlName" here, as used by msstyles.
108
+ // See documentation for SetWindowTheme on MSDN.
109
+ setWindowTheme (widget .substring (0 , i ));
110
+ theme = openTheme (widget .substring (i + 2 ), dpi );
111
+ setWindowTheme (null );
112
+ } else {
113
+ theme = openTheme (widget , dpi );
114
+ }
115
+ return theme ;
116
+ }
117
+
83
118
// this should be called only with writeLock held
84
- private static Long getThemeImpl (String widget ) {
85
- Long theme = widgetToTheme .get (widget );
86
- if (theme == null ) {
87
- int i = widget .indexOf ("::" );
88
- if (i > 0 ) {
89
- // We're using the syntax "subAppName::controlName" here, as used by msstyles.
90
- // See documentation for SetWindowTheme on MSDN.
91
- setWindowTheme (widget .substring (0 , i ));
92
- theme = openTheme (widget .substring (i +2 ));
93
- setWindowTheme (null );
94
- } else {
95
- theme = openTheme (widget );
96
- }
97
- widgetToTheme .put (widget , theme );
98
- }
99
- return theme ;
119
+ private static Long getThemeImpl (String widget , int dpi ) {
120
+ return dpiAwareWidgetToTheme .computeIfAbsent (dpi , key -> new HashMap <>())
121
+ .computeIfAbsent (widget , w -> openThemeImpl (widget , dpi ));
100
122
}
101
123
102
124
// returns theme value
103
125
// this method should be invoked with readLock locked
104
- private static Long getTheme (String widget ) {
126
+ private static Long getTheme (String widget , int dpi ) {
105
127
if (!isThemed ) {
106
128
throw new IllegalStateException ("Themes are not loaded" );
107
129
}
@@ -111,10 +133,12 @@ private static Long getTheme(String widget) {
111
133
try {
112
134
if (!valid ) {
113
135
// Close old themes.
114
- for (Long value : widgetToTheme .values ()) {
115
- closeTheme (value );
136
+ for (Map <String , Long > dpiVal : dpiAwareWidgetToTheme .values ()) {
137
+ for (Long value : dpiVal .values ()) {
138
+ closeTheme (value );
139
+ }
116
140
}
117
- widgetToTheme .clear ();
141
+ dpiAwareWidgetToTheme .clear ();
118
142
valid = true ;
119
143
}
120
144
} finally {
@@ -123,13 +147,20 @@ private static Long getTheme(String widget) {
123
147
}
124
148
}
125
149
150
+ Long theme = null ;
151
+
152
+ Map <String , Long > widgetToTheme = dpiAwareWidgetToTheme .get (dpi );
153
+
154
+ if (widgetToTheme != null ) {
155
+ theme = widgetToTheme .get (widget );
156
+ }
157
+
126
158
// mostly copied from the javadoc for ReentrantReadWriteLock
127
- Long theme = widgetToTheme .get (widget );
128
159
if (theme == null ) {
129
160
readLock .unlock ();
130
161
writeLock .lock ();
131
162
try {
132
- theme = getThemeImpl (widget );
163
+ theme = getThemeImpl (widget , dpi );
133
164
} finally {
134
165
readLock .lock ();
135
166
writeLock .unlock ();// Unlock write, still hold read
@@ -139,14 +170,23 @@ private static Long getTheme(String widget) {
139
170
}
140
171
141
172
private static native void paintBackground (int [] buffer , long theme ,
142
- int part , int state , int x ,
143
- int y , int w , int h , int stride );
173
+ int part , int state ,
174
+ int rectRight , int rectBottom ,
175
+ int w , int h , int stride );
144
176
145
177
public static void paintBackground (int [] buffer , String widget ,
146
- int part , int state , int x , int y , int w , int h , int stride ) {
178
+ int part , int state , int x , int y , int w , int h , int stride , int dpi ) {
147
179
readLock .lock ();
148
180
try {
149
- paintBackground (buffer , getTheme (widget ), part , state , x , y , w , h , stride );
181
+ /* For widgets and parts in the lists, we get the part size
182
+ for the current screen DPI to scale them better. */
183
+ Dimension d = (partSizeWidgets .contains (widget )
184
+ && partSizeWidgetParts .contains (Integer .valueOf (part )))
185
+ ? getPartSize (getTheme (widget , dpi ), part , state )
186
+ : new Dimension (w , h );
187
+
188
+ paintBackground (buffer , getTheme (widget , dpi ), part , state ,
189
+ d .width , d .height , w , h , stride );
150
190
} finally {
151
191
readLock .unlock ();
152
192
}
@@ -158,7 +198,7 @@ private static native Insets getThemeMargins(long theme, int part,
158
198
public static Insets getThemeMargins (String widget , int part , int state , int marginType ) {
159
199
readLock .lock ();
160
200
try {
161
- return getThemeMargins (getTheme (widget ), part , state , marginType );
201
+ return getThemeMargins (getTheme (widget , defaultDPI ), part , state , marginType );
162
202
} finally {
163
203
readLock .unlock ();
164
204
}
@@ -169,7 +209,7 @@ public static Insets getThemeMargins(String widget, int part, int state, int mar
169
209
public static boolean isThemePartDefined (String widget , int part , int state ) {
170
210
readLock .lock ();
171
211
try {
172
- return isThemePartDefined (getTheme (widget ), part , state );
212
+ return isThemePartDefined (getTheme (widget , defaultDPI ), part , state );
173
213
} finally {
174
214
readLock .unlock ();
175
215
}
@@ -181,7 +221,7 @@ private static native Color getColor(long theme, int part, int state,
181
221
public static Color getColor (String widget , int part , int state , int property ) {
182
222
readLock .lock ();
183
223
try {
184
- return getColor (getTheme (widget ), part , state , property );
224
+ return getColor (getTheme (widget , defaultDPI ), part , state , property );
185
225
} finally {
186
226
readLock .unlock ();
187
227
}
@@ -193,7 +233,7 @@ private static native int getInt(long theme, int part, int state,
193
233
public static int getInt (String widget , int part , int state , int property ) {
194
234
readLock .lock ();
195
235
try {
196
- return getInt (getTheme (widget ), part , state , property );
236
+ return getInt (getTheme (widget , defaultDPI ), part , state , property );
197
237
} finally {
198
238
readLock .unlock ();
199
239
}
@@ -205,7 +245,7 @@ private static native int getEnum(long theme, int part, int state,
205
245
public static int getEnum (String widget , int part , int state , int property ) {
206
246
readLock .lock ();
207
247
try {
208
- return getEnum (getTheme (widget ), part , state , property );
248
+ return getEnum (getTheme (widget , defaultDPI ), part , state , property );
209
249
} finally {
210
250
readLock .unlock ();
211
251
}
@@ -218,7 +258,7 @@ public static boolean getBoolean(String widget, int part, int state,
218
258
int property ) {
219
259
readLock .lock ();
220
260
try {
221
- return getBoolean (getTheme (widget ), part , state , property );
261
+ return getBoolean (getTheme (widget , defaultDPI ), part , state , property );
222
262
} finally {
223
263
readLock .unlock ();
224
264
}
@@ -229,7 +269,7 @@ public static boolean getBoolean(String widget, int part, int state,
229
269
public static boolean getSysBoolean (String widget , int property ) {
230
270
readLock .lock ();
231
271
try {
232
- return getSysBoolean (getTheme (widget ), property );
272
+ return getSysBoolean (getTheme (widget , defaultDPI ), property );
233
273
} finally {
234
274
readLock .unlock ();
235
275
}
@@ -241,7 +281,7 @@ private static native Point getPoint(long theme, int part, int state,
241
281
public static Point getPoint (String widget , int part , int state , int property ) {
242
282
readLock .lock ();
243
283
try {
244
- return getPoint (getTheme (widget ), part , state , property );
284
+ return getPoint (getTheme (widget , defaultDPI ), part , state , property );
245
285
} finally {
246
286
readLock .unlock ();
247
287
}
@@ -254,7 +294,7 @@ public static Dimension getPosition(String widget, int part, int state,
254
294
int property ) {
255
295
readLock .lock ();
256
296
try {
257
- return getPosition (getTheme (widget ), part ,state ,property );
297
+ return getPosition (getTheme (widget , defaultDPI ), part ,state ,property );
258
298
} finally {
259
299
readLock .unlock ();
260
300
}
@@ -266,13 +306,13 @@ private static native Dimension getPartSize(long theme, int part,
266
306
public static Dimension getPartSize (String widget , int part , int state ) {
267
307
readLock .lock ();
268
308
try {
269
- return getPartSize (getTheme (widget ), part , state );
309
+ return getPartSize (getTheme (widget , defaultDPI ), part , state );
270
310
} finally {
271
311
readLock .unlock ();
272
312
}
273
313
}
274
314
275
- private static native long openTheme (String widget );
315
+ private static native long openTheme (String widget , int dpi );
276
316
277
317
private static native void closeTheme (long theme );
278
318
@@ -285,8 +325,9 @@ public static long getThemeTransitionDuration(String widget, int part,
285
325
int stateFrom , int stateTo , int propId ) {
286
326
readLock .lock ();
287
327
try {
288
- return getThemeTransitionDuration (getTheme (widget ),
289
- part , stateFrom , stateTo , propId );
328
+ return getThemeTransitionDuration (getTheme (widget , defaultDPI ),
329
+ part , stateFrom , stateTo ,
330
+ propId );
290
331
} finally {
291
332
readLock .unlock ();
292
333
}
@@ -299,8 +340,9 @@ public static Insets getThemeBackgroundContentMargins(String widget,
299
340
int part , int state , int boundingWidth , int boundingHeight ) {
300
341
readLock .lock ();
301
342
try {
302
- return getThemeBackgroundContentMargins (getTheme (widget ),
303
- part , state , boundingWidth , boundingHeight );
343
+ return getThemeBackgroundContentMargins (getTheme (widget , defaultDPI ),
344
+ part , state ,
345
+ boundingWidth , boundingHeight );
304
346
} finally {
305
347
readLock .unlock ();
306
348
}
1 commit comments
openjdk-notifier[bot] commentedon Sep 20, 2023
Review
Issues