[PATCH] Weston: window.c: add icon, minimize, maximize, close

Kristian Høgsberg hoegsberg at gmail.com
Wed May 2 06:34:09 PDT 2012


On Wed, May 02, 2012 at 01:00:10AM +0200, Martin Minarik wrote:
> This provides basic icon and minimize, maximize, close buttons for window
> frame.

Very nice, thanks for looking into this.

> ----
> 
> diff --git a/clients/window.c b/clients/window.c
> index 2390485..790e849 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -234,7 +234,11 @@ enum window_location {
>  	WINDOW_RESIZING_MASK = 15,
>  	WINDOW_EXTERIOR = 16,
>  	WINDOW_TITLEBAR = 17,
> -	WINDOW_CLIENT_AREA = 18,
> +	WINDOW_TITLEBAR_ITEM_ICON = 18,
> +	WINDOW_TITLEBAR_ITEM_CLOSE = 19,
> +	WINDOW_TITLEBAR_ITEM_MAXIMIZE = 20,
> +	WINDOW_TITLEBAR_ITEM_MINIMIZE = 21,
> +	WINDOW_CLIENT_AREA = 22,
>  };
> 
>  const char *option_xkb_layout = "us";
> @@ -504,16 +508,16 @@ display_create_surface_from_file(struct display
> *display,
>  	const char *filename;
>  	int hotspot_x, hotspot_y;
>  } pointer_images[] = {
> -	{ DATADIR "/weston/bottom_left_corner.png",	 6, 30 },
> -	{ DATADIR "/weston/bottom_right_corner.png",	28, 28 },
> -	{ DATADIR "/weston/bottom_side.png",		16, 20 },
> +	{ DATADIR "/weston/bottom_left_corner.png",	 7, 25 },
> +	{ DATADIR "/weston/bottom_right_corner.png",	25, 25 },
> +	{ DATADIR "/weston/bottom_side.png",		16, 25 },
>  	{ DATADIR "/weston/grabbing.png",		20, 17 },
>  	{ DATADIR "/weston/left_ptr.png",		10,  5 },
> -	{ DATADIR "/weston/left_side.png",		10, 20 },
> -	{ DATADIR "/weston/right_side.png",		30, 19 },
> -	{ DATADIR "/weston/top_left_corner.png",	 8,  8 },
> -	{ DATADIR "/weston/top_right_corner.png",	26,  8 },
> -	{ DATADIR "/weston/top_side.png",		18,  8 },
> +	{ DATADIR "/weston/left_side.png",		 7, 16 },
> +	{ DATADIR "/weston/right_side.png",		26, 16 },
> +	{ DATADIR "/weston/top_left_corner.png",	 6,  6 },
> +	{ DATADIR "/weston/top_right_corner.png",	24,  6 },
> +	{ DATADIR "/weston/top_side.png",		16,  5 },
>  	{ DATADIR "/weston/xterm.png",			15, 15 },
>  	{ DATADIR "/weston/hand1.png",			18, 11 }

What's up with these changes?  The hotspot location is take from the
DMZ theme, for example bottom_left_corner:

http://gitorious.org/opensuse/art/blobs/master/cursors/dmz/pngs/bottom_left_corner.in

for the 32x32 cursor, the hotspot there is 6,30.  Another good project
would be good to be parse Xcursor files instead of hardcoding a bunch
of pngs here.

>  };
> @@ -1017,9 +1021,25 @@ frame_redraw_handler(struct widget *widget, void
> *data)
>  	cairo_t *cr;
>  	cairo_text_extents_t extents;
>  	cairo_surface_t *source;
> -	int x, y, width, height;
> +	int x, y, width, height, a;
>  	struct window *window = widget->window;
> 
> +	cairo_surface_t* window_icon = cairo_image_surface_create_from_png(
> +		DATADIR "/weston/icon_window.png"
> +	);
> +
> +	cairo_surface_t* (sign[3]);
> +
> +	sign[0] = cairo_image_surface_create_from_png(
> +		DATADIR "/weston/sign_close.png"
> +	);
> +	sign[1] = cairo_image_surface_create_from_png(
> +		DATADIR "/weston/sign_maximize.png"
> +	);
> +	sign[2] = cairo_image_surface_create_from_png(
> +		DATADIR "/weston/sign_minimize.png"
> +	);
> +

We shouldn't be loading the pngs each in the rendering function.  Load
them up front in display_render_frame and keep the around like we do
with display->active_frame etc.  Having all that in struct display is
a bit of a hack, but we can fix that later.

