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