Patch for mouse coverage in win32

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

}

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.

Your code doesn’t work in the case where part or all of your window is
covered by another. Try running your program and then running another
application over top of it, the SDL program will get mouse coverage
messages when it shouldn’t.

I have included a fix in the below. I just added one line, marked by a
comment with my initials (DCS).

I also don’t really like the fact that a timer is used; your application
can never go idle. I looked at capturing the mouse, which works great. The
only problem is that for some strange reason the window won’t respond to
Alt-F4, F10 and some other system keypresses. I didn’t spend enough time
on it to figure out why and the documentation says nothing of that effect.

If you want that code I can send it over. It’s just one function -
everything can be done from a simple WM_NCHITTEST message handler.


border = ((bounds.right-bounds.left+1)-client.right)/2;
inside = (WindowFromPoint(arrow) == hwnd) && //DCS
(arrow.x>=bounds.left+border) &&
(arrow.x<bounds.right-border) &&
(arrow.y>=bounds.bottom-border-client.bottom) &&
(arrow.y<bounds.bottom-border);
…On Thu, 14 Oct 1999, Enzo wrote:

Your code doesn’t work in the case where part or all of your window is
covered by another. Try running your program and then running another
application over top of it, the SDL program will get mouse coverage
messages when it shouldn’t.

I am concerned about this. When my SDL application has focus I want to
receive mouse events regardless of whether the mouse is inside the window
or whether the SDL window is obscured by another window. Really it is none
of the application’s business how I organize my windows. At very least I’d
like it optional.

When my window has focus, I want ALL mouse events. Not just mouse events,
ALL events!
-Dave

Your code doesn’t work in the case where part or all of your window is
covered by another. Try running your program and then running another
application over top of it, the SDL program will get mouse coverage
messages when it shouldn’t.

I am concerned about this. When my SDL application has focus I want to
receive mouse events regardless of whether the mouse is inside the window
or whether the SDL window is obscured by another window. Really it is none
of the application’s business how I organize my windows. At very least I’d
like it optional.

I’m not sure I follow you. Why should you get mouse messages if the mouse
cursor isn’t in your window? If the bottom right quarter of your window is
covered then you shouldn’t have mouse focus or receive mouse messages when
the cursor is in that quarter (in the other window). My tiny patch makes
it so that whenever the mouse cursor enters the VISIBLE client area of the
SDL window, you gain mouse focus; whenever it leaves the VISIBLE client
area you lose mouse focus. The way Enzo had it was even if your SDL window
was completely covered (not visible at all) you could still gain and lose
mouse focus although you would never get any mouse messages.

When my window has focus, I want ALL mouse events. Not just mouse events,
ALL events!
-Dave

Keyboard focus or mouse focus? It’s treated as seperate in SDL. And by ‘I
want ALL mouse events’ do you mean mouse events that occur even when the
cursor is outside of the window?On Sat, 16 Oct 1999, Dave Ashley wrote:

Danny Sinclair wrote:

Your code doesn’t work in the case where part or all of your window is
covered by another. Try running your program and then running another
application over top of it, the SDL program will get mouse coverage
messages when it shouldn’t.

Oh, I already know it but I didn’t know the correct way to skip the problem.

I also don’t really like the fact that a timer is used;

I don’t like it too but at the moment is the only way I tried that worked
correctly.

I looked at capturing the mouse, which works great.

You mean using “SetCapture” ? Win32 api reference says that only one
window can have the mouse capture. So what happens if another window
that uses this function starts?

If you want that code I can send it over. It’s just one function -
everything can be done from a simple WM_NCHITTEST message handler.

border = ((bounds.right-bounds.left+1)-client.right)/2;
inside = (WindowFromPoint(arrow) == hwnd) && //DCS
(arrow.x>=bounds.left+border) &&
(arrow.x<bounds.right-border) &&
(arrow.y>=bounds.bottom-border-client.bottom) &&
(arrow.y<bounds.bottom-border);

I tried to follow with borland winsight all the messages (really too much in
win32!!!)
that occurs when the mouse enter/leave the window, but I think that
WM_NCHITTEST
doesn’t work if the window isn’t the foreground window.
Maybe I’m wrong (I’m not good in win32 api programming), on monday I’ll try
it.

Dave Ashley wrote:

When my window has focus, I want ALL mouse events. Not just mouse events,
ALL events!

Danny Sinclair wrote:

