[PATCH weston 4/4] xwayland: Use decoration frame from cairo-util

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


In particular, this gives us a close button on xwayland windows.

Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
---

In some applications (specifically GLXGears), the close button does not
work.  Unfortunately, my knowledge of X window managers is small, so I'm
not sure what's wrong.

 src/xwayland/window-manager.c | 160 +++++++++++++++++++++++++++---------------
 1 file changed, 103 insertions(+), 57 deletions(-)

diff --git a/src/xwayland/window-manager.c b/src/xwayland/window-manager.c
index 2c1c9e0..ac59624 100644
--- a/src/xwayland/window-manager.c
+++ b/src/xwayland/window-manager.c
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <signal.h>
 #include <X11/Xcursor/Xcursor.h>
+#include <linux/input.h>
 
 #include "xwayland.h"
 
@@ -119,6 +120,7 @@ struct weston_wm_window {
 	struct weston_wm *wm;
 	xcb_window_t id;
 	xcb_window_t frame_id;
+	struct frame *frame;
 	cairo_surface_t *cairo_surface;
 	struct weston_surface *surface;
 	struct shell_surface *shsurf;
@@ -473,6 +475,8 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
 
 	if (window->shsurf && window->name)
 		shell_interface->set_title(window->shsurf, window->name);
+	if (window->frame && window->name)
+		frame_set_title(window->frame, window->name);
 }
 
 static void
@@ -485,9 +489,8 @@ weston_wm_window_get_frame_size(struct weston_wm_window *window,
 		*width = window->width;
 		*height = window->height;
 	} else if (window->decorate) {
-		*width = window->width + (t->margin + t->width) * 2;
-		*height = window->height +
-			t->margin * 2 + t->width + t->titlebar_height;
+		*width = frame_width(window->frame);
+		*height = frame_height(window->frame);
 	} else {
 		*width = window->width + t->margin * 2;
 		*height = window->height + t->margin * 2;
@@ -504,8 +507,7 @@ weston_wm_window_get_child_position(struct weston_wm_window *window,
 		*x = 0;
 		*y = 0;
 	} else if (window->decorate) {
-		*x = t->margin + t->width;
-		*y = t->margin + t->titlebar_height;
+		frame_interior(window->frame, x, y, NULL, NULL);
 	} else {
 		*x = t->margin;
 		*y = t->margin;
@@ -564,6 +566,9 @@ weston_wm_handle_configure_request(struct weston_wm *wm, xcb_generic_event_t *ev
 	if (configure_request->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
 		window->height = configure_request->height;
 
+	if (window->frame)
+		frame_resize_inside(window->frame, window->width, window->height);
+
 	weston_wm_window_get_child_position(window, &x, &y);
 	values[i++] = x;
 	values[i++] = y;
@@ -609,7 +614,6 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve
 	xcb_configure_notify_event_t *configure_notify = 
 		(xcb_configure_notify_event_t *) event;
 	struct weston_wm_window *window;
-	int x, y;
 
 	wm_log("XCB_CONFIGURE_NOTIFY (window %d) %d,%d @ %dx%d\n",
 	       configure_notify->window,
@@ -617,12 +621,14 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve
 	       configure_notify->width, configure_notify->height);
 
 	window = hash_table_lookup(wm->window_hash, configure_notify->window);
-	weston_wm_window_get_child_position(window, &x, &y);
 	window->x = configure_notify->x;
 	window->y = configure_notify->y;
 	if (window->override_redirect) {
 		window->width = configure_notify->width;
 		window->height = configure_notify->height;
+		if (window->frame)
+			frame_resize_inside(window->frame,
+					    window->width, window->height);
 	}
 }
 
@@ -679,11 +685,15 @@ weston_wm_window_activate(struct wl_listener *listener, void *data)
 				     XCB_TIME_CURRENT_TIME);
 	}
 
-	if (wm->focus_window)
+	if (wm->focus_window) {
+		frame_unset_flag(wm->focus_window->frame, FRAME_FLAG_ACTIVE);
 		weston_wm_window_schedule_repaint(wm->focus_window);
+	}
 	wm->focus_window = window;
-	if (wm->focus_window)
+	if (wm->focus_window) {
+		frame_set_flag(wm->focus_window->frame, FRAME_FLAG_ACTIVE);
 		weston_wm_window_schedule_repaint(wm->focus_window);
+	}
 }
 
 static void
@@ -761,6 +771,11 @@ weston_wm_window_create_frame(struct weston_wm_window *window)
 	uint32_t values[3];
 	int x, y, width, height;
 
