Home | History | Annotate | Download | only in wincommon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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 (at) 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 /* Win32 icon mask semantics are different from those of SDL:
     45      SDL applies the mask to the icon and copies result to desktop.
     46      Win32 applies the mask to the desktop and XORs the icon on.
     47    This means that the SDL mask needs to be applied to the icon and
     48    then inverted and passed to Win32.
     49 */
     50 void WIN_SetWMIcon(_THIS, SDL_Surface *icon, Uint8 *mask)
     51 {
     52 #ifdef DISABLE_ICON_SUPPORT
     53 	return;
     54 #else
     55 	SDL_Palette *pal_256;
     56 	SDL_Surface *icon_256;
     57 	Uint8 *pdata, *pwin32;
     58 	Uint8 *mdata, *mwin32, m = 0;
     59 	int icon_len;
     60 	int icon_plen;
     61 	int icon_mlen;
     62 	int icon_pitch;
     63 	int mask_pitch;
     64 	SDL_Rect bounds;
     65 	int i, skip;
     66 	int row, col;
     67 	struct /* quasi-BMP format */ Win32Icon {
     68 		Uint32 biSize;
     69 		Sint32 biWidth;
     70 		Sint32 biHeight;
     71 		Uint16 biPlanes;
     72 		Uint16 biBitCount;
     73 		Uint32 biCompression;
     74 		Uint32 biSizeImage;
     75 		Sint32 biXPelsPerMeter;
     76 		Sint32 biYPelsPerMeter;
     77 		Uint32 biClrUsed;
     78 		Uint32 biClrImportant;
     79 		struct /* RGBQUAD -- note it's BGR ordered */ {
     80 			Uint8 rgbBlue;
     81 			Uint8 rgbGreen;
     82 			Uint8 rgbRed;
     83 			Uint8 rgbReserved;
     84 		} biColors[256];
     85 		/* Pixels:
     86 		Uint8 pixels[]
     87 		*/
     88 		/* Mask:
     89 		Uint8 mask[]
     90 		*/
     91 	} *icon_win32;
     92 
     93 	/* Allocate the win32 bmp icon and set everything to zero */
     94 	icon_pitch = ((icon->w+3)&~3);
     95 	mask_pitch = ((icon->w+7)/8);
     96 	icon_plen = icon->h*icon_pitch;
     97 	icon_mlen = icon->h*mask_pitch;
     98 	icon_len = sizeof(*icon_win32)+icon_plen+icon_mlen;
     99 	icon_win32 = (struct Win32Icon *)SDL_stack_alloc(Uint8, icon_len);
    100 	if ( icon_win32 == NULL ) {
    101 		return;
    102 	}
    103 	SDL_memset(icon_win32, 0, icon_len);
    104 
    105 	/* Set the basic BMP parameters */
    106 	icon_win32->biSize = sizeof(*icon_win32)-sizeof(icon_win32->biColors);
    107 	icon_win32->biWidth = icon->w;
    108 	icon_win32->biHeight = icon->h*2;
    109 	icon_win32->biPlanes = 1;
    110 	icon_win32->biBitCount = 8;
    111 	icon_win32->biSizeImage = icon_plen+icon_mlen;
    112 
    113 	/* Allocate a standard 256 color icon surface */
    114 	icon_256 = SDL_CreateRGBSurface(SDL_SWSURFACE, icon->w, icon->h,
    115 					 icon_win32->biBitCount, 0, 0, 0, 0);
    116 	if ( icon_256 == NULL ) {
    117 		SDL_stack_free(icon_win32);
    118 		return;
    119 	}
    120 	pal_256 = icon_256->format->palette;
    121 	if (icon->format->palette &&
    122 		(icon->format->BitsPerPixel == icon_256->format->BitsPerPixel)){
    123 		Uint8 black;
    124 		SDL_memcpy(pal_256->colors, icon->format->palette->colors,
    125 					pal_256->ncolors*sizeof(SDL_Color));
    126 		/* Make sure that 0 is black! */
    127 		black = SDL_FindColor(pal_256, 0x00, 0x00, 0x00);
    128 		pal_256->colors[black] = pal_256->colors[0];
    129 		pal_256->colors[0].r = 0x00;
    130 		pal_256->colors[0].g = 0x00;
    131 		pal_256->colors[0].b = 0x00;
    132 	} else {
    133 		SDL_DitherColors(pal_256->colors,
    134 					icon_256->format->BitsPerPixel);
    135 	}
    136 
    137 	/* Now copy color data to the icon BMP */
    138 	for ( i=0; i<(1<<icon_win32->biBitCount); ++i ) {
    139 		icon_win32->biColors[i].rgbRed = pal_256->colors[i].r;
    140 		icon_win32->biColors[i].rgbGreen = pal_256->colors[i].g;
    141 		icon_win32->biColors[i].rgbBlue = pal_256->colors[i].b;
    142 	}
    143 
    144 	/* Convert icon to a standard surface format.  This may not always
    145 	   be necessary, as Windows supports a variety of BMP formats, but
    146 	   it greatly simplifies our code.
    147 	*/
    148     bounds.x = 0;
    149     bounds.y = 0;
    150     bounds.w = icon->w;
    151     bounds.h = icon->h;
    152     if ( SDL_LowerBlit(icon, &bounds, icon_256, &bounds) < 0 ) {
    153 	    SDL_stack_free(icon_win32);
    154 		SDL_FreeSurface(icon_256);
    155         return;
    156 	}
    157 
    158 	/* Copy pixels upside-down to icon BMP, masked with the icon mask */
    159 	if ( SDL_MUSTLOCK(icon_256) || (icon_256->pitch != icon_pitch) ) {
    160 		SDL_stack_free(icon_win32);
    161 		SDL_FreeSurface(icon_256);
    162 		SDL_SetError("Warning: Unexpected icon_256 characteristics");
    163 		return;
    164 	}
    165 	pdata = (Uint8 *)icon_256->pixels;
    166 	mdata = mask;
    167 	pwin32 = (Uint8 *)icon_win32+sizeof(*icon_win32)+icon_plen-icon_pitch;
    168 	skip = icon_pitch - icon->w;
    169 	for ( row=0; row<icon->h; ++row ) {
    170 		for ( col=0; col<icon->w; ++col ) {
    171 			if ( (col%8) == 0 ) {
    172 				m = *mdata++;
    173 			}
    174 			if ( (m&0x80) != 0x00 ) {
    175 				*pwin32 = *pdata;
    176 			}
    177 			m <<= 1;
    178 			++pdata;
    179 			++pwin32;
    180 		}
    181 		pdata  += skip;
    182 		pwin32 += skip;
    183 		pwin32 -= 2*icon_pitch;
    184 	}
    185 	SDL_FreeSurface(icon_256);
    186 
    187 	/* Copy mask inverted and upside-down to icon BMP */
    188 	mdata = mask;
    189 	mwin32 = (Uint8 *)icon_win32
    190 			+sizeof(*icon_win32)+icon_plen+icon_mlen-mask_pitch;
    191 	for ( row=0; row<icon->h; ++row ) {
    192 		for ( col=0; col<mask_pitch; ++col ) {
    193 			*mwin32++ = ~*mdata++;
    194 		}
    195 		mwin32 -= 2*mask_pitch;
    196 	}
    197 
    198 	/* Finally, create the icon handle and set the window icon */
    199 	screen_icn = CreateIconFromResourceEx((Uint8 *)icon_win32, icon_len,
    200 			TRUE, 0x00030000, icon->w, icon->h, LR_DEFAULTCOLOR);
    201 	if ( screen_icn == NULL ) {
    202 		SDL_SetError("Couldn't create Win32 icon handle");
    203 	} else {
    204 		SetClassLongPtr(SDL_Window, GCLP_HICON, (LONG_PTR)screen_icn);
    205 	}
    206 	SDL_stack_free(icon_win32);
    207 #endif /* DISABLE_ICON_SUPPORT */
    208 }
    209 
    210 typedef BOOL (WINAPI *PtrSetWindowTextW)(HWND hWnd, LPCWSTR lpString);
    211 
    212 void WIN_SetWMCaption(_THIS, const char *title, const char *icon)
    213 {
    214 #ifdef _WIN32_WCE
    215 	/* WinCE uses the UNICODE version */
    216 	LPWSTR lpszW = SDL_iconv_utf8_ucs2((char *)title);
    217 	SetWindowText(SDL_Window, lpszW);
    218 	SDL_free(lpszW);
    219 #else
    220 	Uint16 *lpsz = SDL_iconv_utf8_ucs2(title);
    221 	size_t len = WideCharToMultiByte(CP_ACP, 0, lpsz, -1, NULL, 0, NULL, NULL);
    222 	char *cvt = SDL_stack_alloc(char, len + 1);
    223 	WideCharToMultiByte(CP_ACP, 0, lpsz, -1, cvt, len, NULL, NULL);
    224 	SetWindowText(SDL_Window, cvt);
    225 	SDL_stack_free(cvt);
    226 	SDL_free(lpsz);
    227 #endif
    228 }
    229 
    230 int WIN_IconifyWindow(_THIS)
    231 {
    232 	ShowWindow(SDL_Window, SW_MINIMIZE);
    233 	return(1);
    234 }
    235 
    236 SDL_GrabMode WIN_GrabInput(_THIS, SDL_GrabMode mode)
    237 {
    238 	if ( mode == SDL_GRAB_OFF ) {
    239 		ClipCursor(NULL);
    240 		if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
    241 		/*	RJR: March 28, 2000
    242 			must be leaving relative mode, move mouse from
    243 			center of window to where it belongs ... */
    244 			POINT pt;
    245 			int x, y;
    246 			SDL_GetMouseState(&x,&y);
    247 			pt.x = x;
    248 			pt.y = y;
    249 			ClientToScreen(SDL_Window, &pt);
    250 			SetCursorPos(pt.x,pt.y);
    251 		}
    252 #ifdef _WIN32_WCE
    253 		AllKeys(0);
    254 #endif
    255 	} else {
    256 		ClipCursor(&SDL_bounds);
    257 		if ( !(SDL_cursorstate & CURSOR_VISIBLE) ) {
    258 		/*	RJR: March 28, 2000
    259 			must be entering relative mode, get ready by
    260 			moving mouse to	center of window ... */
    261 			POINT pt;
    262 			pt.x = (SDL_VideoSurface->w/2);
    263 			pt.y = (SDL_VideoSurface->h/2);
    264 			ClientToScreen(SDL_Window, &pt);
    265 			SetCursorPos(pt.x, pt.y);
    266 		}
    267 #ifdef _WIN32_WCE
    268 		AllKeys(1);
    269 #endif
    270 	}
    271 	return(mode);
    272 }
    273 
    274 /* If 'info' is the right version, this function fills it and returns 1.
    275    Otherwise, in case of a version mismatch, it returns -1.
    276 */
    277 int WIN_GetWMInfo(_THIS, SDL_SysWMinfo *info)
    278 {
    279 	if ( info->version.major <= SDL_MAJOR_VERSION ) {
    280 		info->window = SDL_Window;
    281 		if ( SDL_VERSIONNUM(info->version.major,
    282 		                    info->version.minor,
    283 		                    info->version.patch) >=
    284 		     SDL_VERSIONNUM(1, 2, 5) ) {
    285 #if SDL_VIDEO_OPENGL
    286 			info->hglrc = GL_hrc;
    287 #else
    288 			info->hglrc = NULL;
    289 #endif
    290 		}
    291 		return(1);
    292 	} else {
    293 		SDL_SetError("Application not compiled with SDL %d.%d\n",
    294 					SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
    295 		return(-1);
    296 	}
    297 }
    298