summaryrefslogtreecommitdiff
path: root/libmdock/thumbnailer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmdock/thumbnailer.c')
-rw-r--r--libmdock/thumbnailer.c135
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;
+}