Mercurial > sdl-ios-xcode
view src/video/win32/SDL_win32events.c @ 1722:5daa04d862f1 SDL-1.3
Added a userdata parameter for event filters.
Added a function to filter the existing queued events.
Added explicit support for relative mouse mode to the API.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 30 Jun 2006 08:18:44 +0000 |
parents | 5b9f50c957ed |
children | 6c63fc2bd986 |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" #include "SDL_win32video.h" #include "../../events/SDL_events_c.h" LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { SDL_WindowData *data; /* Get the window data for the window */ data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData")); if (!data) { return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam); } #if 0 switch (msg) { case WM_ACTIVATE: { BOOL minimized; minimized = HIWORD(wParam); if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) { SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0); SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0, 0); if (IsZoomed(hwnd)) { SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_MAXIMIZED, 0, 0); } SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0); /* FIXME: Restore mode state (mode, gamma, grab) */ /* FIXME: Update keyboard state */ } else { SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0); if (minimized) { SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, 0); } /* FIXME: Restore desktop state (mode, gamma, grab) */ } return (0); } break; case WM_MOUSEMOVE: { int index; SDL_Mouse *mouse; if (! (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_MOUSE_FOCUS)) { /* mouse has entered the window */ TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hwnd; TrackMouseEvent(&tme); SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_ENTER, 0, 0); } index = data->videodata->mouse; mouse = SDL_GetMouse(index); if (mouse) { int x, y; /* mouse has moved within the window */ x = LOWORD(lParam); y = HIWORD(lParam); if (mouse->relative_mode) { int w, h; POINT center; SDL_GetWindowSize(data->windowID, &w, &h); center.x = (w / 2); center.y = (h / 2); x -= center.x; y -= center.y; if (x || y) { ClientToScreen(SDL_Window, ¢er); SetCursorPos(center.x, center.y); SDL_SendMouseMotion(index, data->windowID, 1, x, y); } } else { SDL_SendMouseMotion(index, data->windowID, 0, x, y); } } } return (0); case WM_MOUSELEAVE: { SDL_PrivateWindowEvent(data->windowID, SDL_WINDOWEVENT_LEAVE, 0, 0); } return (0); case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: { int x, y; Uint8 button, state; /* DJM: We want the SDL window to take focus so that it acts like a normal windows "component" (e.g. gains keyboard focus on a mouse click). */ SetFocus(SDL_Window); /* Figure out which button to use */ switch (msg) { case WM_LBUTTONDOWN: button = SDL_BUTTON_LEFT; state = SDL_PRESSED; break; case WM_LBUTTONUP: button = SDL_BUTTON_LEFT; state = SDL_RELEASED; break; case WM_MBUTTONDOWN: button = SDL_BUTTON_MIDDLE; state = SDL_PRESSED; break; case WM_MBUTTONUP: button = SDL_BUTTON_MIDDLE; state = SDL_RELEASED; break; case WM_RBUTTONDOWN: button = SDL_BUTTON_RIGHT; state = SDL_PRESSED; break; case WM_RBUTTONUP: button = SDL_BUTTON_RIGHT; state = SDL_RELEASED; break; default: /* Eh? Unknown button? */ return (0); } if (state == SDL_PRESSED) { /* Grab mouse so we get up events */ if (++mouse_pressed > 0) { SetCapture(hwnd); } } else { /* Release mouse after all up events */ if (--mouse_pressed <= 0) { ReleaseCapture(); mouse_pressed = 0; } } x = LOWORD(lParam); y = HIWORD(lParam); #ifdef _WIN32_WCE if (SDL_VideoSurface) GapiTransform(this->hidden->userOrientation, this->hidden->hiresFix, &x, &y); #endif posted = SDL_PrivateMouseButton(state, button, x, y); } return (0); #if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400) case WM_MOUSEWHEEL: if (SDL_VideoSurface && !DINPUT_FULLSCREEN()) { int move = (short) HIWORD(wParam); if (move) { Uint8 button; if (move > 0) button = SDL_BUTTON_WHEELUP; else button = SDL_BUTTON_WHEELDOWN; posted = SDL_PrivateMouseButton(SDL_PRESSED, button, 0, 0); posted |= SDL_PrivateMouseButton(SDL_RELEASED, button, 0, 0); } } return (0); #endif #ifdef WM_GETMINMAXINFO /* This message is sent as a way for us to "check" the values * of a position change. If we don't like it, we can adjust * the values before they are changed. */ case WM_GETMINMAXINFO: { MINMAXINFO *info; RECT size; int x, y; int style; int width; int height; /* We don't want to clobber an internal resize */ if (SDL_resizing) return (0); /* We allow resizing with the SDL_RESIZABLE flag */ if (SDL_PublicSurface && (SDL_PublicSurface->flags & SDL_RESIZABLE)) { return (0); } /* Get the current position of our window */ GetWindowRect(SDL_Window, &size); x = size.left; y = size.top; /* Calculate current width and height of our window */ size.top = 0; size.left = 0; if (SDL_PublicSurface != NULL) { size.bottom = SDL_PublicSurface->h; size.right = SDL_PublicSurface->w; } else { size.bottom = 0; size.right = 0; } /* DJM - according to the docs for GetMenu(), the return value is undefined if hwnd is a child window. Aparently it's too difficult for MS to check inside their function, so I have to do it here. */ style = GetWindowLong(hwnd, GWL_STYLE); AdjustWindowRect(&size, style, style & WS_CHILDWINDOW ? FALSE : GetMenu(hwnd) != NULL); width = size.right - size.left; height = size.bottom - size.top; /* Fix our size to the current size */ info = (MINMAXINFO *) lParam; info->ptMaxSize.x = width; info->ptMaxSize.y = height; info->ptMaxPosition.x = x; info->ptMaxPosition.y = y; info->ptMinTrackSize.x = width; info->ptMinTrackSize.y = height; info->ptMaxTrackSize.x = width; info->ptMaxTrackSize.y = height; } return (0); #endif /* WM_GETMINMAXINFO */ case WM_WINDOWPOSCHANGED: { SDL_VideoDevice *this = current_video; int w, h; GetClientRect(SDL_Window, &SDL_bounds); ClientToScreen(SDL_Window, (LPPOINT) & SDL_bounds); ClientToScreen(SDL_Window, (LPPOINT) & SDL_bounds + 1); if (!SDL_resizing && !IsZoomed(SDL_Window) && SDL_PublicSurface && !(SDL_PublicSurface->flags & SDL_FULLSCREEN)) { SDL_windowX = SDL_bounds.left; SDL_windowY = SDL_bounds.top; } w = SDL_bounds.right - SDL_bounds.left; h = SDL_bounds.bottom - SDL_bounds.top; if (this->input_grab != SDL_GRAB_OFF) { ClipCursor(&SDL_bounds); } if (SDL_PublicSurface && (SDL_PublicSurface->flags & SDL_RESIZABLE)) { SDL_PrivateResize(w, h); } } break; /* We need to set the cursor */ case WM_SETCURSOR: { Uint16 hittest; hittest = LOWORD(lParam); if (hittest == HTCLIENT) { SetCursor(SDL_hcursor); return (TRUE); } } break; /* We are about to get palette focus! */ case WM_QUERYNEWPALETTE: { WIN_RealizePalette(current_video); return (TRUE); } break; /* Another application changed the palette */ case WM_PALETTECHANGED: { WIN_PaletteChanged(current_video, (HWND) wParam); } break; /* We were occluded, refresh our display */ case WM_PAINT: { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(SDL_Window, &ps); if (current_video->screen && !(current_video->screen->flags & SDL_INTERNALOPENGL)) { WIN_WinPAINT(current_video, hdc); } EndPaint(SDL_Window, &ps); } return (0); /* DJM: Send an expose event in this case */ case WM_ERASEBKGND: { posted = SDL_PrivateExpose(); } return (0); case WM_CLOSE: { if ((posted = SDL_PrivateQuit())) PostQuitMessage(0); } return (0); case WM_DESTROY: { PostQuitMessage(0); } return (0); } #endif return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam); } void WIN_PumpEvents(_THIS) { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } static int app_registered = 0; LPTSTR SDL_Appname = NULL; Uint32 SDL_Appstyle = 0; HINSTANCE SDL_Instance = NULL; /* Register the class for this application */ int SDL_RegisterApp(char *name, Uint32 style, void *hInst) { WNDCLASS class; /* Only do this once... */ if (app_registered) { ++app_registered; return (0); } if (!name && !SDL_Appname) { name = "SDL_app"; SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC); SDL_Instance = hInst ? hInst : GetModuleHandle(NULL); } if (name) { SDL_Appname = WIN_UTF8ToString(name); SDL_Appstyle = style; SDL_Instance = hInst ? hInst : GetModuleHandle(NULL); } /* Register the application class */ class.hCursor = NULL; class.hIcon = LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); class.lpszMenuName = NULL; class.lpszClassName = SDL_Appname; class.hbrBackground = NULL; class.hInstance = SDL_Instance; class.style = SDL_Appstyle; class.lpfnWndProc = DefWindowProc; class.cbWndExtra = 0; class.cbClsExtra = 0; if (!RegisterClass(&class)) { SDL_SetError("Couldn't register application class"); return (-1); } app_registered = 1; return (0); } /* Unregisters the windowclass registered in SDL_RegisterApp above. */ void SDL_UnregisterApp() { WNDCLASS class; /* SDL_RegisterApp might not have been called before */ if (!app_registered) { return; } --app_registered; if (app_registered == 0) { /* Check for any registered window classes. */ if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) { UnregisterClass(SDL_Appname, SDL_Instance); } SDL_free(SDL_Appname); SDL_Appname = NULL; } } /* Sets an error message based on GetLastError() */ void WIN_SetError(const char *prefix) { TCHAR buffer[1024]; char *message; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, buffer, SDL_arraysize(buffer), NULL); message = WIN_StringToUTF8(buffer); SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ":" : "", message); SDL_free(message); } /* vi: set ts=4 sw=4 expandtab: */