Fixed bug #335 SDL-1.2
authorSam Lantinga
Tue, 03 Jul 2007 09:05:51 +0000
branchSDL-1.2
changeset 3992c75679dce60c
parent 3991 7a649501c089
child 3993 8488d3c24dd5
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
src/video/wincommon/SDL_sysevents.c
src/video/windib/SDL_dibvideo.c
src/video/windib/SDL_dibvideo.h
src/video/windx5/SDL_dx5video.c
     1.1 --- a/src/video/wincommon/SDL_lowvideo.h	Mon Jul 02 02:45:52 2007 +0000
     1.2 +++ b/src/video/wincommon/SDL_lowvideo.h	Tue Jul 03 09:05:51 2007 +0000
     1.3 @@ -84,6 +84,9 @@
     1.4  */
     1.5  extern void WIN_FlushMessageQueue();
     1.6  
     1.7 +/* Called by windows message loop when application is activated */
     1.8 +extern void (*WIN_Activate)(_THIS, BOOL active, BOOL minimized);
     1.9 +
    1.10  /* Called by windows message loop when system palette is available */
    1.11  extern void (*WIN_RealizePalette)(_THIS);
    1.12  
     2.1 --- a/src/video/wincommon/SDL_sysevents.c	Mon Jul 02 02:45:52 2007 +0000
     2.2 +++ b/src/video/wincommon/SDL_sysevents.c	Tue Jul 03 09:05:51 2007 +0000
     2.3 @@ -84,6 +84,7 @@
     2.4  
     2.5  /* Functions called by the message processing function */
     2.6  LONG (*HandleMessage)(_THIS, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)=NULL;
     2.7 +void (*WIN_Activate)(_THIS, BOOL active, BOOL iconic);
     2.8  void (*WIN_RealizePalette)(_THIS);
     2.9  void (*WIN_PaletteChanged)(_THIS, HWND window);
    2.10  void (*WIN_WinPAINT)(_THIS, HDC hdc);
    2.11 @@ -348,11 +349,12 @@
    2.12  
    2.13  		case WM_ACTIVATE: {
    2.14  			SDL_VideoDevice *this = current_video;
    2.15 -			BOOL minimized;
    2.16 +			BOOL active, minimized;
    2.17  			Uint8 appstate;
    2.18  
    2.19  			minimized = HIWORD(wParam);
    2.20 -			if ( !minimized && (LOWORD(wParam) != WA_INACTIVE) ) {
    2.21 +			active = (LOWORD(wParam) != WA_INACTIVE) && !minimized;
    2.22 +			if ( active ) {
    2.23  				/* Gain the following states */
    2.24  				appstate = SDL_APPACTIVE|SDL_APPINPUTFOCUS;
    2.25  				if ( this->input_grab != SDL_GRAB_OFF ) {
    2.26 @@ -367,17 +369,14 @@
    2.27  					}
    2.28  				}
    2.29  #if defined(_WIN32_WCE)
    2.30 -			if ( WINDIB_FULLSCREEN() )
    2.31 -			{
    2.32 -						LoadAygshell();
    2.33 -						if( SHFullScreen )
    2.34 -							SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON);
    2.35 -						else
    2.36 -							ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE);
    2.37 -
    2.38 -			}
    2.39 +				if ( WINDIB_FULLSCREEN() ) {
    2.40 +					LoadAygshell();
    2.41 +					if( SHFullScreen )
    2.42 +						SHFullScreen(SDL_Window, SHFS_HIDESTARTICON|SHFS_HIDETASKBAR|SHFS_HIDESIPBUTTON);
    2.43 +					else
    2.44 +						ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_HIDE);
    2.45 +				}
    2.46  #endif
    2.47 -
    2.48  				posted = SDL_PrivateAppActive(1, appstate);
    2.49  				WIN_GetKeyboardState();
    2.50  			} else {
    2.51 @@ -401,12 +400,12 @@
    2.52  							SHFullScreen(SDL_Window, SHFS_SHOWSTARTICON|SHFS_SHOWTASKBAR|SHFS_SHOWSIPBUTTON);
    2.53  						else
    2.54  							ShowWindow(FindWindow(TEXT("HHTaskBar"),NULL),SW_SHOW);
    2.55 -
    2.56  #endif
    2.57  					}
    2.58  				}
    2.59  				posted = SDL_PrivateAppActive(0, appstate);
    2.60  			}
    2.61 +			WIN_Activate(this, active, minimized);
    2.62  			return(0);
    2.63  		}
    2.64  		break;
     3.1 --- a/src/video/windib/SDL_dibvideo.c	Mon Jul 02 02:45:52 2007 +0000
     3.2 +++ b/src/video/windib/SDL_dibvideo.c	Tue Jul 03 09:05:51 2007 +0000
     3.3 @@ -87,6 +87,9 @@
     3.4  static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface);
     3.5  
     3.6  /* Windows message handling functions */
     3.7 +static void DIB_GrabStaticColors(HWND window);
     3.8 +static void DIB_ReleaseStaticColors(HWND window);
     3.9 +static void DIB_Activate(_THIS, BOOL active, BOOL minimized);
    3.10  static void DIB_RealizePalette(_THIS);
    3.11  static void DIB_PaletteChanged(_THIS, HWND window);
    3.12  static void DIB_WinPAINT(_THIS, HDC hdc);
    3.13 @@ -176,6 +179,7 @@
    3.14  	device->PumpEvents = DIB_PumpEvents;
    3.15  
    3.16  	/* Set up the windows message handling functions */
    3.17 +	WIN_Activate = DIB_Activate;
    3.18  	WIN_RealizePalette = DIB_RealizePalette;
    3.19  	WIN_PaletteChanged = DIB_PaletteChanged;
    3.20  	WIN_WinPAINT = DIB_WinPAINT;
    3.21 @@ -248,36 +252,25 @@
    3.22  	return(0);
    3.23  }
    3.24  
    3.25 -static HPALETTE DIB_CreatePalette(int bpp)
    3.26 +static void DIB_CreatePalette(_THIS, int bpp)
    3.27  {
    3.28  /*	RJR: March 28, 2000
    3.29  	moved palette creation here from "DIB_VideoInit" */
    3.30  
    3.31 -	HPALETTE handle = NULL;
    3.32 -	
    3.33 -	if ( bpp <= 8 )
    3.34 -	{
    3.35 -		LOGPALETTE *palette;
    3.36 -		HDC hdc;
    3.37 -		int ncolors;
    3.38 -		int i;
    3.39 +	LOGPALETTE *palette;
    3.40 +	HDC hdc;
    3.41 +	int ncolors;
    3.42  
    3.43 -		ncolors = 1;
    3.44 -		for ( i=0; i<bpp; ++i ) {
    3.45 -			ncolors *= 2;
    3.46 -		}
    3.47 -		palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+
    3.48 -					ncolors*sizeof(PALETTEENTRY));
    3.49 -		palette->palVersion = 0x300;
    3.50 -		palette->palNumEntries = ncolors;
    3.51 -		hdc = GetDC(SDL_Window);
    3.52 -		GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry);
    3.53 -		ReleaseDC(SDL_Window, hdc);
    3.54 -		handle = CreatePalette(palette);
    3.55 -		SDL_free(palette);
    3.56 -	}
    3.57 -	
    3.58 -	return handle;
    3.59 +	ncolors = (1 << bpp);
    3.60 +	palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+
    3.61 +				ncolors*sizeof(PALETTEENTRY));
    3.62 +	palette->palVersion = 0x300;
    3.63 +	palette->palNumEntries = ncolors;
    3.64 +	hdc = GetDC(SDL_Window);
    3.65 +	GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry);
    3.66 +	ReleaseDC(SDL_Window, hdc);
    3.67 +	screen_pal = CreatePalette(palette);
    3.68 +	screen_logpal = palette;
    3.69  }
    3.70  
    3.71  int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat)
    3.72 @@ -371,7 +364,7 @@
    3.73  	if ( vformat->BitsPerPixel <= 8 ) {
    3.74  	/*	RJR: March 28, 2000
    3.75  		moved palette creation to "DIB_CreatePalette" */
    3.76 -		screen_pal = DIB_CreatePalette(vformat->BitsPerPixel);
    3.77 +		DIB_CreatePalette(this, vformat->BitsPerPixel);
    3.78  	}
    3.79  
    3.80  	/* Fill in some window manager capabilities */
    3.81 @@ -645,16 +638,23 @@
    3.82  
    3.83  	/* Reset the palette and create a new one if necessary */
    3.84  	if ( screen_pal != NULL ) {
    3.85 +		if ( video->flags & SDL_HWPALETTE ) {
    3.86 +			DIB_ReleaseStaticColors(SDL_Window);
    3.87 +		}
    3.88  	/*	RJR: March 28, 2000
    3.89  		delete identity palette if switching from a palettized mode */
    3.90  		DeleteObject(screen_pal);
    3.91  		screen_pal = NULL;
    3.92  	}
    3.93 +	if ( screen_logpal != NULL ) {
    3.94 +		SDL_free(screen_logpal);
    3.95 +		screen_logpal = NULL;
    3.96 +	}
    3.97  	if ( bpp <= 8 )
    3.98  	{
    3.99  	/*	RJR: March 28, 2000
   3.100  		create identity palette switching to a palettized mode */
   3.101 -		screen_pal = DIB_CreatePalette(bpp);
   3.102 +		DIB_CreatePalette(this, bpp);
   3.103  	}
   3.104  
   3.105  	style = GetWindowLong(SDL_Window, GWL_STYLE);
   3.106 @@ -755,12 +755,7 @@
   3.107  		this->UpdateRects = DIB_NormalUpdate;
   3.108  
   3.109  		/* Set video surface flags */
   3.110 -		if ( bpp <= 8 ) {
   3.111 -			if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
   3.112 -				hdc = GetDC(SDL_Window);
   3.113 -				SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
   3.114 -				ReleaseDC(SDL_Window, hdc);
   3.115 -			}
   3.116 +		if ( (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) != 0 ) {
   3.117  			/* BitBlt() maps colors for us */
   3.118  			video->flags |= SDL_HWPALETTE;
   3.119  		}
   3.120 @@ -885,6 +880,41 @@
   3.121  	ReleaseDC(SDL_Window, hdc);
   3.122  }
   3.123  
   3.124 +static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b)
   3.125 +{
   3.126 +	PALETTEENTRY *entry;
   3.127 +	int i;
   3.128 +	int nentries = pal->palNumEntries;
   3.129 +
   3.130 +	for ( i = 0; i < nentries; ++i ) {
   3.131 +		entry = &pal->palPalEntry[i];
   3.132 +		if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) {
   3.133 +			return i;
   3.134 +		}
   3.135 +	}
   3.136 +	return -1;
   3.137 +}
   3.138 +
   3.139 +static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b)
   3.140 +{
   3.141 +	PALETTEENTRY *entry;
   3.142 +	BOOL moved = 0;
   3.143 +
   3.144 +	entry = &pal->palPalEntry[index];
   3.145 +	if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) {
   3.146 +		int found = FindPaletteIndex(pal, r, g, b);
   3.147 +		if ( found >= 0 ) {
   3.148 +			pal->palPalEntry[found] = *entry;
   3.149 +		}
   3.150 +		entry->peRed = r;
   3.151 +		entry->peGreen = g;
   3.152 +		entry->peBlue = b;
   3.153 +		moved = 1;
   3.154 +	}
   3.155 +	entry->peFlags = 0;
   3.156 +
   3.157 +	return moved;
   3.158 +}
   3.159  
   3.160  int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   3.161  {
   3.162 @@ -895,23 +925,37 @@
   3.163  	HDC hdc;
   3.164  #endif
   3.165  	int i;
   3.166 +	int moved_entries = 0;
   3.167  
   3.168  	/* Update the display palette */
   3.169  	hdc = GetDC(SDL_Window);
   3.170  	if ( screen_pal ) {
   3.171 -		PALETTEENTRY *entries;
   3.172 +		PALETTEENTRY *entry;
   3.173  
   3.174 -		entries = SDL_stack_alloc(PALETTEENTRY, ncolors);
   3.175  		for ( i=0; i<ncolors; ++i ) {
   3.176 -			entries[i].peRed   = colors[i].r;
   3.177 -			entries[i].peGreen = colors[i].g;
   3.178 -			entries[i].peBlue  = colors[i].b;
   3.179 -			entries[i].peFlags = PC_NOCOLLAPSE;
   3.180 +			entry = &screen_logpal->palPalEntry[firstcolor+i];
   3.181 +			entry->peRed   = colors[i].r;
   3.182 +			entry->peGreen = colors[i].g;
   3.183 +			entry->peBlue  = colors[i].b;
   3.184 +			entry->peFlags = PC_NOCOLLAPSE;
   3.185 +		}
   3.186 +		/* Check to make sure black and white are in position */
   3.187 +		if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
   3.188 +			moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00);
   3.189 +			moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff);
   3.190  		}
   3.191 -		SetPaletteEntries(screen_pal, firstcolor, ncolors, entries);
   3.192 +		/* FIXME:
   3.193 +		   If we don't have full access to the palette, what we
   3.194 +		   really want to do is find the 236 most diverse colors
   3.195 +		   in the desired palette, set those entries (10-245) and
   3.196 +		   then map everything into the new system palette.
   3.197 +		 */
   3.198 +
   3.199 +		/* Copy the entries into the system palette */
   3.200 +		UnrealizeObject(screen_pal);
   3.201 +		SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry);
   3.202  		SelectPalette(hdc, screen_pal, FALSE);
   3.203  		RealizePalette(hdc);
   3.204 -		SDL_stack_free(entries);
   3.205  	}
   3.206  
   3.207  #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
   3.208 @@ -928,8 +972,10 @@
   3.209  	mdc = CreateCompatibleDC(hdc);
   3.210  	SelectObject(mdc, screen_bmp);
   3.211  	SetDIBColorTable(mdc, firstcolor, ncolors, pal);
   3.212 -	BitBlt(hdc, 0, 0, this->screen->w, this->screen->h,
   3.213 -	       mdc, 0, 0, SRCCOPY);
   3.214 +	if ( moved_entries || !(this->screen->flags & SDL_HWPALETTE) ) {
   3.215 +		BitBlt(hdc, 0, 0, this->screen->w, this->screen->h,
   3.216 +		       mdc, 0, 0, SRCCOPY);
   3.217 +	}
   3.218  	DeleteDC(mdc);
   3.219  	SDL_stack_free(pal);
   3.220  #endif
   3.221 @@ -1048,6 +1094,9 @@
   3.222  	if ( SDL_Window ) {
   3.223  		/* Delete the screen bitmap (also frees screen->pixels) */
   3.224  		if ( this->screen ) {
   3.225 +			if ( this->screen->flags & SDL_HWPALETTE ) {
   3.226 +				DIB_ReleaseStaticColors(SDL_Window);
   3.227 +			}
   3.228  #ifndef NO_CHANGEDISPLAYSETTINGS
   3.229  			if ( this->screen->flags & SDL_FULLSCREEN ) {
   3.230  				ChangeDisplaySettings(NULL, 0);
   3.231 @@ -1059,6 +1108,14 @@
   3.232  			}
   3.233  			this->screen->pixels = NULL;
   3.234  		}
   3.235 +		if ( screen_pal != NULL ) {
   3.236 +			DeleteObject(screen_pal);
   3.237 +			screen_pal = NULL;
   3.238 +		}
   3.239 +		if ( screen_logpal != NULL ) {
   3.240 +			SDL_free(screen_logpal);
   3.241 +			screen_logpal = NULL;
   3.242 +		}
   3.243  		if ( screen_bmp ) {
   3.244  			DeleteObject(screen_bmp);
   3.245  			screen_bmp = NULL;
   3.246 @@ -1097,26 +1154,55 @@
   3.247  }
   3.248  
   3.249  /* Exported for the windows message loop only */
   3.250 -static void DIB_FocusPalette(_THIS, int foreground)
   3.251 +static void DIB_GrabStaticColors(HWND window)
   3.252 +{
   3.253 +	HDC hdc;
   3.254 +
   3.255 +	hdc = GetDC(window);
   3.256 +	SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256);
   3.257 +	if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
   3.258 +		SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
   3.259 +	}
   3.260 +	ReleaseDC(window, hdc);
   3.261 +}
   3.262 +static void DIB_ReleaseStaticColors(HWND window)
   3.263 +{
   3.264 +	HDC hdc;
   3.265 +
   3.266 +	hdc = GetDC(window);
   3.267 +	SetSystemPaletteUse(hdc, SYSPAL_STATIC);
   3.268 +	ReleaseDC(window, hdc);
   3.269 +}
   3.270 +static void DIB_Activate(_THIS, BOOL active, BOOL minimized)
   3.271 +{
   3.272 +	if ( screen_pal && (this->screen->flags & SDL_HWPALETTE) ) {
   3.273 +		if ( !active ) {
   3.274 +			DIB_ReleaseStaticColors(SDL_Window);
   3.275 +			DIB_RealizePalette(this);
   3.276 +		} else if ( !minimized ) {
   3.277 +			DIB_GrabStaticColors(SDL_Window);
   3.278 +			DIB_RealizePalette(this);
   3.279 +		}
   3.280 +	}
   3.281 +}
   3.282 +static void DIB_RealizePalette(_THIS)
   3.283  {
   3.284  	if ( screen_pal != NULL ) {
   3.285  		HDC hdc;
   3.286  
   3.287  		hdc = GetDC(SDL_Window);
   3.288 +		UnrealizeObject(screen_pal);
   3.289  		SelectPalette(hdc, screen_pal, FALSE);
   3.290 -		if ( RealizePalette(hdc) )
   3.291 +		if ( RealizePalette(hdc) ) {
   3.292  			InvalidateRect(SDL_Window, NULL, FALSE);
   3.293 +		}
   3.294  		ReleaseDC(SDL_Window, hdc);
   3.295  	}
   3.296  }
   3.297 -static void DIB_RealizePalette(_THIS)
   3.298 -{
   3.299 -	DIB_FocusPalette(this, 1);
   3.300 -}
   3.301  static void DIB_PaletteChanged(_THIS, HWND window)
   3.302  {
   3.303  	if ( window != SDL_Window ) {
   3.304 -		DIB_FocusPalette(this, 0);
   3.305 +		DIB_RealizePalette(this);
   3.306  	}
   3.307  }
   3.308  
     4.1 --- a/src/video/windib/SDL_dibvideo.h	Mon Jul 02 02:45:52 2007 +0000
     4.2 +++ b/src/video/windib/SDL_dibvideo.h	Tue Jul 03 09:05:51 2007 +0000
     4.3 @@ -40,6 +40,7 @@
     4.4  struct SDL_PrivateVideoData {
     4.5      HBITMAP screen_bmp;
     4.6      HPALETTE screen_pal;
     4.7 +    LOGPALETTE *screen_logpal;
     4.8  
     4.9      int allow_screensaver;
    4.10  
    4.11 @@ -58,6 +59,7 @@
    4.12  /* Old variable names */
    4.13  #define screen_bmp		(this->hidden->screen_bmp)
    4.14  #define screen_pal		(this->hidden->screen_pal)
    4.15 +#define screen_logpal		(this->hidden->screen_logpal)
    4.16  #define SDL_nummodes		(this->hidden->SDL_nummodes)
    4.17  #define SDL_modelist		(this->hidden->SDL_modelist)
    4.18  
     5.1 --- a/src/video/windx5/SDL_dx5video.c	Mon Jul 02 02:45:52 2007 +0000
     5.2 +++ b/src/video/windx5/SDL_dx5video.c	Tue Jul 03 09:05:51 2007 +0000
     5.3 @@ -427,6 +427,7 @@
     5.4  				LPDIRECTDRAWSURFACE3 requested, Uint32 flag);
     5.5  
     5.6  /* Windows message handling functions */
     5.7 +static void DX5_Activate(_THIS, BOOL active, BOOL minimized);
     5.8  static void DX5_RealizePalette(_THIS);
     5.9  static void DX5_PaletteChanged(_THIS, HWND window);
    5.10  static void DX5_WinPAINT(_THIS, HDC hdc);
    5.11 @@ -620,6 +621,7 @@
    5.12  	device->PumpEvents = DX5_PumpEvents;
    5.13  
    5.14  	/* Set up the windows message handling functions */
    5.15 +	WIN_Activate = DX5_Activate;
    5.16  	WIN_RealizePalette = DX5_RealizePalette;
    5.17  	WIN_PaletteChanged = DX5_PaletteChanged;
    5.18  	WIN_WinPAINT = DX5_WinPAINT;
    5.19 @@ -2421,6 +2423,9 @@
    5.20  }
    5.21  
    5.22  /* Exported for the windows message loop only */
    5.23 +void DX5_Activate(_THIS, BOOL active, BOOL minimized)
    5.24 +{
    5.25 +}
    5.26  void DX5_RealizePalette(_THIS)
    5.27  {
    5.28  	if ( SDL_palette ) {