Rename GP_Context -> GP_Pixmap
[gfxprim.git] / libs / backends / GP_X11_Win.h
blob58873d1b46e71225b9796ac1cdcc4e1acb7f5bd0
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
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. *
8 * *
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. *
13 * *
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 *
18 * *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
24 * X11 window.
26 struct x11_win {
27 /* X11 Display */
28 Display *dpy;
29 /* X11 Screen */
30 int scr;
31 /* X11 Screen depth */
32 int scr_depth;
33 /* X11 Visual */
34 Visual *vis;
35 /* X11 Window */
36 Window win;
38 /* Image info SHM or XImage */
39 XImage *img;
41 #ifdef HAVE_X_SHM
42 XShmSegmentInfo shminfo;
43 #endif /* HAVE_X_SHM */
45 GP_Pixmap pixmap;
47 /* Window list pointers */
48 struct x11_win *prev;
49 struct x11_win *next;
51 /* Flags */
52 int resized_flag:1;
53 int shm_flag:1;
54 int fullscreen_flag:1;
56 /* used to store width and height from ConfigureNotify event */
57 unsigned int new_w;
58 unsigned int new_h;
61 static struct x11_win *win_list = NULL;
63 static void win_list_add(struct x11_win *win)
65 win->next = win_list;
66 win->prev = NULL;
67 win_list = win;
70 static void win_list_rem(struct x11_win *win)
72 if (win->prev)
73 win->prev->next = win->next;
75 if (win->next)
76 win->next->prev = win->prev;
78 if (win == win_list)
79 win_list = win->next;
82 static struct x11_win *win_list_lookup(Window win)
84 struct x11_win *i;
86 for (i = win_list; i != NULL; i = i->next) {
87 if (i->win == win)
88 return i;
91 return NULL;
94 static int win_list_empty(void)
96 return win_list == NULL;
99 #ifndef _NET_WM_STATE_REMOVE
100 # define _NET_WM_STATE_REMOVE 0
101 #endif
103 #ifndef _NET_WM_STATE_ADD
104 # define _NET_WM_STATE_ADD 1
105 #endif
107 #ifndef _NET_WM_STATE_TOGGLE
108 # define _NET_WM_STATE_TOGGLE 2
109 #endif
111 /* Send NETWM message, most modern Window Managers should understand */
112 static void x11_win_fullscreen(struct x11_win *win, int mode)
114 int fs;
115 XEvent ev;
117 switch (mode) {
118 case _NET_WM_STATE_REMOVE:
119 fs = 0;
120 break;
121 case _NET_WM_STATE_ADD:
122 fs = 1;
123 break;
124 case _NET_WM_STATE_TOGGLE:
125 fs = !win->fullscreen_flag;
126 break;
127 default:
128 GP_WARN("Invalid fullscreen mode = %u", mode);
129 return;
132 if (fs == win->fullscreen_flag)
133 return;
135 if (!x11_conn.S__NET_WM_STATE || !x11_conn.S__NET_WM_STATE_FULLSCREEN) {
136 GP_WARN("NetWM Fullscreen not supported");
137 return;
140 GP_DEBUG(2, "Requesting fullscreen mode = %u, fs = %i", mode, fs);
142 memset(&ev, 0, sizeof(ev));
144 ev.type = ClientMessage;
145 ev.xclient.window = win->win;
146 ev.xclient.message_type = x11_conn.A__NET_WM_STATE;
147 ev.xclient.format = 32;
148 ev.xclient.data.l[0] = mode;
149 ev.xclient.data.l[1] = x11_conn.A__NET_WM_STATE_FULLSCREEN;
150 ev.xclient.data.l[2] = 0;
151 ev.xclient.data.l[3] = 1;
153 if (!XSendEvent(win->dpy, XDefaultRootWindow(win->dpy),
154 False, SubstructureNotifyMask|SubstructureRedirectMask, &ev)) {
155 GP_WARN("Failed to send _NET_WM_STATE_FULLSCREEN event");
156 return;
159 win->fullscreen_flag = fs;
161 XFlush(win->dpy);
164 /* Window request structure */
165 struct x11_wreq {
166 struct x11_win *win;
168 /* X11 display */
169 const char *display;
171 /* geometry */
172 int x;
173 int y;
174 unsigned int w;
175 unsigned int h;
177 const char *caption;
179 unsigned int flags;
182 static void x11_get_screen_size(struct x11_wreq *wreq)
184 wreq->w = DisplayWidth(wreq->win->dpy, wreq->win->scr);
185 wreq->h = DisplayHeight(wreq->win->dpy, wreq->win->scr);
188 static int x11_win_open(struct x11_wreq *wreq)
190 XSetWindowAttributes attrs;
191 unsigned long attr_mask = 0;
192 struct x11_win *win;
193 Screen *scr_ptr;
195 /* Initialize connection/increase ref count */
196 if (!x11_open(wreq->display))
197 return 1;
199 win = wreq->win;
201 win->fullscreen_flag = 0;
203 /* Copy display */
204 win->dpy = x11_conn.dpy;
206 /* Get visual and screen depth */
207 win->scr = DefaultScreen(win->dpy);
208 win->vis = DefaultVisual(win->dpy, win->scr);
209 scr_ptr = DefaultScreenOfDisplay(win->dpy);
210 win->scr_depth = DefaultDepthOfScreen(scr_ptr);
212 GP_DEBUG(2, "Have Visual id %i, depth %u", (int)win->vis->visualid, win->scr_depth);
214 /* Set event mask */
215 attrs.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
216 KeyReleaseMask | PointerMotionMask;
217 attr_mask |= CWEventMask;
220 * If root window was selected, resize w and h and set win->win to root
221 * window.
223 if (wreq->flags & GP_X11_USE_ROOT_WIN) {
225 win->win = DefaultRootWindow(win->dpy);
227 x11_get_screen_size(wreq);
229 GP_DEBUG(2, "Using root window, owerriding size to %ux%u",
230 wreq->w, wreq->h);
232 win_list_add(win);
234 XChangeWindowAttributes(win->dpy, win->win, attr_mask, &attrs);
236 return 0;
240 * For some reason reading mouse button clicks on root win are not
241 * allowed...
243 attrs.event_mask |= ButtonPressMask | ButtonReleaseMask;
246 * Create undecoreated root window on background
248 if (wreq->flags & GP_X11_CREATE_ROOT_WIN) {
249 Atom xa;
251 x11_get_screen_size(wreq);
253 GP_DEBUG(2, "Creating a window above root, owerriding size to %ux%u",
254 wreq->w, wreq->h);
256 win->win = XCreateWindow(win->dpy, DefaultRootWindow(win->dpy),
257 0, 0, wreq->w, wreq->h, 0, CopyFromParent,
258 InputOutput, CopyFromParent, attr_mask, &attrs);
260 /* Set empty WM_PROTOCOLS */
261 GP_DEBUG(2, "Setting empty MW_PROTOCOLS");
262 XSetWMProtocols(win->dpy, win->win, NULL, 0);
264 /* Set window type to desktop */
265 xa = XInternAtom(win->dpy, "_NET_WM_WINDOW_TYPE", False);
267 if (xa != None) {
268 GP_DEBUG(2, "Setting Atom _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_DESKTOP");
270 Atom xa_prop = XInternAtom(win->dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
272 XChangeProperty(win->dpy, win->win, xa, XA_ATOM, 32,
273 PropModeReplace, (unsigned char *) &xa_prop, 1);
276 /* Turn off window decoration */
277 xa = XInternAtom(win->dpy, "_MOTIF_WM_HINTS", False);
279 if (xa != None) {
280 GP_DEBUG(2, "Setting Atom _MOTIF_WM_HINTS to 2, 0, 0, 0, 0");
282 long prop[5] = {2, 0, 0, 0, 0};
284 XChangeProperty(win->dpy, win->win, xa, xa, 32,
285 PropModeReplace, (unsigned char *) prop, 5);
288 /* Set below other windows */
289 xa = XInternAtom(win->dpy, "_WIN_LAYER", False);
291 if (xa != None) {
292 GP_DEBUG(2, "Setting Atom _WIN_LAYER to 6");
294 long prop = 6;
296 XChangeProperty(win->dpy, win->win, xa, XA_CARDINAL, 32,
297 PropModeAppend, (unsigned char *) &prop, 1);
300 xa = XInternAtom(win->dpy, "_NET_WM_STATE", False);
302 if (xa != None) {
303 GP_DEBUG(2, "Setting Atom _NET_WM_STATE to _NET_WM_STATE_BELOW");
305 Atom xa_prop = XInternAtom(win->dpy, "_NET_WM_STATE_BELOW", False);
307 XChangeProperty(win->dpy, win->win, xa, XA_ATOM, 32,
308 PropModeAppend, (unsigned char *) &xa_prop, 1);
311 /* Set sticky */
312 xa = XInternAtom(win->dpy, "_NET_WM_DESKTOP", False);
314 if (xa != None) {
315 GP_DEBUG(2, "Setting Atom _NET_WM_DESKTOP to 0xffffffff");
317 CARD32 xa_prop = 0xffffffff;
319 XChangeProperty(win->dpy, win->win, xa, XA_CARDINAL, 32,
320 PropModeAppend, (unsigned char *) &xa_prop, 1);
323 xa = XInternAtom(win->dpy, "_NET_WM_STATE", False);
325 if (xa != None) {
326 GP_DEBUG(2, "Appending to Atom _NET_WM_STATE atom _NET_WM_STATE_STICKY");
328 Atom xa_prop = XInternAtom(win->dpy, "_NET_WM_STATE_STICKY", False);
330 XChangeProperty(win->dpy, win->win, xa, XA_ATOM, 32,
331 PropModeAppend, (unsigned char *) &xa_prop, 1);
334 /* Skip taskbar */
335 xa = XInternAtom(win->dpy, "_NET_WM_STATE", False);
337 if (xa != None) {
338 GP_DEBUG(2, "Appending to Atom _NET_WM_STATE atom _NET_STATE_SKIP_TASKBAR");
340 Atom xa_prop = XInternAtom(win->dpy, "_NET_WM_STATE_SKIP_TASKBAR", False);
342 XChangeProperty(win->dpy, win->win, xa, XA_ATOM, 32,
343 PropModeAppend, (unsigned char *) &xa_prop, 1);
346 /* Skip pager */
347 xa = XInternAtom(win->dpy, "_NET_WM_STATE", False);
349 if (xa != None) {
350 GP_DEBUG(2, "Appending to Atom _NET_WM_STATE atom _NET_STATE_SKIP_PAGER");
352 Atom xa_prop = XInternAtom(win->dpy, "_NET_WM_STATE_SKIP_PAGER", False);
354 XChangeProperty(win->dpy, win->win, xa, XA_ATOM, 32,
355 PropModeAppend, (unsigned char *) &xa_prop, 1);
358 /* Set 100% opacity */
359 xa = XInternAtom(win->dpy, "_NET_WM_WINDOW_OPACITY", False);
361 if (xa != None) {
362 GP_DEBUG(2, "Setting Atom _NET_WM_WINDOW_OPACITY to 0xffffffff");
364 long prop = 0xffffffff;
366 XChangeProperty(win->dpy, win->win, xa, XA_CARDINAL, 32,
367 PropModeAppend, (unsigned char *) &prop, 1);
370 win_list_add(win);
372 /* Show window */
373 XMapWindow(win->dpy, win->win);
374 return 0;
377 GP_DEBUG(2, "Opening window '%s' %ix%i-%ux%u",
378 wreq->caption, wreq->x, wreq->y, wreq->w, wreq->h);
380 win->win = XCreateWindow(win->dpy, DefaultRootWindow(win->dpy),
381 wreq->x, wreq->y, wreq->w, wreq->h, 0,
382 CopyFromParent, InputOutput, CopyFromParent,
383 attr_mask, &attrs);
385 /* Set window caption */
386 XmbSetWMProperties(win->dpy, win->win, wreq->caption, wreq->caption,
387 NULL, 0, NULL, NULL, NULL);
389 /* Make the window close button send event */
390 XSetWMProtocols(win->dpy, win->win, &x11_conn.A_WM_DELETE_WINDOW, 1);
392 win_list_add(win);
394 /* Show window */
395 XMapWindow(win->dpy, win->win);
397 return 0;
400 static void x11_win_close(struct x11_win *win)
402 GP_DEBUG(1, "Closing window");
404 XLockDisplay(win->dpy);
406 win_list_rem(win);
409 if (x11->shm_flag)
410 destroy_shm_ximage(self);
411 else
412 destroy_ximage(self);
414 XUnmapWindow(win->dpy, win->win);
416 XDestroyWindow(win->dpy, win->win);
418 if (!win_list_empty())
419 XFlush(win->dpy);
421 XUnlockDisplay(win->dpy);
423 /* Close connection/Decrease ref count */
424 x11_close();