src/video/wincommon/SDL_syswm.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 13 Mar 2006 01:33:58 +0000
changeset 1505 4d005dfbb7f5
parent 1481 deb22b9fe970
child 1510 720f8bb49d7d
permissions -rw-r--r--
Fixed bug #139
The text in SDL_WM_SetCaption() is in UTF-8 encoding.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 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     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #define WIN32_LEAN_AND_MEAN
    25 #include <windows.h>
    26 
    27 #include "SDL_version.h"
    28 #include "SDL_video.h"
    29 #include "SDL_loadso.h"
    30 #include "SDL_syswm.h"
    31 #include "../SDL_pixels_c.h"
    32 #include "../SDL_cursor_c.h"
    33 #include "SDL_syswm_c.h"
    34 #include "SDL_wingl_c.h"
    35 
    36 
    37 #ifdef _WIN32_WCE
    38 #define DISABLE_ICON_SUPPORT
    39 #endif
    40 
    41 /* The screen icon -- needs to be freed on SDL_VideoQuit() */
    42 HICON   screen_icn = NULL;
    43 
    44 #ifdef _WIN32_WCE
    45 
    46 BOOL (WINAPI *CoreCatchInput)(int flag) = NULL;
    47 int input_catched = 0;
    48 HINSTANCE coredll = NULL;
    49 
    50 // the same API call that gx.dll does to catch the input
    51 void LoadInputCatchFunc()
    52 {
    53 	coredll = SDL_LoadObject("coredll.dll");
    54 	if( coredll )
    55 	{
    56 		CoreCatchInput = (int (WINAPI *)(int)) GetProcAddress(coredll, (const unsigned short *) 1453);
    57 	}
    58 }
    59 
    60 #endif
    61 
    62 
    63 /* Win32 icon mask semantics are different from those of SDL:
    64      SDL applies the mask to the icon and copies result to desktop.
    65      Win32 applies the mask to the desktop and XORs the icon on.
    66    This means that the SDL mask needs to be applied to the icon and
    67    then inverted and passed to Win32.
    68 */
    69 void WIN_SetWMIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
    70 {
    71 #ifdef DISABLE_ICON_SUPPORT
    72 	return;
    73 #else
    74 	SDL_Palette *pal_256;
    75 	SDL_Surface *icon_256;
    76 	Uint8 *pdata, *pwin32;
    77 	Uint8 *mdata, *mwin32, m = 0;
    78 	int icon_len;
    79 	int icon_plen;
    80 	int icon_mlen;
    81 	int icon_pitch;
    82 	int mask_pitch;
    83 	SDL_Rect bounds;
    84 	int i, skip;
    85 	int row, col;
    86 	struct /* quasi-BMP format */ Win32Icon {
    87 		Uint32 biSize;
    88 		Sint32 biWidth;
    89 		Sint32 biHeight;
    90 		Uint16 biPlanes;
    91 		Uint16 biBitCount;
    92 		Uint32 biCompression;
    93 		Uint32 biSizeImage;
    94 		Sint32 biXPelsPerMeter;
    95 		Sint32 biYPelsPerMeter;
    96 		Uint32 biClrUsed;
    97 		Uint32 biClrImportant;
    98 		struct /* RGBQUAD -- note it's BGR ordered */ {
    99 			Uint8 rgbBlue;
   100 			Uint8 rgbGreen;
   101 			Uint8 rgbRed;
   102 			Uint8 rgbReserved;
   103 		} biColors[256];
   104 		/* Pixels:
   105 		Uint8 pixels[]
   106 		*/
   107 		/* Mask:
   108 		Uint8 mask[]
   109 		*/
   110 	} *icon_win32;
   111 	
   112 	/* Allocate the win32 bmp icon and set everything to zero */
   113 	icon_pitch = ((icon->w+3)&~3);
   114 	mask_pitch = ((icon->w+7)/8);
   115 	icon_plen = icon->h*icon_pitch;
   116 	icon_mlen = icon->h*mask_pitch;
   117 	icon_len = sizeof(*icon_win32)+icon_plen+icon_mlen;
   118 	icon_win32 = (struct Win32Icon *)SDL_stack_alloc(Uint8, icon_len);
   119 	if ( icon_win32 == NULL ) {
   120 		return;
   121 	}
   122 	SDL_memset(icon_win32, 0, icon_len);
   123 
   124 	/* Set the basic BMP parameters */
   125 	icon_win32->biSize = sizeof(*icon_win32)-sizeof(icon_win32->biColors);
   126 	icon_win32->biWidth = icon->w;
   127 	icon_win32->biHeight = icon->h*2;
   128 	icon_win32->biPlanes = 1;
   129 	icon_win32->biBitCount = 8;
   130 	icon_win32->biSizeImage = icon_plen+icon_mlen;
   131 
   132 	/* Allocate a standard 256 color icon surface */
   133 	icon_256 = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
   134 					 icon_win32->biBitCount, 0, 0, 0, 0);
   135 	if ( icon_256 == NULL ) {
   136 		SDL_stack_free(icon_win32);
   137 		return;
   138 	}
   139 	pal_256 = icon_256->format->palette;
   140 	if (icon->format->palette && 
   141 		(icon->format->BitsPerPixel == icon_256->format->BitsPerPixel)){
   142 		Uint8 black;
   143 		SDL_memcpy(pal_256->colors, icon->format->palette->colors,
   144 					pal_256->ncolors*sizeof(SDL_Color));
   145 		/* Make sure that 0 is black! */
   146 		black = SDL_FindColor(pal_256, 0x00, 0x00, 0x00);
   147 		pal_256->colors[black] = pal_256->colors[0];
   148 		pal_256->colors[0].r = 0x00;
   149 		pal_256->colors[0].g = 0x00;
   150 		pal_256->colors[0].b = 0x00;
   151 	} else {
   152 		SDL_DitherColors(pal_256->colors,
   153 					icon_256->format->BitsPerPixel);
   154 	}
   155 
   156 	/* Now copy color data to the icon BMP */
   157 	for ( i=0; i<(1<<icon_win32->biBitCount); ++i ) {
   158 		icon_win32->biColors[i].rgbRed = pal_256->colors[i].r;
   159 		icon_win32->biColors[i].rgbGreen = pal_256->colors[i].g;
   160 		icon_win32->biColors[i].rgbBlue = pal_256->colors[i].b;
   161 	}
   162 
   163 	/* Convert icon to a standard surface format.  This may not always
   164 	   be necessary, as Windows supports a variety of BMP formats, but
   165 	   it greatly simplifies our code.
   166 	*/ 
   167     bounds.x = 0;
   168     bounds.y = 0;
   169     bounds.w = icon->w;
   170     bounds.h = icon->h;
   171     if ( SDL_LowerBlit(icon, &bounds, icon_256, &bounds) < 0 ) {
   172 	    SDL_stack_free(icon_win32);
   173 		SDL_FreeSurface(icon_256);
   174         return;
   175 	}
   176 
   177 	/* Copy pixels upside-down to icon BMP, masked with the icon mask */
   178 	if ( SDL_MUSTLOCK(icon_256) || (icon_256->pitch != icon_pitch) ) {
   179 		SDL_stack_free(icon_win32);
   180 		SDL_FreeSurface(icon_256);
   181 		SDL_SetError("Warning: Unexpected icon_256 characteristics");
   182 		return;
   183 	}
   184 	pdata = (Uint8 *)icon_256->pixels;
   185 	mdata = mask;
   186 	pwin32 = (Uint8 *)icon_win32+sizeof(*icon_win32)+icon_plen-icon_pitch;
   187 	skip = icon_pitch - icon->w;
   188 	for ( row=0; row<icon->h; ++row ) {
   189 		for ( col=0; col<icon->w; ++col ) {
   190 			if ( (col%8) == 0 ) {
   191 				m = *mdata++;
   192 			}
   193 			if ( (m&0x80) != 0x00 ) {
   194 				*pwin32 = *pdata;
   195 			}
   196 			m <<= 1;
   197 			++pdata;
   198 			++pwin32;
   199 		}
   200 		pdata  += skip;
   201 		pwin32 += skip;
   202 		pwin32 -= 2*icon_pitch;
   203 	}
   204 	SDL_FreeSurface(icon_256);
   205 
   206 	/* Copy mask inverted and upside-down to icon BMP */
   207 	mdata = mask;
   208 	mwin32 = (Uint8 *)icon_win32
   209 			+sizeof(*icon_win32)+icon_plen+icon_mlen-mask_pitch;
   210 	for ( row=0; row<icon->h; ++row ) {
   211 		for ( col=0; col<mask_pitch; ++col ) {
   212 			*mwin32++ = ~*mdata++;
   213 		}
   214 		mwin32 -= 2*mask_pitch;
   215 	}
   216 
   217 	/* Finally, create the icon handle and set the window icon */
   218 	screen_icn = CreateIconFromResourceEx((Uint8 *)icon_win32, icon_len,
   219 			TRUE, 0x00030000, icon->w, icon->h, LR_DEFAULTCOLOR);
   220 	if ( screen_icn == NULL ) {
   221 		SDL_SetError("Couldn't create Win32 icon handle");
   222 	} else {
   223 		SetClassLongPtr(SDL_Window, GCLP_HICON, (LONG_PTR)screen_icn);
   224 	}
   225 	SDL_stack_free(icon_win32);
   226 #endif /* DISABLE_ICON_SUPPORT */
   227 }
   228 
   229 void WIN_SetWMCaption(_THIS, const char *title, const char *icon)
   230 {
   231 #ifdef _WIN32_WCE
   232 	/* WinCE uses the UNICODE version */
   233 	LPWSTR lpszW = SDL_iconv_utf8_ucs2(title);
   234 	SetWindowText(SDL_Window, lpszW);
   235 	SDL_free(lpszW);
   236 #else
   237 	char *lpsz = SDL_iconv_utf8_latin1(title);
   238 	SetWindowText(SDL_Window, lpsz);
   239 	SDL_free(lpsz);
   240 #endif
   241 }
   242 
   243 int WIN_IconifyWindow(_THIS)
   244 {
   245 	ShowWindow(SDL_Window, SW_MINIMIZE);
   246 	return(1);
   247 }
   248 
   249 SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode)
   250 {
   251 	if ( mode == SDL_GRAB_OFF ) {
   252 		ClipCursor(NULL);
   253 		if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
   254 		/*	RJR: March 28, 2000
   255 			must be leaving relative mode, move mouse from
   256 			center of window to where it belongs ... */
   257 			POINT pt;
   258 			int x, y;
   259 			SDL_GetMouseState(&x,&y);
   260 			pt.x = x;
   261 			pt.y = y;
   262 			ClientToScreen(SDL_Window, &pt);
   263 			SetCursorPos(pt.x,pt.y);
   264 		}
   265 #ifdef _WIN32_WCE
   266 		if( input_catched )
   267 		{
   268 			if( !CoreCatchInput ) LoadInputCatchFunc();
   269 
   270 			if( CoreCatchInput )
   271 				CoreCatchInput(0);
   272 		}
   273 #endif
   274 	} else {
   275 		ClipCursor(&SDL_bounds);
   276 		if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
   277 		/*	RJR: March 28, 2000
   278 			must be entering relative mode, get ready by
   279 			moving mouse to	center of window ... */
   280 			POINT pt;
   281 			pt.x = (SDL_VideoSurface->w/2);
   282 			pt.y = (SDL_VideoSurface->h/2);
   283 			ClientToScreen(SDL_Window, &pt);
   284 			SetCursorPos(pt.x, pt.y);
   285 		}
   286 #ifdef _WIN32_WCE
   287 		if( !input_catched )
   288 		{
   289 			if( !CoreCatchInput ) LoadInputCatchFunc();
   290 
   291 			if( CoreCatchInput )
   292 				CoreCatchInput(1);
   293 		}
   294 #endif
   295 	}
   296 	return(mode);
   297 }
   298 
   299 /* If 'info' is the right version, this function fills it and returns 1.
   300    Otherwise, in case of a version mismatch, it returns -1.
   301 */
   302 int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info)
   303 {
   304 	if ( info->version.major <= SDL_MAJOR_VERSION ) {
   305 		info->window = SDL_Window;
   306 		if ( SDL_VERSIONNUM(info->version.major,
   307 		                    info->version.minor,
   308 		                    info->version.patch) >=
   309 		     SDL_VERSIONNUM(1, 2, 5) ) {
   310 #if SDL_VIDEO_OPENGL
   311 			info->hglrc = GL_hrc;
   312 #else
   313 			info->hglrc = NULL;
   314 #endif
   315 		}
   316 		return(1);
   317 	} else {
   318 		SDL_SetError("Application not compiled with SDL %d.%d\n",
   319 					SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
   320 		return(-1);
   321 	}
   322 }