win32_window.c 65.7 KB
Newer Older
Camilla Berglund's avatar
Camilla Berglund committed
1
//========================================================================
Camilla Berglund's avatar
Camilla Berglund committed
2
// GLFW 3.3 Win32 - www.glfw.org
Camilla Berglund's avatar
Camilla Berglund committed
3
4
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
Camilla Löwy's avatar
Camilla Löwy committed
5
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
Camilla Berglund's avatar
Camilla Berglund committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would
//    be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
//    be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
//========================================================================

#include "internal.h"

Camilla Berglund's avatar
Camilla Berglund committed
30
#include <limits.h>
Camilla Berglund's avatar
Camilla Berglund committed
31
#include <stdlib.h>
32
#include <malloc.h>
33
#include <string.h>
34
#include <windowsx.h>
Camilla Berglund's avatar
Camilla Berglund committed
35
#include <shellapi.h>
Camilla Berglund's avatar
Camilla Berglund committed
36

37
38
#define _GLFW_KEY_INVALID -2

39
40
// Returns the window style for the specified window
//
41
static DWORD getWindowStyle(const _GLFWwindow* window)
42
43
44
{
    DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

Camilla Berglund's avatar
Camilla Berglund committed
45
46
47
    if (window->monitor)
        style |= WS_POPUP;
    else
48
    {
49
50
        style |= WS_SYSMENU | WS_MINIMIZEBOX;

Camilla Berglund's avatar
Camilla Berglund committed
51
52
        if (window->decorated)
        {
53
            style |= WS_CAPTION;
54

Camilla Berglund's avatar
Camilla Berglund committed
55
56
57
58
59
            if (window->resizable)
                style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
        }
        else
            style |= WS_POPUP;
60
61
62
63
64
65
66
    }

    return style;
}

// Returns the extended window style for the specified window
//
67
static DWORD getWindowExStyle(const _GLFWwindow* window)
68
69
70
{
    DWORD style = WS_EX_APPWINDOW;

Camilla Berglund's avatar
Camilla Berglund committed
71
72
    if (window->monitor || window->floating)
        style |= WS_EX_TOPMOST;
73
74
75
76

    return style;
}

Camilla Berglund's avatar
Camilla Berglund committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Returns the image whose area most closely matches the desired one
//
static const GLFWimage* chooseImage(int count, const GLFWimage* images,
                                    int width, int height)
{
    int i, leastDiff = INT_MAX;
    const GLFWimage* closest = NULL;

    for (i = 0;  i < count;  i++)
    {
        const int currDiff = abs(images[i].width * images[i].height -
                                 width * height);
        if (currDiff < leastDiff)
        {
            closest = images + i;
            leastDiff = currDiff;
        }
    }

    return closest;
}

// Creates an RGBA icon or cursor
//
static HICON createIcon(const GLFWimage* image,
                        int xhot, int yhot, GLFWbool icon)
{
    int i;
    HDC dc;
    HICON handle;
    HBITMAP color, mask;
    BITMAPV5HEADER bi;
    ICONINFO ii;
    unsigned char* target = NULL;
    unsigned char* source = image->pixels;

    ZeroMemory(&bi, sizeof(bi));
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
114
    bi.bV5Size        = sizeof(bi);
Camilla Berglund's avatar
Camilla Berglund committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
    bi.bV5Width       = image->width;
    bi.bV5Height      = -image->height;
    bi.bV5Planes      = 1;
    bi.bV5BitCount    = 32;
    bi.bV5Compression = BI_BITFIELDS;
    bi.bV5RedMask     = 0x00ff0000;
    bi.bV5GreenMask   = 0x0000ff00;
    bi.bV5BlueMask    = 0x000000ff;
    bi.bV5AlphaMask   = 0xff000000;

    dc = GetDC(NULL);
    color = CreateDIBSection(dc,
                             (BITMAPINFO*) &bi,
                             DIB_RGB_COLORS,
                             (void**) &target,
                             NULL,
                             (DWORD) 0);
    ReleaseDC(NULL, dc);

    if (!color)
    {
136
137
        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
                             "Win32: Failed to create RGBA bitmap");
Camilla Berglund's avatar
Camilla Berglund committed
138
139
140
141
142
143
        return NULL;
    }

    mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
    if (!mask)
    {
144
145
        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
                             "Win32: Failed to create mask bitmap");
Camilla Berglund's avatar
Camilla Berglund committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
        DeleteObject(color);
        return NULL;
    }

    for (i = 0;  i < image->width * image->height;  i++)
    {
        target[0] = source[2];
        target[1] = source[1];
        target[2] = source[0];
        target[3] = source[3];
        target += 4;
        source += 4;
    }

    ZeroMemory(&ii, sizeof(ii));
    ii.fIcon    = icon;
    ii.xHotspot = xhot;
    ii.yHotspot = yhot;
    ii.hbmMask  = mask;
    ii.hbmColor = color;

    handle = CreateIconIndirect(&ii);

    DeleteObject(color);
    DeleteObject(mask);

    if (!handle)
    {
        if (icon)
175
176
177
178
        {
            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
                                 "Win32: Failed to create icon");
        }
Camilla Berglund's avatar
Camilla Berglund committed
179
        else
