summaryrefslogtreecommitdiffstats
path: root/abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd.c
diff options
context:
space:
mode:
authorJames Meyer <james.meyer@operamail.com>2009-02-23 21:19:04 (GMT)
committerJames Meyer <james.meyer@operamail.com>2009-02-23 21:19:04 (GMT)
commit577c09bc1ea57e3fc5fe459ad91aafa4412b2297 (patch)
tree5fdcf480f545a75514783b155e3b23dea397eaf6 /abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd.c
parent1552b1b0221ed6a7e26e486187be25031408b453 (diff)
downloadlinhes_pkgbuild-577c09bc1ea57e3fc5fe459ad91aafa4412b2297.zip
linhes_pkgbuild-577c09bc1ea57e3fc5fe459ad91aafa4412b2297.tar.gz
linhes_pkgbuild-577c09bc1ea57e3fc5fe459ad91aafa4412b2297.tar.bz2
adding in ghosd
Diffstat (limited to 'abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd.c')
-rw-r--r--abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd.c b/abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd.c
new file mode 100644
index 0000000..d830a1b
--- /dev/null
+++ b/abs/mv-core/ghosd/ghosd-0.0.1/ghosd/ghosd.c
@@ -0,0 +1,226 @@
+/* ghosd -- OSD with fake transparency, cairo, and pango.
+ * Copyright (C) 2006 Evan Martin <martine@danga.com>
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cairo/cairo-xlib-xrender.h>
+#include <X11/Xatom.h>
+
+#include "ghosd.h"
+#include "ghosd-internal.h"
+
+static Pixmap
+take_snapshot(Ghosd *ghosd) {
+ Pixmap pixmap;
+ GC gc;
+
+ /* create a pixmap to hold the screenshot. */
+ pixmap = XCreatePixmap(ghosd->dpy, ghosd->win,
+ ghosd->width, ghosd->height,
+ DefaultDepth(ghosd->dpy, DefaultScreen(ghosd->dpy)));
+
+ /* then copy the screen into the pixmap. */
+ gc = XCreateGC(ghosd->dpy, pixmap, 0, NULL);
+ XSetSubwindowMode(ghosd->dpy, gc, IncludeInferiors);
+ XCopyArea(ghosd->dpy, DefaultRootWindow(ghosd->dpy), pixmap, gc,
+ ghosd->x, ghosd->y, ghosd->width, ghosd->height,
+ 0, 0);
+ XSetSubwindowMode(ghosd->dpy, gc, ClipByChildren);
+ XFreeGC(ghosd->dpy, gc);
+
+ return pixmap;
+}
+
+void
+ghosd_render(Ghosd *ghosd) {
+ Pixmap pixmap;
+ GC gc;
+
+ /* make our own copy of the background pixmap as the initial surface. */
+ pixmap = XCreatePixmap(ghosd->dpy, ghosd->win, ghosd->width, ghosd->height,
+ DefaultDepth(ghosd->dpy, DefaultScreen(ghosd->dpy)));
+
+ gc = XCreateGC(ghosd->dpy, pixmap, 0, NULL);
+ if (ghosd->transparent) {
+ XCopyArea(ghosd->dpy, ghosd->background, pixmap, gc,
+ 0, 0, ghosd->width, ghosd->height, 0, 0);
+ } else {
+ XFillRectangle(ghosd->dpy, pixmap, gc,
+ 0, 0, ghosd->width, ghosd->height);
+ }
+ XFreeGC(ghosd->dpy, gc);
+
+ /* render with cairo. */
+ if (ghosd->render_func) {
+ /* create cairo surface using the pixmap. */
+ XRenderPictFormat *xrformat =
+ XRenderFindVisualFormat(ghosd->dpy,
+ DefaultVisual(ghosd->dpy,
+ DefaultScreen(ghosd->dpy)));
+ cairo_surface_t *surf =
+ cairo_xlib_surface_create_with_xrender_format(
+ ghosd->dpy, pixmap,
+ ScreenOfDisplay(ghosd->dpy, DefaultScreen(ghosd->dpy)),
+ xrformat,
+ ghosd->width, ghosd->height);
+
+ /* draw some stuff. */
+ cairo_t *cr = cairo_create(surf);
+ ghosd->render_func(ghosd, cr, ghosd->render_data);
+ cairo_destroy(cr);
+ }
+
+ /* point window at its new backing pixmap. */
+ XSetWindowBackgroundPixmap(ghosd->dpy, ghosd->win, pixmap);
+ XFreePixmap(ghosd->dpy, pixmap);
+
+ /* and tell the window to redraw with this pixmap. */
+ XClearWindow(ghosd->dpy, ghosd->win);
+}
+
+static void
+set_hints(Display *dpy, Window win) {
+ /* we're almost a _NET_WM_WINDOW_TYPE_SPLASH, but we don't want
+ * to be centered on the screen. instead, manually request the
+ * behavior we want. */
+
+ /* turn off window decorations.
+ * we could pull this in from a motif header, but it's easier to
+ * use this snippet i found on a mailing list. */
+ Atom mwm_hints = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
+#define MWM_HINTS_DECORATIONS (1<<1)
+ struct {
+ long flags, functions, decorations, input_mode;
+ } mwm_hints_setting = {
+ MWM_HINTS_DECORATIONS, 0, 0, 0
+ };
+ XChangeProperty(dpy, win,
+ mwm_hints, mwm_hints, 32, PropModeReplace,
+ (unsigned char *)&mwm_hints_setting, 4);
+
+ /* always on top, not in taskbar or pager. */
+ Atom win_state = XInternAtom(dpy, "_NET_WM_STATE", False);
+ Atom win_state_setting[] = {
+ XInternAtom(dpy, "_NET_WM_STATE_ABOVE", False),
+ XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False),
+ XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False)
+ };
+ XChangeProperty(dpy, win, win_state, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)&win_state_setting, 3);
+}
+
+static Window
+make_window(Display *dpy) {
+ Window win;
+ XSetWindowAttributes att;
+
+ /* XXX I don't understand X well enough to know if these are the correct
+ * settings. */
+ att.backing_store = WhenMapped;
+ att.background_pixel = None;
+ att.border_pixel = 0;
+ att.background_pixmap = None;
+ att.save_under = True;
+ att.event_mask = ExposureMask | StructureNotifyMask;
+ att.override_redirect = True;
+
+ win = XCreateWindow(dpy, DefaultRootWindow(dpy),
+ -1, -1, 1, 1, 0,
+ CopyFromParent, InputOutput, CopyFromParent,
+ CWBackingStore | CWBackPixel | CWBackPixmap |
+ CWEventMask | CWSaveUnder | CWOverrideRedirect,
+ &att);
+
+ set_hints(dpy, win);
+
+ /* XXX: XSetClassHint? */
+
+ return win;
+}
+
+void
+ghosd_show(Ghosd *ghosd) {
+ XMapWindow(ghosd->dpy, ghosd->win);
+}
+
+void
+ghosd_set_transparent(Ghosd *ghosd, int transparent) {
+ ghosd->transparent = (transparent != 0);
+}
+
+void
+ghosd_set_render(Ghosd *ghosd, GhosdRenderFunc render_func, void *render_data) {
+ ghosd->render_func = render_func;
+ ghosd->render_data = render_data;
+}
+
+void
+ghosd_set_position(Ghosd *ghosd, int x, int y, int width, int height) {
+ const int dpy_width = DisplayWidth(ghosd->dpy, DefaultScreen(ghosd->dpy));
+ const int dpy_height = DisplayHeight(ghosd->dpy, DefaultScreen(ghosd->dpy));
+
+ if (x == GHOSD_COORD_CENTER) {
+ x = (dpy_width - width) / 2;
+ } else if (x < 0) {
+ x = dpy_width - width + x;
+ }
+
+ if (y == GHOSD_COORD_CENTER) {
+ y = (dpy_height - height) / 2;
+ } else if (y < 0) {
+ y = dpy_height - height + y;
+ }
+
+ ghosd->x = x;
+ ghosd->y = y;
+ ghosd->width = width;
+ ghosd->height = height;
+
+ if (ghosd->transparent)
+ ghosd->background = take_snapshot(ghosd);
+
+ XMoveResizeWindow(ghosd->dpy, ghosd->win,
+ ghosd->x, ghosd->y, ghosd->width, ghosd->height);
+}
+
+#if 0
+static int
+x_error_handler(Display *dpy, XErrorEvent* evt) {
+ /* segfault so we can get a backtrace. */
+ char *x = NULL;
+ *x = 0;
+ return 0;
+}
+#endif
+
+Ghosd *
+ghosd_new(void) {
+ Ghosd *ghosd;
+ Display *dpy;
+ Window win;
+
+ dpy = XOpenDisplay(NULL);
+ if (dpy == NULL) {
+ fprintf(stderr, "Couldn't open display: (XXX FIXME)\n");
+ return NULL;
+ }
+
+ win = make_window(dpy);
+
+ ghosd = calloc(1, sizeof(Ghosd));
+ ghosd->dpy = dpy;
+ ghosd->win = win;
+ ghosd->transparent = 1;
+
+ return ghosd;
+}
+
+int
+ghosd_get_socket(Ghosd *ghosd) {
+ return ConnectionNumber(ghosd->dpy);
+}
+
+/* vim: set ts=2 sw=2 et cino=(0 : */