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"
38 #include "registers.h"
46 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
48 #define DndNotDnd -1 /* OffiX drag&drop */
60 /* X context to associate a hwnd to an X window */
61 static XContext winContext
= 0;
64 BOOL MouseButtonsStates
[NB_BUTTONS
];
65 BOOL AsyncMouseButtonsStates
[NB_BUTTONS
];
66 BYTE InputKeyStateTable
[256];
69 static HWND32 captureWnd
= 0;
70 static BOOL32 InputEnabled
= TRUE
;
72 /* Keyboard translation tables */
73 static const int special_key
[] =
75 VK_BACK
, VK_TAB
, 0, VK_CLEAR
, 0, VK_RETURN
, 0, 0, /* FF08 */
76 0, 0, 0, VK_PAUSE
, VK_SCROLL
, 0, 0, 0, /* FF10 */
77 0, 0, 0, VK_ESCAPE
/* FF18 */
80 static const int cursor_key
[] =
82 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
83 VK_NEXT
, VK_END
/* FF50 */
86 static const int misc_key
[] =
88 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
89 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
92 static const int keypad_key
[] =
94 VK_MENU
, VK_NUMLOCK
, /* FF7E */
95 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
96 0, 0, 0, 0, 0, VK_RETURN
, 0, 0, /* FF88 */
97 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
98 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
99 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
100 0, 0, VK_MULTIPLY
, VK_ADD
, VK_SEPARATOR
, VK_SUBTRACT
,
101 VK_DECIMAL
, VK_DIVIDE
, /* FFA8 */
102 VK_NUMPAD0
, VK_NUMPAD1
, VK_NUMPAD2
, VK_NUMPAD3
, VK_NUMPAD4
,
103 VK_NUMPAD5
, VK_NUMPAD6
, VK_NUMPAD7
, /* FFB0 */
104 VK_NUMPAD8
, VK_NUMPAD9
/* FFB8 */
107 static const int function_key
[] =
109 VK_F1
, VK_F2
, /* FFBE */
110 VK_F3
, VK_F4
, VK_F5
, VK_F6
, VK_F7
, VK_F8
, VK_F9
, VK_F10
, /* FFC0 */
111 VK_F11
, VK_F12
, VK_F13
, VK_F14
, VK_F15
, VK_F16
/* FFC8 */
114 static const int modifier_key
[] =
116 VK_SHIFT
, VK_SHIFT
, VK_CONTROL
, VK_CONTROL
, VK_CAPITAL
,
118 0, VK_MENU
, VK_MENU
/* FFE8 */
125 unsigned long count
: 16;
126 unsigned long code
: 8;
127 unsigned long extended
: 1;
128 unsigned long unused
: 2;
129 unsigned long win_internal
: 2;
130 unsigned long context
: 1;
131 unsigned long previous
: 1;
132 unsigned long transition
: 1;
137 static BOOL KeyDown
= FALSE
;
139 static Atom wmProtocols
= None
;
140 static Atom wmDeleteWindow
= None
;
141 static Atom dndProtocol
= None
;
142 static Atom dndSelection
= None
;
144 static const char * const event_names
[] =
146 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
147 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
148 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
149 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
150 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
151 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
152 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
153 "ClientMessage", "MappingNotify"
157 static void EVENT_key( XKeyEvent
*event
);
158 static void EVENT_ButtonPress( XButtonEvent
*event
);
159 static void EVENT_ButtonRelease( XButtonEvent
*event
);
160 static void EVENT_MotionNotify( XMotionEvent
*event
);
161 static void EVENT_FocusIn( HWND hwnd
, XFocusChangeEvent
*event
);
162 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
);
163 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
);
164 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
);
165 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
);
166 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
);
167 static void EVENT_SelectionNotify( XSelectionEvent
*event
);
168 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
);
169 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
);
170 static void EVENT_MapNotify( HWND hwnd
, XMapEvent
*event
);
172 /* Usable only with OLVWM - compile option perhaps?
173 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
176 extern void FOCUS_SetXFocus( HWND32
);
177 extern BOOL16
DRAG_QueryUpdate( HWND
, SEGPTR
, BOOL32
);
179 /***********************************************************************
182 * Process an X event.
184 void EVENT_ProcessEvent( XEvent
*event
)
188 if (XFindContext( display
, event
->xany
.window
, winContext
,
189 (char **)&pWnd
) != 0)
190 return; /* Not for a registered window */
192 dprintf_event( stddeb
, "Got event %s for hwnd %04x\n",
193 event_names
[event
->type
], pWnd
->hwndSelf
);
200 EVENT_key( (XKeyEvent
*)event
);
205 EVENT_ButtonPress( (XButtonEvent
*)event
);
210 EVENT_ButtonRelease( (XButtonEvent
*)event
);
214 /* Wine between two fast machines across the overloaded campus
215 ethernet gets very boged down in MotionEvents. The following
216 simply finds the last motion event in the queue and drops
217 the rest. On a good link events are servered before they build
218 up so this doesn't take place. On a slow link this may cause
219 problems if the event order is important. I'm not yet seen
220 of any problems. Jon 7/6/96.
224 while (XCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
225 MotionNotify
, event
));
226 EVENT_MotionNotify( (XMotionEvent
*)event
);
231 EVENT_FocusIn( pWnd
->hwndSelf
, (XFocusChangeEvent
*)event
);
235 EVENT_FocusOut( pWnd
->hwndSelf
, (XFocusChangeEvent
*)event
);
239 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
243 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
246 case ConfigureNotify
:
247 EVENT_ConfigureNotify( pWnd
->hwndSelf
, (XConfigureEvent
*)event
);
250 case SelectionRequest
:
251 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
254 case SelectionNotify
:
255 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
259 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
263 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
267 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
273 /* We get all these because of StructureNotifyMask. */
275 case CirculateNotify
:
283 EVENT_MapNotify( pWnd
->hwndSelf
, (XMapEvent
*)event
);
287 dprintf_event(stddeb
, "Unprocessed event %s for hwnd %04x\n",
288 event_names
[event
->type
], pWnd
->hwndSelf
);
294 /***********************************************************************
295 * EVENT_RegisterWindow
297 * Associate an X window to a HWND.
299 void EVENT_RegisterWindow( WND
*pWnd
)
301 if (wmProtocols
== None
)
302 wmProtocols
= XInternAtom( display
, "WM_PROTOCOLS", True
);
303 if (wmDeleteWindow
== None
)
304 wmDeleteWindow
= XInternAtom( display
, "WM_DELETE_WINDOW", True
);
305 if( dndProtocol
== None
)
306 dndProtocol
= XInternAtom( display
, "DndProtocol" , False
);
307 if( dndSelection
== None
)
308 dndSelection
= XInternAtom( display
, "DndSelection" , False
);
310 XSetWMProtocols( display
, pWnd
->window
, &wmDeleteWindow
, 1 );
312 if (!winContext
) winContext
= XUniqueContext();
313 XSaveContext( display
, pWnd
->window
, winContext
, (char *)pWnd
);
316 /***********************************************************************
317 * EVENT_DestroyWindow
319 void EVENT_DestroyWindow( WND
*pWnd
)
323 XDeleteContext( display
, pWnd
->window
, winContext
);
324 XDestroyWindow( display
, pWnd
->window
);
325 while( XCheckWindowEvent(display
, pWnd
->window
, NoEventMask
, &xe
) );
328 /***********************************************************************
331 * Wait for an X event, optionally sleeping until one arrives.
332 * Return TRUE if an event is pending, FALSE on timeout or error
333 * (for instance lost connection with the server).
335 BOOL32
EVENT_WaitXEvent( BOOL32 sleep
, BOOL32 peek
)
338 LONG maxWait
= sleep
? TIMER_GetNextExpiration() : 0;
340 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
341 * in this case, we fall through directly to the XNextEvent loop.
344 if ((maxWait
!= -1) && !XPending(display
))
347 struct timeval timeout
;
348 int fd
= ConnectionNumber(display
);
350 FD_ZERO( &read_set
);
351 FD_SET( fd
, &read_set
);
353 timeout
.tv_usec
= (maxWait
% 1000) * 1000;
354 timeout
.tv_sec
= maxWait
/ 1000;
357 sigsetjmp(env_wait_x
, 1);
360 if (DDE_GetRemoteMessage()) {
361 while(DDE_GetRemoteMessage())
365 stop_wait_op
= STOP_WAIT_X
;
366 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
367 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1 &&
371 TIMER_ExpireTimers();
374 else stop_wait_op
= CONT
;
375 #else /* CONFIG_IPC */
376 if (select( fd
+1, &read_set
, NULL
, NULL
, &timeout
) != 1)
378 /* Timeout or error */
379 TIMER_ExpireTimers();
382 #endif /* CONFIG_IPC */
386 /* Process the event (and possibly others that occurred in the meantime) */
392 if (DDE_GetRemoteMessage())
394 while(DDE_GetRemoteMessage()) ;
397 #endif /* CONFIG_IPC */
399 XNextEvent( display
, &event
);
406 if (XFindContext( display
, ((XAnyEvent
*)&event
)->window
, winContext
,
407 (char **)&pWnd
) || (event
.type
== NoExpose
))
410 /* check for the "safe" hardware events */
412 if( event
.type
== MotionNotify
||
413 event
.type
== ButtonPress
|| event
.type
== ButtonRelease
||
414 event
.type
== KeyPress
|| event
.type
== KeyRelease
||
415 event
.type
== SelectionRequest
|| event
.type
== SelectionClear
)
417 EVENT_ProcessEvent( &event
);
422 if( (pQ
= (MESSAGEQUEUE
*)GlobalLock16(pWnd
->hmemTaskQ
)) )
424 pQ
->flags
|= QUEUE_FLAG_XEVENT
;
425 PostEvent(pQ
->hTask
);
426 XPutBackEvent(display
, &event
);
431 EVENT_ProcessEvent( &event
);
433 while (XPending( display
));
438 /***********************************************************************
441 * Synchronize with the X server. Should not be used too often.
443 void EVENT_Synchronize()
447 XSync( display
, False
);
448 while (XPending( display
))
450 XNextEvent( display
, &event
);
451 EVENT_ProcessEvent( &event
);
456 /***********************************************************************
457 * EVENT_XStateToKeyState
459 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
460 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
462 static WORD
EVENT_XStateToKeyState( int state
)
466 if (state
& Button1Mask
) kstate
|= MK_LBUTTON
;
467 if (state
& Button2Mask
) kstate
|= MK_MBUTTON
;
468 if (state
& Button3Mask
) kstate
|= MK_RBUTTON
;
469 if (state
& ShiftMask
) kstate
|= MK_SHIFT
;
470 if (state
& ControlMask
) kstate
|= MK_CONTROL
;
475 /***********************************************************************
478 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
482 /* Make position relative to client area instead of window */
483 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
484 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
485 rect
.right
= rect
.left
+ event
->width
;
486 rect
.bottom
= rect
.top
+ event
->height
;
488 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
489 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
|
490 (event
->count
? 0 : RDW_ERASENOW
), 0 );
494 /***********************************************************************
495 * EVENT_GraphicsExpose
497 * This is needed when scrolling area is partially obscured
498 * by non-Wine X window.
500 static void EVENT_GraphicsExpose( WND
*pWnd
, XGraphicsExposeEvent
*event
)
504 /* Make position relative to client area instead of window */
505 rect
.left
= event
->x
- (pWnd
->rectClient
.left
- pWnd
->rectWindow
.left
);
506 rect
.top
= event
->y
- (pWnd
->rectClient
.top
- pWnd
->rectWindow
.top
);
507 rect
.right
= rect
.left
+ event
->width
;
508 rect
.bottom
= rect
.top
+ event
->height
;
510 PAINT_RedrawWindow( pWnd
->hwndSelf
, &rect
, 0,
511 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
|
512 (event
->count
? 0 : RDW_ERASENOW
), 0 );
516 /***********************************************************************
519 * Handle a X key event
521 static void EVENT_key( XKeyEvent
*event
)
527 WORD xkey
, key_type
, key
;
529 BOOL extended
= FALSE
;
531 int ascii_chars
= XLookupString(event
, Str
, 1, &keysym
, &cs
);
533 Str
[ascii_chars
] = '\0';
538 ksname
= XKeysymToString(keysym
);
541 fprintf(stddeb
, "WM_KEY??? : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
542 keysym
, ksname
, ascii_chars
, Str
[0], Str
);
545 /* Ctrl-Alt-Return enters the debugger */
546 if ((keysym
== XK_Return
) && (event
->type
== KeyPress
) &&
547 (event
->state
& ControlMask
) && (event
->state
& Mod1Mask
))
548 DEBUG_EnterDebugger();
550 xkey
= LOWORD(keysym
);
551 key_type
= HIBYTE(xkey
);
553 dprintf_key(stddeb
," key_type=%X, key=%X\n", key_type
, key
);
555 if (key_type
== 0xFF) /* non-character key */
557 if (key
>= 0x08 && key
<= 0x1B) /* special key */
558 vkey
= special_key
[key
- 0x08];
559 else if (key
>= 0x50 && key
<= 0x57) /* cursor key */
560 vkey
= cursor_key
[key
- 0x50];
561 else if (key
>= 0x60 && key
<= 0x6B) /* miscellaneous key */
562 vkey
= misc_key
[key
- 0x60];
563 else if (key
>= 0x7E && key
<= 0xB9) /* keypad key */
565 vkey
= keypad_key
[key
- 0x7E];
568 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
570 vkey
= function_key
[key
- 0xBE];
573 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
574 vkey
= modifier_key
[key
- 0xE1];
575 else if (key
== 0xFF) /* DEL key */
577 /* extended must also be set for ALT_R, CTRL_R,
578 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
579 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
599 else if (key_type
== 0) /* character key */
602 vkey
= toupper(key
); /* convert lc to uc */
603 else if ( isspace(key
) )
604 vkey
= key
; /* XXX approximately */
606 switch (key
) /* the rest... */
608 #define vkcase(k,val) case k: vkey = val; break;
609 #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
614 fprintf( stderr
, "Unknown key! Please report!\n" );
615 vkey
= 0; /* whatever */
619 if (event
->type
== KeyPress
)
621 if (!(InputKeyStateTable
[vkey
] & 0x80))
622 InputKeyStateTable
[vkey
] ^= 0x01;
623 InputKeyStateTable
[vkey
] |= 0x80;
625 keylp
.lp1
.code
= LOBYTE(event
->keycode
) - 8;
626 keylp
.lp1
.extended
= (extended
? 1 : 0);
627 keylp
.lp1
.win_internal
= 0; /* this has something to do with dialogs,
628 * don't remember where I read it - AK */
629 keylp
.lp1
.context
= ( (event
->state
& Mod1Mask
) ||
630 (InputKeyStateTable
[VK_MENU
] & 0x80)) ? 1 : 0;
631 keylp
.lp1
.previous
= (KeyDown
? 0 : 1);
632 keylp
.lp1
.transition
= 0;
633 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
635 dprintf_key(stddeb
," InputKeyState=%X\n", InputKeyStateTable
[vkey
]);
636 hardware_event( InputKeyStateTable
[VK_MENU
] & 0x80 ? WM_SYSKEYDOWN
: WM_KEYDOWN
,
638 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
639 event
->time
- MSG_WineStartTicks
, 0 );
644 UINT sysKey
= InputKeyStateTable
[VK_MENU
];
646 InputKeyStateTable
[vkey
] &= ~0x80;
648 keylp
.lp1
.code
= LOBYTE(event
->keycode
) - 8;
649 keylp
.lp1
.extended
= (extended
? 1 : 0);
650 keylp
.lp1
.win_internal
= 0;
651 keylp
.lp1
.context
= (event
->state
& Mod1Mask
? 1 : 0);
652 keylp
.lp1
.previous
= 1;
653 keylp
.lp1
.transition
= 1;
654 dprintf_key(stddeb
," wParam=%X, lParam=%lX\n",
656 dprintf_key(stddeb
," InputKeyState=%X\n", InputKeyStateTable
[vkey
]);
657 hardware_event( sysKey
& 0x80 ? WM_SYSKEYUP
: WM_KEYUP
,
659 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
660 event
->time
- MSG_WineStartTicks
, 0 );
666 /***********************************************************************
669 static void EVENT_MotionNotify( XMotionEvent
*event
)
671 hardware_event( WM_MOUSEMOVE
, EVENT_XStateToKeyState( event
->state
), 0L,
672 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
673 event
->time
- MSG_WineStartTicks
, 0 );
677 /***********************************************************************
678 * EVENT_DummyMotionNotify
680 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
682 void EVENT_DummyMotionNotify(void)
685 int rootX
, rootY
, childX
, childY
;
688 if (XQueryPointer( display
, rootWindow
, &root
, &child
,
689 &rootX
, &rootY
, &childX
, &childY
, &state
))
691 hardware_event(WM_MOUSEMOVE
, EVENT_XStateToKeyState( state
), 0L,
692 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0 );
697 /***********************************************************************
700 static void EVENT_ButtonPress( XButtonEvent
*event
)
702 static WORD messages
[NB_BUTTONS
] =
703 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
704 int buttonNum
= event
->button
- 1;
706 if (buttonNum
>= NB_BUTTONS
) return;
707 MouseButtonsStates
[buttonNum
] = 0x8000;
708 AsyncMouseButtonsStates
[buttonNum
] = 0x8000;
709 hardware_event( messages
[buttonNum
],
710 EVENT_XStateToKeyState( event
->state
), 0L,
711 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
712 event
->time
- MSG_WineStartTicks
, 0 );
716 /***********************************************************************
717 * EVENT_ButtonRelease
719 static void EVENT_ButtonRelease( XButtonEvent
*event
)
721 static const WORD messages
[NB_BUTTONS
] =
722 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
723 int buttonNum
= event
->button
- 1;
725 if (buttonNum
>= NB_BUTTONS
) return;
726 MouseButtonsStates
[buttonNum
] = FALSE
;
727 hardware_event( messages
[buttonNum
],
728 EVENT_XStateToKeyState( event
->state
), 0L,
729 event
->x_root
- desktopX
, event
->y_root
- desktopY
,
730 event
->time
- MSG_WineStartTicks
, 0 );
734 /**********************************************************************
737 static void EVENT_FocusIn (HWND hwnd
, XFocusChangeEvent
*event
)
739 if (event
->detail
== NotifyPointer
) return;
740 if (hwnd
!= GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
741 if ((hwnd
!= GetFocus32()) && !IsChild( hwnd
, GetFocus32()))
746 /**********************************************************************
749 * Note: only top-level override-redirect windows get FocusOut events.
751 static void EVENT_FocusOut( HWND hwnd
, XFocusChangeEvent
*event
)
753 if (event
->detail
== NotifyPointer
) return;
754 if (hwnd
== GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE
);
755 if ((hwnd
== GetFocus32()) || IsChild( hwnd
, GetFocus32()))
760 /**********************************************************************
761 * EVENT_ConfigureNotify
763 * The ConfigureNotify event is only selected on the desktop window
764 * and on top-level windows when the -managed flag is used.
766 static void EVENT_ConfigureNotify( HWND hwnd
, XConfigureEvent
*event
)
768 /* FIXME: with -desktop xxx we get this event _before_ desktop
769 * window structure is created. WIN_GetDesktop() check is a hack.
772 if ( !WIN_GetDesktop() || hwnd
== GetDesktopWindow32())
781 RECT16 newWindowRect
, newClientRect
;
782 HRGN32 hrgnOldPos
, hrgnNewPos
;
784 if (!(wndPtr
= WIN_FindWndPtr( hwnd
)) ||
785 !(wndPtr
->flags
& WIN_MANAGED
) )
788 if (!(winpos
= SEGPTR_NEW(WINDOWPOS16
))) return;
790 /* XTranslateCoordinates(display, event->window, rootWindow,
791 event->x, event->y, &event->x, &event->y, &child);
794 /* Fill WINDOWPOS struct */
795 winpos
->flags
= SWP_NOACTIVATE
| SWP_NOZORDER
;
797 winpos
->x
= event
->x
;
798 winpos
->y
= event
->y
;
799 winpos
->cx
= event
->width
;
800 winpos
->cy
= event
->height
;
802 /* Check for unchanged attributes */
803 if(winpos
->x
== wndPtr
->rectWindow
.left
&&
804 winpos
->y
== wndPtr
->rectWindow
.top
)
805 winpos
->flags
|= SWP_NOMOVE
;
806 if(winpos
->cx
== wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
&&
807 winpos
->cy
== wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
)
808 winpos
->flags
|= SWP_NOSIZE
;
810 /* Send WM_WINDOWPOSCHANGING */
811 SendMessage16(hwnd
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)SEGPTR_GET(winpos
));
813 /* Calculate new position and size */
814 newWindowRect
.left
= event
->x
;
815 newWindowRect
.right
= event
->x
+ event
->width
;
816 newWindowRect
.top
= event
->y
;
817 newWindowRect
.bottom
= event
->y
+ event
->height
;
819 WINPOS_SendNCCalcSize( winpos
->hwnd
, TRUE
, &newWindowRect
,
820 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
821 SEGPTR_GET(winpos
), &newClientRect
);
823 hrgnOldPos
= CreateRectRgnIndirect16( &wndPtr
->rectWindow
);
824 hrgnNewPos
= CreateRectRgnIndirect16( &newWindowRect
);
825 CombineRgn32( hrgnOldPos
, hrgnOldPos
, hrgnNewPos
, RGN_DIFF
);
827 /* Set new size and position */
828 wndPtr
->rectWindow
= newWindowRect
;
829 wndPtr
->rectClient
= newClientRect
;
830 SendMessage16( hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)SEGPTR_GET(winpos
));
833 /* full window drag leaves unrepainted garbage without this */
834 PAINT_RedrawWindow( 0, NULL
, hrgnOldPos
, RDW_INVALIDATE
|
835 RDW_ALLCHILDREN
| RDW_ERASE
| RDW_ERASENOW
,
837 DeleteObject32(hrgnOldPos
);
838 DeleteObject32(hrgnNewPos
);
843 /***********************************************************************
844 * EVENT_SelectionRequest
846 static void EVENT_SelectionRequest( WND
*pWnd
, XSelectionRequestEvent
*event
)
848 XSelectionEvent result
;
850 Window request
= event
->requestor
;
852 if(event
->target
== XA_STRING
)
858 rprop
= event
->property
;
860 if(rprop
== None
) rprop
= event
->target
;
862 if(event
->selection
!=XA_PRIMARY
) rprop
= None
;
863 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT
)) rprop
= None
;
866 /* open to make sure that clipboard is available */
868 BOOL couldOpen
= OpenClipboard( pWnd
->hwndSelf
);
871 hText
= GetClipboardData(CF_TEXT
);
872 text
= GlobalLock16(hText
);
873 size
= GlobalSize16(hText
);
875 /* remove carriage returns */
877 lpstr
= (char*)xmalloc(size
--);
878 for(i
=0,j
=0; i
< size
&& text
[i
]; i
++ )
880 if( text
[i
] == '\r' &&
881 (text
[i
+1] == '\n' || text
[i
+1] == '\0') ) continue;
882 lpstr
[j
++] = text
[i
];
886 XChangeProperty(display
, request
, rprop
,
887 XA_STRING
, 8, PropModeReplace
,
891 /* close only if we opened before */
893 if(couldOpen
) CloseClipboard();
898 dprintf_event(stddeb
,"Request for %s ignored\n", XGetAtomName(display
,event
->target
));
900 result
.type
=SelectionNotify
;
901 result
.display
=display
;
902 result
.requestor
=request
;
903 result
.selection
=event
->selection
;
904 result
.property
=rprop
;
905 result
.target
=event
->target
;
906 result
.time
=event
->time
;
907 XSendEvent(display
,event
->requestor
,False
,NoEventMask
,(XEvent
*)&result
);
911 /***********************************************************************
912 * EVENT_SelectionNotify
914 static void EVENT_SelectionNotify( XSelectionEvent
*event
)
916 if (event
->selection
!= XA_PRIMARY
) return;
918 if (event
->target
!= XA_STRING
) CLIPBOARD_ReadSelection( 0, None
);
919 else CLIPBOARD_ReadSelection( event
->requestor
, event
->property
);
921 dprintf_clipboard(stddeb
,"\tSelectionNotify done!\n");
925 /***********************************************************************
926 * EVENT_SelectionClear
928 static void EVENT_SelectionClear( WND
*pWnd
, XSelectionClearEvent
*event
)
930 if (event
->selection
!= XA_PRIMARY
) return;
931 CLIPBOARD_ReleaseSelection( event
->window
, pWnd
->hwndSelf
);
935 /**********************************************************************
936 * EVENT_ClientMessage
938 static void EVENT_ClientMessage( WND
*pWnd
, XClientMessageEvent
*event
)
940 if (event
->message_type
!= None
&& event
->format
== 32)
942 if ((event
->message_type
== wmProtocols
) &&
943 (((Atom
) event
->data
.l
[0]) == wmDeleteWindow
))
944 SendMessage16( pWnd
->hwndSelf
, WM_SYSCOMMAND
, SC_CLOSE
, 0 );
945 else if ( event
->message_type
== dndProtocol
&&
946 (event
->data
.l
[0] == DndFile
|| event
->data
.l
[0] == DndFiles
) )
948 unsigned long data_length
;
949 unsigned long aux_long
;
950 unsigned char* p_data
= NULL
;
958 HGLOBAL16 hDragInfo
= GlobalAlloc16( GMEM_SHARE
| GMEM_ZEROINIT
, sizeof(DRAGINFO
));
959 LPDRAGINFO lpDragInfo
= (LPDRAGINFO
) GlobalLock16(hDragInfo
);
960 SEGPTR spDragInfo
= (SEGPTR
) WIN16_GlobalLock16(hDragInfo
);
961 Window w_aux_root
, w_aux_child
;
964 if( !lpDragInfo
|| !spDragInfo
) return;
966 XQueryPointer( display
, pWnd
->window
, &w_aux_root
, &w_aux_child
,
967 &x
, &y
, &u
.pt_aux
.x
, &u
.pt_aux
.y
, (unsigned int*)&aux_long
);
969 lpDragInfo
->hScope
= pWnd
->hwndSelf
;
970 lpDragInfo
->pt
.x
= (INT16
)x
; lpDragInfo
->pt
.y
= (INT16
)y
;
972 /* find out drop point and drop window */
973 if( x
< 0 || y
< 0 ||
974 x
> (pWnd
->rectWindow
.right
- pWnd
->rectWindow
.left
) ||
975 y
> (pWnd
->rectWindow
.bottom
- pWnd
->rectWindow
.top
) )
976 { u
.bAccept
= pWnd
->dwExStyle
& WS_EX_ACCEPTFILES
; x
= y
= 0; }
979 u
.bAccept
= DRAG_QueryUpdate( pWnd
->hwndSelf
, spDragInfo
, TRUE
);
980 x
= lpDragInfo
->pt
.x
; y
= lpDragInfo
->pt
.y
;
982 pDropWnd
= WIN_FindWndPtr( lpDragInfo
->hScope
);
983 GlobalFree16( hDragInfo
);
987 XGetWindowProperty( display
, DefaultRootWindow(display
),
988 dndSelection
, 0, 65535, FALSE
,
989 AnyPropertyType
, &u
.atom_aux
, &u
.pt_aux
.y
,
990 &data_length
, &aux_long
, &p_data
);
992 if( !aux_long
&& p_data
) /* don't bother if > 64K */
994 char* p
= (char*) p_data
;
995 char* p_filename
,*p_drop
;
998 while( *p
) /* calculate buffer size */
1001 if((u
.i
= *p
) != -1 )
1002 u
.i
= DRIVE_FindDriveRoot( (const char**)&p_drop
);
1003 if( u
.i
== -1 ) *p
= -1; /* mark as "bad" */
1006 p_filename
= (char*) DOSFS_GetDosTrueName( (const char*)p
, TRUE
);
1007 if( p_filename
) aux_long
+= strlen(p_filename
) + 1;
1012 if( aux_long
&& aux_long
< 65535 )
1015 LPDROPFILESTRUCT lpDrop
;
1017 aux_long
+= sizeof(DROPFILESTRUCT
) + 1;
1018 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
1019 lpDrop
= (LPDROPFILESTRUCT
) GlobalLock16( hDrop
);
1023 lpDrop
->wSize
= sizeof(DROPFILESTRUCT
);
1024 lpDrop
->ptMousePos
.x
= (INT16
)x
;
1025 lpDrop
->ptMousePos
.y
= (INT16
)y
;
1026 lpDrop
->fInNonClientArea
= (BOOL16
)
1027 ( x
< (pDropWnd
->rectClient
.left
- pDropWnd
->rectWindow
.left
) ||
1028 y
< (pDropWnd
->rectClient
.top
- pDropWnd
->rectWindow
.top
) ||
1029 x
> (pDropWnd
->rectClient
.right
- pDropWnd
->rectWindow
.left
) ||
1030 y
> (pDropWnd
->rectClient
.bottom
- pDropWnd
->rectWindow
.top
) );
1031 p_drop
= ((char*)lpDrop
) + sizeof(DROPFILESTRUCT
);
1035 if( *p
!= -1 ) /* use only "good" entries */
1037 p_filename
= (char*) DOSFS_GetDosTrueName( p
, TRUE
);
1038 strcpy(p_drop
, p_filename
);
1039 p_drop
+= strlen( p_filename
) + 1;
1044 PostMessage( pWnd
->hwndSelf
, WM_DROPFILES
, (WPARAM16
)hDrop
, 0L );
1048 if( p_data
) XFree(p_data
);
1050 } /* WS_EX_ACCEPTFILES */
1053 dprintf_event( stddeb
, "unrecognized ClientMessage\n" );
1057 /**********************************************************************
1060 * Install colormap when Wine window is focused in
1061 * self-managed mode with private colormap
1064 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1066 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1067 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1068 XInstallColormap( display, COLOR_GetColormap() );
1072 /**********************************************************************
1075 void EVENT_MapNotify( HWND hWnd
, XMapEvent
*event
)
1077 HWND32 hwndFocus
= GetFocus32();
1079 if (hwndFocus
&& IsChild( hWnd
, hwndFocus
))
1080 FOCUS_SetXFocus( (HWND32
)hwndFocus
);
1086 /**********************************************************************
1087 * SetCapture16 (USER.18)
1089 HWND16
SetCapture16( HWND16 hwnd
)
1091 return (HWND16
)SetCapture32( hwnd
);
1095 /**********************************************************************
1096 * SetCapture32 (USER32.463)
1098 HWND32
SetCapture32( HWND32 hwnd
)
1101 HWND32 old_capture_wnd
= captureWnd
;
1106 return old_capture_wnd
;
1108 if (!(win
= WIN_GetXWindow( hwnd
))) return 0;
1109 if (XGrabPointer(display
, win
, False
,
1110 ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
,
1111 GrabModeAsync
, GrabModeAsync
,
1112 None
, None
, CurrentTime
) == GrabSuccess
)
1114 dprintf_win(stddeb
, "SetCapture: %04x\n", hwnd
);
1116 return old_capture_wnd
;
1122 /**********************************************************************
1123 * ReleaseCapture (USER.19) (USER32.438)
1125 void ReleaseCapture(void)
1127 if (captureWnd
== 0) return;
1128 XUngrabPointer( display
, CurrentTime
);
1130 dprintf_win(stddeb
, "ReleaseCapture\n");
1134 /**********************************************************************
1135 * GetCapture16 (USER.236)
1137 HWND16
GetCapture16(void)
1139 return (HWND16
)captureWnd
;
1143 /**********************************************************************
1144 * GetCapture32 (USER32.207)
1146 HWND32
GetCapture32(void)
1152 /***********************************************************************
1153 * GetMouseEventProc (USER.337)
1155 FARPROC16
GetMouseEventProc(void)
1157 HMODULE16 hmodule
= GetModuleHandle("USER");
1158 return MODULE_GetEntryPoint( hmodule
,
1159 MODULE_GetOrdinal( hmodule
, "Mouse_Event" ) );
1163 /***********************************************************************
1164 * Mouse_Event (USER.299)
1167 void Mouse_Event( SIGCONTEXT
*context
)
1171 * BX = horizontal displacement if AX & ME_MOVE
1172 * CX = vertical displacement if AX & ME_MOVE
1173 * DX = button state (?)
1174 * SI = mouse event flags (?)
1177 int rootX
, rootY
, childX
, childY
;
1180 if (AX_reg(context
) & ME_MOVE
)
1182 /* We have to actually move the cursor */
1183 XWarpPointer( display
, rootWindow
, None
, 0, 0, 0, 0,
1184 (short)BX_reg(context
), (short)CX_reg(context
) );
1187 if (!XQueryPointer( display
, rootWindow
, &root
, &child
,
1188 &rootX
, &rootY
, &childX
, &childY
, &state
)) return;
1189 if (AX_reg(context
) & ME_LDOWN
)
1190 hardware_event( WM_LBUTTONDOWN
, EVENT_XStateToKeyState( state
), 0L,
1191 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1192 if (AX_reg(context
) & ME_LUP
)
1193 hardware_event( WM_LBUTTONUP
, EVENT_XStateToKeyState( state
), 0L,
1194 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1195 if (AX_reg(context
) & ME_RDOWN
)
1196 hardware_event( WM_RBUTTONDOWN
, EVENT_XStateToKeyState( state
), 0L,
1197 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1198 if (AX_reg(context
) & ME_RUP
)
1199 hardware_event( WM_RBUTTONUP
, EVENT_XStateToKeyState( state
), 0L,
1200 rootX
- desktopX
, rootY
- desktopY
, GetTickCount(), 0);
1205 /**********************************************************************
1206 * EnableHardwareInput (USER.331)
1208 BOOL16
EnableHardwareInput(BOOL16 bEnable
)
1210 BOOL16 bOldState
= InputEnabled
;
1211 dprintf_event(stdnimp
,"EnableHardwareInput(%d);\n", bEnable
);
1212 InputEnabled
= bEnable
;