180
181
182
183
        {
            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
                                 "Win32: Failed to create cursor");
        }
Camilla Berglund's avatar
Camilla Berglund committed
184
185
186
187
188
    }

    return handle;
}

189
// Translate client window size to full window size according to styles and DPI
190
//
191
static void getFullWindowSize(DWORD style, DWORD exStyle,
192
                              int clientWidth, int clientHeight,
193
194
                              int* fullWidth, int* fullHeight,
                              UINT dpi)
195
196
{
    RECT rect = { 0, 0, clientWidth, clientHeight };
197
198
199
200
201
202

    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
        AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
    else
        AdjustWindowRectEx(&rect, style, FALSE, exStyle);

203
204
205
206
207
208
209
210
211
    *fullWidth = rect.right - rect.left;
    *fullHeight = rect.bottom - rect.top;
}

// Enforce the client rect aspect ratio based on which edge is being dragged
//
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{
    int xoff, yoff;
Camilla Berglund's avatar
Camilla Berglund committed
212
    const float ratio = (float) window->numer / (float) window->denom;
213

214
    getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
215
216
                      0, 0, &xoff, &yoff,
                      GetDpiForWindow(window->win32.handle));
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

    if (edge == WMSZ_LEFT  || edge == WMSZ_BOTTOMLEFT ||
        edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
    {
        area->bottom = area->top + yoff +
            (int) ((area->right - area->left - xoff) / ratio);
    }
    else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
    {
        area->top = area->bottom - yoff -
            (int) ((area->right - area->left - xoff) / ratio);
    }
    else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
    {
        area->right = area->left + xoff +
            (int) ((area->bottom - area->top - yoff) * ratio);
    }
}

236
237
238
239
240
241
242
243
244
// Centers the cursor over the window client area
//
static void centerCursor(_GLFWwindow* window)
{
    int width, height;
    _glfwPlatformGetWindowSize(window, &width, &height);
    _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}

245
// Updates the cursor image according to its cursor mode
246
//
247
static void updateCursorImage(_GLFWwindow* window)
248
{
249
    if (window->cursorMode == GLFW_CURSOR_NORMAL)
250
251
252
253
254
255
256
    {
        if (window->cursor)
            SetCursor(window->cursor->win32.handle);
        else
            SetCursor(LoadCursorW(NULL, IDC_ARROW));
    }
    else
257
        SetCursor(NULL);
258
259
}

260
261
262
263
// Updates the cursor clip rect
//
static void updateClipRect(_GLFWwindow* window)
{
264
265
266
267
268
269
270
271
272
273
    if (window)
    {
        RECT clipRect;
        GetClientRect(window->win32.handle, &clipRect);
        ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
        ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
        ClipCursor(&clipRect);
    }
    else
        ClipCursor(NULL);
274
275
}

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
// Apply disabled cursor mode to a focused window
//
static void disableCursor(_GLFWwindow* window)
{
    const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };

    _glfw.win32.disabledCursorWindow = window;
    _glfwPlatformGetCursorPos(window,
                              &_glfw.win32.restoreCursorPosX,
                              &_glfw.win32.restoreCursorPosY);
    updateCursorImage(window);
    centerCursor(window);
    updateClipRect(window);

    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
    {
        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
                             "Win32: Failed to register raw input device");
    }
}

// Exit disabled cursor mode for the specified window
//
static void enableCursor(_GLFWwindow* window)
{
    const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };

    _glfw.win32.disabledCursorWindow = NULL;
    updateClipRect(NULL);
    _glfwPlatformSetCursorPos(window,
                              _glfw.win32.restoreCursorPosX,
                              _glfw.win32.restoreCursorPosY);
    updateCursorImage(window);

    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
    {
        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
                             "Win32: Failed to remove raw input device");
    }
}

// Returns whether the cursor is in the client area of the specified window
//
static GLFWbool cursorInClientArea(_GLFWwindow* window)
{
    RECT area;
    POINT pos;

    if (!GetCursorPos(&pos))
        return GLFW_FALSE;

    if (WindowFromPoint(pos) != window->win32.handle)
        return GLFW_FALSE;

    GetClientRect(window->win32.handle, &area);
    ClientToScreen(window->win32.handle, (POINT*) &area.left);
    ClientToScreen(window->win32.handle, (POINT*) &area.right);

    return PtInRect(&area, pos);
}

Camilla Löwy's avatar
Camilla Löwy committed
337
338
339
340
341
342
343
344
345
346
// Update native window styles to match attributes
//
static void updateWindowStyles(const _GLFWwindow* window)
{
    RECT rect;
    DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
    style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
    style |= getWindowStyle(window);

    GetClientRect(window->win32.handle, &rect);
347
348
349
350
351
352
353
354
355
356

    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
    {
        AdjustWindowRectExForDpi(&rect, style, FALSE,
                                 getWindowExStyle(window),
                                 GetDpiForWindow(window->win32.handle));
    }
    else
        AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));

Camilla Löwy's avatar
Camilla Löwy committed
357
358
359
360
361
362
363
364
365
    ClientToScreen(window->win32.handle, (POINT*) &rect.left);
    ClientToScreen(window->win32.handle, (POINT*) &rect.right);
    SetWindowLongW(window->win32.handle, GWL_STYLE, style);
    SetWindowPos(window->win32.handle, HWND_TOP,
                 rect.left, rect.top,
                 rect.right - rect.left, rect.bottom - rect.top,
                 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
}

