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