Adding upstream version 0.3.5.2+svn20080509.
[debian/lxpanel.git] / src / bg.c
CommitLineData
6cc5e1a6
DB
1/*
2 * fb-background-monitor.c:
3 *
4 * Copyright (C) 2001, 2002 Ian McKellar <yakk@yakk.net>
5 * 2002 Sun Microsystems, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
21 *
22 * Authors:
23 * Ian McKellar <yakk@yakk.net>
24 * Mark McLoughlin <mark@skynet.ie>
25 */
26
27#include <glib.h>
28#include <glib-object.h>
29#include <gdk/gdk.h>
30#include <gdk/gdkx.h>
31#include <X11/Xlib.h>
32#include <X11/Xatom.h>
33
34#include "bg.h"
35
36//#define DEBUG
37#include "dbg.h"
38
39
40enum {
41 CHANGED,
42 LAST_SIGNAL
43};
44
45
46struct _FbBgClass {
47 GObjectClass parent_class;
48 void (*changed) (FbBg *monitor);
49};
50
51struct _FbBg {
52 GObject parent_instance;
53
54 Window xroot;
55 Atom id;
56 GC gc;
57 Display *dpy;
58 Pixmap pixmap;
59};
60
61static void fb_bg_class_init (FbBgClass *klass);
62static void fb_bg_init (FbBg *monitor);
63static void fb_bg_finalize (GObject *object);
64static Pixmap fb_bg_get_xrootpmap(FbBg *monitor);
65static void fb_bg_changed(FbBg *monitor);
66
67
68static guint signals [LAST_SIGNAL] = { 0 };
69
70static FbBg *default_bg = NULL;
71
72GType
73fb_bg_get_type (void)
74{
75 static GType object_type = 0;
76
77 if (!object_type) {
78 static const GTypeInfo object_info = {
79 sizeof (FbBgClass),
80 (GBaseInitFunc) NULL,
81 (GBaseFinalizeFunc) NULL,
82 (GClassInitFunc) fb_bg_class_init,
83 NULL, /* class_finalize */
84 NULL, /* class_data */
85 sizeof (FbBg),
86 0, /* n_preallocs */
87 (GInstanceInitFunc) fb_bg_init,
88 };
89
90 object_type = g_type_register_static (
91 G_TYPE_OBJECT, "FbBg", &object_info, 0);
92 }
93
94 return object_type;
95}
96
97
98
99static void
100fb_bg_class_init (FbBgClass *klass)
101{
102 GObjectClass *object_class = G_OBJECT_CLASS (klass);
103 ENTER;
104 signals [CHANGED] =
105 g_signal_new ("changed",
106 G_OBJECT_CLASS_TYPE (object_class),
107 G_SIGNAL_RUN_FIRST,
108 G_STRUCT_OFFSET (FbBgClass, changed),
109 NULL, NULL,
110 g_cclosure_marshal_VOID__VOID,
111 G_TYPE_NONE, 0);
112 klass->changed = fb_bg_changed;
113 object_class->finalize = fb_bg_finalize;
114 RET();
115}
116
117static void
118fb_bg_init (FbBg *bg)
119{
120 XGCValues gcv;
121 uint mask;
122
123 ENTER;
124 bg->dpy = GDK_DISPLAY();
125 bg->xroot = DefaultRootWindow(bg->dpy);
126 bg->id = XInternAtom(bg->dpy, "_XROOTPMAP_ID", False);
127 bg->pixmap = fb_bg_get_xrootpmap(bg);
128 gcv.ts_x_origin = 0;
129 gcv.ts_y_origin = 0;
130 gcv.fill_style = FillTiled;
131 mask = GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle;
132 if (bg->pixmap != None) {
133 gcv.tile = bg->pixmap;
134 mask |= GCTile ;
135 }
136 bg->gc = XCreateGC (bg->dpy, bg->xroot, mask, &gcv) ;
137 RET();
138}
139
140
141FbBg *
142fb_bg_new()
143{
144 ENTER;
145 RET(g_object_new (FB_TYPE_BG, NULL));
146}
147
148static void
149fb_bg_finalize (GObject *object)
150{
151 FbBg *bg;
152
153 ENTER;
154 bg = FB_BG (object);
155 XFreeGC(bg->dpy, bg->gc);
156 RET();
157}
158
159
160static Pixmap
161fb_bg_get_xrootpmap(FbBg *bg)
162{
163 Pixmap ret = None;
164
165 ENTER;
166 if (bg->id) {
167 int act_format, c = 2 ;
168 u_long nitems ;
169 u_long bytes_after ;
170 u_char *prop = NULL;
171 Atom ret_type;
172
173 do {
174 if (XGetWindowProperty(bg->dpy, bg->xroot, bg->id, 0, 1,
175 False, XA_PIXMAP, &ret_type, &act_format,
176 &nitems, &bytes_after, &prop) == Success) {
177 if (ret_type == XA_PIXMAP) {
178 ret = *((Pixmap *)prop);
179 XFree(prop);
180 break;
181 }
182 }
183 } while (--c > 0);
184 }
185 RET(ret);
186
187}
188
189
190GdkPixmap *
191fb_bg_get_xroot_pix_for_win(FbBg *bg, GtkWidget *widget)
192{
193 Window win;
194 Window dummy;
195 Pixmap bgpix;
196 GdkPixmap *gbgpix;
197 guint width, height, border, depth;
198 int x, y;
199
200 ENTER;
201 win = GDK_WINDOW_XWINDOW(widget->window);
202 if (!XGetGeometry(bg->dpy, win, &dummy, &x, &y, &width, &height, &border,
203 &depth)) {
204 DBG2("XGetGeometry failed\n");
205 RET(NULL);
206 }
207 XTranslateCoordinates(bg->dpy, win, bg->xroot, 0, 0, &x, &y, &dummy);
208 DBG("win=%x %dx%d%+d%+d\n", win, width, height, x, y);
209 gbgpix = gdk_pixmap_new(NULL, width, height, depth);
210 if (!gbgpix) {
211 ERR("gdk_pixmap_new failed\n");
212 RET(NULL);
213 }
214 bgpix = gdk_x11_drawable_get_xid(gbgpix);
215 XSetTSOrigin(bg->dpy, bg->gc, -x, -y) ;
216 XFillRectangle(bg->dpy, bgpix, bg->gc, 0, 0, width, height);
217 RET(gbgpix);
218}
219
220void
221fb_bg_composite(GdkDrawable *base, GdkGC *gc, guint32 tintcolor, gint alpha)
222{
223 GdkPixbuf *ret, *ret2;
224 int w, h;
225 static GdkColormap *cmap = NULL;
226
227 ENTER;
228 gdk_drawable_get_size (base, &w, &h);
229 if (!cmap) {
230 cmap = gdk_colormap_get_system ();
231 }
232 DBG("here\n");
233 ret = gdk_pixbuf_get_from_drawable (NULL, base, cmap, 0, 0, 0, 0, w, h);
234 if (!ret)
235 RET();
236 DBG("here w=%d h=%d\n", w, h);
237 ret2 = gdk_pixbuf_composite_color_simple(ret, w, h,
238 GDK_INTERP_HYPER, 255-alpha, MIN(w, h), tintcolor, tintcolor);
239 DBG("here\n");
240 if (!ret2) {
241 g_object_unref(ret);
242 RET();
243 }
244 //gdk_pixbuf_render_to_drawable (ret2, base, gc, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
245 gdk_draw_pixbuf (base, gc, ret2, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
246 g_object_unref(ret);
247 g_object_unref(ret2);
248 RET();
249}
250
251
252static void
253fb_bg_changed(FbBg *bg)
254{
255 ENTER;
256 bg->pixmap = fb_bg_get_xrootpmap(bg);
257 if (bg->pixmap != None) {
258 XGCValues gcv;
259
260 gcv.tile = bg->pixmap;
261 XChangeGC(bg->dpy, bg->gc, GCTile, &gcv);
262 DBG("changed\n");
263 }
264 RET();
265}
266
267
268void fb_bg_notify_changed_bg(FbBg *bg)
269{
270 ENTER;
271 g_signal_emit (bg, signals [CHANGED], 0);
272 RET();
273}
274
275FbBg *fb_bg_get_for_display(void)
276{
277 ENTER;
278 if (!default_bg)
279 {
280 default_bg = fb_bg_new();
281 g_object_add_weak_pointer( default_bg, &default_bg );
282 }
283 else
284 g_object_ref(default_bg);
285 RET(default_bg);
286}
287
288GdkPixmap *
289fb_bg_get_pix_from_file(GtkWidget *widget, const char *filename)
290{
291 ENTER;
292 GdkPixbuf *pixbuf;
293 GdkPixmap *pixmap;
294
295 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
296 if (!pixbuf) {
297 RET(widget->style->bg_pixmap[0]);
298 }
299 pixmap = gdk_pixmap_new(widget->window, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), -1);
300 gdk_pixbuf_render_to_drawable(pixbuf,pixmap,
301 widget->style->fg_gc[GTK_STATE_NORMAL],
302 0,0,0,0,
303 gdk_pixbuf_get_width(pixbuf),
304 gdk_pixbuf_get_height(pixbuf),
305 GDK_RGB_DITHER_NORMAL,0,0);
306
307 g_object_unref( pixbuf );
308 RET(pixmap);
309}