366
367
368
369
// Update window framebuffer transparency
//
static void updateFramebufferTransparency(const _GLFWwindow* window)
{
Camilla Löwy's avatar
Camilla Löwy committed
370
371
    BOOL enabled;

372
373
374
    if (!IsWindowsVistaOrGreater())
        return;

Camilla Löwy's avatar
Camilla Löwy committed
375
    if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
    {
        HRGN region = CreateRectRgn(0, 0, -1, -1);
        DWM_BLURBEHIND bb = {0};
        bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
        bb.hRgnBlur = region;
        bb.fEnable = TRUE;

        if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
        {
            // Decorated windows don't repaint the transparent background
            // leaving a trail behind animations
            // HACK: Making the window layered with a transparency color key
            //       seems to fix this.  Normally, when specifying
            //       a transparency color key to be used when composing the
            //       layered window, all pixels painted by the window in this
            //       color will be transparent.  That doesn't seem to be the
            //       case anymore, at least when used with blur behind window
            //       plus negative region.
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
394
395
396
            LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
            exStyle |= WS_EX_LAYERED;
            SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
397
398
399
400
401
402
403
404
405
406
407
408

            // Using a color key not equal to black to fix the trailing
            // issue.  When set to black, something is making the hit test
            // not resize with the window frame.
            SetLayeredWindowAttributes(window->win32.handle,
                                       RGB(0, 193, 48), 255, LWA_COLORKEY);
        }

        DeleteObject(region);
    }
    else
    {
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
409
410
411
        LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
        exStyle &= ~WS_EX_LAYERED;
        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
412
413
414
415
416
        RedrawWindow(window->win32.handle, NULL, NULL,
                     RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
    }
}

417
418
419
420
421
422
// Retrieves and translates modifier keys
//
static int getKeyMods(void)
{
    int mods = 0;

423
    if (GetKeyState(VK_SHIFT) & 0x8000)
424
        mods |= GLFW_MOD_SHIFT;
425
    if (GetKeyState(VK_CONTROL) & 0x8000)
426
        mods |= GLFW_MOD_CONTROL;
427
    if (GetKeyState(VK_MENU) & 0x8000)
428
        mods |= GLFW_MOD_ALT;
429
    if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
Noel Cower's avatar
Noel Cower committed
430
        mods |= GLFW_MOD_SUPER;
431
432
433
434
    if (GetKeyState(VK_CAPITAL) & 1)
        mods |= GLFW_MOD_CAPS_LOCK;
    if (GetKeyState(VK_NUMLOCK) & 1)
        mods |= GLFW_MOD_NUM_LOCK;
435
436
437
438
439
440
441
442
443
444

    return mods;
}

// Retrieves and translates modifier keys
//
static int getAsyncKeyMods(void)
{
    int mods = 0;

445
    if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
446
        mods |= GLFW_MOD_SHIFT;
447
    if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
448
        mods |= GLFW_MOD_CONTROL;
449
    if (GetAsyncKeyState(VK_MENU) & 0x8000)
450
        mods |= GLFW_MOD_ALT;
451
    if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & 0x8000)
Noel Cower's avatar
Noel Cower committed
452
        mods |= GLFW_MOD_SUPER;
453
454
455
456
    if (GetAsyncKeyState(VK_CAPITAL) & 1)
        mods |= GLFW_MOD_CAPS_LOCK;
    if (GetAsyncKeyState(VK_NUMLOCK) & 1)
        mods |= GLFW_MOD_NUM_LOCK;
457
458
459
460

    return mods;
}

Camilla Berglund's avatar
Camilla Berglund committed
461
// Translates a Windows key to the corresponding GLFW key
462
//
Camilla Berglund's avatar
Camilla Berglund committed
463
static int translateKey(WPARAM wParam, LPARAM lParam)
Camilla Berglund's avatar
Camilla Berglund committed
464
{
Camilla Löwy's avatar
Camilla Löwy committed
465
    // The Ctrl keys require special handling
466
    if (wParam == VK_CONTROL)
Camilla Berglund's avatar
Camilla Berglund committed
467
    {
468
469
        MSG next;
        DWORD time;
Camilla Berglund's avatar
Camilla Berglund committed
470

Camilla Löwy's avatar
Camilla Löwy committed
471
        // Right side keys have the extended key bit set
472
473
        if (lParam & 0x01000000)
            return GLFW_KEY_RIGHT_CONTROL;
Camilla Berglund's avatar
Camilla Berglund committed
474

Camilla Löwy's avatar
Camilla Löwy committed
475
476
477
        // HACK: Alt Gr sends Left Ctrl and then Right Alt in close sequence
        //       We only want the Right Alt message, so if the next message is
        //       Right Alt we ignore this (synthetic) Left Ctrl message
478
479
480
481
482
483
484
485
        time = GetMessageTime();

        if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
        {
            if (next.message == WM_KEYDOWN ||
                next.message == WM_SYSKEYDOWN ||
                next.message == WM_KEYUP ||
                next.message == WM_SYSKEYUP)
Camilla Berglund's avatar
Camilla Berglund committed
486
            {
487
488
489
                if (next.wParam == VK_MENU &&
                    (next.lParam & 0x01000000) &&
                    next.time == time)
Camilla Berglund's avatar
Camilla Berglund committed
490
                {
Camilla Löwy's avatar
Camilla Löwy committed
491
                    // Next message is Right Alt down so discard this
492
                    return _GLFW_KEY_INVALID;
Camilla Berglund's avatar
Camilla Berglund committed
493
494
495
496
                }
            }
        }

497
        return GLFW_KEY_LEFT_CONTROL;
Camilla Berglund's avatar
Camilla Berglund committed
498
    }
499

500
501
502
503
504
505
506
    if (wParam == VK_PROCESSKEY)
    {
        // IME notifies that keys have been filtered by setting the virtual
        // key-code to VK_PROCESSKEY
        return _GLFW_KEY_INVALID;
    }

Camilla Berglund's avatar
Cleanup    
Camilla Berglund committed
507
    return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
Camilla Berglund's avatar
Camilla Berglund committed
508
509
}