+	window->frame = frame_create(window->wm->theme,
+				     window->width, window->height,
+				     FRAME_BUTTON_CLOSE, window->name);
+	frame_resize_inside(window->frame, window->width, window->height);
+
 	weston_wm_window_get_frame_size(window, &width, &height);
 	weston_wm_window_get_child_position(window, &x, &y);
 
@@ -889,7 +904,8 @@ weston_wm_window_draw_decoration(void *data)
 	struct theme *t = wm->theme;
 	cairo_t *cr;
 	int x, y, width, height;
-	const char *title;
+	int32_t input_x, input_y, input_w, input_h;
+
 	uint32_t flags = 0;
 
 	weston_wm_window_read_properties(window);
@@ -908,12 +924,7 @@ weston_wm_window_draw_decoration(void *data)
 		if (wm->focus_window == window)
 			flags |= THEME_FRAME_ACTIVE;
 
-		if (window->name)
-			title = window->name;
-		else
-			title = "untitled";
-
-		theme_render_frame(t, cr, width, height, title, flags);
+		frame_repaint(window->frame, cr);
 	} else {
 		cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
 		cairo_set_source_rgba(cr, 0, 0, 0, 0);
@@ -944,10 +955,10 @@ weston_wm_window_draw_decoration(void *data)
 
 	if (window->surface && !window->fullscreen) {
 		pixman_region32_fini(&window->surface->pending.input);
+		frame_input_rect(window->frame, &input_x, &input_y,
+				 &input_w, &input_h);
 		pixman_region32_init_rect(&window->surface->pending.input,
-					  t->margin, t->margin,
-					  width - 2 * t->margin,
-					  height - 2 * t->margin);
+					  input_x, input_y, input_w, input_h);
 	}
 }
 
@@ -1241,6 +1252,10 @@ weston_wm_window_handle_state(struct weston_wm_window *window,
 			shell_interface->set_toplevel(window->shsurf);
 			window->width = window->saved_width;
 			window->height = window->saved_height;
+			if (window->frame)
+				frame_resize_inside(window->frame,
+						    window->width,
+						    window->height);
 			weston_wm_window_configure(window);
 		}
 	}
@@ -1393,9 +1408,9 @@ weston_wm_destroy_cursors(struct weston_wm *wm)
 }
 
 static int
