1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00
wine/windows/event.c
Alexandre Julliard dba420a731 Release 940201
Tue Feb  1 21:14:47 1994  Bob Amstadt  (bob@pooh)

	* [loader/selector.c]
	Added function CreateNewSegments().  Modified IPCCopySelector
	to allow aliasing to any arbitrary memory space.

	* [memory/global.c]
	Fixed potential bug in GlobalGetFreeSegments().

	* [memory/linear.c]
	Created functions GlobalLinearLock() and GlobalLinearUnlock().

Tue Feb  1 05:51:43 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [controls/widgets.c]
	Removed CAPTION window class.

	* [loader/cursor.c]
	Bug fix in LoadCursor(): don't allocate memory every time for
	built-in cursors.

	* [windows/clipping.c]
	Invalidate child windows in InvalidateRgn().

	* [windows/defwnd.c]
	Added repaint of the caption when changing window text.

	* [windows/event.c]
	Modified SetCapture() to allow keyboard events while capturing.

	* [windows/message.c]
	New function MSG_GetHardwareMessage(), to do mouse tracking
	without returning control to the Windows program.

	* [windows/nonclient.c]
	A couple of changes in frame drawing for DLGMODALFRAME windows.
	Rewritten window moving code, to use MSG_GetHardwareMessage()
	instead of non-client mouse events (this is the way Windows
	does it), and to send WM_ENTERSIZEMOVE messages.
	Removed WM_NCBUTTONUP and WM_NCMOUSEMOVE handlers.

	* [windows/win.c]
	Allocate temporary structures on the USER heap instead of
	using GlobalAlloc().

	* [windows/winpos.c]
	Added function WINPOS_GetMinMaxInfo() to get sizing informations.

Jan 31, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [windows/nonclient.c]
	Call to StdDrawScrollBar() during NC's drawing.
	Call to NC_ScrollBarButtonDown() on NC mouse events WM_LBUTTONDOWN.
	Call to NC_ScrollBarButtonUp() on NC mouse events WM_LBUTTONUP.
	Call to NC_ScrollBarMouseMove() on NC mouse events WM_MOUSEMOVE.

	* [controls/menu.c]
	New GetSubMenu() function.
	Move GetMenu() & SetMenu() functions from 'windows/win.c'.

	* [controls/listbox.c]
	Start changes to satisfy recent changes in scrollbars/windows.

	* [loader/resource.c]
	Put some code in LoadAccelerators() stub.
	New TranslateAccelerator() function.

	* [windows/win.c]
	Remove GetMenu() & SetMenu() functions.
	Call to NC_CreateScrollBars() if required by CreateWindow().

Mon Jan 24 10:40:10 EST 1994 John Richardson (jrichard@cs.uml.edu)

        * [window/win.c]
        Added functions EnumWindows, EnumChildWindows, and helper
        WIN_EnumChildWin.  EnumWindows won't list all wine windows
        because GetDesktopWindow isn't complete.  However, the code
        is in place for it to work correctly and only needs 
        GetDesktopWindow to do so.  

Tue Jan 25 05:51:47 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [windows/defwnd.c]
	Added handling of activation messages (WM_ACTIVATE,
	WM_NCACTIVATE, WM_MOUSEACTIVATE)

	* [windows/event.c]
	De-activate the window when losing input focus.

	* [windows/focus.c]
	Bug fix in SetFocus().

	* [windows/message.c]
	Added activation of the window on mouse-clicks.

	* [windows/nonclient.c]
	Changed non-client area painting to use the correct colors
	depending upon the activation state.
	Added WM_NCACTIVATE message handling.
	Fixed a couple of bugs in window moving and resizing.

	* [windows/winpos.c]
	Implemented Get/SetActiveWindow().
	Implemented SWP_NOACTIVATE flag in SetWindowPos().

Jan 17, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [misc/message.c]
	MessageBox has a CaptionBar for his title except for
		MB_SYSTEMMODAL with MB_ICONHAND.

	* [windows/nonclient.c]
	Call to NC_TrackSysMenu on SysMenu button mouse click.

	* [windows/defwnd.c]
	Call to NC_TrackSysMenu on Alt key (VK_MENU).

	* [controls/menu.c]
	New GetSystemMenu() function.
	New CopySystemMenu() internal function.
	New NC_TrackSysMenu() internal function.

	* [include/windows.h]
	New WM_INITMENU, WM_INITMENUPOPUP, WM_MENUSELECT & WM_MENUCHAR defines.
1994-02-02 06:48:31 +00:00

545 lines
15 KiB
C

