SDL-1.2.14
[sdl_omap.git] / src / video / wincommon / SDL_syswm.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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 /* 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 }