-get_cursor_for_location(struct theme *t, int width, int height, int x, int y)
+get_cursor_for_location(enum theme_location location)
 {
-	int location = theme_get_location(t, x, y, width, height, 0);
+	// int location = theme_get_location(t, x, y, width, height, 0);
 
 	switch (location) {
 		case THEME_LOCATION_RESIZING_TOP:
@@ -1439,6 +1454,23 @@ weston_wm_window_set_cursor(struct weston_wm *wm, xcb_window_t window_id,
 }
 
 static void
+weston_wm_window_close(struct weston_wm_window *window)
+{
+	xcb_client_message_event_t client_message;
+
+	client_message.response_type = XCB_CLIENT_MESSAGE;
+	client_message.format = 32;
+	client_message.window = window->id;
+	client_message.type = window->wm->atom.wm_protocols;
+	client_message.data.data32[0] = window->wm->atom.wm_delete_window;
+	client_message.data.data32[1] = XCB_TIME_CURRENT_TIME;
+
+	xcb_send_event(window->wm->conn, 0, window->id, 
+		       XCB_EVENT_MASK_NO_EVENT,
+		       (char *) &client_message);
+}
+
+static void
 weston_wm_handle_button(struct weston_wm *wm, xcb_generic_event_t *event)
 {
 	xcb_button_press_event_t *button = (xcb_button_press_event_t *) event;
@@ -1447,41 +1479,42 @@ weston_wm_handle_button(struct weston_wm *wm, xcb_generic_event_t *event)
 	struct weston_seat *seat = weston_wm_pick_seat(wm);
 	struct weston_wm_window *window;
 	enum theme_location location;
-	struct theme *t = wm->theme;
-	int width, height;
+	enum frame_button_state button_state;
+	uint32_t button_id;
 
 	wm_log("XCB_BUTTON_%s (detail %d)\n",
 	       button->response_type == XCB_BUTTON_PRESS ?
 	       "PRESS" : "RELEASE", button->detail);
 
 	window = hash_table_lookup(wm->window_hash, button->event);
-	weston_wm_window_get_frame_size(window, &width, &height);
+	if (!window || !window->decorate)
+		return;
 
-	if (button->response_type == XCB_BUTTON_PRESS &&
-	    button->detail == 1) {
-		location = theme_get_location(t,
-					      button->event_x,
-					      button->event_y,
-					      width, height, 0);
+	if (button->detail != 1 && button->detail != 2)
+		return;
+	
+	button_state = button->response_type == XCB_BUTTON_PRESS ?
+		FRAME_BUTTON_PRESSED : FRAME_BUTTON_RELEASED;
+	button_id = button->detail == 1 ? BTN_LEFT : BTN_RIGHT;
+	
+	location = frame_pointer_button(window->frame, NULL,
+					button_id, button_state);
+	if (frame_status(window->frame) & FRAME_STATUS_REPAINT)
+		weston_wm_window_schedule_repaint(window);
 
-		switch (location) {
-		case THEME_LOCATION_TITLEBAR:
-			shell_interface->move(window->shsurf, seat);
-			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:
-			shell_interface->resize(window->shsurf,
-						seat, location);
-			break;
-		default:
-			break;
-		}
+	if (frame_status(window->frame) & FRAME_STATUS_MOVE) {
+		shell_interface->move(window->shsurf, seat);
+		frame_status_clear(window->frame, FRAME_STATUS_MOVE);
+	}
+
+	if (frame_status(window->frame) & FRAME_STATUS_RESIZE) {
+		shell_interface->resize(window->shsurf, seat, location);
+		frame_status_clear(window->frame, FRAME_STATUS_RESIZE);
+	}
+
+	if (frame_status(window->frame) & FRAME_STATUS_CLOSE) {
+		weston_wm_window_close(window);
+		frame_status_clear(window->frame, FRAME_STATUS_CLOSE);
 	}
 }
 
@@ -1490,16 +1523,19 @@ weston_wm_handle_motion(struct weston_wm *wm, xcb_generic_event_t *event)
 {
 	xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *) event;
 	struct weston_wm_window *window;
-	int cursor, width, height;
+	enum theme_location location;
+	int cursor;
 
 	window = hash_table_lookup(wm->window_hash, motion->event);
 	if (!window || !window->decorate)
 		return;
 
-	weston_wm_window_get_frame_size(window, &width, &height);
-	cursor = get_cursor_for_location(wm->theme, width, height,
-					 motion->event_x, motion->event_y);
+	location = frame_pointer_motion(window->frame, NULL,
+					motion->event_x, motion->event_y);
+	if (frame_status(window->frame) & FRAME_STATUS_REPAINT)
+		weston_wm_window_schedule_repaint(window);
 
+	cursor = get_cursor_for_location(location);
 	weston_wm_window_set_cursor(wm, window->frame_id, cursor);
 }
 
@@ -1508,16 +1544,19 @@ weston_wm_handle_enter(struct weston_wm *wm, xcb_generic_event_t *event)
 {
 	xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *) event;
 	struct weston_wm_window *window;
-	int cursor, width, height;
+	enum theme_location location;
+	int cursor;
 
 	window = hash_table_lookup(wm->window_hash, enter->event);
 	if (!window || !window->decorate)
 		return;
+	
+	location = frame_pointer_enter(window->frame, NULL,
+				       enter->event_x, enter->event_y);
+	if (frame_status(window->frame) & FRAME_STATUS_REPAINT)
+		weston_wm_window_schedule_repaint(window);
 
-	weston_wm_window_get_frame_size(window, &width, &height);
-	cursor = get_cursor_for_location(wm->theme, width, height,
-					 enter->event_x, enter->event_y);
-
+	cursor = get_cursor_for_location(location);
 	weston_wm_window_set_cursor(wm, window->frame_id, cursor);
 }
 
@@ -1531,6 +1570,10 @@ weston_wm_handle_leave(struct weston_wm *wm, xcb_generic_event_t *event)
 	if (!window || !window->decorate)
 		return;
 
+	frame_pointer_leave(window->frame, NULL);
+	if (frame_status(window->frame) & FRAME_STATUS_REPAINT)
+		weston_wm_window_schedule_repaint(window);
+
 	weston_wm_window_set_cursor(wm, window->frame_id, XWM_CURSOR_LEFT_PTR);
 }
 
@@ -2036,6 +2079,9 @@ send_configure(struct weston_surface *surface,
 		window->height = height - vborder;
 	else
 		window->height = 1;
+	
+	if (window->frame)
+		frame_resize_inside(window->frame, window->width, window->height);
 
 	if (window->configure_source)
 		return;
-- 
1.8.3.1



More information about the wayland-devel mailing list