510
511
512
513
514
515
516
517
518
519
520
521
static void fitToMonitor(_GLFWwindow* window)
{
    MONITORINFO mi = { sizeof(mi) };
    GetMonitorInfo(window->monitor->win32.handle, &mi);
    SetWindowPos(window->win32.handle, HWND_TOPMOST,
                 mi.rcMonitor.left,
                 mi.rcMonitor.top,
                 mi.rcMonitor.right - mi.rcMonitor.left,
                 mi.rcMonitor.bottom - mi.rcMonitor.top,
                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
}

522
// Make the specified window and its video mode active on its monitor
523
//
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
524
static void acquireMonitor(_GLFWwindow* window)
525
{
526
    if (!_glfw.win32.acquiredMonitorCount)
527
    {
528
        SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
529
530
531
532
533
534
535
536
537
538

        // HACK: When mouse trails are enabled the cursor becomes invisible when
        //       the OpenGL ICD switches to page flipping
        if (IsWindowsXPOrGreater())
        {
            SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
            SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
        }
    }

539
540
541
    if (!window->monitor->window)
        _glfw.win32.acquiredMonitorCount++;

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
542
    _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
543
    _glfwInputMonitorWindow(window->monitor, window);
544
545
}

546
// Remove the window and restore the original video mode
547
//
548
static void releaseMonitor(_GLFWwindow* window)
549
{
550
551
552
    if (window->monitor->window != window)
        return;

553
554
    _glfw.win32.acquiredMonitorCount--;
    if (!_glfw.win32.acquiredMonitorCount)
555
    {
556
557
        SetThreadExecutionState(ES_CONTINUOUS);

558
559
560
561
562
        // HACK: Restore mouse trail length saved in acquireMonitor
        if (IsWindowsXPOrGreater())
            SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
    }

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
563
    _glfwInputMonitorWindow(window->monitor, NULL);
564
    _glfwRestoreVideoModeWin32(window->monitor);
565
566
}

Camilla Berglund's avatar
Camilla Berglund committed
567
// Window callback function (handles window messages)
568
//
Camilla Berglund's avatar
Camilla Berglund committed
569
570
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
                                   WPARAM wParam, LPARAM lParam)
