win32_window.c 68.2 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-2019 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
//
// 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.
//
//========================================================================
27
28
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
Camilla Berglund's avatar
Camilla Berglund committed
29
30
31

#include "internal.h"

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

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;
}

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
189
// Translate content area size to full window size according to styles and DPI
190
//
191
static void getFullWindowSize(DWORD style, DWORD exStyle,
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
192
                              int contentWidth, int contentHeight,
193
194
                              int* fullWidth, int* fullHeight,
                              UINT dpi)
195
{
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
196
    RECT rect = { 0, 0, contentWidth, contentHeight };
197
198
199
200
201
202

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

203
204
205
206
    *fullWidth = rect.right - rect.left;
    *fullHeight = rect.bottom - rect.top;
}

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
207
// Enforce the content area aspect ratio based on which edge is being dragged
208
209
210
211
//
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{
    int xoff, yoff;
212
    UINT dpi = USER_DEFAULT_SCREEN_DPI;
Camilla Berglund's avatar
Camilla Berglund committed
213
    const float ratio = (float) window->numer / (float) window->denom;
214

215
216
217
    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
        dpi = GetDpiForWindow(window->win32.handle);

218
    getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
219
                      0, 0, &xoff, &yoff, dpi);
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

    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);
    }
}

239
// Updates the cursor image according to its cursor mode
240
//
241
static void updateCursorImage(_GLFWwindow* window)
242
{
243
    if (window->cursorMode == GLFW_CURSOR_NORMAL)
244
245
246
247
248
249
250
    {
        if (window->cursor)
            SetCursor(window->cursor->win32.handle);
        else
            SetCursor(LoadCursorW(NULL, IDC_ARROW));
    }
    else
251
        SetCursor(NULL);
252
253
}

254
255
256
257
// Updates the cursor clip rect
//
static void updateClipRect(_GLFWwindow* window)
{
258
259
260
261
262
263
264
265
266
267
    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);
268
269
}

270
// Enables WM_INPUT messages for the mouse for the specified window
271
//
272
static void enableRawMouseMotion(_GLFWwindow* window)
273
274
275
{
    const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
    {
        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
                             "Win32: Failed to register raw input device");
    }
}

// Disables WM_INPUT messages for the mouse
//
static void disableRawMouseMotion(_GLFWwindow* window)
{
    const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };

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

// Apply disabled cursor mode to a focused window
//
static void disableCursor(_GLFWwindow* window)
{
300
301
302
303
304
    _glfw.win32.disabledCursorWindow = window;
    _glfwPlatformGetCursorPos(window,
                              &_glfw.win32.restoreCursorPosX,
                              &_glfw.win32.restoreCursorPosY);
    updateCursorImage(window);
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
305
    _glfwCenterCursorInContentArea(window);
306
307
    updateClipRect(window);

308
309
    if (window->rawMouseMotion)
        enableRawMouseMotion(window);
310
311
312
313
314
315
}

// Exit disabled cursor mode for the specified window
//
static void enableCursor(_GLFWwindow* window)
{
316
317
    if (window->rawMouseMotion)
        disableRawMouseMotion(window);
318
319
320
321
322
323
324
325
326

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

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
327
// Returns whether the cursor is in the content area of the specified window
328
//
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
329
static GLFWbool cursorInContentArea(_GLFWwindow* window)
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
{
    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
347
348
349
350
351
352
353
354
355
356
// 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);
357
358
359
360
361
362
363
364
365
366

    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
367
368
369
370
371
372
373
374
375
    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);
}

376
377
378
379
// Update window framebuffer transparency
//
static void updateFramebufferTransparency(const _GLFWwindow* window)
{
Camilla Löwy's avatar
Camilla Löwy committed
380
381
    BOOL enabled;

382
383
384
    if (!IsWindowsVistaOrGreater())
        return;

Camilla Löwy's avatar
Camilla Löwy committed
385
    if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
    {
        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
404
405
406
            LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
            exStyle |= WS_EX_LAYERED;
            SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
407
408
409
410
411

            // 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,
412
                                       RGB(255, 0, 255), 255, LWA_COLORKEY);
413
414
415
416
417
418
        }

        DeleteObject(region);
    }
    else
    {
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
419
420
421
        LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
        exStyle &= ~WS_EX_LAYERED;
        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
422
423
424
425
426
        RedrawWindow(window->win32.handle, NULL, NULL,
                     RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
    }
}

