/* viewer-x.c: Common code for X-based viewers * * Copyright (C) 1999,2004,2005 Red Hat, Inc. * Copyright (C) 2001 Sun Microsystems * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "config.h" #include #include "viewer-render.h" #include "viewer-x.h" void x_view_init (gpointer instance, const PangoViewer *klass G_GNUC_UNUSED) { XViewer *x = (XViewer *)instance; x->display = XOpenDisplay (NULL); if (!x->display) fail ("Cannot open display %s", XDisplayName (NULL)); x->screen = DefaultScreen (x->display); } gpointer x_view_create (const PangoViewer *klass) { XViewer *instance; instance = g_slice_new (XViewer); x_view_init (instance, klass); return instance; } void x_view_destroy (gpointer instance) { XViewer *x = (XViewer *)instance; XCloseDisplay (x->display); g_slice_free (XViewer, instance); } gpointer x_view_create_surface (gpointer instance, int width, int height) { XViewer *x = (XViewer *) instance; Pixmap pixmap; pixmap = XCreatePixmap (x->display, DefaultRootWindow (x->display), width, height, DefaultDepth (x->display, x->screen)); return (gpointer) pixmap; } void x_view_destroy_surface (gpointer instance, gpointer surface) { XViewer *x = (XViewer *) instance; Pixmap pixmap = (Pixmap) surface; XFreePixmap (x->display, pixmap); } static void update (Display *display, Pixmap pixmap, Window window, Region *update_region) { GC gc; XRectangle extents; XClipBox (*update_region, &extents); gc = XCreateGC (display, pixmap, 0, NULL); XCopyArea (display, pixmap, window, gc, extents.x, extents.y, extents.width, extents.height, extents.x, extents.y); XFreeGC (display, gc); XDestroyRegion (*update_region); *update_region = NULL; } static void expose (XExposeEvent *xev, Region *update_region) { XRectangle r; if (!*update_region) *update_region = XCreateRegion (); r.x = xev->x; r.y = xev->y; r.width = xev->width; r.height = xev->height; XUnionRectWithRegion (&r, *update_region, *update_region); } gpointer x_view_create_window (gpointer instance, const char *title, int width, int height) { XViewer *x = (XViewer *) instance; unsigned long bg; Window window; XSizeHints size_hints; bg = WhitePixel (x->display, x->screen); window = XCreateSimpleWindow (x->display, DefaultRootWindow (x->display), 0, 0, width, height, 0, bg, bg); XSelectInput (x->display, window, ExposureMask | KeyPressMask); XMapWindow (x->display, window); XmbSetWMProperties (x->display, window, title, NULL, NULL, 0, NULL, NULL, NULL); memset ((char *)&size_hints, 0, sizeof (XSizeHints)); size_hints.flags = PSize | PMaxSize; size_hints.width = width; size_hints.height = height; /* for compat only */ size_hints.max_width = width; size_hints.max_height = height; XSetWMNormalHints (x->display, window, &size_hints); return (gpointer) window; } void x_view_destroy_window (gpointer instance, gpointer window) { XViewer *x = (XViewer *) instance; Window win = (Window) window; XDestroyWindow (x->display, win); } gpointer x_view_display (gpointer instance, gpointer surface, gpointer win, int width, int height, gpointer state) { XViewer *x = (XViewer *) instance; Pixmap pixmap = (Pixmap) surface; Window window = (Window) win; XEvent xev; XRectangle r; Region update_region; unsigned int quit_keycode; unsigned int annotate_keycode; /* force a full redraw */ update_region = XCreateRegion (); r.x = 0; r.y = 0; r.width = width; r.height = height; XUnionRectWithRegion (&r, update_region, update_region); annotate_keycode = XKeysymToKeycode(x->display, 'B'); quit_keycode = XKeysymToKeycode(x->display, 'Q'); while (1) { if (!XPending (x->display) && update_region) update (x->display, pixmap, window, &update_region); XNextEvent (x->display, &xev); switch (xev.xany.type) { case KeyPress: if (xev.xkey.keycode == quit_keycode) return GINT_TO_POINTER (-1); else if (xev.xkey.keycode == annotate_keycode) { return GUINT_TO_POINTER (GPOINTER_TO_INT (state) + 1); } break; case Expose: expose (&xev.xexpose, &update_region); break; } } } const PangoViewer x_viewer = { "X", NULL, NULL, x_view_create, x_view_destroy, NULL, x_view_create_surface, x_view_destroy_surface, NULL, NULL, x_view_create_window, x_view_destroy_window, x_view_display };