void * SplashScreenThread(void *param) { Splash *splash = (Splash *) param; // pthread_key_t key; // pthread_key_create(&key, SplashPThreadDestructor); // pthread_setspecific(key, splash); SplashLock(splash); pipe(splash->controlpipe); fcntl(splash->controlpipe[0], F_SETFL, fcntl(splash->controlpipe[0], F_GETFL, 0) | O_NONBLOCK); splash->time = SplashTime(); SplashCreateWindow(splash); fflush(stdout); if (splash->window) { SplashRemoveDecoration(splash); XStoreName(splash->display, splash->window, "Java"); XMapRaised(splash->display, splash->window); SplashUpdateShape(splash); SplashRedrawWindow(splash); SplashEventLoop(splash); } SplashUnlock(splash); SplashDone(splash); splash->isVisible=-1; return 0; }
static int SplashLoadStream(SplashStream * stream) { int success = 0; int c; size_t i; Splash *splash = SplashGetInstance(); if (splash->isVisible < 0) { return 0; } SplashLock(splash); /* the formats we support can be easily distinguished by the first byte */ c = stream->peek(stream); if (c != -1) { for (i = 0; i < sizeof(formats) / sizeof(FILEFORMAT); i++) { if (c == formats[i].sign) { success = formats[i].decodeStream(splash, stream); break; } } } stream->close(stream); if (!success) { // failed to decode if (splash->isVisible == 0) { SplashCleanup(splash); } SplashUnlock(splash); // SplashClose locks if (splash->isVisible == 0) { SplashClose(); } } else { splash->currentFrame = 0; if (splash->isVisible == 0) { SplashStart(splash); } else { SplashReconfigure(splash); splash->time = SplashTime(); } SplashUnlock(splash); } return success; }
DWORD WINAPI SplashScreenThread(LPVOID param) { Splash *splash = (Splash *) param; splash->currentFrame = 0; SplashLock(splash); splash->time = SplashTime(); splash->hWnd = SplashCreateWindow(splash); if (splash->hWnd) { SplashRedrawWindow(splash); SplashUnlock(splash); SplashMessagePump(); SplashLock(splash); } SplashDone(splash); splash->isVisible = -1; SplashUnlock(splash); return 0; }
void SplashNextFrame(Splash * splash) { if (splash->currentFrame < 0) { return; } do { if (!SplashIsStillLooping(splash)) { return; } splash->time += splash->frames[splash->currentFrame].delay; if (++splash->currentFrame >= splash->frameCount) { splash->currentFrame = 0; if (splash->loopCount > 0) { splash->loopCount--; } } } while (splash->time + splash->frames[splash->currentFrame].delay - SplashTime() <= 0); }
/* The function makes the window visible if it is hidden or is not yet shown. */ void SplashRedrawWindow(Splash * splash) { if (!SplashIsStillLooping(splash)) { KillTimer(splash->hWnd, 0); } if (splash->currentFrame < 0) { return; } SplashUpdateScreenData(splash); if (splash->isLayered) { BLENDFUNCTION bf; POINT ptSrc; HDC hdcSrc = CreateCompatibleDC(NULL), hdcDst; BITMAPINFOHEADER bmi; void *bitmapBits; HBITMAP hBitmap, hOldBitmap; RECT rect; POINT ptDst; SIZE size; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.AlphaFormat = AC_SRC_ALPHA; bf.SourceConstantAlpha = 0xFF; ptSrc.x = ptSrc.y = 0; memset(&bmi, 0, sizeof(bmi)); bmi.biSize = sizeof(BITMAPINFOHEADER); bmi.biWidth = splash->width; bmi.biHeight = -splash->height; bmi.biPlanes = 1; bmi.biBitCount = 32; bmi.biCompression = BI_RGB; // FIXME: this is somewhat ineffective // maybe if we allocate memory for all frames as DIBSections, // then we could select the frames into the DC directly hBitmap = CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS, &bitmapBits, NULL, 0); memcpy(bitmapBits, splash->screenData, splash->screenStride * splash->height); hOldBitmap = (HBITMAP) SelectObject(hdcSrc, hBitmap); hdcDst = GetDC(splash->hWnd); GetWindowRect(splash->hWnd, &rect); ptDst.x = rect.left; ptDst.y = rect.top; size.cx = splash->width; size.cy = splash->height; UpdateLayeredWindow(splash->hWnd, hdcDst, &ptDst, &size, hdcSrc, &ptSrc, 0, &bf, ULW_ALPHA); ReleaseDC(splash->hWnd, hdcDst); SelectObject(hdcSrc, hOldBitmap); DeleteObject(hBitmap); DeleteDC(hdcSrc); } else { InvalidateRect(splash->hWnd, NULL, FALSE); if (splash->maskRequired) { HRGN hRgn = CreateRectRgn(0, 0, 0, 0); CombineRgn(hRgn, splash->frames[splash->currentFrame].hRgn, splash->frames[splash->currentFrame].hRgn, RGN_COPY); SetWindowRgn(splash->hWnd, hRgn, TRUE); } else { SetWindowRgn(splash->hWnd, NULL, TRUE); } UpdateWindow(splash->hWnd); } if (!IsWindowVisible(splash->hWnd)) { POINT cursorPos; ShowWindow(splash->hWnd, SW_SHOW); // Windows won't update the cursor after the window is shown, // if the cursor is already above the window. need to do this manually. GetCursorPos(&cursorPos); if (WindowFromPoint(cursorPos) == splash->hWnd) { // unfortunately Windows fail to understand that the window // thread should own the cursor, even though the mouse pointer // is over the window, until the mouse has been moved. // we're using SetCursorPos here to fake the mouse movement // and enable proper update of the cursor. SetCursorPos(cursorPos.x, cursorPos.y); SetCursor(LoadCursor(NULL, IDC_WAIT)); } } if (SplashIsStillLooping(splash)) { int time = splash->time + splash->frames[splash->currentFrame].delay - SplashTime(); if (time < 0) time = 0; SetTimer(splash->hWnd, 0, time, NULL); } }
void SplashEventLoop(Splash * splash) { /* Different from win32 implementation - this loop uses poll timeouts instead of a timer */ /* we should have splash _locked_ on entry!!! */ int xconn = XConnectionNumber(splash->display); while (1) { struct pollfd pfd[2]; int timeout = -1; int ctl = splash->controlpipe[0]; int rc; int pipes_empty; pfd[0].fd = xconn; pfd[0].events = POLLIN | POLLPRI; pfd[1].fd = ctl; pfd[1].events = POLLIN | POLLPRI; errno = 0; if (splash->isVisible>0 && SplashIsStillLooping(splash)) { timeout = splash->time + splash->frames[splash->currentFrame].delay - SplashTime(); if (timeout < 0) { timeout = 0; } } SplashUnlock(splash); rc = poll(pfd, 2, timeout); SplashLock(splash); if (splash->isVisible>0 && SplashTime() >= splash->time + splash->frames[splash->currentFrame].delay) { SplashNextFrame(splash); SplashUpdateShape(splash); SplashRedrawWindow(splash); } if (rc <= 0) { errno = 0; continue; } pipes_empty = 0; while(!pipes_empty) { char buf; pipes_empty = 1; if (read(ctl, &buf, sizeof(buf)) > 0) { pipes_empty = 0; switch (buf) { case SPLASHCTL_UPDATE: if (splash->isVisible>0) { SplashRedrawWindow(splash); } break; case SPLASHCTL_RECONFIGURE: if (splash->isVisible>0) { SplashReconfigureNow(splash); } break; case SPLASHCTL_QUIT: return; } } // we're not using "while(XPending)", processing one event // at a time to avoid control pipe starvation if (XPending(splash->display)) { XEvent evt; pipes_empty = 0; XNextEvent(splash->display, &evt); switch (evt.type) { case Expose: if (splash->isVisible>0) { // we're doing full redraw so we just // skip the remaining painting events in the queue while(XCheckTypedEvent(splash->display, Expose, &evt)); SplashRedrawWindow(splash); } break; /* ... */ } } } } }