427
428
429
430
431
432
// Retrieves and translates modifier keys
//
static int getKeyMods(void)
{
    int mods = 0;

433
    if (GetKeyState(VK_SHIFT) & 0x8000)
434
        mods |= GLFW_MOD_SHIFT;
435
    if (GetKeyState(VK_CONTROL) & 0x8000)
436
        mods |= GLFW_MOD_CONTROL;
437
    if (GetKeyState(VK_MENU) & 0x8000)
438
        mods |= GLFW_MOD_ALT;
439
    if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
Noel Cower's avatar
Noel Cower committed
440
        mods |= GLFW_MOD_SUPER;
441
442
443
444
    if (GetKeyState(VK_CAPITAL) & 1)
        mods |= GLFW_MOD_CAPS_LOCK;
    if (GetKeyState(VK_NUMLOCK) & 1)
        mods |= GLFW_MOD_NUM_LOCK;
445
446
447
448

    return mods;
}

449
450
451
452
453
454
455
456
457
458
459
460
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);
}

461
// Make the specified window and its video mode active on its monitor
462
//
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
463
static void acquireMonitor(_GLFWwindow* window)
464
{
465
    if (!_glfw.win32.acquiredMonitorCount)
466
    {
467
        SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
468
469
470
471
472
473
474
475
476
477

        // 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);
        }
    }

478
479
480
    if (!window->monitor->window)
        _glfw.win32.acquiredMonitorCount++;

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
481
    _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
482
    _glfwInputMonitorWindow(window->monitor, window);
483
484
}

485
// Remove the window and restore the original video mode
486
//
487
static void releaseMonitor(_GLFWwindow* window)
488
{
489
490
491
    if (window->monitor->window != window)
        return;

492
493
    _glfw.win32.acquiredMonitorCount--;
    if (!_glfw.win32.acquiredMonitorCount)
494
    {
495
496
        SetThreadExecutionState(ES_CONTINUOUS);

497
498
499
500
501
        // 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
502
    _glfwInputMonitorWindow(window->monitor, NULL);
503
    _glfwRestoreVideoModeWin32(window->monitor);
504
505
}

Camilla Berglund's avatar
Camilla Berglund committed
506
// Window callback function (handles window messages)
507
//
Camilla Berglund's avatar
Camilla Berglund committed
508
509
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
                                   WPARAM wParam, LPARAM lParam)