Camilla Berglund's avatar
Camilla Berglund committed
571
{
572
    _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
573
    if (!window)
Camilla Berglund's avatar
Camilla Berglund committed
574
    {
575
        // This is the message handling for the hidden helper window
576
        // and for a regular window during its initial creation
577

Camilla Berglund's avatar
Camilla Berglund committed
578
        switch (uMsg)
Camilla Berglund's avatar
Camilla Berglund committed
579
        {
580
581
582
583
584
585
586
587
            case WM_NCCREATE:
            {
                if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
                    EnableNonClientDpiScaling(hWnd);

                break;
            }

588
589
590
591
            case WM_DISPLAYCHANGE:
                _glfwPollMonitorsWin32();
                break;

Camilla Berglund's avatar
Camilla Berglund committed
592
            case WM_DEVICECHANGE:
Camilla Berglund's avatar
Camilla Berglund committed
593
            {
594
                if (wParam == DBT_DEVICEARRIVAL)
Camilla Berglund's avatar
Camilla Berglund committed
595
596
                {
                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
597
598
                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
                        _glfwDetectJoystickConnectionWin32();
Camilla Berglund's avatar
Camilla Berglund committed
599
600
601
602
                }
                else if (wParam == DBT_DEVICEREMOVECOMPLETE)
                {
                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
603
604
                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
                        _glfwDetectJoystickDisconnectionWin32();
Camilla Berglund's avatar
Camilla Berglund committed
605
606
607
                }

                break;
Camilla Berglund's avatar
Camilla Berglund committed
608
            }
Camilla Berglund's avatar
Camilla Berglund committed
609
610
        }

611
612
613
614
615
        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
    }

    switch (uMsg)
    {
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
        case WM_MOUSEACTIVATE:
        {
            // HACK: Postpone cursor disabling when the window was activated by
            //       clicking a caption button
            if (HIWORD(lParam) == WM_LBUTTONDOWN)
            {
                if (LOWORD(lParam) == HTCLOSE ||
                    LOWORD(lParam) == HTMINBUTTON ||
                    LOWORD(lParam) == HTMAXBUTTON)
                {
                    window->win32.frameAction = GLFW_TRUE;
                }
            }

            break;
        }

        case WM_CAPTURECHANGED:
        {
            // HACK: Disable the cursor once the caption button action has been
            //       completed or cancelled
            if (lParam == 0 && window->win32.frameAction)
            {
                if (window->cursorMode == GLFW_CURSOR_DISABLED)
640
                    disableCursor(window);
641
642
643
644
645
646
647

                window->win32.frameAction = GLFW_FALSE;
            }

            break;
        }

648
        case WM_SETFOCUS:
Camilla Berglund's avatar
Camilla Berglund committed
649
        {
650
651
            _glfwInputWindowFocus(window, GLFW_TRUE);

652
653
654
655
656
            // HACK: Do not disable cursor while the user is interacting with
            //       a caption button
            if (window->win32.frameAction)
                break;

657
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
658
                disableCursor(window);
Camilla Berglund's avatar
Camilla Berglund committed
659
660
661
662

            return 0;
        }

663
        case WM_KILLFOCUS:
664
        {
665
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
666
                enableCursor(window);
667
668
669

            if (window->monitor && window->autoIconify)
                _glfwPlatformIconifyWindow(window);
670

671
            _glfwInputWindowFocus(window, GLFW_FALSE);
672
673
674
            return 0;
        }

Camilla Berglund's avatar
Camilla Berglund committed
675
676
        case WM_SYSCOMMAND:
        {
Camilla Berglund's avatar
Camilla Berglund committed
677
            switch (wParam & 0xfff0)
Camilla Berglund's avatar
Camilla Berglund committed
678
679
680
681
            {
                case SC_SCREENSAVE:
                case SC_MONITORPOWER:
                {
682
                    if (window->monitor)
Camilla Berglund's avatar
Camilla Berglund committed
683
                    {
684
                        // We are running in full screen mode, so disallow
Camilla Berglund's avatar
Camilla Berglund committed
685
                        // screen saver and screen blanking
Camilla Berglund's avatar
Camilla Berglund committed
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
                        return 0;
                    }
                    else
                        break;
                }

                // User trying to access application menu using ALT?
                case SC_KEYMENU:
                    return 0;
            }
            break;
        }

        case WM_CLOSE:
        {
701
            _glfwInputWindowCloseRequest(window);
Camilla Berglund's avatar
Camilla Berglund committed
702
703
704
            return 0;
        }

705
706
707
708
709
710
        case WM_INPUTLANGCHANGE:
        {
            _glfwUpdateKeyNamesWin32();
            break;
        }

Camilla Berglund's avatar
Camilla Berglund committed
711
        case WM_CHAR:
712
        case WM_SYSCHAR:
713
714
        case WM_UNICHAR:
        {
715
            const GLFWbool plain = (uMsg != WM_SYSCHAR);
716

717
            if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
718
            {
719
720
                // WM_UNICHAR is not sent by Windows, but is sent by some
                // third-party input method engine
721
722
723
724
                // Returning TRUE here announces support for this message
                return TRUE;
            }

725
726
727
728
729
730
            _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);
            return 0;
        }

        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
Camilla Berglund's avatar
Camilla Berglund committed
731
732
733
        case WM_KEYUP:
        case WM_SYSKEYUP:
        {
734
            const int key = translateKey(wParam, lParam);
735
736
737
738
            const int scancode = (lParam >> 16) & 0x1ff;
            const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS;
            const int mods = getKeyMods();

739
740
            if (key == _GLFW_KEY_INVALID)
                break;
741

742
            if (action == GLFW_RELEASE && wParam == VK_SHIFT)
Camilla Berglund's avatar
Camilla Berglund committed
743
            {
Camilla Löwy's avatar
Camilla Löwy committed
744
745
746
                // HACK: Release both Shift keys on Shift up event, as when both
                //       are pressed the first release does not emit any event
                // NOTE: The other half of this is in _glfwPlatformPollEvents
747
748
                _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
                _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
Camilla Berglund's avatar
Camilla Berglund committed
749
            }
750
751
            else if (wParam == VK_SNAPSHOT)
            {
Camilla Löwy's avatar
Camilla Löwy committed
752
                // HACK: Key down is not reported for the Print Screen key
753
754
                _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
                _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
755
            }
Camilla Berglund's avatar
Camilla Berglund committed
756
            else
757
                _glfwInputKey(window, key, scancode, action, mods);
Camilla Berglund's avatar
Camilla Berglund committed
758

759
            break;
Camilla Berglund's avatar
Camilla Berglund committed
760
761
762
763
764
        }

        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_MBUTTONDOWN:
765
766
        case WM_XBUTTONDOWN:
        case WM_LBUTTONUP:
Camilla Berglund's avatar
Camilla Berglund committed
767
768
        case WM_RBUTTONUP:
        case WM_MBUTTONUP:
769
        case WM_XBUTTONUP:
Camilla Berglund's avatar
Camilla Berglund committed
770
        {
771
            int i, button, action;
772
773
774
775
776
777
778
779
780
781
782

            if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
                button = GLFW_MOUSE_BUTTON_LEFT;
            else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP)
                button = GLFW_MOUSE_BUTTON_RIGHT;
            else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
                button = GLFW_MOUSE_BUTTON_MIDDLE;
            else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
                button = GLFW_MOUSE_BUTTON_4;
            else
                button = GLFW_MOUSE_BUTTON_5;
Camilla Berglund's avatar
Camilla Berglund committed
783

784
785
786
787
788
            if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN ||
                uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
            {
                action = GLFW_PRESS;
            }
789
            else
790
                action = GLFW_RELEASE;
791

792
            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
793
794
795
            {
                if (window->mouseButtons[i] == GLFW_PRESS)
                    break;
796
            }
797

798
            if (i > GLFW_MOUSE_BUTTON_LAST)
799
800
                SetCapture(hWnd);

801
802
            _glfwInputMouseClick(window, button, action, getKeyMods());

803
            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
804
805
806
807
808
            {
                if (window->mouseButtons[i] == GLFW_PRESS)
                    break;
            }

809
            if (i > GLFW_MOUSE_BUTTON_LAST)
810
811
                ReleaseCapture();

812
            if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
813
                return TRUE;
Camilla Berglund's avatar
Camilla Berglund committed
814

815
            return 0;
Camilla Berglund's avatar
Camilla Berglund committed
816
817
818
819
        }

        case WM_MOUSEMOVE:
        {
820
821
            const int x = GET_X_LPARAM(lParam);
            const int y = GET_Y_LPARAM(lParam);
Camilla Berglund's avatar
Camilla Berglund committed
822

823
            // Disabled cursor motion input is provided by WM_INPUT
824
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
825
                break;
826

827
            _glfwInputCursorPos(window, x, y);
828

829
830
            window->win32.lastCursorPosX = x;
            window->win32.lastCursorPosY = y;
Camilla Berglund's avatar
Camilla Berglund committed
831

832
            if (!window->win32.cursorTracked)
833
834
835
836
837
            {
                TRACKMOUSEEVENT tme;
                ZeroMemory(&tme, sizeof(tme));
                tme.cbSize = sizeof(tme);
                tme.dwFlags = TME_LEAVE;
838
                tme.hwndTrack = window->win32.handle;
839
840
                TrackMouseEvent(&tme);

841
842
                window->win32.cursorTracked = GLFW_TRUE;
                _glfwInputCursorEnter(window, GLFW_TRUE);
843
844
845
846
847
            }

            return 0;
        }

