1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
23 #include "../../config.h"
28 #include <X11/Xutil.h>
30 #include "core/GP_Debug.h"
31 #include "input/GP_InputDriverX11.h"
44 static void x11_exit(GP_Backend
*self
)
46 struct x11_priv
*x11
= GP_BACKEND_PRIV(self
);
48 XLockDisplay(x11
->dpy
);
50 GP_ContextFree(self
->context
);
52 x11
->img
->data
= NULL
;
53 XDestroyImage(x11
->img
);
54 XDestroyWindow(x11
->dpy
, x11
->win
);
55 /* I wonder if this is right sequence... */
56 XUnlockDisplay(x11
->dpy
);
57 XCloseDisplay(x11
->dpy
);
62 static void x11_update_rect(GP_Backend
*self
, GP_Coord x0
, GP_Coord y0
,
63 GP_Coord x1
, GP_Coord y1
)
65 struct x11_priv
*x11
= GP_BACKEND_PRIV(self
);
67 GP_DEBUG(4, "Updating rect %ix%i-%ix%i", x0
, y0
, x1
, y1
);
69 XLockDisplay(x11
->dpy
);
71 XPutImage(x11
->dpy
, x11
->win
, DefaultGC(x11
->dpy
, x11
->scr
),
72 x11
->img
, x0
, y0
, x0
, y0
, x1
-x0
+1, y1
-y0
+1);
75 x11
->resized_flag
= 0;
77 XUnlockDisplay(x11
->dpy
);
80 static void x11_flip(GP_Backend
*self
)
82 struct x11_priv
*x11
= GP_BACKEND_PRIV(self
);
83 unsigned int w
= self
->context
->w
;
84 unsigned int h
= self
->context
->h
;
86 GP_DEBUG(4, "Flipping context");
88 XLockDisplay(x11
->dpy
);
90 XPutImage(x11
->dpy
, x11
->win
, DefaultGC(x11
->dpy
, x11
->scr
),
91 x11
->img
, 0, 0, 0, 0, w
, h
);
94 x11
->resized_flag
= 0;
96 XUnlockDisplay(x11
->dpy
);
99 static void x11_poll(GP_Backend
*self
)
101 struct x11_priv
*x11
= GP_BACKEND_PRIV(self
);
104 XLockDisplay(x11
->dpy
);
106 while (XPending(x11
->dpy
)) {
107 XNextEvent(x11
->dpy
, &ev
);
111 GP_DEBUG(4, "Expose %ix%i-%ix%i %i",
112 ev
.xexpose
.x
, ev
.xexpose
.y
,
113 ev
.xexpose
.width
, ev
.xexpose
.height
,
116 if (x11
->resized_flag
)
119 x11_update_rect(self
, ev
.xexpose
.x
, ev
.xexpose
.y
,
120 ev
.xexpose
.x
+ ev
.xexpose
.width
- 1,
121 ev
.xexpose
.y
+ ev
.xexpose
.height
- 1);
123 case ConfigureNotify
:
124 if (ev
.xconfigure
.width
== (int)self
->context
->w
&&
125 ev
.xconfigure
.height
== (int)self
->context
->h
)
128 GP_InputDriverX11EventPut(&ev
);
133 XUnlockDisplay(x11
->dpy
);
136 static int x11_set_attributes(struct GP_Backend
*self
,
137 uint32_t w
, uint32_t h
,
140 struct x11_priv
*x11
= GP_BACKEND_PRIV(self
);
142 XLockDisplay(x11
->dpy
);
144 if (caption
!= NULL
) {
145 GP_DEBUG(3, "Setting window caption to '%s'", caption
);
146 XmbSetWMProperties(x11
->dpy
, x11
->win
, caption
, caption
,
147 NULL
, 0, NULL
, NULL
, NULL
);
150 if (w
!= 0 || h
!= 0) {
154 w
= self
->context
->w
;
157 h
= self
->context
->h
;
159 GP_DEBUG(3, "Setting window size to %ux%u", w
, h
);
161 /* Create new X image */
162 img
= XCreateImage(x11
->dpy
, x11
->vis
, 24, ZPixmap
, 0, NULL
,
165 /* Allocate new context */
167 if (GP_ContextResize(self
->context
, w
, h
)) {
173 x11
->img
->data
= NULL
;
174 XDestroyImage(x11
->img
);
176 /* Swap the pointers */
177 img
->data
= (char*)self
->context
->pixels
;
180 /* Resize X11 window */
181 XResizeWindow(x11
->dpy
, x11
->win
, w
, h
);
184 x11
->resized_flag
= 1;
187 XUnlockDisplay(x11
->dpy
);
192 GP_Backend
*GP_BackendX11Init(const char *display
, int x
, int y
,
193 unsigned int w
, unsigned int h
,
197 struct x11_priv
*x11
;
199 GP_DEBUG(1, "Initalizing X11 display '%s'", display
);
201 backend
= malloc(sizeof(GP_Backend
) +
202 sizeof(struct x11_priv
));
207 x11
= GP_BACKEND_PRIV(backend
);
209 backend
->context
= GP_ContextAlloc(w
, h
, GP_PIXEL_xRGB8888
);
211 if (backend
->context
== NULL
)
214 //TODO: Error checking
217 x11
->dpy
= XOpenDisplay(display
);
219 if (x11
->dpy
== NULL
)
222 x11
->scr
= DefaultScreen(x11
->dpy
);
223 x11
->vis
= DefaultVisual(x11
->dpy
, x11
->scr
);
225 GP_DEBUG(2, "Opening window '%s' %ix%i-%ux%u",
226 caption
, x
, y
, w
, h
);
228 x11
->img
= XCreateImage(x11
->dpy
, x11
->vis
, 24, ZPixmap
, 0, NULL
,
231 x11
->img
->data
= (char*)backend
->context
->pixels
;
233 x11
->win
= XCreateWindow(x11
->dpy
, DefaultRootWindow(x11
->dpy
),
234 x
, y
, w
, h
, 0, CopyFromParent
,
235 InputOutput
, CopyFromParent
, 0, NULL
);
237 if (x11
->win
== None
) {
238 //TODO: Error message?
239 GP_DEBUG(1, "Failed to create window");
244 XSelectInput(x11
->dpy
, x11
->win
, ExposureMask
| StructureNotifyMask
|
245 KeyPressMask
| KeyReleaseMask
|
246 ButtonPressMask
| ButtonReleaseMask
|
249 /* Set window caption */
250 XmbSetWMProperties(x11
->dpy
, x11
->win
, caption
, caption
,
251 NULL
, 0, NULL
, NULL
, NULL
);
254 XMapWindow(x11
->dpy
, x11
->win
);
257 x11
->resized_flag
= 0;
261 enum GP_PixelType pixel_type;
262 pixel_type = GP_PixelRGBLookup(vscri.red.length, vscri.red.offset,
263 vscri.green.length, vscri.green.offset,
264 vscri.blue.length, vscri.blue.offset,
265 vscri.transp.length, vscri.transp.offset,
266 vscri.bits_per_pixel);
268 if (pixel_type == GP_PIXEL_UNKNOWN) {
269 GP_DEBUG(1, "Unknown pixel type\n");
276 backend
->name
= "X11";
277 backend
->Flip
= x11_flip
;
278 backend
->UpdateRect
= x11_update_rect
;
279 backend
->Exit
= x11_exit
;
280 backend
->fd_list
= NULL
;
281 backend
->Poll
= x11_poll
;
282 backend
->SetAttributes
= x11_set_attributes
;
287 // XDestroyWindow(x11->dpy, x11->win);
289 XCloseDisplay(x11
->dpy
);
291 GP_ContextFree(backend
->context
);
299 #include "GP_Backend.h"
301 GP_Backend
*GP_BackendX11Init(const char *display
, int x
, int y
,
302 unsigned int w
, unsigned int h
,
308 #endif /* HAVE_LIBX11 */