Camilla Berglund's avatar
Camilla Berglund committed
510
{
511
    _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
512
    if (!window)
Camilla Berglund's avatar
Camilla Berglund committed
513
    {
514
        // This is the message handling for the hidden helper window
515
        // and for a regular window during its initial creation
516

Camilla Berglund's avatar
Camilla Berglund committed
517
        switch (uMsg)
Camilla Berglund's avatar
Camilla Berglund committed
518
        {
519
520
521
522
523
524
525
526
            case WM_NCCREATE:
            {
                if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
                    EnableNonClientDpiScaling(hWnd);

                break;
            }

527
528
529
530
            case WM_DISPLAYCHANGE:
                _glfwPollMonitorsWin32();
                break;

Camilla Berglund's avatar
Camilla Berglund committed
531
            case WM_DEVICECHANGE:
Camilla Berglund's avatar
Camilla Berglund committed
532
            {
533
                if (wParam == DBT_DEVICEARRIVAL)
Camilla Berglund's avatar
Camilla Berglund committed
534
535
                {
                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
536
537
                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
                        _glfwDetectJoystickConnectionWin32();
Camilla Berglund's avatar
Camilla Berglund committed
538
539
540
541
                }
                else if (wParam == DBT_DEVICEREMOVECOMPLETE)
                {
                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
542
543
                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
                        _glfwDetectJoystickDisconnectionWin32();
Camilla Berglund's avatar
Camilla Berglund committed
544
545
546
                }

                break;
Camilla Berglund's avatar
Camilla Berglund committed
547
            }
Camilla Berglund's avatar
Camilla Berglund committed
548
549
        }

550
551
552
553
554
        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
    }

    switch (uMsg)
    {
555
556
557
558
559
560
        case WM_MOUSEACTIVATE:
        {
            // HACK: Postpone cursor disabling when the window was activated by
            //       clicking a caption button
            if (HIWORD(lParam) == WM_LBUTTONDOWN)
            {
561
                if (LOWORD(lParam) != HTCLIENT)
562
563
564
565
566
567
568
569
570
571
572
573
574
                    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)
575
                    disableCursor(window);
576
577
578
579
580
581
582

                window->win32.frameAction = GLFW_FALSE;
            }

            break;
        }

583
        case WM_SETFOCUS:
Camilla Berglund's avatar
Camilla Berglund committed
584
        {
585
586
            _glfwInputWindowFocus(window, GLFW_TRUE);

587
588
589
590
591
            // HACK: Do not disable cursor while the user is interacting with
            //       a caption button
            if (window->win32.frameAction)
                break;

592
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
593
                disableCursor(window);
Camilla Berglund's avatar
Camilla Berglund committed
594
595
596
597

            return 0;
        }

598
        case WM_KILLFOCUS:
599
        {
600
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
601
                enableCursor(window);
602
603
604

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

606
            _glfwInputWindowFocus(window, GLFW_FALSE);
607
608
609
            return 0;
        }

Camilla Berglund's avatar
Camilla Berglund committed
610
611
        case WM_SYSCOMMAND:
        {
Camilla Berglund's avatar
Camilla Berglund committed
612
            switch (wParam & 0xfff0)
Camilla Berglund's avatar
Camilla Berglund committed
613
614
615
616
            {
                case SC_SCREENSAVE:
                case SC_MONITORPOWER:
                {
617
                    if (window->monitor)
Camilla Berglund's avatar
Camilla Berglund committed
618
                    {
619
                        // We are running in full screen mode, so disallow
Camilla Berglund's avatar
Camilla Berglund committed
620
                        // screen saver and screen blanking
Camilla Berglund's avatar
Camilla Berglund committed
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
                        return 0;
                    }
                    else
                        break;
                }

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

        case WM_CLOSE:
        {
636
            _glfwInputWindowCloseRequest(window);
Camilla Berglund's avatar
Camilla Berglund committed
637
638
639
            return 0;
        }

640
641
642
643
644
645
        case WM_INPUTLANGCHANGE:
        {
            _glfwUpdateKeyNamesWin32();
            break;
        }

Camilla Berglund's avatar
Camilla Berglund committed
646
        case WM_CHAR:
647
        case WM_SYSCHAR:
648
649
        case WM_UNICHAR:
        {
650
            const GLFWbool plain = (uMsg != WM_SYSCHAR);
651

652
            if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
653
            {
654
655
                // WM_UNICHAR is not sent by Windows, but is sent by some
                // third-party input method engine
656
657
658
659
                // Returning TRUE here announces support for this message
                return TRUE;
            }

660
661
662
663
664
665
            _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);
            return 0;
        }

        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
Camilla Berglund's avatar
Camilla Berglund committed
666
667
668
        case WM_KEYUP:
        case WM_SYSKEYUP:
        {
669
            int key, scancode;
670
            const int action = (HIWORD(lParam) & KF_UP) ? GLFW_RELEASE : GLFW_PRESS;
671
672
            const int mods = getKeyMods();

673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
            scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
            if (!scancode)
            {
                // NOTE: Some synthetic key messages have a scancode of zero
                // HACK: Map the virtual key back to a usable scancode
                scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
            }

            key = _glfw.win32.keycodes[scancode];

            // The Ctrl keys require special handling
            if (wParam == VK_CONTROL)
            {
                if (HIWORD(lParam) & KF_EXTENDED)
                {
                    // Right side keys have the extended key bit set
                    key = GLFW_KEY_RIGHT_CONTROL;
                }
                else
                {
                    // NOTE: Alt Gr sends Left Ctrl followed by Right Alt
                    // HACK: We only want one event for Alt Gr, so if we detect
                    //       this sequence we discard this Left Ctrl message now
                    //       and later report Right Alt normally
                    MSG next;
                    const DWORD 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)
                        {
                            if (next.wParam == VK_MENU &&
                                (HIWORD(next.lParam) & KF_EXTENDED) &&
                                next.time == time)
                            {
                                // Next message is Right Alt down so discard this
                                break;
                            }
                        }
                    }

                    // This is a regular Left Ctrl message
                    key = GLFW_KEY_LEFT_CONTROL;
                }
            }
            else if (wParam == VK_PROCESSKEY)
            {
                // IME notifies that keys have been filtered by setting the
                // virtual key-code to VK_PROCESSKEY
725
                break;
726
            }
727

728
            if (action == GLFW_RELEASE && wParam == VK_SHIFT)
Camilla Berglund's avatar
Camilla Berglund committed
729
            {
Camilla Löwy's avatar
Camilla Löwy committed
730
731
732
                // 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
733
734
                _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
735
            }
736
737
            else if (wParam == VK_SNAPSHOT)
            {
Camilla Löwy's avatar
Camilla Löwy committed
738
                // HACK: Key down is not reported for the Print Screen key
739
740
                _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
                _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
741
            }
Camilla Berglund's avatar
Camilla Berglund committed
742
            else
743
                _glfwInputKey(window, key, scancode, action, mods);
Camilla Berglund's avatar
Camilla Berglund committed
744

745
            break;
Camilla Berglund's avatar
Camilla Berglund committed
746
747
748
749
750
        }

        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_MBUTTONDOWN:
