static void handlePointerButton(_GLFWwindow* window, int pressed, const MirPointerEvent* pointer_event) { MirPointerButton button = mir_pointer_event_buttons (pointer_event); int mods = mir_pointer_event_modifiers(pointer_event); const int publicMods = mirModToGLFWMod(mods); int publicButton; switch (button) { case mir_pointer_button_primary: publicButton = GLFW_MOUSE_BUTTON_LEFT; break; case mir_pointer_button_secondary: publicButton = GLFW_MOUSE_BUTTON_RIGHT; break; case mir_pointer_button_tertiary: publicButton = GLFW_MOUSE_BUTTON_MIDDLE; break; case mir_pointer_button_forward: // FIXME What is the forward button? publicButton = GLFW_MOUSE_BUTTON_4; break; case mir_pointer_button_back: // FIXME What is the back button? publicButton = GLFW_MOUSE_BUTTON_5; break; default: break; } _glfwInputMouseClick(window, publicButton, pressed, publicMods); }
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); if (!focused) { int key, button; for (key = 0; key <= GLFW_KEY_LAST; key++) { if (window->keys[key] == GLFW_PRESS) { const int scancode = _glfwPlatformGetKeyScancode(key); _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0); } } for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++) { if (window->mouseButtons[button] == GLFW_PRESS) _glfwInputMouseClick(window, button, GLFW_RELEASE, 0); } } }
static void handleMouseButton(_GLFWwindow* window, int pressed, int mods, MirMotionButton button) { static int lastButton; int publicButton; const int publicMods = mirModToGLFWMod(mods); switch (button) { case mir_motion_button_primary: publicButton = GLFW_MOUSE_BUTTON_LEFT; break; case mir_motion_button_secondary: publicButton = GLFW_MOUSE_BUTTON_RIGHT; break; case mir_motion_button_tertiary: publicButton = GLFW_MOUSE_BUTTON_MIDDLE; break; case mir_motion_button_forward: // FIXME What is the forward button? publicButton = GLFW_MOUSE_BUTTON_4; break; case mir_motion_button_back: // FIXME What is the back button? publicButton = GLFW_MOUSE_BUTTON_5; break; default: publicButton = lastButton; break; } lastButton = publicButton; _glfwInputMouseClick(window, publicButton, pressed, publicMods); }
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { if (focused) { _glfw.cursorWindow = window; if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); } else { int i; _glfw.cursorWindow = NULL; if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); // Release all pressed keyboard keys for (i = 0; i <= GLFW_KEY_LAST; i++) { if (window->keys[i] == GLFW_PRESS) _glfwInputKey(window, i, 0, GLFW_RELEASE, 0); } // Release all pressed mouse buttons for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) { if (window->mouseButtons[i] == GLFW_PRESS) _glfwInputMouseClick(window, i, GLFW_RELEASE, 0); } } }
static void handlePointerButton(_GLFWwindow* window, int pressed, const MirPointerEvent* pointer_event) { int mods = mir_pointer_event_modifiers(pointer_event); const int publicMods = mirModToGLFWMod(mods); MirPointerButton button = mir_pointer_button_primary; static uint32_t oldButtonStates = 0; uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event); int publicButton = GLFW_MOUSE_BUTTON_LEFT; // XOR our old button states our new states to figure out what was added or removed button = newButtonStates ^ oldButtonStates; switch (button) { case mir_pointer_button_primary: publicButton = GLFW_MOUSE_BUTTON_LEFT; break; case mir_pointer_button_secondary: publicButton = GLFW_MOUSE_BUTTON_RIGHT; break; case mir_pointer_button_tertiary: publicButton = GLFW_MOUSE_BUTTON_MIDDLE; break; case mir_pointer_button_forward: // FIXME What is the forward button? publicButton = GLFW_MOUSE_BUTTON_4; break; case mir_pointer_button_back: // FIXME What is the back button? publicButton = GLFW_MOUSE_BUTTON_5; break; default: break; } oldButtonStates = newButtonStates; _glfwInputMouseClick(window, publicButton, pressed, publicMods); }
void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused) { if (focused) { if (_glfwLibrary.focusedWindow != window) { _glfwLibrary.focusedWindow = window; if (window->windowFocusCallback) window->windowFocusCallback(window, focused); } } else { if (_glfwLibrary.focusedWindow == window) { int i; // Release all pressed keyboard keys for (i = 0; i <= GLFW_KEY_LAST; i++) { if (window->key[i] == GLFW_PRESS) _glfwInputKey(window, i, GLFW_RELEASE); } // Release all pressed mouse buttons for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++) { if (window->mouseButton[i] == GLFW_PRESS) _glfwInputMouseClick(window, i, GLFW_RELEASE); } _glfwLibrary.focusedWindow = NULL; if (window->windowFocusCallback) window->windowFocusCallback(window, focused); } } }
void _glfwInputDeactivation( void ) { int i; // Release all keyboard keys for( i = 0; i <= GLFW_KEY_LAST; i ++ ) { if( _glfwInput.Key[ i ] == GLFW_PRESS ) { _glfwInputKey( i, GLFW_RELEASE ); } } // Release all mouse buttons for( i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i ++ ) { if( _glfwInput.MouseButton[ i ] == GLFW_PRESS ) { _glfwInputMouseClick( i, GLFW_RELEASE ); } } }
static void pointerHandleButton(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { _GLFWwindow* window = _glfw.wl.pointerFocus; int glfwButton; if (!window) return; /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev * codes. */ glfwButton = button - BTN_LEFT; _glfwInputMouseClick(window, glfwButton, state == WL_POINTER_BUTTON_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE, _glfw.wl.xkb.modifiers); }
static int _glfwProcessEvents( void ) { struct IntuiMessage message, *tmp_message = NULL; struct MsgPort *msg_port; int win_closed = GL_FALSE, action; int x, y; // Examine pending messages msg_port = _glfwWin.Window->UserPort; while( (tmp_message = (struct IntuiMessage *) GetMsg( msg_port )) ) { // Copy contents of message structure message = *tmp_message; // Now reply to the message (we don't need it anymore) ReplyMsg( (struct Message *) tmp_message ); // Handle different messages switch( message.Class ) { // Was the window activated? case IDCMP_ACTIVEWINDOW: _glfwWin.Active = GL_TRUE; break; // Was the window deactivated? case IDCMP_INACTIVEWINDOW: _glfwWin.Active = GL_FALSE; _glfwInputDeactivation(); break; // Did we get a keyboard press or release? case IDCMP_RAWKEY: action = (message.Code & 0x80) ? GLFW_RELEASE : GLFW_PRESS; message.Code &= 0x7F; _glfwInputKey( _glfwTranslateKey( &message ), action ); _glfwInputChar( _glfwTranslateChar( &message ), action ); break; // Was the mouse moved? case IDCMP_MOUSEMOVE: x = message.MouseX; y = message.MouseY; if( _glfwWin.PointerHidden ) { // When pointer is hidden, we get delta moves x += _glfwInput.MousePosX; y += _glfwInput.MousePosY; } else if( x < 0 || x >= _glfwWin.Width || y < 0 || y >= _glfwWin.Height ) { // Only report mouse moves that are INSIDE client area break; } if( x != _glfwInput.MousePosX || y != _glfwInput.MousePosY ) { _glfwInput.MousePosX = x; _glfwInput.MousePosY = y; if( _glfwWin.MousePosCallback ) { _glfwWin.MousePosCallback( x, y ); } } break; // Did we get a mouse button event? case IDCMP_MOUSEBUTTONS: switch( message.Code ) { case SELECTUP: _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE ); break; case SELECTDOWN: _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS ); break; case MENUUP: _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE ); break; case MENUDOWN: _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS ); break; default: break; } break; // Was the window size changed? case IDCMP_NEWSIZE: _glfwWin.Width = message.IDCMPWindow->GZZWidth; _glfwWin.Height = message.IDCMPWindow->GZZHeight; if( _glfwWin.WindowSizeCallback ) { _glfwWin.WindowSizeCallback( _glfwWin.Width, _glfwWin.Height ); } break; // Was the window contents damaged? case IDCMP_REFRESHWINDOW: // Intuition wants us to do this... BeginRefresh( _glfwWin.Window ); EndRefresh( _glfwWin.Window, TRUE ); // Call user callback function if( _glfwWin.WindowRefreshCallback ) { _glfwWin.WindowRefreshCallback(); } break; // Was the window closed? case IDCMP_CLOSEWINDOW: win_closed = GL_TRUE; break; default: break; } } // Return GL_TRUE if window was closed return( win_closed ); }
LRESULT CALLBACK _glfwWindowCallback( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { int WheelDelta, Iconified; // ZBS added this code to look for the correct _glfwWin given the hWnd // Changed all the references from _glfwWin. to winPtr-> _GLFWwin *winPtr = 0; int i; for( i=0; i<MAX_ALIASES; i++ ) { if( aliases[i].Wnd == hWnd ) { winPtr = &aliases[i]; break; } } if( winPtr == 0 ) { winPtr = &_glfwWin; } // Handle certain window messages switch( uMsg ) { // Window activate message? (iconification?) case WM_ACTIVATE: winPtr->Active = LOWORD(wParam) != WA_INACTIVE ? GL_TRUE : GL_FALSE; Iconified = HIWORD(wParam) ? GL_TRUE : GL_FALSE; // Were we deactivated/iconified? if( (!winPtr->Active || Iconified) && !winPtr->Iconified ) { // If we are in fullscreen mode we need to iconify if( winPtr->Fullscreen ) { // Do we need to manually iconify? if( !Iconified ) { // Minimize window CloseWindow( winPtr->Wnd ); // The window is now iconified Iconified = GL_TRUE; } // Change display settings to the desktop resolution ChangeDisplaySettings( NULL, CDS_FULLSCREEN ); } // Unlock mouse if( !winPtr->OldMouseLockValid ) { winPtr->OldMouseLock = winPtr->MouseLock; winPtr->OldMouseLockValid = GL_TRUE; glfwEnable( GLFW_MOUSE_CURSOR ); } } else if( winPtr->Active || !Iconified ) { // If we are in fullscreen mode we need to maximize if( winPtr->Fullscreen && winPtr->Iconified ) { // Change display settings to the user selected mode _glfwSetVideoModeMODE( winPtr->ModeID ); // Do we need to manually restore window? if( Iconified ) { // Restore window OpenIcon( winPtr->Wnd ); // The window is no longer iconified Iconified = GL_FALSE; // Activate window ShowWindow( hWnd, SW_SHOW ); _glfwSetForegroundWindow( winPtr->Wnd ); SetFocus( winPtr->Wnd ); } } // Lock mouse, if necessary if( winPtr->OldMouseLockValid && winPtr->OldMouseLock ) { glfwDisable( GLFW_MOUSE_CURSOR ); } winPtr->OldMouseLockValid = GL_FALSE; } winPtr->Iconified = Iconified; return 0; // Intercept system commands (forbid certain actions/events) case WM_SYSCOMMAND: switch( wParam ) { // Screensaver trying to start or monitor trying to enter // powersave? case SC_SCREENSAVE: case SC_MONITORPOWER: if( winPtr->Fullscreen ) { return 0; } else { break; } // User trying to access application menu using ALT? case SC_KEYMENU: return 0; } break; // Did we receive a close message? case WM_CLOSE: PostQuitMessage( 0 ); return 0; // Is a key being pressed? case WM_KEYDOWN: case WM_SYSKEYDOWN: // Translate and report key press _glfwInputKey( _glfwTranslateKey( wParam, lParam ), GLFW_PRESS ); // Translate and report character input if( winPtr->CharCallback ) { _glfwTranslateChar( wParam, lParam, GLFW_PRESS ); } return 0; // Is a key being released? case WM_KEYUP: case WM_SYSKEYUP: // Special trick: release both shift keys on SHIFT up event if( wParam == VK_SHIFT ) { _glfwInputKey( GLFW_KEY_LSHIFT, GLFW_RELEASE ); _glfwInputKey( GLFW_KEY_RSHIFT, GLFW_RELEASE ); } else { // Translate and report key release _glfwInputKey( _glfwTranslateKey( wParam, lParam ), GLFW_RELEASE ); } // Translate and report character input if( winPtr->CharCallback ) { _glfwTranslateChar( wParam, lParam, GLFW_RELEASE ); } return 0; // Were any of the mouse-buttons pressed? case WM_LBUTTONDOWN: SetCapture(hWnd); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS ); return 0; case WM_RBUTTONDOWN: SetCapture(hWnd); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS ); return 0; case WM_MBUTTONDOWN: SetCapture(hWnd); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS ); return 0; case WM_XBUTTONDOWN: if( HIWORD(wParam) == XBUTTON1 ) { SetCapture(hWnd); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_4, GLFW_PRESS ); } else if( HIWORD(wParam) == XBUTTON2 ) { SetCapture(hWnd); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_5, GLFW_PRESS ); } return 1; // Were any of the mouse-buttons released? case WM_LBUTTONUP: ReleaseCapture(); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE ); return 0; case WM_RBUTTONUP: ReleaseCapture(); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE ); return 0; case WM_MBUTTONUP: ReleaseCapture(); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE ); return 0; case WM_XBUTTONUP: if( HIWORD(wParam) == XBUTTON1 ) { ReleaseCapture(); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_4, GLFW_RELEASE ); } else if( HIWORD(wParam) == XBUTTON2 ) { ReleaseCapture(); _glfwInputMouseClick( GLFW_MOUSE_BUTTON_5, GLFW_RELEASE ); } return 1; // Did the mouse move? case WM_MOUSEMOVE: { int NewMouseX, NewMouseY; // Get signed (!) mouse position NewMouseX = (int)((short)LOWORD(lParam)); NewMouseY = (int)((short)HIWORD(lParam)); if( NewMouseX != _glfwInput.OldMouseX || NewMouseY != _glfwInput.OldMouseY ) { if( winPtr->MouseLock ) { _glfwInput.MousePosX += NewMouseX - _glfwInput.OldMouseX; _glfwInput.MousePosY += NewMouseY - _glfwInput.OldMouseY; } else { _glfwInput.MousePosX = NewMouseX; _glfwInput.MousePosY = NewMouseY; } _glfwInput.OldMouseX = NewMouseX; _glfwInput.OldMouseY = NewMouseY; _glfwInput.MouseMoved = GL_TRUE; // Call user callback function if( winPtr->MousePosCallback ) { winPtr->MousePosCallback( _glfwInput.MousePosX, _glfwInput.MousePosY ); } } } return 0; // Mouse wheel action? case WM_MOUSEWHEEL: // WM_MOUSEWHEEL is not supported under Windows 95 if( _glfwSys.WinVer != _GLFW_WIN_95 ) { WheelDelta = (((int)wParam) >> 16) / WHEEL_DELTA; _glfwInput.WheelPos += WheelDelta; if( winPtr->MouseWheelCallback ) { winPtr->MouseWheelCallback( _glfwInput.WheelPos ); } return 0; } break; // Resize the window? case WM_SIZE: winPtr->Width = LOWORD(lParam); winPtr->Height = HIWORD(lParam); if( winPtr->WindowSizeCallback ) { winPtr->WindowSizeCallback( LOWORD(lParam), HIWORD(lParam) ); } return 0; // Was the window contents damaged? case WM_PAINT: // Call user callback function if( winPtr->WindowRefreshCallback ) { winPtr->WindowRefreshCallback(); } break; default: break; }
// Window callback function (handles window events) // static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { _GLFWwindow* window = (_GLFWwindow*) GetWindowLongPtrW(hWnd, 0); switch (uMsg) { case WM_NCCREATE: { CREATESTRUCTW* cs = (CREATESTRUCTW*) lParam; SetWindowLongPtrW(hWnd, 0, (LONG_PTR) cs->lpCreateParams); break; } case WM_SETFOCUS: { if (window->cursorMode != GLFW_CURSOR_NORMAL) _glfwPlatformApplyCursorMode(window); if (window->monitor && window->autoIconify) enterFullscreenMode(window); _glfwInputWindowFocus(window, GL_TRUE); return 0; } case WM_KILLFOCUS: { if (window->cursorMode != GLFW_CURSOR_NORMAL) restoreCursor(window); if (window->monitor && window->autoIconify) { _glfwPlatformIconifyWindow(window); leaveFullscreenMode(window); } _glfwInputWindowFocus(window, GL_FALSE); return 0; } case WM_SYSCOMMAND: { switch (wParam & 0xfff0) { case SC_SCREENSAVE: case SC_MONITORPOWER: { if (window->monitor) { // We are running in full screen mode, so disallow // screen saver and screen blanking return 0; } else break; } // User trying to access application menu using ALT? case SC_KEYMENU: return 0; } break; } case WM_CLOSE: { _glfwInputWindowCloseRequest(window); return 0; } case WM_KEYDOWN: case WM_SYSKEYDOWN: { const int scancode = (lParam >> 16) & 0x1ff; const int key = translateKey(wParam, lParam); if (key == _GLFW_KEY_INVALID) break; _glfwInputKey(window, key, scancode, GLFW_PRESS, getKeyMods()); break; } case WM_CHAR: { _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE); return 0; } case WM_SYSCHAR: { _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_FALSE); return 0; } case WM_UNICHAR: { // This message is not sent by Windows, but is sent by some // third-party input method engines if (wParam == UNICODE_NOCHAR) { // Returning TRUE here announces support for this message return TRUE; } _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE); return FALSE; } case WM_KEYUP: case WM_SYSKEYUP: { const int mods = getKeyMods(); const int scancode = (lParam >> 16) & 0x1ff; const int key = translateKey(wParam, lParam); if (key == _GLFW_KEY_INVALID) break; if (wParam == VK_SHIFT) { // Release both Shift keys on Shift up event, as only one event // is sent even if both keys are released _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods); _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods); } else if (wParam == VK_SNAPSHOT) { // Key down is not reported for the print screen key _glfwInputKey(window, key, scancode, GLFW_PRESS, mods); _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods); } else _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods); break; } case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: { const int mods = getKeyMods(); SetCapture(hWnd); if (uMsg == WM_LBUTTONDOWN) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); else if (uMsg == WM_RBUTTONDOWN) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods); else if (uMsg == WM_MBUTTONDOWN) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods); else { if (HIWORD(wParam) == XBUTTON1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_PRESS, mods); else if (HIWORD(wParam) == XBUTTON2) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS, mods); return TRUE; } return 0; } case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: { const int mods = getKeyMods(); ReleaseCapture(); if (uMsg == WM_LBUTTONUP) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods); else if (uMsg == WM_RBUTTONUP) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods); else if (uMsg == WM_MBUTTONUP) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods); else { if (HIWORD(wParam) == XBUTTON1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_RELEASE, mods); else if (HIWORD(wParam) == XBUTTON2) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE, mods); return TRUE; } return 0; } case WM_MOUSEMOVE: { const int x = GET_X_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam); if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (_glfw.focusedWindow != window) break; _glfwInputCursorMotion(window, x - window->win32.cursorPosX, y - window->win32.cursorPosY); } else _glfwInputCursorMotion(window, x, y); window->win32.cursorPosX = x; window->win32.cursorPosY = y; if (!window->win32.cursorInside) { TRACKMOUSEEVENT tme; ZeroMemory(&tme, sizeof(tme)); tme.cbSize = sizeof(tme); tme.dwFlags = TME_LEAVE; tme.hwndTrack = window->win32.handle; TrackMouseEvent(&tme); window->win32.cursorInside = GL_TRUE; _glfwInputCursorEnter(window, GL_TRUE); } return 0; } case WM_MOUSELEAVE: { window->win32.cursorInside = GL_FALSE; _glfwInputCursorEnter(window, GL_FALSE); return 0; } case WM_MOUSEWHEEL: { _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA); return 0; } case WM_MOUSEHWHEEL: { // This message is only sent on Windows Vista and later // NOTE: The X-axis is inverted for consistency with OS X and X11. _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0); return 0; } case WM_SIZE: { if (_glfw.focusedWindow == window) { if (window->cursorMode == GLFW_CURSOR_DISABLED) updateClipRect(window); } if (!window->win32.iconified && wParam == SIZE_MINIMIZED) { window->win32.iconified = GL_TRUE; _glfwInputWindowIconify(window, GL_TRUE); } else if (window->win32.iconified && (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)) { window->win32.iconified = GL_FALSE; _glfwInputWindowIconify(window, GL_FALSE); } _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam)); _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam)); return 0; } case WM_MOVE: { if (_glfw.focusedWindow == window) { if (window->cursorMode == GLFW_CURSOR_DISABLED) updateClipRect(window); } // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // those macros do not handle negative window positions correctly _glfwInputWindowPos(window, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); return 0; } case WM_PAINT: { _glfwInputWindowDamage(window); break; } case WM_ERASEBKGND: { return TRUE; } case WM_SETCURSOR: { if (_glfw.focusedWindow == window && LOWORD(lParam) == HTCLIENT) { if (window->cursorMode == GLFW_CURSOR_HIDDEN || window->cursorMode == GLFW_CURSOR_DISABLED) { SetCursor(NULL); return TRUE; } else if (window->cursor) { SetCursor(window->cursor->win32.handle); return TRUE; } } break; } case WM_DEVICECHANGE: { if (DBT_DEVNODES_CHANGED == wParam) { _glfwInputMonitorChange(); return TRUE; } break; } case WM_DWMCOMPOSITIONCHANGED: { if (_glfwIsCompositionEnabled()) { _GLFWwindow* previous = _glfwPlatformGetCurrentContext(); _glfwPlatformMakeContextCurrent(window); _glfwPlatformSwapInterval(0); _glfwPlatformMakeContextCurrent(previous); } // TODO: Restore vsync if compositing was disabled break; } case WM_DROPFILES: { HDROP hDrop = (HDROP) wParam; POINT pt; int i; const int count = DragQueryFileW(hDrop, 0xffffffff, NULL, 0); char** paths = calloc(count, sizeof(char*)); // Move the mouse to the position of the drop DragQueryPoint(hDrop, &pt); _glfwInputCursorMotion(window, pt.x, pt.y); for (i = 0; i < count; i++) { const UINT length = DragQueryFileW(hDrop, i, NULL, 0); WCHAR* buffer = calloc(length + 1, sizeof(WCHAR)); DragQueryFileW(hDrop, i, buffer, length + 1); paths[i] = _glfwCreateUTF8FromWideString(buffer); free(buffer); } _glfwInputDrop(window, count, (const char**) paths); for (i = 0; i < count; i++) free(paths[i]); free(paths); DragFinish(hDrop); return 0; } } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
static void processEvent(XEvent *event) { _GLFWwindow* window; switch (event->type) { case KeyPress: { // A keyboard key was pressed window = findWindow(event->xkey.window); if (window == NULL) return; _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_PRESS); _glfwInputChar(window, translateChar(&event->xkey)); break; } case KeyRelease: { // A keyboard key was released window = findWindow(event->xkey.window); if (window == NULL) return; // Do not report key releases for key repeats. For key repeats we // will get KeyRelease/KeyPress pairs with similar or identical // time stamps. User selected key repeat filtering is handled in // _glfwInputKey/_glfwInputChar. if (XEventsQueued(_glfwLibrary.X11.display, QueuedAfterReading)) { XEvent nextEvent; XPeekEvent(_glfwLibrary.X11.display, &nextEvent); if (nextEvent.type == KeyPress && nextEvent.xkey.window == event->xkey.window && nextEvent.xkey.keycode == event->xkey.keycode) { // This last check is a hack to work around key repeats // leaking through due to some sort of time drift // Toshiyuki Takahashi can press a button 16 times per // second so it's fairly safe to assume that no human is // pressing the key 50 times per second (value is ms) if ((nextEvent.xkey.time - event->xkey.time) < 20) { // Do not report anything for this event break; } } } _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_RELEASE); break; } case ButtonPress: { // A mouse button was pressed or a scrolling event occurred window = findWindow(event->xbutton.window); if (window == NULL) return; if (event->xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); else if (event->xbutton.button == Button2) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS); else if (event->xbutton.button == Button3) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS); // XFree86 3.3.2 and later translates mouse wheel up/down into // mouse button 4 & 5 presses else if (event->xbutton.button == Button4) _glfwInputScroll(window, 0.0, 1.0); else if (event->xbutton.button == Button5) _glfwInputScroll(window, 0.0, -1.0); else if (event->xbutton.button == Button6) _glfwInputScroll(window, -1.0, 0.0); else if (event->xbutton.button == Button7) _glfwInputScroll(window, 1.0, 0.0); break; } case ButtonRelease: { // A mouse button was released window = findWindow(event->xbutton.window); if (window == NULL) return; if (event->xbutton.button == Button1) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE); } else if (event->xbutton.button == Button2) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE); } else if (event->xbutton.button == Button3) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE); } break; } case EnterNotify: { // The cursor entered the window window = findWindow(event->xcrossing.window); if (window == NULL) return; if (window->cursorMode == GLFW_CURSOR_HIDDEN) hideCursor(window); _glfwInputCursorEnter(window, GL_TRUE); break; } case LeaveNotify: { // The cursor left the window window = findWindow(event->xcrossing.window); if (window == NULL) return; if (window->cursorMode == GLFW_CURSOR_HIDDEN) showCursor(window); _glfwInputCursorEnter(window, GL_FALSE); break; } case MotionNotify: { // The cursor was moved window = findWindow(event->xmotion.window); if (window == NULL) return; if (event->xmotion.x != window->X11.cursorPosX || event->xmotion.y != window->X11.cursorPosY) { // The cursor was moved by something other than GLFW int x, y; if (window->cursorMode == GLFW_CURSOR_CAPTURED) { if (_glfwLibrary.activeWindow != window) break; x = event->xmotion.x - window->X11.cursorPosX; y = event->xmotion.y - window->X11.cursorPosY; } else { x = event->xmotion.x; y = event->xmotion.y; } window->X11.cursorPosX = event->xmotion.x; window->X11.cursorPosY = event->xmotion.y; window->X11.cursorCentered = GL_FALSE; _glfwInputCursorMotion(window, x, y); } break; } case ConfigureNotify: { // The window configuration changed somehow window = findWindow(event->xconfigure.window); if (window == NULL) return; _glfwInputWindowSize(window, event->xconfigure.width, event->xconfigure.height); _glfwInputWindowPos(window, event->xconfigure.x, event->xconfigure.y); break; } case ClientMessage: { // Custom client message, probably from the window manager window = findWindow(event->xclient.window); if (window == NULL) return; if ((Atom) event->xclient.data.l[0] == _glfwLibrary.X11.wmDeleteWindow) { // The window manager was asked to close the window, for example by // the user pressing a 'close' window decoration button _glfwInputWindowCloseRequest(window); } else if (_glfwLibrary.X11.wmPing != None && (Atom) event->xclient.data.l[0] == _glfwLibrary.X11.wmPing) { // The window manager is pinging the application to ensure it's // still responding to events event->xclient.window = _glfwLibrary.X11.root; XSendEvent(_glfwLibrary.X11.display, event->xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, event); } break; } case MapNotify: { // The window was mapped window = findWindow(event->xmap.window); if (window == NULL) return; _glfwInputWindowVisibility(window, GL_TRUE); _glfwInputWindowIconify(window, GL_FALSE); break; } case UnmapNotify: { // The window was unmapped window = findWindow(event->xmap.window); if (window == NULL) return; _glfwInputWindowVisibility(window, GL_FALSE); _glfwInputWindowIconify(window, GL_TRUE); break; } case FocusIn: { // The window gained focus window = findWindow(event->xfocus.window); if (window == NULL) return; _glfwInputWindowFocus(window, GL_TRUE); if (window->cursorMode == GLFW_CURSOR_CAPTURED) captureCursor(window); break; } case FocusOut: { // The window lost focus window = findWindow(event->xfocus.window); if (window == NULL) return; _glfwInputWindowFocus(window, GL_FALSE); if (window->cursorMode == GLFW_CURSOR_CAPTURED) showCursor(window); break; } case Expose: { // The window's contents was damaged window = findWindow(event->xexpose.window); if (window == NULL) return; _glfwInputWindowDamage(window); break; } case SelectionClear: { // The ownership of the selection was lost free(_glfwLibrary.X11.selection.string); _glfwLibrary.X11.selection.string = NULL; break; } case SelectionNotify: { // The selection conversion status is available XSelectionEvent* request = &event->xselection; if (_glfwReadSelection(request)) _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_SUCCEEDED; else _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_FAILED; break; } case SelectionRequest: { // The contents of the selection was requested XSelectionRequestEvent* request = &event->xselectionrequest; XEvent response; memset(&response, 0, sizeof(response)); response.xselection.property = _glfwWriteSelection(request); response.xselection.type = SelectionNotify; response.xselection.display = request->display; response.xselection.requestor = request->requestor; response.xselection.selection = request->selection; response.xselection.target = request->target; response.xselection.time = request->time; XSendEvent(_glfwLibrary.X11.display, request->requestor, False, 0, &response); break; } case DestroyNotify: return; default: { #if defined(_GLFW_HAS_XRANDR) switch (event->type - _glfwLibrary.X11.RandR.eventBase) { case RRScreenChangeNotify: { XRRUpdateConfiguration(event); break; } } #endif /*_GLFW_HAS_XRANDR*/ break; } } }
// Process the specified X event // static void processEvent(XEvent *event) { _GLFWwindow* window = NULL; if (event->type != GenericEvent) { window = _glfwFindWindowByHandle(event->xany.window); if (window == NULL) { // This is either an event for a destroyed GLFW window or an event // of a type not currently supported by GLFW return; } } switch (event->type) { case KeyPress: { _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_PRESS); if (!(event->xkey.state & ControlMask) && !(event->xkey.state & Mod1Mask /*Alt*/)) { _glfwInputChar(window, translateChar(&event->xkey)); } break; } case KeyRelease: { _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_RELEASE); break; } case ButtonPress: { if (event->xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); else if (event->xbutton.button == Button2) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS); else if (event->xbutton.button == Button3) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS); // Modern X provides scroll events as mouse button presses else if (event->xbutton.button == Button4) _glfwInputScroll(window, 0.0, 1.0); else if (event->xbutton.button == Button5) _glfwInputScroll(window, 0.0, -1.0); else if (event->xbutton.button == Button6) _glfwInputScroll(window, -1.0, 0.0); else if (event->xbutton.button == Button7) _glfwInputScroll(window, 1.0, 0.0); break; } case ButtonRelease: { if (event->xbutton.button == Button1) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE); } else if (event->xbutton.button == Button2) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE); } else if (event->xbutton.button == Button3) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE); } break; } case EnterNotify: { if (window->cursorMode == GLFW_CURSOR_HIDDEN) hideCursor(window); _glfwInputCursorEnter(window, GL_TRUE); break; } case LeaveNotify: { if (window->cursorMode == GLFW_CURSOR_HIDDEN) showCursor(window); _glfwInputCursorEnter(window, GL_FALSE); break; } case MotionNotify: { if (event->xmotion.x != window->x11.cursorPosX || event->xmotion.y != window->x11.cursorPosY) { // The cursor was moved by something other than GLFW int x, y; if (window->cursorMode == GLFW_CURSOR_CAPTURED) { if (_glfw.focusedWindow != window) break; x = event->xmotion.x - window->x11.cursorPosX; y = event->xmotion.y - window->x11.cursorPosY; } else { x = event->xmotion.x; y = event->xmotion.y; } window->x11.cursorPosX = event->xmotion.x; window->x11.cursorPosY = event->xmotion.y; window->x11.cursorCentered = GL_FALSE; _glfwInputCursorMotion(window, x, y); } break; } case ConfigureNotify: { _glfwInputWindowSize(window, event->xconfigure.width, event->xconfigure.height); _glfwInputWindowPos(window, event->xconfigure.x, event->xconfigure.y); break; } case ClientMessage: { // Custom client message, probably from the window manager if ((Atom) event->xclient.data.l[0] == _glfw.x11.WM_DELETE_WINDOW) { // The window manager was asked to close the window, for example by // the user pressing a 'close' window decoration button _glfwInputWindowCloseRequest(window); } else if (_glfw.x11.NET_WM_PING != None && (Atom) event->xclient.data.l[0] == _glfw.x11.NET_WM_PING) { // The window manager is pinging the application to ensure it's // still responding to events event->xclient.window = _glfw.x11.root; XSendEvent(_glfw.x11.display, event->xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, event); } break; } case MapNotify: { _glfwInputWindowVisibility(window, GL_TRUE); break; } case UnmapNotify: { _glfwInputWindowVisibility(window, GL_FALSE); break; } case FocusIn: { _glfwInputWindowFocus(window, GL_TRUE); if (window->cursorMode == GLFW_CURSOR_CAPTURED) captureCursor(window); break; } case FocusOut: { _glfwInputWindowFocus(window, GL_FALSE); if (window->cursorMode == GLFW_CURSOR_CAPTURED) showCursor(window); break; } case Expose: { _glfwInputWindowDamage(window); break; } case PropertyNotify: { if (event->xproperty.atom == _glfw.x11.WM_STATE && event->xproperty.state == PropertyNewValue) { struct { CARD32 state; Window icon; } *state = NULL; if (_glfwGetWindowProperty(window->x11.handle, _glfw.x11.WM_STATE, _glfw.x11.WM_STATE, (unsigned char**) &state) >= 2) { if (state->state == IconicState) _glfwInputWindowIconify(window, GL_TRUE); else if (state->state == NormalState) _glfwInputWindowIconify(window, GL_FALSE); } XFree(state); } break; } case SelectionClear: { // The ownership of the clipboard selection was lost free(_glfw.x11.selection.string); _glfw.x11.selection.string = NULL; break; } case SelectionRequest: { // The contents of the clipboard selection was requested XSelectionRequestEvent* request = &event->xselectionrequest; XEvent response; memset(&response, 0, sizeof(response)); response.xselection.property = _glfwWriteSelection(request); response.xselection.type = SelectionNotify; response.xselection.display = request->display; response.xselection.requestor = request->requestor; response.xselection.selection = request->selection; response.xselection.target = request->target; response.xselection.time = request->time; XSendEvent(_glfw.x11.display, request->requestor, False, 0, &response); break; } case DestroyNotify: return; case GenericEvent: { if (event->xcookie.extension == _glfw.x11.xi2.majorOpcode && XGetEventData(_glfw.x11.display, &event->xcookie)) { if (event->xcookie.evtype == XI_Motion) { XIDeviceEvent* data = (XIDeviceEvent*) event->xcookie.data; window = _glfwFindWindowByHandle(data->event); if (window) { if (data->event_x != window->x11.cursorPosX || data->event_y != window->x11.cursorPosY) { // The cursor was moved by something other than GLFW double x, y; if (window->cursorMode == GLFW_CURSOR_CAPTURED) { if (_glfw.focusedWindow != window) break; x = data->event_x - window->x11.cursorPosX; y = data->event_y - window->x11.cursorPosY; } else { x = data->event_x; y = data->event_y; } window->x11.cursorPosX = data->event_x; window->x11.cursorPosY = data->event_y; window->x11.cursorCentered = GL_FALSE; _glfwInputCursorMotion(window, x, y); } } } } XFreeEventData(_glfw.x11.display, &event->xcookie); break; } default: { switch (event->type - _glfw.x11.randr.eventBase) { case RRScreenChangeNotify: { XRRUpdateConfiguration(event); break; } } break; } } }
int32_t _glfwPlatformProcInputEvent( struct android_app* app, AInputEvent *event ) { // Motion events if ( AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION ) { int action = AKeyEvent_getAction(event); int count = AMotionEvent_getPointerCount(event); switch (action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_DOWN: if(count == 1){ _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); if(_glfwWin.mousePosCallback) _glfwWin.mousePosCallback(_glfwInput.MousePosX, _glfwInput.MousePosY, GLFW_RELEASE, GLFW_RELEASE); _glfwInputMouseClick(GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); } break; case AMOTION_EVENT_ACTION_UP: if(count == 1){ _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); if(_glfwWin.mousePosCallback) _glfwWin.mousePosCallback(_glfwInput.MousePosX, _glfwInput.MousePosY, GLFW_RELEASE, GLFW_RELEASE); _glfwInputMouseClick(GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE); } break; case AMOTION_EVENT_ACTION_MOVE: if(count == 1){ _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); if(_glfwWin.mousePosCallback) _glfwWin.mousePosCallback(_glfwInput.MousePosX, _glfwInput.MousePosY, GLFW_RELEASE, GLFW_RELEASE); }else if(count == 2){ int old_x1 = (int) _glfwInput.MousePosX; int old_y1 = (int) _glfwInput.MousePosY; int old_x2 = (int) _glfwInput.MousePosX2; int old_y2 = (int) _glfwInput.MousePosY2; int new_x1 = (int) AMotionEvent_getX(event, 0); int new_y1 = (int) AMotionEvent_getY(event, 0); int new_x2 = (int) AMotionEvent_getX(event, 1); int new_y2 = (int) AMotionEvent_getY(event, 1); if(old_x1 == new_x1 && old_y1 == new_y1) { } else if(old_x2 == new_x2 && old_y2 == new_y2) { } else { if(abs((new_x2 - new_x1) * (new_y2 - new_y1)) > abs((old_x2 - old_x1) * (old_y2 - old_y1))){ _glfwInput.WheelPos++; }else{ _glfwInput.WheelPos--; } if(_glfwWin.mouseWheelCallback) _glfwWin.mouseWheelCallback(_glfwInput.WheelPos); } } _glfwInput.MousePosX = AMotionEvent_getX(event, 0); _glfwInput.MousePosY = AMotionEvent_getY(event, 0); _glfwInput.MousePosX2 = AMotionEvent_getX(event, 1); _glfwInput.MousePosY2 = AMotionEvent_getY(event, 1); break; } return 1; } return 0; }
OSStatus _glfwMouseEventHandler( EventHandlerCallRef handlerCallRef, EventRef event, void *userData ) { switch( GetEventKind( event ) ) { case kEventMouseDown: { WindowRef window; EventRecord oldStyleMacEvent; ConvertEventRefToEventRecord( event, &oldStyleMacEvent ); if( FindWindow ( oldStyleMacEvent.where, &window ) == inMenuBar ) { MenuSelect( oldStyleMacEvent.where ); HiliteMenu(0); return noErr; } else { EventMouseButton button; if( GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof( EventMouseButton ), NULL, &button ) == noErr ) { button -= kEventMouseButtonPrimary; if( button <= GLFW_MOUSE_BUTTON_LAST ) { _glfwInputMouseClick( button + GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS ); } return noErr; } } break; } case kEventMouseUp: { EventMouseButton button; if( GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof( EventMouseButton ), NULL, &button ) == noErr ) { button -= kEventMouseButtonPrimary; if( button <= GLFW_MOUSE_BUTTON_LAST ) { _glfwInputMouseClick( button + GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE ); } return noErr; } break; } case kEventMouseMoved: case kEventMouseDragged: { HIPoint mouseLocation; if( _glfwWin.MouseLock ) { if( GetEventParameter( event, kEventParamMouseDelta, typeHIPoint, NULL, sizeof( HIPoint ), NULL, &mouseLocation ) != noErr ) { break; } _glfwInput.MousePosX += mouseLocation.x; _glfwInput.MousePosY += mouseLocation.y; } else { if( GetEventParameter( event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof( HIPoint ), NULL, &mouseLocation ) != noErr ) { break; } _glfwInput.MousePosX = mouseLocation.x; _glfwInput.MousePosY = mouseLocation.y; if( !_glfwWin.Fullscreen ) { Rect content; GetWindowBounds( _glfwWin.MacWindow, kWindowContentRgn, &content ); _glfwInput.MousePosX -= content.left; _glfwInput.MousePosY -= content.top; } } if( _glfwWin.MousePosCallback ) { _glfwWin.MousePosCallback( _glfwInput.MousePosX, _glfwInput.MousePosY ); } break; } case kEventMouseWheelMoved: { EventMouseWheelAxis axis; if( GetEventParameter( event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof( EventMouseWheelAxis ), NULL, &axis) == noErr ) { long wheelDelta; if( axis == kEventMouseWheelAxisY && GetEventParameter( event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof( long ), NULL, &wheelDelta ) == noErr ) { _glfwInput.WheelPos += wheelDelta; if( _glfwWin.MouseWheelCallback ) { _glfwWin.MouseWheelCallback( _glfwInput.WheelPos ); } return noErr; } } break; } } return eventNotHandledErr; }
// Process the specified X event // static void processEvent(XEvent *event) { _GLFWwindow* window = NULL; if (event->type != GenericEvent) { window = _glfwFindWindowByHandle(event->xany.window); if (window == NULL) { // This is an event for a window that has already been destroyed return; } } switch (event->type) { case KeyPress: { const int key = translateKey(event->xkey.keycode); const int mods = translateState(event->xkey.state); const int character = translateChar(&event->xkey); _glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods); if (character != -1) _glfwInputChar(window, character); break; } case KeyRelease: { const int key = translateKey(event->xkey.keycode); const int mods = translateState(event->xkey.state); _glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods); break; } case ButtonPress: { const int mods = translateState(event->xbutton.state); if (event->xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); else if (event->xbutton.button == Button2) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods); else if (event->xbutton.button == Button3) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods); // Modern X provides scroll events as mouse button presses else if (event->xbutton.button == Button4) _glfwInputScroll(window, 0.0, 1.0); else if (event->xbutton.button == Button5) _glfwInputScroll(window, 0.0, -1.0); else if (event->xbutton.button == Button6) _glfwInputScroll(window, -1.0, 0.0); else if (event->xbutton.button == Button7) _glfwInputScroll(window, 1.0, 0.0); else { // Additional buttons after 7 are treated as regular buttons // We subtract 4 to fill the gap left by scroll input above _glfwInputMouseClick(window, event->xbutton.button - 4, GLFW_PRESS, mods); } break; } case ButtonRelease: { const int mods = translateState(event->xbutton.state); if (event->xbutton.button == Button1) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods); } else if (event->xbutton.button == Button2) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods); } else if (event->xbutton.button == Button3) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods); } else if (event->xbutton.button > Button7) { // Additional buttons after 7 are treated as regular buttons // We subtract 4 to fill the gap left by scroll input above _glfwInputMouseClick(window, event->xbutton.button - 4, GLFW_RELEASE, mods); } break; } case EnterNotify: { _glfwInputCursorEnter(window, GL_TRUE); break; } case LeaveNotify: { _glfwInputCursorEnter(window, GL_FALSE); break; } case MotionNotify: { if (event->xmotion.x != window->x11.warpPosX || event->xmotion.y != window->x11.warpPosY) { // The cursor was moved by something other than GLFW int x, y; if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (_glfw.focusedWindow != window) break; x = event->xmotion.x - window->x11.cursorPosX; y = event->xmotion.y - window->x11.cursorPosY; } else { x = event->xmotion.x; y = event->xmotion.y; } _glfwInputCursorMotion(window, x, y); } window->x11.cursorPosX = event->xmotion.x; window->x11.cursorPosY = event->xmotion.y; break; } case ConfigureNotify: { if (event->xconfigure.width != window->x11.width || event->xconfigure.height != window->x11.height) { _glfwInputFramebufferSize(window, event->xconfigure.width, event->xconfigure.height); _glfwInputWindowSize(window, event->xconfigure.width, event->xconfigure.height); window->x11.width = event->xconfigure.width; window->x11.height = event->xconfigure.height; } if (event->xconfigure.x != window->x11.xpos || event->xconfigure.y != window->x11.ypos) { _glfwInputWindowPos(window, event->xconfigure.x, event->xconfigure.y); window->x11.xpos = event->xconfigure.x; window->x11.ypos = event->xconfigure.y; } break; } case ClientMessage: { // Custom client message, probably from the window manager if ((Atom) event->xclient.data.l[0] == _glfw.x11.WM_DELETE_WINDOW) { // The window manager was asked to close the window, for example by // the user pressing a 'close' window decoration button _glfwInputWindowCloseRequest(window); } else if (_glfw.x11.NET_WM_PING && (Atom) event->xclient.data.l[0] == _glfw.x11.NET_WM_PING) { // The window manager is pinging the application to ensure it's // still responding to events event->xclient.window = _glfw.x11.root; XSendEvent(_glfw.x11.display, event->xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, event); } else if (event->xclient.message_type == _glfw.x11.XdndEnter) { // A drag operation has entered the window // TODO: Check if UTF-8 string is supported by the source } else if (event->xclient.message_type == _glfw.x11.XdndDrop) { // The drag operation has finished dropping on // the window, ask to convert it to a UTF-8 string _glfw.x11.xdnd.source = event->xclient.data.l[0]; XConvertSelection(_glfw.x11.display, _glfw.x11.XdndSelection, _glfw.x11.UTF8_STRING, _glfw.x11.XdndSelection, window->x11.handle, CurrentTime); } else if (event->xclient.message_type == _glfw.x11.XdndPosition) { // The drag operation has moved over the window const int absX = (event->xclient.data.l[2] >> 16) & 0xFFFF; const int absY = (event->xclient.data.l[2]) & 0xFFFF; int x, y; _glfwPlatformGetWindowPos(window, &x, &y); _glfwInputCursorMotion(window, absX - x, absY - y); // Reply that we are ready to copy the dragged data XEvent reply; memset(&reply, 0, sizeof(reply)); reply.type = ClientMessage; reply.xclient.window = event->xclient.data.l[0]; reply.xclient.message_type = _glfw.x11.XdndStatus; reply.xclient.format = 32; reply.xclient.data.l[0] = window->x11.handle; reply.xclient.data.l[1] = 1; // Always accept the dnd with no rectangle reply.xclient.data.l[2] = 0; // Specify an empty rectangle reply.xclient.data.l[3] = 0; reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy; XSendEvent(_glfw.x11.display, event->xclient.data.l[0], False, NoEventMask, &reply); XFlush(_glfw.x11.display); } break; } case SelectionNotify: { if (event->xselection.property) { // The converted data from the drag operation has arrived char* data; const int result = _glfwGetWindowProperty(event->xselection.requestor, event->xselection.property, event->xselection.target, (unsigned char**) &data); if (result) { int i, count; char** names = splitUriList(data, &count); _glfwInputDrop(window, count, (const char**) names); for (i = 0; i < count; i++) free(names[i]); free(names); } XFree(data); XEvent reply; memset(&reply, 0, sizeof(reply)); reply.type = ClientMessage; reply.xclient.window = _glfw.x11.xdnd.source; reply.xclient.message_type = _glfw.x11.XdndFinished; reply.xclient.format = 32; reply.xclient.data.l[0] = window->x11.handle; reply.xclient.data.l[1] = result; reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy; // Reply that all is well XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source, False, NoEventMask, &reply); XFlush(_glfw.x11.display); } break; } case MapNotify: { _glfwInputWindowVisibility(window, GL_TRUE); break; } case UnmapNotify: { _glfwInputWindowVisibility(window, GL_FALSE); break; } case FocusIn: { _glfwInputWindowFocus(window, GL_TRUE); if (window->cursorMode == GLFW_CURSOR_DISABLED) disableCursor(window); break; } case FocusOut: { _glfwInputWindowFocus(window, GL_FALSE); if (window->cursorMode == GLFW_CURSOR_DISABLED) restoreCursor(window); break; } case Expose: { _glfwInputWindowDamage(window); break; } case PropertyNotify: { if (event->xproperty.atom == _glfw.x11.WM_STATE && event->xproperty.state == PropertyNewValue) { struct { CARD32 state; Window icon; } *state = NULL; if (_glfwGetWindowProperty(window->x11.handle, _glfw.x11.WM_STATE, _glfw.x11.WM_STATE, (unsigned char**) &state) >= 2) { if (state->state == IconicState) _glfwInputWindowIconify(window, GL_TRUE); else if (state->state == NormalState) _glfwInputWindowIconify(window, GL_FALSE); } XFree(state); } break; } case SelectionClear: { _glfwHandleSelectionClear(event); break; } case SelectionRequest: { _glfwHandleSelectionRequest(event); break; } case DestroyNotify: return; case GenericEvent: { if (event->xcookie.extension == _glfw.x11.xi.majorOpcode && XGetEventData(_glfw.x11.display, &event->xcookie)) { if (event->xcookie.evtype == XI_Motion) { XIDeviceEvent* data = (XIDeviceEvent*) event->xcookie.data; window = _glfwFindWindowByHandle(data->event); if (window) { if (data->event_x != window->x11.warpPosX || data->event_y != window->x11.warpPosY) { // The cursor was moved by something other than GLFW double x, y; if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (_glfw.focusedWindow != window) break; x = data->event_x - window->x11.cursorPosX; y = data->event_y - window->x11.cursorPosY; } else { x = data->event_x; y = data->event_y; } _glfwInputCursorMotion(window, x, y); } window->x11.cursorPosX = data->event_x; window->x11.cursorPosY = data->event_y; } } } XFreeEventData(_glfw.x11.display, &event->xcookie); break; } default: { switch (event->type - _glfw.x11.randr.eventBase) { case RRScreenChangeNotify: { XRRUpdateConfiguration(event); break; } } break; } } }
// Process the specified X event // static void processEvent(XEvent *event) { _GLFWwindow* window = NULL; if (event->type != GenericEvent) { window = _glfwFindWindowByHandle(event->xany.window); if (window == NULL) { // This is an event for a window that has already been destroyed return; } } switch (event->type) { case KeyPress: { const int key = translateKey(event->xkey.keycode); const int mods = translateState(event->xkey.state); const int character = translateChar(&event->xkey); _glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods); if (character != -1) _glfwInputChar(window, character); break; } case KeyRelease: { const int key = translateKey(event->xkey.keycode); const int mods = translateState(event->xkey.state); _glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods); break; } case ButtonPress: { const int mods = translateState(event->xbutton.state); if (event->xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods); else if (event->xbutton.button == Button2) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods); else if (event->xbutton.button == Button3) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods); // Modern X provides scroll events as mouse button presses else if (event->xbutton.button == Button4) _glfwInputScroll(window, 0.0, 1.0); else if (event->xbutton.button == Button5) _glfwInputScroll(window, 0.0, -1.0); else if (event->xbutton.button == Button6) _glfwInputScroll(window, -1.0, 0.0); else if (event->xbutton.button == Button7) _glfwInputScroll(window, 1.0, 0.0); break; } case ButtonRelease: { const int mods = translateState(event->xbutton.state); if (event->xbutton.button == Button1) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods); } else if (event->xbutton.button == Button2) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods); } else if (event->xbutton.button == Button3) { _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods); } break; } case EnterNotify: { if (window->cursorMode == GLFW_CURSOR_HIDDEN) hideCursor(window); _glfwInputCursorEnter(window, GL_TRUE); break; } case LeaveNotify: { if (window->cursorMode == GLFW_CURSOR_HIDDEN) showCursor(window); _glfwInputCursorEnter(window, GL_FALSE); break; } case MotionNotify: { if (event->xmotion.x != window->x11.warpPosX || event->xmotion.y != window->x11.warpPosY) { // The cursor was moved by something other than GLFW int x, y; if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (_glfw.focusedWindow != window) break; x = event->xmotion.x - window->x11.cursorPosX; y = event->xmotion.y - window->x11.cursorPosY; } else { x = event->xmotion.x; y = event->xmotion.y; } _glfwInputCursorMotion(window, x, y); } window->x11.cursorPosX = event->xmotion.x; window->x11.cursorPosY = event->xmotion.y; break; } case ConfigureNotify: { if (event->xconfigure.width != window->x11.width || event->xconfigure.height != window->x11.height) { _glfwInputFramebufferSize(window, event->xconfigure.width, event->xconfigure.height); _glfwInputWindowSize(window, event->xconfigure.width, event->xconfigure.height); window->x11.width = event->xconfigure.width; window->x11.height = event->xconfigure.height; } if (event->xconfigure.x != window->x11.xpos || event->xconfigure.y != window->x11.ypos) { _glfwInputWindowPos(window, event->xconfigure.x, event->xconfigure.y); window->x11.xpos = event->xconfigure.x; window->x11.ypos = event->xconfigure.y; } break; } case ClientMessage: { // Custom client message, probably from the window manager if ((Atom) event->xclient.data.l[0] == _glfw.x11.WM_DELETE_WINDOW) { // The window manager was asked to close the window, for example by // the user pressing a 'close' window decoration button _glfwInputWindowCloseRequest(window); } else if (_glfw.x11.NET_WM_PING != None && (Atom) event->xclient.data.l[0] == _glfw.x11.NET_WM_PING) { // The window manager is pinging the application to ensure it's // still responding to events event->xclient.window = _glfw.x11.root; XSendEvent(_glfw.x11.display, event->xclient.window, False, SubstructureNotifyMask | SubstructureRedirectMask, event); } break; } case MapNotify: { _glfwInputWindowVisibility(window, GL_TRUE); break; } case UnmapNotify: { _glfwInputWindowVisibility(window, GL_FALSE); break; } case FocusIn: { _glfwInputWindowFocus(window, GL_TRUE); if (window->cursorMode == GLFW_CURSOR_DISABLED) captureCursor(window); break; } case FocusOut: { _glfwInputWindowFocus(window, GL_FALSE); if (window->cursorMode == GLFW_CURSOR_DISABLED) showCursor(window); break; } case Expose: { _glfwInputWindowDamage(window); break; } case PropertyNotify: { if (event->xproperty.atom == _glfw.x11.WM_STATE && event->xproperty.state == PropertyNewValue) { struct { CARD32 state; Window icon; } *state = NULL; if (_glfwGetWindowProperty(window->x11.handle, _glfw.x11.WM_STATE, _glfw.x11.WM_STATE, (unsigned char**) &state) >= 2) { if (state->state == IconicState) _glfwInputWindowIconify(window, GL_TRUE); else if (state->state == NormalState) _glfwInputWindowIconify(window, GL_FALSE); } XFree(state); } break; } case SelectionClear: { _glfwHandleSelectionClear(event); break; } case SelectionRequest: { _glfwHandleSelectionRequest(event); break; } case DestroyNotify: return; case GenericEvent: { if (event->xcookie.extension == _glfw.x11.xi.majorOpcode && XGetEventData(_glfw.x11.display, &event->xcookie)) { /* if (event->xcookie.evtype == XI_Motion) { XIDeviceEvent* data = (XIDeviceEvent*) event->xcookie.data; window = _glfwFindWindowByHandle(data->event); if (window) { if (data->event_x != window->x11.warpPosX || data->event_y != window->x11.warpPosY) { // The cursor was moved by something other than GLFW double x, y; if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (_glfw.focusedWindow != window) break; x = data->event_x - window->x11.cursorPosX; y = data->event_y - window->x11.cursorPosY; } else { x = data->event_x; y = data->event_y; } _glfwInputCursorMotion(window, x, y); } window->x11.cursorPosX = data->event_x; window->x11.cursorPosY = data->event_y; } }*/ } XFreeEventData(_glfw.x11.display, &event->xcookie); break; } default: { /* switch (event->type - _glfw.x11.randr.eventBase) { case RRScreenChangeNotify: { XRRUpdateConfiguration(event); break; } } */ break; } } }
static void pointerHandleButton(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { _GLFWwindow* window = _glfw.wl.pointerFocus; int glfwButton; // Both xdg-shell and wl_shell use the same values. uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE; if (!window) return; if (button == BTN_LEFT) { switch (window->wl.decorations.focus) { case mainWindow: break; case topDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) edges = WL_SHELL_SURFACE_RESIZE_TOP; else { if (window->wl.xdg.toplevel) xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); else wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial); } break; case leftDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT; else edges = WL_SHELL_SURFACE_RESIZE_LEFT; break; case rightDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT; else edges = WL_SHELL_SURFACE_RESIZE_RIGHT; break; case bottomDecoration: if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH) edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT; else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH) edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT; else edges = WL_SHELL_SURFACE_RESIZE_BOTTOM; break; default: assert(0); } if (edges != WL_SHELL_SURFACE_RESIZE_NONE) { if (window->wl.xdg.toplevel) xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges); else wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat, serial, edges); } } else if (button == BTN_RIGHT) { if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel) { xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, _glfw.wl.seat, serial, window->wl.cursorPosX, window->wl.cursorPosY); return; } } // Don’t pass the button to the user if it was related to a decoration. if (window->wl.decorations.focus != mainWindow) return; _glfw.wl.pointerSerial = serial; /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev * codes. */ glfwButton = button - BTN_LEFT; _glfwInputMouseClick(window, glfwButton, state == WL_POINTER_BUTTON_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE, _glfw.wl.xkb.modifiers); }
// Window callback function (handles window messages) // static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { _GLFWwindow* window = (_GLFWwindow*) GetWindowLongPtrW(hWnd, 0); if (!window) { switch (uMsg) { case WM_NCCREATE: { CREATESTRUCTW* cs = (CREATESTRUCTW*) lParam; SetWindowLongPtrW(hWnd, 0, (LONG_PTR) cs->lpCreateParams); break; } case WM_DEVICECHANGE: { if (wParam == DBT_DEVNODES_CHANGED) { _glfwInputMonitorChange(); return TRUE; } break; } } return DefWindowProcW(hWnd, uMsg, wParam, lParam); } switch (uMsg) { case WM_SETFOCUS: { if (window->cursorMode == GLFW_CURSOR_DISABLED) _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED); _glfwInputWindowFocus(window, GLFW_TRUE); return 0; } case WM_KILLFOCUS: { if (window->cursorMode == GLFW_CURSOR_DISABLED) _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL); if (window->monitor && window->autoIconify) _glfwPlatformIconifyWindow(window); _glfwInputWindowFocus(window, GLFW_FALSE); return 0; } case WM_SYSCOMMAND: { switch (wParam & 0xfff0) { case SC_SCREENSAVE: case SC_MONITORPOWER: { if (window->monitor) { // We are running in full screen mode, so disallow // screen saver and screen blanking return 0; } else break; } // User trying to access application menu using ALT? case SC_KEYMENU: return 0; } break; } case WM_CLOSE: { _glfwInputWindowCloseRequest(window); return 0; } case WM_CHAR: case WM_SYSCHAR: case WM_UNICHAR: { const GLFWbool plain = (uMsg != WM_SYSCHAR); if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) { // WM_UNICHAR is not sent by Windows, but is sent by some // third-party input method engine // Returning TRUE here announces support for this message return TRUE; } _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain); return 0; } case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: { const int key = translateKey(wParam, lParam); const int scancode = (lParam >> 16) & 0x1ff; const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS; const int mods = getKeyMods(); if (key == _GLFW_KEY_INVALID) break; if (action == GLFW_RELEASE && wParam == VK_SHIFT) { // Release both Shift keys on Shift up event, as only one event // is sent even if both keys are released _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods); _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods); } else if (wParam == VK_SNAPSHOT) { // Key down is not reported for the Print Screen key _glfwInputKey(window, key, scancode, GLFW_PRESS, mods); _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods); } else _glfwInputKey(window, key, scancode, action, mods); break; } case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: { int button, action; 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; if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN) { action = GLFW_PRESS; SetCapture(hWnd); } else { action = GLFW_RELEASE; ReleaseCapture(); } _glfwInputMouseClick(window, button, action, getKeyMods()); if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP) return TRUE; return 0; } case WM_MOUSEMOVE: { const int x = GET_X_LPARAM(lParam); const int y = GET_Y_LPARAM(lParam); if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (_glfw.cursorWindow != window) break; _glfwInputCursorMotion(window, x - window->win32.cursorPosX, y - window->win32.cursorPosY); } else _glfwInputCursorMotion(window, x, y); window->win32.cursorPosX = x; window->win32.cursorPosY = y; 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); } return 0; } case WM_MOUSELEAVE: { window->win32.cursorTracked = GLFW_FALSE; _glfwInputCursorEnter(window, GLFW_FALSE); return 0; } case WM_MOUSEWHEEL: { _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA); return 0; } case WM_MOUSEHWHEEL: { // This message is only sent on Windows Vista and later // NOTE: The X-axis is inverted for consistency with OS X and X11. _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0); return 0; } case WM_SIZE: { if (_glfw.cursorWindow == window) { if (window->cursorMode == GLFW_CURSOR_DISABLED) updateClipRect(window); } if (!window->win32.iconified && wParam == SIZE_MINIMIZED) { window->win32.iconified = GLFW_TRUE; if (window->monitor) leaveFullscreenMode(window); _glfwInputWindowIconify(window, GLFW_TRUE); } else if (window->win32.iconified && (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)) { window->win32.iconified = GLFW_FALSE; if (window->monitor) enterFullscreenMode(window); _glfwInputWindowIconify(window, GLFW_FALSE); } _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam)); _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam)); return 0; } case WM_MOVE: { if (_glfw.cursorWindow == window) { if (window->cursorMode == GLFW_CURSOR_DISABLED) updateClipRect(window); } // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as // those macros do not handle negative window positions correctly _glfwInputWindowPos(window, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); return 0; } case WM_SIZING: { if (window->win32.numer == GLFW_DONT_CARE || window->win32.denom == GLFW_DONT_CARE) { break; } applyAspectRatio(window, (int) wParam, (RECT*) lParam); return TRUE; } case WM_GETMINMAXINFO: { int xoff, yoff; MINMAXINFO* mmi = (MINMAXINFO*) lParam; getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), 0, 0, &xoff, &yoff); if (window->win32.minwidth != GLFW_DONT_CARE && window->win32.minheight != GLFW_DONT_CARE) { mmi->ptMinTrackSize.x = window->win32.minwidth + xoff; mmi->ptMinTrackSize.y = window->win32.minheight + yoff; } if (window->win32.maxwidth != GLFW_DONT_CARE && window->win32.maxheight != GLFW_DONT_CARE) { mmi->ptMaxTrackSize.x = window->win32.maxwidth + xoff; mmi->ptMaxTrackSize.y = window->win32.maxheight + yoff; } return 0; } case WM_PAINT: { _glfwInputWindowDamage(window); break; } case WM_ERASEBKGND: { return TRUE; } case WM_SETCURSOR: { if (_glfw.cursorWindow == window && LOWORD(lParam) == HTCLIENT) { if (window->cursorMode == GLFW_CURSOR_HIDDEN || window->cursorMode == GLFW_CURSOR_DISABLED) { SetCursor(NULL); return TRUE; } else if (window->cursor) { SetCursor(window->cursor->win32.handle); return TRUE; } } break; } case WM_DPICHANGED: { RECT* rect = (RECT*) lParam; SetWindowPos(window->win32.handle, HWND_TOP, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, SWP_NOACTIVATE | SWP_NOZORDER); break; } case WM_DROPFILES: { HDROP drop = (HDROP) wParam; POINT pt; int i; const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0); char** paths = calloc(count, sizeof(char*)); // Move the mouse to the position of the drop DragQueryPoint(drop, &pt); _glfwInputCursorMotion(window, pt.x, pt.y); for (i = 0; i < count; i++) { const UINT length = DragQueryFileW(drop, i, NULL, 0); WCHAR* buffer = calloc(length + 1, sizeof(WCHAR)); DragQueryFileW(drop, i, buffer, length + 1); paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer); free(buffer); } _glfwInputDrop(window, count, (const char**) paths); for (i = 0; i < count; i++) free(paths[i]); free(paths); DragFinish(drop); return 0; } } return DefWindowProcW(hWnd, uMsg, wParam, lParam); }