Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c
41149 views
1
/*
2
* Copyright (c) 2005, 2019, 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
// copy from awt.h
27
#ifndef _WIN32_WINNT
28
#define _WIN32_WINNT 0x0600
29
#endif
30
31
// copy from awt.h
32
#ifndef _WIN32_IE
33
#define _WIN32_IE 0x0600
34
#endif
35
36
#include "splashscreen_impl.h"
37
#include <windowsx.h>
38
#include <windows.h>
39
#include <winuser.h>
40
#include "sizecalc.h"
41
42
#ifndef WS_EX_LAYERED
43
#define WS_EX_LAYERED 0x80000
44
#endif
45
46
#ifndef ULW_ALPHA
47
#define ULW_ALPHA 0x00000002
48
#endif
49
50
#ifndef AC_SRC_OVER
51
#define AC_SRC_OVER 0x00
52
#endif
53
54
#ifndef AC_SRC_ALPHA
55
#define AC_SRC_ALPHA 0x01
56
#endif
57
58
#define WM_SPLASHUPDATE WM_USER+1
59
#define WM_SPLASHRECONFIGURE WM_USER+2
60
61
#define BUFF_SIZE 1024
62
63
/* Could use npt but decided to cut down on linked code size */
64
char* SplashConvertStringAlloc(const char* in, int *size) {
65
int len, outChars, rc;
66
WCHAR* buf;
67
if (!in) {
68
return NULL;
69
}
70
len = strlen(in);
71
outChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, in, len,
72
NULL, 0);
73
buf = (WCHAR*) SAFE_SIZE_ARRAY_ALLOC(malloc, outChars, sizeof(WCHAR));
74
if (!buf) {
75
return NULL;
76
}
77
rc = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, in, len,
78
buf, outChars);
79
if (rc==0) {
80
free(buf);
81
return NULL;
82
} else {
83
if (size) {
84
*size = rc;
85
}
86
return (char*)buf;
87
}
88
}
89
90
unsigned
91
SplashTime(void)
92
{
93
return GetTickCount();
94
}
95
96
void
97
SplashInitFrameShape(Splash * splash, int imageIndex)
98
{
99
RGNDATA *pRgnData;
100
RGNDATAHEADER *pRgnHdr;
101
ImageRect maskRect;
102
103
if (!splash->maskRequired)
104
return;
105
106
/* reserving memory for the worst case */
107
if (!IS_SAFE_SIZE_MUL(splash->width / 2 + 1, splash->height)) {
108
return;
109
}
110
pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(malloc, sizeof(RGNDATAHEADER),
111
sizeof(RECT), (splash->width / 2 + 1) * splash->height);
112
if (!pRgnData) {
113
return;
114
}
115
pRgnHdr = (RGNDATAHEADER *) pRgnData;
116
initRect(&maskRect, 0, 0, splash->width, splash->height, 1,
117
splash->width * splash->imageFormat.depthBytes,
118
splash->frames[imageIndex].bitmapBits, &splash->imageFormat);
119
120
pRgnHdr->dwSize = sizeof(RGNDATAHEADER);
121
pRgnHdr->iType = RDH_RECTANGLES;
122
pRgnHdr->nRgnSize = 0;
123
pRgnHdr->rcBound.top = 0;
124
pRgnHdr->rcBound.left = 0;
125
pRgnHdr->rcBound.bottom = splash->height;
126
pRgnHdr->rcBound.right = splash->width;
127
128
pRgnHdr->nCount = BitmapToYXBandedRectangles(&maskRect,
129
(RECT *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER)));
130
131
splash->frames[imageIndex].hRgn = ExtCreateRegion(NULL,
132
sizeof(RGNDATAHEADER) + sizeof(RECT) * pRgnHdr->nCount, pRgnData);
133
134
free(pRgnData);
135
}
136
137
/* paint current splash screen frame to hdc
138
this function is unused in layered window mode */
139
140
void
141
SplashPaint(Splash * splash, HDC hdc)
142
{
143
unsigned numColors = splash->screenFormat.colorMap ?
144
splash->screenFormat.numColors : 0;
145
BITMAPV4HEADER *pBmi;
146
HPALETTE hOldPal = NULL;
147
148
if (!splash->frames)
149
return;
150
if (splash->currentFrame < 0 || splash->currentFrame >= splash->frameCount)
151
return;
152
pBmi = (BITMAPV4HEADER *) SAFE_SIZE_STRUCT_ALLOC(alloca, sizeof(BITMAPV4HEADER),
153
sizeof(RGBQUAD), numColors);
154
if (!pBmi) {
155
return;
156
}
157
memset(pBmi, 0, sizeof(BITMAPV4HEADER));
158
if (splash->screenFormat.colorMap)
159
memcpy(((BYTE *) pBmi) + sizeof(BITMAPV4HEADER),
160
splash->screenFormat.colorMap, sizeof(RGBQUAD) * numColors);
161
162
pBmi->bV4Size = sizeof(BITMAPV4HEADER);
163
pBmi->bV4Width = splash->width;
164
pBmi->bV4Height = -splash->height;
165
pBmi->bV4Planes = 1;
166
pBmi->bV4BitCount = (WORD) (splash->screenFormat.depthBytes * 8);
167
/* we're ALWAYS using BGRA in screenFormat */
168
pBmi->bV4V4Compression = BI_RGB;
169
pBmi->bV4ClrUsed = numColors;
170
pBmi->bV4ClrImportant = numColors;
171
pBmi->bV4AlphaMask = splash->screenFormat.mask[3];
172
pBmi->bV4RedMask = splash->screenFormat.mask[2];
173
pBmi->bV4GreenMask = splash->screenFormat.mask[1];
174
pBmi->bV4BlueMask = splash->screenFormat.mask[0];
175
176
/* creating the palette in SplashInitPlatform does not work, so I'm creating it
177
here on demand */
178
if (!splash->hPalette) {
179
unsigned i;
180
LOGPALETTE *pLogPal = (LOGPALETTE *) SAFE_SIZE_STRUCT_ALLOC(malloc,
181
sizeof(LOGPALETTE), sizeof(PALETTEENTRY), numColors);
182
if (!pLogPal) {
183
return;
184
}
185
186
pLogPal->palVersion = 0x300;
187
pLogPal->palNumEntries = (WORD) numColors;
188
for (i = 0; i < numColors; i++) {
189
pLogPal->palPalEntry[i].peRed = (BYTE)
190
QUAD_RED(splash->colorMap[i]);
191
pLogPal->palPalEntry[i].peGreen = (BYTE)
192
QUAD_GREEN(splash->colorMap[i]);
193
pLogPal->palPalEntry[i].peBlue = (BYTE)
194
QUAD_BLUE(splash->colorMap[i]);
195
pLogPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
196
}
197
splash->hPalette = CreatePalette(pLogPal);
198
free(pLogPal);
199
}
200
if (splash->hPalette) {
201
hOldPal = SelectPalette(hdc, splash->hPalette, FALSE);
202
RealizePalette(hdc);
203
}
204
205
StretchDIBits(hdc, 0, 0, splash->width, splash->height, 0, 0,
206
splash->width, splash->height, splash->screenData,
207
(BITMAPINFO *) pBmi, DIB_RGB_COLORS, SRCCOPY);
208
if (hOldPal)
209
SelectPalette(hdc, hOldPal, FALSE);
210
}
211
212
213
/* The function makes the window visible if it is hidden
214
or is not yet shown. */
215
void
216
SplashRedrawWindow(Splash * splash)
217
{
218
if (!SplashIsStillLooping(splash)) {
219
KillTimer(splash->hWnd, 0);
220
}
221
222
if (splash->currentFrame < 0) {
223
return;
224
}
225
226
SplashUpdateScreenData(splash);
227
if (splash->isLayered) {
228
BLENDFUNCTION bf;
229
POINT ptSrc;
230
HDC hdcSrc = CreateCompatibleDC(NULL), hdcDst;
231
BITMAPINFOHEADER bmi;
232
void *bitmapBits;
233
HBITMAP hBitmap, hOldBitmap;
234
RECT rect;
235
POINT ptDst;
236
SIZE size;
237
238
bf.BlendOp = AC_SRC_OVER;
239
bf.BlendFlags = 0;
240
bf.AlphaFormat = AC_SRC_ALPHA;
241
bf.SourceConstantAlpha = 0xFF;
242
ptSrc.x = ptSrc.y = 0;
243
244
memset(&bmi, 0, sizeof(bmi));
245
bmi.biSize = sizeof(BITMAPINFOHEADER);
246
bmi.biWidth = splash->width;
247
bmi.biHeight = -splash->height;
248
bmi.biPlanes = 1;
249
bmi.biBitCount = 32;
250
bmi.biCompression = BI_RGB;
251
252
// FIXME: this is somewhat ineffective
253
// maybe if we allocate memory for all frames as DIBSections,
254
// then we could select the frames into the DC directly
255
256
hBitmap = CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS,
257
&bitmapBits, NULL, 0);
258
memcpy(bitmapBits, splash->screenData,
259
splash->screenStride * splash->height);
260
hOldBitmap = (HBITMAP) SelectObject(hdcSrc, hBitmap);
261
hdcDst = GetDC(splash->hWnd);
262
263
GetWindowRect(splash->hWnd, &rect);
264
265
ptDst.x = rect.left;
266
ptDst.y = rect.top;
267
268
size.cx = splash->width;
269
size.cy = splash->height;
270
271
UpdateLayeredWindow(splash->hWnd, hdcDst, &ptDst, &size,
272
hdcSrc, &ptSrc, 0, &bf, ULW_ALPHA);
273
274
ReleaseDC(splash->hWnd, hdcDst);
275
SelectObject(hdcSrc, hOldBitmap);
276
DeleteObject(hBitmap);
277
DeleteDC(hdcSrc);
278
}
279
else {
280
InvalidateRect(splash->hWnd, NULL, FALSE);
281
if (splash->maskRequired) {
282
HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
283
284
CombineRgn(hRgn, splash->frames[splash->currentFrame].hRgn,
285
splash->frames[splash->currentFrame].hRgn, RGN_COPY);
286
SetWindowRgn(splash->hWnd, hRgn, TRUE);
287
} else {
288
SetWindowRgn(splash->hWnd, NULL, TRUE);
289
}
290
UpdateWindow(splash->hWnd);
291
}
292
if (!IsWindowVisible(splash->hWnd)) {
293
POINT cursorPos;
294
ShowWindow(splash->hWnd, SW_SHOW);
295
// Windows won't update the cursor after the window is shown,
296
// if the cursor is already above the window. need to do this manually.
297
GetCursorPos(&cursorPos);
298
if (WindowFromPoint(cursorPos) == splash->hWnd) {
299
// unfortunately Windows fail to understand that the window
300
// thread should own the cursor, even though the mouse pointer
301
// is over the window, until the mouse has been moved.
302
// we're using SetCursorPos here to fake the mouse movement
303
// and enable proper update of the cursor.
304
SetCursorPos(cursorPos.x, cursorPos.y);
305
SetCursor(LoadCursor(NULL, IDC_WAIT));
306
}
307
}
308
if (SplashIsStillLooping(splash)) {
309
int time = splash->time +
310
splash->frames[splash->currentFrame].delay - SplashTime();
311
312
if (time < 0)
313
time = 0;
314
SetTimer(splash->hWnd, 0, time, NULL);
315
}
316
}
317
318
void SplashReconfigureNow(Splash * splash) {
319
splash->x = (GetSystemMetrics(SM_CXSCREEN) - splash->width) / 2;
320
splash->y = (GetSystemMetrics(SM_CYSCREEN) - splash->height) / 2;
321
if (splash->hWnd) {
322
//Fixed 6474657: splash screen image jumps towards left while
323
// setting the new image using setImageURL()
324
// We may safely hide the splash window because SplashRedrawWindow()
325
// will show the window again.
326
ShowWindow(splash->hWnd, SW_HIDE);
327
MoveWindow(splash->hWnd, splash->x, splash->y, splash->width, splash->height, FALSE);
328
}
329
SplashRedrawWindow(splash);
330
}
331
332
static LRESULT CALLBACK
333
SplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
334
{
335
PAINTSTRUCT ps;
336
HDC hdc;
337
338
339
switch (message) {
340
341
case WM_ERASEBKGND:
342
return TRUE; // to avoid flicker
343
344
case WM_SYSCOMMAND:
345
if (wParam==SC_CLOSE||wParam==SC_DEFAULT||wParam==SC_HOTKEY||
346
wParam==SC_KEYMENU||wParam==SC_MAXIMIZE||
347
wParam==SC_MINIMIZE||wParam==SC_MOUSEMENU||wParam==SC_MOVE||
348
wParam==SC_RESTORE||wParam==SC_SIZE)
349
{
350
return 0;
351
}
352
353
/* double switch to avoid prologue/epilogue duplication */
354
case WM_TIMER:
355
case WM_SPLASHUPDATE:
356
case WM_PAINT:
357
case WM_SPLASHRECONFIGURE:
358
{
359
Splash *splash = (Splash *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
360
361
SplashLock(splash);
362
if (splash->isVisible>0) {
363
switch(message) {
364
case WM_TIMER:
365
SplashNextFrame(splash);
366
SplashRedrawWindow(splash);
367
break;
368
case WM_SPLASHUPDATE:
369
SplashRedrawWindow(splash);
370
break;
371
case WM_PAINT:
372
hdc = BeginPaint(hWnd, &ps);
373
SplashPaint(splash, hdc);
374
EndPaint(hWnd, &ps);
375
break;
376
case WM_SPLASHRECONFIGURE:
377
SplashReconfigureNow(splash);
378
break;
379
}
380
}
381
SplashUnlock(splash);
382
break;
383
}
384
case WM_DESTROY:
385
PostQuitMessage(0);
386
break;
387
default:
388
return DefWindowProc(hWnd, message, wParam, lParam);
389
390
}
391
return 0;
392
}
393
394
HWND
395
SplashCreateWindow(Splash * splash)
396
{
397
WNDCLASSEX wcex;
398
ATOM wndClass;
399
DWORD style, exStyle;
400
HWND hWnd;
401
402
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
403
404
wcex.cbSize = sizeof(WNDCLASSEX);
405
wcex.style = CS_HREDRAW | CS_VREDRAW;
406
wcex.lpfnWndProc = (WNDPROC) SplashWndProc;
407
wcex.hInstance = GetModuleHandle(NULL);
408
wcex.lpszClassName = "JavaSplash";
409
wcex.hCursor = LoadCursor(NULL, IDC_WAIT);
410
411
wndClass = RegisterClassEx(&wcex);
412
if (!wndClass) {
413
return 0;
414
}
415
416
splash->x = (GetSystemMetrics(SM_CXSCREEN) - splash->width) / 2;
417
splash->y = (GetSystemMetrics(SM_CYSCREEN) - splash->height) / 2;
418
exStyle = splash->isLayered ? WS_EX_LAYERED : 0;
419
exStyle |= WS_EX_TOOLWINDOW; /* don't show the window on taskbar */
420
style = WS_POPUP;
421
hWnd = CreateWindowEx(exStyle, (LPCSTR) wndClass, "", style,
422
splash->x, splash->y, splash->width, splash->height, NULL, NULL,
423
wcex.hInstance, NULL);
424
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) splash);
425
return hWnd;
426
}
427
428
void
429
SplashLock(Splash * splash)
430
{
431
EnterCriticalSection(&splash->lock);
432
}
433
434
void
435
SplashUnlock(Splash * splash)
436
{
437
LeaveCriticalSection(&splash->lock);
438
}
439
440
int
441
SplashInitPlatform(Splash * splash)
442
{
443
HDC hdc;
444
int paletteMode;
445
446
InitializeCriticalSection(&splash->lock);
447
splash->isLayered = FALSE;
448
hdc = GetDC(NULL);
449
paletteMode = (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0;
450
if (UpdateLayeredWindow && !paletteMode) {
451
splash->isLayered = TRUE;
452
}
453
splash->byteAlignment = 4;
454
if (splash->isLayered) {
455
initFormat(&splash->screenFormat,
456
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
457
splash->screenFormat.premultiplied = 1;
458
splash->maskRequired = 0;
459
}
460
else {
461
splash->maskRequired = 1;
462
if (paletteMode) {
463
int numColors = GetDeviceCaps(hdc, SIZEPALETTE) -
464
GetDeviceCaps(hdc, NUMRESERVED);
465
int i;
466
int numComponents[3];
467
468
initFormat(&splash->screenFormat, 0, 0, 0, 0);
469
/* FIXME: maybe remapping to non-reserved colors would improve performance */
470
for (i = 0; i < numColors; i++) {
471
splash->colorIndex[i] = i;
472
}
473
numColors = quantizeColors(numColors, numComponents);
474
initColorCube(numComponents, splash->colorMap, splash->dithers,
475
splash->colorIndex);
476
splash->screenFormat.colorIndex = splash->colorIndex;
477
splash->screenFormat.depthBytes = 1;
478
splash->screenFormat.colorMap = splash->colorMap;
479
splash->screenFormat.dithers = splash->dithers;
480
splash->screenFormat.numColors = numColors;
481
splash->hPalette = NULL;
482
}
483
else {
484
initFormat(&splash->screenFormat,
485
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
486
}
487
}
488
ReleaseDC(NULL, hdc);
489
return 1;
490
}
491
492
void
493
SplashCleanupPlatform(Splash * splash)
494
{
495
int i;
496
497
if (splash->frames) {
498
for (i = 0; i < splash->frameCount; i++) {
499
if (splash->frames[i].hRgn) {
500
DeleteObject(splash->frames[i].hRgn);
501
splash->frames[i].hRgn = NULL;
502
}
503
}
504
}
505
if (splash->hPalette)
506
DeleteObject(splash->hPalette);
507
splash->maskRequired = !splash->isLayered;
508
}
509
510
void
511
SplashDonePlatform(Splash * splash)
512
{
513
if (splash->hWnd)
514
DestroyWindow(splash->hWnd);
515
}
516
517
void
518
SplashMessagePump()
519
{
520
MSG msg;
521
522
while (GetMessage(&msg, NULL, 0, 0)) {
523
TranslateMessage(&msg);
524
DispatchMessage(&msg);
525
}
526
}
527
528
DWORD WINAPI
529
SplashScreenThread(LPVOID param)
530
{
531
Splash *splash = (Splash *) param;
532
533
splash->currentFrame = 0;
534
SplashLock(splash);
535
splash->time = SplashTime();
536
splash->hWnd = SplashCreateWindow(splash);
537
if (splash->hWnd) {
538
SplashRedrawWindow(splash);
539
//map the splash co-ordinates as per system scale
540
splash->x /= splash->scaleFactor;
541
splash->y /= splash->scaleFactor;
542
SplashUnlock(splash);
543
SplashMessagePump();
544
SplashLock(splash);
545
}
546
SplashDone(splash);
547
splash->isVisible = -1;
548
SplashUnlock(splash);
549
return 0;
550
}
551
552
void
553
SplashCreateThread(Splash * splash)
554
{
555
DWORD threadId;
556
557
CreateThread(NULL, 0, SplashScreenThread, (LPVOID) splash, 0, &threadId);
558
}
559
560
void
561
SplashClosePlatform(Splash * splash)
562
{
563
PostMessage(splash->hWnd, WM_QUIT, 0, 0);
564
}
565
566
void
567
SplashUpdate(Splash * splash)
568
{
569
PostMessage(splash->hWnd, WM_SPLASHUPDATE, 0, 0);
570
}
571
572
void
573
SplashReconfigure(Splash * splash)
574
{
575
PostMessage(splash->hWnd, WM_SPLASHRECONFIGURE, 0, 0);
576
}
577
578
JNIEXPORT jboolean
579
SplashGetScaledImageName(const char* jarName, const char* fileName,
580
float *scaleFactor, char *scaleImageName,
581
const size_t scaledImageLength)
582
{
583
float dpiScaleX = -1.0f;
584
float dpiScaleY = -1.0f;
585
FILE *fp = NULL;
586
*scaleFactor = 1.0;
587
GetScreenDpi(getPrimaryMonitor(), &dpiScaleX, &dpiScaleY);
588
*scaleFactor = dpiScaleX > 0 ? dpiScaleX / 96 : *scaleFactor;
589
return GetScaledImageName(fileName, scaleImageName,
590
scaleFactor, scaledImageLength);
591
}
592
593
594