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);