static LRESULT CALLBACK SplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_ERASEBKGND: return TRUE; // to avoid flicker case WM_SYSCOMMAND: if (wParam==SC_CLOSE||wParam==SC_DEFAULT||wParam==SC_HOTKEY|| wParam==SC_KEYMENU||wParam==SC_MAXIMIZE|| wParam==SC_MINIMIZE||wParam==SC_MOUSEMENU||wParam==SC_MOVE|| wParam==SC_RESTORE||wParam==SC_SIZE) { return 0; } /* double switch to avoid prologue/epilogue duplication */ case WM_TIMER: case WM_SPLASHUPDATE: case WM_PAINT: case WM_SPLASHRECONFIGURE: { Splash *splash = (Splash *) GetWindowLongPtr(hWnd, GWLP_USERDATA); SplashLock(splash); if (splash->isVisible>0) { switch(message) { case WM_TIMER: SplashNextFrame(splash); SplashRedrawWindow(splash); break; case WM_SPLASHUPDATE: SplashRedrawWindow(splash); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); SplashPaint(splash, hdc); EndPaint(hWnd, &ps); break; case WM_SPLASHRECONFIGURE: SplashReconfigureNow(splash); break; } } SplashUnlock(splash); break; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
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; /* ... */ } } } } }