comparison src/video/windows/SDL_windowswindow.c @ 5062:e8916fe9cfc8

Fixed bug #925 Changed "win32" to "windows"
author Sam Lantinga <slouken@libsdl.org>
date Thu, 20 Jan 2011 18:04:05 -0800
parents src/video/win32/SDL_win32window.c@8b7988f42fcb
children c2539ff054c8
comparison
equal deleted inserted replaced
5061:9e9940eae455 5062:e8916fe9cfc8
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 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 #include "../SDL_sysvideo.h"
25 #include "../SDL_pixels_c.h"
26 #include "../../events/SDL_keyboard_c.h"
27
28 #include "SDL_windowsvideo.h"
29 #include "SDL_windowswindow.h"
30
31 /* This is included after SDL_windowsvideo.h, which includes windows.h */
32 #include "SDL_syswm.h"
33 #include "SDL_gapirender.h"
34
35
36 /* Fake window to help with DirectInput events. */
37 HWND SDL_HelperWindow = NULL;
38 static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
39 static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
40 static ATOM SDL_HelperWindowClass = 0;
41
42 static int
43 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, SDL_bool created)
44 {
45 SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
46 SDL_VideoDisplay *display = window->display;
47 SDL_WindowData *data;
48
49 /* Allocate the window data */
50 data = (SDL_WindowData *) SDL_malloc(sizeof(*data));
51 if (!data) {
52 SDL_OutOfMemory();
53 return -1;
54 }
55 data->window = window;
56 data->hwnd = hwnd;
57 data->hdc = GetDC(hwnd);
58 data->created = created;
59 data->mouse_pressed = SDL_FALSE;
60 data->videodata = videodata;
61
62 /* Associate the data with the window */
63 if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
64 ReleaseDC(hwnd, data->hdc);
65 SDL_free(data);
66 WIN_SetError("SetProp() failed");
67 return -1;
68 }
69
70 /* Set up the window proc function */
71 data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
72 if (data->wndproc == WIN_WindowProc) {
73 data->wndproc = NULL;
74 }
75 else {
76 SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
77 }
78
79 /* Fill in the SDL window with the window data */
80 {
81 POINT point;
82 point.x = 0;
83 point.y = 0;
84 if (ClientToScreen(hwnd, &point)) {
85 SDL_Rect bounds;
86 WIN_GetDisplayBounds(_this, display, &bounds);
87 window->x = point.x - bounds.x;
88 window->y = point.y - bounds.y;
89 }
90 }
91 {
92 RECT rect;
93 if (GetClientRect(hwnd, &rect)) {
94 window->w = rect.right;
95 window->h = rect.bottom;
96 }
97 }
98 {
99 DWORD style = GetWindowLong(hwnd, GWL_STYLE);
100 if (style & WS_VISIBLE) {
101 window->flags |= SDL_WINDOW_SHOWN;
102 } else {
103 window->flags &= ~SDL_WINDOW_SHOWN;
104 }
105 if (style & (WS_BORDER | WS_THICKFRAME)) {
106 window->flags &= ~SDL_WINDOW_BORDERLESS;
107 } else {
108 window->flags |= SDL_WINDOW_BORDERLESS;
109 }
110 if (style & WS_THICKFRAME) {
111 window->flags |= SDL_WINDOW_RESIZABLE;
112 } else {
113 window->flags &= ~SDL_WINDOW_RESIZABLE;
114 }
115 if (style & WS_MAXIMIZE) {
116 window->flags |= SDL_WINDOW_MAXIMIZED;
117 } else {
118 window->flags &= ~SDL_WINDOW_MAXIMIZED;
119 }
120 if (style & WS_MINIMIZE) {
121 window->flags |= SDL_WINDOW_MINIMIZED;
122 } else {
123 window->flags &= ~SDL_WINDOW_MINIMIZED;
124 }
125 }
126 if (GetFocus() == hwnd) {
127 window->flags |= SDL_WINDOW_INPUT_FOCUS;
128 SDL_SetKeyboardFocus(data->window);
129
130 if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
131 RECT rect;
132 GetClientRect(hwnd, &rect);
133 ClientToScreen(hwnd, (LPPOINT) & rect);
134 ClientToScreen(hwnd, (LPPOINT) & rect + 1);
135 ClipCursor(&rect);
136 }
137 }
138
139 /* Enable multi-touch */
140 if (videodata->RegisterTouchWindow) {
141 videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
142 }
143
144 /* All done! */
145 window->driverdata = data;
146 return 0;
147 }
148
149 int
150 WIN_CreateWindow(_THIS, SDL_Window * window)
151 {
152 SDL_VideoDisplay *display = window->display;
153 HWND hwnd;
154 RECT rect;
155 SDL_Rect bounds;
156 DWORD style = (WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
157 int x, y;
158 int w, h;
159
160 if (window->flags & (SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN)) {
161 style |= WS_POPUP;
162 } else {
163 style |= (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
164 }
165 if ((window->flags & SDL_WINDOW_RESIZABLE)
166 && !(window->flags & SDL_WINDOW_FULLSCREEN)) {
167 style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
168 }
169
170 /* Figure out what the window area will be */
171 rect.left = 0;
172 rect.top = 0;
173 rect.right = window->w;
174 rect.bottom = window->h;
175 AdjustWindowRectEx(&rect, style, FALSE, 0);
176 w = (rect.right - rect.left);
177 h = (rect.bottom - rect.top);
178
179 WIN_GetDisplayBounds(_this, display, &bounds);
180 if (window->flags & SDL_WINDOW_FULLSCREEN) {
181 /* The bounds when this window is visible is the fullscreen mode */
182 SDL_DisplayMode fullscreen_mode;
183 if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) {
184 bounds.w = fullscreen_mode.w;
185 bounds.h = fullscreen_mode.h;
186 }
187 }
188 if ((window->flags & SDL_WINDOW_FULLSCREEN)
189 || window->x == SDL_WINDOWPOS_CENTERED) {
190 x = bounds.x + (bounds.w - w) / 2;
191 } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
192 if (bounds.x == 0) {
193 x = CW_USEDEFAULT;
194 } else {
195 x = bounds.x;
196 }
197 } else {
198 x = bounds.x + window->x + rect.left;
199 }
200 if ((window->flags & SDL_WINDOW_FULLSCREEN)
201 || window->y == SDL_WINDOWPOS_CENTERED) {
202 y = bounds.y + (bounds.h - h) / 2;
203 } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
204 if (bounds.x == 0) {
205 y = CW_USEDEFAULT;
206 } else {
207 y = bounds.y;
208 }
209 } else {
210 y = bounds.y + window->y + rect.top;
211 }
212
213 hwnd =
214 CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, NULL, NULL,
215 SDL_Instance, NULL);
216 if (!hwnd) {
217 WIN_SetError("Couldn't create window");
218 return -1;
219 }
220 //RegisterTouchWindow(hwnd, 0);
221
222 WIN_PumpEvents(_this);
223
224 if (SetupWindowData(_this, window, hwnd, SDL_TRUE) < 0) {
225 DestroyWindow(hwnd);
226 return -1;
227 }
228 #ifdef SDL_VIDEO_OPENGL_WGL
229 if (window->flags & SDL_WINDOW_OPENGL) {
230 if (WIN_GL_SetupWindow(_this, window) < 0) {
231 WIN_DestroyWindow(_this, window);
232 return -1;
233 }
234 }
235 #endif
236 return 0;
237 }
238
239 int
240 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
241 {
242 HWND hwnd = (HWND) data;
243 LPTSTR title;
244 int titleLen;
245
246 /* Query the title from the existing window */
247 titleLen = GetWindowTextLength(hwnd);
248 title = SDL_stack_alloc(TCHAR, titleLen + 1);
249 if (title) {
250 titleLen = GetWindowText(hwnd, title, titleLen);
251 } else {
252 titleLen = 0;
253 }
254 if (titleLen > 0) {
255 window->title = WIN_StringToUTF8(title);
256 }
257 if (title) {
258 SDL_stack_free(title);
259 }
260
261 if (SetupWindowData(_this, window, hwnd, SDL_FALSE) < 0) {
262 return -1;
263 }
264 return 0;
265 }
266
267 void
268 WIN_SetWindowTitle(_THIS, SDL_Window * window)
269 {
270 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
271 LPTSTR title;
272
273 if (window->title) {
274 title = WIN_UTF8ToString(window->title);
275 } else {
276 title = NULL;
277 }
278 SetWindowText(hwnd, title ? title : TEXT(""));
279 if (title) {
280 SDL_free(title);
281 }
282 }
283
284 void
285 WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
286 {
287 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
288 HICON hicon = NULL;
289
290 if (icon) {
291 BYTE *icon_bmp;
292 int icon_len;
293 SDL_RWops *dst;
294 SDL_PixelFormat format;
295 SDL_Surface *surface;
296
297 /* Create temporary bitmap buffer */
298 icon_len = 40 + icon->h * icon->w * 4;
299 icon_bmp = SDL_stack_alloc(BYTE, icon_len);
300 dst = SDL_RWFromMem(icon_bmp, icon_len);
301 if (!dst) {
302 SDL_stack_free(icon_bmp);
303 return;
304 }
305
306 /* Write the BITMAPINFO header */
307 SDL_WriteLE32(dst, 40);
308 SDL_WriteLE32(dst, icon->w);
309 SDL_WriteLE32(dst, icon->h * 2);
310 SDL_WriteLE16(dst, 1);
311 SDL_WriteLE16(dst, 32);
312 SDL_WriteLE32(dst, BI_RGB);
313 SDL_WriteLE32(dst, icon->h * icon->w * 4);
314 SDL_WriteLE32(dst, 0);
315 SDL_WriteLE32(dst, 0);
316 SDL_WriteLE32(dst, 0);
317 SDL_WriteLE32(dst, 0);
318
319 /* Convert the icon to a 32-bit surface with alpha channel */
320 SDL_InitFormat(&format, 32,
321 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
322 surface = SDL_ConvertSurface(icon, &format, 0);
323 if (surface) {
324 /* Write the pixels upside down into the bitmap buffer */
325 int y = surface->h;
326 while (y--) {
327 Uint8 *src = (Uint8 *) surface->pixels + y * surface->pitch;
328 SDL_RWwrite(dst, src, surface->pitch, 1);
329 }
330 SDL_FreeSurface(surface);
331
332 /* TODO: create the icon in WinCE (CreateIconFromResource isn't available) */
333 #ifndef _WIN32_WCE
334 hicon =
335 CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
336 #endif
337 }
338 SDL_RWclose(dst);
339 SDL_stack_free(icon_bmp);
340 }
341
342 /* Set the icon for the window */
343 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
344
345 /* Set the icon in the task manager (should we do this?) */
346 SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
347 }
348
349 void
350 WIN_SetWindowPosition(_THIS, SDL_Window * window)
351 {
352 SDL_VideoDisplay *display = window->display;
353 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
354 RECT rect;
355 SDL_Rect bounds;
356 DWORD style;
357 HWND top;
358 BOOL menu;
359 int x, y;
360 int w, h;
361
362 /* Figure out what the window area will be */
363 if (window->flags & SDL_WINDOW_FULLSCREEN) {
364 top = HWND_TOPMOST;
365 } else {
366 top = HWND_NOTOPMOST;
367 }
368 style = GetWindowLong(hwnd, GWL_STYLE);
369 rect.left = 0;
370 rect.top = 0;
371 rect.right = window->w;
372 rect.bottom = window->h;
373 #ifdef _WIN32_WCE
374 menu = FALSE;
375 #else
376 menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
377 #endif
378 AdjustWindowRectEx(&rect, style, menu, 0);
379 w = (rect.right - rect.left);
380 h = (rect.bottom - rect.top);
381
382 WIN_GetDisplayBounds(_this, display, &bounds);
383 if (window->flags & SDL_WINDOW_FULLSCREEN) {
384 /* The bounds when this window is visible is the fullscreen mode */
385 SDL_DisplayMode fullscreen_mode;
386 if (SDL_GetWindowDisplayMode(window, &fullscreen_mode) == 0) {
387 bounds.w = fullscreen_mode.w;
388 bounds.h = fullscreen_mode.h;
389 }
390 }
391 if ((window->flags & SDL_WINDOW_FULLSCREEN)
392 || window->x == SDL_WINDOWPOS_CENTERED) {
393 x = bounds.x + (bounds.w - w) / 2;
394 } else {
395 x = bounds.x + window->x + rect.left;
396 }
397 if ((window->flags & SDL_WINDOW_FULLSCREEN)
398 || window->y == SDL_WINDOWPOS_CENTERED) {
399 y = bounds.y + (bounds.h - h) / 2;
400 } else {
401 y = bounds.y + window->y + rect.top;
402 }
403
404 SetWindowPos(hwnd, top, x, y, 0, 0, (SWP_NOCOPYBITS | SWP_NOSIZE));
405 }
406
407 void
408 WIN_SetWindowSize(_THIS, SDL_Window * window)
409 {
410 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
411 RECT rect;
412 DWORD style;
413 HWND top;
414 BOOL menu;
415 int w, h;
416
417 /* Figure out what the window area will be */
418 if (window->flags & SDL_WINDOW_FULLSCREEN) {
419 top = HWND_TOPMOST;
420 } else {
421 top = HWND_NOTOPMOST;
422 }
423 style = GetWindowLong(hwnd, GWL_STYLE);
424 rect.left = 0;
425 rect.top = 0;
426 rect.right = window->w;
427 rect.bottom = window->h;
428 #ifdef _WIN32_WCE
429 menu = FALSE;
430 #else
431 menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
432 #endif
433 AdjustWindowRectEx(&rect, style, menu, 0);
434 w = (rect.right - rect.left);
435 h = (rect.bottom - rect.top);
436
437 SetWindowPos(hwnd, top, 0, 0, w, h, (SWP_NOCOPYBITS | SWP_NOMOVE));
438 }
439
440 void
441 WIN_ShowWindow(_THIS, SDL_Window * window)
442 {
443 #ifdef _WIN32_WCE
444 WINCE_ShowWindow(_this, window, 1);
445 #else
446 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
447 ShowWindow(hwnd, SW_SHOW);
448 #endif
449 }
450
451 void
452 WIN_HideWindow(_THIS, SDL_Window * window)
453 {
454 #ifdef _WIN32_WCE
455 WINCE_ShowWindow(_this, window, 0);
456 #else
457 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
458 ShowWindow(hwnd, SW_HIDE);
459 #endif
460 }
461
462 void
463 WIN_RaiseWindow(_THIS, SDL_Window * window)
464 {
465 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
466 HWND top;
467
468 if (window->flags & SDL_WINDOW_FULLSCREEN) {
469 top = HWND_TOPMOST;
470 } else {
471 top = HWND_NOTOPMOST;
472 }
473 SetWindowPos(hwnd, top, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE));
474 }
475
476 void
477 WIN_MaximizeWindow(_THIS, SDL_Window * window)
478 {
479 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
480 SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
481
482 #ifdef _WIN32_WCE
483 if((window->flags & SDL_WINDOW_FULLSCREEN) && videodata->SHFullScreen)
484 videodata->SHFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON);
485 #endif
486
487 ShowWindow(hwnd, SW_MAXIMIZE);
488 }
489
490 void
491 WIN_MinimizeWindow(_THIS, SDL_Window * window)
492 {
493 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
494 SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
495
496 ShowWindow(hwnd, SW_MINIMIZE);
497
498 #ifdef _WIN32_WCE
499 if((window->flags & SDL_WINDOW_FULLSCREEN) && videodata->SHFullScreen)
500 videodata->SHFullScreen(hwnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON | SHFS_SHOWSIPBUTTON);
501 #endif
502 }
503
504 void
505 WIN_RestoreWindow(_THIS, SDL_Window * window)
506 {
507 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
508
509 ShowWindow(hwnd, SW_RESTORE);
510 }
511
512 void
513 WIN_SetWindowGrab(_THIS, SDL_Window * window)
514 {
515 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
516
517 if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
518 && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
519 RECT rect;
520 GetClientRect(hwnd, &rect);
521 ClientToScreen(hwnd, (LPPOINT) & rect);
522 ClientToScreen(hwnd, (LPPOINT) & rect + 1);
523 ClipCursor(&rect);
524 } else {
525 ClipCursor(NULL);
526 }
527 }
528
529 void
530 WIN_DestroyWindow(_THIS, SDL_Window * window)
531 {
532 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
533
534 if (data) {
535 #ifdef _WIN32_WCE
536 WINCE_ShowWindow(_this, window, 0);
537 #endif
538 ReleaseDC(data->hwnd, data->hdc);
539 if (data->created) {
540 DestroyWindow(data->hwnd);
541 }
542 SDL_free(data);
543 }
544 }
545
546 SDL_bool
547 WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
548 {
549 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
550 if (info->version.major <= SDL_MAJOR_VERSION) {
551 info->subsystem = SDL_SYSWM_WINDOWS;
552 info->info.win.window = hwnd;
553 return SDL_TRUE;
554 } else {
555 SDL_SetError("Application not compiled with SDL %d.%d\n",
556 SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
557 return SDL_FALSE;
558 }
559 }
560
561
562 /*
563 * Creates a HelperWindow used for DirectInput events.
564 */
565 int
566 SDL_HelperWindowCreate(void)
567 {
568 HINSTANCE hInstance = GetModuleHandle(NULL);
569 WNDCLASS wce;
570 HWND hWndParent = NULL;
571
572 /* Make sure window isn't created twice. */
573 if (SDL_HelperWindow != NULL) {
574 return 0;
575 }
576
577 /* Create the class. */
578 SDL_zero(wce);
579 wce.lpfnWndProc = DefWindowProc;
580 wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
581 wce.hInstance = hInstance;
582
583 /* Register the class. */
584 SDL_HelperWindowClass = RegisterClass(&wce);
585 if (SDL_HelperWindowClass == 0) {
586 WIN_SetError("Unable to create Helper Window Class");
587 return -1;
588 }
589
590 #ifndef _WIN32_WCE
591 /* WinCE doesn't have HWND_MESSAGE */
592 hWndParent = HWND_MESSAGE;
593 #endif
594
595 /* Create the window. */
596 SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
597 SDL_HelperWindowName,
598 WS_OVERLAPPED, CW_USEDEFAULT,
599 CW_USEDEFAULT, CW_USEDEFAULT,
600 CW_USEDEFAULT, hWndParent, NULL,
601 hInstance, NULL);
602 if (SDL_HelperWindow == NULL) {
603 UnregisterClass(SDL_HelperWindowClassName, hInstance);
604 WIN_SetError("Unable to create Helper Window");
605 return -1;
606 }
607
608 return 0;
609 }
610
611
612 /*
613 * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
614 */
615 void
616 SDL_HelperWindowDestroy(void)
617 {
618 HINSTANCE hInstance = GetModuleHandle(NULL);
619
620 /* Destroy the window. */
621 if (SDL_HelperWindow != NULL) {
622 if (DestroyWindow(SDL_HelperWindow) == 0) {
623 WIN_SetError("Unable to destroy Helper Window");
624 return;
625 }
626 SDL_HelperWindow = NULL;
627 }
628
629 /* Unregister the class. */
630 if (SDL_HelperWindowClass != 0) {
631 if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
632 WIN_SetError("Unable to destroy Helper Window Class");
633 return;
634 }
635 SDL_HelperWindowClass = 0;
636 }
637 }
638
639 /* vi: set ts=4 sw=4 expandtab: */