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