Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/UNIXToolkit.java
32287 views
1
/*
2
* Copyright (c) 2004, 2018, 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
package sun.awt;
26
27
import java.awt.RenderingHints;
28
import static java.awt.RenderingHints.*;
29
import java.awt.color.ColorSpace;
30
import java.awt.image.*;
31
import java.security.AccessController;
32
import java.security.PrivilegedAction;
33
import sun.security.action.GetIntegerAction;
34
import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection;
35
import sun.java2d.opengl.OGLRenderQueue;
36
import sun.security.action.GetPropertyAction;
37
38
public abstract class UNIXToolkit extends SunToolkit
39
{
40
/** All calls into GTK should be synchronized on this lock */
41
public static final Object GTK_LOCK = new Object();
42
43
private static final int[] BAND_OFFSETS = { 0, 1, 2 };
44
private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 };
45
private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000;
46
47
// Allowed GTK versions
48
public enum GtkVersions {
49
ANY(0),
50
GTK2(Constants.GTK2_MAJOR_NUMBER),
51
GTK3(Constants.GTK3_MAJOR_NUMBER);
52
53
static class Constants {
54
static final int GTK2_MAJOR_NUMBER = 2;
55
static final int GTK3_MAJOR_NUMBER = 3;
56
}
57
58
final int number;
59
60
GtkVersions(int number) {
61
this.number = number;
62
}
63
64
public static GtkVersions getVersion(int number) {
65
switch (number) {
66
case Constants.GTK2_MAJOR_NUMBER:
67
return GTK2;
68
case Constants.GTK3_MAJOR_NUMBER:
69
return GTK3;
70
default:
71
return ANY;
72
}
73
}
74
75
// major GTK version number
76
public int getNumber() {
77
return number;
78
}
79
};
80
81
private Boolean nativeGTKAvailable;
82
private Boolean nativeGTKLoaded;
83
private BufferedImage tmpImage = null;
84
85
public static int getDatatransferTimeout() {
86
Integer dt = (Integer)AccessController.doPrivileged(
87
new GetIntegerAction("sun.awt.datatransfer.timeout"));
88
if (dt == null || dt <= 0) {
89
return DEFAULT_DATATRANSFER_TIMEOUT;
90
} else {
91
return dt;
92
}
93
}
94
95
/**
96
* Returns true if the native GTK libraries are capable of being
97
* loaded and are expected to work properly, false otherwise. Note
98
* that this method will not leave the native GTK libraries loaded if
99
* they haven't already been loaded. This allows, for example, Swing's
100
* GTK L&F to test for the presence of native GTK support without
101
* leaving the native libraries loaded. To attempt long-term loading
102
* of the native GTK libraries, use the loadGTK() method instead.
103
*/
104
@Override
105
public boolean isNativeGTKAvailable() {
106
synchronized (GTK_LOCK) {
107
if (nativeGTKLoaded != null) {
108
// We've already attempted to load GTK, so just return the
109
// status of that attempt.
110
return nativeGTKLoaded;
111
112
} else if (nativeGTKAvailable != null) {
113
// We've already checked the availability of the native GTK
114
// libraries, so just return the status of that attempt.
115
return nativeGTKAvailable;
116
117
} else {
118
boolean success = check_gtk(getEnabledGtkVersion().getNumber());
119
nativeGTKAvailable = success;
120
return success;
121
}
122
}
123
}
124
125
/**
126
* Loads the GTK libraries, if necessary. The first time this method
127
* is called, it will attempt to load the native GTK library. If
128
* successful, it leaves the library open and returns true; otherwise,
129
* the library is left closed and returns false. On future calls to
130
* this method, the status of the first attempt is returned (a simple
131
* lightweight boolean check, no native calls required).
132
*/
133
public boolean loadGTK() {
134
synchronized (GTK_LOCK) {
135
if (nativeGTKLoaded == null) {
136
nativeGTKLoaded = load_gtk(getEnabledGtkVersion().getNumber(),
137
isGtkVerbose());
138
}
139
}
140
return nativeGTKLoaded;
141
}
142
143
/**
144
* Overridden to handle GTK icon loading
145
*/
146
protected Object lazilyLoadDesktopProperty(String name) {
147
if (name.startsWith("gtk.icon.")) {
148
return lazilyLoadGTKIcon(name);
149
}
150
return super.lazilyLoadDesktopProperty(name);
151
}
152
153
/**
154
* Load a native Gtk stock icon.
155
*
156
* @param longname a desktop property name. This contains icon name, size
157
* and orientation, e.g. <code>"gtk.icon.gtk-add.4.rtl"</code>
158
* @return an <code>Image</code> for the icon, or <code>null</code> if the
159
* icon could not be loaded
160
*/
161
protected Object lazilyLoadGTKIcon(String longname) {
162
// Check if we have already loaded it.
163
Object result = desktopProperties.get(longname);
164
if (result != null) {
165
return result;
166
}
167
168
// We need to have at least gtk.icon.<stock_id>.<size>.<orientation>
169
String str[] = longname.split("\\.");
170
if (str.length != 5) {
171
return null;
172
}
173
174
// Parse out the stock icon size we are looking for.
175
int size = 0;
176
try {
177
size = Integer.parseInt(str[3]);
178
} catch (NumberFormatException nfe) {
179
return null;
180
}
181
182
// Direction.
183
TextDirection dir = ("ltr".equals(str[4]) ? TextDirection.LTR :
184
TextDirection.RTL);
185
186
// Load the stock icon.
187
BufferedImage img = getStockIcon(-1, str[2], size, dir.ordinal(), null);
188
if (img != null) {
189
// Create the desktop property for the icon.
190
setDesktopProperty(longname, img);
191
}
192
return img;
193
}
194
195
/**
196
* Returns a BufferedImage which contains the Gtk icon requested. If no
197
* such icon exists or an error occurs loading the icon the result will
198
* be null.
199
*
200
* @param filename
201
* @return The icon or null if it was not found or loaded.
202
*/
203
public BufferedImage getGTKIcon(final String filename) {
204
if (!loadGTK()) {
205
return null;
206
207
} else {
208
// Call the native method to load the icon.
209
synchronized (GTK_LOCK) {
210
if (!load_gtk_icon(filename)) {
211
tmpImage = null;
212
}
213
}
214
}
215
// Return local image the callback loaded the icon into.
216
return tmpImage;
217
}
218
219
/**
220
* Returns a BufferedImage which contains the Gtk stock icon requested.
221
* If no such stock icon exists the result will be null.
222
*
223
* @param widgetType one of WidgetType values defined in GTKNativeEngine or
224
* -1 for system default stock icon.
225
* @param stockId String which defines the stock id of the gtk item.
226
* For a complete list reference the API at www.gtk.org for StockItems.
227
* @param iconSize One of the GtkIconSize values defined in GTKConstants
228
* @param textDirection One of the TextDirection values defined in
229
* GTKConstants
230
* @param detail Render detail that is passed to the native engine (feel
231
* free to pass null)
232
* @return The stock icon or null if it was not found or loaded.
233
*/
234
public BufferedImage getStockIcon(final int widgetType, final String stockId,
235
final int iconSize, final int direction,
236
final String detail) {
237
if (!loadGTK()) {
238
return null;
239
240
} else {
241
// Call the native method to load the icon.
242
synchronized (GTK_LOCK) {
243
if (!load_stock_icon(widgetType, stockId, iconSize, direction, detail)) {
244
tmpImage = null;
245
}
246
}
247
}
248
// Return local image the callback loaded the icon into.
249
return tmpImage; // set by loadIconCallback
250
}
251
252
/**
253
* This method is used by JNI as a callback from load_stock_icon.
254
* Image data is passed back to us via this method and loaded into the
255
* local BufferedImage and then returned via getStockIcon.
256
*
257
* Do NOT call this method directly.
258
*/
259
public void loadIconCallback(byte[] data, int width, int height,
260
int rowStride, int bps, int channels, boolean alpha) {
261
// Reset the stock image to null.
262
tmpImage = null;
263
264
// Create a new BufferedImage based on the data returned from the
265
// JNI call.
266
DataBuffer dataBuf = new DataBufferByte(data, (rowStride * height));
267
// Maybe test # channels to determine band offsets?
268
WritableRaster raster = Raster.createInterleavedRaster(dataBuf,
269
width, height, rowStride, channels,
270
(alpha ? BAND_OFFSETS_ALPHA : BAND_OFFSETS), null);
271
ColorModel colorModel = new ComponentColorModel(
272
ColorSpace.getInstance(ColorSpace.CS_sRGB), alpha, false,
273
ColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);
274
275
// Set the local image so we can return it later from
276
// getStockIcon().
277
tmpImage = new BufferedImage(colorModel, raster, false, null);
278
}
279
280
private static native boolean check_gtk(int version);
281
private static native boolean load_gtk(int version, boolean verbose);
282
private static native boolean unload_gtk();
283
private native boolean load_gtk_icon(String filename);
284
private native boolean load_stock_icon(int widget_type, String stock_id,
285
int iconSize, int textDirection, String detail);
286
287
private native void nativeSync();
288
private static native int get_gtk_version();
289
290
@Override
291
public void sync() {
292
// flush the X11 buffer
293
nativeSync();
294
// now flush the OGL pipeline (this is a no-op if OGL is not enabled)
295
OGLRenderQueue.sync();
296
}
297
298
/*
299
* This returns the value for the desktop property "awt.font.desktophints"
300
* It builds this by querying the Gnome desktop properties to return
301
* them as platform independent hints.
302
* This requires that the Gnome properties have already been gathered.
303
*/
304
public static final String FONTCONFIGAAHINT = "fontconfig/Antialias";
305
306
@Override
307
protected RenderingHints getDesktopAAHints() {
308
309
Object aaValue = getDesktopProperty("gnome.Xft/Antialias");
310
311
if (aaValue == null) {
312
/* On a KDE desktop running KWin the rendering hint will
313
* have been set as property "fontconfig/Antialias".
314
* No need to parse further in this case.
315
*/
316
aaValue = getDesktopProperty(FONTCONFIGAAHINT);
317
if (aaValue != null) {
318
return new RenderingHints(KEY_TEXT_ANTIALIASING, aaValue);
319
} else {
320
return null; // no Gnome or KDE Desktop properties available.
321
}
322
}
323
324
/* 0 means off, 1 means some ON. What would any other value mean?
325
* If we require "1" to enable AA then some new value would cause
326
* us to default to "OFF". I don't think that's the best guess.
327
* So if its !=0 then lets assume AA.
328
*/
329
boolean aa = ((aaValue instanceof Number)
330
&& ((Number) aaValue).intValue() != 0);
331
Object aaHint;
332
if (aa) {
333
String subpixOrder =
334
(String)getDesktopProperty("gnome.Xft/RGBA");
335
336
if (subpixOrder == null || subpixOrder.equals("none")) {
337
aaHint = VALUE_TEXT_ANTIALIAS_ON;
338
} else if (subpixOrder.equals("rgb")) {
339
aaHint = VALUE_TEXT_ANTIALIAS_LCD_HRGB;
340
} else if (subpixOrder.equals("bgr")) {
341
aaHint = VALUE_TEXT_ANTIALIAS_LCD_HBGR;
342
} else if (subpixOrder.equals("vrgb")) {
343
aaHint = VALUE_TEXT_ANTIALIAS_LCD_VRGB;
344
} else if (subpixOrder.equals("vbgr")) {
345
aaHint = VALUE_TEXT_ANTIALIAS_LCD_VBGR;
346
} else {
347
/* didn't recognise the string, but AA is requested */
348
aaHint = VALUE_TEXT_ANTIALIAS_ON;
349
}
350
} else {
351
aaHint = VALUE_TEXT_ANTIALIAS_DEFAULT;
352
}
353
return new RenderingHints(KEY_TEXT_ANTIALIASING, aaHint);
354
}
355
356
private native boolean gtkCheckVersionImpl(int major, int minor,
357
int micro);
358
359
/**
360
* Returns {@code true} if the GTK+ library is compatible with the given
361
* version.
362
*
363
* @param major
364
* The required major version.
365
* @param minor
366
* The required minor version.
367
* @param micro
368
* The required micro version.
369
* @return {@code true} if the GTK+ library is compatible with the given
370
* version.
371
*/
372
public boolean checkGtkVersion(int major, int minor, int micro) {
373
if (loadGTK()) {
374
return gtkCheckVersionImpl(major, minor, micro);
375
}
376
return false;
377
}
378
379
public static GtkVersions getEnabledGtkVersion() {
380
String version = AccessController.doPrivileged(
381
new GetPropertyAction("jdk.gtk.version"));
382
if (version == null) {
383
return GtkVersions.ANY;
384
} else if (version.startsWith("2")) {
385
return GtkVersions.GTK2;
386
} else if("3".equals(version) ){
387
return GtkVersions.GTK3;
388
}
389
return GtkVersions.ANY;
390
}
391
392
public static GtkVersions getGtkVersion() {
393
return GtkVersions.getVersion(get_gtk_version());
394
}
395
396
public static boolean isGtkVerbose() {
397
return AccessController.doPrivileged((PrivilegedAction<Boolean>)()
398
-> Boolean.getBoolean("jdk.gtk.verbose"));
399
}
400
}
401
402