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>
28 #include "clipboard.h"
35 #include "registers.h"
41 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
43 /* X context to associate a hwnd to an X window */
44 static XContext winContext
= 0;
47 BOOL MouseButtonsStates
[NB_BUTTONS
];
48 BOOL AsyncMouseButtonsStates
[NB_BUTTONS
];
49 BYTE KeyStateTable
[256];
50 BYTE AsyncKeyStateTable
[256];
53 WPARAM lastEventChar
= 0; /* this will have to be changed once
54 * ToAscii starts working */
56 static HWND32 captureWnd
= 0;
57 static BOOL32 InputEnabled
= TRUE
;
59 /* Keyboard translation tables */
60 static const int special_key
[] =
62 VK_BACK
, VK_TAB
, 0, VK_CLEAR
, 0, VK_RETURN
, 0, 0, /* FF08 */
63 0, 0, 0, VK_PAUSE
, VK_SCROLL
, 0, 0, 0, /* FF10 */
64 0, 0, 0, VK_ESCAPE
/* FF18 */
67 static const int cursor_key
[] =
69 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
70 VK_NEXT
, VK_END
/* FF50 */
73 static const int misc_key
[] =
75 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
76 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
79 static const int keypad_key
[] =
81 VK_MENU
, VK_NUMLOCK
, /* FF7E */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
83 0, 0, 0, 0, 0, VK_RETURN
, 0, 0, /* FF88 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
85 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
86 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
87 0, 0, VK_MULTIPLY
, VK_ADD
, VK_SEPARATOR
, VK_SUBTRACT
,
88 VK_DECIMAL
, VK_DIVIDE
, /* FFA8 */
89 VK_NUMPAD0
, VK_NUMPAD1
, VK_NUMPAD2
, VK_NUMPAD3
, VK_NUMPAD4
,
90 VK_NUMPAD5
, VK_NUMPAD6
, VK_NUMPAD7
, /* FFB0 */
91 VK_NUMPAD8
, VK_NUMPAD9
/* FFB8 */
94 static const int function_key
[] =
96 VK_F1
, VK_F2
, /* FFBE */
97 VK_F3
, VK_F4
, VK_F5
, VK_F6
, VK_F7
, VK_F8
, VK_F9
, VK_F10
, /* FFC0 */
98 VK_F11
, VK_F12
, VK_F13
, VK_F14
, VK_F15
, VK_F16
/* FFC8 */
101 static const int modifier_key
[] =
103 VK_SHIFT
, VK_SHIFT
, VK_CONTROL
, VK_CONTROL
, VK_CAPITAL
,
105 0, VK_MENU
, VK_MENU
/* FFE8 */
112 unsigned long count
: 16;
113 unsigned long code
: 8;
114 unsigned long extended
: 1;
116 unsigned long reserved
: 2;
117 unsigned long context
: 1;
118 unsigned long previous
: 1;
119 unsigned long transition
: 1;
124 static BOOL KeyDown
= FALSE
;
126 static const char * const event_names
[] =
128 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
129 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
130 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
131 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
132 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
133 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
134 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
135 "ClientMessage", "MappingNotify"
139 static void EVENT_key( XKeyEvent
*event
);
140 static void EVENT_ButtonPress( XButtonEvent
*event
);
141 static void EVENT_ButtonRelease( XButtonEvent
*event
);
142 static void EVENT_MotionNotify( XMotionEvent
*event
);
143 static void EVENT_FocusIn( HWND hwnd
, XFocusChangeEvent
*event
);
144 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
);
145 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
);
146 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
);
147 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
);
148 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
);
149 static void EVENT_SelectionNotify( XSelectionEvent
*event
);
150 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
);
151 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
);
152 static void EVENT_MapNotify( HWND hwnd
, XMapEvent
*event
);
154 /* Usable only with OLVWM - compile option perhaps?
155 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
158 /***********************************************************************
161 * Process an X event.
163 void EVENT_ProcessEvent( XEvent
*event
)
167 if (XFindContext( display
, ((XAnyEvent
*)event
)->window
, winContext
,
168 (char **)&pWnd
) != 0)
169 return; /* Not for a registered window */
171 dprintf_event( stddeb
, "Got event %s for hwnd %04x\n",
172 event_names
[event
->type
], pWnd
->hwndSelf
);
179 EVENT_key( (XKeyEvent
*)event
);
184 EVENT_ButtonPress( (XButtonEvent
*)event
);
189 EVENT_ButtonRelease( (XButtonEvent
*)event
);
193 /* Wine between two fast machines across the overloaded campus
194 ethernet gets very boged down in MotionEvents. The following
195 simply finds the last motion event in the queue and drops
196 the rest. On a good link events are servered before they build
197 up so this doesn't take place. On a slow link this may cause
198 problems if the event order is important. I'm not yet seen
199 of any problems. Jon 7/6/96.
203 while (XCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
204 MotionNotify
, event
));
205 EVENT_MotionNotify( (XMotionEvent
*)event
);
210 EVENT_FocusIn( pWnd
->hwndSelf
, (XFocusChangeEvent
*)event
);
214 EVENT_FocusOut( pWnd
->hwndSelf
, (XFocusChangeEvent
*)event
);
218 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
222 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
225 case ConfigureNotify
:
226 EVENT_ConfigureNotify( pWnd
->hwndSelf
, (XConfigureEvent
*)event
);
229 case SelectionRequest
:
230 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
233 case SelectionNotify
:
234 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
238 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
242 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
246 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
252 /* We get all these because of StructureNotifyMask. */
254 case CirculateNotify
:
262 EVENT_MapNotify( pWnd
->hwndSelf
, (XMapEvent
*)event
);
266 dprintf_event(stddeb
, "Unprocessed event %s for hwnd %04x\n",
267 event_names
[event
->type
], pWnd
->hwndSelf
);
273 /***********************************************************************
274 * EVENT_RegisterWindow
276 * Associate an X window to a HWND.
278 void EVENT_RegisterWindow( WND
*pWnd
)
280 if (!winContext
) winContext
= XUniqueContext();
281 XSaveContext( display
, pWnd
->window
, winContext
, (char *)pWnd
);
285 /***********************************************************************
288 * Wait for an X event, optionally sleeping until one arrives.
289 * Return TRUE if an event is pending, FALSE on timeout or error
290 * (for instance lost connection with the server).
292 BOOL32
EVENT_WaitXEvent( BOOL32 sleep
, BOOL32 peek
)
295 struct timeval timeout
;
297 int fd
= ConnectionNumber(display
);
299 if (!XPending(display
))
301 LONG maxWait
= sleep
? TIMER_GetNextExpiration() : 0;
303 FD_ZERO( &read_set
);
304 FD_SET( fd
, &read_set
);
306 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
307 timeout
.tv_sec
= maxWait
/ 1000;
310 sigsetjmp(env_wait_x
, 1);
313 if (DDE_GetRemoteMessage()) {
314 while(DDE_GetRemoteMessage())
318 stop_wait_op
= STOP_WAIT_X
;
319 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
320 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1 &&
324 TIMER_ExpireTimers();
327 else stop_wait_op
= CONT
;
328 #else /* CONFIG_IPC */
329 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1)
331 /* Timeout or error */
332 TIMER_ExpireTimers();
335 #endif /* CONFIG_IPC */
339 /* Process the event (and possibly others that occurred in the meantime) */
345 if (DDE_GetRemoteMessage())
347 while(DDE_GetRemoteMessage()) ;
350 #endif /* CONFIG_IPC */
352 XNextEvent( display
, &event
);
359 if( XFindContext( display
, ((XAnyEvent
*)&event
)->window
, winContext
, (char **)&pWnd
)
360 || event
.type
== NoExpose
)
363 /* check for the "safe" hardware events */
365 if( event
.type
== MotionNotify
||
366 event
.type
== ButtonPress
|| event
.type
== ButtonRelease
||
367 event
.type
== KeyPress
|| event
.type
== KeyRelease
||
368 event
.type
== SelectionRequest
|| event
.type
== SelectionClear
)
370 EVENT_ProcessEvent( &event
);
375 if( (pQ
= (MESSAGEQUEUE
*)GlobalLock16(pWnd
->hmemTaskQ
)) )
377 pQ
->flags
|= QUEUE_FLAG_XEVENT
;
378 PostEvent(pQ
->hTask
);
379 XPutBackEvent(display
, &event
);
384 EVENT_ProcessEvent( &event
);
386 while (XPending( display
));
391 /***********************************************************************
394 * Synchronize with the X server. Should not be used too often.
396 void EVENT_Synchronize()
400 XSync( display
, False
);
401 while (XPending( display
))
403 XNextEvent( display
, &event
);
404 EVENT_ProcessEvent( &event
);
409 /***********************************************************************
410 * EVENT_XStateToKeyState
412 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
413 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
415 static WORD
EVENT_XStateToKeyState( int state
)
419 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
420 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
421 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
422 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
423 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
428 /***********************************************************************
431 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
435 /* Make position relative to client area instead of window */
436 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
437 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
438 rect
.right
= rect
.left
+ event
->width
;
439 rect
.bottom
= rect
.top
+ event
->height
;
441 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
442 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
443 (event
->count
? 0 : RDW_ERASENOW
), 0 );
447 /***********************************************************************
448 * EVENT_GraphicsExpose
450 * This is needed when scrolling area is partially obscured
451 * by non-Wine X window.
453 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
457 /* Make position relative to client area instead of window */
458 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
459 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
460 rect
.right
= rect
.left
+ event
->width
;
461 rect
.bottom
= rect
.top
+ event
->height
;
463 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
464 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
465 (event
->count
? 0 : RDW_ERASENOW
), 0 );
469 /***********************************************************************
472 * Handle a X key event
474 static void EVENT_key( XKeyEvent
*event
)
480 WORD xkey
, key_type
, key
;
482 BOOL extended
= FALSE
;
484 int ascii_chars
= XLookupString(event
, Str
, 1, &keysym
, &cs
);
486 Str
[ascii_chars
] = '\0';
487 dprintf_key(stddeb
,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
488 keysym
, ascii_chars
, Str
[0], Str
);
490 /* Ctrl-Alt-Return enters the debugger */
491 if ((keysym
== XK_Return
) && (event
->type
== KeyPress
) &&
492 (event
->state
& ControlMask
) && (event
->state
& Mod1Mask
))
493 DEBUG_EnterDebugger();
495 xkey
= LOWORD(keysym
);
496 key_type
= HIBYTE(xkey
);
498 dprintf_key(stddeb
," key_type=%X, key=%X\n", key_type
, key
);
500 if (key_type
== 0xFF) /* non-character key */
502 if (key
>= 0x08 && key
<= 0x1B) /* special key */
503 vkey
= special_key
[key
- 0x08];
504 else if (key
>= 0x50 && key
<= 0x57) /* cursor key */
505 vkey
= cursor_key
[key
- 0x50];
506 else if (key
>= 0x60 && key
<= 0x6B) /* miscellaneous key */
507 vkey
= misc_key
[key
- 0x60];
508 else if (key
>= 0x7E && key
<= 0xB9) /* keypad key */
510 vkey
= keypad_key
[key
- 0x7E];
513 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
515 vkey
= function_key
[key
- 0xBE];
518 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
519 vkey
= modifier_key
[key
- 0xE1];
520 else if (key
== 0xFF) /* DEL key */
523 else if (key_type
== 0) /* character key */
526 vkey
= toupper(key
); /* convert lc to uc */
527 else if ( isspace(key
) )
528 vkey
= key
; /* XXX approximately */
530 switch (key
) /* the rest... */
532 #define vkcase(k,val) case k: vkey = val; break;
533 #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
535 /* I wish I had a bit-paired keyboard! */
536 vkcase('!','1'); vkcase('@','2'); vkcase('#','3');
537 vkcase('$','4'); vkcase('%','5'); vkcase('^','6');
538 vkcase('&','7'); vkcase('*','8'); vkcase('(','9');
541 vkcase2('`','~',0xc0);
542 vkcase2('-','_',0xbd);
543 vkcase2('=','+',0xbb);
544 vkcase2('[','{',0xdb);
545 vkcase2(']','}',0xdd);
546 vkcase2(';',':',0xba);
547 vkcase2('\'','\"',0xde);
548 vkcase2(',','<',0xbc);
549 vkcase2('.','>',0xbe);
550 vkcase2('/','?',0xbf);
551 vkcase2('\\','|',0xdc);
555 fprintf( stderr
, "Unknown key! Please report!\n" );
556 vkey
= 0; /* whatever */
560 if (event
->type
== KeyPress
)
562 if (!(KeyStateTable
[vkey
] & 0x80))
563 KeyStateTable
[vkey
] ^= 0x01;
564 KeyStateTable
[vkey
] |= 0x80;
566 keylp
.lp1
.code
= LOBYTE(event
->keycode
) - 8;
567 keylp
.lp1
.extended
= (extended
? 1 : 0);
568 keylp
.lp1
.reserved
= (ascii_chars
? 1 : 0);
569 keylp
.lp1
.context
= ( (event
->state
& Mod1Mask
) ||
570 (KeyStateTable
[VK_MENU
] & 0x80)) ? 1 : 0;
571 keylp
.lp1
.previous
= (KeyDown
? 0 : 1);
572 keylp
.lp1
.transition
= 0;
573 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
575 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
576 hardware_event( KeyStateTable
[VK_MENU
] & 0x80 ? WM_SYSKEYDOWN
: WM_KEYDOWN
,
578 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
579 event
->time
- MSG_WineStartTicks
, 0 );
582 /* Currently we use reserved field in the scan-code byte to
583 * make it possible for TranslateMessage to recognize character keys
584 * and get them from lastEventChar global variable.
586 * ToAscii should handle it.
589 if( ascii_chars
) lastEventChar
= Str
[0];
593 UINT sysKey
= KeyStateTable
[VK_MENU
];
595 KeyStateTable
[vkey
] &= ~0x80;
597 keylp
.lp1
.code
= LOBYTE(event
->keycode
) - 8;
598 keylp
.lp1
.extended
= (extended
? 1 : 0);
599 keylp
.lp1
.reserved
= 0;
600 keylp
.lp1
.context
= (event
->state
& Mod1Mask
? 1 : 0);
601 keylp
.lp1
.previous
= 1;
602 keylp
.lp1
.transition
= 1;
603 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
605 dprintf_key(stddeb
," KeyState=%X\n", KeyStateTable
[vkey
]);
606 hardware_event( sysKey
& 0x80 ? WM_SYSKEYUP
: WM_KEYUP
,
608 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
609 event
->time
- MSG_WineStartTicks
, 0 );
615 /***********************************************************************
618 static void EVENT_MotionNotify( XMotionEvent
*event
)
620 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
621 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
622 event
->time
- MSG_WineStartTicks
, 0 );
626 /***********************************************************************
627 * EVENT_DummyMotionNotify
629 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
631 void EVENT_DummyMotionNotify(void)
634 int rootX
, rootY
, childX
, childY
;
637 if (XQueryPointer( display
, rootWindow
, &root
, &child
,
638 &rootX
, &rootY
, &childX
, &childY
, &state
))
640 hardware_event(WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
641 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0 );
646 /***********************************************************************
649 static void EVENT_ButtonPress( XButtonEvent
*event
)
651 static WORD messages
[NB_BUTTONS
] =
652 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
653 int buttonNum
= event
->button
- 1;
655 if (buttonNum
>= NB_BUTTONS
) return;
656 MouseButtonsStates
[buttonNum
] = 0x8000;
657 AsyncMouseButtonsStates
[buttonNum
] = 0x8000;
658 hardware_event( messages
[buttonNum
],
659 EVENT_XStateToKeyState( event
->state
), 0L,
660 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
661 event
->time
- MSG_WineStartTicks
, 0 );
665 /***********************************************************************
666 * EVENT_ButtonRelease
668 static void EVENT_ButtonRelease( XButtonEvent
*event
)
670 static const WORD messages
[NB_BUTTONS
] =
671 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
672 int buttonNum
= event
->button
- 1;
674 if (buttonNum
>= NB_BUTTONS
) return;
675 MouseButtonsStates
[buttonNum
] = FALSE
;
676 hardware_event( messages
[buttonNum
],
677 EVENT_XStateToKeyState( event
->state
), 0L,
678 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
679 event
->time
- MSG_WineStartTicks
, 0 );
683 /**********************************************************************
686 static void EVENT_FocusIn (HWND hwnd
, XFocusChangeEvent
*event
)
688 if (event
->detail
== NotifyPointer
) return;
689 if (hwnd
!= GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
690 if ((hwnd
!= GetFocus32()) && !IsChild( hwnd
, GetFocus32()))
695 /**********************************************************************
698 * Note: only top-level override-redirect windows get FocusOut events.
700 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
)
702 if (event
->detail
== NotifyPointer
) return;
703 if (hwnd
== GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE
);
704 if ((hwnd
== GetFocus32()) || IsChild( hwnd
, GetFocus32()))
709 /**********************************************************************
710 * EVENT_ConfigureNotify
712 * The ConfigureNotify event is only selected on the desktop window
713 * and on top-level windows when the -managed flag is used.
715 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
)
717 /* FIXME: with -desktop xxx we get this event _before_ desktop
718 * window structure is created. WIN_GetDesktop() check is a hack.
721 if ( !WIN_GetDesktop() || hwnd
== GetDesktopWindow32())
730 RECT16 newWindowRect
, newClientRect
;
731 HRGN hrgnOldPos
, hrgnNewPos
;
733 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)) ||
734 !(wndPtr
->flags
& WIN_MANAGED
) )
737 if (!(winpos
= SEGPTR_NEW(WINDOWPOS16
))) return;
739 /* XTranslateCoordinates(display, event->window, rootWindow,
740 event->x, event->y, &event->x, &event->y, &child);
743 /* Fill WINDOWPOS struct */
744 winpos
->flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
746 winpos
->x
= event
->x
;
747 winpos
->y
= event
->y
;
748 winpos
->cx
= event
->width
;
749 winpos
->cy
= event
->height
;
751 /* Check for unchanged attributes */
752 if(winpos
->x
== wndPtr
->rectWindow
.left
&&
753 winpos
->y
== wndPtr
->rectWindow
.top
)
754 winpos
->flags
|= SWP_NOMOVE
;
755 if(winpos
->cx
== wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
&&
756 winpos
->cy
== wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
)
757 winpos
->flags
|= SWP_NOSIZE
;
759 /* Send WM_WINDOWPOSCHANGING */
760 SendMessage16(hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)SEGPTR_GET(winpos
));
762 /* Calculate new position and size */
763 newWindowRect
.left
= event
->x
;
764 newWindowRect
.right
= event
->x
+ event
->width
;
765 newWindowRect
.top
= event
->y
;
766 newWindowRect
.bottom
= event
->y
+ event
->height
;
768 WINPOS_SendNCCalcSize( winpos
->hwnd
, TRUE
, &newWindowRect
,
769 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
770 SEGPTR_GET(winpos
), &newClientRect
);
772 hrgnOldPos
= CreateRectRgnIndirect16( &wndPtr
->rectWindow
);
773 hrgnNewPos
= CreateRectRgnIndirect16( &newWindowRect
);
774 CombineRgn( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
776 /* Set new size and position */
777 wndPtr
->rectWindow
= newWindowRect
;
778 wndPtr
->rectClient
= newClientRect
;
779 SendMessage16( hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)SEGPTR_GET(winpos
));
782 /* full window drag leaves unrepainted garbage without this */
783 PAINT_RedrawWindow( 0, NULL
, hrgnOldPos
, RDW_INVALIDATE
|
784 RDW_ALLCHILDREN
| RDW_ERASE
| RDW_ERASENOW
,
786 DeleteObject(hrgnOldPos
);
787 DeleteObject(hrgnNewPos
);
792 /***********************************************************************
793 * EVENT_SelectionRequest
795 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
797 XSelectionEvent result
;
799 Window request
= event
->requestor
;
801 if(event
->target
== XA_STRING
)
807 rprop
= event
->property
;
809 if(rprop
== None
) rprop
= event
->target
;
811 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
812 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT
)) rprop
= None
;
815 /* open to make sure that clipboard is available */
817 BOOL couldOpen
= OpenClipboard( pWnd
->hwndSelf
);
820 hText
= GetClipboardData(CF_TEXT
);
821 text
= GlobalLock16(hText
);
822 size
= GlobalSize16(hText
);
824 /* remove carriage returns */
826 lpstr
= (char*)xmalloc(size
--);
827 for(i
=0,j
=0; i
< size
; i
++ )
829 if( text
[i
] == '\r' && text
[i
+1] == '\n' ) continue;
830 lpstr
[j
++] = text
[i
];
831 if( text
[i
] == '\0' ) break;
835 XChangeProperty(display
, request
, rprop
,
836 XA_STRING
, 8, PropModeReplace
,
840 /* close only if we opened before */
842 if(couldOpen
) CloseClipboard();
847 dprintf_event(stddeb
,"Request for %s ignored\n", XGetAtomName(display
,event
->target
));
849 result
.type
=SelectionNotify
;
850 result
.display
=display
;
851 result
.requestor
=request
;
852 result
.selection
=event
->selection
;
853 result
.property
=rprop
;
854 result
.target
=event
->target
;
855 result
.time
=event
->time
;
856 XSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
860 /***********************************************************************
861 * EVENT_SelectionNotify
863 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
865 if (event
->selection
!= XA_PRIMARY
) return;
867 if (event
->target
!= XA_STRING
) CLIPBOARD_ReadSelection( 0, None
);
868 else CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
870 dprintf_clipboard(stddeb
,"\tSelectionNotify done!\n");
874 /***********************************************************************
875 * EVENT_SelectionClear
877 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
879 if (event
->selection
!= XA_PRIMARY
) return;
880 CLIPBOARD_ReleaseSelection( event
->window
, pWnd
->hwndSelf
);
884 /**********************************************************************
885 * EVENT_ClientMessage
887 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
889 static Atom wmProtocols
= None
;
890 static Atom wmDeleteWindow
= None
;
892 if (wmProtocols
== None
)
893 wmProtocols
= XInternAtom( display
, "WM_PROTOCOLS", True
);
894 if (wmDeleteWindow
== None
)
895 wmDeleteWindow
= XInternAtom( display
, "WM_DELETE_WINDOW", True
);
897 if ((event
->format
!= 32) || (event
->message_type
!= wmProtocols
) ||
898 (((Atom
) event
->data
.l
[0]) != wmDeleteWindow
))
900 dprintf_event( stddeb
, "unrecognized ClientMessage\n" );
903 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
906 /**********************************************************************
909 * Install colormap when Wine window is focused in
910 * self-managed mode with private colormap
913 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
915 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
916 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
917 XInstallColormap( display, COLOR_GetColormap() );
921 extern void FOCUS_SetXFocus( HWND32
);
923 /**********************************************************************
926 void EVENT_MapNotify( HWND hWnd
, XMapEvent
*event
)
928 HWND32 hwndFocus
= GetFocus32();
930 if (hwndFocus
&& IsChild( hWnd
, hwndFocus
))
931 FOCUS_SetXFocus( (HWND32
)hwndFocus
);
937 /**********************************************************************
938 * SetCapture16 (USER.18)
940 HWND16
SetCapture16( HWND16 hwnd
)
942 return (HWND16
)SetCapture32( hwnd
);
946 /**********************************************************************
947 * SetCapture32 (USER32.463)
949 HWND32
SetCapture32( HWND32 hwnd
)
952 HWND32 old_capture_wnd
= captureWnd
;
957 return old_capture_wnd
;
959 if (!(win
= WIN_GetXWindow( hwnd
))) return 0;
960 if (XGrabPointer(display
, win
, False
,
961 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
962 GrabModeAsync
, GrabModeAsync
,
963 None
, None
, CurrentTime
) == GrabSuccess
)
965 dprintf_win(stddeb
, "SetCapture: %04x\n", hwnd
);
967 return old_capture_wnd
;
973 /**********************************************************************
974 * ReleaseCapture (USER.19) (USER32.438)
976 void ReleaseCapture(void)
978 if (captureWnd
== 0) return;
979 XUngrabPointer( display
, CurrentTime
);
981 dprintf_win(stddeb
, "ReleaseCapture\n");
985 /**********************************************************************
986 * GetCapture16 (USER.236)
988 HWND16
GetCapture16(void)
990 return (HWND16
)captureWnd
;
994 /**********************************************************************
995 * GetCapture32 (USER32.207)
997 HWND32
GetCapture32(void)
1003 /***********************************************************************
1004 * GetMouseEventProc (USER.337)
1006 FARPROC16
GetMouseEventProc(void)
1008 HMODULE16 hmodule
= GetModuleHandle("USER");
1009 return MODULE_GetEntryPoint( hmodule
,
1010 MODULE_GetOrdinal( hmodule
, "Mouse_Event" ) );
1014 /***********************************************************************
1015 * Mouse_Event (USER.299)
1018 void Mouse_Event( SIGCONTEXT
*context
)
1022 * BX = horizontal displacement if AX & ME_MOVE
1023 * CX = vertical displacement if AX & ME_MOVE
1024 * DX = button state (?)
1025 * SI = mouse event flags (?)
1028 int rootX
, rootY
, childX
, childY
;
1031 if (AX_reg(context
) & ME_MOVE
)
1033 /* We have to actually move the cursor */
1034 XWarpPointer( display
, rootWindow
, None
, 0, 0, 0, 0,
1035 (short)BX_reg(context
), (short)CX_reg(context
) );
1038 if (!XQueryPointer( display
, rootWindow
, &root
, &child
,
1039 &rootX
, &rootY
, &childX
, &childY
, &state
)) return;
1040 if (AX_reg(context
) & ME_LDOWN
)
1041 hardware_event( WM_LBUTTONDOWN
, EVENT_XStateToKeyState( state
), 0L,
1042 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1043 if (AX_reg(context
) & ME_LUP
)
1044 hardware_event( WM_LBUTTONUP
, EVENT_XStateToKeyState( state
), 0L,
1045 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1046 if (AX_reg(context
) & ME_RDOWN
)
1047 hardware_event( WM_RBUTTONDOWN
, EVENT_XStateToKeyState( state
), 0L,
1048 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1049 if (AX_reg(context
) & ME_RUP
)
1050 hardware_event( WM_RBUTTONUP
, EVENT_XStateToKeyState( state
), 0L,
1051 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1056 /**********************************************************************
1057 * EnableHardwareInput (USER.331)
1059 BOOL16
EnableHardwareInput(BOOL16 bEnable
)
1061 BOOL16 bOldState
= InputEnabled
;
1062 dprintf_event(stdnimp
,"EnableHardwareInput(%d);\n", bEnable
);
1063 InputEnabled
= bEnable
;