[PATCH] wlt_toolkit.c: Fix resize window stuck in need_resize=true
Martin Minarik
minarik11 at student.fiit.stuba.sk
Thu Jan 24 07:48:03 PST 2013
The problem is that:
wnd->w_frame contains a number
and
wnd->need_frame=true
Therefore schedule_frame() doesn't schedule the callback.
But deleting these checks causes flicker. Further redesign
of the frame sheduling was necessary.
4. frame_callback()
3. do_frame()
3. idle_frame()
2. schedule_frame()
1. wlt_window_set_size()
Please, observe the need_resize variable.
-------------------------------------------------------------------------------
BAD (window stuck on resize):
$3 = {ref = 1, list = {next = 0x659c70, prev = 0x659c70},
buffer_attached = true, skip_damage = false, need_resize = true,
w_frame = 0x70d9b0, widget_list = {next = 0x686cb0, prev = 0x6b54d0}}
OK (window not stuck on resize):
$3 = {ref = 1, list = {next = 0x240cc70, prev = 0x240cc70},
buffer_attached = true, skip_damage = false, need_resize = false,
w_frame = 0x241bb10, widget_list = {next = 0x2439cb0, prev = 0x2468560}}
-----------------------------------------------------------------------------------
This is the basic idea:
-> time ->
frame callbacks() * * * * * *
wnd->idle_pending ------ --------- --------- -------- ---------------------
wnd->need_frame --- --- --- --- --- ------ ---
schedule_frame() * * * * * * * **
idle_frame() * * * * * * * *
This design follows similiar design in weston/clients/window.c
Kmscon Weston
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wlt_window_do_redraw() ~~~ shm_surface_swap()
do_frame() ~~~~~~~~~~~~~~~ window_attach_surface()
wnd->idle_pending ~~~~~~~~ window->redraw_scheduled
frame_callback() ~~~~~~~~ frame_callback()
do_frame() ~~~~~~~~~~~~~~ idle_redraw()
wlt_window_set_size()
wlt_window_schedule_redraw()
schedule_frame() ~~~~~~~~ window_schedule_redraw()
---
src/wlt_toolkit.c | 34 ++++++++++++++--------------------
1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/src/wlt_toolkit.c b/src/wlt_toolkit.c
index 7ae6fdc..bdc1245 100644
--- a/src/wlt_toolkit.c
+++ b/src/wlt_toolkit.c
@@ -126,7 +126,6 @@ struct wlt_window {
bool buffer_attached;
bool skip_damage;
bool need_resize;
- bool need_redraw;
bool need_frame;
bool idle_pending;
unsigned int new_width;
@@ -1305,7 +1304,7 @@ static void wlt_window_do_redraw(struct wlt_window *wnd,
}
static int resize_window(struct wlt_window *wnd, unsigned int width,
- unsigned int height, bool force_redraw)
+ unsigned int height)
{
struct shl_dlist *iter;
struct wlt_widget *widget;
@@ -1351,8 +1350,7 @@ static int resize_window(struct wlt_window *wnd, unsigned int width,
if (width == wnd->buffer.width &&
height == wnd->buffer.height) {
- if (force_redraw)
- wlt_window_do_redraw(wnd, width, height);
+ wlt_window_do_redraw(wnd, width, height);
return 0;
}
@@ -1420,25 +1418,17 @@ static const struct wl_callback_listener frame_callback_listener = {
static void do_frame(struct wlt_window *wnd)
{
- bool force;
-
- wnd->idle_pending = false;
ev_eloop_unregister_idle_cb(wnd->disp->eloop, idle_frame, wnd);
if (wnd->need_resize) {
- force = wnd->need_redraw;
wnd->need_frame = true;
wnd->need_resize = false;
- wnd->need_redraw = false;
wnd->w_frame = wl_surface_frame(wnd->w_surface);
wl_callback_add_listener(wnd->w_frame,
&frame_callback_listener, wnd);
- resize_window(wnd, wnd->new_width, wnd->new_height, force);
- }
-
- if (wnd->need_redraw) {
+ resize_window(wnd, wnd->new_width, wnd->new_height);
+ } else {
wnd->need_frame = true;
- wnd->need_redraw = false;
wnd->w_frame = wl_surface_frame(wnd->w_surface);
wl_callback_add_listener(wnd->w_frame,
&frame_callback_listener, wnd);
@@ -1447,6 +1437,8 @@ static void do_frame(struct wlt_window *wnd)
}
}
+static void schedule_frame(struct wlt_window *wnd);
+
static void frame_callback(void *data, struct wl_callback *w_callback,
uint32_t time)
{
@@ -1454,9 +1446,10 @@ static void frame_callback(void *data, struct wl_callback *w_callback,
wl_callback_destroy(w_callback);
wnd->w_frame = NULL;
- wnd->need_frame = false;
- do_frame(wnd);
+ wnd->idle_pending = false;
+ if (wnd->need_frame)
+ schedule_frame(wnd);
}
static void idle_frame(struct ev_eloop *eloop, void *unused, void *data)
@@ -1495,10 +1488,12 @@ static void schedule_frame(struct wlt_window *wnd)
{
int ret;
- if (!wnd || wnd->w_frame)
+ if (!wnd)
return;
- if (wnd->need_frame || wnd->idle_pending)
+ wnd->need_frame = true;
+
+ if (wnd->idle_pending)
return;
ret = ev_eloop_register_idle_cb(wnd->disp->eloop, idle_frame, wnd);
@@ -1590,7 +1585,7 @@ int wlt_display_create_window(struct wlt_display *disp,
&shell_surface_listener, wnd);
wl_shell_surface_set_toplevel(wnd->w_shell_surface);
- ret = resize_window(wnd, width, height, true);
+ ret = resize_window(wnd, width, height);
if (ret)
goto err_shell_surface;
@@ -1674,7 +1669,6 @@ void wlt_window_schedule_redraw(struct wlt_window *wnd)
if (!wnd)
return;
- wnd->need_redraw = true;
schedule_frame(wnd);
}
--
1.7.10.4
More information about the wayland-devel
mailing list