Moved WIN_FindWinToRepaint functionality to the server.

This commit is contained in:
Alexandre Julliard 2001-11-14 21:28:36 +00:00
parent 272023190e
commit 47f9821817
6 changed files with 50 additions and 115 deletions

View File

@ -1884,17 +1884,11 @@ BOOL WINAPI PeekMessageW( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT f
/* need to fill the window handle for WM_PAINT message */
if (msg.message == WM_PAINT)
{
if (!(msg.hwnd = WIN_FindWinToRepaint( hwnd ))) return FALSE;
if (IsIconic( msg.hwnd ) && GetClassLongA( msg.hwnd, GCL_HICON ))
{
msg.message = WM_PAINTICON;
msg.wParam = 1;
}
/* check hwnd filter */
if (hwnd && msg.hwnd != hwnd && !IsChild( hwnd, msg.hwnd )) return FALSE;
/* clear internal paint flag */
RedrawWindow( msg.hwnd, NULL, 0, RDW_NOINTERNALPAINT | RDW_NOCHILDREN );
}

View File

@ -92,7 +92,6 @@ extern void WIN_SetOwner( HWND hwnd, HWND owner );
extern LONG WIN_SetStyle( HWND hwnd, LONG style );
extern LONG WIN_SetExStyle( HWND hwnd, LONG style );
extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient );
extern HWND WIN_FindWinToRepaint( HWND hwnd );
extern LRESULT WIN_DestroyWindow( HWND hwnd );
extern void WIN_DestroyThreadWindows( HWND hwnd );
extern BOOL WIN_CreateDesktopWindow(void);

View File

@ -891,11 +891,11 @@ DECL_HANDLER(get_message)
}
/* now check for WM_PAINT */
if ((queue->wake_bits & QS_PAINT) &&
(WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
if (queue->paint_count &&
(WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last) &&
(req->win = find_window_to_repaint( get_win, current )))
{
req->type = MSG_POSTED;
req->win = 0;
req->msg = WM_PAINT;
req->wparam = 0;
req->lparam = 0;

View File

@ -36,5 +36,6 @@ extern void queue_cleanup_window( struct thread *thread, user_handle_t win );
extern void destroy_thread_windows( struct thread *thread );
extern int is_child_window( user_handle_t parent, user_handle_t child );
extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread );
#endif /* __WINE_SERVER_USER_H */

View File

@ -6,6 +6,10 @@
#include <assert.h>
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "object.h"
#include "request.h"
#include "thread.h"
@ -325,6 +329,47 @@ int is_child_window( user_handle_t parent, user_handle_t child )
return 0;
}
/* find a child of the specified window that needs repainting */
static struct window *find_child_to_repaint( struct window *parent, struct thread *thread )
{
struct window *ptr, *ret = NULL;
for (ptr = parent->first_child; ptr && !ret; ptr = ptr->next)
{
if (!(ptr->style & WS_VISIBLE)) continue;
if (ptr->paint_count && ptr->thread == thread)
ret = ptr;
else /* explore its children */
ret = find_child_to_repaint( ptr, thread );
}
if (ret && (ret->ex_style & WS_EX_TRANSPARENT))
{
/* transparent window, check for non-transparent sibling to paint first */
for (ptr = ret->next; ptr; ptr = ptr->next)
{
if (!(ptr->style & WS_VISIBLE)) continue;
if (ptr->ex_style & WS_EX_TRANSPARENT) continue;
if (ptr->paint_count && ptr->thread == thread) return ptr;
}
}
return ret;
}
/* find a window that needs repainting */
user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread )
{
struct window *win = parent ? get_window( parent ) : top_window;
if (!win || !(win->style & WS_VISIBLE)) return 0;
if (!win->paint_count || win->thread != thread)
win = find_child_to_repaint( win, thread );
return win ? win->handle : 0;
}
/* create a window */
DECL_HANDLER(create_window)
{
@ -612,7 +657,7 @@ DECL_HANDLER(inc_window_paint_count)
{
struct window *win = get_window( req->handle );
if (win)
if (win && win->thread)
{
int old = win->paint_count;
if ((win->paint_count += req->incr) < 0) win->paint_count = 0;

View File

@ -564,110 +564,6 @@ void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClien
}
/***********************************************************************
* find_child_to_repaint
*
* Find a window that needs repaint among the children of the specified window.
*/
static HWND find_child_to_repaint( HWND parent )
{
int i;
HWND ret = 0;
HWND *list;
if (!parent) parent = GetDesktopWindow();
if (!(list = list_window_children( parent, 0, 0 ))) return 0;
for (i = 0; list[i] && !ret; i++)
{
WND *win = WIN_GetPtr( list[i] );
if (!win) continue; /* ignore it */
if (win == WND_OTHER_PROCESS)
{
/* doesn't belong to this process, but check children */
ret = find_child_to_repaint( list[i] );
continue;
}
if (!(win->dwStyle & WS_VISIBLE))
{
WIN_ReleasePtr( win );
continue;
}
if ((win->tid != GetCurrentThreadId()) ||
(!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
{
/* does not need repaint, check children */
WIN_ReleasePtr( win );
ret = find_child_to_repaint( list[i] );
continue;
}
/* now we have something */
ret = list[i];
if (!(win->dwExStyle & WS_EX_TRANSPARENT))
{
/* not transparent, we can repaint it */
WIN_ReleasePtr( win );
break;
}
WIN_ReleasePtr( win );
/* transparent window, look for non-transparent sibling to paint first */
for (i++; list[i]; i++)
{
if (!(win = WIN_GetPtr( list[i] ))) continue;
if (win == WND_OTHER_PROCESS) continue;
if (!(win->dwStyle & WS_VISIBLE))
{
WIN_ReleasePtr( win );
continue;
}
if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
(win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
{
ret = list[i];
WIN_ReleasePtr( win );
break;
}
WIN_ReleasePtr( win );
}
}
HeapFree( GetProcessHeap(), 0, list );
return ret;
}
/***********************************************************************
* WIN_FindWinToRepaint
*
* Find a window that needs repaint.
*/
HWND WIN_FindWinToRepaint( HWND hwnd )
{
/* Note: the desktop window never gets WM_PAINT messages
* The real reason why is because Windows DesktopWndProc
* does ValidateRgn inside WM_ERASEBKGND handler.
*/
if (hwnd == GetDesktopWindow()) hwnd = 0;
if (hwnd)
{
/* check the window itself first */
WND *win = WIN_FindWndPtr( hwnd );
if (!win) return 0;
if ((win->dwStyle & WS_VISIBLE) &&
(win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
{
WIN_ReleaseWndPtr( win );
return hwnd;
}
WIN_ReleaseWndPtr( win );
}
/* now check its children */
return find_child_to_repaint( hwnd );
}
/***********************************************************************
* WIN_DestroyWindow
*