src/video/wincommon/SDL_syswm.c
author Sam Lantinga <slouken@lokigames.com>
Wed, 23 May 2001 23:35:10 +0000
changeset 36 13ee9f4834ea
parent 0 74212992fb08
child 252 e8157fcb3114
permissions -rw-r--r--
Windows CE patches contributed by Rainer Loritz
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@devolution.com
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$"
    26 #endif
    27 
    28 #include <stdio.h>
    29 #include <malloc.h>
    30 #include <windows.h>
    31 
    32 #include "SDL_version.h"
    33 #include "SDL_error.h"
    34 #include "SDL_video.h"
    35 #include "SDL_syswm.h"
    36 #include "SDL_syswm_c.h"
    37 #include "SDL_pixels_c.h"
    38 
    39 #ifdef _WIN32_WCE
    40 #define DISABLE_ICON_SUPPORT
    41 #endif
    42 
    43 /*	RJR: March 28, 2000
    44 	we need "SDL_cursor_c.h" for mods to WIN_GrabInput */
    45 #include "SDL_cursor_c.h"
    46 
    47 /* The screen icon -- needs to be freed on SDL_VideoQuit() */
    48 HICON   screen_icn = NULL;
    49 
    50 /* Win32 icon mask semantics are different from those of SDL:
    51      SDL applies the mask to the icon and copies result to desktop.
    52      Win32 applies the mask to the desktop and XORs the icon on.
    53    This means that the SDL mask needs to be applied to the icon and
    54    then inverted and passed to Win32.
    55 */
    56 void WIN_SetWMIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
    57 {
    58 #ifdef DISABLE_ICON_SUPPORT
    59 	return;
    60 #else
    61 	SDL_Palette *pal_256;
    62 	SDL_Surface *icon_256;
    63 	Uint8 *pdata, *pwin32;
    64 	Uint8 *mdata, *mwin32, m = 0;
    65 	int icon_len;
    66 	int icon_plen;
    67 	int icon_mlen;
    68 	int icon_pitch;
    69 	int mask_pitch;
    70 	SDL_Rect bounds;
    71 	int i, skip;
    72 	int row, col;
    73 	struct /* quasi-BMP format */ Win32Icon {
    74 		Uint32 biSize;
    75 		Sint32 biWidth;
    76 		Sint32 biHeight;
    77 		Uint16 biPlanes;
    78 		Uint16 biBitCount;
    79 		Uint32 biCompression;
    80 		Uint32 biSizeImage;
    81 		Sint32 biXPelsPerMeter;
    82 		Sint32 biYPelsPerMeter;
    83 		Uint32 biClrUsed;
    84 		Uint32 biClrImportant;
    85 		struct /* RGBQUAD -- note it's BGR ordered */ {
    86 			Uint8 rgbBlue;
    87 			Uint8 rgbGreen;
    88 			Uint8 rgbRed;
    89 			Uint8 rgbReserved;
    90 		} biColors[256];
    91 		/* Pixels:
    92 		Uint8 pixels[]
    93 		*/
    94 		/* Mask:
    95 		Uint8 mask[]
    96 		*/
    97 	} *icon_win32;
    98 	
    99 	/* Allocate the win32 bmp icon and set everything to zero */
   100 	icon_pitch = ((icon->w+3)&~3);
   101 	mask_pitch = ((icon->w+7)/8);
   102 	icon_plen = icon->h*icon_pitch;
   103 	icon_mlen = icon->h*mask_pitch;
   104 	icon_len = sizeof(*icon_win32)+icon_plen+icon_mlen;
   105 	icon_win32 = (struct Win32Icon *)alloca(icon_len);
   106 	if ( icon_win32 == NULL ) {
   107 		return;
   108 	}
   109 	memset(icon_win32, 0, icon_len);
   110 
   111 	/* Set the basic BMP parameters */
   112 	icon_win32->biSize = sizeof(*icon_win32)-sizeof(icon_win32->biColors);
   113 	icon_win32->biWidth = icon->w;
   114 	icon_win32->biHeight = icon->h*2;
   115 	icon_win32->biPlanes = 1;
   116 	icon_win32->biBitCount = 8;
   117 	icon_win32->biSizeImage = icon_plen+icon_mlen;
   118 
   119 	/* Allocate a standard 256 color icon surface */
   120 	icon_256 = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
   121 					 icon_win32->biBitCount, 0, 0, 0, 0);
   122 	if ( icon_256 == NULL ) {
   123 		return;
   124 	}
   125 	pal_256 = icon_256->format->palette;
   126 	if (icon->format->palette && 
   127 		(icon->format->BitsPerPixel == icon_256->format->BitsPerPixel)){
   128 		Uint8 black;
   129 		memcpy(pal_256->colors, icon->format->palette->colors,
   130 					pal_256->ncolors*sizeof(SDL_Color));
   131 		/* Make sure that 0 is black! */
   132 		black = SDL_FindColor(pal_256, 0x00, 0x00, 0x00);
   133 		pal_256->colors[black] = pal_256->colors[0];
   134 		pal_256->colors[0].r = 0x00;
   135 		pal_256->colors[0].g = 0x00;
   136 		pal_256->colors[0].b = 0x00;
   137 	} else {
   138 		SDL_DitherColors(pal_256->colors,
   139 					icon_256->format->BitsPerPixel);
   140 	}
   141 
   142 	/* Now copy color data to the icon BMP */
   143 	for ( i=0; i<(1<<icon_win32->biBitCount); ++i ) {
   144 		icon_win32->biColors[i].rgbRed = pal_256->colors[i].r;
   145 		icon_win32->biColors[i].rgbGreen = pal_256->colors[i].g;
   146 		icon_win32->biColors[i].rgbBlue = pal_256->colors[i].b;
   147 	}
   148 
   149 	/* Convert icon to a standard surface format.  This may not always
   150 	   be necessary, as Windows supports a variety of BMP formats, but
   151 	   it greatly simplifies our code.
   152 	*/ 
   153         bounds.x = 0;
   154         bounds.y = 0;
   155         bounds.w = icon->w;
   156         bounds.h = icon->h;
   157         if ( SDL_LowerBlit(icon, &bounds, icon_256, &bounds) < 0 ) {
   158 		SDL_FreeSurface(icon_256);
   159                 return;
   160 	}
   161 
   162 	/* Copy pixels upside-down to icon BMP, masked with the icon mask */
   163 	if ( SDL_MUSTLOCK(icon_256) || (icon_256->pitch != icon_pitch) ) {
   164 		SDL_FreeSurface(icon_256);
   165 		SDL_SetError("Warning: Unexpected icon_256 characteristics");
   166 		return;
   167 	}
   168 	pdata = (Uint8 *)icon_256->pixels;
   169 	mdata = mask;
   170 	pwin32 = (Uint8 *)icon_win32+sizeof(*icon_win32)+icon_plen-icon_pitch;
   171 	skip = icon_pitch - icon->w;
   172 	for ( row=0; row<icon->h; ++row ) {
   173 		for ( col=0; col<icon->w; ++col ) {
   174 			if ( (col%8) == 0 ) {
   175 				m = *mdata++;
   176 			}
   177 			if ( (m&0x80) != 0x00 ) {
   178 				*pwin32 = *pdata;
   179 			}
   180 			m <<= 1;
   181 			++pdata;
   182 			++pwin32;
   183 		}
   184 		pdata  += skip;
   185 		pwin32 += skip;
   186 		pwin32 -= 2*icon_pitch;
   187 	}
   188 	SDL_FreeSurface(icon_256);
   189 
   190 	/* Copy mask inverted and upside-down to icon BMP */
   191 	mdata = mask;
   192 	mwin32 = (Uint8 *)icon_win32
   193 			+sizeof(*icon_win32)+icon_plen+icon_mlen-mask_pitch;
   194 	for ( row=0; row<icon->h; ++row ) {
   195 		for ( col=0; col<mask_pitch; ++col ) {
   196 			*mwin32++ = ~*mdata++;
   197 		}
   198 		mwin32 -= 2*mask_pitch;
   199 	}
   200 
   201 	/* Finally, create the icon handle and set the window icon */
   202 	screen_icn = CreateIconFromResourceEx((Uint8 *)icon_win32, icon_len,
   203 			TRUE, 0x00030000, icon->w, icon->h, LR_DEFAULTCOLOR);
   204 	if ( screen_icn == NULL ) {
   205 		SDL_SetError("Couldn't create Win32 icon handle");
   206 	} else {
   207 		SetClassLong(SDL_Window, GCL_HICON, (LONG)screen_icn);
   208 	}
   209 #endif /* DISABLE_ICON_SUPPORT */
   210 }
   211 
   212 void WIN_SetWMCaption(_THIS, const char *title, const char *icon)
   213 {
   214 #ifdef _WIN32_WCE
   215 	/* WinCE uses the UNICODE version */
   216 	int nLen = strlen(title)+1;
   217 	LPWSTR lpszW = alloca(nLen*2);
   218 	MultiByteToWideChar(CP_ACP, 0, title, -1, lpszW, nLen);
   219 	SetWindowText(SDL_Window, lpszW);
   220 #else
   221 	SetWindowText(SDL_Window, title);
   222 #endif
   223 }
   224 
   225 int WIN_IconifyWindow(_THIS)
   226 {
   227 	ShowWindow(SDL_Window, SW_MINIMIZE);
   228 	return(1);
   229 }
   230 
   231 SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode)
   232 {
   233 	if ( mode == SDL_GRAB_OFF ) {
   234 		ClipCursor(NULL);
   235 		if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
   236 		/*	RJR: March 28, 2000
   237 			must be leaving relative mode, move mouse from
   238 			center of window to where it belongs ... */
   239 			POINT pt;
   240 			int x, y;
   241 			SDL_GetMouseState(&x,&y);
   242 			pt.x = x;
   243 			pt.y = y;
   244 			ClientToScreen(SDL_Window, &pt);
   245 			SetCursorPos(pt.x,pt.y);
   246 		}
   247 	} else {
   248 		ClipCursor(&SDL_bounds);
   249 		if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
   250 		/*	RJR: March 28, 2000
   251 			must be entering relative mode, get ready by
   252 			moving mouse to	center of window ... */
   253 			POINT pt;
   254 			pt.x = (SDL_VideoSurface->w/2);
   255 			pt.y = (SDL_VideoSurface->h/2);
   256 			ClientToScreen(SDL_Window, &pt);
   257 			SetCursorPos(pt.x, pt.y);
   258 		}
   259 	}
   260 	return(mode);
   261 }
   262 
   263 /* If 'info' is the right version, this function fills it and returns 1.
   264    Otherwise, in case of a version mismatch, it returns -1.
   265 */
   266 int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info)
   267 {
   268 	if ( info->version.major <= SDL_MAJOR_VERSION ) {
   269 		info->window = SDL_Window;
   270 		return(1);
   271 	} else {
   272 		SDL_SetError("Application not compiled with SDL %d.%d\n",
   273 					SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   274 		return(-1);
   275 	}
   276 }