Keyboard focus or mouse focus? It’s treated as seperate in SDL. And by ‘I
want ALL mouse events’ do you mean mouse events that occur even when the
cursor is outside of the window?

In each case, SDL must be MULTI-PLATFORM, and so the sys events in win32
mode must have the same behaviour as in linux, beOS, macOS modes.
Have a look on how it works in linux mode (I think it’s the correct way).

Thanks.
Bye.
Enzo.

I am concerned about this. When my SDL application has focus I want to
receive mouse events regardless of whether the mouse is inside the window
or whether the SDL window is obscured by another window. Really it is none
of the application’s business how I organize my windows. At very least I’d
like it optional.

I’m not sure I follow you. Why should you get mouse messages if the mouse
cursor isn’t in your window? If the bottom right quarter of your window is
covered then you shouldn’t have mouse focus or receive mouse messages when
the cursor is in that quarter (in the other window). My tiny patch makes
it so that whenever the mouse cursor enters the VISIBLE client area of the
SDL window, you gain mouse focus; whenever it leaves the VISIBLE client
area you lose mouse focus. The way Enzo had it was even if your SDL window
was completely covered (not visible at all) you could still gain and lose
mouse focus although you would never get any mouse messages.

When my window has focus, I want ALL mouse events. Not just mouse events,
ALL events!
-Dave

Keyboard focus or mouse focus? It’s treated as seperate in SDL. And by ‘I
want ALL mouse events’ do you mean mouse events that occur even when the
cursor is outside of the window?

I really wasn’t thinking of the question of what the mouse pointer should
look like. If the pointer is over my window it should look like what my
application wants it to look like. If it is over another window, it should
look like what that appication wants it to look like. Regardless of how
the cursor is rendered, if my application has focus, I want mouse, keyboard,
whatever events. I also want mouse movement events even if the mouse is
outside my window–I don’t want any clipping going on, I can do that myself
if I want to.

For example in the SDL version of scavenger, I turn the pointer off (the
hardware sprite pointer) and I render my own + style cursor into my window
myself. When the user moves the mouse out of the window, there is a
dangling pointer sitting there because I didn’t get mouse movement events
outside of the window. Then when I bring the pointer back into the window
the pointer will pop over to the new position. My program can handle the
clipping, I’d just like to get the mouse events outside so there isn’t that
silly looking pointer sitting there. Now there is probably some check I
can do to see if the pointer is looking like I want it and if it isn’t, don’t
draw the cursor. Meaning the pointer moved outside or is over another window.
Which is what I don’t want.

Possibly regarding the cursor appearance issue–if the cursor moves over
an SDL window that doesn’t have focus, the cursor should probably stay as
the default system cursor. Because in that case if the cursor is being
rendered in software by the SDL application, you wouldn’t see anything for
that period.

I just ran an experiment with founts and it is close but I’m not happy with
how it works. If the mouse button isn’t down, the mouse movement events stop
when the SDL window is obscured by another window. If the mouse button is down,
I continue to get events even in the obscured part. And I never get events
outside the SDL window’s area.

I’d rather it work so that the SDL window gets all events all the time if
it has focus–and gets no events ever if it doesn’t have focus. And if
the mouse moves within the SDL window when it doesn’t have focus, the
pointer remains the default system pointer.
-Dave

Danny Sinclair wrote:

If you want that code I can send it over. It’s just one function -
everything can be done from a simple WM_NCHITTEST message handler.

I tried to follow with borland winsight all the messages (really too much in
win32!!!)

You should be able to filter out messages you don’t want to spy on.
Otherwise, yes, there is way too many to follow.

that occurs when the mouse enter/leave the window, but I think that
WM_NCHITTEST doesn’t work if the window isn’t the foreground window.
Maybe I’m wrong (I’m not good in win32 api programming), on monday
I’ll try it.

Ughh. I don’t know how I did it, but my code DOESN’T work at all. I must
have been testing my WM_MOUSEMOVE method. I have several different
attempts in the same file and was switching between them all night (until
6:00 in the morning). It appears that WM_NCHITTEST isn’t sent at all when
the mouse is captured. That method would have been the best. The
WM_MOUSEMOVE method is very similar, but I had to do my own bounds
checking. The problem with both of those methods was that while the mouse
is captured, certain things don’t work as usual.

