summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-12-03 16:29:38 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-12-03 16:29:38 +1100
commitc91bf27e592e509639c61dc735fdd7f7e94815fb (patch)
tree519a89fb760dd714934da788ffb8bec9ba0b511a
parent1ef6eaa1c4c6f895546fe9ad42d40e572be4a8aa (diff)
Add some damage handling to windows, to be typically used by windows
who have a drawproc installed. I intend to use that for some apps that directly paint in windows rather than using the widgets mecanism Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--twin.h9
-rw-r--r--twin_window.c84
2 files changed, 89 insertions, 4 deletions
diff --git a/twin.h b/twin.h
index 2e13fe0..a2653c7 100644
--- a/twin.h
+++ b/twin.h
@@ -397,6 +397,7 @@ struct _twin_window {
twin_rect_t damage;
twin_bool_t client_grab;
twin_bool_t want_focus;
+ twin_bool_t draw_queued;
void *client_data;
char *name;
@@ -1204,6 +1205,14 @@ twin_window_style_size (twin_window_style_t style,
void
twin_window_draw (twin_window_t *window);
+void
+twin_window_damage (twin_window_t *window,
+ twin_coord_t left, twin_coord_t top,
+ twin_coord_t right, twin_coord_t bottom);
+
+void
+twin_window_queue_paint (twin_window_t *window);
+
twin_bool_t
twin_window_dispatch (twin_window_t *window, twin_event_t *event);
diff --git a/twin_window.c b/twin_window.c
index ff2862f..0ca180b 100644
--- a/twin_window.c
+++ b/twin_window.c
@@ -73,10 +73,10 @@ twin_window_create (twin_screen_t *screen,
twin_pixmap_origin_to_clip (window->pixmap);
window->pixmap->window = window;
twin_pixmap_move (window->pixmap, x, y);
- window->damage.left = window->damage.right = 0;
- window->damage.top = window->damage.bottom = 0;
+ window->damage = window->client;
window->client_grab = TWIN_FALSE;
window->want_focus = TWIN_FALSE;
+ window->draw_queued = TWIN_FALSE;
window->client_data = 0;
window->name = 0;
@@ -331,8 +331,84 @@ twin_window_draw (twin_window_t *window)
twin_window_frame (window);
break;
}
- if (window->draw)
- (*window->draw) (window);
+
+ /* if no draw function or no damage, return */
+ if (window->draw == NULL ||
+ (window->damage.left >= window->damage.right ||
+ window->damage.top >= window->damage.bottom))
+ return;
+
+ /* clip to damaged area and draw */
+ twin_pixmap_reset_clip (pixmap);
+ twin_pixmap_clip(pixmap,
+ window->damage.left, window->damage.top,
+ window->damage.right, window->damage.bottom);
+ (*window->draw) (window);
+
+ /* damage matching screen area */
+ twin_pixmap_damage(pixmap,
+ window->damage.left, window->damage.top,
+ window->damage.right, window->damage.bottom);
+
+ /* clear damage and restore clip */
+ window->damage.left = window->damage.right = 0;
+ window->damage.top = window->damage.bottom = 0;
+ twin_pixmap_reset_clip (pixmap);
+ twin_pixmap_clip (pixmap,
+ window->client.left, window->client.top,
+ window->client.right, window->client.bottom);
+}
+
+/* window keep track of local damage */
+void twin_window_damage (twin_window_t *window,
+ twin_coord_t left, twin_coord_t top,
+ twin_coord_t right, twin_coord_t bottom)
+{
+ if (left < window->client.left)
+ left = window->client.left;
+ if (top < window->client.top)
+ top = window->client.top;
+ if (right > window->client.right)
+ right = window->client.right;
+ if (bottom > window->client.bottom)
+ bottom = window->client.bottom;
+
+ if (window->damage.left == window->damage.right)
+ {
+ window->damage.left = left;
+ window->damage.right = right;
+ window->damage.top = top;
+ window->damage.bottom = bottom;
+ }
+ else
+ {
+ if (left < window->damage.left)
+ window->damage.left = left;
+ if (top < window->damage.top)
+ window->damage.top = top;
+ if (window->damage.right < right)
+ window->damage.right = right;
+ if (window->damage.bottom < bottom)
+ window->damage.bottom = bottom;
+ }
+}
+
+static twin_bool_t _twin_window_repaint (void *closure)
+{
+ twin_window_t *window = closure;
+
+ window->draw_queued = TWIN_FALSE;
+ twin_window_draw(window);
+
+ return TWIN_FALSE;
+}
+
+void twin_window_queue_paint (twin_window_t *window)
+{
+ if (!window->draw_queued) {
+ window->draw_queued = TWIN_TRUE;
+ twin_set_work (_twin_window_repaint, TWIN_WORK_PAINT, window);
+ }
}
twin_bool_t