Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/awt/splashscreen/splashscreen_sys.c
32288 views
/*1* Copyright (c) 2005, 2014, 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// copy from awt.h26#ifndef _WIN32_WINNT27#define _WIN32_WINNT 0x060028#endif2930// copy from awt.h31#ifndef _WIN32_IE32#define _WIN32_IE 0x060033#endif3435#include "splashscreen_impl.h"36#include <windowsx.h>37#include <windows.h>38#include <winuser.h>39#include "sizecalc.h"4041#ifndef WS_EX_LAYERED42#define WS_EX_LAYERED 0x8000043#endif4445#ifndef ULW_ALPHA46#define ULW_ALPHA 0x0000000247#endif4849#ifndef AC_SRC_OVER50#define AC_SRC_OVER 0x0051#endif5253#ifndef AC_SRC_ALPHA54#define AC_SRC_ALPHA 0x0155#endif5657#define WM_SPLASHUPDATE WM_USER+158#define WM_SPLASHRECONFIGURE WM_USER+25960/* Could use npt but decided to cut down on linked code size */61char* SplashConvertStringAlloc(const char* in, int *size) {62int len, outChars, rc;63WCHAR* buf;64if (!in) {65return NULL;66}67len = strlen(in);68outChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, in, len,69NULL, 0);70buf = (WCHAR*) SAFE_SIZE_ARRAY_ALLOC(malloc, outChars, sizeof(WCHAR));71if (!buf) {72return NULL;73}74rc = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, in, len,75buf, outChars);76if (rc==0) {77free(buf);78return NULL;79} else {80if (size) {81*size = rc;82}83return (char*)buf;84}85}8687unsigned88SplashTime(void)89{90return GetTickCount();91}9293void94SplashInitFrameShape(Splash * splash, int imageIndex)95{96RGNDATA *pRgnData;97RGNDATAHEADER *pRgnHdr;98ImageRect maskRect;99100if (!splash->maskRequired)101return;102103/* reserving memory for the worst case */104if (!IS_SAFE_SIZE_MUL(splash->width / 2 + 1, splash->height)) {105return;106}107pRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(malloc, sizeof(RGNDATAHEADER),108sizeof(RECT), (splash->width / 2 + 1) * splash->height);109if (!pRgnData) {110return;111}112pRgnHdr = (RGNDATAHEADER *) pRgnData;113initRect(&maskRect, 0, 0, splash->width, splash->height, 1,114splash->width * splash->imageFormat.depthBytes,115splash->frames[imageIndex].bitmapBits, &splash->imageFormat);116117pRgnHdr->dwSize = sizeof(RGNDATAHEADER);118pRgnHdr->iType = RDH_RECTANGLES;119pRgnHdr->nRgnSize = 0;120pRgnHdr->rcBound.top = 0;121pRgnHdr->rcBound.left = 0;122pRgnHdr->rcBound.bottom = splash->height;123pRgnHdr->rcBound.right = splash->width;124125pRgnHdr->nCount = BitmapToYXBandedRectangles(&maskRect,126(RECT *) (((BYTE *) pRgnData) + sizeof(RGNDATAHEADER)));127128splash->frames[imageIndex].hRgn = ExtCreateRegion(NULL,129sizeof(RGNDATAHEADER) + sizeof(RECT) * pRgnHdr->nCount, pRgnData);130131free(pRgnData);132}133134/* paint current splash screen frame to hdc135this function is unused in layered window mode */136137void138SplashPaint(Splash * splash, HDC hdc)139{140unsigned numColors = splash->screenFormat.colorMap ?141splash->screenFormat.numColors : 0;142BITMAPV4HEADER *pBmi;143HPALETTE hOldPal = NULL;144145if (!splash->frames)146return;147if (splash->currentFrame < 0 || splash->currentFrame >= splash->frameCount)148return;149pBmi = (BITMAPV4HEADER *) SAFE_SIZE_STRUCT_ALLOC(alloca, sizeof(BITMAPV4HEADER),150sizeof(RGBQUAD), numColors);151if (!pBmi) {152return;153}154memset(pBmi, 0, sizeof(BITMAPV4HEADER));155if (splash->screenFormat.colorMap)156memcpy(((BYTE *) pBmi) + sizeof(BITMAPV4HEADER),157splash->screenFormat.colorMap, sizeof(RGBQUAD) * numColors);158159pBmi->bV4Size = sizeof(BITMAPV4HEADER);160pBmi->bV4Width = splash->width;161pBmi->bV4Height = -splash->height;162pBmi->bV4Planes = 1;163pBmi->bV4BitCount = (WORD) (splash->screenFormat.depthBytes * 8);164/* we're ALWAYS using BGRA in screenFormat */165pBmi->bV4V4Compression = BI_RGB;166pBmi->bV4ClrUsed = numColors;167pBmi->bV4ClrImportant = numColors;168pBmi->bV4AlphaMask = splash->screenFormat.mask[3];169pBmi->bV4RedMask = splash->screenFormat.mask[2];170pBmi->bV4GreenMask = splash->screenFormat.mask[1];171pBmi->bV4BlueMask = splash->screenFormat.mask[0];172173/* creating the palette in SplashInitPlatform does not work, so I'm creating it174here on demand */175if (!splash->hPalette) {176unsigned i;177LOGPALETTE *pLogPal = (LOGPALETTE *) SAFE_SIZE_STRUCT_ALLOC(malloc,178sizeof(LOGPALETTE), sizeof(PALETTEENTRY), numColors);179if (!pLogPal) {180return;181}182183pLogPal->palVersion = 0x300;184pLogPal->palNumEntries = (WORD) numColors;185for (i = 0; i < numColors; i++) {186pLogPal->palPalEntry[i].peRed = (BYTE)187QUAD_RED(splash->colorMap[i]);188pLogPal->palPalEntry[i].peGreen = (BYTE)189QUAD_GREEN(splash->colorMap[i]);190pLogPal->palPalEntry[i].peBlue = (BYTE)191QUAD_BLUE(splash->colorMap[i]);192pLogPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;193}194splash->hPalette = CreatePalette(pLogPal);195free(pLogPal);196}197if (splash->hPalette) {198hOldPal = SelectPalette(hdc, splash->hPalette, FALSE);199RealizePalette(hdc);200}201202StretchDIBits(hdc, 0, 0, splash->width, splash->height, 0, 0,203splash->width, splash->height, splash->screenData,204(BITMAPINFO *) pBmi, DIB_RGB_COLORS, SRCCOPY);205if (hOldPal)206SelectPalette(hdc, hOldPal, FALSE);207}208209210/* The function makes the window visible if it is hidden211or is not yet shown. */212void213SplashRedrawWindow(Splash * splash)214{215if (!SplashIsStillLooping(splash)) {216KillTimer(splash->hWnd, 0);217}218219if (splash->currentFrame < 0) {220return;221}222223SplashUpdateScreenData(splash);224if (splash->isLayered) {225BLENDFUNCTION bf;226POINT ptSrc;227HDC hdcSrc = CreateCompatibleDC(NULL), hdcDst;228BITMAPINFOHEADER bmi;229void *bitmapBits;230HBITMAP hBitmap, hOldBitmap;231RECT rect;232POINT ptDst;233SIZE size;234235bf.BlendOp = AC_SRC_OVER;236bf.BlendFlags = 0;237bf.AlphaFormat = AC_SRC_ALPHA;238bf.SourceConstantAlpha = 0xFF;239ptSrc.x = ptSrc.y = 0;240241memset(&bmi, 0, sizeof(bmi));242bmi.biSize = sizeof(BITMAPINFOHEADER);243bmi.biWidth = splash->width;244bmi.biHeight = -splash->height;245bmi.biPlanes = 1;246bmi.biBitCount = 32;247bmi.biCompression = BI_RGB;248249// FIXME: this is somewhat ineffective250// maybe if we allocate memory for all frames as DIBSections,251// then we could select the frames into the DC directly252253hBitmap = CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS,254&bitmapBits, NULL, 0);255memcpy(bitmapBits, splash->screenData,256splash->screenStride * splash->height);257hOldBitmap = (HBITMAP) SelectObject(hdcSrc, hBitmap);258hdcDst = GetDC(splash->hWnd);259260GetWindowRect(splash->hWnd, &rect);261262ptDst.x = rect.left;263ptDst.y = rect.top;264265size.cx = splash->width;266size.cy = splash->height;267268UpdateLayeredWindow(splash->hWnd, hdcDst, &ptDst, &size,269hdcSrc, &ptSrc, 0, &bf, ULW_ALPHA);270271ReleaseDC(splash->hWnd, hdcDst);272SelectObject(hdcSrc, hOldBitmap);273DeleteObject(hBitmap);274DeleteDC(hdcSrc);275}276else {277InvalidateRect(splash->hWnd, NULL, FALSE);278if (splash->maskRequired) {279HRGN hRgn = CreateRectRgn(0, 0, 0, 0);280281CombineRgn(hRgn, splash->frames[splash->currentFrame].hRgn,282splash->frames[splash->currentFrame].hRgn, RGN_COPY);283SetWindowRgn(splash->hWnd, hRgn, TRUE);284} else {285SetWindowRgn(splash->hWnd, NULL, TRUE);286}287UpdateWindow(splash->hWnd);288}289if (!IsWindowVisible(splash->hWnd)) {290POINT cursorPos;291ShowWindow(splash->hWnd, SW_SHOW);292// Windows won't update the cursor after the window is shown,293// if the cursor is already above the window. need to do this manually.294GetCursorPos(&cursorPos);295if (WindowFromPoint(cursorPos) == splash->hWnd) {296// unfortunately Windows fail to understand that the window297// thread should own the cursor, even though the mouse pointer298// is over the window, until the mouse has been moved.299// we're using SetCursorPos here to fake the mouse movement300// and enable proper update of the cursor.301SetCursorPos(cursorPos.x, cursorPos.y);302SetCursor(LoadCursor(NULL, IDC_WAIT));303}304}305if (SplashIsStillLooping(splash)) {306int time = splash->time +307splash->frames[splash->currentFrame].delay - SplashTime();308309if (time < 0)310time = 0;311SetTimer(splash->hWnd, 0, time, NULL);312}313}314315void SplashReconfigureNow(Splash * splash) {316splash->x = (GetSystemMetrics(SM_CXSCREEN) - splash->width) / 2;317splash->y = (GetSystemMetrics(SM_CYSCREEN) - splash->height) / 2;318if (splash->hWnd) {319//Fixed 6474657: splash screen image jumps towards left while320// setting the new image using setImageURL()321// We may safely hide the splash window because SplashRedrawWindow()322// will show the window again.323ShowWindow(splash->hWnd, SW_HIDE);324MoveWindow(splash->hWnd, splash->x, splash->y, splash->width, splash->height, FALSE);325}326SplashRedrawWindow(splash);327}328329static LRESULT CALLBACK330SplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)331{332PAINTSTRUCT ps;333HDC hdc;334335336switch (message) {337338case WM_ERASEBKGND:339return TRUE; // to avoid flicker340341case WM_SYSCOMMAND:342if (wParam==SC_CLOSE||wParam==SC_DEFAULT||wParam==SC_HOTKEY||343wParam==SC_KEYMENU||wParam==SC_MAXIMIZE||344wParam==SC_MINIMIZE||wParam==SC_MOUSEMENU||wParam==SC_MOVE||345wParam==SC_RESTORE||wParam==SC_SIZE)346{347return 0;348}349350/* double switch to avoid prologue/epilogue duplication */351case WM_TIMER:352case WM_SPLASHUPDATE:353case WM_PAINT:354case WM_SPLASHRECONFIGURE:355{356Splash *splash = (Splash *) GetWindowLongPtr(hWnd, GWLP_USERDATA);357358SplashLock(splash);359if (splash->isVisible>0) {360switch(message) {361case WM_TIMER:362SplashNextFrame(splash);363SplashRedrawWindow(splash);364break;365case WM_SPLASHUPDATE:366SplashRedrawWindow(splash);367break;368case WM_PAINT:369hdc = BeginPaint(hWnd, &ps);370SplashPaint(splash, hdc);371EndPaint(hWnd, &ps);372break;373case WM_SPLASHRECONFIGURE:374SplashReconfigureNow(splash);375break;376}377}378SplashUnlock(splash);379break;380}381case WM_DESTROY:382PostQuitMessage(0);383break;384default:385return DefWindowProc(hWnd, message, wParam, lParam);386387}388return 0;389}390391HWND392SplashCreateWindow(Splash * splash)393{394WNDCLASSEX wcex;395ATOM wndClass;396DWORD style, exStyle;397HWND hWnd;398399ZeroMemory(&wcex, sizeof(WNDCLASSEX));400401wcex.cbSize = sizeof(WNDCLASSEX);402wcex.style = CS_HREDRAW | CS_VREDRAW;403wcex.lpfnWndProc = (WNDPROC) SplashWndProc;404wcex.hInstance = GetModuleHandle(NULL);405wcex.lpszClassName = "JavaSplash";406wcex.hCursor = LoadCursor(NULL, IDC_WAIT);407408wndClass = RegisterClassEx(&wcex);409if (!wndClass) {410return 0;411}412413splash->x = (GetSystemMetrics(SM_CXSCREEN) - splash->width) / 2;414splash->y = (GetSystemMetrics(SM_CYSCREEN) - splash->height) / 2;415exStyle = splash->isLayered ? WS_EX_LAYERED : 0;416exStyle |= WS_EX_TOOLWINDOW; /* don't show the window on taskbar */417style = WS_POPUP;418hWnd = CreateWindowEx(exStyle, (LPCSTR) wndClass, "", style,419splash->x, splash->y, splash->width, splash->height, NULL, NULL,420wcex.hInstance, NULL);421SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) splash);422return hWnd;423}424425void426SplashLock(Splash * splash)427{428EnterCriticalSection(&splash->lock);429}430431void432SplashUnlock(Splash * splash)433{434LeaveCriticalSection(&splash->lock);435}436437void438SplashInitPlatform(Splash * splash)439{440HDC hdc;441int paletteMode;442443InitializeCriticalSection(&splash->lock);444splash->isLayered = FALSE;445hdc = GetDC(NULL);446paletteMode = (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) != 0;447if (UpdateLayeredWindow && !paletteMode) {448splash->isLayered = TRUE;449}450splash->byteAlignment = 4;451if (splash->isLayered) {452initFormat(&splash->screenFormat,4530x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);454splash->screenFormat.premultiplied = 1;455splash->maskRequired = 0;456}457else {458splash->maskRequired = 1;459if (paletteMode) {460int numColors = GetDeviceCaps(hdc, SIZEPALETTE) -461GetDeviceCaps(hdc, NUMRESERVED);462int i;463int numComponents[3];464465initFormat(&splash->screenFormat, 0, 0, 0, 0);466/* FIXME: maybe remapping to non-reserved colors would improve performance */467for (i = 0; i < numColors; i++) {468splash->colorIndex[i] = i;469}470numColors = quantizeColors(numColors, numComponents);471initColorCube(numComponents, splash->colorMap, splash->dithers,472splash->colorIndex);473splash->screenFormat.colorIndex = splash->colorIndex;474splash->screenFormat.depthBytes = 1;475splash->screenFormat.colorMap = splash->colorMap;476splash->screenFormat.dithers = splash->dithers;477splash->screenFormat.numColors = numColors;478splash->hPalette = NULL;479}480else {481initFormat(&splash->screenFormat,4820x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);483}484}485ReleaseDC(NULL, hdc);486}487488void489SplashCleanupPlatform(Splash * splash)490{491int i;492493if (splash->frames) {494for (i = 0; i < splash->frameCount; i++) {495if (splash->frames[i].hRgn) {496DeleteObject(splash->frames[i].hRgn);497splash->frames[i].hRgn = NULL;498}499}500}501if (splash->hPalette)502DeleteObject(splash->hPalette);503splash->maskRequired = !splash->isLayered;504}505506void507SplashDonePlatform(Splash * splash)508{509if (splash->hWnd)510DestroyWindow(splash->hWnd);511}512513void514SplashMessagePump()515{516MSG msg;517518while (GetMessage(&msg, NULL, 0, 0)) {519TranslateMessage(&msg);520DispatchMessage(&msg);521}522}523524DWORD WINAPI525SplashScreenThread(LPVOID param)526{527Splash *splash = (Splash *) param;528529splash->currentFrame = 0;530SplashLock(splash);531splash->time = SplashTime();532splash->hWnd = SplashCreateWindow(splash);533if (splash->hWnd) {534SplashRedrawWindow(splash);535SplashUnlock(splash);536SplashMessagePump();537SplashLock(splash);538}539SplashDone(splash);540splash->isVisible = -1;541SplashUnlock(splash);542return 0;543}544545void546SplashCreateThread(Splash * splash)547{548DWORD threadId;549550CreateThread(NULL, 0, SplashScreenThread, (LPVOID) splash, 0, &threadId);551}552553void554SplashClosePlatform(Splash * splash)555{556PostMessage(splash->hWnd, WM_QUIT, 0, 0);557}558559void560SplashUpdate(Splash * splash)561{562PostMessage(splash->hWnd, WM_SPLASHUPDATE, 0, 0);563}564565void566SplashReconfigure(Splash * splash)567{568PostMessage(splash->hWnd, WM_SPLASHRECONFIGURE, 0, 0);569}570571SPLASHEXPORT char*572SplashGetScaledImageName(const char* jarName, const char* fileName,573float *scaleFactor)574{575*scaleFactor = 1;576return NULL;577}578579580