From 725697e1f7fec77c4443b8ab77ac5b496a2b5fee Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 3 Jul 2007 09:05:51 +0000 Subject: [PATCH] Fixed bug #335 Use SetSystemPaletteUse() to get better access to the system palette. We can still do better palette matching in the case where we aren't using fullscreen mode or a hardware palette, but that can wait for another day. :) --- src/video/wincommon/SDL_lowvideo.h | 3 + src/video/wincommon/SDL_sysevents.c | 25 ++-- src/video/windib/SDL_dibvideo.c | 186 ++++++++++++++++++++-------- src/video/windib/SDL_dibvideo.h | 2 + src/video/windx5/SDL_dx5video.c | 5 + 5 files changed, 158 insertions(+), 63 deletions(-) diff --git a/src/video/wincommon/SDL_lowvideo.h b/src/video/wincommon/SDL_lowvideo.h index f8ea258fa..96ea1459a 100644 --- a/src/video/wincommon/SDL_lowvideo.h +++ b/src/video/wincommon/SDL_lowvideo.h @@ -84,6 +84,9 @@ extern BOOL SDL_windowid; */ extern void WIN_FlushMessageQueue(); +/* Called by windows message loop when application is activated */ +extern void (*WIN_Activate)(_THIS, BOOL active, BOOL minimized); + /* Called by windows message loop when system palette is available */ extern void (*WIN_RealizePalette)(_THIS); diff --git a/src/video/wincommon/SDL_sysevents.c b/src/video/wincommon/SDL_sysevents.c index f5d4d1c33..1dc9bdb29 100644 --- a/src/video/wincommon/SDL_sysevents.c +++ b/src/video/wincommon/SDL_sysevents.c @@ -84,6 +84,7 @@ WORD *gamma_saved = NULL; /* Functions called by the message processing function */ LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)=NULL; +void (*WIN_Activate)(_THIS, BOOL active, BOOL iconic); void (*WIN_RealizePalette)(_THIS); void (*WIN_PaletteChanged)(_THIS, HWND window); void (*WIN_WinPAINT)(_THIS, HDC hdc); @@ -348,11 +349,12 @@ LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_ACTIVATE: { SDL_VideoDevice *this = current_video; - BOOL minimized; + BOOL active, minimized; Uint8 appstate; minimized = HIWORD(wParam); - if ( !minimized && (LOWORD(wParam) != WA_INACTIVE) ) { + active = (LOWORD(wParam) != WA_INACTIVE) && !minimized; + if ( active ) { /* Gain the following states */ appstate = SDL_APPACTIVE|SDL_APPINPUTFOCUS; if ( this->input_grab != SDL_GRAB_OFF ) { @@ -367,17 +369,14 @@ LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } } #if defined(_WIN32_WCE) - if ( WINDIB_FULLSCREEN() ) - { - LoadAygshell(); - if( SHFullScreen ) - SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON); - else - ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE); - - } + if ( WINDIB_FULLSCREEN() ) { + LoadAygshell(); + if( SHFullScreen ) + SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON); + else + ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE); + } #endif - posted = SDL_PrivateAppActive(1, appstate); WIN_GetKeyboardState(); } else { @@ -401,12 +400,12 @@ LRESULT CALLBACK WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SHFullScreen(SDL_Window, SHFS_SHOWSTARTICON|SHFS_SHOWTASKBAR|SHFS_SHOWSIPBUTTON); else ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_SHOW); - #endif } } posted = SDL_PrivateAppActive(0, appstate); } + WIN_Activate(this, active, minimized); return(0); } break; diff --git a/src/video/windib/SDL_dibvideo.c b/src/video/windib/SDL_dibvideo.c index 82b41d99a..285a83547 100644 --- a/src/video/windib/SDL_dibvideo.c +++ b/src/video/windib/SDL_dibvideo.c @@ -87,6 +87,9 @@ static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface); static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface); /* Windows message handling functions */ +static void DIB_GrabStaticColors(HWND window); +static void DIB_ReleaseStaticColors(HWND window); +static void DIB_Activate(_THIS, BOOL active, BOOL minimized); static void DIB_RealizePalette(_THIS); static void DIB_PaletteChanged(_THIS, HWND window); static void DIB_WinPAINT(_THIS, HDC hdc); @@ -176,6 +179,7 @@ static SDL_VideoDevice *DIB_CreateDevice(int devindex) device->PumpEvents = DIB_PumpEvents; /* Set up the windows message handling functions */ + WIN_Activate = DIB_Activate; WIN_RealizePalette = DIB_RealizePalette; WIN_PaletteChanged = DIB_PaletteChanged; WIN_WinPAINT = DIB_WinPAINT; @@ -248,36 +252,25 @@ static int DIB_AddMode(_THIS, int bpp, int w, int h) return(0); } -static HPALETTE DIB_CreatePalette(int bpp) +static void DIB_CreatePalette(_THIS, int bpp) { /* RJR: March 28, 2000 moved palette creation here from "DIB_VideoInit" */ - HPALETTE handle = NULL; - - if ( bpp <= 8 ) - { - LOGPALETTE *palette; - HDC hdc; - int ncolors; - int i; + LOGPALETTE *palette; + HDC hdc; + int ncolors; - ncolors = 1; - for ( i=0; ipalVersion = 0x300; - palette->palNumEntries = ncolors; - hdc = GetDC(SDL_Window); - GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry); - ReleaseDC(SDL_Window, hdc); - handle = CreatePalette(palette); - SDL_free(palette); - } - - return handle; + ncolors = (1 << bpp); + palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+ + ncolors*sizeof(PALETTEENTRY)); + palette->palVersion = 0x300; + palette->palNumEntries = ncolors; + hdc = GetDC(SDL_Window); + GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry); + ReleaseDC(SDL_Window, hdc); + screen_pal = CreatePalette(palette); + screen_logpal = palette; } int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat) @@ -371,7 +364,7 @@ int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat) if ( vformat->BitsPerPixel <= 8 ) { /* RJR: March 28, 2000 moved palette creation to "DIB_CreatePalette" */ - screen_pal = DIB_CreatePalette(vformat->BitsPerPixel); + DIB_CreatePalette(this, vformat->BitsPerPixel); } /* Fill in some window manager capabilities */ @@ -645,16 +638,23 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, /* Reset the palette and create a new one if necessary */ if ( screen_pal != NULL ) { + if ( video->flags & SDL_HWPALETTE ) { + DIB_ReleaseStaticColors(SDL_Window); + } /* RJR: March 28, 2000 delete identity palette if switching from a palettized mode */ DeleteObject(screen_pal); screen_pal = NULL; } + if ( screen_logpal != NULL ) { + SDL_free(screen_logpal); + screen_logpal = NULL; + } if ( bpp <= 8 ) { /* RJR: March 28, 2000 create identity palette switching to a palettized mode */ - screen_pal = DIB_CreatePalette(bpp); + DIB_CreatePalette(this, bpp); } style = GetWindowLong(SDL_Window, GWL_STYLE); @@ -755,12 +755,7 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, this->UpdateRects = DIB_NormalUpdate; /* Set video surface flags */ - if ( bpp <= 8 ) { - if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { - hdc = GetDC(SDL_Window); - SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); - ReleaseDC(SDL_Window, hdc); - } + if ( (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) != 0 ) { /* BitBlt() maps colors for us */ video->flags |= SDL_HWPALETTE; } @@ -885,6 +880,41 @@ static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) ReleaseDC(SDL_Window, hdc); } +static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b) +{ + PALETTEENTRY *entry; + int i; + int nentries = pal->palNumEntries; + + for ( i = 0; i < nentries; ++i ) { + entry = &pal->palPalEntry[i]; + if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) { + return i; + } + } + return -1; +} + +static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b) +{ + PALETTEENTRY *entry; + BOOL moved = 0; + + entry = &pal->palPalEntry[index]; + if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) { + int found = FindPaletteIndex(pal, r, g, b); + if ( found >= 0 ) { + pal->palPalEntry[found] = *entry; + } + entry->peRed = r; + entry->peGreen = g; + entry->peBlue = b; + moved = 1; + } + entry->peFlags = 0; + + return moved; +} int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) { @@ -895,23 +925,37 @@ int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) HDC hdc; #endif int i; + int moved_entries = 0; /* Update the display palette */ hdc = GetDC(SDL_Window); if ( screen_pal ) { - PALETTEENTRY *entries; + PALETTEENTRY *entry; - entries = SDL_stack_alloc(PALETTEENTRY, ncolors); for ( i=0; ipalPalEntry[firstcolor+i]; + entry->peRed = colors[i].r; + entry->peGreen = colors[i].g; + entry->peBlue = colors[i].b; + entry->peFlags = PC_NOCOLLAPSE; + } + /* Check to make sure black and white are in position */ + if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { + moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00); + moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff); } - SetPaletteEntries(screen_pal, firstcolor, ncolors, entries); + /* FIXME: + If we don't have full access to the palette, what we + really want to do is find the 236 most diverse colors + in the desired palette, set those entries (10-245) and + then map everything into the new system palette. + */ + + /* Copy the entries into the system palette */ + UnrealizeObject(screen_pal); + SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry); SelectPalette(hdc, screen_pal, FALSE); RealizePalette(hdc); - SDL_stack_free(entries); } #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400) @@ -928,8 +972,10 @@ int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) mdc = CreateCompatibleDC(hdc); SelectObject(mdc, screen_bmp); SetDIBColorTable(mdc, firstcolor, ncolors, pal); - BitBlt(hdc, 0, 0, this->screen->w, this->screen->h, - mdc, 0, 0, SRCCOPY); + if ( moved_entries || !(this->screen->flags & SDL_HWPALETTE) ) { + BitBlt(hdc, 0, 0, this->screen->w, this->screen->h, + mdc, 0, 0, SRCCOPY); + } DeleteDC(mdc); SDL_stack_free(pal); #endif @@ -1048,6 +1094,9 @@ void DIB_VideoQuit(_THIS) if ( SDL_Window ) { /* Delete the screen bitmap (also frees screen->pixels) */ if ( this->screen ) { + if ( this->screen->flags & SDL_HWPALETTE ) { + DIB_ReleaseStaticColors(SDL_Window); + } #ifndef NO_CHANGEDISPLAYSETTINGS if ( this->screen->flags & SDL_FULLSCREEN ) { ChangeDisplaySettings(NULL, 0); @@ -1059,6 +1108,14 @@ void DIB_VideoQuit(_THIS) } this->screen->pixels = NULL; } + if ( screen_pal != NULL ) { + DeleteObject(screen_pal); + screen_pal = NULL; + } + if ( screen_logpal != NULL ) { + SDL_free(screen_logpal); + screen_logpal = NULL; + } if ( screen_bmp ) { DeleteObject(screen_bmp); screen_bmp = NULL; @@ -1097,26 +1154,55 @@ void DIB_VideoQuit(_THIS) } /* Exported for the windows message loop only */ -static void DIB_FocusPalette(_THIS, int foreground) +static void DIB_GrabStaticColors(HWND window) +{ + HDC hdc; + + hdc = GetDC(window); + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256); + if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) { + SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC); + } + ReleaseDC(window, hdc); +} +static void DIB_ReleaseStaticColors(HWND window) +{ + HDC hdc; + + hdc = GetDC(window); + SetSystemPaletteUse(hdc, SYSPAL_STATIC); + ReleaseDC(window, hdc); +} +static void DIB_Activate(_THIS, BOOL active, BOOL minimized) +{ + if ( screen_pal && (this->screen->flags & SDL_HWPALETTE) ) { + if ( !active ) { + DIB_ReleaseStaticColors(SDL_Window); + DIB_RealizePalette(this); + } else if ( !minimized ) { + DIB_GrabStaticColors(SDL_Window); + DIB_RealizePalette(this); + } + } +} +static void DIB_RealizePalette(_THIS) { if ( screen_pal != NULL ) { HDC hdc; hdc = GetDC(SDL_Window); + UnrealizeObject(screen_pal); SelectPalette(hdc, screen_pal, FALSE); - if ( RealizePalette(hdc) ) + if ( RealizePalette(hdc) ) { InvalidateRect(SDL_Window, NULL, FALSE); + } ReleaseDC(SDL_Window, hdc); } } -static void DIB_RealizePalette(_THIS) -{ - DIB_FocusPalette(this, 1); -} static void DIB_PaletteChanged(_THIS, HWND window) { if ( window != SDL_Window ) { - DIB_FocusPalette(this, 0); + DIB_RealizePalette(this); } } diff --git a/src/video/windib/SDL_dibvideo.h b/src/video/windib/SDL_dibvideo.h index 695ef33c0..efc6ebc8b 100644 --- a/src/video/windib/SDL_dibvideo.h +++ b/src/video/windib/SDL_dibvideo.h @@ -40,6 +40,7 @@ typedef enum struct SDL_PrivateVideoData { HBITMAP screen_bmp; HPALETTE screen_pal; + LOGPALETTE *screen_logpal; int allow_screensaver; @@ -58,6 +59,7 @@ struct SDL_PrivateVideoData { /* Old variable names */ #define screen_bmp (this->hidden->screen_bmp) #define screen_pal (this->hidden->screen_pal) +#define screen_logpal (this->hidden->screen_logpal) #define SDL_nummodes (this->hidden->SDL_nummodes) #define SDL_modelist (this->hidden->SDL_modelist) diff --git a/src/video/windx5/SDL_dx5video.c b/src/video/windx5/SDL_dx5video.c index e304bd5f9..aae58be62 100644 --- a/src/video/windx5/SDL_dx5video.c +++ b/src/video/windx5/SDL_dx5video.c @@ -427,6 +427,7 @@ static int DX5_AllocDDSurface(_THIS, SDL_Surface *surface, LPDIRECTDRAWSURFACE3 requested, Uint32 flag); /* Windows message handling functions */ +static void DX5_Activate(_THIS, BOOL active, BOOL minimized); static void DX5_RealizePalette(_THIS); static void DX5_PaletteChanged(_THIS, HWND window); static void DX5_WinPAINT(_THIS, HDC hdc); @@ -620,6 +621,7 @@ static SDL_VideoDevice *DX5_CreateDevice(int devindex) device->PumpEvents = DX5_PumpEvents; /* Set up the windows message handling functions */ + WIN_Activate = DX5_Activate; WIN_RealizePalette = DX5_RealizePalette; WIN_PaletteChanged = DX5_PaletteChanged; WIN_WinPAINT = DX5_WinPAINT; @@ -2421,6 +2423,9 @@ void DX5_VideoQuit(_THIS) } /* Exported for the windows message loop only */ +void DX5_Activate(_THIS, BOOL active, BOOL minimized) +{ +} void DX5_RealizePalette(_THIS) { if ( SDL_palette ) {