751
752
        case WM_XBUTTONDOWN:
        case WM_LBUTTONUP:
Camilla Berglund's avatar
Camilla Berglund committed
753
754
        case WM_RBUTTONUP:
        case WM_MBUTTONUP:
755
        case WM_XBUTTONUP:
Camilla Berglund's avatar
Camilla Berglund committed
756
        {
757
            int i, button, action;
758
759
760
761
762
763
764
765
766
767
768

            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
769

770
771
772
773
774
            if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN ||
                uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
            {
                action = GLFW_PRESS;
            }
775
            else
776
                action = GLFW_RELEASE;
777

778
            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
779
780
781
            {
                if (window->mouseButtons[i] == GLFW_PRESS)
                    break;
782
            }
783

784
            if (i > GLFW_MOUSE_BUTTON_LAST)
785
786
                SetCapture(hWnd);

787
788
            _glfwInputMouseClick(window, button, action, getKeyMods());

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

795
            if (i > GLFW_MOUSE_BUTTON_LAST)
796
797
                ReleaseCapture();

798
            if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
799
                return TRUE;
Camilla Berglund's avatar
Camilla Berglund committed
800

801
            return 0;
Camilla Berglund's avatar
Camilla Berglund committed
802
803
804
805
        }

        case WM_MOUSEMOVE:
        {
806
807
            const int x = GET_X_LPARAM(lParam);
            const int y = GET_Y_LPARAM(lParam);
Camilla Berglund's avatar
Camilla Berglund committed
808

809
810
811
812
813
814
815
816
817
818
819
820
821
            if (!window->win32.cursorTracked)
            {
                TRACKMOUSEEVENT tme;
                ZeroMemory(&tme, sizeof(tme));
                tme.cbSize = sizeof(tme);
                tme.dwFlags = TME_LEAVE;
                tme.hwndTrack = window->win32.handle;
                TrackMouseEvent(&tme);

                window->win32.cursorTracked = GLFW_TRUE;
                _glfwInputCursorEnter(window, GLFW_TRUE);
            }

822
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
823
824
825
            {
                const int dx = x - window->win32.lastCursorPosX;
                const int dy = y - window->win32.lastCursorPosY;
826
827
828
829
830
831

                if (_glfw.win32.disabledCursorWindow != window)
                    break;
                if (window->rawMouseMotion)
                    break;

832
833
834
835
836
837
                _glfwInputCursorPos(window,
                                    window->virtualCursorPosX + dx,
                                    window->virtualCursorPosY + dy);
            }
            else
                _glfwInputCursorPos(window, x, y);
838

839
840
            window->win32.lastCursorPosX = x;
            window->win32.lastCursorPosY = y;
Camilla Berglund's avatar
Camilla Berglund committed
841

842
843
844
            return 0;
        }

