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-2013 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
31 /* X11 Screen depth */
38 /* Image info SHM or XImage */
42 XShmSegmentInfo shminfo
;
43 #endif /* HAVE_X_SHM */
47 /* Window list pointers */
54 int fullscreen_flag
:1;
56 /* used to store width and height from ConfigureNotify event */
61 static struct x11_win
*win_list
= NULL
;
63 static void win_list_add(struct x11_win
*win
)
70 static void win_list_rem(struct x11_win
*win
)
73 win
->prev
->next
= win
->next
;
76 win
->next
->prev
= win
->prev
;
82 static struct x11_win
*win_list_lookup(Window win
)
86 for (i
= win_list
; i
!= NULL
; i
= i
->next
) {
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
103 #ifndef _NET_WM_STATE_ADD
104 # define _NET_WM_STATE_ADD 1
107 #ifndef _NET_WM_STATE_TOGGLE
108 # define _NET_WM_STATE_TOGGLE 2
111 /* Send NETWM message, most modern Window Managers should understand */
112 static void x11_win_fullscreen(struct x11_win
*win
, int mode
)
118 case _NET_WM_STATE_REMOVE
:
121 case _NET_WM_STATE_ADD
:
124 case _NET_WM_STATE_TOGGLE
:
125 fs
= !win
->fullscreen_flag
;
128 GP_WARN("Invalid fullscreen mode = %u", mode
);
132 if (fs
== win
->fullscreen_flag
)
135 if (!x11_conn
.S__NET_WM_STATE
|| !x11_conn
.S__NET_WM_STATE_FULLSCREEN
) {
136 GP_WARN("NetWM Fullscreen not supported");
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");
159 win
->fullscreen_flag
= fs
;
164 /* Window request structure */
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;
195 /* Initialize connection/increase ref count */
196 if (!x11_open(wreq
->display
))
201 win
->fullscreen_flag
= 0;
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
);
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
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",
234 XChangeWindowAttributes(win
->dpy
, win
->win
, attr_mask
, &attrs
);
240 * For some reason reading mouse button clicks on root win are not
243 attrs
.event_mask
|= ButtonPressMask
| ButtonReleaseMask
;
246 * Create undecoreated root window on background
248 if (wreq
->flags
& GP_X11_CREATE_ROOT_WIN
) {
251 x11_get_screen_size(wreq
);
253 GP_DEBUG(2, "Creating a window above root, owerriding size to %ux%u",
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
);
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
);
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
);
292 GP_DEBUG(2, "Setting Atom _WIN_LAYER to 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
);
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);
312 xa
= XInternAtom(win
->dpy
, "_NET_WM_DESKTOP", False
);
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
);
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);
335 xa
= XInternAtom(win
->dpy
, "_NET_WM_STATE", False
);
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);
347 xa
= XInternAtom(win
->dpy
, "_NET_WM_STATE", False
);
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
);
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);
373 XMapWindow(win
->dpy
, win
->win
);
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
,
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);
395 XMapWindow(win
->dpy
, win
->win
);
400 static void x11_win_close(struct x11_win
*win
)
402 GP_DEBUG(1, "Closing window");
404 XLockDisplay(win
->dpy
);
410 destroy_shm_ximage(self);
412 destroy_ximage(self);
414 XUnmapWindow(win
->dpy
, win
->win
);
416 XDestroyWindow(win
->dpy
, win
->win
);
418 if (!win_list_empty())
421 XUnlockDisplay(win
->dpy
);
423 /* Close connection/Decrease ref count */