xwm: Add icon support to the frame

This fetches the _NET_WM_ICON property of the X11 window, and use the
first image found as the frame icon.

This has been tested with various X11 programs, and improves usability
and user-friendliness a bit.

Changes since v1:
- Changed frame_button_create() to use
  frame_button_create_from_surface() internally.
- Removed a check that should never have been commited.

Changes since v2:
- Request UINT32_MAX items instead of 2048, to avoid cutting valid
  icons.
- Strengthen checks against malformed input.
- Handle XCB_PROPERTY_DELETE to remove the icon.
- Schedule a repaint if the icon changed.

Changes since v3:
- Keep the previous Cairo surface until the new one has been
  successfully loaded.
- Use uint32_t for cardinals.  Unsigned is the same type except on
  16-bit machines, but uint32_t is clearer.
- Declare length as uint32_t too, like in xcb_get_property_reply_t.

Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
Reviewed-by: Quentin Glidic <sardemff7+git@sardemff7.net>
This commit is contained in:
Emmanuel Gil Peyrot
2017-12-01 19:20:40 +01:00
committed by Daniel Stone
parent cb04cc4f68
commit 6b58ea8c43
5 changed files with 107 additions and 20 deletions
+1 -1
View File
@@ -126,7 +126,7 @@ enum {
struct frame *
frame_create(struct theme *t, int32_t width, int32_t height, uint32_t buttons,
const char *title);
const char *title, cairo_surface_t *icon);
void
frame_destroy(struct frame *frame);
+40 -14
View File
@@ -108,9 +108,9 @@ struct frame {
};
static struct frame_button *
frame_button_create(struct frame *frame, const char *icon,
enum frame_status status_effect,
enum frame_button_flags flags)
frame_button_create_from_surface(struct frame *frame, cairo_surface_t *icon,
enum frame_status status_effect,
enum frame_button_flags flags)
{
struct frame_button *button;
@@ -118,12 +118,7 @@ frame_button_create(struct frame *frame, const char *icon,
if (!button)
return NULL;
button->icon = cairo_image_surface_create_from_png(icon);
if (!button->icon) {
free(button);
return NULL;
}
button->icon = icon;
button->frame = frame;
button->flags = flags;
button->status_effect = status_effect;
@@ -133,6 +128,30 @@ frame_button_create(struct frame *frame, const char *icon,
return button;
}
static struct frame_button *
frame_button_create(struct frame *frame, const char *icon_name,
enum frame_status status_effect,
enum frame_button_flags flags)
{
struct frame_button *button;
cairo_surface_t *icon;
icon = cairo_image_surface_create_from_png(icon_name);
if (cairo_surface_status(icon) != CAIRO_STATUS_SUCCESS)
goto error;
button = frame_button_create_from_surface(frame, icon, status_effect,
flags);
if (!button)
goto error;
return button;
error:
cairo_surface_destroy(icon);
return NULL;
}
static void
frame_button_destroy(struct frame_button *button)
{
@@ -305,7 +324,7 @@ frame_destroy(struct frame *frame)
struct frame *
frame_create(struct theme *t, int32_t width, int32_t height, uint32_t buttons,
const char *title)
const char *title, cairo_surface_t *icon)
{
struct frame *frame;
struct frame_button *button;
@@ -332,10 +351,17 @@ frame_create(struct theme *t, int32_t width, int32_t height, uint32_t buttons,
}
if (title) {
button = frame_button_create(frame,
DATADIR "/weston/icon_window.png",
FRAME_STATUS_MENU,
FRAME_BUTTON_CLICK_DOWN);
if (icon) {
button = frame_button_create_from_surface(frame,
icon,
FRAME_STATUS_MENU,
FRAME_BUTTON_CLICK_DOWN);
} else {
button = frame_button_create(frame,
DATADIR "/weston/icon_window.png",
FRAME_STATUS_MENU,
FRAME_BUTTON_CLICK_DOWN);
}
if (!button)
goto free_frame;
}