845
846
        case WM_INPUT:
        {
847
            UINT size = 0;
848
            HRAWINPUT ri = (HRAWINPUT) lParam;
849
            RAWINPUT* data = NULL;
850
851
            int dx, dy;

852
853
854
            if (_glfw.win32.disabledCursorWindow != window)
                break;
            if (!window->rawMouseMotion)
855
856
857
                break;

            GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
Camilla Löwy's avatar
Camilla Löwy committed
858
            if (size > (UINT) _glfw.win32.rawInputSize)
859
860
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
            {
                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;
        }

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

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

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

917
918
919
        case WM_ENTERSIZEMOVE:
        case WM_ENTERMENULOOP:
        {
920
921
922
            if (window->win32.frameAction)
                break;

923
924
            // HACK: Enable the cursor while the user is moving or
            //       resizing the window or using the window menu
925
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
926
                enableCursor(window);
927
928
929
930
931
932
933

            break;
        }

        case WM_EXITSIZEMOVE:
        case WM_EXITMENULOOP:
        {
934
935
936
            if (window->win32.frameAction)
                break;

937
938
            // HACK: Disable the cursor once the user is done moving or
            //       resizing the window or using the menu
939
            if (window->cursorMode == GLFW_CURSOR_DISABLED)
940
                disableCursor(window);
941
942
943
944

            break;
        }

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

952
953
            if (_glfw.win32.disabledCursorWindow == window)
                updateClipRect(window);
Camilla Berglund's avatar
Camilla Berglund committed
954

955
956
957
958
959
            if (window->win32.iconified != iconified)
                _glfwInputWindowIconify(window, iconified);

            if (window->win32.maximized != maximized)
                _glfwInputWindowMaximize(window, maximized);
960
961
962
963

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

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

975
976
            window->win32.iconified = iconified;
            window->win32.maximized = maximized;
Camilla Berglund's avatar
Camilla Berglund committed
977
978
979
980
981
            return 0;
        }

        case WM_MOVE:
        {
982
983
            if (_glfw.win32.disabledCursorWindow == window)
                updateClipRect(window);
984

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

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

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

        case WM_GETMINMAXINFO:
        {
            int xoff, yoff;
1008
            UINT dpi = USER_DEFAULT_SCREEN_DPI;
1009
            MINMAXINFO* mmi = (MINMAXINFO*) lParam;
1010

Camilla Berglund's avatar
Camilla Berglund committed
1011
1012
1013
            if (window->monitor)
                break;

1014
1015
1016
            if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
                dpi = GetDpiForWindow(window->win32.handle);

1017
            getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
1018
                              0, 0, &xoff, &yoff, dpi);
1019

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

Camilla Berglund's avatar
Camilla Berglund committed
1027
1028
            if (window->maxwidth != GLFW_DONT_CARE &&
                window->maxheight != GLFW_DONT_CARE)
1029
            {
Camilla Berglund's avatar
Camilla Berglund committed
1030
1031
                mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
                mmi->ptMaxTrackSize.y = window->maxheight + yoff;
1032
1033
            }

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
            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;
            }

1050
1051
1052
            return 0;
        }

Camilla Berglund's avatar
Camilla Berglund committed
1053
1054
        case WM_PAINT:
        {
1055
            _glfwInputWindowDamage(window);
Camilla Berglund's avatar
Camilla Berglund committed
1056
1057
1058
            break;
        }

Camilla Berglund's avatar
Camilla Berglund committed
1059
1060
1061
1062
1063
        case WM_ERASEBKGND:
        {
            return TRUE;
        }

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
        case WM_NCACTIVATE:
        case WM_NCPAINT:
        {
            // Prevent title bar from being drawn after restoring a minimized
            // undecorated window
            if (!window->decorated)
                return TRUE;

            break;
        }

1075
1076
1077
1078
1079
1080
1081
        case WM_DWMCOMPOSITIONCHANGED:
        {
            if (window->win32.transparent)
                updateFramebufferTransparency(window);
            return 0;
        }

