SDL 2.0
SDL_windowswindow.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "../../SDL_internal.h"
22
23#if SDL_VIDEO_DRIVER_WINDOWS
24
25#include "../../core/windows/SDL_windows.h"
26
27#include "SDL_assert.h"
28#include "../SDL_sysvideo.h"
29#include "../SDL_pixels_c.h"
30#include "../../events/SDL_keyboard_c.h"
31#include "../../events/SDL_mouse_c.h"
32
33#include "SDL_windowsvideo.h"
34#include "SDL_windowswindow.h"
35#include "SDL_hints.h"
36
37/* Dropfile support */
38#include <shellapi.h>
39
40/* This is included after SDL_windowsvideo.h, which includes windows.h */
41#include "SDL_syswm.h"
42
43/* Windows CE compatibility */
44#ifndef SWP_NOCOPYBITS
45#define SWP_NOCOPYBITS 0
46#endif
47
48/* Fake window to help with DirectInput events. */
49HWND SDL_HelperWindow = NULL;
50static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
51static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
52static ATOM SDL_HelperWindowClass = 0;
53
54/* For borderless Windows, still want the following flags:
55 - WS_CAPTION: this seems to enable the Windows minimize animation
56 - WS_SYSMENU: enables system context menu on task bar
57 - WS_MINIMIZEBOX: window will respond to Windows minimize commands sent to all windows, such as windows key + m, shaking title bar, etc.
58 This will also cause the task bar to overlap the window and other windowed behaviors, so only use this for windows that shouldn't appear to be fullscreen
59 */
60
61#define STYLE_BASIC (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
62#define STYLE_FULLSCREEN (WS_POPUP)
63#define STYLE_BORDERLESS (WS_POPUP)
64#define STYLE_BORDERLESS_WINDOWED (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
65#define STYLE_NORMAL (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
66#define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
67#define STYLE_MASK (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
68
69static DWORD
70GetWindowStyle(SDL_Window * window)
71{
72 DWORD style = 0;
73
74 if (window->flags & SDL_WINDOW_FULLSCREEN) {
75 style |= STYLE_FULLSCREEN;
76 } else {
77 if (window->flags & SDL_WINDOW_BORDERLESS) {
78 /* SDL 2.1:
79 This behavior more closely matches other platform where the window is borderless
80 but still interacts with the window manager (e.g. task bar shows above it, it can
81 be resized to fit within usable desktop area, etc.) so this should be the behavior
82 for a future SDL release.
83
84 If you want a borderless window the size of the desktop that looks like a fullscreen
85 window, then you should use the SDL_WINDOW_FULLSCREEN_DESKTOP flag.
86 */
87 if (SDL_GetHintBoolean("SDL_BORDERLESS_WINDOWED_STYLE", SDL_FALSE)) {
88 style |= STYLE_BORDERLESS_WINDOWED;
89 } else {
90 style |= STYLE_BORDERLESS;
91 }
92 } else {
93 style |= STYLE_NORMAL;
94 }
95
96 /* You can have a borderless resizable window */
97 if (window->flags & SDL_WINDOW_RESIZABLE) {
98 style |= STYLE_RESIZABLE;
99 }
100
101 /* Need to set initialize minimize style, or when we call ShowWindow with WS_MINIMIZE it will activate a random window */
102 if (window->flags & SDL_WINDOW_MINIMIZED) {
103 style |= WS_MINIMIZE;
104 }
105 }
106 return style;
107}
108
109static void
110WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current)
111{
112 RECT rect;
113
114 rect.left = 0;
115 rect.top = 0;
116 rect.right = (use_current ? window->w : window->windowed.w);
117 rect.bottom = (use_current ? window->h : window->windowed.h);
118
119 /* borderless windows will have WM_NCCALCSIZE return 0 for the non-client area. When this happens, it looks like windows will send a resize message
120 expanding the window client area to the previous window + chrome size, so shouldn't need to adjust the window size for the set styles.
121 */
122 if (!(window->flags & SDL_WINDOW_BORDERLESS))
123 AdjustWindowRectEx(&rect, style, menu, 0);
124
125 *x = (use_current ? window->x : window->windowed.x) + rect.left;
126 *y = (use_current ? window->y : window->windowed.y) + rect.top;
127 *width = (rect.right - rect.left);
128 *height = (rect.bottom - rect.top);
129}
130
131static void
132WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_bool use_current)
133{
134 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
135 HWND hwnd = data->hwnd;
136 DWORD style;
137 BOOL menu;
138
139 style = GetWindowLong(hwnd, GWL_STYLE);
140 menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
141 WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current);
142}
143
144static void
145WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
146{
147 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
148 HWND hwnd = data->hwnd;
149 HWND top;
150 int x, y;
151 int w, h;
152
153 /* Figure out what the window area will be */
155 top = HWND_TOPMOST;
156 } else {
157 top = HWND_NOTOPMOST;
158 }
159
160 WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
161
162 data->expected_resize = SDL_TRUE;
163 SetWindowPos(hwnd, top, x, y, w, h, flags);
164 data->expected_resize = SDL_FALSE;
165}
166
167static int
168SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
169{
172
173 /* Allocate the window data */
174 data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
175 if (!data) {
176 return SDL_OutOfMemory();
177 }
178 data->window = window;
179 data->hwnd = hwnd;
180 data->parent = parent;
181 data->hdc = GetDC(hwnd);
182 data->hinstance = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
183 data->created = created;
184 data->mouse_button_flags = 0;
185 data->videodata = videodata;
186 data->initializing = SDL_TRUE;
187
188 window->driverdata = data;
189
190 /* Associate the data with the window */
191 if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
192 ReleaseDC(hwnd, data->hdc);
193 SDL_free(data);
194 return WIN_SetError("SetProp() failed");
195 }
196
197 /* Set up the window proc function */
198#ifdef GWLP_WNDPROC
199 data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
200 if (data->wndproc == WIN_WindowProc) {
201 data->wndproc = NULL;
202 } else {
203 SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
204 }
205#else
206 data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
207 if (data->wndproc == WIN_WindowProc) {
208 data->wndproc = NULL;
209 } else {
210 SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
211 }
212#endif
213
214 /* Fill in the SDL window with the window data */
215 {
216 RECT rect;
217 if (GetClientRect(hwnd, &rect)) {
218 int w = rect.right;
219 int h = rect.bottom;
220 if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) {
221 /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */
222 int x, y;
223 /* Figure out what the window area will be */
224 WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_FALSE);
225 SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
226 } else {
227 window->w = w;
228 window->h = h;
229 }
230 }
231 }
232 {
233 POINT point;
234 point.x = 0;
235 point.y = 0;
236 if (ClientToScreen(hwnd, &point)) {
237 window->x = point.x;
238 window->y = point.y;
239 }
240 }
241 {
242 DWORD style = GetWindowLong(hwnd, GWL_STYLE);
243 if (style & WS_VISIBLE) {
244 window->flags |= SDL_WINDOW_SHOWN;
245 } else {
246 window->flags &= ~SDL_WINDOW_SHOWN;
247 }
248 if (style & WS_POPUP) {
250 } else {
251 window->flags &= ~SDL_WINDOW_BORDERLESS;
252 }
253 if (style & WS_THICKFRAME) {
255 } else {
256 window->flags &= ~SDL_WINDOW_RESIZABLE;
257 }
258#ifdef WS_MAXIMIZE
259 if (style & WS_MAXIMIZE) {
261 } else
262#endif
263 {
264 window->flags &= ~SDL_WINDOW_MAXIMIZED;
265 }
266#ifdef WS_MINIMIZE
267 if (style & WS_MINIMIZE) {
269 } else
270#endif
271 {
272 window->flags &= ~SDL_WINDOW_MINIMIZED;
273 }
274 }
275 if (GetFocus() == hwnd) {
277 SDL_SetKeyboardFocus(data->window);
278
279 if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
280 RECT rect;
281 GetClientRect(hwnd, &rect);
282 ClientToScreen(hwnd, (LPPOINT) & rect);
283 ClientToScreen(hwnd, (LPPOINT) & rect + 1);
284 ClipCursor(&rect);
285 }
286 }
287
288 /* Enable multi-touch */
289 if (videodata->RegisterTouchWindow) {
290 videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
291 }
292
293 data->initializing = SDL_FALSE;
294
295 /* All done! */
296 return 0;
297}
298
299
300
301int
303{
304 HWND hwnd, parent = NULL;
305 DWORD style = STYLE_BASIC;
306 int x, y;
307 int w, h;
308
309 if (window->flags & SDL_WINDOW_SKIP_TASKBAR) {
310 parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL);
311 }
312
313 style |= GetWindowStyle(window);
314
315 /* Figure out what the window area will be */
316 WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE);
317
318 hwnd =
319 CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
321 if (!hwnd) {
322 return WIN_SetError("Couldn't create window");
323 }
324
326
327 if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) {
328 DestroyWindow(hwnd);
329 if (parent) {
330 DestroyWindow(parent);
331 }
332 return -1;
333 }
334
335 /* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */
336 SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
337
338 if (window->flags & SDL_WINDOW_MINIMIZED) {
339 ShowWindow(hwnd, SW_SHOWMINNOACTIVE);
340 }
341
342 if (!(window->flags & SDL_WINDOW_OPENGL)) {
343 return 0;
344 }
345
346 /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
347#if SDL_VIDEO_OPENGL_ES2
350 && (!_this->gl_data || WIN_GL_UseEGL(_this))
351#endif /* SDL_VIDEO_OPENGL_WGL */
352 ) {
353#if SDL_VIDEO_OPENGL_EGL
354 if (WIN_GLES_SetupWindow(_this, window) < 0) {
356 return -1;
357 }
358 return 0;
359#else
360 return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
361#endif /* SDL_VIDEO_OPENGL_EGL */
362 }
363#endif /* SDL_VIDEO_OPENGL_ES2 */
364
365#if SDL_VIDEO_OPENGL_WGL
366 if (WIN_GL_SetupWindow(_this, window) < 0) {
368 return -1;
369 }
370#else
371 return SDL_SetError("Could not create GL window (WGL support not configured)");
372#endif
373
374 return 0;
375}
376
377int
379{
380 HWND hwnd = (HWND) data;
381 LPTSTR title;
382 int titleLen;
383 SDL_bool isstack;
384
385 /* Query the title from the existing window */
386 titleLen = GetWindowTextLength(hwnd);
387 title = SDL_small_alloc(TCHAR, titleLen + 1, &isstack);
388 if (title) {
389 titleLen = GetWindowText(hwnd, title, titleLen + 1);
390 } else {
391 titleLen = 0;
392 }
393 if (titleLen > 0) {
394 window->title = WIN_StringToUTF8(title);
395 }
396 if (title) {
397 SDL_small_free(title, isstack);
398 }
399
400 if (SetupWindowData(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) {
401 return -1;
402 }
403
404#if SDL_VIDEO_OPENGL_WGL
405 {
407 if (hint) {
408 /* This hint is a pointer (in string form) of the address of
409 the window to share a pixel format with
410 */
411 SDL_Window *otherWindow = NULL;
412 SDL_sscanf(hint, "%p", (void**)&otherWindow);
413
414 /* Do some error checking on the pointer */
415 if (otherWindow != NULL && otherWindow->magic == &_this->window_magic) {
416 /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */
417 if (otherWindow->flags & SDL_WINDOW_OPENGL) {
418 window->flags |= SDL_WINDOW_OPENGL;
419 if (!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
420 return -1;
421 }
422 }
423 }
424 }
425 }
426#endif
427 return 0;
428}
429
430void
432{
433 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
434 LPTSTR title = WIN_UTF8ToString(window->title);
435 SetWindowText(hwnd, title);
436 SDL_free(title);
437}
438
439void
441{
442 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
443 HICON hicon = NULL;
444 BYTE *icon_bmp;
445 int icon_len, mask_len, y;
446 SDL_RWops *dst;
447 SDL_bool isstack;
448
449 /* Create temporary buffer for ICONIMAGE structure */
450 mask_len = (icon->h * (icon->w + 7)/8);
451 icon_len = 40 + icon->h * icon->w * sizeof(Uint32) + mask_len;
452 icon_bmp = SDL_small_alloc(BYTE, icon_len, &isstack);
453 dst = SDL_RWFromMem(icon_bmp, icon_len);
454 if (!dst) {
455 SDL_small_free(icon_bmp, isstack);
456 return;
457 }
458
459 /* Write the BITMAPINFO header */
460 SDL_WriteLE32(dst, 40);
461 SDL_WriteLE32(dst, icon->w);
462 SDL_WriteLE32(dst, icon->h * 2);
463 SDL_WriteLE16(dst, 1);
464 SDL_WriteLE16(dst, 32);
466 SDL_WriteLE32(dst, icon->h * icon->w * sizeof(Uint32));
467 SDL_WriteLE32(dst, 0);
468 SDL_WriteLE32(dst, 0);
469 SDL_WriteLE32(dst, 0);
470 SDL_WriteLE32(dst, 0);
471
472 /* Write the pixels upside down into the bitmap buffer */
474 y = icon->h;
475 while (y--) {
476 Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
477 SDL_RWwrite(dst, src, icon->w * sizeof(Uint32), 1);
478 }
479
480 /* Write the mask */
481 SDL_memset(icon_bmp + icon_len - mask_len, 0xFF, mask_len);
482
483 hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
484
486 SDL_small_free(icon_bmp, isstack);
487
488 /* Set the icon for the window */
489 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
490
491 /* Set the icon in the task manager (should we do this?) */
492 SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
493}
494
495void
497{
498 WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
499}
500
501void
503{
504 WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
505}
506
507int
509{
510 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
511 RECT rcClient, rcWindow;
512 POINT ptDiff;
513
514 /* rcClient stores the size of the inner window, while rcWindow stores the outer size relative to the top-left
515 * screen position; so the top/left values of rcClient are always {0,0} and bottom/right are {height,width} */
516 GetClientRect(hwnd, &rcClient);
517 GetWindowRect(hwnd, &rcWindow);
518
519 /* convert the top/left values to make them relative to
520 * the window; they will end up being slightly negative */
521 ptDiff.y = rcWindow.top;
522 ptDiff.x = rcWindow.left;
523
524 ScreenToClient(hwnd, &ptDiff);
525
526 rcWindow.top = ptDiff.y;
527 rcWindow.left = ptDiff.x;
528
529 /* convert the bottom/right values to make them relative to the window,
530 * these will be slightly bigger than the inner width/height */
531 ptDiff.y = rcWindow.bottom;
532 ptDiff.x = rcWindow.right;
533
534 ScreenToClient(hwnd, &ptDiff);
535
536 rcWindow.bottom = ptDiff.y;
537 rcWindow.right = ptDiff.x;
538
539 /* Now that both the inner and outer rects use the same coordinate system we can substract them to get the border size.
540 * Keep in mind that the top/left coordinates of rcWindow are negative because the border lies slightly before {0,0},
541 * so switch them around because SDL2 wants them in positive. */
542 *top = rcClient.top - rcWindow.top;
543 *left = rcClient.left - rcWindow.left;
544 *bottom = rcWindow.bottom - rcClient.bottom;
545 *right = rcWindow.right - rcClient.right;
546
547 return 0;
548}
549
550void
552{
553 DWORD style;
554 HWND hwnd;
555 int nCmdShow;
556
557 hwnd = ((SDL_WindowData *)window->driverdata)->hwnd;
558 nCmdShow = SW_SHOW;
559 style = GetWindowLong(hwnd, GWL_EXSTYLE);
560 if (style & WS_EX_NOACTIVATE) {
561 nCmdShow = SW_SHOWNOACTIVATE;
562 }
563 ShowWindow(hwnd, nCmdShow);
564}
565
566void
568{
569 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
570 ShowWindow(hwnd, SW_HIDE);
571}
572
573void
575{
576 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
577 SetForegroundWindow(hwnd);
578}
579
580void
582{
583 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
584 HWND hwnd = data->hwnd;
585 data->expected_resize = SDL_TRUE;
586 ShowWindow(hwnd, SW_MAXIMIZE);
587 data->expected_resize = SDL_FALSE;
588}
589
590void
592{
593 HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
594 ShowWindow(hwnd, SW_MINIMIZE);
595}
596
597void
599{
600 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
601 HWND hwnd = data->hwnd;
602 DWORD style;
603
604 style = GetWindowLong(hwnd, GWL_STYLE);
605 style &= ~STYLE_MASK;
606 style |= GetWindowStyle(window);
607
608 data->in_border_change = SDL_TRUE;
609 SetWindowLong(hwnd, GWL_STYLE, style);
610 WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
611 data->in_border_change = SDL_FALSE;
612}
613
614void
616{
617 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
618 HWND hwnd = data->hwnd;
619 DWORD style;
620
621 style = GetWindowLong(hwnd, GWL_STYLE);
622 style &= ~STYLE_MASK;
623 style |= GetWindowStyle(window);
624
625 SetWindowLong(hwnd, GWL_STYLE, style);
626}
627
628void
630{
631 SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
632 HWND hwnd = data->hwnd;
633 data->expected_resize = SDL_TRUE;
634 ShowWindow(hwnd, SW_RESTORE);
635 data->expected_resize = SDL_FALSE;
636}
637
638void
640{
641 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
642 HWND hwnd = data->hwnd;
643 SDL_Rect bounds;
644 DWORD style;
645 HWND top;
646 int x, y;
647 int w, h;
648
650 top = HWND_TOPMOST;
651 } else {
652 top = HWND_NOTOPMOST;
653 }
654
655 style = GetWindowLong(hwnd, GWL_STYLE);
656 style &= ~STYLE_MASK;
657 style |= GetWindowStyle(window);
658
659 WIN_GetDisplayBounds(_this, display, &bounds);
660
661 if (fullscreen) {
662 x = bounds.x;
663 y = bounds.y;
664 w = bounds.w;
665 h = bounds.h;
666
667 /* Unset the maximized flag. This fixes
668 https://bugzilla.libsdl.org/show_bug.cgi?id=3215
669 */
670 if (style & WS_MAXIMIZE) {
671 data->windowed_mode_was_maximized = SDL_TRUE;
672 style &= ~WS_MAXIMIZE;
673 }
674 } else {
675 BOOL menu;
676
677 /* Restore window-maximization state, as applicable.
678 Special care is taken to *not* do this if and when we're
679 alt-tab'ing away (to some other window; as indicated by
680 in_window_deactivation), otherwise
681 https://bugzilla.libsdl.org/show_bug.cgi?id=3215 can reproduce!
682 */
683 if (data->windowed_mode_was_maximized && !data->in_window_deactivation) {
684 style |= WS_MAXIMIZE;
685 data->windowed_mode_was_maximized = SDL_FALSE;
686 }
687
688 menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
689 WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE);
690 }
691 SetWindowLong(hwnd, GWL_STYLE, style);
692 data->expected_resize = SDL_TRUE;
693 SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS | SWP_NOACTIVATE);
694 data->expected_resize = SDL_FALSE;
695}
696
697int
699{
702 HDC hdc;
703 BOOL succeeded = FALSE;
704
705 hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
706 if (hdc) {
707 succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
708 if (!succeeded) {
709 WIN_SetError("SetDeviceGammaRamp()");
710 }
711 DeleteDC(hdc);
712 }
713 return succeeded ? 0 : -1;
714}
715
716int
718{
721 HDC hdc;
722 BOOL succeeded = FALSE;
723
724 hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
725 if (hdc) {
726 succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
727 if (!succeeded) {
728 WIN_SetError("GetDeviceGammaRamp()");
729 }
730 DeleteDC(hdc);
731 }
732 return succeeded ? 0 : -1;
733}
734
735void
737{
739
740 if (window->flags & SDL_WINDOW_FULLSCREEN) {
741 UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
742
743 if (!(window->flags & SDL_WINDOW_SHOWN)) {
744 flags |= SWP_NOACTIVATE;
745 }
746 WIN_SetWindowPositionInternal(_this, window, flags);
747 }
748}
749
750void
752{
753 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
754
755 if (data) {
756 ReleaseDC(data->hwnd, data->hdc);
757 RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
758 if (data->created) {
759 DestroyWindow(data->hwnd);
760 if (data->parent) {
761 DestroyWindow(data->parent);
762 }
763 } else {
764 /* Restore any original event handler... */
765 if (data->wndproc != NULL) {
766#ifdef GWLP_WNDPROC
767 SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
768 (LONG_PTR) data->wndproc);
769#else
770 SetWindowLong(data->hwnd, GWL_WNDPROC,
771 (LONG_PTR) data->wndproc);
772#endif
773 }
774 }
775 SDL_free(data);
776 }
777 window->driverdata = NULL;
778}
779
782{
783 const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
784 if (info->version.major <= SDL_MAJOR_VERSION) {
785 int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch);
786
788 info->info.win.window = data->hwnd;
789
790 if (versionnum >= SDL_VERSIONNUM(2, 0, 4)) {
791 info->info.win.hdc = data->hdc;
792 }
793
794 if (versionnum >= SDL_VERSIONNUM(2, 0, 5)) {
795 info->info.win.hinstance = data->hinstance;
796 }
797
798 return SDL_TRUE;
799 } else {
800 SDL_SetError("Application not compiled with SDL %d.%d",
802 return SDL_FALSE;
803 }
804}
805
806
807/*
808 * Creates a HelperWindow used for DirectInput events.
809 */
810int
811SDL_HelperWindowCreate(void)
812{
813 HINSTANCE hInstance = GetModuleHandle(NULL);
814 WNDCLASS wce;
815
816 /* Make sure window isn't created twice. */
817 if (SDL_HelperWindow != NULL) {
818 return 0;
819 }
820
821 /* Create the class. */
822 SDL_zero(wce);
823 wce.lpfnWndProc = DefWindowProc;
824 wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
825 wce.hInstance = hInstance;
826
827 /* Register the class. */
828 SDL_HelperWindowClass = RegisterClass(&wce);
829 if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
830 return WIN_SetError("Unable to create Helper Window Class");
831 }
832
833 /* Create the window. */
834 SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
835 SDL_HelperWindowName,
836 WS_OVERLAPPED, CW_USEDEFAULT,
837 CW_USEDEFAULT, CW_USEDEFAULT,
838 CW_USEDEFAULT, HWND_MESSAGE, NULL,
839 hInstance, NULL);
840 if (SDL_HelperWindow == NULL) {
841 UnregisterClass(SDL_HelperWindowClassName, hInstance);
842 return WIN_SetError("Unable to create Helper Window");
843 }
844
845 return 0;
846}
847
848
849/*
850 * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
851 */
852void
853SDL_HelperWindowDestroy(void)
854{
855 HINSTANCE hInstance = GetModuleHandle(NULL);
856
857 /* Destroy the window. */
858 if (SDL_HelperWindow != NULL) {
859 if (DestroyWindow(SDL_HelperWindow) == 0) {
860 WIN_SetError("Unable to destroy Helper Window");
861 return;
862 }
863 SDL_HelperWindow = NULL;
864 }
865
866 /* Unregister the class. */
867 if (SDL_HelperWindowClass != 0) {
868 if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
869 WIN_SetError("Unable to destroy Helper Window Class");
870 return;
871 }
872 SDL_HelperWindowClass = 0;
873 }
874}
875
877{
878 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
879
880 if (!data || !data->hwnd) {
881 /* The window wasn't fully initialized */
882 return;
883 }
884
885 if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
886 WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
887 }
888
889#ifdef WM_MOUSELEAVE
890 {
891 TRACKMOUSEEVENT trackMouseEvent;
892
893 trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
894 trackMouseEvent.dwFlags = TME_LEAVE;
895 trackMouseEvent.hwndTrack = data->hwnd;
896
897 TrackMouseEvent(&trackMouseEvent);
898 }
899#endif /* WM_MOUSELEAVE */
900}
901
902void
904{
905 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
906 SDL_Mouse *mouse = SDL_GetMouse();
907 RECT rect;
908
909 if (data->in_title_click || data->focus_click_pending) {
910 return;
911 }
912 if (data->skip_update_clipcursor) {
913 data->skip_update_clipcursor = SDL_FALSE;
914 return;
915 }
916
917 if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
918 (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
919 if (mouse->relative_mode && !mouse->relative_mode_warp) {
920 LONG cx, cy;
921 GetWindowRect(data->hwnd, &rect);
922
923 cx = (rect.left + rect.right) / 2;
924 cy = (rect.top + rect.bottom) / 2;
925
926 /* Make an absurdly small clip rect */
927 rect.left = cx - 1;
928 rect.right = cx + 1;
929 rect.top = cy - 1;
930 rect.bottom = cy + 1;
931
932 if (ClipCursor(&rect)) {
933 data->cursor_clipped_rect = rect;
934 }
935 } else {
936 if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
937 ClientToScreen(data->hwnd, (LPPOINT) & rect);
938 ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
939 if (ClipCursor(&rect)) {
940 data->cursor_clipped_rect = rect;
941 }
942 }
943 }
944 } else if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) {
945 ClipCursor(NULL);
946 SDL_zero(data->cursor_clipped_rect);
947 }
948}
949
950int
952{
953 return 0; /* just succeed, the real work is done elsewhere. */
954}
955
956int
958{
959 const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
960 const HWND hwnd = data->hwnd;
961 const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
962
963 SDL_assert(style != 0);
964
965 if (opacity == 1.0f) {
966 /* want it fully opaque, just mark it unlayered if necessary. */
967 if (style & WS_EX_LAYERED) {
968 if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
969 return WIN_SetError("SetWindowLong()");
970 }
971 }
972 } else {
973 const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
974 /* want it transparent, mark it layered if necessary. */
975 if ((style & WS_EX_LAYERED) == 0) {
976 if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
977 return WIN_SetError("SetWindowLong()");
978 }
979 }
980
981 if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
982 return WIN_SetError("SetLayeredWindowAttributes()");
983 }
984 }
985
986 return 0;
987}
988
989void
991{
992 const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
993 DragAcceptFiles(data->hwnd, accept ? TRUE : FALSE);
994}
995
996#endif /* SDL_VIDEO_DRIVER_WINDOWS */
997
998/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define BI_RGB
Definition: SDL_bmp.c:45
#define SDL_VIDEO_OPENGL_WGL
#define SDL_SetError
#define SDL_memset
#define SDL_RWwrite
#define SDL_WriteLE16
#define SDL_RWFromMem
#define SDL_free
#define SDL_memcmp
#define SDL_GetHintBoolean
#define SDL_sscanf
#define SDL_WriteLE32
#define SDL_calloc
#define SDL_GetHint
#define SDL_RWclose
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT
A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
Definition: SDL_hints.h:695
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLdouble GLdouble GLdouble GLdouble top
GLenum src
GLint left
GLenum GLenum dst
GLbitfield flags
GLint GLint bottom
GLfloat GLfloat GLfloat alpha
GLdouble GLdouble right
GLfloat GLfloat GLfloat GLfloat h
GLubyte GLubyte GLubyte GLubyte w
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
uint32_t Uint32
Definition: SDL_stdinc.h:203
uint16_t Uint16
Definition: SDL_stdinc.h:191
uint8_t Uint8
Definition: SDL_stdinc.h:179
SDL_bool SDL_ShouldAllowTopmost(void)
Definition: SDL_video.c:3992
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1089
@ SDL_SYSWM_WINDOWS
Definition: SDL_syswm.h:122
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
#define SDL_VERSIONNUM(X, Y, Z)
Definition: SDL_version.h:94
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
@ SDL_WINDOW_ALWAYS_ON_TOP
Definition: SDL_video.h:117
@ SDL_WINDOW_SHOWN
Definition: SDL_video.h:102
@ SDL_WINDOW_SKIP_TASKBAR
Definition: SDL_video.h:118
@ SDL_WINDOW_OPENGL
Definition: SDL_video.h:101
@ SDL_WINDOW_MINIMIZED
Definition: SDL_video.h:106
@ SDL_WINDOW_INPUT_GRABBED
Definition: SDL_video.h:108
@ SDL_WINDOW_RESIZABLE
Definition: SDL_video.h:105
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
@ SDL_WINDOW_MAXIMIZED
Definition: SDL_video.h:107
@ SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:104
@ SDL_WINDOW_INPUT_FOCUS
Definition: SDL_video.h:109
@ SDL_GL_CONTEXT_PROFILE_ES
Definition: SDL_video.h:233
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
int WIN_SetError(const char *prefix)
HINSTANCE SDL_Instance
LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
LPTSTR SDL_Appname
void WIN_PumpEvents(_THIS)
int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
#define TWF_FINETOUCH
#define TWF_WANTPALM
int WIN_GetWindowBordersSize(_THIS, SDL_Window *window, int *top, int *left, int *bottom, int *right)
void WIN_ShowWindow(_THIS, SDL_Window *window)
void WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
int WIN_SetWindowOpacity(_THIS, SDL_Window *window, float opacity)
void WIN_RaiseWindow(_THIS, SDL_Window *window)
int WIN_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
void WIN_SetWindowPosition(_THIS, SDL_Window *window)
void WIN_HideWindow(_THIS, SDL_Window *window)
void WIN_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
void WIN_DestroyWindow(_THIS, SDL_Window *window)
int WIN_GetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 *ramp)
void WIN_MinimizeWindow(_THIS, SDL_Window *window)
void WIN_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
void WIN_SetWindowTitle(_THIS, SDL_Window *window)
void WIN_MaximizeWindow(_THIS, SDL_Window *window)
void WIN_AcceptDragAndDrop(SDL_Window *window, SDL_bool accept)
void WIN_RestoreWindow(_THIS, SDL_Window *window)
void WIN_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable)
void WIN_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
void WIN_OnWindowEnter(_THIS, SDL_Window *window)
int WIN_CreateWindow(_THIS, SDL_Window *window)
SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
void WIN_UpdateClipCursor(SDL_Window *window)
int WIN_SetWindowGammaRamp(_THIS, SDL_Window *window, const Uint16 *ramp)
void WIN_SetWindowSize(_THIS, SDL_Window *window)
#define NULL
Definition: begin_code.h:167
#define TRUE
Definition: edid-parse.c:33
#define FALSE
Definition: edid-parse.c:34
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
A collection of pixels used in software blitting.
Definition: SDL_surface.h:71
SDL_PixelFormat * format
Definition: SDL_surface.h:73
void * pixels
Definition: SDL_surface.h:76
union SDL_SysWMinfo::@17 info
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:200
Window window
Definition: SDL_syswm.h:221
SDL_version version
Definition: SDL_syswm.h:199
struct SDL_VideoDevice::@262 gl_config
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:382
The type used to identify a window.
Definition: SDL_sysvideo.h:74
Uint32 flags
Definition: SDL_sysvideo.h:83
const void * magic
Definition: SDL_sysvideo.h:75
Uint8 minor
Definition: SDL_version.h:54
Uint8 patch
Definition: SDL_version.h:55
Uint8 major
Definition: SDL_version.h:53
SDL_Rect rect
Definition: testrelative.c:27