[PATCH weston 2/4] Add decoration frame support to cairo-util

Jason Ekstrand jason at jlekstrand.net
Mon Oct 14 02:08:39 CEST 2013


Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
---
 shared/Makefile.am  |   2 +
 shared/cairo-util.h | 111 +++++++++
 shared/frame.c      | 670 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 783 insertions(+)
 create mode 100644 shared/frame.c

diff --git a/shared/Makefile.am b/shared/Makefile.am
index 2fcff7b..31fab5f 100644
--- a/shared/Makefile.am
+++ b/shared/Makefile.am
@@ -10,6 +10,7 @@ libshared_la_SOURCES =				\
 	os-compatibility.h
 
 libshared_cairo_la_CFLAGS =			\
+	-DDATADIR='"$(datadir)"'		\
 	$(GCC_CFLAGS)				\
 	$(COMPOSITOR_CFLAGS)			\
 	$(PIXMAN_CFLAGS)			\
@@ -29,4 +30,5 @@ libshared_cairo_la_SOURCES =			\
 	image-loader.c				\
 	image-loader.h				\
 	cairo-util.c				\
+	frame.c					\
 	cairo-util.h
diff --git a/shared/cairo-util.h b/shared/cairo-util.h
index 7b40394..da1cef9 100644
--- a/shared/cairo-util.h
+++ b/shared/cairo-util.h
@@ -23,6 +23,7 @@
 #ifndef _CAIRO_UTIL_H
 #define _CAIRO_UTIL_H
 
+#include <stdint.h>
 #include <cairo.h>
 
 void
