Handle non-hardware X events correctly with native USER

(removed reference to MESSAGEQUEUE from KERNEL code).
Handle Expose events with native USER.
This commit is contained in:
Ulrich Weigand 1998-12-24 14:59:53 +00:00 committed by Alexandre Julliard
parent a6ceb0feec
commit be672fe587
7 changed files with 98 additions and 76 deletions

View file

@ -130,7 +130,7 @@ static THUNK *firstThunk = NULL;
static LRESULT WINAPI THUNK_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
UINT16 msg, WPARAM16 wParam,
LPARAM lParam );
static void WINAPI THUNK_CallTaskReschedule(void);
static BOOL32 WINAPI THUNK_CallTaskReschedule(void);
static BOOL32 WINAPI THUNK_WOWCallback16Ex( FARPROC16,DWORD,DWORD,
LPVOID,LPDWORD );
@ -309,9 +309,9 @@ static LRESULT WINAPI THUNK_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
/***********************************************************************
* THUNK_CallTaskReschedule
*/
static void WINAPI THUNK_CallTaskReschedule(void)
static BOOL32 WINAPI THUNK_CallTaskReschedule(void)
{
CallTo16_word_(TASK_RescheduleProc);
return CallTo16_word_(TASK_RescheduleProc);
}

View file

@ -21,7 +21,7 @@ typedef struct
{
LONG (CALLBACK *CallRegisterShortProc)( CONTEXT *, INT32 );
LONG (CALLBACK *CallRegisterLongProc)( CONTEXT *, INT32 );
VOID (CALLBACK *CallTaskRescheduleProc)(void);
BOOL32 (CALLBACK *CallTaskRescheduleProc)(void);
VOID (CALLBACK *CallFrom16WndProc)(void);
LRESULT (CALLBACK *CallWndProc)( WNDPROC16, HWND16, UINT16,
WPARAM16, LPARAM );

View file

@ -71,7 +71,6 @@ typedef struct tagMESSAGEQUEUE
#define QS_SMPARAMSFREE 0x4000 /* SendMessage() parameters are available */
/* Queue flags */
#define QUEUE_FLAG_XEVENT 0x0001
#define QUEUE_SM_WIN32 0x0002 /* Currently sent message is Win32 */
#define QUEUE_SM_UNICODE 0x0004 /* Currently sent message is Unicode */

View file

@ -152,7 +152,7 @@ extern HTASK16 TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule,
extern void TASK_StartTask( HTASK16 hTask );
extern void TASK_KillCurrentTask( INT16 exitCode );
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
extern void TASK_Reschedule(void);
extern BOOL32 TASK_Reschedule(void);
extern void TASK_InstallTHHook( THHOOK *pNewThook );
#endif /* __WINE_TASK_H */

View file

@ -653,11 +653,12 @@ void TASK_KillCurrentTask( INT16 exitCode )
*
* It must not call functions that may yield control.
*/
void TASK_Reschedule(void)
BOOL32 TASK_Reschedule(void)
{
TDB *pOldTask = NULL, *pNewTask;
HTASK16 hTask = 0;
STACK16FRAME *newframe16;
BOOL32 pending = FALSE;
/* Get the initial task up and running */
if (!hCurrentTask && GetCurrentTask())
@ -683,7 +684,7 @@ void TASK_Reschedule(void)
hCurrentTask = GetCurrentTask();
pNewTask = (TDB *)GlobalLock16( hCurrentTask );
pNewTask->ss_sp = pNewTask->thdb->cur_stack;
return;
return FALSE;
}
/* NOTE: As we are entered from 16-bit code, we hold the Win16Lock.
@ -720,7 +721,7 @@ void TASK_Reschedule(void)
/* extract hardware events only! */
if (!hTask) EVENT_WaitNetEvent( FALSE, TRUE );
if (!hTask) pending = EVENT_WaitNetEvent( FALSE, TRUE );
while (!hTask)
{
@ -739,6 +740,10 @@ void TASK_Reschedule(void)
if (hLockedTask && (hTask != hLockedTask)) hTask = 0;
if (hTask) break;
/* If a non-hardware event is pending, return to TASK_YieldToSystem
temporarily to process it safely */
if (pending) return TRUE;
/* No task found, wait for some events to come in */
/* NOTE: We release the Win16Lock while waiting for events. This is to enable
@ -747,14 +752,14 @@ void TASK_Reschedule(void)
TASK_Reschedule anyway, there should be no re-entrancy problem ... */
SYSLEVEL_ReleaseWin16Lock();
EVENT_WaitNetEvent( TRUE, TRUE );
pending = EVENT_WaitNetEvent( TRUE, TRUE );
SYSLEVEL_RestoreWin16Lock();
}
if (hTask == hCurrentTask)
{
TRACE(task, "returning to the current task(%04x)\n", hTask );
return; /* Nothing to do */
return FALSE; /* Nothing to do */
}
pNewTask = (TDB *)GlobalLock16( hTask );
TRACE(task, "Switching to task %04x (%.8s)\n",
@ -797,6 +802,8 @@ void TASK_Reschedule(void)
pNewTask->ss_sp = pNewTask->thdb->cur_stack;
SYSLEVEL_RestoreWin16Lock();
return FALSE;
}
@ -808,26 +815,30 @@ void TASK_Reschedule(void)
*/
void TASK_YieldToSystem(TDB* pTask)
{
MESSAGEQUEUE* pQ;
if ( !THREAD_IsWin16( THREAD_Current() ) )
{
FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
return;
}
Callbacks->CallTaskRescheduleProc();
if( pTask )
{
pQ = (MESSAGEQUEUE*)GlobalLock16(pTask->hQueue);
if( pQ && pQ->flags & QUEUE_FLAG_XEVENT &&
!(pQ->wakeBits & (QS_SENDMESSAGE | QS_SMRESULT)) )
if ( !THREAD_IsWin16( THREAD_Current() ) )
{
pQ->flags &= ~QUEUE_FLAG_XEVENT;
EVENT_WaitNetEvent( FALSE, FALSE );
FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
return;
}
if ( Callbacks->CallTaskRescheduleProc() )
{
/* NOTE: We get here only when no task has an event. This means also
the current task, so we shouldn't actually return to the
caller here. But, we need to do so, as the EVENT_WaitNetEvent
call could lead to a complex series of inter-task SendMessage
calls which might leave this task in a state where it again
has no event, but where its queue's wakeMask is also reset
to zero. Reentering TASK_Reschedule in this state would be
suicide. Hence, we do return to the caller after processing
non-hardware events. Actually, this should not hurt anyone,
as the caller must be WaitEvent, and thus the QUEUE_WaitBits
loop in USER. Should there actually be no message pending
for this task after processing non-hardware events, that loop
will simply return to WaitEvent. */
EVENT_WaitNetEvent( FALSE, FALSE );
}
}
}

View file

@ -238,11 +238,15 @@ static BOOL32 WINAPI CALLBACK_CallWOWCallback16Ex(
/**********************************************************************
* CALLBACK_CallTaskRescheduleProc
*/
static void WINAPI CALLBACK_CallTaskRescheduleProc( void )
static BOOL32 WINAPI CALLBACK_CallTaskRescheduleProc( void )
{
BOOL32 pending;
SYSLEVEL_EnterWin16Lock();
TASK_Reschedule();
pending = TASK_Reschedule();
SYSLEVEL_LeaveWin16Lock();
return pending;
}

View file

@ -27,13 +27,10 @@
#include "gdi.h"
#include "heap.h"
#include "queue.h"
#include "win.h"
#include "class.h"
#include "dce.h"
#include "message.h"
#include "module.h"
#include "options.h"
#include "queue.h"
#include "winpos.h"
#include "drive.h"
#include "shell.h"
@ -113,6 +110,10 @@ static void EVENT_GetGeometry( Window win, int *px, int *py,
unsigned int *pwidth, unsigned int *pheight );
static BOOL32 (WINAPI *EVENT_RedrawWindow)( HWND32 hwnd, const RECT32 *rectUpdate,
HRGN32 hrgnUpdate, UINT32 flags ) = NULL;
/***********************************************************************
* EVENT_Init
*
@ -166,8 +167,8 @@ BOOL16 X11DRV_EVENT_IsUserIdle(void)
* X11DRV_EVENT_WaitNetEvent
*
* Wait for a network event, optionally sleeping until one arrives.
* Return TRUE if an event is pending, FALSE on timeout or error
* (for instance lost connection with the server).
* Returns TRUE if an event is pending that cannot be processed in
* 'peek' mode, FALSE otherwise.
*/
BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
@ -198,7 +199,7 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
if (DDE_GetRemoteMessage()) {
while(DDE_GetRemoteMessage())
;
return TRUE;
return FALSE;
}
stop_wait_op = STOP_WAIT_X;
/* The code up to the next "stop_wait_op = CONT" must be reentrant */
@ -233,7 +234,10 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
}
else /* no X events */
return WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
{
WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
return FALSE;
}
}
else if(!pending)
{ /* Wait for X11 input. */
@ -255,19 +259,14 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
{
LeaveCriticalSection(&X11DRV_CritSection);
while(DDE_GetRemoteMessage()) ;
return TRUE;
return FALSE;
}
#endif /* CONFIG_IPC */
XNextEvent( display, &event );
LeaveCriticalSection(&X11DRV_CritSection);
if( peek )
{
WND* pWnd;
MESSAGEQUEUE* pQ;
{
/* Check only for those events which can be processed
* internally. */
@ -276,31 +275,30 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
event.type == KeyPress || event.type == KeyRelease ||
event.type == SelectionRequest || event.type == SelectionClear ||
event.type == ClientMessage )
{
{
LeaveCriticalSection(&X11DRV_CritSection);
EVENT_ProcessEvent( &event );
EnterCriticalSection(&X11DRV_CritSection);
continue;
}
}
if ( event.type == NoExpose )
continue;
if (TSXFindContext( display, ((XAnyEvent *)&event)->window, winContext,
(char **)&pWnd ) || (event.type == NoExpose))
pWnd = NULL;
if( pWnd )
{
if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
{
pQ->flags |= QUEUE_FLAG_XEVENT;
PostEvent(pQ->hTask);
TSXPutBackEvent(display, &event);
break;
}
}
}
else EVENT_ProcessEvent( &event );
EnterCriticalSection(&X11DRV_CritSection);
XPutBackEvent(display, &event);
LeaveCriticalSection(&X11DRV_CritSection);
return TRUE;
}
else
{
LeaveCriticalSection(&X11DRV_CritSection);
EVENT_ProcessEvent( &event );
EnterCriticalSection(&X11DRV_CritSection);
}
}
LeaveCriticalSection(&X11DRV_CritSection);
return TRUE;
return FALSE;
}
/***********************************************************************
@ -396,12 +394,10 @@ static void EVENT_ProcessEvent( XEvent *event )
break;
case Expose:
if (!pWnd) return;
EVENT_Expose( pWnd, (XExposeEvent *)event );
break;
case GraphicsExpose:
if (!pWnd) return;
EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
break;
@ -613,14 +609,20 @@ static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
RECT32 rect;
/* Make position relative to client area instead of window */
rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
rect.right = rect.left + event->width;
rect.bottom = rect.top + event->height;
PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
if ( !EVENT_RedrawWindow )
{
HMODULE32 hModule = GetModuleHandle32A( "USER32" );
EVENT_RedrawWindow = GetProcAddress32( hModule, "RedrawWindow" );
}
EVENT_RedrawWindow( pWnd? pWnd->hwndSelf : 0, &rect, 0,
RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
(event->count ? 0 : RDW_ERASENOW), 0 );
(event->count ? 0 : RDW_ERASENOW) );
}
@ -635,14 +637,20 @@ static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
RECT32 rect;
/* Make position relative to client area instead of window */
rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
rect.right = rect.left + event->width;
rect.bottom = rect.top + event->height;
PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
if ( !EVENT_RedrawWindow )
{
HMODULE32 hModule = GetModuleHandle32A( "USER32" );
EVENT_RedrawWindow = GetProcAddress32( hModule, "RedrawWindow" );
}
EVENT_RedrawWindow( pWnd? pWnd->hwndSelf : 0, &rect, 0,
RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
(event->count ? 0 : RDW_ERASENOW), 0 );
(event->count ? 0 : RDW_ERASENOW) );
}