[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