1082
1083
        case WM_GETDPISCALEDSIZE:
        {
Camilla Löwy's avatar
Camilla Löwy committed
1084
1085
1086
            if (window->win32.scaleToMonitor)
                break;

Camilla Löwy's avatar
Cleanup    
Camilla Löwy committed
1087
            // Adjust the window size to keep the content area size constant
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
            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;
        }

1110
1111
        case WM_DPICHANGED:
        {
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
            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);
            }

1128
1129
1130
1131
            _glfwInputWindowContentScale(window, xscale, yscale);
            break;
        }

1132
1133
        case WM_SETCURSOR:
        {
1134
            if (LOWORD(lParam) == HTCLIENT)
1135
            {
1136
                updateCursorImage(window);
1137
                return TRUE;
1138
1139
1140
1141
1142
            }

            break;
        }

arturo's avatar
arturo committed
1143
1144
        case WM_DROPFILES:
        {
Camilla Berglund's avatar
Camilla Berglund committed
1145
            HDROP drop = (HDROP) wParam;
Camilla Berglund's avatar
Camilla Berglund committed
1146
            POINT pt;
1147
1148
            int i;

Camilla Berglund's avatar
Camilla Berglund committed
1149
            const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
1150
            char** paths = calloc(count, sizeof(char*));
Camilla Berglund's avatar
Camilla Berglund committed
1151
1152

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

1156
            for (i = 0;  i < count;  i++)
Camilla Berglund's avatar
Camilla Berglund committed
1157
            {
Camilla Berglund's avatar
Camilla Berglund committed
1158
                const UINT length = DragQueryFileW(drop, i, NULL, 0);
1159
                WCHAR* buffer = calloc((size_t) length + 1, sizeof(WCHAR));
Camilla Berglund's avatar
Camilla Berglund committed
1160

Camilla Berglund's avatar
Camilla Berglund committed
1161
                DragQueryFileW(drop, i, buffer, length + 1);
1162
                paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
Camilla Berglund's avatar
Camilla Berglund committed
1163

1164
                free(buffer);
Camilla Berglund's avatar
Camilla Berglund committed
1165
1166
            }

1167
            _glfwInputDrop(window, count, (const char**) paths);
1168
1169

            for (i = 0;  i < count;  i++)
1170
1171
                free(paths[i]);
            free(paths);
1172

Camilla Berglund's avatar
Camilla Berglund committed
1173
            DragFinish(drop);
1174
            return 0;
arturo's avatar
arturo committed
1175
        }
Camilla Berglund's avatar
Camilla Berglund committed
1176
1177
    }

1178
    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
Camilla Berglund's avatar
Camilla Berglund committed
1179
1180
}

Camilla Berglund's avatar
Camilla Berglund committed
1181
// Creates the GLFW window
1182
//
Camilla Berglund's avatar
Cleanup    
Camilla Berglund committed
1183
static int createNativeWindow(_GLFWwindow* window,
1184
1185
                              const _GLFWwndconfig* wndconfig,
                              const _GLFWfbconfig* fbconfig)
Camilla Berglund's avatar
Camilla Berglund committed
1186
{
1187
    int xpos, ypos, fullWidth, fullHeight;
1188
    WCHAR* wideTitle;
1189
1190
    DWORD style = getWindowStyle(window);
    DWORD exStyle = getWindowExStyle(window);
Camilla Berglund's avatar
Camilla Berglund committed
1191

1192
    if (window->monitor)
1193
    {
1194
1195
        GLFWvidmode mode;

1196
1197
        // 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
1198
        //       video mode has been picked in _glfwSetVideoModeWin32
1199
1200
        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
        _glfwPlatformGetVideoMode(window->monitor, &mode);
1201
1202
        fullWidth  = mode.width;
        fullHeight = mode.height;
1203
    }
Camilla Berglund's avatar
Camilla Berglund committed
1204
1205
    else
    {
1206
1207
        xpos = CW_USEDEFAULT;
        ypos = CW_USEDEFAULT;
Camilla Berglund's avatar
Camilla Berglund committed
1208

1209
        window->win32.maximized = wndconfig->maximized;
1210
1211
1212
1213
        if (wndconfig->maximized)
            style |= WS_MAXIMIZE;

        getFullWindowSize(style, exStyle,