Releasing debian version 0.5.10-1.
[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);
10862fa6 126 bg->id = gdk_x11_get_xatom_by_name("_XROOTPMAP_ID");
6cc5e1a6
DB
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
6cc5e1a6
DB
140static void
141fb_bg_finalize (GObject *object)
142{
143 FbBg *bg;
144
145 ENTER;
146 bg = FB_BG (object);
147 XFreeGC(bg->dpy, bg->gc);
148 RET();
149}
150
151
152static Pixmap
153fb_bg_get_xrootpmap(FbBg *bg)
154{
155 Pixmap ret = None;
156
157 ENTER;
158 if (bg->id) {
159 int act_format, c = 2 ;
160 u_long nitems ;
161 u_long bytes_after ;
162 u_char *prop = NULL;
163 Atom ret_type;
164
165 do {
166 if (XGetWindowProperty(bg->dpy, bg->xroot, bg->id, 0, 1,
167 False, XA_PIXMAP, &ret_type, &act_format,
168 &nitems, &bytes_after, &prop) == Success) {
169 if (ret_type == XA_PIXMAP) {
170 ret = *((Pixmap *)prop);
171 XFree(prop);
172 break;
173 }
174 }
175 } while (--c > 0);
176 }
177 RET(ret);
178
179}
180
181
182GdkPixmap *
183fb_bg_get_xroot_pix_for_win(FbBg *bg, GtkWidget *widget)
184{
185 Window win;
186 Window dummy;
187 Pixmap bgpix;
188 GdkPixmap *gbgpix;
189 guint width, height, border, depth;
190 int x, y;
191
192 ENTER;
193 win = GDK_WINDOW_XWINDOW(widget->window);
194 if (!XGetGeometry(bg->dpy, win, &dummy, &x, &y, &width, &height, &border,
195 &depth)) {
196 DBG2("XGetGeometry failed\n");
197 RET(NULL);
198 }
199 XTranslateCoordinates(bg->dpy, win, bg->xroot, 0, 0, &x, &y, &dummy);
200 DBG("win=%x %dx%d%+d%+d\n", win, width, height, x, y);
201 gbgpix = gdk_pixmap_new(NULL, width, height, depth);
202 if (!gbgpix) {
203 ERR("gdk_pixmap_new failed\n");
204 RET(NULL);
205 }
206 bgpix = gdk_x11_drawable_get_xid(gbgpix);
207 XSetTSOrigin(bg->dpy, bg->gc, -x, -y) ;
208 XFillRectangle(bg->dpy, bgpix, bg->gc, 0, 0, width, height);
209 RET(gbgpix);
210}
211
212void
213fb_bg_composite(GdkDrawable *base, GdkGC *gc, guint32 tintcolor, gint alpha)
214{
215 GdkPixbuf *ret, *ret2;
216 int w, h;
217 static GdkColormap *cmap = NULL;
218
219 ENTER;
220 gdk_drawable_get_size (base, &w, &h);
221 if (!cmap) {
222 cmap = gdk_colormap_get_system ();
223 }
224 DBG("here\n");
225 ret = gdk_pixbuf_get_from_drawable (NULL, base, cmap, 0, 0, 0, 0, w, h);
226 if (!ret)
227 RET();
228 DBG("here w=%d h=%d\n", w, h);
229 ret2 = gdk_pixbuf_composite_color_simple(ret, w, h,
230 GDK_INTERP_HYPER, 255-alpha, MIN(w, h), tintcolor, tintcolor);
231 DBG("here\n");
232 if (!ret2) {
233 g_object_unref(ret);
234 RET();
235 }
236 //gdk_pixbuf_render_to_drawable (ret2, base, gc, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
237 gdk_draw_pixbuf (base, gc, ret2, 0, 0, 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
238 g_object_unref(ret);
239 g_object_unref(ret2);
240 RET();
241}
242
243
244static void
245fb_bg_changed(FbBg *bg)
246{
247 ENTER;
248 bg->pixmap = fb_bg_get_xrootpmap(bg);
249 if (bg->pixmap != None) {
250 XGCValues gcv;
251
252 gcv.tile = bg->pixmap;
253 XChangeGC(bg->dpy, bg->gc, GCTile, &gcv);
254 DBG("changed\n");
255 }
256 RET();
257}
258
10862fa6 259inline void fb_bg_notify_changed_bg(FbBg *bg)
6cc5e1a6
DB
260{
261 ENTER;
262 g_signal_emit (bg, signals [CHANGED], 0);
263 RET();
264}
265
266FbBg *fb_bg_get_for_display(void)
267{
268 ENTER;
269 if (!default_bg)
270 {
271 default_bg = fb_bg_new();
10862fa6
DB
272 g_object_add_weak_pointer( G_OBJECT(default_bg),
273 (gpointer)&default_bg );
6cc5e1a6
DB
274 }
275 else
276 g_object_ref(default_bg);
277 RET(default_bg);
278}
279
280GdkPixmap *
281fb_bg_get_pix_from_file(GtkWidget *widget, const char *filename)
282{
283 ENTER;
284 GdkPixbuf *pixbuf;
285 GdkPixmap *pixmap;
286
287 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
288 if (!pixbuf) {
289 RET(widget->style->bg_pixmap[0]);
290 }
291 pixmap = gdk_pixmap_new(widget->window, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), -1);
292 gdk_pixbuf_render_to_drawable(pixbuf,pixmap,
293 widget->style->fg_gc[GTK_STATE_NORMAL],
294 0,0,0,0,
295 gdk_pixbuf_get_width(pixbuf),
296 gdk_pixbuf_get_height(pixbuf),
297 GDK_RGB_DITHER_NORMAL,0,0);
298
299 g_object_unref( pixbuf );
300 RET(pixmap);
301}