mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 22:20:26 +00:00
user32: Maintain a list of active window surfaces and flush them periodically.
This commit is contained in:
parent
a5ef549c6e
commit
7304445a7e
@ -801,23 +801,11 @@ void move_window_bits( HWND hwnd, struct window_surface *old_surface,
|
||||
* update_now
|
||||
*
|
||||
* Implementation of RDW_UPDATENOW behavior.
|
||||
*
|
||||
* FIXME: Windows uses WM_SYNCPAINT to cut down the number of intertask
|
||||
* SendMessage() calls. This is a comment inside DefWindowProc() source
|
||||
* from 16-bit SDK:
|
||||
*
|
||||
* This message avoids lots of inter-app message traffic
|
||||
* by switching to the other task and continuing the
|
||||
* recursion there.
|
||||
*
|
||||
* wParam = flags
|
||||
* LOWORD(lParam) = hrgnClip
|
||||
* HIWORD(lParam) = hwndSkip (not used; always NULL)
|
||||
*
|
||||
*/
|
||||
static void update_now( HWND hwnd, UINT rdw_flags )
|
||||
{
|
||||
HWND child = 0;
|
||||
int count = 0;
|
||||
|
||||
/* desktop window never gets WM_PAINT, only WM_ERASEBKGND */
|
||||
if (hwnd == GetDesktopWindow()) erase_now( hwnd, rdw_flags | RDW_NOCHILDREN );
|
||||
@ -834,8 +822,10 @@ static void update_now( HWND hwnd, UINT rdw_flags )
|
||||
if (!flags) break; /* nothing more to do */
|
||||
|
||||
SendMessageW( child, WM_PAINT, 0, 0 );
|
||||
count++;
|
||||
if (rdw_flags & RDW_NOCHILDREN) break;
|
||||
}
|
||||
if (count) flush_window_surfaces( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,6 +44,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
|
||||
|
||||
static DWORD process_layout = ~0u;
|
||||
|
||||
static struct list window_surfaces = LIST_INIT( window_surfaces );
|
||||
|
||||
static CRITICAL_SECTION surfaces_section;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
{
|
||||
0, 0, &surfaces_section,
|
||||
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": surfaces_section") }
|
||||
};
|
||||
static CRITICAL_SECTION surfaces_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/* helper for Get/SetWindowLong */
|
||||
@ -475,6 +486,45 @@ BOOL is_desktop_window( HWND hwnd )
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* register_window_surface
|
||||
*
|
||||
* Register a window surface in the global list, possibly replacing another one.
|
||||
*/
|
||||
void register_window_surface( struct window_surface *old, struct window_surface *new )
|
||||
{
|
||||
if (old == new) return;
|
||||
EnterCriticalSection( &surfaces_section );
|
||||
if (old) list_remove( &old->entry );
|
||||
if (new) list_add_tail( &window_surfaces, &new->entry );
|
||||
LeaveCriticalSection( &surfaces_section );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* flush_window_surfaces
|
||||
*
|
||||
* Flush pending output from all window surfaces.
|
||||
*/
|
||||
void flush_window_surfaces( BOOL idle )
|
||||
{
|
||||
static DWORD last_idle;
|
||||
DWORD now;
|
||||
struct window_surface *surface;
|
||||
|
||||
EnterCriticalSection( &surfaces_section );
|
||||
now = GetTickCount();
|
||||
if (idle) last_idle = now;
|
||||
/* if not idle, we only flush if there's evidence that the app never goes idle */
|
||||
else if ((int)(now - last_idle) < 1000) goto done;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( surface, &window_surfaces, struct window_surface, entry )
|
||||
surface->funcs->flush( surface );
|
||||
done:
|
||||
LeaveCriticalSection( &surfaces_section );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WIN_GetPtr
|
||||
*
|
||||
@ -863,7 +913,11 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
|
||||
if (icon_title) DestroyWindow( icon_title );
|
||||
if (menu) DestroyMenu( menu );
|
||||
if (sys_menu) DestroyMenu( sys_menu );
|
||||
if (surface) window_surface_release( surface );
|
||||
if (surface)
|
||||
{
|
||||
register_window_surface( surface, NULL );
|
||||
window_surface_release( surface );
|
||||
}
|
||||
|
||||
USER_Driver->pDestroyWindow( hwnd );
|
||||
|
||||
@ -917,7 +971,11 @@ static void destroy_thread_window( HWND hwnd )
|
||||
HeapFree( GetProcessHeap(), 0, wndPtr );
|
||||
if (menu) DestroyMenu( menu );
|
||||
if (sys_menu) DestroyMenu( sys_menu );
|
||||
if (surface) window_surface_release( surface );
|
||||
if (surface)
|
||||
{
|
||||
register_window_surface( surface, NULL );
|
||||
window_surface_release( surface );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,6 +80,8 @@ typedef struct tagWND
|
||||
/* Window functions */
|
||||
extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
|
||||
extern BOOL is_desktop_window( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern void register_window_surface( struct window_surface *old, struct window_surface *new ) DECLSPEC_HIDDEN;
|
||||
extern void flush_window_surfaces( BOOL idle ) DECLSPEC_HIDDEN;
|
||||
extern WND *WIN_GetPtr( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HWND WIN_GetFullHandle( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern HWND WIN_IsCurrentProcess( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
|
@ -2020,6 +2020,7 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
|
||||
if (ret)
|
||||
{
|
||||
TRACE( "win %p surface %p -> %p\n", hwnd, old_surface, new_surface );
|
||||
register_window_surface( old_surface, new_surface );
|
||||
if (old_surface)
|
||||
{
|
||||
if (!IsRectEmpty( valid_rects ))
|
||||
|
@ -1123,7 +1123,10 @@ static LRESULT WINAPI StaticWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM
|
||||
|
||||
static DWORD wait_message( DWORD count, CONST HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags )
|
||||
{
|
||||
DWORD ret = USER_Driver->pMsgWaitForMultipleObjectsEx( count, handles, timeout, mask, flags );
|
||||
DWORD ret;
|
||||
|
||||
flush_window_surfaces( TRUE );
|
||||
ret = USER_Driver->pMsgWaitForMultipleObjectsEx( count, handles, timeout, mask, flags );
|
||||
if (ret == WAIT_TIMEOUT && !count && !timeout) NtYieldExecution();
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user