Mercurial > audlegacy-plugins
comparison src/aosd/ghosd.c @ 906:16e51fb5908e trunk
[svn] - aosd: beta4, ghosd source was rewritten to support argb visual (x composite extension) as an option, this allows to have real transparency in the OSD
author | giacomo |
---|---|
date | Sat, 31 Mar 2007 17:44:23 -0700 |
parents | 68508f8cdf25 |
children | f20ca9b8cd7d |
comparison
equal
deleted
inserted
replaced
905:987eebc33408 | 906:16e51fb5908e |
---|---|
1 /* ghosd -- OSD with fake transparency, cairo, and pango. | 1 /* ghosd -- OSD with fake transparency, cairo, and pango. |
2 * Copyright (C) 2006 Evan Martin <martine@danga.com> | 2 * Copyright (C) 2006 Evan Martin <martine@danga.com> |
3 * | 3 * |
4 * With further development by Giacomo Lozito <james@develia.org> | 4 * With further development by Giacomo Lozito <james@develia.org> |
5 * for the ghosd-based Audacious OSD | 5 * for the ghosd-based Audacious OSD |
6 * - added real transparency with X Composite Extension | |
7 * - added mouse event handling on OSD window | |
8 * - added/changed some other stuff | |
6 */ | 9 */ |
7 | 10 |
8 #include "config.h" | 11 #include "config.h" |
9 | 12 |
10 #include <stdio.h> | 13 #include <stdio.h> |
35 return cur_workspace; | 38 return cur_workspace; |
36 } | 39 } |
37 | 40 |
38 /* fall back to desktop number 0 */ | 41 /* fall back to desktop number 0 */ |
39 return 0; | 42 return 0; |
43 } | |
44 | |
45 Visual * | |
46 find_argb_visual (Display *dpy, int scr) | |
47 { | |
48 XVisualInfo *xvi; | |
49 XVisualInfo template; | |
50 int nvi, i; | |
51 XRenderPictFormat *format; | |
52 Visual *visual; | |
53 | |
54 template.screen = scr; | |
55 template.depth = 32; | |
56 template.class = TrueColor; | |
57 xvi = XGetVisualInfo (dpy, | |
58 VisualScreenMask | VisualDepthMask | VisualClassMask, | |
59 &template, &nvi); | |
60 if (xvi == NULL) | |
61 return NULL; | |
62 | |
63 visual = NULL; | |
64 for (i = 0; i < nvi; i++) | |
65 { | |
66 format = XRenderFindVisualFormat (dpy, xvi[i].visual); | |
67 if (format->type == PictTypeDirect && format->direct.alphaMask) | |
68 { | |
69 visual = xvi[i].visual; | |
70 break; | |
71 } | |
72 } | |
73 XFree (xvi); | |
74 | |
75 return visual; | |
40 } | 76 } |
41 | 77 |
42 static Pixmap | 78 static Pixmap |
43 take_snapshot(Ghosd *ghosd) { | 79 take_snapshot(Ghosd *ghosd) { |
44 Pixmap pixmap; | 80 Pixmap pixmap; |
64 void | 100 void |
65 ghosd_render(Ghosd *ghosd) { | 101 ghosd_render(Ghosd *ghosd) { |
66 Pixmap pixmap; | 102 Pixmap pixmap; |
67 GC gc; | 103 GC gc; |
68 | 104 |
69 /* make our own copy of the background pixmap as the initial surface. */ | 105 if (ghosd->composite) |
70 pixmap = XCreatePixmap(ghosd->dpy, ghosd->win, ghosd->width, ghosd->height, | 106 { |
71 DefaultDepth(ghosd->dpy, DefaultScreen(ghosd->dpy))); | 107 pixmap = XCreatePixmap(ghosd->dpy, ghosd->win, ghosd->width, ghosd->height, 32); |
72 | 108 gc = XCreateGC(ghosd->dpy, pixmap, 0, NULL); |
73 gc = XCreateGC(ghosd->dpy, pixmap, 0, NULL); | |
74 if (ghosd->transparent) { | |
75 XCopyArea(ghosd->dpy, ghosd->background.pixmap, pixmap, gc, | |
76 0, 0, ghosd->width, ghosd->height, 0, 0); | |
77 } else { | |
78 XFillRectangle(ghosd->dpy, pixmap, gc, | 109 XFillRectangle(ghosd->dpy, pixmap, gc, |
79 0, 0, ghosd->width, ghosd->height); | 110 0, 0, ghosd->width, ghosd->height); |
111 } | |
112 else | |
113 { | |
114 pixmap = XCreatePixmap(ghosd->dpy, ghosd->win, ghosd->width, ghosd->height, | |
115 DefaultDepth(ghosd->dpy, DefaultScreen(ghosd->dpy))); | |
116 gc = XCreateGC(ghosd->dpy, pixmap, 0, NULL); | |
117 if (ghosd->transparent) { | |
118 /* make our own copy of the background pixmap as the initial surface. */ | |
119 XCopyArea(ghosd->dpy, ghosd->background.pixmap, pixmap, gc, | |
120 0, 0, ghosd->width, ghosd->height, 0, 0); | |
121 } else { | |
122 XFillRectangle(ghosd->dpy, pixmap, gc, | |
123 0, 0, ghosd->width, ghosd->height); | |
124 } | |
80 } | 125 } |
81 XFreeGC(ghosd->dpy, gc); | 126 XFreeGC(ghosd->dpy, gc); |
82 | 127 |
83 /* render with cairo. */ | 128 /* render with cairo. */ |
84 if (ghosd->render.func) { | 129 if (ghosd->render.func) { |
85 /* create cairo surface using the pixmap. */ | 130 /* create cairo surface using the pixmap. */ |
86 XRenderPictFormat *xrformat = | 131 XRenderPictFormat *xrformat; |
87 XRenderFindVisualFormat(ghosd->dpy, | 132 cairo_surface_t *surf; |
88 DefaultVisual(ghosd->dpy, | 133 if (ghosd->composite) { |
89 DefaultScreen(ghosd->dpy))); | 134 xrformat = XRenderFindVisualFormat(ghosd->dpy, ghosd->visual); |
90 cairo_surface_t *surf = | 135 surf = cairo_xlib_surface_create_with_xrender_format( |
91 cairo_xlib_surface_create_with_xrender_format( | 136 ghosd->dpy, pixmap, |
92 ghosd->dpy, pixmap, | 137 ScreenOfDisplay(ghosd->dpy, ghosd->screen_num), |
93 ScreenOfDisplay(ghosd->dpy, DefaultScreen(ghosd->dpy)), | 138 xrformat, ghosd->width, ghosd->height); |
94 xrformat, | 139 } else { |
95 ghosd->width, ghosd->height); | 140 xrformat = XRenderFindVisualFormat(ghosd->dpy, |
141 DefaultVisual(ghosd->dpy, DefaultScreen(ghosd->dpy))); | |
142 surf = cairo_xlib_surface_create_with_xrender_format( | |
143 ghosd->dpy, pixmap, | |
144 ScreenOfDisplay(ghosd->dpy, DefaultScreen(ghosd->dpy)), | |
145 xrformat, ghosd->width, ghosd->height); | |
146 } | |
96 | 147 |
97 /* draw some stuff. */ | 148 /* draw some stuff. */ |
98 cairo_t *cr = cairo_create(surf); | 149 cairo_t *cr = cairo_create(surf); |
99 ghosd->render.func(ghosd, cr, ghosd->render.data); | 150 ghosd->render.func(ghosd, cr, ghosd->render.data); |
100 cairo_destroy(cr); | 151 cairo_destroy(cr); |
164 XSetClassHint(dpy, win, classhints); | 215 XSetClassHint(dpy, win, classhints); |
165 XFree( classhints ); | 216 XFree( classhints ); |
166 } | 217 } |
167 | 218 |
168 static Window | 219 static Window |
169 make_window(Display *dpy) { | 220 make_window(Display *dpy, Window root_win, Visual *visual, Colormap colormap, Bool use_argbvisual) { |
170 Window win; | 221 Window win; |
171 XSetWindowAttributes att; | 222 XSetWindowAttributes att; |
172 | 223 |
173 att.backing_store = WhenMapped; | 224 att.backing_store = WhenMapped; |
174 att.background_pixel = None; | 225 att.background_pixel = 0x0; |
175 att.border_pixel = 0; | 226 att.border_pixel = 0; |
176 att.background_pixmap = None; | 227 att.background_pixmap = None; |
177 att.save_under = True; | 228 att.save_under = True; |
178 att.event_mask = ExposureMask | StructureNotifyMask | ButtonPressMask; | 229 att.event_mask = ExposureMask | StructureNotifyMask | ButtonPressMask; |
179 att.override_redirect = True; | 230 att.override_redirect = True; |
180 | 231 |
181 win = XCreateWindow(dpy, DefaultRootWindow(dpy), | 232 if ( use_argbvisual ) |
182 -1, -1, 1, 1, 0, | 233 { |
183 CopyFromParent, InputOutput, CopyFromParent, | 234 att.colormap = colormap; |
184 CWBackingStore | CWBackPixel | CWBackPixmap | | 235 win = XCreateWindow(dpy, root_win, |
236 -1, -1, 1, 1, 0, 32, InputOutput, visual, | |
237 CWBackingStore | CWBackPixel | CWBackPixmap | CWBorderPixel | | |
238 CWColormap | CWEventMask | CWSaveUnder | CWOverrideRedirect, | |
239 &att); | |
240 } else { | |
241 win = XCreateWindow(dpy, root_win, | |
242 -1, -1, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, | |
243 CWBackingStore | CWBackPixel | CWBackPixmap | CWBorderPixel | | |
185 CWEventMask | CWSaveUnder | CWOverrideRedirect, | 244 CWEventMask | CWSaveUnder | CWOverrideRedirect, |
186 &att); | 245 &att); |
246 } | |
187 | 247 |
188 set_hints(dpy, win); | 248 set_hints(dpy, win); |
189 | 249 |
190 return win; | 250 return win; |
191 } | 251 } |
192 | 252 |
193 void | 253 void |
194 ghosd_show(Ghosd *ghosd) { | 254 ghosd_show(Ghosd *ghosd) { |
195 if (ghosd->transparent) { | 255 if ((!ghosd->composite) && (ghosd->transparent)) { |
196 if (ghosd->background.set) | 256 if (ghosd->background.set) |
197 { | 257 { |
198 XFreePixmap(ghosd->dpy, ghosd->background.pixmap); | 258 XFreePixmap(ghosd->dpy, ghosd->background.pixmap); |
199 ghosd->background.set = 0; | 259 ghosd->background.set = 0; |
200 } | 260 } |
201 ghosd->background.pixmap = take_snapshot(ghosd); | 261 ghosd->background.pixmap = take_snapshot(ghosd); |
202 ghosd->background.set = 1; | 262 ghosd->background.set = 1; |
203 } | 263 } |
204 | 264 |
205 ghosd_render(ghosd); | 265 ghosd_render(ghosd); |
206 | |
207 XMapRaised(ghosd->dpy, ghosd->win); | 266 XMapRaised(ghosd->dpy, ghosd->win); |
208 } | 267 } |
209 | 268 |
210 void | 269 void |
211 ghosd_hide(Ghosd *ghosd) { | 270 ghosd_hide(Ghosd *ghosd) { |
270 | 329 |
271 Ghosd* | 330 Ghosd* |
272 ghosd_new(void) { | 331 ghosd_new(void) { |
273 Ghosd *ghosd; | 332 Ghosd *ghosd; |
274 Display *dpy; | 333 Display *dpy; |
275 Window win; | 334 Window win, root_win; |
335 int screen_num; | |
336 Visual *visual; | |
337 Colormap colormap; | |
338 Bool use_argbvisual = False; | |
276 | 339 |
277 dpy = XOpenDisplay(NULL); | 340 dpy = XOpenDisplay(NULL); |
278 if (dpy == NULL) { | 341 if (dpy == NULL) { |
279 fprintf(stderr, "Couldn't open display: (XXX FIXME)\n"); | 342 fprintf(stderr, "Couldn't open display: (XXX FIXME)\n"); |
280 return NULL; | 343 return NULL; |
281 } | 344 } |
282 | 345 |
283 win = make_window(dpy); | 346 screen_num = DefaultScreen(dpy); |
347 root_win = RootWindow(dpy, screen_num); | |
348 visual = NULL; /* unused */ | |
349 colormap = None; /* unused */ | |
350 | |
351 win = make_window(dpy, root_win, visual, colormap, use_argbvisual); | |
284 | 352 |
285 ghosd = calloc(1, sizeof(Ghosd)); | 353 ghosd = calloc(1, sizeof(Ghosd)); |
286 ghosd->dpy = dpy; | 354 ghosd->dpy = dpy; |
355 ghosd->visual = visual; | |
356 ghosd->colormap = colormap; | |
287 ghosd->win = win; | 357 ghosd->win = win; |
358 ghosd->root_win = root_win; | |
359 ghosd->screen_num = screen_num; | |
288 ghosd->transparent = 1; | 360 ghosd->transparent = 1; |
361 ghosd->composite = 0; | |
289 ghosd->eventbutton.func = NULL; | 362 ghosd->eventbutton.func = NULL; |
290 ghosd->background.set = 0; | 363 ghosd->background.set = 0; |
291 | 364 |
292 return ghosd; | 365 return ghosd; |
293 } | 366 } |
294 | 367 |
368 Ghosd * | |
369 ghosd_new_with_argbvisual(void) { | |
370 Ghosd *ghosd; | |
371 Display *dpy; | |
372 Window win, root_win; | |
373 int screen_num; | |
374 Visual *visual; | |
375 Colormap colormap; | |
376 Bool use_argbvisual = True; | |
377 | |
378 dpy = XOpenDisplay(NULL); | |
379 if (dpy == NULL) { | |
380 fprintf(stderr, "Couldn't open display: (XXX FIXME)\n"); | |
381 return NULL; | |
382 } | |
383 | |
384 screen_num = DefaultScreen(dpy); | |
385 root_win = RootWindow(dpy, screen_num); | |
386 visual = find_argb_visual(dpy, screen_num); | |
387 colormap = XCreateColormap(dpy, root_win, visual, AllocNone); | |
388 | |
389 win = make_window(dpy, root_win, visual, colormap, use_argbvisual); | |
390 | |
391 ghosd = calloc(1, sizeof(Ghosd)); | |
392 ghosd->dpy = dpy; | |
393 ghosd->visual = visual; | |
394 ghosd->colormap = colormap; | |
395 ghosd->win = win; | |
396 ghosd->root_win = root_win; | |
397 ghosd->screen_num = screen_num; | |
398 ghosd->transparent = 1; | |
399 ghosd->composite = 1; | |
400 ghosd->eventbutton.func = NULL; | |
401 ghosd->background.set = 0; | |
402 | |
403 return ghosd; | |
404 } | |
405 | |
295 void | 406 void |
296 ghosd_destroy(Ghosd* ghosd) { | 407 ghosd_destroy(Ghosd* ghosd) { |
297 if (ghosd->background.set) | 408 if (ghosd->background.set) |
298 { | 409 { |
299 XFreePixmap(ghosd->dpy, ghosd->background.pixmap); | 410 XFreePixmap(ghosd->dpy, ghosd->background.pixmap); |
300 ghosd->background.set = 0; | 411 ghosd->background.set = 0; |
301 } | 412 } |
413 if (ghosd->composite) | |
414 { | |
415 XFreeColormap(ghosd->dpy, ghosd->colormap); | |
416 } | |
302 XDestroyWindow(ghosd->dpy, ghosd->win); | 417 XDestroyWindow(ghosd->dpy, ghosd->win); |
418 XCloseDisplay(ghosd->dpy); | |
303 } | 419 } |
304 | 420 |
305 int | 421 int |
306 ghosd_get_socket(Ghosd *ghosd) { | 422 ghosd_get_socket(Ghosd *ghosd) { |
307 return ConnectionNumber(ghosd->dpy); | 423 return ConnectionNumber(ghosd->dpy); |