wine/windows/event.c
Alexandre Julliard 7e50df392b Release 940804
Thu Aug  4 07:18:02 1994  Michael Patra  <micky@marie.physik.tu-berlin.de>

        * [windows/message.c]
	Implemented WaitMessage() (USER.112).

        * [if1632/user.spec]
	Added WaitMessage.

	* [windows/defwnd.c]
	WM_ERASEBKGND: Added support for hbrBackground=COLOR_xxx.

   	* [miscemu/int{13,21,2a}.c]
        * [miscemu/Imakefile]
	* [signal/loader.c]
	Added a few basic disk information and diagnostic functions to
	prevent programs using this function from crashing. All drives
	are claimed to be remote ones, so direct I/O isn't allowed.

	* [controls/edit.c]
	EDIT_WriteText(): Added code to correctly erase the remaining space
	of the edit-control if the size of the control has changed sinced it's
	creation.

Tue Jul 26 22:05:54 MET DST 1994 Erik Bos <erik@hacktic.nl>

	* [if1632/mouse.spec]
	Added mouse.dll entry, no functions.

	* [loader/resource.c]
	Bug fix in AccessResource(). 

	* [misc/keyboard.c], added [include/keyboard.h]
	Changed functions to return more useful values.

	* [windows/dialog.c]
	Hacked DIALOG_GetControl() to support resources which
	have 0xff00 - 0xffff as id. ** Needs to be done properly by
	someone who knows the NE fileformat **

Jul 29, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [windows/event.c]
	Add new stub for EnableHGardwareInput() function.

	* [windows/message.c]
	Add coding for HWND_BROADCAST in PostMessage().

	* [misc/file.c]
	Add coding for OpenFile() also search in WindowPaths.

	* [misc/mmsystem.c]
	* [misc/audio.c]
	* [misc/mmaux.c]
	* [misc/mcicda.c]
	Change #include "linux/soundcard.h" by #include "sys/soundcard.h"
	Add coding in MMIO functions. Now, mmioDescend() can find WAV chunks.
	SndPlaySound & MCI_ELEMENT now use MMIO and adjust to proper formats.
1994-08-06 11:22:41 +00:00

534 lines
15 KiB
C

