diff options
Diffstat (limited to 'libmdock/thumbnailer.c')
-rw-r--r-- | libmdock/thumbnailer.c | 135 |
1 files changed, 135 insertions, 0 deletions
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 <dev.git@javispedro.com> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include <gdk/gdkx.h> +#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; +} |