summaryrefslogtreecommitdiff
path: root/lpdamage.c
diff options
context:
space:
mode:
Diffstat (limited to 'lpdamage.c')
-rw-r--r--lpdamage.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/lpdamage.c b/lpdamage.c
new file mode 100644
index 0000000..d87c66a
--- /dev/null
+++ b/lpdamage.c
@@ -0,0 +1,126 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2004 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "lpint.h"
+
+static void
+add_damage (light_pipe_window *lpw)
+{
+ light_pipe_display *lpd = find_display (lpw->display);
+ light_pipe_window **prev;
+
+ if (!lpd)
+ return;
+ for (prev = &lpd->damaged; *prev; prev = &(*prev)->next_damaged)
+ if ((*prev) == lpw)
+ return;
+ lpw->next_damaged = *prev;
+ *prev = lpw;
+}
+
+static void
+remove_damage (light_pipe_window *lpw)
+{
+ light_pipe_display *lpd = find_display (lpw->display);
+ light_pipe_window **prev;
+
+ if (!lpd)
+ return;
+ for (prev = &lpd->damaged; *prev; prev = &(*prev)->next_damaged)
+ if ((*prev) == lpw)
+ {
+ *prev = lpw->next_damaged;
+ break;
+ }
+}
+
+void
+damage_window (light_pipe_window *lpw, int x, int y, int width, int height)
+{
+ add_damage (lpw);
+ if (lpw->public.damage.width == 0)
+ {
+ lpw->public.damage.x = x;
+ lpw->public.damage.y = y;
+ lpw->public.damage.width = width;
+ lpw->public.damage.height = height;
+ }
+ else
+ {
+ int old_x2 = lpw->public.damage.x + lpw->public.damage.width;
+ int old_y2 = lpw->public.damage.y + lpw->public.damage.height;
+ int new_x2 = x + width;
+ int new_y2 = y + height;
+
+ if (x < lpw->public.damage.x)
+ lpw->public.damage.x = x;
+ if (new_x2 > old_x2)
+ old_x2 = new_x2;
+ lpw->public.damage.width = old_x2 - lpw->public.damage.x;
+ if (y < lpw->public.damage.y)
+ lpw->public.damage.y = y;
+ if (new_y2 > old_y2)
+ old_y2 = new_y2;
+ lpw->public.damage.height = old_y2 - lpw->public.damage.y;
+ }
+}
+
+void
+update_window (light_pipe_window *lpw)
+{
+ if (lpw->public.damage.width && lpw->public.damage.height)
+ {
+ XFixesSetRegion (lpw->display,
+ lpw->repair,
+ &lpw->public.damage,
+ 1);
+ XDamageSubtract (lpw->display,
+ lpw->damage,
+ lpw->repair,
+ None);
+ update_region (lpw,
+ lpw->public.damage.x,
+ lpw->public.damage.y,
+ lpw->public.damage.width,
+ lpw->public.damage.height);
+ XSync (lpw->display, False);
+ }
+}
+
+void
+undamage_window (light_pipe_window *lpw)
+{
+ remove_damage (lpw);
+ lpw->public.damage.x = lpw->public.damage.y = 0;
+ lpw->public.damage.width = lpw->public.damage.height = 0;
+}
+
+light_pipe_window *
+find_damaged (Display *display)
+{
+ light_pipe_display *lpd;
+
+ lpd = find_display (display);
+ return lpd->damaged;
+}