Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
41149 views
1
/*
2
* Copyright (c) 2005, 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
26
#include "splashscreen_impl.h"
27
#include <X11/Xlib.h>
28
#include <X11/Xutil.h>
29
#include <X11/extensions/shape.h>
30
#include <X11/Xmd.h>
31
#include <X11/Xatom.h>
32
#include <X11/cursorfont.h>
33
#include <sys/types.h>
34
#include <pthread.h>
35
#include <signal.h>
36
#include <unistd.h>
37
#include <sys/time.h>
38
#include <errno.h>
39
#include <iconv.h>
40
#include <langinfo.h>
41
#include <locale.h>
42
#include <fcntl.h>
43
#include <poll.h>
44
#include <sizecalc.h>
45
#include "jni.h"
46
47
static Bool shapeSupported;
48
static int shapeEventBase, shapeErrorBase;
49
50
void SplashRemoveDecoration(Splash * splash);
51
52
53
/* Could use npt but decided to cut down on linked code size */
54
char* SplashConvertStringAlloc(const char* in, int* size) {
55
const char *codeset;
56
const char *codeset_out;
57
iconv_t cd;
58
size_t rc;
59
char *buf = NULL, *out;
60
size_t bufSize, inSize, outSize;
61
const char* old_locale;
62
63
if (!in) {
64
return NULL;
65
}
66
old_locale = setlocale(LC_ALL, "");
67
68
codeset = nl_langinfo(CODESET);
69
if ( codeset == NULL || codeset[0] == 0 ) {
70
goto done;
71
}
72
/* we don't need BOM in output so we choose native BE or LE encoding here */
73
codeset_out = (platformByteOrder()==BYTE_ORDER_MSBFIRST) ?
74
"UCS-2BE" : "UCS-2LE";
75
76
cd = iconv_open(codeset_out, codeset);
77
if (cd == (iconv_t)-1 ) {
78
goto done;
79
}
80
inSize = strlen(in);
81
buf = SAFE_SIZE_ARRAY_ALLOC(malloc, inSize, 2);
82
if (!buf) {
83
return NULL;
84
}
85
bufSize = inSize*2; // need 2 bytes per char for UCS-2, this is
86
// 2 bytes per source byte max
87
out = buf; outSize = bufSize;
88
/* linux iconv wants char** source and solaris wants const char**...
89
cast to void* */
90
rc = iconv(cd, (void*)&in, &inSize, &out, &outSize);
91
iconv_close(cd);
92
93
if (rc == (size_t)-1) {
94
free(buf);
95
buf = NULL;
96
} else {
97
if (size) {
98
*size = (bufSize-outSize)/2; /* bytes to wchars */
99
}
100
}
101
done:
102
setlocale(LC_ALL, old_locale);
103
return buf;
104
}
105
106
void
107
SplashInitFrameShape(Splash * splash, int imageIndex) {
108
ImageRect maskRect;
109
XRectangle *rects;
110
SplashImage *frame = splash->frames + imageIndex;
111
112
frame->rects = NULL;
113
frame->numRects = 0;
114
115
if (!splash->maskRequired)
116
return;
117
if (!shapeSupported)
118
return;
119
initRect(&maskRect, 0, 0, splash->width, splash->height, 1,
120
splash->width * splash->imageFormat.depthBytes,
121
splash->frames[imageIndex].bitmapBits, &splash->imageFormat);
122
if (!IS_SAFE_SIZE_MUL(splash->width / 2 + 1, splash->height)) {
123
return;
124
}
125
rects = SAFE_SIZE_ARRAY_ALLOC(malloc,
126
sizeof(XRectangle), (splash->width / 2 + 1) * splash->height);
127
if (!rects) {
128
return;
129
}
130
131
frame->numRects = BitmapToYXBandedRectangles(&maskRect, rects);
132
frame->rects = SAFE_SIZE_ARRAY_ALLOC(malloc, frame->numRects, sizeof(XRectangle));
133
if (frame->rects) { // handle the error after the if(){}
134
memcpy(frame->rects, rects, frame->numRects * sizeof(XRectangle));
135
}
136
free(rects);
137
}
138
139
unsigned
140
SplashTime(void) {
141
struct timeval tv;
142
struct timezone tz;
143
unsigned long long msec;
144
145
gettimeofday(&tv, &tz);
146
msec = (unsigned long long) tv.tv_sec * 1000 +
147
(unsigned long long) tv.tv_usec / 1000;
148
149
return (unsigned) msec;
150
}
151
152
void
153
msec2timeval(unsigned time, struct timeval *tv) {
154
tv->tv_sec = time / 1000;
155
tv->tv_usec = (time % 1000) * 1000;
156
}
157
158
int
159
GetNumAvailableColors(Display * display, Screen * screen, unsigned map_entries) {
160
unsigned long pmr[1];
161
unsigned long pr[SPLASH_COLOR_MAP_SIZE];
162
unsigned nFailed, nAllocated, done = 0, nPlanes = 0;
163
Colormap cmap;
164
unsigned numColors = SPLASH_COLOR_MAP_SIZE; // never try allocating more than that
165
166
if (numColors > map_entries) {
167
numColors = map_entries;
168
}
169
cmap = XDefaultColormapOfScreen(screen);
170
nAllocated = 0; /* lower bound */
171
nFailed = numColors + 1; /* upper bound */
172
173
/* Binary search to determine the number of available cells */
174
for (done = 0; !done;) {
175
if (XAllocColorCells(display, cmap, 0, pmr, nPlanes, pr, numColors)) {
176
nAllocated = numColors;
177
XFreeColors(display, cmap, pr, numColors, 0);
178
if (nAllocated < (nFailed - 1)) {
179
numColors = (nAllocated + nFailed) / 2;
180
} else
181
done = 1;
182
} else {
183
nFailed = numColors;
184
if (nFailed > (nAllocated + 1))
185
numColors = (nAllocated + nFailed) / 2;
186
else
187
done = 1;
188
}
189
}
190
return nAllocated;
191
}
192
193
Colormap
194
AllocColors(Display * display, Screen * screen, int numColors,
195
unsigned long *pr) {
196
unsigned long pmr[1];
197
Colormap cmap = XDefaultColormapOfScreen(screen);
198
199
XAllocColorCells(display, cmap, 0, pmr, 0, pr, numColors);
200
return cmap;
201
}
202
203
void
204
FreeColors(Display * display, Screen * screen, int numColors,
205
unsigned long *pr) {
206
Colormap cmap = XDefaultColormapOfScreen(screen);
207
208
XFreeColors(display, cmap, pr, numColors, 0);
209
}
210
211
static void SplashCenter(Splash * splash) {
212
Atom type, atom, actual_type;
213
int status, actual_format;
214
unsigned long nitems, bytes_after;
215
CARD16 *prop = NULL;
216
217
/* try centering using Xinerama hint
218
if there's no hint, use the center of the screen */
219
atom = XInternAtom(splash->display, "XINERAMA_CENTER_HINT", True);
220
if (atom != None) {
221
status = XGetWindowProperty(splash->display,
222
XRootWindowOfScreen(splash->screen), atom, 0, 1, False, XA_INTEGER,
223
&actual_type, &actual_format, &nitems,
224
&bytes_after, (unsigned char**)(&prop));
225
if (status == Success && actual_type != None && prop != NULL) {
226
splash->x = prop[0] - splash->width/2;
227
splash->y = prop[1] - splash->height/2;
228
XFree(prop);
229
return;
230
}
231
if (prop != NULL) {
232
XFree(prop);
233
}
234
}
235
splash->x = (XWidthOfScreen(splash->screen) - splash->width) / 2;
236
splash->y = (XHeightOfScreen(splash->screen) - splash->height) / 2;
237
}
238
239
static void SplashUpdateSizeHints(Splash * splash) {
240
if (splash->window) {
241
XSizeHints sizeHints;
242
243
sizeHints.flags = USPosition | PPosition | USSize | PSize | PMinSize | PMaxSize | PWinGravity;
244
sizeHints.width = sizeHints.base_width = sizeHints.min_width = sizeHints.max_width = splash->width;
245
sizeHints.height = sizeHints.base_height = sizeHints.min_height = sizeHints.max_height = splash->height;
246
sizeHints.win_gravity = NorthWestGravity;
247
248
XSetWMNormalHints(splash->display, splash->window, &sizeHints);
249
}
250
}
251
252
void
253
SplashCreateWindow(Splash * splash) {
254
XSizeHints sizeHints;
255
256
XSetWindowAttributes attr;
257
258
attr.backing_store = NotUseful;
259
attr.colormap = XDefaultColormapOfScreen(splash->screen);
260
attr.save_under = True;
261
attr.cursor = splash->cursor = XCreateFontCursor(splash->display, XC_watch);
262
attr.event_mask = ExposureMask;
263
264
SplashCenter(splash);
265
266
splash->window = XCreateWindow(splash->display, XRootWindowOfScreen(splash->screen),
267
splash->x, splash->y, splash->width, splash->height, 0, CopyFromParent,
268
InputOutput, CopyFromParent, CWColormap | CWBackingStore | CWSaveUnder | CWCursor | CWEventMask,
269
&attr);
270
SplashUpdateSizeHints(splash);
271
272
273
splash->wmHints = XAllocWMHints();
274
if (splash->wmHints) {
275
splash->wmHints->flags = InputHint | StateHint;
276
splash->wmHints->input = False;
277
splash->wmHints->initial_state = NormalState;
278
XSetWMHints(splash->display, splash->window, splash->wmHints);
279
}
280
}
281
282
/* for changing the visible shape of a window to an nonrectangular form */
283
void
284
SplashUpdateShape(Splash * splash) {
285
if (splash->currentFrame < 0 || !shapeSupported || !splash->maskRequired) {
286
return;
287
}
288
XShapeCombineRectangles(splash->display, splash->window, ShapeClip, 0, 0,
289
splash->frames[splash->currentFrame].rects,
290
splash->frames[splash->currentFrame].numRects, ShapeSet, YXBanded);
291
XShapeCombineRectangles(splash->display, splash->window, ShapeBounding,
292
0, 0, splash->frames[splash->currentFrame].rects,
293
splash->frames[splash->currentFrame].numRects, ShapeSet, YXBanded);
294
}
295
296
/* for reverting the visible shape of a window to an rectangular form */
297
void
298
SplashRevertShape(Splash * splash) {
299
if (!shapeSupported)
300
return;
301
if (splash->maskRequired)
302
return;
303
304
XShapeCombineMask (splash->display, splash->window, ShapeClip,
305
0, 0, None, ShapeSet);
306
XShapeCombineMask (splash->display, splash->window , ShapeBounding,
307
0, 0, None, ShapeSet);
308
}
309
310
int
311
ByteOrderToX(int byteOrder) {
312
if (byteOrder == BYTE_ORDER_NATIVE)
313
byteOrder = platformByteOrder();
314
switch (byteOrder) {
315
case BYTE_ORDER_LSBFIRST:
316
return LSBFirst;
317
case BYTE_ORDER_MSBFIRST:
318
return MSBFirst;
319
default:
320
return -1;
321
}
322
}
323
324
void
325
SplashRedrawWindow(Splash * splash) {
326
if (splash->currentFrame < 0) {
327
return;
328
}
329
330
XImage *ximage;
331
332
// making this method redraw a part of the image does not make
333
// much sense as SplashUpdateScreenData always re-generates
334
// the image completely, so whole window is always redrawn
335
336
SplashUpdateScreenData(splash);
337
ximage = XCreateImage(splash->display, splash->visual,
338
splash->screenFormat.depthBytes * 8, ZPixmap, 0, (char *) NULL,
339
splash->width, splash->height, 8, 0);
340
ximage->data = (char *) splash->screenData;
341
ximage->bits_per_pixel = ximage->depth;
342
ximage->bytes_per_line = ximage->depth * ximage->width / 8;
343
ximage->byte_order = ByteOrderToX(splash->screenFormat.byteOrder);
344
ximage->bitmap_unit = 8;
345
XPutImage(splash->display, splash->window,
346
XDefaultGCOfScreen(splash->screen), ximage, 0, 0, 0, 0,
347
splash->width, splash->height);
348
ximage->data = NULL;
349
XDestroyImage(ximage);
350
SplashRemoveDecoration(splash);
351
XMapWindow(splash->display, splash->window);
352
XFlush(splash->display);
353
}
354
355
void SplashReconfigureNow(Splash * splash) {
356
SplashCenter(splash);
357
if (splash->window) {
358
XUnmapWindow(splash->display, splash->window);
359
XMoveResizeWindow(splash->display, splash->window,
360
splash->x, splash->y,
361
splash->width, splash->height);
362
SplashUpdateSizeHints(splash);
363
}
364
if (splash->maskRequired) {
365
SplashUpdateShape(splash);
366
} else {
367
SplashRevertShape(splash);
368
}
369
SplashRedrawWindow(splash);
370
}
371
372
373
void
374
sendctl(Splash * splash, char code) {
375
// if (splash->isVisible>0) {
376
if (splash && splash->controlpipe[1]) {
377
write(splash->controlpipe[1], &code, 1);
378
}
379
}
380
381
int
382
HandleError(Display * disp, XErrorEvent * err) {
383
// silently ignore non-fatal errors
384
/*
385
char msg[0x1000];
386
char buf[0x1000];
387
XGetErrorText(disp, err->error_code, msg, sizeof(msg));
388
fprintf(stderr, "Xerror %s, XID %x, ser# %d\n", msg, err->resourceid,
389
err->serial);
390
sprintf(buf, "%d", err->request_code);
391
XGetErrorDatabaseText(disp, "XRequest", buf, "Unknown", msg, sizeof(msg));
392
fprintf(stderr, "Major opcode %d (%s)\n", err->request_code, msg);
393
if (err->request_code > 128) {
394
fprintf(stderr, "Minor opcode %d\n", err->minor_code);
395
}
396
*/
397
return 0;
398
}
399
400
int
401
HandleIOError(Display * display) {
402
// for really bad errors, we should exit the thread we're on
403
SplashCleanup(SplashGetInstance());
404
pthread_exit(NULL);
405
return 0;
406
}
407
408
int
409
SplashInitPlatform(Splash * splash) {
410
int shapeVersionMajor, shapeVersionMinor;
411
412
// This setting enables the synchronous Xlib mode!
413
// Don't use it == 1 in production builds!
414
#if (defined DEBUG)
415
_Xdebug = 1;
416
#endif
417
418
pthread_mutex_init(&splash->lock, NULL);
419
420
// We should not ignore any errors.
421
//XSetErrorHandler(HandleError);
422
// XSetIOErrorHandler(HandleIOError);
423
XSetIOErrorHandler(NULL);
424
splash->display = XOpenDisplay(NULL);
425
if (!splash->display) {
426
splash->isVisible = -1;
427
return 0;
428
}
429
430
shapeSupported = XShapeQueryExtension(splash->display, &shapeEventBase,
431
&shapeErrorBase);
432
if (shapeSupported) {
433
XShapeQueryVersion(splash->display, &shapeVersionMajor,
434
&shapeVersionMinor);
435
}
436
437
splash->screen = XDefaultScreenOfDisplay(splash->display);
438
splash->visual = XDefaultVisualOfScreen(splash->screen);
439
switch (splash->visual->class) {
440
case TrueColor: {
441
int depth = XDefaultDepthOfScreen(splash->screen);
442
443
splash->byteAlignment = 1;
444
splash->maskRequired = shapeSupported;
445
initFormat(&splash->screenFormat, splash->visual->red_mask,
446
splash->visual->green_mask, splash->visual->blue_mask, 0);
447
splash->screenFormat.byteOrder =
448
(XImageByteOrder(splash->display) == LSBFirst ?
449
BYTE_ORDER_LSBFIRST : BYTE_ORDER_MSBFIRST);
450
splash->screenFormat.depthBytes = (depth + 7) / 8;
451
// TrueColor depth probably can't be less
452
// than 8 bits, and it's always byte padded
453
break;
454
}
455
case PseudoColor: {
456
int availableColors;
457
int numColors;
458
int numComponents[3];
459
unsigned long colorIndex[SPLASH_COLOR_MAP_SIZE];
460
XColor xColors[SPLASH_COLOR_MAP_SIZE];
461
int i;
462
int depth = XDefaultDepthOfScreen(splash->screen);
463
int scale = 65535 / MAX_COLOR_VALUE;
464
465
availableColors = GetNumAvailableColors(splash->display, splash->screen,
466
splash->visual->map_entries);
467
numColors = quantizeColors(availableColors, numComponents);
468
if (numColors > availableColors) {
469
// Could not allocate the color cells. Most probably
470
// the pool got exhausted. Disable the splash screen.
471
XCloseDisplay(splash->display);
472
splash->isVisible = -1;
473
splash->display = NULL;
474
splash->screen = NULL;
475
splash->visual = NULL;
476
fprintf(stderr, "Warning: unable to initialize the splashscreen. Not enough available color cells.\n");
477
return 0;
478
}
479
splash->cmap = AllocColors(splash->display, splash->screen,
480
numColors, colorIndex);
481
for (i = 0; i < numColors; i++) {
482
splash->colorIndex[i] = colorIndex[i];
483
}
484
initColorCube(numComponents, splash->colorMap, splash->dithers,
485
splash->colorIndex);
486
for (i = 0; i < numColors; i++) {
487
xColors[i].pixel = colorIndex[i];
488
xColors[i].red = (unsigned short)
489
QUAD_RED(splash->colorMap[colorIndex[i]]) * scale;
490
xColors[i].green = (unsigned short)
491
QUAD_GREEN(splash->colorMap[colorIndex[i]]) * scale;
492
xColors[i].blue = (unsigned short)
493
QUAD_BLUE(splash->colorMap[colorIndex[i]]) * scale;
494
xColors[i].flags = DoRed | DoGreen | DoBlue;
495
}
496
XStoreColors(splash->display, splash->cmap, xColors, numColors);
497
initFormat(&splash->screenFormat, 0, 0, 0, 0);
498
splash->screenFormat.colorIndex = splash->colorIndex;
499
splash->screenFormat.depthBytes = (depth + 7) / 8; // or always 8?
500
splash->screenFormat.colorMap = splash->colorMap;
501
splash->screenFormat.dithers = splash->dithers;
502
splash->screenFormat.numColors = numColors;
503
splash->screenFormat.byteOrder = BYTE_ORDER_NATIVE;
504
break;
505
}
506
default:
507
; /* FIXME: should probably be fixed, but javaws splash screen doesn't support other visuals either */
508
}
509
return 1;
510
}
511
512
513
void
514
SplashCleanupPlatform(Splash * splash) {
515
int i;
516
517
if (splash->frames) {
518
for (i = 0; i < splash->frameCount; i++) {
519
if (splash->frames[i].rects) {
520
free(splash->frames[i].rects);
521
splash->frames[i].rects = NULL;
522
}
523
}
524
}
525
splash->maskRequired = shapeSupported;
526
}
527
528
void
529
SplashDonePlatform(Splash * splash) {
530
pthread_mutex_destroy(&splash->lock);
531
if (splash->cmap) {
532
unsigned long colorIndex[SPLASH_COLOR_MAP_SIZE];
533
int i;
534
535
for (i = 0; i < splash->screenFormat.numColors; i++) {
536
colorIndex[i] = splash->colorIndex[i];
537
}
538
FreeColors(splash->display, splash->screen,
539
splash->screenFormat.numColors, colorIndex);
540
}
541
if (splash->window)
542
XDestroyWindow(splash->display, splash->window);
543
if (splash->wmHints)
544
XFree(splash->wmHints);
545
if (splash->cursor)
546
XFreeCursor(splash->display, splash->cursor);
547
if (splash->display)
548
XCloseDisplay(splash->display);
549
}
550
551
void
552
SplashEventLoop(Splash * splash) {
553
554
/* Different from win32 implementation - this loop
555
uses poll timeouts instead of a timer */
556
/* we should have splash _locked_ on entry!!! */
557
558
int xconn = XConnectionNumber(splash->display);
559
560
while (1) {
561
struct pollfd pfd[2];
562
int timeout = -1;
563
int ctl = splash->controlpipe[0];
564
int rc;
565
int pipes_empty;
566
567
pfd[0].fd = xconn;
568
pfd[0].events = POLLIN | POLLPRI;
569
570
pfd[1].fd = ctl;
571
pfd[1].events = POLLIN | POLLPRI;
572
573
errno = 0;
574
if (splash->isVisible>0 && SplashIsStillLooping(splash)) {
575
timeout = splash->time + splash->frames[splash->currentFrame].delay
576
- SplashTime();
577
if (timeout < 0) {
578
timeout = 0;
579
}
580
}
581
SplashUnlock(splash);
582
rc = poll(pfd, 2, timeout);
583
SplashLock(splash);
584
if (splash->isVisible > 0 && splash->currentFrame >= 0 &&
585
SplashTime() >= splash->time + splash->frames[splash->currentFrame].delay) {
586
SplashNextFrame(splash);
587
SplashUpdateShape(splash);
588
SplashRedrawWindow(splash);
589
}
590
if (rc <= 0) {
591
errno = 0;
592
continue;
593
}
594
pipes_empty = 0;
595
while(!pipes_empty) {
596
char buf;
597
598
pipes_empty = 1;
599
if (read(ctl, &buf, sizeof(buf)) > 0) {
600
pipes_empty = 0;
601
switch (buf) {
602
case SPLASHCTL_UPDATE:
603
if (splash->isVisible>0) {
604
SplashRedrawWindow(splash);
605
}
606
break;
607
case SPLASHCTL_RECONFIGURE:
608
if (splash->isVisible>0) {
609
SplashReconfigureNow(splash);
610
}
611
break;
612
case SPLASHCTL_QUIT:
613
return;
614
}
615
}
616
// we're not using "while(XPending)", processing one event
617
// at a time to avoid control pipe starvation
618
if (XPending(splash->display)) {
619
XEvent evt;
620
621
pipes_empty = 0;
622
XNextEvent(splash->display, &evt);
623
switch (evt.type) {
624
case Expose:
625
if (splash->isVisible>0) {
626
// we're doing full redraw so we just
627
// skip the remaining painting events in the queue
628
while(XCheckTypedEvent(splash->display, Expose,
629
&evt));
630
SplashRedrawWindow(splash);
631
}
632
break;
633
/* ... */
634
}
635
}
636
}
637
}
638
}
639
640
/* we can't use OverrideRedirect for the window as the window should not be
641
always-on-top, so we must set appropriate wm hints
642
643
this functions sets olwm, mwm and EWMH hints for undecorated window at once
644
645
It works for: mwm, openbox, wmaker, metacity, KWin (FIXME: test more wm's)
646
Should work for: fvwm2.5.x, blackbox, olwm
647
Maybe works for: enlightenment, icewm
648
Does not work for: twm, fvwm2.4.7
649
650
*/
651
652
void
653
SplashRemoveDecoration(Splash * splash) {
654
Atom atom_set;
655
Atom atom_list[4];
656
657
/* the struct below was copied from MwmUtil.h */
658
659
struct PROPMOTIFWMHINTS {
660
/* 32-bit property items are stored as long on the client (whether
661
* that means 32 bits or 64). XChangeProperty handles the conversion
662
* to the actual 32-bit quantities sent to the server.
663
*/
664
unsigned long flags;
665
unsigned long functions;
666
unsigned long decorations;
667
long inputMode;
668
unsigned long status;
669
}
670
mwm_hints;
671
672
/* WM_TAKE_FOCUS hint to avoid wm's transfer of focus to this window */
673
/* WM_DELETE_WINDOW hint to avoid closing this window with Alt-F4. See bug 6474035 */
674
atom_set = XInternAtom(splash->display, "WM_PROTOCOLS", True);
675
if (atom_set != None) {
676
atom_list[0] = XInternAtom(splash->display, "WM_TAKE_FOCUS", True);
677
atom_list[1] = XInternAtom(splash->display, "WM_DELETE_WINDOW", True);
678
679
XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,
680
PropModeReplace, (unsigned char *) atom_list, 2);
681
}
682
683
/* mwm hints */
684
atom_set = XInternAtom(splash->display, "_MOTIF_WM_HINTS", True);
685
if (atom_set != None) {
686
/* flags for decoration and functions */
687
mwm_hints.flags = (1L << 1) | (1L << 0);
688
mwm_hints.decorations = 0;
689
mwm_hints.functions = 0;
690
XChangeProperty(splash->display, splash->window, atom_set, atom_set,
691
32, PropModeReplace, (unsigned char *) &mwm_hints, 5);
692
}
693
694
/* olwm hints */
695
atom_set = XInternAtom(splash->display, "_OL_DECOR_DEL", True);
696
if (atom_set != None) {
697
atom_list[0] = XInternAtom(splash->display, "_OL_DECOR_RESIZE", True);
698
atom_list[1] = XInternAtom(splash->display, "_OL_DECOR_HEADER", True);
699
atom_list[2] = XInternAtom(splash->display, "_OL_DECOR_PIN", True);
700
atom_list[3] = XInternAtom(splash->display, "_OL_DECOR_CLOSE", True);
701
XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,
702
PropModeReplace, (unsigned char *) atom_list, 4);
703
}
704
705
/* generic EMWH hints
706
we do not set _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_SPLASH
707
hint support due to gnome making this window always-on-top
708
so we have to set _NET_WM_STATE and _NET_WM_ALLOWED_ACTIONS correctly
709
_NET_WM_STATE: SKIP_TASKBAR and SKIP_PAGER
710
_NET_WM_ALLOWED_ACTIONS: disable all actions */
711
atom_set = XInternAtom(splash->display, "_NET_WM_STATE", True);
712
if (atom_set != None) {
713
atom_list[0] = XInternAtom(splash->display,
714
"_NET_WM_STATE_SKIP_TASKBAR", True);
715
atom_list[1] = XInternAtom(splash->display,
716
"_NET_WM_STATE_SKIP_PAGER", True);
717
XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,
718
PropModeReplace, (unsigned char *) atom_list, 2);
719
}
720
atom_set = XInternAtom(splash->display, "_NET_WM_ALLOWED_ACTIONS", True);
721
if (atom_set != None) {
722
XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,
723
PropModeReplace, (unsigned char *) atom_list, 0);
724
}
725
}
726
727
void
728
SplashPThreadDestructor(void *arg) {
729
/* this will be used in case of emergency thread exit on xlib error */
730
Splash *splash = (Splash *) arg;
731
732
if (splash) {
733
SplashCleanup(splash);
734
}
735
}
736
737
void *
738
SplashScreenThread(void *param) {
739
Splash *splash = (Splash *) param;
740
// pthread_key_t key;
741
742
// pthread_key_create(&key, SplashPThreadDestructor);
743
// pthread_setspecific(key, splash);
744
745
SplashLock(splash);
746
pipe(splash->controlpipe);
747
fcntl(splash->controlpipe[0], F_SETFL,
748
fcntl(splash->controlpipe[0], F_GETFL, 0) | O_NONBLOCK);
749
splash->time = SplashTime();
750
SplashCreateWindow(splash);
751
fflush(stdout);
752
if (splash->window) {
753
SplashRemoveDecoration(splash);
754
XStoreName(splash->display, splash->window, "Java");
755
XMapRaised(splash->display, splash->window);
756
SplashUpdateShape(splash);
757
SplashRedrawWindow(splash);
758
//map the splash co-ordinates as per system scale
759
splash->x /= splash->scaleFactor;
760
splash->y /= splash->scaleFactor;
761
SplashEventLoop(splash);
762
}
763
SplashUnlock(splash);
764
SplashDone(splash);
765
766
splash->isVisible=-1;
767
return 0;
768
}
769
770
void
771
SplashCreateThread(Splash * splash) {
772
pthread_t thr;
773
pthread_attr_t attr;
774
int rc;
775
776
pthread_attr_init(&attr);
777
rc = pthread_create(&thr, &attr, SplashScreenThread, (void *) splash);
778
}
779
780
void
781
SplashLock(Splash * splash) {
782
pthread_mutex_lock(&splash->lock);
783
}
784
785
void
786
SplashUnlock(Splash * splash) {
787
pthread_mutex_unlock(&splash->lock);
788
}
789
790
void
791
SplashClosePlatform(Splash * splash) {
792
sendctl(splash, SPLASHCTL_QUIT);
793
}
794
795
void
796
SplashUpdate(Splash * splash) {
797
sendctl(splash, SPLASHCTL_UPDATE);
798
}
799
800
void
801
SplashReconfigure(Splash * splash) {
802
sendctl(splash, SPLASHCTL_RECONFIGURE);
803
}
804
805
JNIEXPORT jboolean
806
SplashGetScaledImageName(const char* jarName, const char* fileName,
807
float *scaleFactor, char *scaledImgName,
808
const size_t scaledImageNameLength)
809
{
810
*scaleFactor = 1;
811
#ifndef __linux__
812
return JNI_FALSE;
813
#endif
814
*scaleFactor = (float)getNativeScaleFactor();
815
return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength);
816
}
817
818
819