848
849
850
851
852
853
854
855
856
857
858
859
        case WM_INPUT:
        {
            UINT size;
            HRAWINPUT ri = (HRAWINPUT) lParam;
            RAWINPUT* data;
            int dx, dy;

            // Only process input when disabled cursor mode is applied
            if (_glfw.win32.disabledCursorWindow != window)
                break;

            GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
Camilla Löwy's avatar
Camilla Löwy committed
860
            if (size > (UINT) _glfw.win32.rawInputSize)
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
            {
                free(_glfw.win32.rawInput);
                _glfw.win32.rawInput = calloc(size, 1);
                _glfw.win32.rawInputSize = size;
            }

            size = _glfw.win32.rawInputSize;
            if (GetRawInputData(ri, RID_INPUT,
                                _glfw.win32.rawInput, &size,
                                sizeof(RAWINPUTHEADER)) == (UINT) -1)
            {
                _glfwInputError(GLFW_PLATFORM_ERROR,
                                "Win32: Failed to retrieve raw input data");
                break;
            }

            data = _glfw.win32.rawInput;
            if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
            {
                dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
                dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
            }
            else
            {
                dx = data->data.mouse.lLastX;
                dy = data->data.mouse.lLastY;
            }

            _glfwInputCursorPos(window,
                                window->virtualCursorPosX + dx,
                                window->virtualCursorPosY + dy);

            window->win32.lastCursorPosX += dx;
            window->win32.lastCursorPosY += dy;
            break;
        }

898
899
        case WM_MOUSELEAVE:
        {
900
901
            window->win32.cursorTracked = GLFW_FALSE;
            _glfwInputCursorEnter(window, GLFW_FALSE);
Camilla Berglund's avatar
Camilla Berglund committed
902
903
904
905
906
            return 0;
        }

        case WM_MOUSEWHEEL:
        {
907
            _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
908
909
            return 0;
        }
Camilla Berglund's avatar
Camilla Berglund committed
910

911
912
913
        case WM_MOUSEHWHEEL:
        {
            // This message is only sent on Windows Vista and later
914
            // NOTE: The X-axis is inverted for consistency with macOS and X11
915
            _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
Camilla Berglund's avatar
Camilla Berglund committed
916
            return 0;
Camilla Berglund's avatar
Camilla Berglund committed
917
918
        }

919
920
921
        case WM_ENTERSIZEMOVE:
        case WM_ENTERMENULOOP:
        {
922
923
            // HACK: Enable the cursor while the user is moving or
            //       resizing the window or using the window menu
924
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
925
                enableCursor(window);
926
927
928
929
930
931
932

            break;
        }

        case WM_EXITSIZEMOVE:
        case WM_EXITMENULOOP:
        {
933
934
            // HACK: Disable the cursor once the user is done moving or
            //       resizing the window or using the menu
935
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
936
                disableCursor(window);
937
938
939
940

            break;
        }