/*
* X events handling functions
*
* Copyright 1993 Alexandre Julliard
*/
static char Copyright[] = "Copyright Alexandre Julliard, 1993";
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <X11/Xutil.h>
#include "windows.h"
#include "win.h"
#include "class.h"
#include "message.h"
#ifdef ndef
#ifndef FamilyAmoeba
typedef char *XPointer;
#endif
#endif
#ifdef sparc
/* Dirty hack to compile with Sun's OpenWindows */
typedef char *XPointer;
#endif
#define NB_BUTTONS 3 /* Windows can handle 3 buttons */
extern int desktopX, desktopY; /* misc/main.c */
extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
/* X context to associate a hwnd to an X window */
static XContext winContext = 0;
/* State variables */
BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
BYTE KeyStateTable[256];
BYTE AsyncKeyStateTable[256];
static WORD ALTKeyState;
static HWND captureWnd = 0;
static BOOL InputEnabled = TRUE;
Window winHasCursor = 0;
/* Keyboard translation tables */
static int special_key[] =
{
VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
0, 0, 0, VK_ESCAPE /* FF18 */
};
static cursor_key[] =
{
VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
VK_NEXT, VK_END /* FF50 */
};
static misc_key[] =
{
VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
};
static keypad_key[] =
{
VK_MENU, VK_NUMLOCK, /* FF7E */
0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
VK_DECIMAL, VK_DIVIDE, /* FFA8 */
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
};
static function_key[] =
{
VK_F1, VK_F2, /* FFBE */
VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
};
static modifier_key[] =
{
VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
0, 0, /* FFE1 */
0, VK_MENU, VK_MENU /* FFE8 */
};
typedef union
{
struct
{
unsigned long count : 16;
unsigned long code : 8;
unsigned long extended : 1;
unsigned long : 4;
unsigned long context : 1;
unsigned long previous : 1;
unsigned long transition : 1;
} lp1;
unsigned long lp2;
} KEYLP;
static BOOL KeyDown = FALSE;
#ifdef DEBUG_EVENT
static char *event_names[] =
{
"", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
"MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
"KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
"CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
"ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
"ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
"SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
"ClientMessage", "MappingNotify"
};
#endif
/* Event handlers */
static void EVENT_key( HWND hwnd, XKeyEvent *event );
static void EVENT_ButtonPress( XButtonEvent *event );
static void EVENT_ButtonRelease( XButtonEvent *event );
static void EVENT_MotionNotify( XMotionEvent *event );
static void EVENT_EnterNotify( XCrossingEvent *event );
static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
/***********************************************************************
* EVENT_ProcessEvent
*
* Process an X event.
*/
void EVENT_ProcessEvent( XEvent *event )
{
HWND hwnd;
XPointer ptr;
XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
hwnd = (HWND) (int)ptr;
#ifdef DEBUG_EVENT
printf( "Got event %s for hwnd %d\n", event_names[event->type], hwnd );
#endif
switch(event->type)
{
case KeyPress:
case KeyRelease:
EVENT_key( hwnd, (XKeyEvent*)event );
break;
case ButtonPress:
EVENT_ButtonPress( (XButtonEvent*)event );
break;
case ButtonRelease:
EVENT_ButtonRelease( (XButtonEvent*)event );
break;
case MotionNotify:
/* Wine between two fast machines across the overloaded campus
ethernet gets very boged down in MotionEvents. The following
simply finds the last motion event in the queue and drops
the rest. On a good link events are servered before they build
up so this doesn't take place. On a slow link this may cause
problems if the event order is important. I'm not yet seen
of any problems. Jon 7/6/96.
*/
while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
MotionNotify, event));
EVENT_MotionNotify( (XMotionEvent*)event );
break;
case EnterNotify:
EVENT_EnterNotify( (XCrossingEvent*)event );
break;
case FocusOut:
EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
break;
case Expose:
EVENT_Expose( hwnd, (XExposeEvent*)event );
break;
case ConfigureNotify:
EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
break;
#ifdef DEBUG_EVENT
default:
printf( "Unprocessed event %s for hwnd %d\n",
event_names[event->type], hwnd );
break;
#endif
}
}
/***********************************************************************
* EVENT_RegisterWindow
*
* Associate an X window to a HWND.
*/
void EVENT_RegisterWindow( Window w, HWND hwnd )
{
if (!winContext) winContext = XUniqueContext();
XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
}
/***********************************************************************
* EVENT_XStateToKeyState
*
* Translate a X event state (Button1Mask, ShiftMask, etc...) to
* a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
*/
static WORD EVENT_XStateToKeyState( int state )
{
int kstate = 0;
if (state & Button1Mask) kstate |= MK_LBUTTON;
if (state & Button2Mask) kstate |= MK_MBUTTON;
if (state & Button3Mask) kstate |= MK_RBUTTON;
if (state & ShiftMask) kstate |= MK_SHIFT;
if (state & ControlMask) kstate |= MK_CONTROL;
return kstate;
}
/***********************************************************************
* EVENT_Expose
*/
static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
{
RECT rect;
UINT flags;
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return;
if (IsIconic(hwnd) && wndPtr->hIcon)
{
SendMessage(hwnd, WM_PAINTICON, 0, 0);
return;
}
/* Make position relative to client area instead of window */
rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
rect.right = rect.left + event->width;
rect.bottom = rect.top + event->height;
winHasCursor = event->window;
flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME;
/* Erase desktop background synchronously */
if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN;
RedrawWindow( hwnd, &rect, 0, flags );
}
/***********************************************************************
* EVENT_key
*
* Handle a X key event
*/
static void EVENT_key( HWND hwnd, XKeyEvent *event )
{
char Str[24];
XComposeStatus cs;
KeySym keysym;
WORD xkey, vkey, key_type, key;
KEYLP keylp;
BOOL extended = FALSE;
int count = XLookupString(event, Str, 1, &keysym, &cs);
Str[count] = '\0';
#ifdef DEBUG_KEY
printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
keysym, count, Str[0], Str);
#endif
xkey = LOWORD(keysym);
key_type = HIBYTE(xkey);
key = LOBYTE(xkey);
#ifdef DEBUG_KEY
printf(" key_type=%X, key=%X\n", key_type, key);
#endif
if (key_type == 0xFF) /* non-character key */
{
if (key >= 0x08 && key <= 0x1B) /* special key */
vkey = special_key[key - 0x08];
else if (key >= 0x50 && key <= 0x57) /* cursor key */
vkey = cursor_key[key - 0x50];
else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
vkey = misc_key[key - 0x60];
else if (key >= 0x7E && key <= 0xB9) /* keypad key */
{
vkey = keypad_key[key - 0x7E];
extended = TRUE;
}
else if (key >= 0xBE && key <= 0xCD) /* function key */
{
vkey = function_key[key - 0xBE];
extended = TRUE;
}
else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
vkey = modifier_key[key - 0xE1];
else if (key == 0xFF) /* DEL key */
vkey = VK_DELETE;
}
else if (key_type == 0) /* character key */
{
if (key >= 0x61 && key <= 0x7A)
vkey = key - 0x20; /* convert lower to uppercase */
else
vkey = key;
}
if (event->type == KeyPress)
{
if (vkey == VK_MENU) ALTKeyState = TRUE;
if (!(KeyStateTable[vkey] & 0x0f))
KeyStateTable[vkey] ^= 0x80;
KeyStateTable[vkey] |= 0x01;
keylp.lp1.count = 1;
keylp.lp1.code = LOBYTE(event->keycode);
keylp.lp1.extended = (extended ? 1 : 0);
keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
keylp.lp1.previous = (KeyDown ? 0 : 1);
keylp.lp1.transition = 0;
#ifdef DEBUG_KEY
printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
printf(" KeyState=%X\n", KeyStateTable[vkey]);
#endif
hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
vkey, keylp.lp2,
event->x_root - desktopX, event->y_root - desktopY,
event->time, 0 );
KeyDown = TRUE;
/* The key translation ought to take place in TranslateMessage().
* However, there is no way of passing the required information
* in a Windows message, so TranslateMessage does not currently
* do anything and the translation is done here.
*/
if (count == 1) /* key has an ASCII representation */
{
#ifdef DEBUG_KEY
printf("WM_CHAR : wParam=%X\n", (WORD)Str[0] );
#endif
PostMessage( GetFocus(), WM_CHAR, (WORD)Str[0], keylp.lp2 );
}
}
else
{
if (vkey == VK_MENU) ALTKeyState = FALSE;
KeyStateTable[vkey] &= 0xf0;
keylp.lp1.count = 1;
keylp.lp1.code = LOBYTE(event->keycode);
keylp.lp1.extended = (extended ? 1 : 0);
keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
keylp.lp1.previous = 1;
keylp.lp1.transition = 1;
#ifdef DEBUG_KEY
printf(" wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
printf(" KeyState=%X\n", KeyStateTable[vkey]);
#endif
hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
WM_SYSKEYUP : WM_KEYUP),
vkey, keylp.lp2,
event->x_root - desktopX, event->y_root - desktopY,
event->time, 0 );
KeyDown = FALSE;
}
}
/***********************************************************************
* EVENT_MotionNotify
*/
static void EVENT_MotionNotify( XMotionEvent *event )
{
hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
event->x_root - desktopX, event->y_root - desktopY,
event->time, 0 );
}
/***********************************************************************
* EVENT_ButtonPress
*/
static void EVENT_ButtonPress( XButtonEvent *event )
{
static WORD messages[NB_BUTTONS] =
{ WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
int buttonNum = event->button - 1;
if (buttonNum >= NB_BUTTONS) return;
MouseButtonsStates[buttonNum] = TRUE;
AsyncMouseButtonsStates[buttonNum] = TRUE;
winHasCursor = event->window;
hardware_event( messages[buttonNum],
EVENT_XStateToKeyState( event->state ), 0L,
event->x_root - desktopX, event->y_root - desktopY,
event->time, 0 );
}
/***********************************************************************
* EVENT_ButtonRelease
*/
static void EVENT_ButtonRelease( XButtonEvent *event )
{
static const WORD messages[NB_BUTTONS] =
{ WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
int buttonNum = event->button - 1;
if (buttonNum >= NB_BUTTONS) return;
MouseButtonsStates[buttonNum] = FALSE;
winHasCursor = event->window;
hardware_event( messages[buttonNum],
EVENT_XStateToKeyState( event->state ), 0L,
event->x_root - desktopX, event->y_root - desktopY,
event->time, 0 );
}
/**********************************************************************
* EVENT_FocusOut
*
* Note: only top-level override-redirect windows get FocusOut events.
*/
static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
{
if (event->detail == NotifyPointer) return;
if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
}
/**********************************************************************
* EVENT_EnterNotify
*/
static void EVENT_EnterNotify( XCrossingEvent *event )
{
if (captureWnd != 0) return;
winHasCursor = event->window;
}
/**********************************************************************
* EVENT_ConfigureNotify
*
* The ConfigureNotify event is only selected on the desktop window.
*/
static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
{
desktopX = event->x;
desktopY = event->y;
}
/**********************************************************************
* SetCapture (USER.18)
*/
HWND SetCapture(HWND wnd)
{
int rv;
HWND old_capture_wnd = captureWnd;
WND *wnd_p = WIN_FindWndPtr(wnd);
if (wnd_p == NULL)
return 0;
rv = XGrabPointer(display, wnd_p->window, False,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
if (rv == GrabSuccess)
{
winHasCursor = wnd_p->window;
captureWnd = wnd;
return old_capture_wnd;
}
else
return 0;
}
/**********************************************************************
* ReleaseCapture (USER.19)
*/
void ReleaseCapture()
{
if (captureWnd == 0) return;
XUngrabPointer( display, CurrentTime );
captureWnd = 0;
}
/**********************************************************************
* GetCapture (USER.236)
*/
HWND GetCapture()
{
return captureWnd;
}
/**********************************************************************
* EnableHardwareInput [USER.331]
*/
BOOL EnableHardwareInput(BOOL bEnable)
{
BOOL bOldState = InputEnabled;
printf("EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
InputEnabled = bEnable;
return (bOldState && !bEnable);
}