/*
* X events handling functions
*
* Copyright 1993 Alexandre Julliard
*/
static char Copyright[] = "Copyright Alexandre Julliard, 1993";
#include <X11/Xlib.h>
#include "windows.h"
#include "win.h"
#include "class.h"
#include "message.h"
#define NB_BUTTONS 3 /* Windows can handle 3 buttons */
extern Display * display;
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 */
static WORD ALTKeyState;
static HWND captureWnd = 0;
Window winHasCursor = 0;
extern HWND hWndFocus;
/* 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( HWND hwnd, XButtonEvent *event );
static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event );
static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event );
static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event );
static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
static void EVENT_Expose( HWND hwnd, XExposeEvent *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( hwnd, (XButtonEvent*)event );
break;
case ButtonRelease:
EVENT_ButtonRelease( hwnd, (XButtonEvent*)event );
break;
case MotionNotify:
EVENT_MotionNotify( hwnd, (XMotionEvent*)event );
break;
case EnterNotify:
EVENT_EnterNotify( hwnd, (XCrossingEvent*)event );
break;
case FocusIn:
EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
break;
case FocusOut:
EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
break;
case Expose:
EVENT_Expose( hwnd, (XExposeEvent*)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;
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) 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;
InvalidateRect( hwnd, &rect, TRUE );
}
/***********************************************************************
* 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;
WND * wndPtr = WIN_FindWndPtr( hwnd );
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
if (wndPtr->dwStyle & WS_DISABLED) {
if (event->type == KeyPress) XBell(display, 0);
return;
}
xkey = LOWORD(keysym);
key_type = HIBYTE(xkey);
key = LOBYTE(xkey);
#ifdef DEBUG_KEY
printf(" key_type=%X, key=%X\n", key_type, key);
#endif
/* Position must be relative to client area */
event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
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;
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 );
#endif
hardware_event( hwnd, ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
vkey, keylp.lp2,
event->x_root & 0xffff, event->y_root & 0xffff,
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( hwnd, WM_CHAR, (WORD)Str[0], keylp.lp2 );
}
}
else
{
if (vkey == VK_MENU) ALTKeyState = FALSE;
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 );
#endif
hardware_event( hwnd,
((ALTKeyState || vkey == VK_MENU) ?
WM_SYSKEYUP : WM_KEYUP),
vkey, keylp.lp2,
event->x_root & 0xffff, event->y_root & 0xffff,
event->time, 0 );
KeyDown = FALSE;
}
}
/***********************************************************************
* EVENT_MotionNotify
*/
static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return;
if (wndPtr->dwStyle & WS_DISABLED) {
return;
}
hardware_event( hwnd, WM_MOUSEMOVE,
EVENT_XStateToKeyState( event->state ), 0L,
event->x_root & 0xffff, event->y_root & 0xffff,
event->time, 0 );
}
/***********************************************************************
* EVENT_ButtonPress
*/
static void EVENT_ButtonPress( HWND hwnd, XButtonEvent *event )
{
static WORD messages[NB_BUTTONS] =
{ WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
int buttonNum = event->button - 1;
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) {
printf("couldn't find window\n");
return;
}
if (wndPtr->dwStyle & WS_DISABLED) {
XBell(display, 0);
return;
}
if (buttonNum >= NB_BUTTONS) return;
winHasCursor = event->window;
hardware_event( hwnd, messages[buttonNum],
EVENT_XStateToKeyState( event->state ), 0L,
event->x_root & 0xffff, event->y_root & 0xffff,
event->time, 0 );
}
/***********************************************************************
* EVENT_ButtonRelease
*/
static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event )
{
static const WORD messages[NB_BUTTONS] =
{ WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
int buttonNum = event->button - 1;
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return;
if (wndPtr->dwStyle & WS_DISABLED) {
return;
}
if (buttonNum >= NB_BUTTONS) return;
winHasCursor = event->window;
hardware_event( hwnd, messages[buttonNum],
EVENT_XStateToKeyState( event->state ), 0L,
event->x_root & 0xffff, event->y_root & 0xffff,
event->time, 0 );
}
/**********************************************************************
* EVENT_FocusIn
*/
static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return;
if (wndPtr->dwStyle & WS_DISABLED) {
return;
}
PostMessage( hwnd, WM_SETFOCUS, hwnd, 0 );
hWndFocus = hwnd;
}
/**********************************************************************
* EVENT_FocusOut
*/
static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return;
if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
if (wndPtr->dwStyle & WS_DISABLED) {
return;
}
if (hWndFocus)
{
PostMessage( hwnd, WM_KILLFOCUS, hwnd, 0 );
hWndFocus = 0;
}
}
/**********************************************************************
* EVENT_EnterNotify
*/
static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event )
{
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return;
if (wndPtr->dwStyle & WS_DISABLED) {
return;
}
if (captureWnd != 0) return;
winHasCursor = event->window;
/* Simulate a mouse motion to set the correct cursor */
hardware_event( hwnd, WM_MOUSEMOVE,
EVENT_XStateToKeyState( event->state ), 0L,
event->x_root & 0xffff, event->y_root & 0xffff,
event->time, 0 );
}
/**********************************************************************
* 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)
{
captureWnd = wnd;
return old_capture_wnd;
}
else
return 0;
}
/**********************************************************************
* ReleaseCapture (USER.19)
*/
void ReleaseCapture()
{
WND *wnd_p;
if (captureWnd == 0)
return;
wnd_p = WIN_FindWndPtr(captureWnd);
if (wnd_p == NULL)
return;
XUngrabPointer( display, CurrentTime );
captureWnd = 0;
}
/**********************************************************************
* GetCapture (USER.236)
*/
HWND GetCapture()
{
return captureWnd;
}