2006-07-10 21:04:37 +00:00
|
|
|
/*
|
|
|
|
SDL - Simple DirectMedia Layer
|
2008-12-08 00:27:32 +00:00
|
|
|
Copyright (C) 1997-2009 Sam Lantinga
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
2008-08-25 06:33:00 +00:00
|
|
|
|
|
|
|
#if (_WIN32_WINNT < 0x0501)
|
|
|
|
#undef _WIN32_WINNT
|
|
|
|
#define _WIN32_WINNT 0x0501
|
|
|
|
#endif
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
#include "SDL_config.h"
|
|
|
|
|
|
|
|
#include "SDL_win32video.h"
|
|
|
|
#include "SDL_syswm.h"
|
|
|
|
#include "SDL_vkeys.h"
|
|
|
|
#include "../../events/SDL_events_c.h"
|
|
|
|
|
|
|
|
/*#define WMMSG_DEBUG*/
|
|
|
|
#ifdef WMMSG_DEBUG
|
2006-07-17 06:47:33 +00:00
|
|
|
#include <stdio.h>
|
2006-07-10 21:04:37 +00:00
|
|
|
#include "wmmsg.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Masks for processing the windows KEYDOWN and KEYUP messages */
|
2008-02-11 21:06:32 +00:00
|
|
|
#define REPEATED_KEYMASK (1<<30)
|
|
|
|
#define EXTENDED_KEYMASK (1<<24)
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2008-03-07 17:20:37 +00:00
|
|
|
#define VK_ENTER 10 /* Keypad Enter ... no VKEY defined? */
|
2008-02-10 05:34:33 +00:00
|
|
|
|
2007-06-16 05:29:28 +00:00
|
|
|
/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
|
|
|
|
#ifndef WM_XBUTTONDOWN
|
|
|
|
#define WM_XBUTTONDOWN 0x020B
|
|
|
|
#endif
|
|
|
|
#ifndef WM_XBUTTONUP
|
|
|
|
#define WM_XBUTTONUP 0x020C
|
|
|
|
#endif
|
|
|
|
#ifndef GET_XBUTTON_WPARAM
|
|
|
|
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
|
|
|
|
#endif
|
2008-08-26 11:50:37 +00:00
|
|
|
#ifndef WM_INPUT
|
|
|
|
#define WM_INPUT 0x00ff
|
|
|
|
#endif
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2008-08-25 06:33:00 +00:00
|
|
|
extern HCTX *g_hCtx;
|
|
|
|
extern HANDLE *mice;
|
|
|
|
extern int total_mice;
|
|
|
|
extern int tablet;
|
|
|
|
int pressure = 0; /* the pressure reported by the tablet */
|
|
|
|
|
2008-02-09 07:18:38 +00:00
|
|
|
static WPARAM
|
|
|
|
RemapVKEY(WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2008-02-11 21:06:32 +00:00
|
|
|
int i;
|
2008-03-07 17:20:37 +00:00
|
|
|
BYTE scancode = (BYTE) ((lParam >> 16) & 0xFF);
|
2008-02-11 21:06:32 +00:00
|
|
|
|
2008-02-09 07:18:38 +00:00
|
|
|
/* Windows remaps alphabetic keys based on current layout.
|
|
|
|
We try to provide USB scancodes, so undo this mapping.
|
|
|
|
*/
|
|
|
|
if (wParam >= 'A' && wParam <= 'Z') {
|
2008-02-09 22:28:27 +00:00
|
|
|
if (scancode != alpha_scancodes[wParam - 'A']) {
|
|
|
|
for (i = 0; i < SDL_arraysize(alpha_scancodes); ++i) {
|
|
|
|
if (scancode == alpha_scancodes[i]) {
|
2008-02-09 07:18:38 +00:00
|
|
|
wParam = 'A' + i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-11 21:06:32 +00:00
|
|
|
|
|
|
|
/* Keypad keys are a little trickier, we always scan for them. */
|
|
|
|
for (i = 0; i < SDL_arraysize(keypad_scancodes); ++i) {
|
|
|
|
if (scancode == keypad_scancodes[i]) {
|
2008-03-07 17:20:37 +00:00
|
|
|
wParam = VK_NUMPAD0 + i;
|
2008-02-11 21:06:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-09 07:18:38 +00:00
|
|
|
return wParam;
|
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
LRESULT CALLBACK
|
|
|
|
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
SDL_WindowData *data;
|
2008-08-25 06:33:00 +00:00
|
|
|
RAWINPUT *raw;
|
|
|
|
PACKET packet;
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2006-07-27 06:53:23 +00:00
|
|
|
/* Send a SDL_SYSWMEVENT if the application wants them */
|
|
|
|
if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) {
|
|
|
|
SDL_SysWMmsg wmmsg;
|
|
|
|
|
|
|
|
SDL_VERSION(&wmmsg.version);
|
|
|
|
wmmsg.hwnd = hwnd;
|
|
|
|
wmmsg.msg = msg;
|
|
|
|
wmmsg.wParam = wParam;
|
|
|
|
wmmsg.lParam = lParam;
|
|
|
|
SDL_SendSysWMEvent(&wmmsg);
|
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* Get the window data for the window */
|
|
|
|
data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
|
|
|
|
if (!data) {
|
|
|
|
return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
|
|
|
|
}
|
|
|
|
#ifdef WMMSG_DEBUG
|
2006-07-17 06:47:33 +00:00
|
|
|
{
|
|
|
|
FILE *log = fopen("wmmsg.txt", "a");
|
|
|
|
fprintf(log, "Received windows message: %p ", hwnd);
|
|
|
|
if (msg > MAX_WMMSG) {
|
|
|
|
fprintf(log, "%d", msg);
|
|
|
|
} else {
|
|
|
|
fprintf(log, "%s", wmtab[msg]);
|
|
|
|
}
|
|
|
|
fprintf(log, " -- 0x%X, 0x%X\n", wParam, lParam);
|
|
|
|
fclose(log);
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2008-08-25 06:33:00 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
switch (msg) {
|
|
|
|
|
2008-08-25 06:33:00 +00:00
|
|
|
case WT_PACKET:
|
|
|
|
{
|
|
|
|
/* if we receive such data we need to update the pressure */
|
2008-08-26 06:03:48 +00:00
|
|
|
SDL_VideoData *videodata = data->videodata;
|
|
|
|
if (videodata->wintabDLL
|
2009-09-05 23:37:35 +00:00
|
|
|
&& videodata->WTPacket((HCTX) lParam, (UINT) wParam, &packet)) {
|
2008-08-25 06:33:00 +00:00
|
|
|
SDL_ChangeEnd(tablet, (int) packet.pkCursor);
|
|
|
|
pressure = (int) packet.pkNormalPressure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WT_PROXIMITY:
|
|
|
|
{
|
|
|
|
/* checking where the proximity message showed up */
|
|
|
|
int h_context = LOWORD(lParam);
|
2008-08-26 05:26:28 +00:00
|
|
|
POINT point;
|
2008-08-25 06:33:00 +00:00
|
|
|
GetCursorPos(&point);
|
|
|
|
ScreenToClient(hwnd, &point);
|
|
|
|
|
|
|
|
/* are we in proximity or out of proximity */
|
|
|
|
if (h_context == 0) {
|
2008-08-26 05:26:28 +00:00
|
|
|
SDL_SendProximity(tablet, point.x, point.y, SDL_PROXIMITYOUT);
|
2008-08-25 06:33:00 +00:00
|
|
|
} else {
|
2008-08-26 05:26:28 +00:00
|
|
|
SDL_SendProximity(tablet, point.x, point.y, SDL_PROXIMITYIN);
|
2008-08-25 06:33:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
case WM_SHOWWINDOW:
|
|
|
|
{
|
|
|
|
if (wParam) {
|
|
|
|
SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0,
|
|
|
|
0);
|
|
|
|
} else {
|
|
|
|
SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_ACTIVATE:
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
SDL_Keyboard *keyboard;
|
|
|
|
BOOL minimized;
|
|
|
|
|
|
|
|
minimized = HIWORD(wParam);
|
|
|
|
index = data->videodata->keyboard;
|
|
|
|
keyboard = SDL_GetKeyboard(index);
|
|
|
|
if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
|
|
|
|
SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN,
|
|
|
|
0, 0);
|
|
|
|
SDL_SendWindowEvent(data->windowID,
|
|
|
|
SDL_WINDOWEVENT_RESTORED, 0, 0);
|
2009-05-23 22:41:08 +00:00
|
|
|
#ifndef _WIN32_WCE /* WinCE misses IsZoomed() */
|
2006-07-10 21:04:37 +00:00
|
|
|
if (IsZoomed(hwnd)) {
|
|
|
|
SDL_SendWindowEvent(data->windowID,
|
|
|
|
SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
|
|
|
|
}
|
2009-05-23 22:41:08 +00:00
|
|
|
#endif
|
2006-07-10 21:04:37 +00:00
|
|
|
if (keyboard && keyboard->focus != data->windowID) {
|
|
|
|
SDL_SetKeyboardFocus(index, data->windowID);
|
|
|
|
}
|
|
|
|
/* FIXME: Update keyboard state */
|
|
|
|
} else {
|
|
|
|
if (keyboard && keyboard->focus == data->windowID) {
|
|
|
|
SDL_SetKeyboardFocus(index, 0);
|
|
|
|
}
|
|
|
|
if (minimized) {
|
|
|
|
SDL_SendWindowEvent(data->windowID,
|
|
|
|
SDL_WINDOWEVENT_MINIMIZED, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-08-25 06:33:00 +00:00
|
|
|
return (0);
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-03-23 05:35:21 +00:00
|
|
|
/* WinCE has no RawInput, so we use the classic mouse events.
|
|
|
|
In classic Win32 this is done by WM_INPUT
|
|
|
|
*/
|
|
|
|
#ifdef _WIN32_WCE
|
|
|
|
case WM_MOUSEMOVE:
|
2009-05-23 22:41:08 +00:00
|
|
|
SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
|
|
|
|
break;
|
|
|
|
|
2009-03-23 05:35:21 +00:00
|
|
|
case WM_LBUTTONDOWN:
|
2009-05-23 22:41:08 +00:00
|
|
|
SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
|
|
|
|
SDL_SendMouseButton(0, SDL_PRESSED, SDL_BUTTON_LEFT);
|
|
|
|
break;
|
|
|
|
|
2009-03-23 05:35:21 +00:00
|
|
|
case WM_LBUTTONUP:
|
2009-05-23 22:41:08 +00:00
|
|
|
SDL_SendMouseMotion(0, 0, LOWORD(lParam), HIWORD(lParam), 0);
|
|
|
|
SDL_SendMouseButton(0, SDL_RELEASED, SDL_BUTTON_LEFT);
|
|
|
|
break;
|
2009-03-23 05:35:21 +00:00
|
|
|
#else /* _WIN32_WCE */
|
|
|
|
|
2008-08-25 06:33:00 +00:00
|
|
|
case WM_INPUT: /* mouse events */
|
2006-07-10 21:04:37 +00:00
|
|
|
{
|
2008-08-25 06:33:00 +00:00
|
|
|
LPBYTE lpb;
|
|
|
|
const RAWINPUTHEADER *header;
|
2009-09-07 16:04:44 +00:00
|
|
|
int index = -1;
|
2008-08-25 06:33:00 +00:00
|
|
|
int i;
|
|
|
|
int size = 0;
|
|
|
|
const RAWMOUSE *raw_mouse = NULL;
|
2008-08-26 05:26:28 +00:00
|
|
|
POINT point;
|
2008-08-25 06:33:00 +00:00
|
|
|
USHORT flags;
|
2009-01-03 06:03:56 +00:00
|
|
|
int w, h;
|
2008-08-25 06:33:00 +00:00
|
|
|
|
2009-03-23 05:35:21 +00:00
|
|
|
/* we're collecting raw data to be able to identify the mouse (if there are several) */
|
2008-08-25 06:33:00 +00:00
|
|
|
GetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &size,
|
|
|
|
sizeof(RAWINPUTHEADER));
|
2008-10-12 16:05:34 +00:00
|
|
|
lpb = SDL_stack_alloc(BYTE, size);
|
2008-08-25 06:33:00 +00:00
|
|
|
GetRawInputData((HRAWINPUT) lParam, RID_INPUT, lpb, &size,
|
|
|
|
sizeof(RAWINPUTHEADER));
|
|
|
|
raw = (RAWINPUT *) lpb;
|
|
|
|
header = &raw->header;
|
|
|
|
flags = raw->data.mouse.usButtonFlags;
|
|
|
|
|
|
|
|
/* we're checking which mouse generated the event */
|
|
|
|
for (i = 0; i < total_mice; ++i) {
|
|
|
|
if (mice[i] == header->hDevice) {
|
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2009-09-07 16:04:44 +00:00
|
|
|
if (index < 0) {
|
|
|
|
/* New mouse? Should we dynamically update mouse list? */
|
|
|
|
return (0);
|
|
|
|
}
|
2009-05-23 22:41:08 +00:00
|
|
|
|
2008-08-25 06:33:00 +00:00
|
|
|
GetCursorPos(&point);
|
2009-01-03 06:03:56 +00:00
|
|
|
ScreenToClient(hwnd, &point);
|
|
|
|
|
|
|
|
SDL_GetWindowSize(data->windowID, &w, &h);
|
|
|
|
if (point.x >= 0 && point.y >= 0 && point.x < w && point.y < h) {
|
|
|
|
SDL_SetMouseFocus(index, data->windowID);
|
|
|
|
} else {
|
|
|
|
SDL_SetMouseFocus(index, 0);
|
|
|
|
/* FIXME: Should we be doing anything else here? */
|
|
|
|
break;
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2008-08-25 06:33:00 +00:00
|
|
|
/* if the message was sent by a tablet we have to send also pressure */
|
2008-11-27 21:53:18 +00:00
|
|
|
if (index == tablet) {
|
2008-08-26 05:26:28 +00:00
|
|
|
SDL_SendMouseMotion(index, 0, point.x, point.y, pressure);
|
2006-07-10 21:04:37 +00:00
|
|
|
} else {
|
2008-08-26 05:26:28 +00:00
|
|
|
SDL_SendMouseMotion(index, 0, point.x, point.y, 0);
|
2008-08-25 06:33:00 +00:00
|
|
|
}
|
|
|
|
/* we're sending mouse buttons messages to check up if sth changed */
|
2008-10-12 16:05:34 +00:00
|
|
|
if (flags & RI_MOUSE_LEFT_BUTTON_DOWN) {
|
2008-08-25 06:33:00 +00:00
|
|
|
SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_LEFT);
|
2008-10-12 16:05:34 +00:00
|
|
|
} else if (flags & RI_MOUSE_LEFT_BUTTON_UP) {
|
2008-08-25 06:33:00 +00:00
|
|
|
SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_LEFT);
|
|
|
|
}
|
2008-10-12 16:05:34 +00:00
|
|
|
if (flags & RI_MOUSE_MIDDLE_BUTTON_DOWN) {
|
2008-08-25 06:33:00 +00:00
|
|
|
SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_MIDDLE);
|
2008-10-12 16:05:34 +00:00
|
|
|
} else if (flags & RI_MOUSE_MIDDLE_BUTTON_UP) {
|
2008-08-25 06:33:00 +00:00
|
|
|
SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_MIDDLE);
|
|
|
|
}
|
2008-10-12 16:05:34 +00:00
|
|
|
if (flags & RI_MOUSE_RIGHT_BUTTON_DOWN) {
|
2008-08-25 06:33:00 +00:00
|
|
|
SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_RIGHT);
|
2008-10-12 16:05:34 +00:00
|
|
|
} else if (flags & RI_MOUSE_RIGHT_BUTTON_UP) {
|
2008-08-25 06:33:00 +00:00
|
|
|
SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_RIGHT);
|
|
|
|
}
|
2008-08-25 06:58:34 +00:00
|
|
|
if (flags & RI_MOUSE_BUTTON_4_DOWN) {
|
|
|
|
SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_X1);
|
|
|
|
} else if (flags & RI_MOUSE_BUTTON_4_UP) {
|
|
|
|
SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_X1);
|
|
|
|
}
|
|
|
|
if (flags & RI_MOUSE_BUTTON_5_DOWN) {
|
|
|
|
SDL_SendMouseButton(index, SDL_PRESSED, SDL_BUTTON_X2);
|
|
|
|
} else if (flags & RI_MOUSE_BUTTON_5_UP) {
|
|
|
|
SDL_SendMouseButton(index, SDL_RELEASED, SDL_BUTTON_X2);
|
|
|
|
}
|
2008-08-25 06:33:00 +00:00
|
|
|
if (flags & RI_MOUSE_WHEEL) {
|
2009-01-03 06:12:05 +00:00
|
|
|
SDL_SendMouseWheel(index, 0,
|
2009-01-04 17:14:27 +00:00
|
|
|
(short) raw->data.mouse.usButtonData);
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2008-10-12 16:05:34 +00:00
|
|
|
SDL_stack_free(lpb);
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
return (0);
|
2009-03-23 05:35:21 +00:00
|
|
|
#endif /* _WIN32_WCE */
|
2009-05-23 22:41:08 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
case WM_MOUSELEAVE:
|
|
|
|
{
|
2009-01-03 06:03:56 +00:00
|
|
|
int i;
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-01-03 06:03:56 +00:00
|
|
|
for (i = 0; i < SDL_GetNumMice(); ++i) {
|
|
|
|
SDL_Mouse *mouse = SDL_GetMouse(i);
|
2006-07-10 21:04:37 +00:00
|
|
|
|
2009-01-03 06:03:56 +00:00
|
|
|
if (mouse->focus == data->windowID) {
|
|
|
|
SDL_SetMouseFocus(i, 0);
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
case WM_SYSKEYDOWN:
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
|
|
|
/* Ignore repeated keys */
|
|
|
|
if (lParam & REPEATED_KEYMASK) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
index = data->videodata->keyboard;
|
2008-02-09 07:18:38 +00:00
|
|
|
wParam = RemapVKEY(wParam, lParam);
|
2006-07-10 21:04:37 +00:00
|
|
|
switch (wParam) {
|
|
|
|
case VK_CONTROL:
|
|
|
|
if (lParam & EXTENDED_KEYMASK)
|
|
|
|
wParam = VK_RCONTROL;
|
|
|
|
else
|
|
|
|
wParam = VK_LCONTROL;
|
|
|
|
break;
|
|
|
|
case VK_SHIFT:
|
|
|
|
/* EXTENDED trick doesn't work here */
|
|
|
|
{
|
2008-02-08 08:35:49 +00:00
|
|
|
Uint8 *state = SDL_GetKeyboardState(NULL);
|
|
|
|
if (state[SDL_SCANCODE_LSHIFT] == SDL_RELEASED
|
2006-07-10 21:04:37 +00:00
|
|
|
&& (GetKeyState(VK_LSHIFT) & 0x8000)) {
|
|
|
|
wParam = VK_LSHIFT;
|
2008-02-08 08:35:49 +00:00
|
|
|
} else if (state[SDL_SCANCODE_RSHIFT] == SDL_RELEASED
|
2006-07-10 21:04:37 +00:00
|
|
|
&& (GetKeyState(VK_RSHIFT) & 0x8000)) {
|
|
|
|
wParam = VK_RSHIFT;
|
|
|
|
} else {
|
|
|
|
/* Probably a key repeat */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VK_MENU:
|
|
|
|
if (lParam & EXTENDED_KEYMASK)
|
|
|
|
wParam = VK_RMENU;
|
|
|
|
else
|
|
|
|
wParam = VK_LMENU;
|
|
|
|
break;
|
2008-02-10 05:34:33 +00:00
|
|
|
case VK_RETURN:
|
|
|
|
if (lParam & EXTENDED_KEYMASK)
|
|
|
|
wParam = VK_ENTER;
|
|
|
|
break;
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2008-02-08 08:35:49 +00:00
|
|
|
if (wParam < 256) {
|
|
|
|
SDL_SendKeyboardKey(index, SDL_PRESSED,
|
|
|
|
data->videodata->key_layout[wParam]);
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
case WM_SYSKEYUP:
|
|
|
|
case WM_KEYUP:
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
|
|
|
index = data->videodata->keyboard;
|
2008-02-09 07:18:38 +00:00
|
|
|
wParam = RemapVKEY(wParam, lParam);
|
2006-07-10 21:04:37 +00:00
|
|
|
switch (wParam) {
|
|
|
|
case VK_CONTROL:
|
|
|
|
if (lParam & EXTENDED_KEYMASK)
|
|
|
|
wParam = VK_RCONTROL;
|
|
|
|
else
|
|
|
|
wParam = VK_LCONTROL;
|
|
|
|
break;
|
|
|
|
case VK_SHIFT:
|
|
|
|
/* EXTENDED trick doesn't work here */
|
|
|
|
{
|
2008-02-08 08:35:49 +00:00
|
|
|
Uint8 *state = SDL_GetKeyboardState(NULL);
|
|
|
|
if (state[SDL_SCANCODE_LSHIFT] == SDL_PRESSED
|
2006-07-10 21:04:37 +00:00
|
|
|
&& !(GetKeyState(VK_LSHIFT) & 0x8000)) {
|
|
|
|
wParam = VK_LSHIFT;
|
2008-02-08 08:35:49 +00:00
|
|
|
} else if (state[SDL_SCANCODE_RSHIFT] == SDL_PRESSED
|
2006-07-10 21:04:37 +00:00
|
|
|
&& !(GetKeyState(VK_RSHIFT) & 0x8000)) {
|
|
|
|
wParam = VK_RSHIFT;
|
|
|
|
} else {
|
|
|
|
/* Probably a key repeat */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VK_MENU:
|
|
|
|
if (lParam & EXTENDED_KEYMASK)
|
|
|
|
wParam = VK_RMENU;
|
|
|
|
else
|
|
|
|
wParam = VK_LMENU;
|
|
|
|
break;
|
2008-02-10 05:34:33 +00:00
|
|
|
case VK_RETURN:
|
|
|
|
if (lParam & EXTENDED_KEYMASK)
|
|
|
|
wParam = VK_ENTER;
|
|
|
|
break;
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
2008-08-25 06:33:00 +00:00
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* Windows only reports keyup for print screen */
|
|
|
|
if (wParam == VK_SNAPSHOT
|
2008-02-08 08:35:49 +00:00
|
|
|
&& SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
|
|
|
|
SDL_RELEASED) {
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_SendKeyboardKey(index, SDL_PRESSED,
|
2008-02-08 08:35:49 +00:00
|
|
|
data->videodata->key_layout[wParam]);
|
|
|
|
}
|
|
|
|
if (wParam < 256) {
|
|
|
|
SDL_SendKeyboardKey(index, SDL_RELEASED,
|
|
|
|
data->videodata->key_layout[wParam]);
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
|
2008-02-09 06:47:46 +00:00
|
|
|
case WM_CHAR:
|
|
|
|
{
|
|
|
|
char text[4];
|
|
|
|
|
|
|
|
/* Convert to UTF-8 and send it on... */
|
|
|
|
if (wParam <= 0x7F) {
|
|
|
|
text[0] = (char) wParam;
|
|
|
|
text[1] = '\0';
|
|
|
|
} else if (wParam <= 0x7FF) {
|
|
|
|
text[0] = 0xC0 | (char) ((wParam >> 6) & 0x1F);
|
|
|
|
text[1] = 0x80 | (char) (wParam & 0x3F);
|
|
|
|
text[2] = '\0';
|
|
|
|
} else {
|
|
|
|
text[0] = 0xE0 | (char) ((wParam >> 12) & 0x0F);
|
|
|
|
text[1] = 0x80 | (char) ((wParam >> 6) & 0x3F);
|
|
|
|
text[2] = 0x80 | (char) (wParam & 0x3F);
|
|
|
|
text[3] = '\0';
|
|
|
|
}
|
|
|
|
SDL_SendKeyboardText(data->videodata->keyboard, text);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
|
2008-02-09 22:28:27 +00:00
|
|
|
case WM_INPUTLANGCHANGE:
|
|
|
|
{
|
|
|
|
WIN_UpdateKeymap(data->videodata->keyboard);
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
case WM_GETMINMAXINFO:
|
|
|
|
{
|
|
|
|
MINMAXINFO *info;
|
|
|
|
RECT size;
|
|
|
|
int x, y;
|
|
|
|
int w, h;
|
|
|
|
int style;
|
2009-06-07 02:44:46 +00:00
|
|
|
BOOL menu;
|
2006-07-10 21:04:37 +00:00
|
|
|
|
|
|
|
/* If we allow resizing, let the resize happen naturally */
|
|
|
|
if (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_RESIZABLE) {
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the current position of our window */
|
|
|
|
GetWindowRect(hwnd, &size);
|
|
|
|
x = size.left;
|
|
|
|
y = size.top;
|
|
|
|
|
|
|
|
/* Calculate current size of our window */
|
|
|
|
SDL_GetWindowSize(data->windowID, &w, &h);
|
|
|
|
size.top = 0;
|
|
|
|
size.left = 0;
|
|
|
|
size.bottom = h;
|
|
|
|
size.right = w;
|
|
|
|
|
2009-06-07 02:44:46 +00:00
|
|
|
|
|
|
|
style = GetWindowLong(hwnd, GWL_STYLE);
|
|
|
|
#ifdef _WIN32_WCE
|
|
|
|
menu = FALSE;
|
|
|
|
#else
|
2006-07-10 21:04:37 +00:00
|
|
|
/* 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.
|
|
|
|
*/
|
2009-06-07 02:44:46 +00:00
|
|
|
menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
|
|
|
|
#endif
|
|
|
|
AdjustWindowRectEx(&size, style, menu, 0);
|
2006-07-10 21:04:37 +00:00
|
|
|
w = size.right - size.left;
|
|
|
|
h = size.bottom - size.top;
|
|
|
|
|
|
|
|
/* Fix our size to the current size */
|
|
|
|
info = (MINMAXINFO *) lParam;
|
|
|
|
info->ptMaxSize.x = w;
|
|
|
|
info->ptMaxSize.y = h;
|
|
|
|
info->ptMaxPosition.x = x;
|
|
|
|
info->ptMaxPosition.y = y;
|
|
|
|
info->ptMinTrackSize.x = w;
|
|
|
|
info->ptMinTrackSize.y = h;
|
|
|
|
info->ptMaxTrackSize.x = w;
|
|
|
|
info->ptMaxTrackSize.y = h;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
int x, y;
|
|
|
|
int w, h;
|
|
|
|
Uint32 window_flags;
|
|
|
|
|
2009-09-06 15:04:38 +00:00
|
|
|
if (!GetClientRect(hwnd, &rect) ||
|
|
|
|
(rect.right == rect.left && rect.bottom == rect.top)) {
|
|
|
|
break;
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
ClientToScreen(hwnd, (LPPOINT) & rect);
|
|
|
|
ClientToScreen(hwnd, (LPPOINT) & rect + 1);
|
|
|
|
|
|
|
|
window_flags = SDL_GetWindowFlags(data->windowID);
|
|
|
|
if ((window_flags & SDL_WINDOW_INPUT_GRABBED) &&
|
|
|
|
(window_flags & SDL_WINDOW_INPUT_FOCUS)) {
|
|
|
|
ClipCursor(&rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
x = rect.left;
|
|
|
|
y = rect.top;
|
|
|
|
SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, x, y);
|
|
|
|
|
|
|
|
w = rect.right - rect.left;
|
|
|
|
h = rect.bottom - rect.top;
|
|
|
|
SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, w,
|
|
|
|
h);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_SETCURSOR:
|
|
|
|
{
|
2009-02-19 04:41:09 +00:00
|
|
|
Uint16 hittest;
|
|
|
|
|
|
|
|
hittest = LOWORD(lParam);
|
|
|
|
if (hittest == HTCLIENT) {
|
|
|
|
/* FIXME: Implement the cursor API */
|
|
|
|
static HCURSOR cursor;
|
|
|
|
if (!cursor) {
|
|
|
|
cursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
}
|
|
|
|
SetCursor(cursor);
|
|
|
|
return (TRUE);
|
|
|
|
}
|
2006-07-10 21:04:37 +00:00
|
|
|
}
|
|
|
|
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:
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
if (GetUpdateRect(hwnd, &rect, FALSE)) {
|
|
|
|
ValidateRect(hwnd, &rect);
|
|
|
|
SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED,
|
|
|
|
0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
|
2009-03-23 02:02:30 +00:00
|
|
|
/* If this isn't our window, we don't need to repaint the frame.
|
|
|
|
This fixes a reentrancy issue that can cause stack overflows with foreign windows.
|
|
|
|
3/21/09 Mason Wheeler */
|
|
|
|
case WM_NCPAINT:
|
|
|
|
{
|
2009-03-28 06:00:42 +00:00
|
|
|
if (SDL_GetWindowFlags(data->windowID) & SDL_WINDOW_FOREIGN) {
|
2009-05-23 22:41:08 +00:00
|
|
|
return (0);
|
2009-03-23 02:02:30 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-07-10 21:04:37 +00:00
|
|
|
/* We'll do our own drawing, prevent flicker */
|
|
|
|
case WM_ERASEBKGND:
|
|
|
|
{
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
{
|
|
|
|
/* Don't start the screensaver or blank the monitor in fullscreen apps */
|
|
|
|
if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
|
|
|
|
(wParam & 0xFFF0) == SC_MONITORPOWER) {
|
2009-01-12 08:46:28 +00:00
|
|
|
if (SDL_GetVideoDevice()->suspend_screensaver) {
|
2006-07-10 21:04:37 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_CLOSE:
|
|
|
|
{
|
|
|
|
SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, 0);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
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;
|
2008-08-25 06:33:00 +00:00
|
|
|
class.hIcon =
|
|
|
|
LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
|
|
|
|
LR_DEFAULTCOLOR);
|
2006-07-10 21:04:37 +00:00
|
|
|
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;
|
2008-08-25 06:33:00 +00:00
|
|
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
|
|
|
|
buffer, SDL_arraysize(buffer), NULL);
|
2006-07-10 21:04:37 +00:00
|
|
|
message = WIN_StringToUTF8(buffer);
|
2009-12-15 08:11:06 +00:00
|
|
|
SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message);
|
2006-07-10 21:04:37 +00:00
|
|
|
SDL_free(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vi: set ts=4 sw=4 expandtab: */
|