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
|
* update_now
|
||||||
*
|
*
|
||||||
* Implementation of RDW_UPDATENOW behavior.
|
* 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 )
|
static void update_now( HWND hwnd, UINT rdw_flags )
|
||||||
{
|
{
|
||||||
HWND child = 0;
|
HWND child = 0;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
/* desktop window never gets WM_PAINT, only WM_ERASEBKGND */
|
/* desktop window never gets WM_PAINT, only WM_ERASEBKGND */
|
||||||
if (hwnd == GetDesktopWindow()) erase_now( hwnd, rdw_flags | RDW_NOCHILDREN );
|
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 */
|
if (!flags) break; /* nothing more to do */
|
||||||
|
|
||||||
SendMessageW( child, WM_PAINT, 0, 0 );
|
SendMessageW( child, WM_PAINT, 0, 0 );
|
||||||
|
count++;
|
||||||
if (rdw_flags & RDW_NOCHILDREN) break;
|
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 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 */
|
/* 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
|
* WIN_GetPtr
|
||||||
*
|
*
|
||||||
|
@ -863,7 +913,11 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
|
||||||
if (icon_title) DestroyWindow( icon_title );
|
if (icon_title) DestroyWindow( icon_title );
|
||||||
if (menu) DestroyMenu( menu );
|
if (menu) DestroyMenu( menu );
|
||||||
if (sys_menu) DestroyMenu( sys_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 );
|
USER_Driver->pDestroyWindow( hwnd );
|
||||||
|
|
||||||
|
@ -917,7 +971,11 @@ static void destroy_thread_window( HWND hwnd )
|
||||||
HeapFree( GetProcessHeap(), 0, wndPtr );
|
HeapFree( GetProcessHeap(), 0, wndPtr );
|
||||||
if (menu) DestroyMenu( menu );
|
if (menu) DestroyMenu( menu );
|
||||||
if (sys_menu) DestroyMenu( sys_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 */
|
/* Window functions */
|
||||||
extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
|
extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN;
|
||||||
extern BOOL is_desktop_window( HWND hwnd ) 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 WND *WIN_GetPtr( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||||
extern HWND WIN_GetFullHandle( HWND hwnd ) DECLSPEC_HIDDEN;
|
extern HWND WIN_GetFullHandle( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||||
extern HWND WIN_IsCurrentProcess( 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)
|
if (ret)
|
||||||
{
|
{
|
||||||
TRACE( "win %p surface %p -> %p\n", hwnd, old_surface, new_surface );
|
TRACE( "win %p surface %p -> %p\n", hwnd, old_surface, new_surface );
|
||||||
|
register_window_surface( old_surface, new_surface );
|
||||||
if (old_surface)
|
if (old_surface)
|
||||||
{
|
{
|
||||||
if (!IsRectEmpty( valid_rects ))
|
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 )
|
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();
|
if (ret == WAIT_TIMEOUT && !count && !timeout) NtYieldExecution();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue