1 /* viewer-x.c: Common code for X-based viewers
2 *
3 * Copyright (C) 1999,2004,2005 Red Hat, Inc.
4 * Copyright (C) 2001 Sun Microsystems
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21 #include "config.h"
22 #include <string.h>
23
24 #include "viewer-render.h"
25 #include "viewer-x.h"
26
27 void
x_view_init(gpointer instance,const PangoViewer * klass G_GNUC_UNUSED)28 x_view_init (gpointer instance,
29 const PangoViewer *klass G_GNUC_UNUSED)
30 {
31 XViewer *x = (XViewer *)instance;
32
33 x->display = XOpenDisplay (NULL);
34 if (!x->display)
35 fail ("Cannot open display %s", XDisplayName (NULL));
36
37 x->screen = DefaultScreen (x->display);
38 }
39
40 gpointer
x_view_create(const PangoViewer * klass)41 x_view_create (const PangoViewer *klass)
42 {
43 XViewer *instance;
44
45 instance = g_slice_new (XViewer);
46
47 x_view_init (instance, klass);
48
49 return instance;
50 }
51
52 void
x_view_destroy(gpointer instance)53 x_view_destroy (gpointer instance)
54 {
55 XViewer *x = (XViewer *)instance;
56
57 XCloseDisplay (x->display);
58
59 g_slice_free (XViewer, instance);
60 }
61
62 gpointer
x_view_create_surface(gpointer instance,int width,int height)63 x_view_create_surface (gpointer instance,
64 int width,
65 int height)
66 {
67 XViewer *x = (XViewer *) instance;
68 Pixmap pixmap;
69
70 pixmap = XCreatePixmap (x->display, DefaultRootWindow (x->display), width, height,
71 DefaultDepth (x->display, x->screen));
72
73 return (gpointer) pixmap;
74 }
75
76 void
x_view_destroy_surface(gpointer instance,gpointer surface)77 x_view_destroy_surface (gpointer instance,
78 gpointer surface)
79 {
80 XViewer *x = (XViewer *) instance;
81 Pixmap pixmap = (Pixmap) surface;
82
83 XFreePixmap (x->display, pixmap);
84 }
85
86 static void
update(Display * display,Pixmap pixmap,Window window,Region * update_region)87 update (Display *display,
88 Pixmap pixmap,
89 Window window,
90 Region *update_region)
91 {
92 GC gc;
93 XRectangle extents;
94
95 XClipBox (*update_region, &extents);
96
97 gc = XCreateGC (display, pixmap, 0, NULL);
98
99 XCopyArea (display, pixmap, window, gc,
100 extents.x, extents.y,
101 extents.width, extents.height,
102 extents.x, extents.y);
103
104 XFreeGC (display, gc);
105
106 XDestroyRegion (*update_region);
107 *update_region = NULL;
108 }
109
110 static void
expose(XExposeEvent * xev,Region * update_region)111 expose (XExposeEvent *xev,
112 Region *update_region)
113 {
114 XRectangle r;
115
116 if (!*update_region)
117 *update_region = XCreateRegion ();
118
119 r.x = xev->x;
120 r.y = xev->y;
121 r.width = xev->width;
122 r.height = xev->height;
123
124 XUnionRectWithRegion (&r, *update_region, *update_region);
125 }
126
127 gpointer
x_view_create_window(gpointer instance,const char * title,int width,int height)128 x_view_create_window (gpointer instance,
129 const char *title,
130 int width,
131 int height)
132 {
133 XViewer *x = (XViewer *) instance;
134 unsigned long bg;
135 Window window;
136 XSizeHints size_hints;
137
138 bg = WhitePixel (x->display, x->screen);
139 window = XCreateSimpleWindow (x->display, DefaultRootWindow (x->display),
140 0, 0, width, height, 0,
141 bg, bg);
142
143 XSelectInput (x->display, window, ExposureMask | KeyPressMask);
144
145 XMapWindow (x->display, window);
146 XmbSetWMProperties (x->display, window,
147 title,
148 NULL, NULL, 0, NULL, NULL, NULL);
149
150 memset ((char *)&size_hints, 0, sizeof (XSizeHints));
151 size_hints.flags = PSize | PMaxSize;
152 size_hints.width = width; size_hints.height = height; /* for compat only */
153 size_hints.max_width = width; size_hints.max_height = height;
154
155 XSetWMNormalHints (x->display, window, &size_hints);
156
157 return (gpointer) window;
158 }
159
160 void
x_view_destroy_window(gpointer instance,gpointer window)161 x_view_destroy_window (gpointer instance,
162 gpointer window)
163 {
164 XViewer *x = (XViewer *) instance;
165 Window win = (Window) window;
166
167 XDestroyWindow (x->display, win);
168 }
169
170 gpointer
x_view_display(gpointer instance,gpointer surface,gpointer win,int width,int height,gpointer state)171 x_view_display (gpointer instance,
172 gpointer surface,
173 gpointer win,
174 int width,
175 int height,
176 gpointer state)
177 {
178 XViewer *x = (XViewer *) instance;
179 Pixmap pixmap = (Pixmap) surface;
180 Window window = (Window) win;
181 XEvent xev;
182 XRectangle r;
183 Region update_region;
184 unsigned int quit_keycode;
185 unsigned int annotate_keycode;
186
187 /* force a full redraw */
188 update_region = XCreateRegion ();
189 r.x = 0;
190 r.y = 0;
191 r.width = width;
192 r.height = height;
193 XUnionRectWithRegion (&r, update_region, update_region);
194
195 annotate_keycode = XKeysymToKeycode(x->display, 'B');
196 quit_keycode = XKeysymToKeycode(x->display, 'Q');
197
198 while (1)
199 {
200 if (!XPending (x->display) && update_region)
201 update (x->display, pixmap, window, &update_region);
202
203 XNextEvent (x->display, &xev);
204 switch (xev.xany.type) {
205 case KeyPress:
206 if (xev.xkey.keycode == quit_keycode)
207 return GINT_TO_POINTER (-1);
208 else if (xev.xkey.keycode == annotate_keycode)
209 {
210 return GUINT_TO_POINTER (GPOINTER_TO_INT (state) + 1);
211 }
212 break;
213 case Expose:
214 expose (&xev.xexpose, &update_region);
215 break;
216 }
217 }
218 }
219
220 const PangoViewer x_viewer = {
221 "X",
222 NULL,
223 NULL,
224 x_view_create,
225 x_view_destroy,
226 NULL,
227 x_view_create_surface,
228 x_view_destroy_surface,
229 NULL,
230 NULL,
231 x_view_create_window,
232 x_view_destroy_window,
233 x_view_display
234 };
235