The very best method would use DirectInput. SDL would have to get
background, non-exclusive access to the mouse. Every time the mouse moved,
you would check to see if it went in/out of the window and send a mouse
focus message accordingly. I don’t have the time to do that though (unless
I got paid to do it). Hey Loki guys, wanna hire me? I’m looking for a job
in Silicon valley these days (it’s too cold up here). I’ve got a good
amount of Win32/DirectX experience - I could make SDL/Win32 really shine!

Anyway, here’s my version of the WM_TIMER message handler (I’m using
message crackers):On Sun, 17 Oct 1999, Enzo wrote:


static bool m_inside = false;

static void m_OnTimer(HWND hwnd, UINT id)
{
if(id == MOUSE_FOCUS_TIMER_ID)
{
POINT mousePos;
GetCursorPos(&mousePos);

bool inside = (WindowFromPoint(mousePos) == hwnd);
if(inside)
{
  RECT clientArea;
  GetClientRect(hwnd, &clientArea);

  ScreenToClient(hwnd, &mousePos);

  inside = PtInRect(&clientArea, mousePos);
}

if(m_inside != inside)
{
  m_inside = inside;

  // Send mouse focus message here
}

}
}

In each case, SDL must be MULTI-PLATFORM, and so the sys events in win32
mode must have the same behaviour as in linux, beOS, macOS modes.
Have a look on how it works in linux mode (I think it’s the correct way).

I agree that SDL must be exactly the same on all platforms - only problem
is I don’t know how it’s supposed to work. The documentation isn’t at all
clear on several things. For example, it says mouse motion events are
generated ‘whenever the underlying window manager generates them.’ This of
course could be different on each platform.

My Linux box isn’t setup well enough for me to test anything (I’ve never
used SDL in Linux, only Windows95). Maybe you could tell me how it works
exactly.

When my window has focus, I want ALL mouse events. Not just mouse events,
ALL events!
-Dave

Keyboard focus or mouse focus? It’s treated as seperate in SDL. And by ‘I
want ALL mouse events’ do you mean mouse events that occur even when the
cursor is outside of the window?

I really wasn’t thinking of the question of what the mouse pointer should
look like.

!?! Neither was I.

If the pointer is over my window it should look like what my application
wants it to look like. If it is over another window, it should look like
what that appication wants it to look like.

I completely agree.

Regardless of how the cursor is rendered, if my application has focus, I
want mouse, keyboard, whatever events. I also want mouse movement events
even if the mouse is outside my window–I don’t want any clipping going
on, I can do that myself if I want to.

Your window should only get mouse events when the mouse is doing something
in your window. Why should your application care what the mouse is doing
in another window?

For example in the SDL version of scavenger, I turn the pointer off (the
hardware sprite pointer) and I render my own + style cursor into my
window myself. When the user moves the mouse out of the window, there is
a dangling pointer sitting there because I didn’t get mouse movement
events outside of the window. Then when I bring the pointer back into
the window the pointer will pop over to the new position. My program can
handle the clipping, I’d just like to get the mouse events outside so
there isn’t that silly looking pointer sitting there. Now there is
probably some check I can do to see if the pointer is looking like I
want it and if it isn’t, don’t draw the cursor. Meaning the pointer
moved outside or is over another window. Which is what I don’t want.

When you draw your mouse cursor, you should check if your application has
mouse focus (use SDL_GetAppState). Only draw your cursor when you have
mouse focus; you will have mouse focus only when the cursor is within your
window.

Possibly regarding the cursor appearance issue–if the cursor moves over
an SDL window that doesn’t have focus, the cursor should probably stay
as the default system cursor. Because in that case if the cursor is
being rendered in software by the SDL application, you wouldn’t see
anything for that period.

I disagree. Your custom cursor should be drawn whenever the mouse is
within your window. It just looks better that way. Of course, it may be
difficult to do it that way if you only draw your cursor when you update
the entire window.

I just ran an experiment with founts and it is close but I’m not happy
with how it works. If the mouse button isn’t down, the mouse movement
events stop when the SDL window is obscured by another window. If the
mouse button is down, I continue to get events even in the obscured
part. And I never get events outside the SDL window’s area.

I don’t like how that works either. I think that when a mouse button is
down, the cursor shouldn’t be able to move outside of the window. This
will ensure that you get all mouse button up events and you will never get
mouse move events outside of your window.

I’d rather it work so that the SDL window gets all events all the time if
it has focus–and gets no events ever if it doesn’t have focus. And if
the mouse moves within the SDL window when it doesn’t have focus, the
pointer remains the default system pointer.
-Dave

