SDL  2.0
SDL_windowswindow.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 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. */
49 HWND SDL_HelperWindow = NULL;
50 static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
51 static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
52 static 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 
59 #define STYLE_BASIC (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
60 #define STYLE_FULLSCREEN (WS_POPUP)
61 #define STYLE_BORDERLESS (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
62 #define STYLE_NORMAL (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
63 #define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
64 #define STYLE_MASK (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
65 
66 static DWORD
67 GetWindowStyle(SDL_Window * window)
68 {
69  DWORD style = 0;
70 
71  if (window->flags & SDL_WINDOW_FULLSCREEN) {
72  style |= STYLE_FULLSCREEN;
73  } else {
74  if (window->flags & SDL_WINDOW_BORDERLESS) {
75  style |= STYLE_BORDERLESS;
76  } else {
77  style |= STYLE_NORMAL;
78  }
79 
80  /* You can have a borderless resizable window */
81  if (window->flags & SDL_WINDOW_RESIZABLE) {
82  style |= STYLE_RESIZABLE;
83  }
84  }
85  return style;
86 }
87 
88 static void
89 WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current)
90 {
91  RECT rect;
92 
93  rect.left = 0;
94  rect.top = 0;
95  rect.right = (use_current ? window->w : window->windowed.w);
96  rect.bottom = (use_current ? window->h : window->windowed.h);
97 
98  // 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
99  // expanding the window client area to the previous window + chrome size, so shouldn't need to adjust the window size for the set styles.
100  if (!(window->flags & SDL_WINDOW_BORDERLESS))
101  AdjustWindowRectEx(&rect, style, menu, 0);
102 
103  *x = (use_current ? window->x : window->windowed.x) + rect.left;
104  *y = (use_current ? window->y : window->windowed.y) + rect.top;
105  *width = (rect.right - rect.left);
106  *height = (rect.bottom - rect.top);
107 }
108 
109 static void
110 WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_bool use_current)
111 {
113  HWND hwnd = data->hwnd;
114  DWORD style;
115  BOOL menu;
116 
117  style = GetWindowLong(hwnd, GWL_STYLE);
118  menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
119  WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current);
120 }
121 
122 static void
123 WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
124 {
125  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
126  HWND hwnd = data->hwnd;
127  HWND top;
128  int x, y;
129  int w, h;
130 
131  /* Figure out what the window area will be */
133  top = HWND_TOPMOST;
134  } else {
135  top = HWND_NOTOPMOST;
136  }
137 
138  WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
139 
140  data->expected_resize = SDL_TRUE;
141  SetWindowPos(hwnd, top, x, y, w, h, flags);
142  data->expected_resize = SDL_FALSE;
143 }
144 
145 static int
146 SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
147 {
148  SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
149  SDL_WindowData *data;
150 
151  /* Allocate the window data */
152  data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
153  if (!data) {
154  return SDL_OutOfMemory();
155  }
156  data->window = window;
157  data->hwnd = hwnd;
158  data->parent = parent;
159  data->hdc = GetDC(hwnd);
160  data->hinstance = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
161  data->created = created;
162  data->mouse_button_flags = 0;
163  data->videodata = videodata;
164  data->initializing = SDL_TRUE;
165 
166  window->driverdata = data;
167 
168  /* Associate the data with the window */
169  if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
170  ReleaseDC(hwnd, data->hdc);
171  SDL_free(data);
172  return WIN_SetError("SetProp() failed");
173  }
174 
175  /* Set up the window proc function */
176 #ifdef GWLP_WNDPROC
177  data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
178  if (data->wndproc == WIN_WindowProc) {
179  data->wndproc = NULL;
180  } else {
181  SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
182  }
183 #else
184  data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
185  if (data->wndproc == WIN_WindowProc) {
186  data->wndproc = NULL;
187  } else {
188  SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
189  }
190 #endif
191 
192  /* Fill in the SDL window with the window data */
193  {
194  RECT rect;
195  if (GetClientRect(hwnd, &rect)) {
196  int w = rect.right;
197  int h = rect.bottom;
198  if ((window->w && window->w != w) || (window->h && window->h != h)) {
199  /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */
200  int x, y;
201  int w, h;
202 
203  /* Figure out what the window area will be */
204  WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
205  SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
206  } else {
207  window->w = w;
208  window->h = h;
209  }
210  }
211  }
212  {
213  POINT point;
214  point.x = 0;
215  point.y = 0;
216  if (ClientToScreen(hwnd, &point)) {
217  window->x = point.x;
218  window->y = point.y;
219  }
220  }
221  {
222  DWORD style = GetWindowLong(hwnd, GWL_STYLE);
223  if (style & WS_VISIBLE) {
224  window->flags |= SDL_WINDOW_SHOWN;
225  } else {
226  window->flags &= ~SDL_WINDOW_SHOWN;
227  }
228  if (style & WS_POPUP) {
229  window->flags |= SDL_WINDOW_BORDERLESS;
230  } else {
231  window->flags &= ~SDL_WINDOW_BORDERLESS;
232  }
233  if (style & WS_THICKFRAME) {
234  window->flags |= SDL_WINDOW_RESIZABLE;
235  } else {
236  window->flags &= ~SDL_WINDOW_RESIZABLE;
237  }
238 #ifdef WS_MAXIMIZE
239  if (style & WS_MAXIMIZE) {
240  window->flags |= SDL_WINDOW_MAXIMIZED;
241  } else
242 #endif
243  {
244  window->flags &= ~SDL_WINDOW_MAXIMIZED;
245  }
246 #ifdef WS_MINIMIZE
247  if (style & WS_MINIMIZE) {
248  window->flags |= SDL_WINDOW_MINIMIZED;
249  } else
250 #endif
251  {
252  window->flags &= ~SDL_WINDOW_MINIMIZED;
253  }
254  }
255  if (GetFocus() == hwnd) {
256  window->flags |= SDL_WINDOW_INPUT_FOCUS;
258 
259  if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
260  RECT rect;
261  GetClientRect(hwnd, &rect);
262  ClientToScreen(hwnd, (LPPOINT) & rect);
263  ClientToScreen(hwnd, (LPPOINT) & rect + 1);
264  ClipCursor(&rect);
265  }
266  }
267 
268  /* Enable multi-touch */
269  if (videodata->RegisterTouchWindow) {
270  videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
271  }
272 
273  /* Enable dropping files */
274  DragAcceptFiles(hwnd, TRUE);
275 
276  data->initializing = SDL_FALSE;
277 
278  /* All done! */
279  return 0;
280 }
281 
282 
283 
284 int
286 {
287  HWND hwnd, parent = NULL;
288  DWORD style = STYLE_BASIC;
289  int x, y;
290  int w, h;
291 
292  if (window->flags & SDL_WINDOW_SKIP_TASKBAR) {
293  parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL);
294  }
295 
296  style |= GetWindowStyle(window);
297 
298  /* Figure out what the window area will be */
299  WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_TRUE);
300 
301  hwnd =
302  CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
303  SDL_Instance, NULL);
304  if (!hwnd) {
305  return WIN_SetError("Couldn't create window");
306  }
307 
309 
310  if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) {
311  DestroyWindow(hwnd);
312  if (parent) {
313  DestroyWindow(parent);
314  }
315  return -1;
316  }
317 
318  // Inform Windows of the frame change so we can respond to WM_NCCALCSIZE
319  SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
320 
321  if (!(window->flags & SDL_WINDOW_OPENGL)) {
322  return 0;
323  }
324 
325  /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
326 #if SDL_VIDEO_OPENGL_ES2
329  && (!_this->gl_data || WIN_GL_UseEGL(_this))
330 #endif /* SDL_VIDEO_OPENGL_WGL */
331  ) {
332 #if SDL_VIDEO_OPENGL_EGL
333  if (WIN_GLES_SetupWindow(_this, window) < 0) {
334  WIN_DestroyWindow(_this, window);
335  return -1;
336  }
337  return 0;
338 #else
339  return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
340 #endif /* SDL_VIDEO_OPENGL_EGL */
341  }
342 #endif /* SDL_VIDEO_OPENGL_ES2 */
343 
344 #if SDL_VIDEO_OPENGL_WGL
345  if (WIN_GL_SetupWindow(_this, window) < 0) {
346  WIN_DestroyWindow(_this, window);
347  return -1;
348  }
349 #else
350  return SDL_SetError("Could not create GL window (WGL support not configured)");
351 #endif
352 
353  return 0;
354 }
355 
356 int
357 WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
358 {
359  HWND hwnd = (HWND) data;
360  LPTSTR title;
361  int titleLen;
362 
363  /* Query the title from the existing window */
364  titleLen = GetWindowTextLength(hwnd);
365  title = SDL_stack_alloc(TCHAR, titleLen + 1);
366  if (title) {
367  titleLen = GetWindowText(hwnd, title, titleLen);
368  } else {
369  titleLen = 0;
370  }
371  if (titleLen > 0) {
372  window->title = WIN_StringToUTF8(title);
373  }
374  if (title) {
375  SDL_stack_free(title);
376  }
377 
378  if (SetupWindowData(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) {
379  return -1;
380  }
381 
382 #if SDL_VIDEO_OPENGL_WGL
383  {
385  if (hint) {
386  /* This hint is a pointer (in string form) of the address of
387  the window to share a pixel format with
388  */
389  SDL_Window *otherWindow = NULL;
390  SDL_sscanf(hint, "%p", (void**)&otherWindow);
391 
392  /* Do some error checking on the pointer */
393  if (otherWindow != NULL && otherWindow->magic == &_this->window_magic)
394  {
395  /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */
396  if (otherWindow->flags & SDL_WINDOW_OPENGL)
397  {
398  window->flags |= SDL_WINDOW_OPENGL;
399  if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
400  return -1;
401  }
402  }
403  }
404  }
405  }
406 #endif
407  return 0;
408 }
409 
410 void
412 {
413  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
414  LPTSTR title = WIN_UTF8ToString(window->title);
415  SetWindowText(hwnd, title);
416  SDL_free(title);
417 }
418 
419 void
421 {
422  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
423  HICON hicon = NULL;
424  BYTE *icon_bmp;
425  int icon_len, y;
426  SDL_RWops *dst;
427 
428  /* Create temporary bitmap buffer */
429  icon_len = 40 + icon->h * icon->w * sizeof(Uint32);
430  icon_bmp = SDL_stack_alloc(BYTE, icon_len);
431  dst = SDL_RWFromMem(icon_bmp, icon_len);
432  if (!dst) {
433  SDL_stack_free(icon_bmp);
434  return;
435  }
436 
437  /* Write the BITMAPINFO header */
438  SDL_WriteLE32(dst, 40);
439  SDL_WriteLE32(dst, icon->w);
440  SDL_WriteLE32(dst, icon->h * 2);
441  SDL_WriteLE16(dst, 1);
442  SDL_WriteLE16(dst, 32);
443  SDL_WriteLE32(dst, BI_RGB);
444  SDL_WriteLE32(dst, icon->h * icon->w * sizeof(Uint32));
445  SDL_WriteLE32(dst, 0);
446  SDL_WriteLE32(dst, 0);
447  SDL_WriteLE32(dst, 0);
448  SDL_WriteLE32(dst, 0);
449 
450  /* Write the pixels upside down into the bitmap buffer */
452  y = icon->h;
453  while (y--) {
454  Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
455  SDL_RWwrite(dst, src, icon->w * sizeof(Uint32), 1);
456  }
457 
458  hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
459 
460  SDL_RWclose(dst);
461  SDL_stack_free(icon_bmp);
462 
463  /* Set the icon for the window */
464  SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
465 
466  /* Set the icon in the task manager (should we do this?) */
467  SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
468 }
469 
470 void
472 {
473  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
474 }
475 
476 void
478 {
479  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
480 }
481 
482 void
484 {
485  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
486  ShowWindow(hwnd, SW_SHOW);
487 }
488 
489 void
491 {
492  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
493  ShowWindow(hwnd, SW_HIDE);
494 }
495 
496 void
498 {
499  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
500  SetForegroundWindow(hwnd);
501 }
502 
503 void
505 {
506  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
507  HWND hwnd = data->hwnd;
508  data->expected_resize = SDL_TRUE;
509  ShowWindow(hwnd, SW_MAXIMIZE);
510  data->expected_resize = SDL_FALSE;
511 }
512 
513 void
515 {
516  HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
517  ShowWindow(hwnd, SW_MINIMIZE);
518 }
519 
520 void
521 WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
522 {
523  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
524  HWND hwnd = data->hwnd;
525  DWORD style;
526 
527  style = GetWindowLong(hwnd, GWL_STYLE);
528  style &= ~STYLE_MASK;
529  style |= GetWindowStyle(window);
530 
531  data->in_border_change = SDL_TRUE;
532  SetWindowLong(hwnd, GWL_STYLE, style);
533  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
534  data->in_border_change = SDL_FALSE;
535 }
536 
537 void
538 WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
539 {
540  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
541  HWND hwnd = data->hwnd;
542  DWORD style;
543 
544  style = GetWindowLong(hwnd, GWL_STYLE);
545  style &= ~STYLE_MASK;
546  style |= GetWindowStyle(window);
547 
548  SetWindowLong(hwnd, GWL_STYLE, style);
549 }
550 
551 void
553 {
554  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
555  HWND hwnd = data->hwnd;
556  data->expected_resize = SDL_TRUE;
557  ShowWindow(hwnd, SW_RESTORE);
558  data->expected_resize = SDL_FALSE;
559 }
560 
561 void
562 WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
563 {
564  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
565  HWND hwnd = data->hwnd;
566  SDL_Rect bounds;
567  DWORD style;
568  HWND top;
569  int x, y;
570  int w, h;
571 
573  top = HWND_TOPMOST;
574  } else {
575  top = HWND_NOTOPMOST;
576  }
577 
578  style = GetWindowLong(hwnd, GWL_STYLE);
579  style &= ~STYLE_MASK;
580  style |= GetWindowStyle(window);
581 
582  WIN_GetDisplayBounds(_this, display, &bounds);
583 
584  if (fullscreen) {
585  x = bounds.x;
586  y = bounds.y;
587  w = bounds.w;
588  h = bounds.h;
589 
590  /* Unset the maximized flag. This fixes
591  https://bugzilla.libsdl.org/show_bug.cgi?id=3215
592  */
593  if (style & WS_MAXIMIZE) {
595  style &= ~WS_MAXIMIZE;
596  }
597  } else {
598  BOOL menu;
599 
600  /* Restore window-maximization state, as applicable.
601  Special care is taken to *not* do this if and when we're
602  alt-tab'ing away (to some other window; as indicated by
603  in_window_deactivation), otherwise
604  https://bugzilla.libsdl.org/show_bug.cgi?id=3215 can reproduce!
605  */
607  style |= WS_MAXIMIZE;
609  }
610 
611  menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
612  WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE);
613  }
614  SetWindowLong(hwnd, GWL_STYLE, style);
615  data->expected_resize = SDL_TRUE;
616  SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS | SWP_NOACTIVATE);
617  data->expected_resize = SDL_FALSE;
618 }
619 
620 int
621 WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
622 {
623  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
624  SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
625  HDC hdc;
626  BOOL succeeded = FALSE;
627 
628  hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
629  if (hdc) {
630  succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
631  if (!succeeded) {
632  WIN_SetError("SetDeviceGammaRamp()");
633  }
634  DeleteDC(hdc);
635  }
636  return succeeded ? 0 : -1;
637 }
638 
639 int
641 {
642  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
643  SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
644  HDC hdc;
645  BOOL succeeded = FALSE;
646 
647  hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
648  if (hdc) {
649  succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
650  if (!succeeded) {
651  WIN_SetError("GetDeviceGammaRamp()");
652  }
653  DeleteDC(hdc);
654  }
655  return succeeded ? 0 : -1;
656 }
657 
658 void
659 WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
660 {
661  WIN_UpdateClipCursor(window);
662 
663  if (window->flags & SDL_WINDOW_FULLSCREEN) {
664  UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
665 
666  if (!(window->flags & SDL_WINDOW_SHOWN)) {
667  flags |= SWP_NOACTIVATE;
668  }
669  WIN_SetWindowPositionInternal(_this, window, flags);
670  }
671 }
672 
673 void
675 {
676  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
677 
678  if (data) {
679  ReleaseDC(data->hwnd, data->hdc);
680  RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
681  if (data->created) {
682  DestroyWindow(data->hwnd);
683  if (data->parent) {
684  DestroyWindow(data->parent);
685  }
686  } else {
687  /* Restore any original event handler... */
688  if (data->wndproc != NULL) {
689 #ifdef GWLP_WNDPROC
690  SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
691  (LONG_PTR) data->wndproc);
692 #else
693  SetWindowLong(data->hwnd, GWL_WNDPROC,
694  (LONG_PTR) data->wndproc);
695 #endif
696  }
697  }
698  SDL_free(data);
699  }
700  window->driverdata = NULL;
701 }
702 
703 SDL_bool
705 {
706  const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
707  if (info->version.major <= SDL_MAJOR_VERSION) {
708  int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch);
709 
711  info->info.win.window = data->hwnd;
712 
713  if (versionnum >= SDL_VERSIONNUM(2, 0, 4)) {
714  info->info.win.hdc = data->hdc;
715  }
716 
717  if (versionnum >= SDL_VERSIONNUM(2, 0, 5)) {
718  info->info.win.hinstance = data->hinstance;
719  }
720 
721  return SDL_TRUE;
722  } else {
723  SDL_SetError("Application not compiled with SDL %d.%d",
725  return SDL_FALSE;
726  }
727 }
728 
729 
730 /*
731  * Creates a HelperWindow used for DirectInput events.
732  */
733 int
734 SDL_HelperWindowCreate(void)
735 {
736  HINSTANCE hInstance = GetModuleHandle(NULL);
737  WNDCLASS wce;
738 
739  /* Make sure window isn't created twice. */
740  if (SDL_HelperWindow != NULL) {
741  return 0;
742  }
743 
744  /* Create the class. */
745  SDL_zero(wce);
746  wce.lpfnWndProc = DefWindowProc;
747  wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
748  wce.hInstance = hInstance;
749 
750  /* Register the class. */
751  SDL_HelperWindowClass = RegisterClass(&wce);
752  if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
753  return WIN_SetError("Unable to create Helper Window Class");
754  }
755 
756  /* Create the window. */
757  SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
758  SDL_HelperWindowName,
759  WS_OVERLAPPED, CW_USEDEFAULT,
760  CW_USEDEFAULT, CW_USEDEFAULT,
761  CW_USEDEFAULT, HWND_MESSAGE, NULL,
762  hInstance, NULL);
763  if (SDL_HelperWindow == NULL) {
764  UnregisterClass(SDL_HelperWindowClassName, hInstance);
765  return WIN_SetError("Unable to create Helper Window");
766  }
767 
768  return 0;
769 }
770 
771 
772 /*
773  * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
774  */
775 void
776 SDL_HelperWindowDestroy(void)
777 {
778  HINSTANCE hInstance = GetModuleHandle(NULL);
779 
780  /* Destroy the window. */
781  if (SDL_HelperWindow != NULL) {
782  if (DestroyWindow(SDL_HelperWindow) == 0) {
783  WIN_SetError("Unable to destroy Helper Window");
784  return;
785  }
786  SDL_HelperWindow = NULL;
787  }
788 
789  /* Unregister the class. */
790  if (SDL_HelperWindowClass != 0) {
791  if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
792  WIN_SetError("Unable to destroy Helper Window Class");
793  return;
794  }
795  SDL_HelperWindowClass = 0;
796  }
797 }
798 
799 void WIN_OnWindowEnter(_THIS, SDL_Window * window)
800 {
801  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
802 
803  if (!data || !data->hwnd) {
804  /* The window wasn't fully initialized */
805  return;
806  }
807 
808  if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
809  WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
810  }
811 
812 #ifdef WM_MOUSELEAVE
813  {
814  TRACKMOUSEEVENT trackMouseEvent;
815 
816  trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
817  trackMouseEvent.dwFlags = TME_LEAVE;
818  trackMouseEvent.hwndTrack = data->hwnd;
819 
820  TrackMouseEvent(&trackMouseEvent);
821  }
822 #endif /* WM_MOUSELEAVE */
823 }
824 
825 void
827 {
828  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
829  SDL_Mouse *mouse = SDL_GetMouse();
830 
831  if (data->focus_click_pending) {
832  return;
833  }
834 
835  if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
836  (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
837  if (mouse->relative_mode && !mouse->relative_mode_warp) {
838  LONG cx, cy;
839  RECT rect;
840  GetWindowRect(data->hwnd, &rect);
841 
842  cx = (rect.left + rect.right) / 2;
843  cy = (rect.top + rect.bottom) / 2;
844 
845  /* Make an absurdly small clip rect */
846  rect.left = cx - 1;
847  rect.right = cx + 1;
848  rect.top = cy - 1;
849  rect.bottom = cy + 1;
850 
851  ClipCursor(&rect);
852  } else {
853  RECT rect;
854  if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
855  ClientToScreen(data->hwnd, (LPPOINT) & rect);
856  ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
857  ClipCursor(&rect);
858  }
859  }
860  } else {
861  ClipCursor(NULL);
862  }
863 }
864 
865 int
867 {
868  return 0; /* just succeed, the real work is done elsewhere. */
869 }
870 
871 int
872 WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
873 {
874  const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
875  const HWND hwnd = data->hwnd;
876  const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
877 
878  SDL_assert(style != 0);
879 
880  if (opacity == 1.0f) {
881  /* want it fully opaque, just mark it unlayered if necessary. */
882  if (style & WS_EX_LAYERED) {
883  if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
884  return WIN_SetError("SetWindowLong()");
885  }
886  }
887  } else {
888  const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
889  /* want it transparent, mark it layered if necessary. */
890  if ((style & WS_EX_LAYERED) == 0) {
891  if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
892  return WIN_SetError("SetWindowLong()");
893  }
894  }
895 
896  if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
897  return WIN_SetError("SetLayeredWindowAttributes()");
898  }
899  }
900 
901  return 0;
902 }
903 
904 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
905 
906 /* vi: set ts=4 sw=4 expandtab: */
#define BI_RGB
Definition: SDL_bmp.c:45
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
HINSTANCE SDL_Instance
#define WIN_UTF8ToString(S)
Definition: SDL_windows.h:47
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:112
void WIN_SetWindowSize(_THIS, SDL_Window *window)
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
GLenum GLenum dst
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
#define SDL_RWwrite(ctx, ptr, size, n)
Definition: SDL_rwops.h:188
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
void WIN_RaiseWindow(_THIS, SDL_Window *window)
const void * magic
Definition: SDL_sysvideo.h:75
SDL_Rect rect
Definition: testrelative.c:27
int WIN_GetWindowGammaRamp(_THIS, SDL_Window *window, Uint16 *ramp)
LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
void WIN_DestroyWindow(_THIS, SDL_Window *window)
GLfloat GLfloat GLfloat GLfloat h
SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
void WIN_MaximizeWindow(_THIS, SDL_Window *window)
#define SDL_GetHint
SDL_version version
Definition: SDL_syswm.h:196
SDL_bool expected_resize
Uint8 major
Definition: SDL_version.h:53
#define SDL_WriteLE16
LPTSTR SDL_Appname
GLfloat f
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:197
SDL_Window * window
uint32_t Uint32
Definition: SDL_stdinc.h:181
GLenum src
GLdouble GLdouble GLdouble GLdouble top
SDL_Rect windowed
Definition: SDL_sysvideo.h:87
void WIN_OnWindowEnter(_THIS, SDL_Window *window)
GLfloat GLfloat GLfloat alpha
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:378
void WIN_SetWindowPosition(_THIS, SDL_Window *window)
int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
int WIN_CreateWindow(_THIS, SDL_Window *window)
struct SDL_VideoDevice::@33 gl_config
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_bool windowed_mode_was_maximized
TCHAR DeviceName[32]
SDL_bool in_border_change
int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
void WIN_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable)
void * pixels
Definition: SDL_surface.h:75
void WIN_MinimizeWindow(_THIS, SDL_Window *window)
#define _THIS
struct SDL_VideoData * videodata
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:354
#define SDL_VERSIONNUM(X, Y, Z)
Definition: SDL_version.h:94
int WIN_SetWindowOpacity(_THIS, SDL_Window *window, float opacity)
#define TRUE
Definition: edid-parse.c:33
void WIN_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
void WIN_ShowWindow(_THIS, SDL_Window *window)
GLubyte GLubyte GLubyte GLubyte w
#define SDL_RWFromMem
void WIN_UpdateClipCursor(SDL_Window *window)
Uint8 minor
Definition: SDL_version.h:54
#define WIN_StringToUTF8(S)
Definition: SDL_windows.h:46
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
#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:546
#define SDL_sscanf
char * title
Definition: SDL_sysvideo.h:77
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
int x
Definition: SDL_rect.h:66
#define SDL_VIDEO_OPENGL_WGL
#define TWF_FINETOUCH
#define TWF_WANTPALM
int w
Definition: SDL_rect.h:67
void WIN_RestoreWindow(_THIS, SDL_Window *window)
GLenum GLenum GLsizei const GLuint GLboolean enabled
#define SDL_assert(condition)
Definition: SDL_assert.h:169
int WIN_SetWindowGammaRamp(_THIS, SDL_Window *window, const Uint16 *ramp)
Window window
Definition: SDL_syswm.h:218
SDL_bool SDL_ShouldAllowTopmost(void)
Definition: SDL_video.c:3888
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
SDL_PixelFormat * format
Definition: SDL_surface.h:72
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
int WIN_SetError(const char *prefix)
#define SDL_SetError
void WIN_SetWindowTitle(_THIS, SDL_Window *window)
GLbitfield flags
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
void WIN_PumpEvents(_THIS)
#define SDL_calloc
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1073
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
void WIN_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
int h
Definition: SDL_rect.h:67
The type used to identify a window.
Definition: SDL_sysvideo.h:73
void WIN_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
#define SDL_WriteLE32
uint16_t Uint16
Definition: SDL_stdinc.h:169
SDL_bool in_window_deactivation
union SDL_SysWMinfo::@18 info
void WIN_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
void * driverdata
Definition: SDL_sysvideo.h:111
int WIN_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:355
void WIN_HideWindow(_THIS, SDL_Window *window)
#define FALSE
Definition: edid-parse.c:34
Uint32 flags
Definition: SDL_sysvideo.h:83
int y
Definition: SDL_rect.h:66
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
Uint8 patch
Definition: SDL_version.h:55