[PATCH weston v3] xwm: support maximizing xwayland windows

Bryce Harrington bryce at osg.samsung.com
Tue Jan 27 15:41:56 PST 2015


On Tue, Jan 27, 2015 at 03:24:54PM -0800, Bryce Harrington wrote:
> On Tue, Jan 27, 2015 at 07:40:46PM +0200, Giulio Camuffo wrote:
> > This patch adds the maximize button to the window frame for the windows
> > which set the MWM_DECOR_MAXIMIZE hint, and it wires it with the shell
> > via a new method in weston_shell_interface.
> > Additionally, it also listens for the wm hints coming from the client,
> > but it doesn't support maximizing a window only vertically or horizontally.
> > The window will be maximized only when both directions are maximized.
> > Reviewed-by: Daniel Stone <daniels at collabora.com>
> 
> Spotted one minor typo in a comment, but otherwise LGTM,

Also adds a warning:

  CC       xwayland/xwayland_la-window-manager.lo
xwayland/window-manager.c:1365:1: warning: no previous prototype for
‘weston_wm_window_is_maximized’ [-Wmissing-prototypes]
 weston_wm_window_is_maximized(struct weston_wm_window *window)
 ^

Perhaps this needs static added?

+inline bool
+weston_wm_window_is_maximized(struct weston_wm_window *window)
+{
+       return window->maximized_horz && window->maximized_vert;
+}

Also, I don't know how hard it would be to add but it would be nice to
have test cases for window minimize and maximize.  But since I don't
know if that can be easily done within our current infrastructure, that
can be left as a future todo.

