@ -1083,6 +1083,9 @@ shm_surface_prepare(struct toysurface *base, int dx, int dy,
surface - > flags ,
surface - > flags ,
leaf - > resize_pool ,
leaf - > resize_pool ,
& leaf - > data ) ;
& leaf - > data ) ;
if ( ! leaf - > cairo_surface )
return NULL ;
wl_buffer_add_listener ( leaf - > data - > buffer ,
wl_buffer_add_listener ( leaf - > data - > buffer ,
& shm_surface_buffer_listener , surface ) ;
& shm_surface_buffer_listener , surface ) ;
@ -3724,21 +3727,10 @@ hack_prevent_EGL_sub_surface_deadlock(struct window *window)
}
}
static void
static void
idle _resize( struct window * window )
window_do _resize( struct window * window )
{
{
struct surface * surface ;
struct surface * surface ;
window - > resize_needed = 0 ;
window - > redraw_needed = 1 ;
DBG ( " from %dx%d to %dx%d \n " ,
window - > main_surface - > server_allocation . width ,
window - > main_surface - > server_allocation . height ,
window - > pending_allocation . width ,
window - > pending_allocation . height ) ;
hack_prevent_EGL_sub_surface_deadlock ( window ) ;
widget_set_allocation ( window - > main_surface - > widget ,
widget_set_allocation ( window - > main_surface - > widget ,
window - > pending_allocation . x ,
window - > pending_allocation . x ,
window - > pending_allocation . y ,
window - > pending_allocation . y ,
@ -3761,6 +3753,46 @@ idle_resize(struct window *window)
}
}
}
}
static void
idle_resize ( struct window * window )
{
window - > resize_needed = 0 ;
window - > redraw_needed = 1 ;
DBG ( " from %dx%d to %dx%d \n " ,
window - > main_surface - > server_allocation . width ,
window - > main_surface - > server_allocation . height ,
window - > pending_allocation . width ,
window - > pending_allocation . height ) ;
hack_prevent_EGL_sub_surface_deadlock ( window ) ;
window_do_resize ( window ) ;
}
static void
undo_resize ( struct window * window )
{
window - > pending_allocation . width =
window - > main_surface - > server_allocation . width ;
window - > pending_allocation . height =
window - > main_surface - > server_allocation . height ;
DBG ( " back to %dx%d \n " ,
window - > main_surface - > server_allocation . width ,
window - > main_surface - > server_allocation . height ) ;
window_do_resize ( window ) ;
if ( window - > pending_allocation . width = = 0 & &
window - > pending_allocation . height = = 0 ) {
fprintf ( stderr , " Error: Could not draw a surface, "
" most likely due to insufficient disk space in "
" %s (XDG_RUNTIME_DIR). \n " , getenv ( " XDG_RUNTIME_DIR " ) ) ;
exit ( EXIT_FAILURE ) ;
}
}
void
void
window_schedule_resize ( struct window * window , int width , int height )
window_schedule_resize ( struct window * window , int width , int height )
{
{
@ -3885,25 +3917,30 @@ static const struct wl_callback_listener listener = {
frame_callback
frame_callback
} ;
} ;
static void
static int
surface_redraw ( struct surface * surface )
surface_redraw ( struct surface * surface )
{
{
DBG_OBJ ( surface - > surface , " begin \n " ) ;
DBG_OBJ ( surface - > surface , " begin \n " ) ;
if ( ! surface - > window - > redraw_needed & & ! surface - > redraw_needed )
if ( ! surface - > window - > redraw_needed & & ! surface - > redraw_needed )
return ;
return 0 ;
/* Whole-window redraw forces a redraw even if the previous has
/* Whole-window redraw forces a redraw even if the previous has
* not yet hit the screen .
* not yet hit the screen .
*/
*/
if ( surface - > frame_cb ) {
if ( surface - > frame_cb ) {
if ( ! surface - > window - > redraw_needed )
if ( ! surface - > window - > redraw_needed )
return ;
return 0 ;
DBG_OBJ ( surface - > frame_cb , " cancelled \n " ) ;
DBG_OBJ ( surface - > frame_cb , " cancelled \n " ) ;
wl_callback_destroy ( surface - > frame_cb ) ;
wl_callback_destroy ( surface - > frame_cb ) ;
}
}
if ( ! widget_get_cairo_surface ( surface - > widget ) ) {
DBG_OBJ ( surface - > surface , " cancelled due buffer failure \n " ) ;
return - 1 ;
}
surface - > frame_cb = wl_surface_frame ( surface - > surface ) ;
surface - > frame_cb = wl_surface_frame ( surface - > surface ) ;
wl_callback_add_listener ( surface - > frame_cb , & listener , surface ) ;
wl_callback_add_listener ( surface - > frame_cb , & listener , surface ) ;
DBG_OBJ ( surface - > frame_cb , " new \n " ) ;
DBG_OBJ ( surface - > frame_cb , " new \n " ) ;
@ -3912,6 +3949,7 @@ surface_redraw(struct surface *surface)
DBG_OBJ ( surface - > surface , " -> widget_redraw \n " ) ;
DBG_OBJ ( surface - > surface , " -> widget_redraw \n " ) ;
widget_redraw ( surface - > widget ) ;
widget_redraw ( surface - > widget ) ;
DBG_OBJ ( surface - > surface , " done \n " ) ;
DBG_OBJ ( surface - > surface , " done \n " ) ;
return 0 ;
}
}
static void
static void
@ -3919,6 +3957,8 @@ idle_redraw(struct task *task, uint32_t events)
{
{
struct window * window = container_of ( task , struct window , redraw_task ) ;
struct window * window = container_of ( task , struct window , redraw_task ) ;
struct surface * surface ;
struct surface * surface ;
int failed = 0 ;
int resized = 0 ;
DBG ( " --------- \n " ) ;
DBG ( " --------- \n " ) ;
@ -3933,16 +3973,35 @@ idle_redraw(struct task *task, uint32_t events)
}
}
idle_resize ( window ) ;
idle_resize ( window ) ;
resized = 1 ;
}
}
wl_list_for_each ( surface , & window - > subsurface_list , link )
if ( surface_redraw ( window - > main_surface ) < 0 ) {
surface_redraw ( surface ) ;
/*
* Only main_surface failure will cause us to undo the resize .
* If sub - surfaces fail , they will just be broken with old
* content .
*/
failed = 1 ;
} else {
wl_list_for_each ( surface , & window - > subsurface_list , link ) {
if ( surface = = window - > main_surface )
continue ;
surface_redraw ( surface ) ;
}
}
window - > redraw_needed = 0 ;
window - > redraw_needed = 0 ;
window_flush ( window ) ;
window_flush ( window ) ;
wl_list_for_each ( surface , & window - > subsurface_list , link )
wl_list_for_each ( surface , & window - > subsurface_list , link )
surface_set_synchronized_default ( surface ) ;
surface_set_synchronized_default ( surface ) ;
if ( resized & & failed ) {
/* Restore widget tree to correspond to what is on screen. */
undo_resize ( window ) ;
}
}
}
static void
static void