From 54a82d533a67483b3c0eaf33a88914099fb498ee Mon Sep 17 00:00:00 2001 From: Javier Date: Thu, 22 Jan 2015 10:45:18 +0100 Subject: initial screenshot support --- libmdock/Makefile.am | 2 +- libmdock/mdock-item.c | 15 +++++- libmdock/mdock-widget.c | 1 + libmdock/thumbnailer.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++ libmdock/thumbnailer.h | 32 ++++++++++++ 5 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 libmdock/thumbnailer.c create mode 100644 libmdock/thumbnailer.h diff --git a/libmdock/Makefile.am b/libmdock/Makefile.am index dedf339..2d46925 100644 --- a/libmdock/Makefile.am +++ b/libmdock/Makefile.am @@ -1,5 +1,5 @@ lib_LTLIBRARIES = libmdock.la -libmdock_la_SOURCES = mdock-widget.h mdock-widget.c mdock-enums.h mdock-enums.c mdock-item.h mdock-item.c matcher.h matcher.c app-id.h app-id.c +libmdock_la_SOURCES = mdock-widget.h mdock-widget.c mdock-enums.h mdock-enums.c mdock-item.h mdock-item.c matcher.h matcher.c app-id.h app-id.c thumbnailer.h thumbnailer.c libmdock_la_CPPFLAGS = $(GTK_CFLAGS) $(GIO_CFLAGS) $(WNCK_CFLAGS) $(GTOP_CFLAGS) -D_GNU_SOURCE -DG_LOG_DOMAIN=\"libmdock\" libmdock_la_LIBADD = $(GTK_LIBS) $(GIO_LIBS) $(WNCK_LIBS) $(GTOP_LIBS) diff --git a/libmdock/mdock-item.c b/libmdock/mdock-item.c index 43dcdca..9a0572b 100644 --- a/libmdock/mdock-item.c +++ b/libmdock/mdock-item.c @@ -19,6 +19,7 @@ #include "mdock-enums.h" #include "mdock-item.h" +#include "thumbnailer.h" #define MDOCK_ITEM_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), MDOCK_TYPE_ITEM, MDockItemPrivate)) @@ -238,8 +239,15 @@ static gboolean mdock_item_expose(GtkWidget *widget, GdkEventExpose *event) cairo_t *cr = gdk_cairo_create(widget->window); if (self->priv->icon) { - gdk_cairo_set_source_pixbuf(cr, self->priv->icon, 0, 0); - cairo_paint(cr); + if (self->priv->windows) { + GdkPixmap *pix = thumbnailer_get_thumbnail(self->priv->windows->data); + if (pix) { + gdk_cairo_set_source_pixmap(cr, pix, 0, 0); + cairo_paint(cr); + } + } + //gdk_cairo_set_source_pixbuf(cr, self->priv->icon, 0, 0); + //cairo_paint(cr); } cairo_destroy(cr); @@ -408,6 +416,7 @@ void mdock_item_set_desktop_app_info(MDockItem *self, GDesktopAppInfo *app_info) void mdock_item_add_window(MDockItem *self, WnckWindow *window) { + thumbnailer_enable_for_window(window); self->priv->windows = g_list_append(self->priv->windows, window); if (!self->priv->icon) { mdock_item_update_icon(self); @@ -437,6 +446,8 @@ void mdock_item_set_last_active_window(MDockItem *self, WnckWindow *window) self->priv->windows = g_list_remove_link(self->priv->windows, l); self->priv->windows = g_list_concat(l, self->priv->windows); #endif + thumbnailer_update_thumbnail(window); + gtk_widget_queue_draw(GTK_WIDGET(self)); } gint mdock_item_get_num_windows(MDockItem *self) diff --git a/libmdock/mdock-widget.c b/libmdock/mdock-widget.c index ff2a7fd..81e492d 100644 --- a/libmdock/mdock-widget.c +++ b/libmdock/mdock-widget.c @@ -124,6 +124,7 @@ static void handle_window_opened(MDockWidget *self, WnckWindow *window, WnckScre g_settings_bind(self->priv->settings, "icon-size", item, "icon-size", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); + g_settings_set_uint(self->priv->settings, "icon-size", 128); mdock_item_add_window(item, window); diff --git a/libmdock/thumbnailer.c b/libmdock/thumbnailer.c new file mode 100644 index 0000000..774d04c --- /dev/null +++ b/libmdock/thumbnailer.c @@ -0,0 +1,135 @@ +/* + * Copyright 2015 Javier S. Pedro + * + * This file is part of MDock. + * + * MDock is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MDock is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MDock. If not, see . + */ + +#include +#include "thumbnailer.h" + +#define THUMBNAIL_MAX_WIDTH 128 +#define THUMBNAIL_MAX_HEIGHT 128 + +typedef struct _ThumbnailData +{ + GdkPixmap * pix; + guint update_source; + time_t timestamp; +} ThumbnailData; + +G_DEFINE_QUARK(mdock-thumbnail-data, mdock_thumbnail_data) + +static inline ThumbnailData * thumbnail_data_new() +{ + return g_slice_new0(ThumbnailData); +} + +static void thumbnail_data_destroy(ThumbnailData *tdata) +{ + g_clear_object(&tdata->pix); + if (tdata->update_source) g_source_remove(tdata->update_source); + g_slice_free(ThumbnailData, tdata); +} + +static void thumbnail_size(WnckWindow *window, int *thumb_w, int *thumb_h) +{ + int win_x, win_y, win_w, win_h; + +} + +void thumbnailer_enable_for_window(WnckWindow *window) +{ + g_object_set_qdata_full(G_OBJECT(window), + mdock_thumbnail_data_quark(), + thumbnail_data_new(), + (GDestroyNotify)thumbnail_data_destroy); +} + +static gboolean thumbnailer_do_update(gpointer data) +{ + ThumbnailData *tdata = g_object_get_qdata(G_OBJECT(data), mdock_thumbnail_data_quark()); + g_return_if_fail(tdata); + thumbnailer_update_thumbnail(WNCK_WINDOW(data)); + tdata->update_source = 0; + return G_SOURCE_REMOVE; +} + +void thumbnailer_schedule_update(WnckWindow *window) +{ + ThumbnailData *tdata = g_object_get_qdata(G_OBJECT(window), mdock_thumbnail_data_quark()); + g_return_if_fail(tdata); + if (!tdata->update_source) { + tdata->update_source = g_timeout_add(500, thumbnailer_do_update, window); + } +} + +void thumbnailer_update_thumbnail(WnckWindow *window) +{ + GdkDisplay *display = gdk_display_get_default(); + ThumbnailData *tdata = g_object_get_qdata(G_OBJECT(window), mdock_thumbnail_data_quark()); + g_return_if_fail(tdata); + + g_return_if_fail(wnck_window_is_active(window)); + + GdkWindow *root = gdk_get_default_root_window(); + + int screen_x, screen_y, win_x, win_y, win_w, win_h, thumb_w, thumb_h, cur_w, cur_h; + gdk_window_get_origin(root, &screen_x, &screen_y); + wnck_window_get_client_window_geometry(window, &win_x, &win_y, &win_w, &win_h); + + if (win_w > THUMBNAIL_MAX_WIDTH || win_h > THUMBNAIL_MAX_HEIGHT) { + if (win_h > win_w) { + thumb_w = (THUMBNAIL_MAX_HEIGHT * win_w) / win_h; + thumb_h = THUMBNAIL_MAX_HEIGHT; + } else { + thumb_w = THUMBNAIL_MAX_WIDTH; + thumb_h = (THUMBNAIL_MAX_WIDTH * win_h) / win_w; + } + } else { + thumb_w = win_w; + thumb_h = win_h; + } + + if (tdata->pix) { + gdk_pixmap_get_size(tdata->pix, &cur_w, &cur_h); + } + if (!tdata->pix || cur_w != thumb_w || cur_h != thumb_h) { + g_clear_object(&tdata->pix); + g_debug("Recreating pixmap for %s (%dx%d)", wnck_window_get_name(window), thumb_w, thumb_h); + tdata->pix = gdk_pixmap_new(root, thumb_w, thumb_h, -1); + } + + g_return_if_fail(tdata->pix); + + g_debug("Updating thumbnail for %s (%dx%d)", wnck_window_get_name(window), thumb_w, thumb_h); + + double scale_w = thumb_w / (double)win_w, scale_h = thumb_h / (double)win_h; + cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(tdata->pix)); + cairo_scale(cr, scale_w, scale_h); + gdk_cairo_set_source_window(cr, root, -(win_x - screen_x), -(win_y - screen_y)); + cairo_pattern_set_filter(cairo_get_source (cr), CAIRO_FILTER_FAST); + cairo_paint(cr); + cairo_destroy(cr); + + time(&tdata->timestamp); +} + +GdkPixmap * thumbnailer_get_thumbnail(WnckWindow *window) +{ + ThumbnailData *tdata = g_object_get_qdata(G_OBJECT(window), mdock_thumbnail_data_quark()); + g_return_val_if_fail(tdata, NULL); + return tdata->pix; +} diff --git a/libmdock/thumbnailer.h b/libmdock/thumbnailer.h new file mode 100644 index 0000000..d5c4c52 --- /dev/null +++ b/libmdock/thumbnailer.h @@ -0,0 +1,32 @@ +/* + * Copyright 2015 Javier S. Pedro + * + * This file is part of MDock. + * + * MDock is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MDock is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MDock. If not, see . + */ + +#ifndef _THUMBNAILER_H_ +#define _THUMBNAILER_H_ + +#define WNCK_I_KNOW_THIS_IS_UNSTABLE 1 +#include + +void thumbnailer_enable_for_window(WnckWindow *window); + +void thumbnailer_schedule_update(WnckWindow *window); +void thumbnailer_update_thumbnail(WnckWindow *window); +GdkPixmap * thumbnailer_get_thumbnail(WnckWindow *window); + +#endif -- cgit v1.2.3