1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-12-25 20:11:11 +00:00
conky/cairo.c

231 lines
5.3 KiB
C
Raw Normal View History

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* Small example demonstrating emulating knockout-groups as in PDF-1.4
* using cairo_set_operator().
*
* Owen Taylor,
* v0.1 30 November 2002
* v0.2 1 December 2002 - typo fixes from Keith Packard
* v0.3 17 April 2003 - Tracking changes in Xr, (Removal of Xr{Push,Pop}Group)
* v0.4 29 September 2003 - Use cairo_rectangle rather than private rect_path
* Use cairo_arc for oval_path
* Keeping log of changes in ChangeLog/CVS now. (2003-11-19) Carl Worth
*/
#include "conky.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <math.h>
#include <stdio.h>
/* Fill the given area with checks in the standard style
* for showing compositing effects.
*/
static void
fill_checks (cairo_t *cr,
int x, int y,
int width, int height)
{
cairo_surface_t *check;
cairo_pattern_t *check_pattern;
cairo_save (cr);
#define CHECK_SIZE 32
check = cairo_surface_create_similar (cairo_current_target_surface (cr),
CAIRO_FORMAT_RGB24,
2 * CHECK_SIZE, 2 * CHECK_SIZE);
cairo_surface_set_repeat (check, 1);
/* Draw the check */
{
cairo_save (cr);
cairo_set_target_surface (cr, check);
cairo_set_operator (cr, CAIRO_OPERATOR_SRC);
cairo_set_rgb_color (cr, 0.4, 0.4, 0.4);
cairo_rectangle (cr, 0, 0, 2 * CHECK_SIZE, 2 * CHECK_SIZE);
cairo_fill (cr);
cairo_set_rgb_color (cr, 0.7, 0.7, 0.7);
cairo_rectangle (cr, x, y, CHECK_SIZE, CHECK_SIZE);
cairo_fill (cr);
cairo_rectangle (cr, x + CHECK_SIZE, y + CHECK_SIZE, CHECK_SIZE, CHECK_SIZE);
cairo_fill (cr);
cairo_restore (cr);
}
/* Fill the whole surface with the check */
check_pattern = cairo_pattern_create_for_surface (check);
cairo_set_pattern (cr, check_pattern);
cairo_rectangle (cr, 0, 0, width, height);
cairo_fill (cr);
cairo_pattern_destroy (check_pattern);
cairo_surface_destroy (check);
cairo_restore (cr);
}
static void draw_pee (cairo_t *cr, double xc, double yc)
{
cairo_set_rgb_color (cr, 0, 0, 0);
cairo_show_text (cr, "Conky");
}
static void
draw (cairo_t *cr,
int width,
int height)
{
cairo_surface_t *overlay;
/* Fill the background */
double xc = width / 2.;
double yc = height / 2.;
overlay = cairo_surface_create_similar (cairo_current_target_surface (cr),
CAIRO_FORMAT_ARGB32,
width, height);
if (overlay == NULL)
return;
fill_checks (cr, 0, 0, width, height);
cairo_save (cr);
cairo_set_target_surface (cr, overlay);
cairo_set_alpha (cr, 0.5);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
draw_pee (cr, xc, yc);
cairo_restore (cr);
cairo_show_surface (cr, overlay, width, height);
cairo_surface_destroy (overlay);
}
int
do_it (void)
{
Display *dpy;
int screen;
Window w;
Pixmap pixmap;
char *title = "cairo: Knockout Groups";
unsigned int quit_keycode;
int needs_redraw;
GC gc;
XWMHints *wmhints;
XSizeHints *normalhints;
XClassHint *classhint;
int width = 400;
int height = 400;
dpy = XOpenDisplay (NULL);
screen = DefaultScreen (dpy);
w = XCreateSimpleWindow (dpy, RootWindow (dpy, screen),
0, 0, width, height, 0,
BlackPixel (dpy, screen), WhitePixel (dpy, screen));
normalhints = XAllocSizeHints ();
normalhints->flags = 0;
normalhints->x = 0;
normalhints->y = 0;
normalhints->width = width;
normalhints->height = height;
classhint = XAllocClassHint ();
classhint->res_name = "cairo-knockout";
classhint->res_class = "Cairo-knockout";
wmhints = XAllocWMHints ();
wmhints->flags = InputHint;
wmhints->input = True;
XmbSetWMProperties (dpy, w, title, "cairo-knockout", 0, 0,
normalhints, wmhints, classhint);
XFree (wmhints);
XFree (classhint);
XFree (normalhints);
pixmap = XCreatePixmap (dpy, w, width, height, DefaultDepth (dpy, screen));
gc = XCreateGC (dpy, pixmap, 0, NULL);
quit_keycode = XKeysymToKeycode(dpy, XStringToKeysym("Q"));
XSelectInput (dpy, w, ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask);
XMapWindow (dpy, w);
needs_redraw = 1;
while (1) {
XEvent xev;
/* Only do the redraw if there are no events pending. This
* avoids us getting behind doing several redraws for several
* consecutive resize events for example.
*/
if (!XPending (dpy) && needs_redraw) {
cairo_t *cr = cairo_create ();
cairo_set_target_drawable (cr, dpy, pixmap);
draw (cr, width, height);
cairo_destroy (cr);
XCopyArea (dpy, pixmap, w, gc,
0, 0,
width, height,
0, 0);
needs_redraw = 0;
}
XNextEvent (dpy, &xev);
switch (xev.xany.type) {
case ButtonPress:
/* A click on the canvas ends the program */
goto DONE;
case KeyPress:
if (xev.xkey.keycode == quit_keycode)
goto DONE;
break;
case ConfigureNotify:
/* Note new size and create new pixmap. */
width = xev.xconfigure.width;
height = xev.xconfigure.height;
XFreePixmap (dpy, pixmap);
pixmap = XCreatePixmap (dpy, w, width, height, DefaultDepth (dpy, screen));
needs_redraw = 1;
break;
case Expose:
XCopyArea (dpy, pixmap, w, gc,
xev.xexpose.x, xev.xexpose.y,
xev.xexpose.width, xev.xexpose.height,
xev.xexpose.x, xev.xexpose.y);
break;
}
}
DONE:
XFreeGC (dpy, gc);
XCloseDisplay (dpy);
return 0;
}