Path: blob/master/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
41149 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "splashscreen_impl.h"26#include <X11/Xlib.h>27#include <X11/Xutil.h>28#include <X11/extensions/shape.h>29#include <X11/Xmd.h>30#include <X11/Xatom.h>31#include <X11/cursorfont.h>32#include <sys/types.h>33#include <pthread.h>34#include <signal.h>35#include <unistd.h>36#include <sys/time.h>37#include <errno.h>38#include <iconv.h>39#include <langinfo.h>40#include <locale.h>41#include <fcntl.h>42#include <poll.h>43#include <sizecalc.h>44#include "jni.h"4546static Bool shapeSupported;47static int shapeEventBase, shapeErrorBase;4849void SplashRemoveDecoration(Splash * splash);505152/* Could use npt but decided to cut down on linked code size */53char* SplashConvertStringAlloc(const char* in, int* size) {54const char *codeset;55const char *codeset_out;56iconv_t cd;57size_t rc;58char *buf = NULL, *out;59size_t bufSize, inSize, outSize;60const char* old_locale;6162if (!in) {63return NULL;64}65old_locale = setlocale(LC_ALL, "");6667codeset = nl_langinfo(CODESET);68if ( codeset == NULL || codeset[0] == 0 ) {69goto done;70}71/* we don't need BOM in output so we choose native BE or LE encoding here */72codeset_out = (platformByteOrder()==BYTE_ORDER_MSBFIRST) ?73"UCS-2BE" : "UCS-2LE";7475cd = iconv_open(codeset_out, codeset);76if (cd == (iconv_t)-1 ) {77goto done;78}79inSize = strlen(in);80buf = SAFE_SIZE_ARRAY_ALLOC(malloc, inSize, 2);81if (!buf) {82return NULL;83}84bufSize = inSize*2; // need 2 bytes per char for UCS-2, this is85// 2 bytes per source byte max86out = buf; outSize = bufSize;87/* linux iconv wants char** source and solaris wants const char**...88cast to void* */89rc = iconv(cd, (void*)&in, &inSize, &out, &outSize);90iconv_close(cd);9192if (rc == (size_t)-1) {93free(buf);94buf = NULL;95} else {96if (size) {97*size = (bufSize-outSize)/2; /* bytes to wchars */98}99}100done:101setlocale(LC_ALL, old_locale);102return buf;103}104105void106SplashInitFrameShape(Splash * splash, int imageIndex) {107ImageRect maskRect;108XRectangle *rects;109SplashImage *frame = splash->frames + imageIndex;110111frame->rects = NULL;112frame->numRects = 0;113114if (!splash->maskRequired)115return;116if (!shapeSupported)117return;118initRect(&maskRect, 0, 0, splash->width, splash->height, 1,119splash->width * splash->imageFormat.depthBytes,120splash->frames[imageIndex].bitmapBits, &splash->imageFormat);121if (!IS_SAFE_SIZE_MUL(splash->width / 2 + 1, splash->height)) {122return;123}124rects = SAFE_SIZE_ARRAY_ALLOC(malloc,125sizeof(XRectangle), (splash->width / 2 + 1) * splash->height);126if (!rects) {127return;128}129130frame->numRects = BitmapToYXBandedRectangles(&maskRect, rects);131frame->rects = SAFE_SIZE_ARRAY_ALLOC(malloc, frame->numRects, sizeof(XRectangle));132if (frame->rects) { // handle the error after the if(){}133memcpy(frame->rects, rects, frame->numRects * sizeof(XRectangle));134}135free(rects);136}137138unsigned139SplashTime(void) {140struct timeval tv;141struct timezone tz;142unsigned long long msec;143144gettimeofday(&tv, &tz);145msec = (unsigned long long) tv.tv_sec * 1000 +146(unsigned long long) tv.tv_usec / 1000;147148return (unsigned) msec;149}150151void152msec2timeval(unsigned time, struct timeval *tv) {153tv->tv_sec = time / 1000;154tv->tv_usec = (time % 1000) * 1000;155}156157int158GetNumAvailableColors(Display * display, Screen * screen, unsigned map_entries) {159unsigned long pmr[1];160unsigned long pr[SPLASH_COLOR_MAP_SIZE];161unsigned nFailed, nAllocated, done = 0, nPlanes = 0;162Colormap cmap;163unsigned numColors = SPLASH_COLOR_MAP_SIZE; // never try allocating more than that164165if (numColors > map_entries) {166numColors = map_entries;167}168cmap = XDefaultColormapOfScreen(screen);169nAllocated = 0; /* lower bound */170nFailed = numColors + 1; /* upper bound */171172/* Binary search to determine the number of available cells */173for (done = 0; !done;) {174if (XAllocColorCells(display, cmap, 0, pmr, nPlanes, pr, numColors)) {175nAllocated = numColors;176XFreeColors(display, cmap, pr, numColors, 0);177if (nAllocated < (nFailed - 1)) {178numColors = (nAllocated + nFailed) / 2;179} else180done = 1;181} else {182nFailed = numColors;183if (nFailed > (nAllocated + 1))184numColors = (nAllocated + nFailed) / 2;185else186done = 1;187}188}189return nAllocated;190}191192Colormap193AllocColors(Display * display, Screen * screen, int numColors,194unsigned long *pr) {195unsigned long pmr[1];196Colormap cmap = XDefaultColormapOfScreen(screen);197198XAllocColorCells(display, cmap, 0, pmr, 0, pr, numColors);199return cmap;200}201202void203FreeColors(Display * display, Screen * screen, int numColors,204unsigned long *pr) {205Colormap cmap = XDefaultColormapOfScreen(screen);206207XFreeColors(display, cmap, pr, numColors, 0);208}209210static void SplashCenter(Splash * splash) {211Atom type, atom, actual_type;212int status, actual_format;213unsigned long nitems, bytes_after;214CARD16 *prop = NULL;215216/* try centering using Xinerama hint217if there's no hint, use the center of the screen */218atom = XInternAtom(splash->display, "XINERAMA_CENTER_HINT", True);219if (atom != None) {220status = XGetWindowProperty(splash->display,221XRootWindowOfScreen(splash->screen), atom, 0, 1, False, XA_INTEGER,222&actual_type, &actual_format, &nitems,223&bytes_after, (unsigned char**)(&prop));224if (status == Success && actual_type != None && prop != NULL) {225splash->x = prop[0] - splash->width/2;226splash->y = prop[1] - splash->height/2;227XFree(prop);228return;229}230if (prop != NULL) {231XFree(prop);232}233}234splash->x = (XWidthOfScreen(splash->screen) - splash->width) / 2;235splash->y = (XHeightOfScreen(splash->screen) - splash->height) / 2;236}237238static void SplashUpdateSizeHints(Splash * splash) {239if (splash->window) {240XSizeHints sizeHints;241242sizeHints.flags = USPosition | PPosition | USSize | PSize | PMinSize | PMaxSize | PWinGravity;243sizeHints.width = sizeHints.base_width = sizeHints.min_width = sizeHints.max_width = splash->width;244sizeHints.height = sizeHints.base_height = sizeHints.min_height = sizeHints.max_height = splash->height;245sizeHints.win_gravity = NorthWestGravity;246247XSetWMNormalHints(splash->display, splash->window, &sizeHints);248}249}250251void252SplashCreateWindow(Splash * splash) {253XSizeHints sizeHints;254255XSetWindowAttributes attr;256257attr.backing_store = NotUseful;258attr.colormap = XDefaultColormapOfScreen(splash->screen);259attr.save_under = True;260attr.cursor = splash->cursor = XCreateFontCursor(splash->display, XC_watch);261attr.event_mask = ExposureMask;262263SplashCenter(splash);264265splash->window = XCreateWindow(splash->display, XRootWindowOfScreen(splash->screen),266splash->x, splash->y, splash->width, splash->height, 0, CopyFromParent,267InputOutput, CopyFromParent, CWColormap | CWBackingStore | CWSaveUnder | CWCursor | CWEventMask,268&attr);269SplashUpdateSizeHints(splash);270271272splash->wmHints = XAllocWMHints();273if (splash->wmHints) {274splash->wmHints->flags = InputHint | StateHint;275splash->wmHints->input = False;276splash->wmHints->initial_state = NormalState;277XSetWMHints(splash->display, splash->window, splash->wmHints);278}279}280281/* for changing the visible shape of a window to an nonrectangular form */282void283SplashUpdateShape(Splash * splash) {284if (splash->currentFrame < 0 || !shapeSupported || !splash->maskRequired) {285return;286}287XShapeCombineRectangles(splash->display, splash->window, ShapeClip, 0, 0,288splash->frames[splash->currentFrame].rects,289splash->frames[splash->currentFrame].numRects, ShapeSet, YXBanded);290XShapeCombineRectangles(splash->display, splash->window, ShapeBounding,2910, 0, splash->frames[splash->currentFrame].rects,292splash->frames[splash->currentFrame].numRects, ShapeSet, YXBanded);293}294295/* for reverting the visible shape of a window to an rectangular form */296void297SplashRevertShape(Splash * splash) {298if (!shapeSupported)299return;300if (splash->maskRequired)301return;302303XShapeCombineMask (splash->display, splash->window, ShapeClip,3040, 0, None, ShapeSet);305XShapeCombineMask (splash->display, splash->window , ShapeBounding,3060, 0, None, ShapeSet);307}308309int310ByteOrderToX(int byteOrder) {311if (byteOrder == BYTE_ORDER_NATIVE)312byteOrder = platformByteOrder();313switch (byteOrder) {314case BYTE_ORDER_LSBFIRST:315return LSBFirst;316case BYTE_ORDER_MSBFIRST:317return MSBFirst;318default:319return -1;320}321}322323void324SplashRedrawWindow(Splash * splash) {325if (splash->currentFrame < 0) {326return;327}328329XImage *ximage;330331// making this method redraw a part of the image does not make332// much sense as SplashUpdateScreenData always re-generates333// the image completely, so whole window is always redrawn334335SplashUpdateScreenData(splash);336ximage = XCreateImage(splash->display, splash->visual,337splash->screenFormat.depthBytes * 8, ZPixmap, 0, (char *) NULL,338splash->width, splash->height, 8, 0);339ximage->data = (char *) splash->screenData;340ximage->bits_per_pixel = ximage->depth;341ximage->bytes_per_line = ximage->depth * ximage->width / 8;342ximage->byte_order = ByteOrderToX(splash->screenFormat.byteOrder);343ximage->bitmap_unit = 8;344XPutImage(splash->display, splash->window,345XDefaultGCOfScreen(splash->screen), ximage, 0, 0, 0, 0,346splash->width, splash->height);347ximage->data = NULL;348XDestroyImage(ximage);349SplashRemoveDecoration(splash);350XMapWindow(splash->display, splash->window);351XFlush(splash->display);352}353354void SplashReconfigureNow(Splash * splash) {355SplashCenter(splash);356if (splash->window) {357XUnmapWindow(splash->display, splash->window);358XMoveResizeWindow(splash->display, splash->window,359splash->x, splash->y,360splash->width, splash->height);361SplashUpdateSizeHints(splash);362}363if (splash->maskRequired) {364SplashUpdateShape(splash);365} else {366SplashRevertShape(splash);367}368SplashRedrawWindow(splash);369}370371372void373sendctl(Splash * splash, char code) {374// if (splash->isVisible>0) {375if (splash && splash->controlpipe[1]) {376write(splash->controlpipe[1], &code, 1);377}378}379380int381HandleError(Display * disp, XErrorEvent * err) {382// silently ignore non-fatal errors383/*384char msg[0x1000];385char buf[0x1000];386XGetErrorText(disp, err->error_code, msg, sizeof(msg));387fprintf(stderr, "Xerror %s, XID %x, ser# %d\n", msg, err->resourceid,388err->serial);389sprintf(buf, "%d", err->request_code);390XGetErrorDatabaseText(disp, "XRequest", buf, "Unknown", msg, sizeof(msg));391fprintf(stderr, "Major opcode %d (%s)\n", err->request_code, msg);392if (err->request_code > 128) {393fprintf(stderr, "Minor opcode %d\n", err->minor_code);394}395*/396return 0;397}398399int400HandleIOError(Display * display) {401// for really bad errors, we should exit the thread we're on402SplashCleanup(SplashGetInstance());403pthread_exit(NULL);404return 0;405}406407int408SplashInitPlatform(Splash * splash) {409int shapeVersionMajor, shapeVersionMinor;410411// This setting enables the synchronous Xlib mode!412// Don't use it == 1 in production builds!413#if (defined DEBUG)414_Xdebug = 1;415#endif416417pthread_mutex_init(&splash->lock, NULL);418419// We should not ignore any errors.420//XSetErrorHandler(HandleError);421// XSetIOErrorHandler(HandleIOError);422XSetIOErrorHandler(NULL);423splash->display = XOpenDisplay(NULL);424if (!splash->display) {425splash->isVisible = -1;426return 0;427}428429shapeSupported = XShapeQueryExtension(splash->display, &shapeEventBase,430&shapeErrorBase);431if (shapeSupported) {432XShapeQueryVersion(splash->display, &shapeVersionMajor,433&shapeVersionMinor);434}435436splash->screen = XDefaultScreenOfDisplay(splash->display);437splash->visual = XDefaultVisualOfScreen(splash->screen);438switch (splash->visual->class) {439case TrueColor: {440int depth = XDefaultDepthOfScreen(splash->screen);441442splash->byteAlignment = 1;443splash->maskRequired = shapeSupported;444initFormat(&splash->screenFormat, splash->visual->red_mask,445splash->visual->green_mask, splash->visual->blue_mask, 0);446splash->screenFormat.byteOrder =447(XImageByteOrder(splash->display) == LSBFirst ?448BYTE_ORDER_LSBFIRST : BYTE_ORDER_MSBFIRST);449splash->screenFormat.depthBytes = (depth + 7) / 8;450// TrueColor depth probably can't be less451// than 8 bits, and it's always byte padded452break;453}454case PseudoColor: {455int availableColors;456int numColors;457int numComponents[3];458unsigned long colorIndex[SPLASH_COLOR_MAP_SIZE];459XColor xColors[SPLASH_COLOR_MAP_SIZE];460int i;461int depth = XDefaultDepthOfScreen(splash->screen);462int scale = 65535 / MAX_COLOR_VALUE;463464availableColors = GetNumAvailableColors(splash->display, splash->screen,465splash->visual->map_entries);466numColors = quantizeColors(availableColors, numComponents);467if (numColors > availableColors) {468// Could not allocate the color cells. Most probably469// the pool got exhausted. Disable the splash screen.470XCloseDisplay(splash->display);471splash->isVisible = -1;472splash->display = NULL;473splash->screen = NULL;474splash->visual = NULL;475fprintf(stderr, "Warning: unable to initialize the splashscreen. Not enough available color cells.\n");476return 0;477}478splash->cmap = AllocColors(splash->display, splash->screen,479numColors, colorIndex);480for (i = 0; i < numColors; i++) {481splash->colorIndex[i] = colorIndex[i];482}483initColorCube(numComponents, splash->colorMap, splash->dithers,484splash->colorIndex);485for (i = 0; i < numColors; i++) {486xColors[i].pixel = colorIndex[i];487xColors[i].red = (unsigned short)488QUAD_RED(splash->colorMap[colorIndex[i]]) * scale;489xColors[i].green = (unsigned short)490QUAD_GREEN(splash->colorMap[colorIndex[i]]) * scale;491xColors[i].blue = (unsigned short)492QUAD_BLUE(splash->colorMap[colorIndex[i]]) * scale;493xColors[i].flags = DoRed | DoGreen | DoBlue;494}495XStoreColors(splash->display, splash->cmap, xColors, numColors);496initFormat(&splash->screenFormat, 0, 0, 0, 0);497splash->screenFormat.colorIndex = splash->colorIndex;498splash->screenFormat.depthBytes = (depth + 7) / 8; // or always 8?499splash->screenFormat.colorMap = splash->colorMap;500splash->screenFormat.dithers = splash->dithers;501splash->screenFormat.numColors = numColors;502splash->screenFormat.byteOrder = BYTE_ORDER_NATIVE;503break;504}505default:506; /* FIXME: should probably be fixed, but javaws splash screen doesn't support other visuals either */507}508return 1;509}510511512void513SplashCleanupPlatform(Splash * splash) {514int i;515516if (splash->frames) {517for (i = 0; i < splash->frameCount; i++) {518if (splash->frames[i].rects) {519free(splash->frames[i].rects);520splash->frames[i].rects = NULL;521}522}523}524splash->maskRequired = shapeSupported;525}526527void528SplashDonePlatform(Splash * splash) {529pthread_mutex_destroy(&splash->lock);530if (splash->cmap) {531unsigned long colorIndex[SPLASH_COLOR_MAP_SIZE];532int i;533534for (i = 0; i < splash->screenFormat.numColors; i++) {535colorIndex[i] = splash->colorIndex[i];536}537FreeColors(splash->display, splash->screen,538splash->screenFormat.numColors, colorIndex);539}540if (splash->window)541XDestroyWindow(splash->display, splash->window);542if (splash->wmHints)543XFree(splash->wmHints);544if (splash->cursor)545XFreeCursor(splash->display, splash->cursor);546if (splash->display)547XCloseDisplay(splash->display);548}549550void551SplashEventLoop(Splash * splash) {552553/* Different from win32 implementation - this loop554uses poll timeouts instead of a timer */555/* we should have splash _locked_ on entry!!! */556557int xconn = XConnectionNumber(splash->display);558559while (1) {560struct pollfd pfd[2];561int timeout = -1;562int ctl = splash->controlpipe[0];563int rc;564int pipes_empty;565566pfd[0].fd = xconn;567pfd[0].events = POLLIN | POLLPRI;568569pfd[1].fd = ctl;570pfd[1].events = POLLIN | POLLPRI;571572errno = 0;573if (splash->isVisible>0 && SplashIsStillLooping(splash)) {574timeout = splash->time + splash->frames[splash->currentFrame].delay575- SplashTime();576if (timeout < 0) {577timeout = 0;578}579}580SplashUnlock(splash);581rc = poll(pfd, 2, timeout);582SplashLock(splash);583if (splash->isVisible > 0 && splash->currentFrame >= 0 &&584SplashTime() >= splash->time + splash->frames[splash->currentFrame].delay) {585SplashNextFrame(splash);586SplashUpdateShape(splash);587SplashRedrawWindow(splash);588}589if (rc <= 0) {590errno = 0;591continue;592}593pipes_empty = 0;594while(!pipes_empty) {595char buf;596597pipes_empty = 1;598if (read(ctl, &buf, sizeof(buf)) > 0) {599pipes_empty = 0;600switch (buf) {601case SPLASHCTL_UPDATE:602if (splash->isVisible>0) {603SplashRedrawWindow(splash);604}605break;606case SPLASHCTL_RECONFIGURE:607if (splash->isVisible>0) {608SplashReconfigureNow(splash);609}610break;611case SPLASHCTL_QUIT:612return;613}614}615// we're not using "while(XPending)", processing one event616// at a time to avoid control pipe starvation617if (XPending(splash->display)) {618XEvent evt;619620pipes_empty = 0;621XNextEvent(splash->display, &evt);622switch (evt.type) {623case Expose:624if (splash->isVisible>0) {625// we're doing full redraw so we just626// skip the remaining painting events in the queue627while(XCheckTypedEvent(splash->display, Expose,628&evt));629SplashRedrawWindow(splash);630}631break;632/* ... */633}634}635}636}637}638639/* we can't use OverrideRedirect for the window as the window should not be640always-on-top, so we must set appropriate wm hints641642this functions sets olwm, mwm and EWMH hints for undecorated window at once643644It works for: mwm, openbox, wmaker, metacity, KWin (FIXME: test more wm's)645Should work for: fvwm2.5.x, blackbox, olwm646Maybe works for: enlightenment, icewm647Does not work for: twm, fvwm2.4.7648649*/650651void652SplashRemoveDecoration(Splash * splash) {653Atom atom_set;654Atom atom_list[4];655656/* the struct below was copied from MwmUtil.h */657658struct PROPMOTIFWMHINTS {659/* 32-bit property items are stored as long on the client (whether660* that means 32 bits or 64). XChangeProperty handles the conversion661* to the actual 32-bit quantities sent to the server.662*/663unsigned long flags;664unsigned long functions;665unsigned long decorations;666long inputMode;667unsigned long status;668}669mwm_hints;670671/* WM_TAKE_FOCUS hint to avoid wm's transfer of focus to this window */672/* WM_DELETE_WINDOW hint to avoid closing this window with Alt-F4. See bug 6474035 */673atom_set = XInternAtom(splash->display, "WM_PROTOCOLS", True);674if (atom_set != None) {675atom_list[0] = XInternAtom(splash->display, "WM_TAKE_FOCUS", True);676atom_list[1] = XInternAtom(splash->display, "WM_DELETE_WINDOW", True);677678XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,679PropModeReplace, (unsigned char *) atom_list, 2);680}681682/* mwm hints */683atom_set = XInternAtom(splash->display, "_MOTIF_WM_HINTS", True);684if (atom_set != None) {685/* flags for decoration and functions */686mwm_hints.flags = (1L << 1) | (1L << 0);687mwm_hints.decorations = 0;688mwm_hints.functions = 0;689XChangeProperty(splash->display, splash->window, atom_set, atom_set,69032, PropModeReplace, (unsigned char *) &mwm_hints, 5);691}692693/* olwm hints */694atom_set = XInternAtom(splash->display, "_OL_DECOR_DEL", True);695if (atom_set != None) {696atom_list[0] = XInternAtom(splash->display, "_OL_DECOR_RESIZE", True);697atom_list[1] = XInternAtom(splash->display, "_OL_DECOR_HEADER", True);698atom_list[2] = XInternAtom(splash->display, "_OL_DECOR_PIN", True);699atom_list[3] = XInternAtom(splash->display, "_OL_DECOR_CLOSE", True);700XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,701PropModeReplace, (unsigned char *) atom_list, 4);702}703704/* generic EMWH hints705we do not set _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_SPLASH706hint support due to gnome making this window always-on-top707so we have to set _NET_WM_STATE and _NET_WM_ALLOWED_ACTIONS correctly708_NET_WM_STATE: SKIP_TASKBAR and SKIP_PAGER709_NET_WM_ALLOWED_ACTIONS: disable all actions */710atom_set = XInternAtom(splash->display, "_NET_WM_STATE", True);711if (atom_set != None) {712atom_list[0] = XInternAtom(splash->display,713"_NET_WM_STATE_SKIP_TASKBAR", True);714atom_list[1] = XInternAtom(splash->display,715"_NET_WM_STATE_SKIP_PAGER", True);716XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,717PropModeReplace, (unsigned char *) atom_list, 2);718}719atom_set = XInternAtom(splash->display, "_NET_WM_ALLOWED_ACTIONS", True);720if (atom_set != None) {721XChangeProperty(splash->display, splash->window, atom_set, XA_ATOM, 32,722PropModeReplace, (unsigned char *) atom_list, 0);723}724}725726void727SplashPThreadDestructor(void *arg) {728/* this will be used in case of emergency thread exit on xlib error */729Splash *splash = (Splash *) arg;730731if (splash) {732SplashCleanup(splash);733}734}735736void *737SplashScreenThread(void *param) {738Splash *splash = (Splash *) param;739// pthread_key_t key;740741// pthread_key_create(&key, SplashPThreadDestructor);742// pthread_setspecific(key, splash);743744SplashLock(splash);745pipe(splash->controlpipe);746fcntl(splash->controlpipe[0], F_SETFL,747fcntl(splash->controlpipe[0], F_GETFL, 0) | O_NONBLOCK);748splash->time = SplashTime();749SplashCreateWindow(splash);750fflush(stdout);751if (splash->window) {752SplashRemoveDecoration(splash);753XStoreName(splash->display, splash->window, "Java");754XMapRaised(splash->display, splash->window);755SplashUpdateShape(splash);756SplashRedrawWindow(splash);757//map the splash co-ordinates as per system scale758splash->x /= splash->scaleFactor;759splash->y /= splash->scaleFactor;760SplashEventLoop(splash);761}762SplashUnlock(splash);763SplashDone(splash);764765splash->isVisible=-1;766return 0;767}768769void770SplashCreateThread(Splash * splash) {771pthread_t thr;772pthread_attr_t attr;773int rc;774775pthread_attr_init(&attr);776rc = pthread_create(&thr, &attr, SplashScreenThread, (void *) splash);777}778779void780SplashLock(Splash * splash) {781pthread_mutex_lock(&splash->lock);782}783784void785SplashUnlock(Splash * splash) {786pthread_mutex_unlock(&splash->lock);787}788789void790SplashClosePlatform(Splash * splash) {791sendctl(splash, SPLASHCTL_QUIT);792}793794void795SplashUpdate(Splash * splash) {796sendctl(splash, SPLASHCTL_UPDATE);797}798799void800SplashReconfigure(Splash * splash) {801sendctl(splash, SPLASHCTL_RECONFIGURE);802}803804JNIEXPORT jboolean805SplashGetScaledImageName(const char* jarName, const char* fileName,806float *scaleFactor, char *scaledImgName,807const size_t scaledImageNameLength)808{809*scaleFactor = 1;810#ifndef __linux__811return JNI_FALSE;812#endif813*scaleFactor = (float)getNativeScaleFactor();814return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength);815}816817818819