Enabling multithreaded compilation.
[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
0f7f2ef3 213fb_bg_composite(GdkDrawable *base, GdkColor *tintcolor, gint alpha)
6cc5e1a6 214{
0f7f2ef3 215 cairo_t *cr;
6cc5e1a6
DB
216
217 ENTER;
0f7f2ef3
AL
218 cr = gdk_cairo_create(base);
219 gdk_cairo_set_source_color(cr, tintcolor);
220 cairo_paint_with_alpha(cr, (double) alpha/255);
221 check_cairo_status(cr);
222 cairo_destroy(cr);
223 fb_bg_changed(fb_bg_get_for_display());
6cc5e1a6
DB
224 RET();
225}
226
227
228static void
229fb_bg_changed(FbBg *bg)
230{
231 ENTER;
232 bg->pixmap = fb_bg_get_xrootpmap(bg);
233 if (bg->pixmap != None) {
234 XGCValues gcv;
235
236 gcv.tile = bg->pixmap;
237 XChangeGC(bg->dpy, bg->gc, GCTile, &gcv);
238 DBG("changed\n");
239 }
240 RET();
241}
242
10862fa6 243inline void fb_bg_notify_changed_bg(FbBg *bg)
6cc5e1a6
DB
244{
245 ENTER;
246 g_signal_emit (bg, signals [CHANGED], 0);
247 RET();
248}
249
250FbBg *fb_bg_get_for_display(void)
251{
252 ENTER;
253 if (!default_bg)
254 {
255 default_bg = fb_bg_new();
10862fa6
DB
256 g_object_add_weak_pointer( G_OBJECT(default_bg),
257 (gpointer)&default_bg );
6cc5e1a6
DB
258 }
259 else
260 g_object_ref(default_bg);
261 RET(default_bg);
262}
263
264GdkPixmap *
265fb_bg_get_pix_from_file(GtkWidget *widget, const char *filename)
266{
267 ENTER;
268 GdkPixbuf *pixbuf;
0f7f2ef3 269 cairo_t *cr;
6cc5e1a6
DB
270 GdkPixmap *pixmap;
271
272 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
273 if (!pixbuf) {
274 RET(widget->style->bg_pixmap[0]);
275 }
276 pixmap = gdk_pixmap_new(widget->window, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), -1);
0f7f2ef3
AL
277 cr = gdk_cairo_create(pixmap);
278 gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
279 cairo_paint(cr);
280 check_cairo_status(cr);
281 cairo_destroy(cr);
6cc5e1a6
DB
282
283 g_object_unref( pixbuf );
284 RET(pixmap);
285}