@@ -86,4 +87,114 @@ enum theme_location {
 enum theme_location
 theme_get_location(struct theme *t, int x, int y, int width, int height, int flags);
 
+struct frame;
+
+enum frame_status {
+	FRAME_STATUS_NONE = 0,
+	FRAME_STATUS_REPAINT = 0x1,
+	FRAME_STATUS_MINIMIZE = 0x2,
+	FRAME_STATUS_MAXIMIZE = 0x4,
+	FRAME_STATUS_CLOSE = 0x8,
+	FRAME_STATUS_MENU = 0x10,
+	FRAME_STATUS_RESIZE = 0x20,
+	FRAME_STATUS_MOVE = 0x40,
+	FRAME_STATUS_ALL = 0x7f
+};
+
+enum frame_flag {
+	FRAME_FLAG_ACTIVE = 0x1,
+	FRAME_FLAG_MAXIMIZED = 0x2
+};
+
+enum {
+	FRAME_BUTTON_NONE = 0,
+	FRAME_BUTTON_CLOSE = 0x1,
+	FRAME_BUTTON_MAXIMIZE = 0x2,
+	FRAME_BUTTON_MINIMIZE = 0x4,
+	FRAME_BUTTON_ALL = 0x7
+};
+
+enum frame_button_state {
+	FRAME_BUTTON_RELEASED = 0,
+	FRAME_BUTTON_PRESSED = 1
+};
+
+struct frame *
+frame_create(struct theme *t, int32_t width, int32_t height, uint32_t buttons,
+	     const char *title);
+
+void
+frame_destroy(struct frame *frame);
+
+/* May set FRAME_STATUS_REPAINT */
+int
+frame_set_title(struct frame *frame, const char *title);
+
+/* May set FRAME_STATUS_REPAINT */
+void
+frame_set_flag(struct frame *frame, enum frame_flag flag);
+
+/* May set FRAME_STATUS_REPAINT */
+void
+frame_unset_flag(struct frame *frame, enum frame_flag flag);
+
+/* May set FRAME_STATUS_REPAINT */
+void
+frame_resize(struct frame *frame, int32_t width, int32_t height);
+
+/* May set FRAME_STATUS_REPAINT */
+void
+frame_resize_inside(struct frame *frame, int32_t width, int32_t height);
+
+int32_t
+frame_width(struct frame *frame);
+
+int32_t
+frame_height(struct frame *frame);
+
+void
+frame_interior(struct frame *frame, int32_t *x, int32_t *y,
+	       int32_t *width, int32_t *height);
+void
+frame_input_rect(struct frame *frame, int32_t *x, int32_t *y,
+		 int32_t *width, int32_t *height);
+void
+frame_opaque_rect(struct frame *frame, int32_t *x, int32_t *y,
+		  int32_t *width, int32_t *height);
+
+uint32_t
+frame_status(struct frame *frame);
+
+void
+frame_status_clear(struct frame *frame, enum frame_status status);
+
+/* May set FRAME_STATUS_REPAINT */
+enum theme_location
+frame_pointer_enter(struct frame *frame, void *pointer, int x, int y);
+
+/* May set FRAME_STATUS_REPAINT */
+enum theme_location
+frame_pointer_motion(struct frame *frame, void *pointer, int x, int y);
+
+/* May set FRAME_STATUS_REPAINT */
+void
+frame_pointer_leave(struct frame *frame, void *pointer);
+
+/* May set:
+ *	FRAME_STATUS_MINIMIZE
+ *	FRAME_STATUS_MAXIMIZE
+ *	FRAME_STATUS_CLOSE
+ *	FRAME_STATUS_MENU
+ *	FRAME_STATUS_RESIZE
+ *	FRAME_STATUS_MOVE
+ */
+enum theme_location
+frame_pointer_button(struct frame *frame, void *pointer,
+		     uint32_t button, enum frame_button_state state);
+
+/* TODO: Add Touch */
+
+void
+frame_repaint(struct frame *frame, cairo_t *cr);
+
 #endif
diff --git a/shared/frame.c b/shared/frame.c
new file mode 100644
index 0000000..230997b
--- /dev/null
+++ b/shared/frame.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ * Copyright © 2012-2013 Collabora, Ltd.
+ * Copyright © 2013 Jason Ekstrand
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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 "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <wayland-util.h>
+#include <linux/input.h>
+
+#include "cairo-util.h"
+
+enum frame_button_flags {
+	FRAME_BUTTON_ALIGN_RIGHT = 0x1,
+	FRAME_BUTTON_DECORATED = 0x2,
+	FRAME_BUTTON_CLICK_DOWN = 0x4,
+};
+
+struct frame_button {
+	struct frame *frame;
+	struct wl_list link;	/* buttons_list */
+
+	cairo_surface_t *icon;
+	enum frame_button_flags flags;
+	int hover_count;
+	int press_count;
+
+	struct {
+		int x, y;
+		int width, height;
+	} allocation;
+
+	enum frame_status status_effect;
+};
+
+struct frame_pointer {
+	struct wl_list link;
+	void *data;
+
+	int x, y;
+
+	struct frame_button *hover_button;
+	int active;
+};
+
+struct frame {
+	int32_t width, height;
+	char *title;
+	uint32_t flags;
+	struct theme *theme;
+
+	struct {
+		int32_t x, y;
+		int32_t width, height;
+	} interior;
+	int shadow_margin;
+	int opaque_margin;
+	int geometry_dirty;
+
+	uint32_t status;
+
+	struct wl_list buttons;
+	struct wl_list pointers;
+};
+
+static struct frame_button *
+frame_button_create(struct frame *frame, const char *icon,
+		    enum frame_status status_effect,
+		    enum frame_button_flags flags)
+{
+	struct frame_button *button;
+
+	button = calloc(1, sizeof *button);
+	if (!button)
+		return NULL;
+
+	button->icon = cairo_image_surface_create_from_png(icon);
+	if (!button->icon) {
+		free(button);
+		return NULL;
+	}
+
+	button->frame = frame;
+	button->flags = flags;
+	button->status_effect = status_effect;
+
+	wl_list_insert(frame->buttons.prev, &button->link);
+
+	return button;
+}
+
+static void
+frame_button_destroy(struct frame_button *button)
+{
+	cairo_surface_destroy(button->icon);
+	free(button);
+}
+
+static void
+frame_button_enter(struct frame_button *button)
+{
+	if (!button->hover_count)
+		button->frame->status |= FRAME_STATUS_REPAINT;
+	button->hover_count++;
+}
+
+static void
+frame_button_leave(struct frame_button *button, struct frame_pointer *pointer)
+{
+	button->hover_count--;
+	if (!button->hover_count)
+		button->frame->status |= FRAME_STATUS_REPAINT;
+	
+	/* In this case, we won't get a release */
+	if (pointer->active)
+		button->press_count--;
+}
+
+static void
+frame_button_press(struct frame_button *button)
+{
+	if (!button->press_count)
+		button->frame->status |= FRAME_STATUS_REPAINT;
+	button->press_count++;
+
+	if (button->flags & FRAME_BUTTON_CLICK_DOWN)
+		button->frame->status |= button->status_effect;
+}
+
+static void
+frame_button_release(struct frame_button *button)
+{
+	button->press_count--;
+	if (!button->press_count)
+		button->frame->status |= FRAME_STATUS_REPAINT;
+	
+	if (!(button->flags & FRAME_BUTTON_CLICK_DOWN))
+		button->frame->status |= button->status_effect;
+}
+
+static void
+frame_button_repaint(struct frame_button *button, cairo_t *cr)
+{
+	int x, y;
+
+	if (!button->allocation.width)
+		return;
+	if (!button->allocation.height)
+		return;
+
+	x = button->allocation.x;
+	y = button->allocation.y;
+
+	cairo_save(cr);
+
+	if (button->flags & FRAME_BUTTON_DECORATED) {
+		cairo_set_line_width(cr, 1);
+
+		cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+		cairo_rectangle(cr, x, y, 25, 16);
+
+		cairo_stroke_preserve(cr);
+
+		if (button->press_count) {
+			cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+		} else if (button->hover_count) {
+			cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
+		} else {
+			cairo_set_source_rgb(cr, 0.88, 0.88, 0.88);
+		}
+
+		cairo_fill (cr);
+
+		x += 4;
+	}
+
+	cairo_set_source_surface(cr, button->icon, x, y);
+	cairo_paint(cr);
+
+	cairo_restore(cr);
+}
+
+static struct frame_pointer *
+frame_pointer_get(struct frame *frame, void *data)
+{
+	struct frame_pointer *pointer;
+
+	wl_list_for_each(pointer, &frame->pointers, link)
+		if (pointer->data == data)
+			return pointer;
+
+	pointer = calloc(1, sizeof *pointer);
+	if (!pointer)
+		return NULL;
+	
+	pointer->data = data;
+	wl_list_insert(&frame->pointers, &pointer->link);
+
+	return pointer;
+}
+
+static void
+frame_pointer_destroy(struct frame_pointer *pointer)
+{
+	wl_list_remove(&pointer->link);
+	free(pointer);
+}
+
+struct frame *
+frame_create(struct theme *t, int32_t width, int32_t height, uint32_t buttons,
+	     const char *title)
+{
+	struct frame *frame;
+	struct frame_button *button;
+
+	frame = calloc(1, sizeof *frame);
+	if (!frame)
+		return NULL;
+
+	frame->width = width;
+	frame->height = height;
+	frame->flags = 0;
+	frame->theme = t;
+	frame->status = FRAME_STATUS_REPAINT;
+	frame->geometry_dirty = 1;
+
+	if (title) {
+		frame->title = strdup(title);
+		if (!frame->title)
+			goto free_frame;
+	}
+
+	wl_list_init(&frame->buttons);
+	wl_list_init(&frame->pointers);
+
+	button = frame_button_create(frame, DATADIR "/weston/icon_window.png",
+				     FRAME_STATUS_MENU,
+				     FRAME_BUTTON_CLICK_DOWN);
+	if (!button)
+		goto free_frame;
+
+	if (buttons & FRAME_BUTTON_CLOSE) {
+		button = frame_button_create(frame,
+					     DATADIR "/weston/sign_close.png",
+					     FRAME_STATUS_CLOSE,
+					     FRAME_BUTTON_ALIGN_RIGHT |
+					     FRAME_BUTTON_DECORATED);
+		if (!button)
+			goto free_frame;
+	}
+
+	if (buttons & FRAME_BUTTON_MAXIMIZE) {
+		button = frame_button_create(frame,
+					     DATADIR "/weston/sign_maximize.png",
+					     FRAME_STATUS_MAXIMIZE,
+					     FRAME_BUTTON_ALIGN_RIGHT |
+					     FRAME_BUTTON_DECORATED);
+		if (!button)
+			goto free_frame;
+	}
+
+	if (buttons & FRAME_BUTTON_MINIMIZE) {
+		button = frame_button_create(frame,
+					     DATADIR "/weston/sign_minimize.png",
+					     FRAME_STATUS_MINIMIZE,
+					     FRAME_BUTTON_ALIGN_RIGHT |
+					     FRAME_BUTTON_DECORATED);
+		if (!button)
+			goto free_frame;
+	}
+
+	return frame;
+
+free_frame:
+	free(frame->title);
+	free(frame);
+	return NULL;
+}
+
+void
+frame_destroy(struct frame *frame)
+{
+	struct frame_button *button, *next;
+
+	wl_list_for_each_safe(button, next, &frame->buttons, link)
+		frame_button_destroy(button);
+
+	free(frame->title);
+	free(frame);
+}
+
+int
+frame_set_title(struct frame *frame, const char *title)
+{
+	char *dup = NULL;
+
+	if (title) {
+		dup = strdup(title);
+		if (!dup)
+			return -1;
+	}
+	
+	free(frame->title);
+	frame->title = dup;
+
+	frame->status |= FRAME_STATUS_REPAINT;
+
+	return 0;
+}
+
+void
+frame_set_flag(struct frame *frame, enum frame_flag flag)
+{
+	if (flag & FRAME_FLAG_MAXIMIZED && !(frame->flags & FRAME_FLAG_MAXIMIZED))
+		frame->geometry_dirty = 1;
+	
+	frame->flags |= flag;
+	frame->status |= FRAME_STATUS_REPAINT;
+}
+
+void
+frame_unset_flag(struct frame *frame, enum frame_flag flag)
+{
+	if (flag & FRAME_FLAG_MAXIMIZED && frame->flags & FRAME_FLAG_MAXIMIZED)
+		frame->geometry_dirty = 1;
+	
+	frame->flags &= ~flag;
+	frame->status |= FRAME_STATUS_REPAINT;
+}
+
+void
+frame_resize(struct frame *frame, int32_t width, int32_t height)
+{
+	frame->width = width;
+	frame->height = height;
+
+	frame->geometry_dirty = 1;
+	frame->status |= FRAME_STATUS_REPAINT;
+}
+
+void
+frame_resize_inside(struct frame *frame, int32_t width, int32_t height)
+{
+	struct theme *t = frame->theme;
+	int decoration_width, decoration_height;
+
+	if (frame->flags & FRAME_FLAG_MAXIMIZED) {
+		decoration_width = t->width * 2;
+		decoration_height = t->width + t->titlebar_height;
+	} else {
+		decoration_width = (t->width + t->margin) * 2;
+		decoration_height = t->width +
+			t->titlebar_height + t->margin * 2;
+	}
+
+	frame_resize(frame, width + decoration_width,
+		     height + decoration_height);
+}
+
+int32_t
+frame_width(struct frame *frame)
+{
+	return frame->width;
+}
+
+int32_t
+frame_height(struct frame *frame)
+{
+	return frame->height;
+}
+
+static void
+frame_refresh_geometry(struct frame *frame)
+{
+	struct frame_button *button;
+	struct theme *t = frame->theme;
+	int x_l, x_r, y, w, h;
+	int32_t decoration_width, decoration_height;
+
+	if (!frame->geometry_dirty)
+		return;
+
+	if (frame->flags & FRAME_FLAG_MAXIMIZED) {
+		decoration_width = t->width * 2;
+		decoration_height = t->width + t->titlebar_height;
+
+		frame->interior.x = t->width;
+		frame->interior.y = t->titlebar_height;
+		frame->interior.width = frame->width - decoration_width;
+		frame->interior.height = frame->height - decoration_height;
+
+		frame->opaque_margin = 0;
+		frame->shadow_margin = 0;
+	} else {
+		decoration_width = (t->width + t->margin) * 2;
+		decoration_height = t->width +
+			t->titlebar_height + t->margin * 2;
+
+		frame->interior.x = t->width + t->margin;
+		frame->interior.y = t->titlebar_height + t->margin;
+		frame->interior.width = frame->width - decoration_width;
+		frame->interior.height = frame->height - decoration_height;
+
+		frame->opaque_margin = t->margin + t->frame_radius;
+		frame->shadow_margin = t->margin;
+	}
+
+	x_r = frame->width - t->width - frame->shadow_margin;
+	x_l = t->width + frame->shadow_margin;
+	y = t->width + frame->shadow_margin;
+	wl_list_for_each(button, &frame->buttons, link) {
+		const int button_padding = 4;
+		w = cairo_image_surface_get_width(button->icon);
+		h = cairo_image_surface_get_height(button->icon);
+
+		if (button->flags & FRAME_BUTTON_DECORATED)
+			w += 10;
+
+		if (button->flags & FRAME_BUTTON_ALIGN_RIGHT) {
+			x_r -= w;
+
+			button->allocation.x = x_r;
+			button->allocation.y = y;
+			button->allocation.width = w + 1;
+			button->allocation.height = h + 1;
+
+			x_r -= button_padding;
+		} else {
+			button->allocation.x = x_l;
+			button->allocation.y = y;
+			button->allocation.width = w + 1;
+			button->allocation.height = h + 1;
+
+			x_l += w;
+			x_l += button_padding;
+		}
+	}
+
+	frame->geometry_dirty = 0;
+}
+
+void
+frame_interior(struct frame *frame, int32_t *x, int32_t *y,
+		int32_t *width, int32_t *height)
+{
+	frame_refresh_geometry(frame);
+
+	if (x)
+		*x = frame->interior.x;
+	if (y)
+		*y = frame->interior.y;
+	if (width)
+		*width = frame->interior.width;
+	if (height)
+		*height = frame->interior.height;
+}
+
+void
+frame_input_rect(struct frame *frame, int32_t *x, int32_t *y,
+		 int32_t *width, int32_t *height)
+{
+	frame_refresh_geometry(frame);
+
+	if (x)
+		*x = frame->shadow_margin;
+	if (y)
+		*y = frame->shadow_margin;
+	if (width)
+		*width = frame->width - frame->shadow_margin * 2;
+	if (height)
+		*height = frame->height - frame->shadow_margin * 2;
+}
+
+void
+frame_opaque_rect(struct frame *frame, int32_t *x, int32_t *y,
+		  int32_t *width, int32_t *height)
+{
+	frame_refresh_geometry(frame);
+
+	if (x)
+		*x = frame->opaque_margin;
+	if (y)
+		*y = frame->opaque_margin;
+	if (width)
+		*width = frame->width - frame->opaque_margin * 2;
+	if (height)
+		*height = frame->height - frame->opaque_margin * 2;
+}
+
+uint32_t
+frame_status(struct frame *frame)
+{
+	return frame->status;
+}
+
+void
+frame_status_clear(struct frame *frame, enum frame_status status)
+{
+	frame->status &= ~status;
+}
+
+static struct frame_button *
+frame_find_button(struct frame *frame, int x, int y)
+{
+	struct frame_button *button;
+	int rel_x, rel_y;
+
+	wl_list_for_each(button, &frame->buttons, link) {
+		rel_x = x - button->allocation.x;
+		rel_y = y - button->allocation.y;
+
+		if (0 <= rel_x && rel_x < button->allocation.width &&
+		    0 <= rel_y && rel_y < button->allocation.height)
+			return button;
+	}
+
+	return NULL;
+}
+
+enum theme_location
+frame_pointer_enter(struct frame *frame, void *data, int x, int y)
+{
+	return frame_pointer_motion(frame, data, x, y);
+}
+
+enum theme_location
+frame_pointer_motion(struct frame *frame, void *data, int x, int y)
+{
+	struct frame_pointer *pointer = frame_pointer_get(frame, data);
+	struct frame_button *button = frame_find_button(frame, x, y);
+	enum theme_location location;
+
+	location = theme_get_location(frame->theme, x, y,
+				      frame->width, frame->height,
+				      frame->flags & FRAME_FLAG_MAXIMIZED ?
+				      THEME_FRAME_MAXIMIZED : 0);
+	if (!pointer)
+		return location;
+
+	pointer->x = x;
+	pointer->y = y;
+	
+	if (pointer->hover_button == button)
+		return location;
+	
+	if (pointer->hover_button)
+		frame_button_leave(pointer->hover_button, pointer);
+
+	/* No drags */
+	pointer->active = 0;
+	pointer->hover_button = button;
+
+	if (pointer->hover_button)
+		frame_button_enter(pointer->hover_button);
+
+	return location;
+}
+
+void
+frame_pointer_leave(struct frame *frame, void *data)
+{
+	struct frame_pointer *pointer = frame_pointer_get(frame, data);
+	if (!pointer)
+		return;
+
+	if (pointer->hover_button)
+		frame_button_leave(pointer->hover_button, pointer);
+	
+	frame_pointer_destroy(pointer);
+}
+
+enum theme_location
+frame_pointer_button(struct frame *frame, void *data,
+		     uint32_t button, enum frame_button_state state)
+{
+	struct frame_pointer *pointer = frame_pointer_get(frame, data);
+	enum theme_location location;
+
+	location = theme_get_location(frame->theme, pointer->x, pointer->y,
+				      frame->width, frame->height,
+				      frame->flags & FRAME_FLAG_MAXIMIZED ?
+				      THEME_FRAME_MAXIMIZED : 0);
+
+	if (!pointer)
+		return location;
+	
+	if (button == BTN_RIGHT) {
+		if (state == FRAME_BUTTON_PRESSED &&
+		    location == THEME_LOCATION_TITLEBAR)
+			frame->status |= FRAME_STATUS_MENU;
+
+	} else if (button == BTN_LEFT && state == FRAME_BUTTON_PRESSED) {
+		if (pointer->hover_button) {
+			pointer->active = 1;
+			frame_button_press(pointer->hover_button);
+			return location;
+		} else {
+			switch (location) {
+			case THEME_LOCATION_TITLEBAR:
+				frame->status |= FRAME_STATUS_MOVE;
+				break;
+			case THEME_LOCATION_RESIZING_TOP:
+			case THEME_LOCATION_RESIZING_BOTTOM:
+			case THEME_LOCATION_RESIZING_LEFT:
+			case THEME_LOCATION_RESIZING_RIGHT:
+			case THEME_LOCATION_RESIZING_TOP_LEFT:
+			case THEME_LOCATION_RESIZING_TOP_RIGHT:
+			case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
+			case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
+				frame->status |= FRAME_STATUS_RESIZE;
+				break;
+			default:
+				break;
+			}
+		}
+	} else if (button == BTN_LEFT && state == FRAME_BUTTON_RELEASED) {
+		if (pointer->hover_button && pointer->active)
+			frame_button_release(pointer->hover_button);
+
+		pointer->active = 0;
+	}
+
+	return location;
+}
+
+void
+frame_repaint(struct frame *frame, cairo_t *cr)
+{
+	struct frame_button *button;
+	uint32_t flags = 0;
+
+	frame_refresh_geometry(frame);
+
+	if (frame->flags & FRAME_FLAG_MAXIMIZED)
+		flags |= THEME_FRAME_MAXIMIZED;
+
+	if (frame->flags & FRAME_FLAG_ACTIVE)
+		flags |= THEME_FRAME_ACTIVE;
+
+	cairo_save(cr);
+	theme_render_frame(frame->theme, cr, frame->width, frame->height,
+			   frame->title, flags);
+	cairo_restore(cr);
+	
+	wl_list_for_each(button, &frame->buttons, link)
+		frame_button_repaint(button, cr);
+
+	frame_status_clear(frame, FRAME_STATUS_REPAINT);
+}
-- 
1.8.3.1



More information about the wayland-devel mailing list