Camilla Berglund's avatar
Camilla Berglund committed
941
942
        case WM_SIZE:
        {
943
944
945
946
            const GLFWbool iconified = wParam == SIZE_MINIMIZED;
            const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
                                       (window->win32.maximized &&
                                        wParam != SIZE_RESTORED);
947

948
949
            if (_glfw.win32.disabledCursorWindow == window)
                updateClipRect(window);
Camilla Berglund's avatar
Camilla Berglund committed
950

951
952
953
954
955
            if (window->win32.iconified != iconified)
                _glfwInputWindowIconify(window, iconified);

            if (window->win32.maximized != maximized)
                _glfwInputWindowMaximize(window, maximized);
956
957
958
959

            _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
            _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));

960
            if (window->monitor && window->win32.iconified != iconified)
961
            {
962
                if (iconified)
963
                    releaseMonitor(window);
964
                else
965
                {
966
                    acquireMonitor(window);
967
968
                    fitToMonitor(window);
                }
969
            }
Camilla Berglund's avatar
Camilla Berglund committed
970

971
972
            window->win32.iconified = iconified;
            window->win32.maximized = maximized;
Camilla Berglund's avatar
Camilla Berglund committed
973
974
975
976
977
            return 0;
        }

        case WM_MOVE:
        {
978
979
            if (_glfw.win32.disabledCursorWindow == window)
                updateClipRect(window);
980

Camilla Berglund's avatar
Camilla Berglund committed
981
982
            // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
            // those macros do not handle negative window positions correctly
983
984
985
            _glfwInputWindowPos(window,
                                GET_X_LPARAM(lParam),
                                GET_Y_LPARAM(lParam));
Camilla Berglund's avatar
Camilla Berglund committed
986
987
988
            return 0;
        }

989
990
        case WM_SIZING:
        {
Camilla Berglund's avatar
Camilla Berglund committed
991
992
            if (window->numer == GLFW_DONT_CARE ||
                window->denom == GLFW_DONT_CARE)
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
            {
                break;
            }

            applyAspectRatio(window, (int) wParam, (RECT*) lParam);
            return TRUE;
        }

        case WM_GETMINMAXINFO:
        {
            int xoff, yoff;
            MINMAXINFO* mmi = (MINMAXINFO*) lParam;
1005

Camilla Berglund's avatar
Camilla Berglund committed
1006
1007
1008
            if (window->monitor)
                break;

1009
            getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
1010
1011
                              0, 0, &xoff, &yoff,
                              GetDpiForWindow(window->win32.handle));
1012

Camilla Berglund's avatar
Camilla Berglund committed
1013
1014
            if (window->minwidth != GLFW_DONT_CARE &&
                window->minheight != GLFW_DONT_CARE)
1015
            {
Camilla Berglund's avatar
Camilla Berglund committed
1016
1017
                mmi->ptMinTrackSize.x = window->minwidth + xoff;
                mmi->ptMinTrackSize.y = window->minheight + yoff;
1018
1019
            }

Camilla Berglund's avatar
Camilla Berglund committed
1020
1021
            if (window->maxwidth != GLFW_DONT_CARE &&
                window->maxheight != GLFW_DONT_CARE)
1022
            {
Camilla Berglund's avatar
Camilla Berglund committed
1023
1024
                mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
                mmi->ptMaxTrackSize.y = window->maxheight + yoff;
1025
1026
            }

1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
            if (!window->decorated)
            {
                MONITORINFO mi;
                const HMONITOR mh = MonitorFromWindow(window->win32.handle,
                                                      MONITOR_DEFAULTTONEAREST);

                ZeroMemory(&mi, sizeof(mi));
                mi.cbSize = sizeof(mi);
                GetMonitorInfo(mh, &mi);

                mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
                mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
                mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left;
                mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top;
            }

1043
1044
1045
            return 0;
        }

Camilla Berglund's avatar
Camilla Berglund committed
1046
1047
        case WM_PAINT:
        {
1048
            _glfwInputWindowDamage(window);
Camilla Berglund's avatar
Camilla Berglund committed
1049
1050
1051
            break;
        }

Camilla Berglund's avatar
Camilla Berglund committed
1052
1053
1054
1055
1056
        case WM_ERASEBKGND:
        {
            return TRUE;
        }

1057
1058
1059
1060
1061
1062
1063
        case WM_DWMCOMPOSITIONCHANGED:
        {
            if (window->win32.transparent)
                updateFramebufferTransparency(window);
            return 0;
        }

1064
1065
        case WM_GETDPISCALEDSIZE:
        {
Camilla Löwy's avatar
Camilla Löwy committed
1066
1067
1068
            if (window->win32.scaleToMonitor)
                break;

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
            // Adjust the window size to keep the client area size constant
            if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
            {
                RECT source = {0}, target = {0};
                SIZE* size = (SIZE*) lParam;

                AdjustWindowRectExForDpi(&source, getWindowStyle(window),
                                         FALSE, getWindowExStyle(window),
                                         GetDpiForWindow(window->win32.handle));
                AdjustWindowRectExForDpi(&target, getWindowStyle(window),
                                         FALSE, getWindowExStyle(window),
                                         LOWORD(wParam));

                size->cx += (target.right - target.left) -
                            (source.right - source.left);
                size->cy += (target.bottom - target.top) -
                            (source.bottom - source.top);
                return TRUE;
            }

            break;
        }

