source: trunk/third/gnome-core/panel/tasklist_icon.c @ 17152

Revision 17152, 8.5 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17151, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * This has been stolen from the tasklist and then greatly wacked into
3 * shape by jacob and me.  This code needs some nicer place to live then
4 * like this
5 */
6#include "config.h"
7
8#include <X11/Xlib.h>
9#include <X11/Xutil.h>
10#include <gdk-pixbuf/gdk-pixbuf.h>
11#include <gdk/gdkx.h>
12#include <gnome.h>
13#include "gwmh.h"
14#include "xstuff.h"
15
16#include "tasklist_icon.h"
17
18/* so this stuff goes pixmap -> pixbuf -> pixmap, which sucks.
19 * it doesn't need to, except for visuals etc.
20 * someone who understands that stuff better should fix it
21 */
22
23static GdkPixbuf *tasklist_icon_check_mini (GwmhTask *task, GtkWidget *widget);
24static GdkPixbuf *tasklist_icon_check_x (GwmhTask *task, GtkWidget *widget);
25
26#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
27
28/* Shamelessly stolen from gwmh.c by Tim Janik */
29
30static GdkPixbuf *
31tasklist_icon_check_mini (GwmhTask *task,  GtkWidget *widget)
32{
33        GdkGC *gc;
34        int x, y, b, width, height, depth;
35        guint32 *atomdata;
36        Window root;
37        GdkImage *image;
38        GdkPixmap *pixmap;
39        GdkBitmap *mask;
40        GdkPixbuf *pixbuf, *pixbuf2;
41        gint size;
42        static gulong KWM_WIN_ICON = 0;
43        Display *xdisplay;
44        guchar *data;
45       
46        if (!KWM_WIN_ICON) {
47                KWM_WIN_ICON = gdk_atom_intern ("KWM_WIN_ICON", FALSE);
48        }
49
50        xdisplay = GDK_WINDOW_XDISPLAY (task->gdkwindow);
51       
52        atomdata = get_typed_property_data (xdisplay,
53                                            task->xwin,
54                                            KWM_WIN_ICON,
55                                            KWM_WIN_ICON,
56                                            &size,
57                                            32);
58        if (!atomdata)
59                return NULL;
60       
61        if (!atomdata[0]) {
62                g_free (atomdata);
63                return NULL;
64        }
65
66        gdk_error_trap_push ();
67
68        /* Get icon size and depth */
69        XGetGeometry (xdisplay, (Drawable)atomdata[0], &root, &x, &y,
70                      &width, &height, &b, &depth);
71       
72        if (gdk_error_trap_pop () != 0 ||
73            width > 65535 || height > 65535)
74                return FALSE;
75
76
77        gdk_error_trap_push ();
78
79        /* Create a new GdkPixmap and copy the mini icon pixmap to it */
80        pixmap = gdk_pixmap_new (widget->window, width, height, depth);
81        gc = gdk_gc_new (pixmap);
82        XCopyArea (GDK_WINDOW_XDISPLAY (pixmap), atomdata[0], GDK_WINDOW_XWINDOW (pixmap),
83                   GDK_GC_XGC (gc), 0, 0, width, height, 0, 0);
84        gdk_gc_destroy (gc);
85       
86        pixbuf = gdk_pixbuf_get_from_drawable (NULL,
87                                               pixmap,
88                                               gtk_widget_get_colormap (widget),
89                                               0, 0,
90                                               0, 0,
91                                               width, height);
92        gdk_pixmap_unref (pixmap);
93       
94        if (size > 1 && atomdata[1]) {
95                mask = gdk_pixmap_new (widget->window, width, height, depth);
96                gc = gdk_gc_new (mask);
97                gdk_gc_set_background (gc, &widget->style->black);
98                gdk_gc_set_foreground (gc, &widget->style->white);
99                XCopyPlane (GDK_DISPLAY (), atomdata[1], GDK_WINDOW_XWINDOW (mask),
100                            GDK_GC_XGC (gc), 0, 0, width, height, 0, 0, 1);
101                gdk_gc_unref (gc);
102               
103                image = gdk_image_get (mask, 0, 0, width, height);
104                g_return_val_if_fail (image != NULL, FALSE);
105       
106                pixbuf2 = pixbuf;
107                pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
108                gdk_pixbuf_unref(pixbuf2);
109               
110                data = gdk_pixbuf_get_pixels (pixbuf);
111                for (y = 0; y < gdk_pixbuf_get_height (pixbuf); y++)
112                        for (x = 0; x < gdk_pixbuf_get_width (pixbuf); x++)
113                        {
114                                data += 3;
115                                *data++ = gdk_image_get_pixel (image, x, y) == 0 ? 0 : 255;
116                        }
117                gdk_pixmap_unref (mask);
118                gdk_image_destroy(image);       
119        }
120
121        gdk_flush ();
122        gdk_error_trap_pop ();
123
124        g_free (atomdata);
125       
126        return pixbuf;
127}
128
129static GdkPixbuf *
130tasklist_icon_check_x (GwmhTask *task,  GtkWidget *widget)
131{
132        XWMHints * wmhints;
133        GdkPixmap *pixmap, *mask;
134        GdkPixbuf *pixbuf, *scaled;
135        GdkImage *image;
136        GdkGC *gc;
137        Window root;
138        int x, y;
139        unsigned int width, height;
140        unsigned int border_width;
141        unsigned int depth;
142        guchar *data;
143
144        gdk_error_trap_push ();
145       
146        wmhints = XGetWMHints (GDK_DISPLAY (), task->xwin);
147
148        if (!wmhints) {
149                gdk_flush ();
150                gdk_error_trap_pop ();
151                return NULL;
152        }
153       
154        if (!(wmhints->flags & IconPixmapHint)) {
155                XFree (wmhints);
156                gdk_flush ();
157                gdk_error_trap_pop ();
158                return NULL;
159        }
160       
161        XGetGeometry (GDK_DISPLAY (), wmhints->icon_pixmap, &root,
162                      &x, &y, &width, &height,
163                      &border_width, &depth);
164       
165        if (width > 65535 || height > 65535) {
166                XFree (wmhints);
167                gdk_flush ();
168                gdk_error_trap_pop ();
169                return NULL;
170        }
171       
172        pixmap = gdk_pixmap_new (widget->window, width, height, -1);   
173        gc = gdk_gc_new (pixmap);
174
175        if (depth == 1) {
176                gdk_gc_set_background (gc, &widget->style->white);
177                gdk_gc_set_foreground (gc, &widget->style->black);
178                XCopyPlane (GDK_DISPLAY (), wmhints->icon_pixmap, GDK_WINDOW_XWINDOW (pixmap),
179                           GDK_GC_XGC (gc), 0, 0, width, height, 0, 0, 1);
180        }
181        else {
182                XCopyArea (GDK_DISPLAY (), wmhints->icon_pixmap, GDK_WINDOW_XWINDOW (pixmap),
183                           GDK_GC_XGC (gc), 0, 0, width, height, 0, 0);
184        }
185        pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
186                                               gtk_widget_get_colormap (widget),
187                                               0, 0,
188                                               0, 0, width, height);
189        gdk_gc_destroy (gc);
190
191        if (depth == 1) {
192                scaled = pixbuf;
193                pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
194                gdk_pixbuf_unref(scaled);
195        }
196       
197        if (wmhints->flags & IconMaskHint) {
198               mask = gdk_pixmap_new (widget->window, width, height, depth);
199               gc = gdk_gc_new (mask);
200               gdk_gc_set_background (gc, &widget->style->black);
201               gdk_gc_set_foreground (gc, &widget->style->white);
202               XCopyPlane (GDK_DISPLAY (), wmhints->icon_mask, GDK_WINDOW_XWINDOW (mask),
203                           GDK_GC_XGC (gc), 0, 0, width, height, 0, 0, 1);
204               gdk_gc_unref (gc);
205
206               image = gdk_image_get (mask, 0, 0, width, height);
207               g_return_val_if_fail (image != NULL, FALSE);
208               
209               scaled = pixbuf;
210               pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
211               gdk_pixbuf_unref (scaled);
212
213               data = gdk_pixbuf_get_pixels (pixbuf);
214               for (y = 0; y < gdk_pixbuf_get_height (pixbuf); y++)
215                 for (x = 0; x < gdk_pixbuf_get_width (pixbuf); x++)
216                   {
217                     data += 3;
218                     *data++ = gdk_image_get_pixel (image, x, y) == 0 ? 0 : 255;
219                   }
220
221               gdk_pixmap_unref (mask);
222               gdk_image_destroy (image);
223        }
224
225        scaled = gdk_pixbuf_scale_simple (pixbuf, 20, 20,
226                                          GDK_INTERP_BILINEAR);
227        gdk_pixbuf_unref (pixbuf);
228        gdk_pixmap_unref (pixmap);
229       
230        XFree (wmhints);
231
232        gdk_flush ();
233        gdk_error_trap_pop ();
234
235        return scaled;
236}
237
238static GdkPixbuf *
239tasklist_icon_create_minimized_icon (GtkWidget *widget, GdkPixbuf *pixbuf)
240{
241        GdkPixbuf *target;
242        gint i, j;
243        gint width, height, has_alpha, rowstride;
244        guchar *target_pixels;
245        guchar *original_pixels;
246        guchar *dest_pixel, *src_pixel;
247        gint32 red, green, blue;
248        GdkColor color;
249       
250        color = widget->style->bg[GTK_STATE_NORMAL];
251        red = color.red / 255;
252        blue = color.blue / 255;
253        green = color.green / 255;
254       
255        has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
256        width = gdk_pixbuf_get_width (pixbuf);
257        height = gdk_pixbuf_get_height (pixbuf);
258        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
259
260        target = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
261                                 has_alpha,
262                                 gdk_pixbuf_get_bits_per_sample (pixbuf),
263                                 width, height);
264
265        target_pixels = gdk_pixbuf_get_pixels (target);
266        original_pixels = gdk_pixbuf_get_pixels (pixbuf);
267
268        for (i = 0; i < height; i++) {
269                for (j = 0; j < width; j++) {
270                                src_pixel = original_pixels + i*rowstride + j*(has_alpha?4:3);
271                                dest_pixel = target_pixels + i*rowstride + j*(has_alpha?4:3);
272
273                                dest_pixel[0] = ((src_pixel[0] - red) >> 1) + red;
274                                dest_pixel[1] = ((src_pixel[1] - green) >> 1) + green;
275                                dest_pixel[2] = ((src_pixel[2] - blue) >> 1) + blue;
276                               
277                                if (has_alpha)
278                                        dest_pixel[3] = src_pixel[3];
279
280                }
281        }
282       
283        return target;
284}
285
286GtkWidget *
287get_task_icon (GwmhTask *task, GtkWidget *widget)
288{
289        GtkWidget *pixmap2;
290        GdkPixmap *pixmap;
291        GdkBitmap *mask;
292        GdkPixbuf *pixbuf;
293        GdkPixbuf *pixbuf2;
294       
295        pixbuf = tasklist_icon_check_x (task, widget);
296        if (!pixbuf) {
297                pixbuf = tasklist_icon_check_mini (task, widget);
298
299                if (!pixbuf)
300                        return NULL;
301        }
302        if (GWMH_TASK_ICONIFIED (task)) {
303                pixbuf2 = tasklist_icon_create_minimized_icon (widget,
304                                                                pixbuf);
305                gdk_pixbuf_unref (pixbuf);
306                pixbuf = pixbuf2;
307        }
308
309        gdk_pixbuf_render_pixmap_and_mask (pixbuf, &pixmap, &mask, 128);
310
311        gdk_pixbuf_unref (pixbuf);
312
313        if (!pixmap)
314                return NULL;
315       
316        pixmap2 = gtk_pixmap_new (pixmap, mask);
317        gtk_widget_show (pixmap2);
318
319        gdk_pixmap_unref (pixmap);
320        if (mask)
321                gdk_bitmap_unref (mask);
322
323        return pixmap2;
324}
Note: See TracBrowser for help on using the repository browser.