>  	if (window->type == TYPE_FULLSCREEN)
>  		return;
> 
> @@ -1068,6 +1088,32 @@ frame_redraw_handler(struct widget *widget, void
> *data)
>  		cairo_show_text(cr, window->title);
>  	}
> 
> +	/* Window icon */
> +	cairo_set_source_surface(cr, window_icon,
> +		 frame->margin+frame->width, frame->margin+frame->width);
> +	cairo_paint(cr);
> +
> +	/* 3 window buttons, 25x14 pixels */
> +	cairo_set_line_width(cr, 1);
> +
> +	for (a=0; a<3; a++){
> +		unsigned int x,y;
> +
> +		x=width - frame->margin - frame->width - (a+1)*25 - a*6-2;
> +		y=frame->margin+frame->width+1;

Please follow the code style and add spaces around operators, that is,
do this instead:

	y = frame->margin + frame->width + 1;

etc.

> +		cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
> +		cairo_rectangle (cr, x, y, 25, 14);
> +
> +		cairo_stroke_preserve(cr);
> +		cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
> +		cairo_fill (cr);
> +
> +		cairo_set_source_surface(cr, sign[a],
> +			 x+6, y+1);
> +		cairo_paint(cr);
> +	}
> +
>  	cairo_destroy(cr);
>  }
> 
> @@ -1108,6 +1154,20 @@ frame_get_pointer_location(struct frame *frame,
> int32_t x, int32_t y)
>  	else if (location == WINDOW_INTERIOR)
>  		location = WINDOW_CLIENT_AREA;
> 
> +	/* Find icon or buttons in titlebar */
> +	if (location==WINDOW_TITLEBAR)
> +	if (x <= 16 + frame->margin + frame->width)
> +		location=WINDOW_TITLEBAR_ITEM_ICON;
> +	else if ((x > widget->allocation.width - frame->margin - frame->width -
> 27) &&
> +		 (x <= widget->allocation.width - frame->margin - frame->width))
> +		location=WINDOW_TITLEBAR_ITEM_CLOSE;
> +	else if ((x > widget->allocation.width - frame->margin - frame->width -
> 2*27 - 5) &&
> +		 (x <= widget->allocation.width - frame->margin - frame->width - 27 - 5))
> +		location=WINDOW_TITLEBAR_ITEM_MAXIMIZE;
> +	else if ((x > widget->allocation.width - frame->margin - frame->width -
> 3*27 - 10) &&
> +		 (x <= widget->allocation.width - frame->margin - frame->width - 2*27 -
> 10))
> +		location=WINDOW_TITLEBAR_ITEM_MINIMIZE;
> +

We should make the buttons widgets instead extending this ad-hoc hack.
Creating the buttons as widgets give you enter/leave events so you can
highlight the buttons and get button events in a callback.  Call
widget_add_widget(frame, button_data) to add a sub-widget to the frame
widget, then set button and redraw handlers to implement painting and
button click handling.

>  	return location;
>  }
> 
> @@ -1216,6 +1276,24 @@ frame_button_handler(struct widget *widget,
>  					      input_get_input_device(input),
>  					      display->serial);
>  			break;
> +		case WINDOW_TITLEBAR_ITEM_ICON:
> +			window_show_frame_menu(window, input, time);
> +			break;
> +		case WINDOW_TITLEBAR_ITEM_MINIMIZE:
> +			fprintf(stderr,"Minimize\n");
> +			/* TODO: Minimize */
> +			break;
> +		case WINDOW_TITLEBAR_ITEM_MAXIMIZE:
> +			fprintf(stderr,"Maximize\n");
> +			/* TODO: Maximize */
> +			break;

We do have a maximize request in wl_shell_surface you should use here.

> +		case WINDOW_TITLEBAR_ITEM_CLOSE:
> +			if (window->close_handler)
> +				window->close_handler(window->parent,
> +						      window->user_data);
> +			else
> +				display_exit(window->display);
> +			break;

All these cases should just be widget button callbacks.

>  		case WINDOW_RESIZING_TOP:
>  		case WINDOW_RESIZING_BOTTOM:
>  		case WINDOW_RESIZING_LEFT:
> @@ -1260,9 +1338,9 @@ frame_create(struct window *window, void *data)
>  	frame->widget = window_add_widget(window, frame);
>  	frame->child = widget_add_widget(frame->widget, data);
>  	frame->margin = 32;
> -	frame->width = 4;
> -	frame->titlebar_height = 30
> -;
> +	frame->width = 6;
> +	frame->titlebar_height = 27;
> +
>  	widget_set_redraw_handler(frame->widget, frame_redraw_handler);
>  	widget_set_resize_handler(frame->widget, frame_resize_handler);
>  	widget_set_enter_handler(frame->widget, frame_enter_handler);
> diff --git a/data/Makefile.am b/data/Makefile.am
> index 39b62ff..f789ad1 100644
> --- a/data/Makefile.am
> +++ b/data/Makefile.am
> @@ -1,6 +1,10 @@
>  westondatadir = $(datadir)/weston
> 
>  dist_westondata_DATA =				\
> +	icon_window.png				\
> +	sign_close.png				\
> +	sign_maximize.png			\
> +	sign_minimize.png			\
>  	bottom_left_corner.png			\
>  	bottom_right_corner.png			\
>  	bottom_side.png				\

If you send the patch with git send-email, git will encode the pngs
and include them in the patch.

Kristian


More information about the wayland-devel mailing list