2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
14 #include <sys/types.h>
16 #include <X11/keysym.h>
18 #include <X11/Xresource.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
27 #include "clipboard.h"
34 #include "registers.h"
40 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
42 /* X context to associate a hwnd to an X window */
43 static XContext winContext
= 0;
46 BOOL MouseButtonsStates
[NB_BUTTONS
];
47 BOOL AsyncMouseButtonsStates
[NB_BUTTONS
];
48 BYTE KeyStateTable
[256];
49 BYTE AsyncKeyStateTable
[256];
52 WPARAM lastEventChar
= 0; /* this will have to be changed once
53 * ToAscii starts working */
55 static HWND captureWnd
= 0;
56 static BOOL InputEnabled
= TRUE
;
58 /* Keyboard translation tables */
59 static const int special_key
[] =
61 VK_BACK
, VK_TAB
, 0, VK_CLEAR
, 0, VK_RETURN
, 0, 0, /* FF08 */
62 0, 0, 0, VK_PAUSE
, VK_SCROLL
, 0, 0, 0, /* FF10 */
63 0, 0, 0, VK_ESCAPE
/* FF18 */
66 static const int cursor_key
[] =
68 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
69 VK_NEXT
, VK_END
/* FF50 */
72 static const int misc_key
[] =
74 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
75 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
78 static const int keypad_key
[] =
80 VK_MENU
, VK_NUMLOCK
, /* FF7E */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
82 0, 0, 0, 0, 0, VK_RETURN
, 0, 0, /* FF88 */
83 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
85 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
86 0, 0, VK_MULTIPLY
, VK_ADD
, VK_SEPARATOR
, VK_SUBTRACT
,
87 VK_DECIMAL
, VK_DIVIDE
, /* FFA8 */
88 VK_NUMPAD0
, VK_NUMPAD1
, VK_NUMPAD2
, VK_NUMPAD3
, VK_NUMPAD4
,
89 VK_NUMPAD5
, VK_NUMPAD6
, VK_NUMPAD7
, /* FFB0 */
90 VK_NUMPAD8
, VK_NUMPAD9
/* FFB8 */
93 static const int function_key
[] =
95 VK_F1
, VK_F2
, /* FFBE */
96 VK_F3
, VK_F4
, VK_F5
, VK_F6
, VK_F7
, VK_F8
, VK_F9
, VK_F10
, /* FFC0 */
97 VK_F11
, VK_F12
, VK_F13
, VK_F14
, VK_F15
, VK_F16
/* FFC8 */
100 static const int modifier_key
[] =
102 VK_SHIFT
, VK_SHIFT
, VK_CONTROL
, VK_CONTROL
, VK_CAPITAL
,
104 0, VK_MENU
, VK_MENU
/* FFE8 */
111 unsigned long count
: 16;
112 unsigned long code
: 8;
113 unsigned long extended
: 1;
115 unsigned long reserved
: 2;
116 unsigned long context
: 1;
117 unsigned long previous
: 1;
118 unsigned long transition
: 1;
123 static BOOL KeyDown
= FALSE
;
125 static const char * const event_names
[] =
127 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
128 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
129 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
130 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
131 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
132 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
133 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
134 "ClientMessage", "MappingNotify"
138 static void EVENT_key( XKeyEvent
*event
);
139 static void EVENT_ButtonPress( XButtonEvent
*event
);
140 static void EVENT_ButtonRelease( XButtonEvent
*event
);
141 static void EVENT_MotionNotify( XMotionEvent
*event
);
142 static void EVENT_FocusIn( HWND hwnd
, XFocusChangeEvent
*event
);
143 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
);
144 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
);
145 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
);
146 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
);
147 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
);
148 static void EVENT_SelectionNotify( XSelectionEvent
*event
);
149 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
);
150 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
);
153 /***********************************************************************
156 * Process an X event.
158 void EVENT_ProcessEvent( XEvent
*event
)
162 if (XFindContext( display
, ((XAnyEvent
*)event
)->window
, winContext
,
163 (char **)&pWnd
) != 0)
164 return; /* Not for a registered window */
166 dprintf_event( stddeb
, "Got event %s for hwnd %04x\n",
167 event_names
[event
->type
], pWnd
->hwndSelf
);
173 EVENT_key( (XKeyEvent
*)event
);
177 EVENT_ButtonPress( (XButtonEvent
*)event
);
181 EVENT_ButtonRelease( (XButtonEvent
*)event
);
185 /* Wine between two fast machines across the overloaded campus
186 ethernet gets very boged down in MotionEvents. The following
187 simply finds the last motion event in the queue and drops
188 the rest. On a good link events are servered before they build
189 up so this doesn't take place. On a slow link this may cause
190 problems if the event order is important. I'm not yet seen
191 of any problems. Jon 7/6/96.
193 while (XCheckTypedWindowEvent(display
, ((XAnyEvent
*)event
)->window
,
194 MotionNotify
, event
));
195 EVENT_MotionNotify( (XMotionEvent
*)event
);
199 EVENT_FocusIn( pWnd
->hwndSelf
, (XFocusChangeEvent
*)event
);
203 EVENT_FocusOut( pWnd
->hwndSelf
, (XFocusChangeEvent
*)event
);
207 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
211 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
214 case ConfigureNotify
:
215 EVENT_ConfigureNotify( pWnd
->hwndSelf
, (XConfigureEvent
*)event
);
218 case SelectionRequest
:
219 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
222 case SelectionNotify
:
223 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
227 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
231 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
238 dprintf_event(stddeb
, "Unprocessed event %s for hwnd %04x\n",
239 event_names
[event
->type
], pWnd
->hwndSelf
);
245 /***********************************************************************
246 * EVENT_RegisterWindow
248 * Associate an X window to a HWND.
250 void EVENT_RegisterWindow( WND
*pWnd
)
252 if (!winContext
) winContext
= XUniqueContext();
253 XSaveContext( display
, pWnd
->window
, winContext
, (char *)pWnd
);
257 /***********************************************************************
260 * Wait for an X event, optionally sleeping until one arrives.
261 * Return TRUE if an event is pending, FALSE on timeout or error
262 * (for instance lost connection with the server).
264 BOOL
EVENT_WaitXEvent( BOOL sleep
)
267 struct timeval timeout
;
269 int fd
= ConnectionNumber(display
);
271 if (!XPending(display
))
273 LONG maxWait
= sleep
? TIMER_GetNextExpiration() : 0;
275 FD_ZERO( &read_set
);
276 FD_SET( fd
, &read_set
);
278 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
279 timeout
.tv_sec
= maxWait
/ 1000;
282 sigsetjmp(env_wait_x
, 1);
285 if (DDE_GetRemoteMessage()) {
286 while(DDE_GetRemoteMessage())
290 stop_wait_op
= STOP_WAIT_X
;
291 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
292 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1 &&
296 TIMER_ExpireTimers();
299 else stop_wait_op
= CONT
;
300 #else /* CONFIG_IPC */
301 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1)
303 /* Timeout or error */
304 TIMER_ExpireTimers();
307 #endif /* CONFIG_IPC */
311 /* Process the event (and possibly others that occurred in the meantime) */
316 if (DDE_GetRemoteMessage())
318 while(DDE_GetRemoteMessage()) ;
321 #endif /* CONFIG_IPC */
323 XNextEvent( display
, &event
);
324 EVENT_ProcessEvent( &event
);
326 while (XPending( display
));
331 /***********************************************************************
334 * Synchronize with the X server. Should not be used too often.
336 void EVENT_Synchronize()
340 XSync( display
, False
);
341 while (XPending( display
))
343 XNextEvent( display
, &event
);
344 EVENT_ProcessEvent( &event
);
349 /***********************************************************************
350 * EVENT_XStateToKeyState
352 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
353 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
355 static WORD
EVENT_XStateToKeyState( int state
)
359 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
360 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
361 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
362 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
363 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
368 /***********************************************************************
371 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
375 /* Make position relative to client area instead of window */
376 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
377 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
378 rect
.right
= rect
.left
+ event
->width
;
379 rect
.bottom
= rect
.top
+ event
->height
;
381 RedrawWindow32( pWnd
->hwndSelf
, &rect
, 0,
382 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
383 (event
->count
? 0 : RDW_ERASENOW
) );
387 /***********************************************************************
388 * EVENT_GraphicsExpose
390 * This is needed when scrolling area is partially obscured
391 * by non-Wine X window.
393 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
397 /* Make position relative to client area instead of window */
398 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
399 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
400 rect
.right
= rect
.left
+ event
->width
;
401 rect
.bottom
= rect
.top
+ event
->height
;
403 RedrawWindow32( pWnd
->hwndSelf
, &rect
, 0,
404 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
405 (event
->count
? 0 : RDW_ERASENOW
) );
409 /***********************************************************************
412 * Handle a X key event
414 static void EVENT_key( XKeyEvent
*event
)
420 WORD xkey
, key_type
, key
;
422 BOOL extended
= FALSE
;
424 int ascii_chars
= XLookupString(event
, Str
, 1, &keysym
, &cs
);
426 Str
[ascii_chars
] = '\0';
427 dprintf_key(stddeb
,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
428 keysym
, ascii_chars
, Str
[0], Str
);
430 /* Ctrl-Alt-Return enters the debugger */
431 if ((keysym
== XK_Return
) && (event
->type
== KeyPress
) &&
432 (event
->state
& ControlMask
) && (event
->state
& Mod1Mask
))
433 DEBUG_EnterDebugger();
435 xkey
= LOWORD(keysym
);
436 key_type
= HIBYTE(xkey
);
438 dprintf_key(stddeb
," key_type=%X, key=%X\n", key_type
, key
);
440 if (key_type
== 0xFF) /* non-character key */
442 if (key
>= 0x08 && key
<= 0x1B) /* special key */
443 vkey
= special_key
[key
- 0x08];
444 else if (key
>= 0x50 && key
<= 0x57) /* cursor key */
445 vkey
= cursor_key
[key
- 0x50];
446 else if (key
>= 0x60 && key
<= 0x6B) /* miscellaneous key */
447 vkey
= misc_key
[key
- 0x60];
448 else if (key
>= 0x7E && key
<= 0xB9) /* keypad key */
450 vkey
= keypad_key
[key
- 0x7E];
453 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
455 vkey
= function_key
[key
- 0xBE];
458 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
459 vkey
= modifier_key
[key
- 0xE1];
460 else if (key
== 0xFF) /* DEL key */
463 else if (key_type
== 0) /* character key */
466 vkey
= toupper(key
); /* convert lc to uc */
467 else if ( isspace(key
) )
468 vkey
= key
; /* XXX approximately */
470 switch (key
) /* the rest... */
472 #define vkcase(k,val) case k: vkey = val; break;
473 #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
475 /* I wish I had a bit-paired keyboard! */
476 vkcase('!','1'); vkcase('@','2'); vkcase('#','3');
477 vkcase('$','4'); vkcase('%','5'); vkcase('^','6');
478 vkcase('&','7'); vkcase('*','8'); vkcase('(','9');
481 vkcase2('`','~',0xc0);
482 vkcase2('-','_',0xbd);
483 vkcase2('=','+',0xbb);
484 vkcase2('[','{',0xdb);
485 vkcase2(']','}',0xdd);
486 vkcase2(';',':',0xba);
487 vkcase2('\'','\"',0xde);
488 vkcase2(',','<',0xbc);
489 vkcase2('.','>',0xbe);
490 vkcase2('/','?',0xbf);
491 vkcase2('\\','|',0xdc);
495 fprintf( stderr
, "Unknown key! Please report!\n" );
496 vkey
= 0; /* whatever */
500 if (event
->type
== KeyPress
)
502 if (!(KeyStateTable
[vkey
] & 0x80))
503 KeyStateTable
[vkey
] ^= 0x01;
504 KeyStateTable
[vkey
] |= 0x80;
506 keylp
.lp1
.code
= LOBYTE(event
->keycode
) - 8;
507 keylp
.lp1
.extended
= (extended
? 1 : 0);
508 keylp
.lp1
.reserved
= (ascii_chars
? 1 : 0);
509 keylp
.lp1
.context
= ( (event
->state
& Mod1Mask
) ||
510 (KeyStateTable
[VK_MENU
] & 0x80)) ? 1 : 0;
511 keylp
.lp1
.previous
= (KeyDown
? 0 : 1);
512 keylp
.lp1
.transition
= 0;
513 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
515 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
516 hardware_event( KeyStateTable
[VK_MENU
] & 0x80 ? WM_SYSKEYDOWN
: WM_KEYDOWN
,
518 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
522 /* Currently we use reserved field in the scan-code byte to
523 * make it possible for TranslateMessage to recognize character keys
524 * and get them from lastEventChar global variable.
526 * ToAscii should handle it.
529 if( ascii_chars
) lastEventChar
= Str
[0];
533 UINT sysKey
= KeyStateTable
[VK_MENU
];
535 KeyStateTable
[vkey
] &= ~0x80;
537 keylp
.lp1
.code
= LOBYTE(event
->keycode
) - 8;
538 keylp
.lp1
.extended
= (extended
? 1 : 0);
539 keylp
.lp1
.reserved
= 0;
540 keylp
.lp1
.context
= (event
->state
& Mod1Mask
? 1 : 0);
541 keylp
.lp1
.previous
= 1;
542 keylp
.lp1
.transition
= 1;
543 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
545 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
546 hardware_event( sysKey
& 0x80 ? WM_SYSKEYUP
: WM_KEYUP
,
548 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
555 /***********************************************************************
558 static void EVENT_MotionNotify( XMotionEvent
*event
)
560 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
561 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
566 /***********************************************************************
567 * EVENT_DummyMotionNotify
569 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
571 void EVENT_DummyMotionNotify(void)
574 int rootX
, rootY
, childX
, childY
;
577 if (XQueryPointer( display
, rootWindow
, &root
, &child
,
578 &rootX
, &rootY
, &childX
, &childY
, &state
))
580 hardware_event(WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
581 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0 );
586 /***********************************************************************
589 static void EVENT_ButtonPress( XButtonEvent
*event
)
591 static WORD messages
[NB_BUTTONS
] =
592 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
593 int buttonNum
= event
->button
- 1;
595 if (buttonNum
>= NB_BUTTONS
) return;
596 MouseButtonsStates
[buttonNum
] = 0x8000;
597 AsyncMouseButtonsStates
[buttonNum
] = 0x8000;
598 hardware_event( messages
[buttonNum
],
599 EVENT_XStateToKeyState( event
->state
), 0L,
600 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
605 /***********************************************************************
606 * EVENT_ButtonRelease
608 static void EVENT_ButtonRelease( XButtonEvent
*event
)
610 static const WORD messages
[NB_BUTTONS
] =
611 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
612 int buttonNum
= event
->button
- 1;
614 if (buttonNum
>= NB_BUTTONS
) return;
615 MouseButtonsStates
[buttonNum
] = FALSE
;
616 hardware_event( messages
[buttonNum
],
617 EVENT_XStateToKeyState( event
->state
), 0L,
618 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
623 /**********************************************************************
626 static void EVENT_FocusIn (HWND hwnd
, XFocusChangeEvent
*event
)
628 if (event
->detail
== NotifyPointer
) return;
629 if (hwnd
!= GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
630 if ((hwnd
!= GetFocus()) && !IsChild( hwnd
, GetFocus())) SetFocus( hwnd
);
634 /**********************************************************************
637 * Note: only top-level override-redirect windows get FocusOut events.
639 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
)
641 if (event
->detail
== NotifyPointer
) return;
642 if (hwnd
== GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE
);
643 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus())) SetFocus( 0 );
647 /**********************************************************************
648 * EVENT_ConfigureNotify
650 * The ConfigureNotify event is only selected on the desktop window
651 * and on top-level windows when the -managed flag is used.
653 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
)
655 /* FIXME: with -desktop xxx we get this event _before_ desktop
656 * window structure is created. WIN_GetDesktop() check is a hack.
659 if ( !WIN_GetDesktop() || hwnd
== GetDesktopWindow())
666 /* Managed window; most of this code is shamelessly
667 * stolen from SetWindowPos - FIXME: outdated
672 RECT16 newWindowRect
, newClientRect
;
673 HRGN hrgnOldPos
, hrgnNewPos
;
675 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)))
677 dprintf_event(stddeb
,"ConfigureNotify: invalid HWND %04x\n",hwnd
);
681 if (!(winpos
= SEGPTR_NEW(WINDOWPOS16
))) return;
683 /* Artificial messages - what is this for? */
684 SendMessage16(hwnd
, WM_ENTERSIZEMOVE
, 0, 0);
685 SendMessage16(hwnd
, WM_EXITSIZEMOVE
, 0, 0);
687 /* Fill WINDOWPOS struct */
688 winpos
->flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
690 winpos
->x
= event
->x
;
691 winpos
->y
= event
->y
;
692 winpos
->cx
= event
->width
;
693 winpos
->cy
= event
->height
;
695 /* Check for unchanged attributes */
696 if(winpos
->x
== wndPtr
->rectWindow
.left
&&
697 winpos
->y
== wndPtr
->rectWindow
.top
)
698 winpos
->flags
|= SWP_NOMOVE
;
699 if(winpos
->cx
== wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
&&
700 winpos
->cy
== wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
)
701 winpos
->flags
|= SWP_NOSIZE
;
703 /* Send WM_WINDOWPOSCHANGING */
704 SendMessage16(hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)SEGPTR_GET(winpos
));
706 /* Calculate new position and size */
707 newWindowRect
.left
= event
->x
;
708 newWindowRect
.right
= event
->x
+ event
->width
;
709 newWindowRect
.top
= event
->y
;
710 newWindowRect
.bottom
= event
->y
+ event
->height
;
712 WINPOS_SendNCCalcSize( winpos
->hwnd
, TRUE
, &newWindowRect
,
713 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
714 SEGPTR_GET(winpos
), &newClientRect
);
716 hrgnOldPos
= CreateRectRgnIndirect16( &wndPtr
->rectWindow
);
717 hrgnNewPos
= CreateRectRgnIndirect16( &newWindowRect
);
718 CombineRgn( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
720 /* Set new size and position */
721 wndPtr
->rectWindow
= newWindowRect
;
722 wndPtr
->rectClient
= newClientRect
;
723 SendMessage16( hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)SEGPTR_GET(winpos
));
726 /* full window drag leaves unrepainted garbage without this */
727 RedrawWindow32( 0, NULL
, hrgnOldPos
, RDW_INVALIDATE
|
728 RDW_ALLCHILDREN
| RDW_ERASE
| RDW_ERASENOW
);
729 DeleteObject(hrgnOldPos
);
730 DeleteObject(hrgnNewPos
);
735 /***********************************************************************
736 * EVENT_SelectionRequest
738 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
740 XSelectionEvent result
;
742 Window request
= event
->requestor
;
744 if(event
->target
== XA_STRING
)
749 rprop
= event
->property
;
751 if(rprop
== None
) rprop
= event
->target
;
753 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
754 else if(!CLIPBOARD_IsPresent(CF_TEXT
)) rprop
= None
;
756 /* Don't worry if we can't open */
757 BOOL couldOpen
=OpenClipboard( pWnd
->hwndSelf
);
758 hText
=GetClipboardData(CF_TEXT
);
759 text
=GlobalLock16(hText
);
760 XChangeProperty(display
,request
,rprop
,XA_STRING
,
761 8,PropModeReplace
,text
,strlen(text
));
762 GlobalUnlock16(hText
);
763 /* close only if we opened before */
764 if(couldOpen
)CloseClipboard();
769 dprintf_event(stddeb
,"Request for %s ignored\n", XGetAtomName(display
,event
->target
));
771 result
.type
=SelectionNotify
;
772 result
.display
=display
;
773 result
.requestor
=request
;
774 result
.selection
=event
->selection
;
775 result
.property
=rprop
;
776 result
.target
=event
->target
;
777 result
.time
=event
->time
;
778 XSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
782 /***********************************************************************
783 * EVENT_SelectionNotify
785 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
787 if (event
->selection
!= XA_PRIMARY
) return;
788 if (event
->target
!= XA_STRING
) CLIPBOARD_ReadSelection( 0, None
);
789 CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
793 /***********************************************************************
794 * EVENT_SelectionClear
796 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
798 if (event
->selection
!= XA_PRIMARY
) return;
799 CLIPBOARD_ReleaseSelection( pWnd
->hwndSelf
);
803 /**********************************************************************
804 * EVENT_ClientMessage
806 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
808 static Atom wmProtocols
= None
;
809 static Atom wmDeleteWindow
= None
;
811 if (wmProtocols
== None
)
812 wmProtocols
= XInternAtom( display
, "WM_PROTOCOLS", True
);
813 if (wmDeleteWindow
== None
)
814 wmDeleteWindow
= XInternAtom( display
, "WM_DELETE_WINDOW", True
);
816 if ((event
->format
!= 32) || (event
->message_type
!= wmProtocols
) ||
817 (((Atom
) event
->data
.l
[0]) != wmDeleteWindow
))
819 dprintf_event( stddeb
, "unrecognized ClientMessage\n" );
822 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
826 /**********************************************************************
827 * SetCapture (USER.18)
829 HWND
SetCapture( HWND hwnd
)
832 HWND old_capture_wnd
= captureWnd
;
837 return old_capture_wnd
;
839 if (!(win
= WIN_GetXWindow( hwnd
))) return 0;
840 if (XGrabPointer(display
, win
, False
,
841 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
842 GrabModeAsync
, GrabModeAsync
,
843 None
, None
, CurrentTime
) == GrabSuccess
)
845 dprintf_win(stddeb
, "SetCapture: %04x\n", hwnd
);
847 return old_capture_wnd
;
853 /**********************************************************************
854 * ReleaseCapture (USER.19)
856 void ReleaseCapture()
858 if (captureWnd
== 0) return;
859 XUngrabPointer( display
, CurrentTime
);
861 dprintf_win(stddeb
, "ReleaseCapture\n");
864 /**********************************************************************
865 * GetCapture (USER.236)
873 /***********************************************************************
874 * GetMouseEventProc (USER.337)
876 FARPROC16
GetMouseEventProc(void)
878 HMODULE16 hmodule
= GetModuleHandle("USER");
879 return MODULE_GetEntryPoint( hmodule
,
880 MODULE_GetOrdinal( hmodule
, "Mouse_Event" ) );
884 /***********************************************************************
885 * Mouse_Event (USER.299)
888 void Mouse_Event( SIGCONTEXT
*context
)
892 * BX = horizontal displacement if AX & ME_MOVE
893 * CX = vertical displacement if AX & ME_MOVE
894 * DX = button state (?)
895 * SI = mouse event flags (?)
898 int rootX
, rootY
, childX
, childY
;
901 if (AX_reg(context
) & ME_MOVE
)
903 /* We have to actually move the cursor */
904 XWarpPointer( display
, rootWindow
, None
, 0, 0, 0, 0,
905 (short)BX_reg(context
), (short)CX_reg(context
) );
908 if (!XQueryPointer( display
, rootWindow
, &root
, &child
,
909 &rootX
, &rootY
, &childX
, &childY
, &state
)) return;
910 if (AX_reg(context
) & ME_LDOWN
)
911 hardware_event( WM_LBUTTONDOWN
, EVENT_XStateToKeyState( state
), 0L,
912 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
913 if (AX_reg(context
) & ME_LUP
)
914 hardware_event( WM_LBUTTONUP
, EVENT_XStateToKeyState( state
), 0L,
915 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
916 if (AX_reg(context
) & ME_RDOWN
)
917 hardware_event( WM_RBUTTONDOWN
, EVENT_XStateToKeyState( state
), 0L,
918 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
919 if (AX_reg(context
) & ME_RUP
)
920 hardware_event( WM_RBUTTONUP
, EVENT_XStateToKeyState( state
), 0L,
921 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
926 /**********************************************************************
927 * EnableHardwareInput [USER.331]
929 BOOL
EnableHardwareInput(BOOL bEnable
)
931 BOOL bOldState
= InputEnabled
;
932 dprintf_event(stdnimp
,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable
);
933 InputEnabled
= bEnable
;
934 return (bOldState
&& !bEnable
);