Here is a simple application that shows how I detect
the mouse coverage in window and the modified code of
SDL-0.10.0/src/win32/windib/SDL_sysevents.c
I commented with /* these lines added/modified by Enzo */
the parts of the code with the patch.
Unfortunately I can’t test it beacuse I’ve got some problems with
cross-compiling (I use library binaries for win32 mode)
Bye, Enzo.
-------------- next part --------------
#include <windows.h>
#define TIMER_ID 1
#define TIMER_INTERVAL 100 // do 10 tests per second
bool inside = false;
LRESULT CALLBACK WindowProc (HWND, UINT, WPARAM, LPARAM);
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = “Mouse coverage”;
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
RegisterClass(&wndclass);
hwnd = CreateWindow (szAppName,
“Mouse coverage test”,
WS_OVERLAPPEDWINDOW,
100, 100, 400, 200,
NULL, NULL, hInstance, NULL);
ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
SetTimer (hwnd, TIMER_ID, TIMER_INTERVAL, NULL);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
HDC hdc;
hdc = BeginPaint (hwnd, &ps);
GetClientRect (hwnd, &rect);
Rectangle (hdc, 10,10,100,100);
if (inside) {
DrawText (hdc, "Inside", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
MoveTo (hdc,10,10);
LineTo (hdc,100,100);
MoveTo (hdc,10,100);
LineTo (hdc,100,10);
} else {
DrawText (hdc, "Outside", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
EndPaint (hwnd, &ps);
return 0;
}
case WM_TIMER:
{
POINT arrow;
bool prev;
RECT bounds, client;
prev = inside;
int border;
GetCursorPos (&arrow);
GetWindowRect (hwnd,&bounds);
GetClientRect (hwnd,&client);
border = ((bounds.right-bounds.left+1)-client.right)/2;
inside = ((arrow.x>=bounds.left+border) &&
(arrow.x<bounds.right-border) &&
(arrow.y>=bounds.bottom-border-client.bottom) &&
(arrow.y<bounds.bottom-border));
if (inside != prev) InvalidateRect (hwnd, NULL, TRUE);
break;
}
case WM_DESTROY:
{
KillTimer (hwnd, 1);
PostQuitMessage(0);
break;
}
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
-------------- next part --------------
/*
SDL - Simple DirectMedia Layer
Copyright © 1997, 1998 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
5635-34 Springhouse Dr.
Pleasanton, CA 94588 (USA)
slouken at devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_sysevents.c,v 1.15 1999/08/05 19:08:13 slouken Exp $";
#endif
#include <stdio.h>
#include <signal.h>
#include <windows.h>
#include “SDL_events.h”
#include “SDL_video.h”
#include “SDL_error.h”
#include “SDL_syswm.h”
#include “SDL_sysevents.h”
#include “SDL_video_c.h”
#include “SDL_events_c.h”
#include “SDL_lowvideo.h”
#include “SDL_vkeys.h”
#ifdef WMMSG_DEBUG
#include “wmmsg.h”
#endif
#ifndef WM_APP
#define WM_APP 0x8000
#endif
/* these lines added by Enzo /
#define TIMER_ID 1
#define TIMER_INTERVAL 100 // do 10 tests per second
/ ------------------------- */
/* The window we use for everything… */
static char SDL_Appname = NULL;
static HINSTANCE SDL_Instance;
HWND SDL_Window = NULL;
RECT SDL_bounds;
/ these lines added by Enzo /
bool SDL_MouseFocus = FALSE;
/ ------------------------- */
int SDL_resizing = 0;
/* The translation table from a Microsoft VK keysym to a SDL keysym */
static SDLKey VK_keymap[SDLK_LAST];
static SDL_keysym *TranslateKey(UINT vkey, UINT scancode, SDL_keysym *keysym);
/* Masks for processing the windows KEYDOWN and KEYUP messages */
#define REPEATED_KEYMASK (1<<30)
#define EXTENDED_KEYMASK (1<<24)
/* The main Win32 event handler */
LONG CALLBACK
SDL_WinMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int mouse_pressed = 0;
int posted;
#ifdef WMMSG_DEBUG
fprintf(stderr, "Received windows message: “);
if ( msg > MAX_WMMSG ) {
fprintf(stderr, “%d”, msg);
} else {
fprintf(stderr, “%s”, wmtab[msg]);
}
fprintf(stderr, " – 0x%X, 0x%X\n”, wParam, lParam);
#endif
switch (msg) {
/* these lines added by Enzo */
case WM_CREATE: {
SetTimer (SDL_Window, TIMER_ID, TIMER_INTERVAL, NULL);
}
break;
/* ------------------------- */
case WM_ACTIVATE: {
int active, minimized;
minimized = HIWORD(wParam);
active = LOWORD(wParam);
if ( minimized && !active ) {
posted = SDL_PrivateAppActive(0, SDL_APPACTIVE);
}
if ( !minimized && active ) {
posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
}
}
break;
case WM_ACTIVATEAPP: {
int active;
active = (wParam && (GetForegroundWindow() == hwnd));
/* these lines modified by Enzo */
posted = SDL_PrivateAppActive((Uint8)active,
(SDL_APPINPUTFOCUS));
/* ---------------------------- */
}
break;
/* these lines added by Enzo */
case WM_TIMER: {
POINT CursorPos;
bool PrevFlag;
PrevFlag = SDL_MouseFocus;
GetCursorPos (&CursorPos);
GetClientRect(SDL_Window, &SDL_bounds);
ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds);
ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds+1);
SDL_MouseFocus = ((CursorPos.x>=SDL_bounds.left) &&
(CursorPos.x<SDL_bounds.right) &&
(CursorPos.y>=SDL_bounds.bottom) &&
(CursorPos.y<bounds.bottom));
if (inside != prev)
posted = SDL_PrivateAppActive((Uint8)SDL_MouseFocus,
(SDL_APPMOUSEFOCUS));
}
break;
/* ------------------------- */
// this comment is no more true now :)
/* If we lose the application focus, we also lose the mouse.
Unfortunately, I don't know of a way to detect when the
mouse enters and leaves our client area in a casual pass
of the mouse, so we leave our cursor hanging around.
*/
case WM_MOUSEMOVE: {
Uint16 x, y;
x = LOWORD(lParam);
y = HIWORD(lParam);
posted = SDL_PrivateMouseMotion(0, 0, x, y);
}
break;
case WM_LBUTTONDOWN: {
Uint16 x, y;
/* Grab the mouse so we get mouse-up events */
if ( ++mouse_pressed > 0 ) {
SetCapture(hwnd);
}
x = LOWORD(lParam);
y = HIWORD(lParam);
posted = SDL_PrivateMouseButton(SDL_PRESSED, 1, x, y);
}
return(0);
case WM_LBUTTONUP: {
Uint16 x, y;
/* Release the mouse after all mouse-up events */
if ( --mouse_pressed <= 0 ) {
ReleaseCapture();
mouse_pressed = 0;
}
x = LOWORD(lParam);
y = HIWORD(lParam);
posted = SDL_PrivateMouseButton(SDL_RELEASED, 1, x, y);
}
return(0);
case WM_RBUTTONDOWN: {
Uint16 x, y;
/* Grab the mouse so we get mouse-up events */
if ( ++mouse_pressed > 0 ) {
SetCapture(hwnd);
}
x = LOWORD(lParam);
y = HIWORD(lParam);
posted = SDL_PrivateMouseButton(SDL_PRESSED, 3, x, y);
}
return(0);
case WM_RBUTTONUP: {
Uint16 x, y;
/* Release the mouse after all mouse-up events */
if ( --mouse_pressed <= 0 ) {
ReleaseCapture();
mouse_pressed = 0;
}
x = LOWORD(lParam);
y = HIWORD(lParam);
posted = SDL_PrivateMouseButton(SDL_RELEASED, 3, x, y);
}
return(0);
case WM_SYSKEYDOWN:
case WM_KEYDOWN: {
SDL_keysym keysym;
/* Ignore repeated keys */
if ( lParam&REPEATED_KEYMASK ) {
return(0);
}
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 */
wParam = VK_LSHIFT;
break;
case VK_MENU:
if ( lParam&EXTENDED_KEYMASK )
wParam = VK_RMENU;
else
wParam = VK_LMENU;
break;
}
posted = SDL_PrivateKeyboard(SDL_PRESSED,
TranslateKey(wParam,HIWORD(lParam),&keysym));
}
return(0);
case WM_SYSKEYUP:
case WM_KEYUP: {
SDL_keysym keysym;
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 */
wParam = VK_LSHIFT;
break;
case VK_MENU:
if ( lParam&EXTENDED_KEYMASK )
wParam = VK_RMENU;
else
wParam = VK_LMENU;
break;
}
posted = SDL_PrivateKeyboard(SDL_RELEASED,
TranslateKey(wParam,HIWORD(lParam),&keysym));
}
return(0);
/* 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 width;
int height;
/* We don't want to clobber an internal resize */
if ( SDL_resizing )
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;
}
AdjustWindowRect(&size, GetWindowLong(hwnd, GWL_STYLE),
FALSE);
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);
case WM_MOVE: {
GetClientRect(SDL_Window, &SDL_bounds);
ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds);
ClientToScreen(SDL_Window, (LPPOINT)&SDL_bounds+1);
}
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: {
SDL_RealizePalette();
return(TRUE);
}
break;
/* Another application changed the palette */
case WM_PALETTECHANGED: {
SDL_PaletteChanged((HWND)wParam);
}
break;
/* We were occluded, refresh our display */
case WM_PAINT: {
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(SDL_Window, &ps);
SDL_WinPAINT(hdc);
EndPaint(SDL_Window, &ps);
}
break;
case WM_CLOSE: {
if ( (posted = SDL_PrivateQuit()) )
PostQuitMessage(0);
}
return(0);
case WM_DESTROY: {
/* these lines added by Enzo */
KillTimer (SDL_Window, 1);
/* ------------------------- */
PostQuitMessage(0);
}
return(0);
default: {
/* Only post the event if we're watching for it */
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;
posted = SDL_PrivateSysWMEvent(&wmmsg);
}
}
break;
}
return(DefWindowProc(hwnd, msg, wParam, lParam));
}
void SDL_SYS_PumpEvents(void)
{
MSG msg;
while ( PeekMessage(&msg, NULL, 0, (WM_APP-1), PM_NOREMOVE) ) {
if ( GetMessage(&msg, NULL, 0, (WM_APP-1)) > 0 ) {
DispatchMessage(&msg);
}
}
}
void SDL_InitOSKeymap(void)
{
int i;
/* Map the VK keysyms */
for ( i=0; i<SDL_TABLESIZE(VK_keymap); ++i )
VK_keymap[i] = SDLK_UNKNOWN;
VK_keymap[VK_BACK] = SDLK_BACKSPACE;
VK_keymap[VK_TAB] = SDLK_TAB;
VK_keymap[VK_CLEAR] = SDLK_CLEAR;
VK_keymap[VK_RETURN] = SDLK_RETURN;
VK_keymap[VK_PAUSE] = SDLK_PAUSE;
VK_keymap[VK_ESCAPE] = SDLK_ESCAPE;
VK_keymap[VK_SPACE] = SDLK_SPACE;
VK_keymap[VK_APOSTROPHE] = SDLK_QUOTE;
VK_keymap[VK_COMMA] = SDLK_COMMA;
VK_keymap[VK_MINUS] = SDLK_MINUS;
VK_keymap[VK_PERIOD] = SDLK_PERIOD;
VK_keymap[VK_SLASH] = SDLK_SLASH;
VK_keymap[VK_0] = SDLK_0;
VK_keymap[VK_1] = SDLK_1;
VK_keymap[VK_2] = SDLK_2;
VK_keymap[VK_3] = SDLK_3;
VK_keymap[VK_4] = SDLK_4;
VK_keymap[VK_5] = SDLK_5;
VK_keymap[VK_6] = SDLK_6;
VK_keymap[VK_7] = SDLK_7;
VK_keymap[VK_8] = SDLK_8;
VK_keymap[VK_9] = SDLK_9;
VK_keymap[VK_SEMICOLON] = SDLK_SEMICOLON;
VK_keymap[VK_EQUALS] = SDLK_EQUALS;
VK_keymap[VK_LBRACKET] = SDLK_LEFTBRACKET;
VK_keymap[VK_BACKSLASH] = SDLK_BACKSLASH;
VK_keymap[VK_RBRACKET] = SDLK_RIGHTBRACKET;
VK_keymap[VK_GRAVE] = SDLK_BACKQUOTE;
VK_keymap[VK_A] = SDLK_a;
VK_keymap[VK_B] = SDLK_b;
VK_keymap[VK_C] = SDLK_c;
VK_keymap[VK_D] = SDLK_d;
VK_keymap[VK_E] = SDLK_e;
VK_keymap[VK_F] = SDLK_f;
VK_keymap[VK_G] = SDLK_g;
VK_keymap[VK_H] = SDLK_h;
VK_keymap[VK_I] = SDLK_i;
VK_keymap[VK_J] = SDLK_j;
VK_keymap[VK_K] = SDLK_k;
VK_keymap[VK_L] = SDLK_l;
VK_keymap[VK_M] = SDLK_m;
VK_keymap[VK_N] = SDLK_n;
VK_keymap[VK_O] = SDLK_o;
VK_keymap[VK_P] = SDLK_p;
VK_keymap[VK_Q] = SDLK_q;
VK_keymap[VK_R] = SDLK_r;
VK_keymap[VK_S] = SDLK_s;
VK_keymap[VK_T] = SDLK_t;
VK_keymap[VK_U] = SDLK_u;
VK_keymap[VK_V] = SDLK_v;
VK_keymap[VK_W] = SDLK_w;
VK_keymap[VK_X] = SDLK_x;
VK_keymap[VK_Y] = SDLK_y;
VK_keymap[VK_Z] = SDLK_z;
VK_keymap[VK_DELETE] = SDLK_DELETE;
VK_keymap[VK_NUMPAD0] = SDLK_KP0;
VK_keymap[VK_NUMPAD1] = SDLK_KP1;
VK_keymap[VK_NUMPAD2] = SDLK_KP2;
VK_keymap[VK_NUMPAD3] = SDLK_KP3;
VK_keymap[VK_NUMPAD4] = SDLK_KP4;
VK_keymap[VK_NUMPAD5] = SDLK_KP5;
VK_keymap[VK_NUMPAD6] = SDLK_KP6;
VK_keymap[VK_NUMPAD7] = SDLK_KP7;
VK_keymap[VK_NUMPAD8] = SDLK_KP8;
VK_keymap[VK_NUMPAD9] = SDLK_KP9;
VK_keymap[VK_DECIMAL] = SDLK_KP_PERIOD;
VK_keymap[VK_DIVIDE] = SDLK_KP_DIVIDE;
VK_keymap[VK_MULTIPLY] = SDLK_KP_MULTIPLY;
VK_keymap[VK_SUBTRACT] = SDLK_KP_MINUS;
VK_keymap[VK_ADD] = SDLK_KP_PLUS;
VK_keymap[VK_UP] = SDLK_UP;
VK_keymap[VK_DOWN] = SDLK_DOWN;
VK_keymap[VK_RIGHT] = SDLK_RIGHT;
VK_keymap[VK_LEFT] = SDLK_LEFT;
VK_keymap[VK_INSERT] = SDLK_INSERT;
VK_keymap[VK_HOME] = SDLK_HOME;
VK_keymap[VK_END] = SDLK_END;
VK_keymap[VK_PRIOR] = SDLK_PAGEUP;
VK_keymap[VK_NEXT] = SDLK_PAGEDOWN;
VK_keymap[VK_F1] = SDLK_F1;
VK_keymap[VK_F2] = SDLK_F2;
VK_keymap[VK_F3] = SDLK_F3;
VK_keymap[VK_F4] = SDLK_F4;
VK_keymap[VK_F5] = SDLK_F5;
VK_keymap[VK_F6] = SDLK_F6;
VK_keymap[VK_F7] = SDLK_F7;
VK_keymap[VK_F8] = SDLK_F8;
VK_keymap[VK_F9] = SDLK_F9;
VK_keymap[VK_F10] = SDLK_F10;
VK_keymap[VK_F11] = SDLK_F11;
VK_keymap[VK_F12] = SDLK_F12;
VK_keymap[VK_F13] = SDLK_F13;
VK_keymap[VK_F14] = SDLK_F14;
VK_keymap[VK_F15] = SDLK_F15;
VK_keymap[VK_NUMLOCK] = SDLK_NUMLOCK;
VK_keymap[VK_CAPITAL] = SDLK_CAPSLOCK;
VK_keymap[VK_SCROLL] = SDLK_SCROLLOCK;
VK_keymap[VK_RSHIFT] = SDLK_RSHIFT;
VK_keymap[VK_LSHIFT] = SDLK_LSHIFT;
VK_keymap[VK_RCONTROL] = SDLK_RCTRL;
VK_keymap[VK_LCONTROL] = SDLK_LCTRL;
VK_keymap[VK_RMENU] = SDLK_RALT;
VK_keymap[VK_LMENU] = SDLK_LALT;
VK_keymap[VK_RWIN] = SDLK_RSUPER;
VK_keymap[VK_LWIN] = SDLK_LSUPER;
VK_keymap[VK_HELP] = SDLK_HELP;
#ifdef VK_PRINT
VK_keymap[VK_PRINT] = SDLK_PRINT;
#endif
VK_keymap[VK_SNAPSHOT] = SDLK_PRINT;
VK_keymap[VK_CANCEL] = SDLK_BREAK;
VK_keymap[VK_APPS] = SDLK_MENU;
/* Set the numlock state */
if ( GetKeyState(VK_NUMLOCK) )
SDL_SetModState(SDL_GetModState()|KMOD_NUM);
}
static SDL_keysym *TranslateKey(UINT vkey, UINT scancode, SDL_keysym keysym)
{
/ Set the keysym information /
keysym->scancode = vkey&0xFF;
keysym->sym = VK_keymap[vkey];
keysym->mod = KMOD_NONE;
if ( SDL_TranslateUNICODE ) { / Someday use ToUnicode() */
BYTE keystate[256];
BYTE chars[2];
GetKeyboardState(keystate);
if ( ToAscii(vkey,scancode,keystate,(WORD *)chars,0) == 1 ) {
keysym->unicode = chars[0];
}
} else {
keysym->unicode = 0;
}
return(keysym);
}
int SDL_CreateWindow(void)
{
SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX),
0, 0, 0, 0, NULL, NULL, SDL_Instance, NULL);
if ( SDL_Window == NULL ) {
SDL_SetError(“Couldn’t create window”);
return(-1);
}
ShowWindow(SDL_Window, SW_HIDE);
return(0);
}
void SDL_DestroyWindow(void)
{
DestroyWindow(SDL_Window);
}
/* Register the class for this application – exported for winmain.c */
int _SDL_RegisterApp(char *name, UINT style, HINSTANCE hInst)
{
WNDCLASS class;
class.hCursor = NULL;
class.hIcon = LoadImage(hInst, name, IMAGE_ICON,
0, 0, LR_DEFAULTCOLOR);
class.lpszMenuName = "(none)";
class.lpszClassName = name;
class.hbrBackground = GetStockObject(BLACK_BRUSH);
class.hInstance = hInst;
class.style = style;
class.lpfnWndProc = SDL_WinMessage;
class.cbWndExtra = 0;
class.cbClsExtra = 0;
if ( ! RegisterClass(&class) ) {
SDL_SetError("Couldn't register application class");
return(-1);
}
SDL_Appname = name;
SDL_Instance = hInst;
return(0);
}