1092
1093
        case WM_DPICHANGED:
        {
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
            const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
            const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;

            // Only apply the suggested size if the OS is new enough to have
            // sent a WM_GETDPISCALEDSIZE before this
            if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
            {
                RECT* suggested = (RECT*) lParam;
                SetWindowPos(window->win32.handle, HWND_TOP,
                             suggested->left,
                             suggested->top,
                             suggested->right - suggested->left,
                             suggested->bottom - suggested->top,
                             SWP_NOACTIVATE | SWP_NOZORDER);
            }

1110
1111
1112
1113
            _glfwInputWindowContentScale(window, xscale, yscale);
            break;
        }

1114
1115
        case WM_SETCURSOR:
        {
1116
            if (LOWORD(lParam) == HTCLIENT)
1117
            {
1118
                updateCursorImage(window);
1119
                return TRUE;
1120
1121
1122
1123
1124
            }

            break;
        }

arturo's avatar
arturo committed
1125
1126
        case WM_DROPFILES:
        {
Camilla Berglund's avatar
Camilla Berglund committed
1127
            HDROP drop = (HDROP) wParam;
Camilla Berglund's avatar
Camilla Berglund committed
1128
            POINT pt;
1129
1130
            int i;

Camilla Berglund's avatar
Camilla Berglund committed
1131
            const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
1132
            char** paths = calloc(count, sizeof(char*));
Camilla Berglund's avatar
Camilla Berglund committed
1133
1134

            // Move the mouse to the position of the drop
Camilla Berglund's avatar
Camilla Berglund committed
1135
            DragQueryPoint(drop, &pt);
1136
            _glfwInputCursorPos(window, pt.x, pt.y);
Camilla Berglund's avatar
Camilla Berglund committed
1137

1138
            for (i = 0;  i < count;  i++)
Camilla Berglund's avatar
Camilla Berglund committed
1139
            {
Camilla Berglund's avatar
Camilla Berglund committed
1140
                const UINT length = DragQueryFileW(drop, i, NULL, 0);
1141
                WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
Camilla Berglund's avatar
Camilla Berglund committed
1142

Camilla Berglund's avatar
Camilla Berglund committed
1143
                DragQueryFileW(drop, i, buffer, length + 1);
1144
                paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
Camilla Berglund's avatar
Camilla Berglund committed
1145

1146
                free(buffer);
Camilla Berglund's avatar
Camilla Berglund committed
1147
1148
            }

1149
            _glfwInputDrop(window, count, (const char**) paths);
1150
1151

            for (i = 0;  i < count;  i++)
1152
1153
                free(paths[i]);
            free(paths);
1154

Camilla Berglund's avatar
Camilla Berglund committed
1155
            DragFinish(drop);
1156
            return 0;
arturo's avatar
arturo committed
1157
        }
Camilla Berglund's avatar
Camilla Berglund committed
1158
1159
    }

1160
    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
Camilla Berglund's avatar
Camilla Berglund committed
1161
1162
}

Camilla Berglund's avatar
Camilla Berglund committed
1163
// Creates the GLFW window
1164
//
Camilla Berglund's avatar
Cleanup    
Camilla Berglund committed
1165
static int createNativeWindow(_GLFWwindow* window,
1166
1167
                              const _GLFWwndconfig* wndconfig,
                              const _GLFWfbconfig* fbconfig)
Camilla Berglund's avatar
Camilla Berglund committed
1168
{
1169
    int xpos, ypos, fullWidth, fullHeight;
1170
    WCHAR* wideTitle;
1171
1172
    DWORD style = getWindowStyle(window);
    DWORD exStyle = getWindowExStyle(window);
Camilla Berglund's avatar
Camilla Berglund committed
1173

1174
    if (window->monitor)
1175
    {
1176
1177
        GLFWvidmode mode;

1178
1179
        // NOTE: This window placement is temporary and approximate, as the
        //       correct position and size cannot be known until the monitor
Camilla Löwy's avatar
Camilla Löwy committed
1180
        //       video mode has been picked in _glfwSetVideoModeWin32
1181
1182
        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
        _glfwPlatformGetVideoMode(window->monitor, &mode);
1183
1184
        fullWidth  = mode.width;
        fullHeight = mode.height;
1185
    }
Camilla Berglund's avatar
Camilla Berglund committed
1186
1187
    else
    {
1188
1189
        xpos = CW_USEDEFAULT;
        ypos = CW_USEDEFAULT;
Camilla Berglund's avatar
Camilla Berglund committed
1190

1191
1192
1193
1194
        if (wndconfig->maximized)
            style |= WS_MAXIMIZE;

        getFullWindowSize(style, exStyle,
Camilla Berglund's avatar
Camilla Berglund committed
1195
                          wndconfig->width, wndconfig->height,
1196
1197
                          &fullWidth, &fullHeight,
                          USER_DEFAULT_SCREEN_DPI);