> Reviewed-by: Bryce Harrington <bryce at osg.samsung.com>
> 
> > ---
> > 
> > v3: -added a function to reduce repetition of the same maximized check
> >     -add back window->shsurf guard
> > 
> >  desktop-shell/shell.c     | 72 +++++++++++++++++++++++-------------
> >  src/compositor.h          |  1 +
> >  xwayland/window-manager.c | 93 ++++++++++++++++++++++++++++++++++++++++-------
> >  xwayland/xwayland.h       |  2 +
> >  4 files changed, 129 insertions(+), 39 deletions(-)
> > 
> > diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
> > index a7514f7..9815269 100644
> > --- a/desktop-shell/shell.c
> > +++ b/desktop-shell/shell.c
> > @@ -3000,6 +3000,51 @@ shell_interface_set_fullscreen(struct shell_surface *shsurf,
> >  	set_fullscreen(shsurf, method, framerate, output);
> >  }
> >  
> > +static struct weston_output *
> > +get_focused_output(struct weston_compositor *compositor)
> > +{
> > +	struct weston_seat *seat;
> > +	struct weston_output *output = NULL;
> > +
> > +	wl_list_for_each(seat, &compositor->seat_list, link) {
> > +		/* Priority has touch focus, then pointer and
> > +		 * then keyboard focus. We should probably have
> > +		 * three for loops and check frist for touch,
> first
> 
> > +		 * then for pointer, etc. but unless somebody has some
> > +		 * objections, I think this is sufficient. */
> > +		if (seat->touch && seat->touch->focus)
> > +			output = seat->touch->focus->output;
> > +		else if (seat->pointer && seat->pointer->focus)
> > +			output = seat->pointer->focus->output;
> > +		else if (seat->keyboard && seat->keyboard->focus)
> > +			output = seat->keyboard->focus->output;
> > +
> > +		if (output)
> > +			break;
> > +	}
> > +
> > +	return output;
> > +}
> > +
> > +static void
> > +shell_interface_set_maximized(struct shell_surface *shsurf)
> > +{
> > +	struct weston_output *output;
> > +
> > +	surface_clear_next_states(shsurf);
> > +	shsurf->next_state.maximized = true;
> > +	shsurf->state_changed = true;
> > +	shsurf->type = SHELL_SURFACE_TOPLEVEL;
> > +
> > +	if (!weston_surface_is_mapped(shsurf->surface))
> > +		output = get_focused_output(shsurf->surface->compositor);
> > +	else
> > +		output = shsurf->surface->output;
> > +
> > +	shell_surface_set_output(shsurf, output);
> > +	send_configure_for_surface(shsurf);
> > +}
> > +
> >  static int
> >  shell_interface_move(struct shell_surface *shsurf, struct weston_seat *ws)
> >  {
> > @@ -3605,32 +3650,6 @@ get_primary_view(void *shell, struct shell_surface *shsurf)
> >  	return shsurf->view;
> >  }
> >  
> > -static struct weston_output *
> > -get_focused_output(struct weston_compositor *compositor)
> > -{
> > -	struct weston_seat *seat;
> > -	struct weston_output *output = NULL;
> > -
> > -	wl_list_for_each(seat, &compositor->seat_list, link) {
> > -		/* Priority has touch focus, then pointer and
> > -		 * then keyboard focus. We should probably have
> > -		 * three for loops and check frist for touch,
> > -		 * then for pointer, etc. but unless somebody has some
> > -		 * objections, I think this is sufficient. */
> > -		if (seat->touch && seat->touch->focus)
> > -			output = seat->touch->focus->output;
> > -		else if (seat->pointer && seat->pointer->focus)
> > -			output = seat->pointer->focus->output;
> > -		else if (seat->keyboard && seat->keyboard->focus)
> > -			output = seat->keyboard->focus->output;
> > -
> > -		if (output)
> > -			break;
> > -	}
> > -
> > -	return output;
> > -}
> > -
> >  static void
> >  shell_get_shell_surface(struct wl_client *client,
> >  			struct wl_resource *resource,
> > @@ -6624,6 +6643,7 @@ module_init(struct weston_compositor *ec,
> >  	ec->shell_interface.resize = surface_resize;
> >  	ec->shell_interface.set_title = set_title;
> >  	ec->shell_interface.set_window_geometry = set_window_geometry;
> > +	ec->shell_interface.set_maximized = shell_interface_set_maximized;
> >  
> >  	weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
> >  	weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
> > diff --git a/src/compositor.h b/src/compositor.h
> > index aa87ec0..5c0ea74 100644
> > --- a/src/compositor.h
> > +++ b/src/compositor.h
> > @@ -121,6 +121,7 @@ struct weston_shell_interface {
> >  	void (*set_window_geometry)(struct shell_surface *shsurf,
> >  				    int32_t x, int32_t y,
> >  				    int32_t width, int32_t height);
> > +	void (*set_maximized)(struct shell_surface *shsurf);
> >  };
> >  
> >  struct weston_animation {
> > diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c
> > index 6f1996f..cce99a6 100644
> > --- a/xwayland/window-manager.c
> > +++ b/xwayland/window-manager.c
> > @@ -144,6 +144,8 @@ struct weston_wm_window {
> >  	int fullscreen;
> >  	int has_alpha;
> >  	int delete_window;
> > +	int maximized_vert;
> > +	int maximized_horz;
> >  	struct wm_size_hints size_hints;
> >  	struct motif_wm_hints motif_hints;
> >  	struct wl_list link;
> > @@ -472,6 +474,10 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
> >  			for (i = 0; i < reply->value_len; i++)
> >  				if (atom[i] == wm->atom.net_wm_state_fullscreen)
> >  					window->fullscreen = 1;
> > +				if (atom[i] == wm->atom.net_wm_state_maximized_vert)
> > +					window->maximized_vert = 1;
> > +				if (atom[i] == wm->atom.net_wm_state_maximized_horz)
> > +					window->maximized_horz = 1;
> >  			break;
> >  		case TYPE_MOTIF_WM_HINTS:
> >  			memcpy(&window->motif_hints,
> > @@ -479,7 +485,7 @@ weston_wm_window_read_properties(struct weston_wm_window *window)
> >  			       sizeof window->motif_hints);
> >  			if (window->motif_hints.flags & MWM_HINTS_DECORATIONS)
> >  				window->decorate =
> > -					window->motif_hints.decorations > 0;
> > +					window->motif_hints.decorations;
> >  			break;
> >  		default:
> >  			break;
> > @@ -789,12 +795,16 @@ static void
> >  weston_wm_window_set_net_wm_state(struct weston_wm_window *window)
> >  {
> >  	struct weston_wm *wm = window->wm;
> > -	uint32_t property[1];
> > +	uint32_t property[3];
> >  	int i;
> >  
> >  	i = 0;
> >  	if (window->fullscreen)
> >  		property[i++] = wm->atom.net_wm_state_fullscreen;
> > +	if (window->maximized_vert)
> > +		property[i++] = wm->atom.net_wm_state_maximized_vert;
> > +	if (window->maximized_horz)
> > +		property[i++] = wm->atom.net_wm_state_maximized_horz;
> >  
> >  	xcb_change_property(wm->conn,
> >  			    XCB_PROP_MODE_REPLACE,
> > @@ -811,10 +821,14 @@ weston_wm_window_create_frame(struct weston_wm_window *window)
> >  	struct weston_wm *wm = window->wm;
> >  	uint32_t values[3];
> >  	int x, y, width, height;
> > +	int buttons = FRAME_BUTTON_CLOSE;
> > +
> > +	if (window->decorate & MWM_DECOR_MAXIMIZE)
> > +		buttons |= FRAME_BUTTON_MAXIMIZE;
> >  
> >  	window->frame = frame_create(window->wm->theme,
> >  				     window->width, window->height,
> > -				     FRAME_BUTTON_CLOSE, window->name);
> > +				     buttons, window->name);
> >  	frame_resize_inside(window->frame, window->width, window->height);
> >  
> >  	weston_wm_window_get_frame_size(window, &width, &height);
> > @@ -1303,6 +1317,28 @@ static void
> >  weston_wm_window_configure(void *data);
> >  
> >  static void
> > +weston_wm_window_set_toplevel(struct weston_wm_window *window)
> > +{
> > +	struct weston_shell_interface *shell_interface =
> > +		&window->wm->server->compositor->shell_interface;
> > +
> > +	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);
> > +}
> > +
> > +inline bool
> > +weston_wm_window_is_maximized(struct weston_wm_window *window)
> > +{
> > +	return window->maximized_horz && window->maximized_vert;
> > +}
> > +
> > +static void
> >  weston_wm_window_handle_state(struct weston_wm_window *window,
> >  			      xcb_client_message_event_t *client_message)
> >  {
> > @@ -1310,6 +1346,7 @@ weston_wm_window_handle_state(struct weston_wm_window *window,
> >  	struct weston_shell_interface *shell_interface =
> >  		&wm->server->compositor->shell_interface;
> >  	uint32_t action, property;
> > +	int maximized = weston_wm_window_is_maximized(window);
> >  
> >  	action = client_message->data.data32[0];
> >  	property = client_message->data.data32[1];
> > @@ -1327,15 +1364,26 @@ weston_wm_window_handle_state(struct weston_wm_window *window,
> >  								0, NULL);
> >  		} else {
> >  			if (window->shsurf)
> > -				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);
> > +				weston_wm_window_set_toplevel(window);
> > +		}
> > +	} else {
> > +		if (property == wm->atom.net_wm_state_maximized_vert &&
> > +		    update_state(action, &window->maximized_vert))
> > +			weston_wm_window_set_net_wm_state(window);
> > +		if (property == wm->atom.net_wm_state_maximized_horz &&
> > +		    update_state(action, &window->maximized_horz))
> > +			weston_wm_window_set_net_wm_state(window);
> > +
> > +		if (maximized != weston_wm_window_is_maximized(window)) {
> > +			if (weston_wm_window_is_maximized(window)) {
> > +				window->saved_width = window->width;
> > +				window->saved_height = window->height;
> > +
> > +				if (window->shsurf)
> > +					shell_interface->set_maximized(window->shsurf);
> > +			} else if (window->shsurf) {
> > +				weston_wm_window_set_toplevel(window);
> > +			}
> >  		}
> >  	}
> >  }
> > @@ -1667,6 +1715,19 @@ weston_wm_handle_button(struct weston_wm *wm, xcb_generic_event_t *event)
> >  		weston_wm_window_close(window, button->time);
> >  		frame_status_clear(window->frame, FRAME_STATUS_CLOSE);
> >  	}
> > +
> > +	if (frame_status(window->frame) & FRAME_STATUS_MAXIMIZE) {
> > +		window->maximized_horz = !window->maximized_horz;
> > +		window->maximized_vert = !window->maximized_vert;
> > +		if (weston_wm_window_is_maximized(window)) {
> > +			window->saved_width = window->width;
> > +			window->saved_height = window->height;
> > +			shell_interface->set_maximized(window->shsurf);
> > +		} else {
> > +			weston_wm_window_set_toplevel(window);
> > +		}
> > +		frame_status_clear(window->frame, FRAME_STATUS_MAXIMIZE);
> > +	}
> >  }
> >  
> >  static void
> > @@ -1855,6 +1916,8 @@ weston_wm_get_resources(struct weston_wm *wm)
> >  		{ "_NET_WM_PID",	F(atom.net_wm_pid) },
> >  		{ "_NET_WM_ICON",	F(atom.net_wm_icon) },
> >  		{ "_NET_WM_STATE",	F(atom.net_wm_state) },
> > +		{ "_NET_WM_STATE_MAXIMIZED_VERT", F(atom.net_wm_state_maximized_vert) },
> > +		{ "_NET_WM_STATE_MAXIMIZED_HORZ", F(atom.net_wm_state_maximized_horz) },
> >  		{ "_NET_WM_STATE_FULLSCREEN", F(atom.net_wm_state_fullscreen) },
> >  		{ "_NET_WM_USER_TIME", F(atom.net_wm_user_time) },
> >  		{ "_NET_WM_ICON_NAME", F(atom.net_wm_icon_name) },
> > @@ -2031,7 +2094,7 @@ weston_wm_create(struct weston_xserver *wxs, int fd)
> >  	struct wl_event_loop *loop;
> >  	xcb_screen_iterator_t s;
> >  	uint32_t values[1];
> > -	xcb_atom_t supported[3];
> > +	xcb_atom_t supported[5];
> >  
> >  	wm = zalloc(sizeof *wm);
> >  	if (wm == NULL)
> > @@ -2082,6 +2145,8 @@ weston_wm_create(struct weston_xserver *wxs, int fd)
> >  	supported[0] = wm->atom.net_wm_moveresize;
> >  	supported[1] = wm->atom.net_wm_state;
> >  	supported[2] = wm->atom.net_wm_state_fullscreen;
> > +	supported[3] = wm->atom.net_wm_state_maximized_vert;
> > +	supported[4] = wm->atom.net_wm_state_maximized_horz;
> >  	xcb_change_property(wm->conn,
> >  			    XCB_PROP_MODE_REPLACE,
> >  			    wm->screen->root,
> > @@ -2359,6 +2424,8 @@ xserver_map_shell_surface(struct weston_wm_window *window,
> >  					       parent->surface,
> >  					       window->x - parent->x,
> >  					       window->y - parent->y, flags);
> > +	} else if (weston_wm_window_is_maximized(window)) {
> > +		shell_interface->set_maximized(window->shsurf);
> >  	} else {
> >  		if (weston_wm_window_type_inactive(window)) {
> >  			shell_interface->set_xwayland(window->shsurf,
> > diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h
> > index 312c9b2..69fdcfd 100644
> > --- a/xwayland/xwayland.h
> > +++ b/xwayland/xwayland.h
> > @@ -102,6 +102,8 @@ struct weston_wm {
> >  		xcb_atom_t		 net_wm_pid;
> >  		xcb_atom_t		 net_wm_icon;
> >  		xcb_atom_t		 net_wm_state;
> > +		xcb_atom_t		 net_wm_state_maximized_vert;
> > +		xcb_atom_t		 net_wm_state_maximized_horz;
> >  		xcb_atom_t		 net_wm_state_fullscreen;
> >  		xcb_atom_t		 net_wm_user_time;
> >  		xcb_atom_t		 net_wm_icon_name;
> > -- 
> > 2.2.2
> > 
> > _______________________________________________
> > wayland-devel mailing list
> > wayland-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list