wmaker: Replaced local 'extern' definition of wPreferences by proper header usage
[wmaker-crm.git] / wrlib / xutil.c
blob6d0b242d6da57d2f400cf001f1d35433eb90d2d9
1 /* xutil.c - utility functions for X
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
23 #include <config.h>
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
31 #include <assert.h>
33 #ifdef XSHM
34 #include <sys/ipc.h>
35 #include <sys/shm.h>
36 #endif /* XSHM */
38 #include "wraster.h"
40 #ifdef XSHM
42 static int shmError;
44 static int (*oldErrorHandler)(Display *dpy, XErrorEvent *err);
46 static int errorHandler(Display * dpy, XErrorEvent * err)
48 shmError = 1;
49 if (err->error_code != BadAccess)
50 (*oldErrorHandler) (dpy, err);
52 return 0;
55 #endif
57 RXImage *RCreateXImage(RContext * context, int depth, unsigned width, unsigned height)
59 RXImage *rximg;
60 Visual *visual = context->visual;
62 rximg = malloc(sizeof(RXImage));
63 if (!rximg) {
64 RErrorCode = RERR_NOMEMORY;
65 return NULL;
67 #ifndef XSHM
68 rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
69 if (!rximg->image) {
70 free(rximg);
71 RErrorCode = RERR_XERROR;
72 return NULL;
74 rximg->image->data = malloc(rximg->image->bytes_per_line * height);
75 if (!rximg->image->data) {
76 XDestroyImage(rximg->image);
77 free(rximg);
78 RErrorCode = RERR_NOMEMORY;
79 return NULL;
81 #else /* XSHM */
82 if (!context->attribs->use_shared_memory) {
83 retry_without_shm:
85 context->attribs->use_shared_memory = 0;
86 rximg->is_shared = 0;
87 rximg->image = XCreateImage(context->dpy, visual, depth, ZPixmap, 0, NULL, width, height, 8, 0);
88 if (!rximg->image) {
89 free(rximg);
90 RErrorCode = RERR_XERROR;
91 return NULL;
93 rximg->image->data = malloc(rximg->image->bytes_per_line * height);
94 if (!rximg->image->data) {
95 XDestroyImage(rximg->image);
96 free(rximg);
97 RErrorCode = RERR_NOMEMORY;
98 return NULL;
100 } else {
101 rximg->is_shared = 1;
103 rximg->info.readOnly = False;
105 rximg->image = XShmCreateImage(context->dpy, visual, depth,
106 ZPixmap, NULL, &rximg->info, width, height);
108 rximg->info.shmid = shmget(IPC_PRIVATE, rximg->image->bytes_per_line * height, IPC_CREAT | 0777);
109 if (rximg->info.shmid < 0) {
110 context->attribs->use_shared_memory = 0;
111 perror("wrlib: could not allocate shared memory segment");
112 XDestroyImage(rximg->image);
113 goto retry_without_shm;
116 rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
117 if (rximg->info.shmaddr == (void *)-1) {
118 context->attribs->use_shared_memory = 0;
119 if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
120 perror("wrlib: shmctl");
121 perror("wrlib: could not allocate shared memory");
122 XDestroyImage(rximg->image);
123 goto retry_without_shm;
126 shmError = 0;
127 XSync(context->dpy, False);
128 oldErrorHandler = XSetErrorHandler(errorHandler);
129 XShmAttach(context->dpy, &rximg->info);
130 XSync(context->dpy, False);
131 XSetErrorHandler(oldErrorHandler);
133 rximg->image->data = rximg->info.shmaddr;
134 /* rximg->image->obdata = &(rximg->info); */
136 if (shmError) {
137 context->attribs->use_shared_memory = 0;
138 XDestroyImage(rximg->image);
139 if (shmdt(rximg->info.shmaddr) < 0)
140 perror("wrlib: shmdt");
141 if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
142 perror("wrlib: shmctl");
143 /* printf("wrlib:error attaching shared memory segment to XImage\n");
145 goto retry_without_shm;
148 #endif /* XSHM */
150 return rximg;
153 void RDestroyXImage(RContext * context, RXImage * rximage)
155 #ifndef XSHM
156 XDestroyImage(rximage->image);
157 #else /* XSHM */
158 if (rximage->is_shared) {
159 XSync(context->dpy, False);
160 XShmDetach(context->dpy, &rximage->info);
161 XDestroyImage(rximage->image);
162 if (shmdt(rximage->info.shmaddr) < 0)
163 perror("wrlib: shmdt");
164 if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
165 perror("wrlib: shmctl");
166 } else {
167 XDestroyImage(rximage->image);
169 #endif
170 free(rximage);
173 static unsigned getDepth(Display * dpy, Drawable d)
175 Window w;
176 int foo;
177 unsigned bar;
178 unsigned depth;
180 XGetGeometry(dpy, d, &w, &foo, &foo, &bar, &bar, &bar, &depth);
182 return depth;
185 RXImage *RGetXImage(RContext * context, Drawable d, int x, int y, unsigned width, unsigned height)
187 RXImage *ximg = NULL;
189 #ifdef XSHM
190 if (context->attribs->use_shared_memory && 0) {
191 ximg = RCreateXImage(context, getDepth(context->dpy, d), width, height);
193 if (ximg && !ximg->is_shared) {
194 RDestroyXImage(context, ximg);
195 ximg = NULL;
197 if (ximg) {
198 XShmGetImage(context->dpy, d, ximg->image, x, y, AllPlanes);
201 if (!ximg) {
202 ximg = malloc(sizeof(RXImage));
203 if (!ximg) {
204 RErrorCode = RERR_NOMEMORY;
205 return NULL;
207 ximg->is_shared = 0;
208 ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
210 return ximg;
211 #else /* !XSHM */
212 ximg = malloc(sizeof(RXImage));
213 if (!ximg) {
214 RErrorCode = RERR_NOMEMORY;
215 return NULL;
218 ximg->image = XGetImage(context->dpy, d, x, y, width, height, AllPlanes, ZPixmap);
220 return ximg;
221 #endif /* !XSHM */
224 void
225 RPutXImage(RContext * context, Drawable d, GC gc, RXImage * ximage, int src_x,
226 int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height)
228 #ifndef XSHM
229 XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
230 #else
231 if (ximage->is_shared) {
232 XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
233 dest_x, dest_y, width, height, False);
234 } else {
235 XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x, dest_y, width, height);
237 XFlush(context->dpy);
238 #endif /* XSHM */
241 #ifdef XSHM
242 Pixmap R_CreateXImageMappedPixmap(RContext * context, RXImage * rximage)
244 Pixmap pix;
246 pix = XShmCreatePixmap(context->dpy, context->drawable,
247 rximage->image->data, &rximage->info,
248 rximage->image->width, rximage->image->height, rximage->image->depth);
250 return pix;
253 #endif /* XSHM */