Yick. That’s not how window managers work. SDL windows should work just
like regular windows. The user really shouldn’t be able to tell the
difference.

If you want relative mouse motion, well, that’s another story. SDL doesn’t
appear to support that though.On Sun, 17 Oct 1999, Dave Ashley wrote:

Danny Sinclair wrote:

Danny Sinclair wrote:

You should be able to filter out messages you don’t want to spy on.
Otherwise, yes, there is way too many to follow.

Oh, yes, I know it, but I needed to write something bad about microsoft API.
:slight_smile:

Ughh. I don’t know how I did it, but my code DOESN’T work at all. I must
have been testing my WM_MOUSEMOVE method. I have several different
attempts in the same file and was switching between them all night (until
6:00 in the morning). It appears that WM_NCHITTEST isn’t sent at all when
the mouse is captured. That method would have been the best. The
WM_MOUSEMOVE method is very similar, but I had to do my own bounds
checking. The problem with both of those methods was that while the mouse
is captured, certain things don’t work as usual.

I tried WM_NCHITTEST too. And I’ve got only errors. :frowning:

The very best method would use DirectInput. SDL would have to get
background, non-exclusive access to the mouse. Every time the mouse moved,
you would check to see if it went in/out of the window and send a mouse
focus message accordingly.

Yes, DirectInput is surely best, and we can use it in
src/win32/directx/SDL_sysevents.c,
but SDL supports also windib for systems that don’t have directx installed.
In src/win32/windib/SDL_sysevents.c we can’t use DirectInput (maybe in this mode
timer handling is the best: it’s a little trick, but it works!).

Anyway, here’s my version of the WM_TIMER message handler (I’m using
message crackers):

Ok, thanks… I will try it… I see you optimized code,
for windib mode your code can be good enough! :slight_smile:

My Linux box isn’t setup well enough for me to test anything
(I’ve never used SDL in Linux, only Windows95).

My opinion is that development in linux is much better:
the system never crashes and debuggers are powerful !

Maybe you could tell me how it works exactly.

Uhm… I think that Sam (he’s the leader) should tell us how events must
work in ALL platforms, so developers can write the correct code.

Thanks.
Bye.
Enzo.

Oh, yes, I know it, but I needed to write something bad about microsoft API.
:slight_smile:

Now, now. No need to be mean.

Yes, DirectInput is surely best, and we can use it in
src/win32/directx/SDL_sysevents.c,
but SDL supports also windib for systems that don’t have directx installed.
In src/win32/windib/SDL_sysevents.c we can’t use DirectInput (maybe in this mode
timer handling is the best: it’s a little trick, but it works!).

Ok. I wasn’t even aware that there was two different input mechanisms. I
just thought SDL used DirectDraw/Sound when it was available and always
used Win32 calls for input. I don’t see a reason to use DirectInput unless
you’re using joysticks; you can do the same things with Win32 for mouse
and keyboard.

I guess I should look at the latest source. I haven’t played with SDL for
a long time. I got involved with this thread because I have a lot of
experience in Win32. If we can make the Win32 version of SDL really good,
more games will be ported to Linux by the people that are used to Windows.

Ok, thanks… I will try it… I see you optimized code,
for windib mode your code can be good enough! :slight_smile:

No problem. Yeah, I think that code is probably as good as it’s going to
get using the timer method - not meaning to brag :slight_smile:

My opinion is that development in linux is much better:
the system never crashes and debuggers are powerful !

My opinion too. But until a week ago I hadn’t found a text editor I could
stand using (and I’ve been looking for over a year). vi and emacs are
disgusting and most other editors emulate those two. I’m fiddling with
FTE right now, but it doesn’t work right in a 132x43 console. I’m not
using X because my Linux computer is too wimpy (and because I’m a
command-line programming guy).

Once I get an editor that I like I will probably install Linux on my main
computer and make a cross-compiler for Win32 (that’s what I program for
these days). All those nice tools; I can’t wait.

Uhm… I think that Sam (he’s the leader) should tell us how events must
work in ALL platforms, so developers can write the correct code.

The interface should have been designed and documented before each port
was created. We need a reference implementation or a 'how it should work’
paper that describes everything in detail. No one seems to agree on when
we should get something as simple as mouse move events. Maybe other people
could make a few comments?On Mon, 18 Oct 1999, Enzo wrote: