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 */
55 /* used to store width and height from ConfigureNotify event */
60 static struct x11_win
*win_list
= NULL
;
62 static void win_list_add(struct x11_win
*win
)
69 static void win_list_rem(struct x11_win
*win
)
72 win
->prev
->next
= win
->next
;
75 win
->next
->prev
= win
->prev
;
81 struct x11_win
*win_list_lookup(Window win
)
85 for (i
= win_list
; i
!= NULL
; i
= i
->next
) {
93 #ifndef _NET_WM_STATE_ADD
94 # define _NET_WM_STATE_ADD 1
95 #endif /* _NET_WM_STATE_ADD */
97 #ifndef _NET_WM_STATE_REMOVE
98 # define _NET_WM_STATE_REMOVE 0
99 #endif /* _NET_WM_STATE_REMOVE */
101 /* Send NETWM message, most modern Window Managers should understand */
102 static void x11_win_fullscreen(struct x11_win
*win
, int mode
)
104 if (mode
< 0 || mode
> 2) {
105 GP_WARN("Invalid fullscreen mode = %u", mode
);
109 GP_DEBUG(2, "Requesting fullscreen mode = %u", mode
);
111 Atom wm_state
, fullscreen
;
113 wm_state
= XInternAtom(win
->dpy
, "_NET_WM_STATE", True
);
114 fullscreen
= XInternAtom(win
->dpy
, "_NET_WM_STATE_FULLSCREEN", True
);
116 if (wm_state
== None
|| fullscreen
== None
) {
117 GP_WARN("Failed to create _NET_WM_* atoms");
123 memset(&ev
, 0, sizeof(ev
));
125 ev
.type
= ClientMessage
;
126 ev
.xclient
.window
= win
->win
;
127 ev
.xclient
.message_type
= wm_state
;
128 ev
.xclient
.format
= 32;
129 ev
.xclient
.data
.l
[0] = mode
;
130 ev
.xclient
.data
.l
[1] = fullscreen
;
131 ev
.xclient
.data
.l
[2] = 0;
132 ev
.xclient
.data
.l
[3] = 1;
134 if (!XSendEvent(win
->dpy
, XDefaultRootWindow(win
->dpy
),
135 False
, SubstructureNotifyMask
, &ev
)) {
136 GP_WARN("Failed to send _NET_WM_STATE_FULLSCREEN event");
143 /* Window request structure */
161 static void x11_get_screen_size(struct x11_wreq
*wreq
)
163 wreq
->w
= DisplayWidth(wreq
->win
->dpy
, wreq
->win
->scr
);
164 wreq
->h
= DisplayHeight(wreq
->win
->dpy
, wreq
->win
->scr
);
167 static int x11_win_open(struct x11_wreq
*wreq
)
169 XSetWindowAttributes attrs
;
170 unsigned long attr_mask
= 0;
174 /* Initialize connection/increase ref count */
175 if (!x11_open(wreq
->display
))
181 win
->dpy
= x11_conn
.dpy
;
183 /* Get visual and screen depth */
184 win
->scr
= DefaultScreen(win
->dpy
);
185 win
->vis
= DefaultVisual(win
->dpy
, win
->scr
);
186 scr_ptr
= DefaultScreenOfDisplay(win
->dpy
);
187 win
->scr_depth
= DefaultDepthOfScreen(scr_ptr
);
189 GP_DEBUG(2, "Have Visual id %i, depth %u", (int)win
->vis
->visualid
, win
->scr_depth
);
192 attrs
.event_mask
= ExposureMask
| StructureNotifyMask
| KeyPressMask
|
193 KeyReleaseMask
| PointerMotionMask
;
194 attr_mask
|= CWEventMask
;
197 * If root window was selected, resize w and h and set win->win to root
200 if (wreq
->flags
& GP_X11_USE_ROOT_WIN
) {
202 win
->win
= DefaultRootWindow(win
->dpy
);
204 x11_get_screen_size(wreq
);
206 GP_DEBUG(2, "Using root window, owerriding size to %ux%u",
211 XChangeWindowAttributes(win
->dpy
, win
->win
, attr_mask
, &attrs
);
217 * For some reason reading mouse button clicks on root win are not
220 attrs
.event_mask
|= ButtonPressMask
| ButtonReleaseMask
;
223 * Create undecoreated root window on background
225 if (wreq
->flags
& GP_X11_CREATE_ROOT_WIN
) {
228 x11_get_screen_size(wreq
);
230 GP_DEBUG(2, "Creating a window above root, owerriding size to %ux%u",
233 win
->win
= XCreateWindow(win
->dpy
, DefaultRootWindow(win
->dpy
),
234 0, 0, wreq
->w
, wreq
->h
, 0, CopyFromParent
,
235 InputOutput
, CopyFromParent
, attr_mask
, &attrs
);
237 /* Set empty WM_PROTOCOLS */
238 GP_DEBUG(2, "Setting empty MW_PROTOCOLS");
239 XSetWMProtocols(win
->dpy
, win
->win
, NULL
, 0);
241 /* Set window type to desktop */
242 xa
= XInternAtom(win
->dpy
, "_NET_WM_WINDOW_TYPE", False
);
245 GP_DEBUG(2, "Setting Atom _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_DESKTOP");
247 Atom xa_prop
= XInternAtom(win
->dpy
, "_NET_WM_WINDOW_TYPE_DESKTOP", False
);
249 XChangeProperty(win
->dpy
, win
->win
, xa
, XA_ATOM
, 32,
250 PropModeReplace
, (unsigned char *) &xa_prop
, 1);
253 /* Turn off window decoration */
254 xa
= XInternAtom(win
->dpy
, "_MOTIF_WM_HINTS", False
);
257 GP_DEBUG(2, "Setting Atom _MOTIF_WM_HINTS to 2, 0, 0, 0, 0");
259 long prop
[5] = {2, 0, 0, 0, 0};
261 XChangeProperty(win
->dpy
, win
->win
, xa
, xa
, 32,
262 PropModeReplace
, (unsigned char *) prop
, 5);
265 /* Set below other windows */
266 xa
= XInternAtom(win
->dpy
, "_WIN_LAYER", False
);
269 GP_DEBUG(2, "Setting Atom _WIN_LAYER to 6");
273 XChangeProperty(win
->dpy
, win
->win
, xa
, XA_CARDINAL
, 32,
274 PropModeAppend
, (unsigned char *) &prop
, 1);
277 xa
= XInternAtom(win
->dpy
, "_NET_WM_STATE", False
);
280 GP_DEBUG(2, "Setting Atom _NET_WM_STATE to _NET_WM_STATE_BELOW");
282 Atom xa_prop
= XInternAtom(win
->dpy
, "_NET_WM_STATE_BELOW", False
);
284 XChangeProperty(win
->dpy
, win
->win
, xa
, XA_ATOM
, 32,
285 PropModeAppend
, (unsigned char *) &xa_prop
, 1);
289 xa
= XInternAtom(win
->dpy
, "_NET_WM_DESKTOP", False
);
292 GP_DEBUG(2, "Setting Atom _NET_WM_DESKTOP to 0xffffffff");
294 CARD32 xa_prop
= 0xffffffff;
296 XChangeProperty(win
->dpy
, win
->win
, xa
, XA_CARDINAL
, 32,
297 PropModeAppend
, (unsigned char *) &xa_prop
, 1);
300 xa
= XInternAtom(win
->dpy
, "_NET_WM_STATE", False
);
303 GP_DEBUG(2, "Appending to Atom _NET_WM_STATE atom _NET_WM_STATE_STICKY");
305 Atom xa_prop
= XInternAtom(win
->dpy
, "_NET_WM_STATE_STICKY", 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_STATE", False
);
315 GP_DEBUG(2, "Appending to Atom _NET_WM_STATE atom _NET_STATE_SKIP_TASKBAR");
317 Atom xa_prop
= XInternAtom(win
->dpy
, "_NET_WM_STATE_SKIP_TASKBAR", False
);
319 XChangeProperty(win
->dpy
, win
->win
, xa
, XA_ATOM
, 32,
320 PropModeAppend
, (unsigned char *) &xa_prop
, 1);
324 xa
= XInternAtom(win
->dpy
, "_NET_WM_STATE", False
);
327 GP_DEBUG(2, "Appending to Atom _NET_WM_STATE atom _NET_STATE_SKIP_PAGER");
329 Atom xa_prop
= XInternAtom(win
->dpy
, "_NET_WM_STATE_SKIP_PAGER", False
);
331 XChangeProperty(win
->dpy
, win
->win
, xa
, XA_ATOM
, 32,
332 PropModeAppend
, (unsigned char *) &xa_prop
, 1);
335 /* Set 100% opacity */
336 xa
= XInternAtom(win
->dpy
, "_NET_WM_WINDOW_OPACITY", False
);
339 GP_DEBUG(2, "Setting Atom _NET_WM_WINDOW_OPACITY to 0xffffffff");
341 long prop
= 0xffffffff;
343 XChangeProperty(win
->dpy
, win
->win
, xa
, XA_CARDINAL
, 32,
344 PropModeAppend
, (unsigned char *) &prop
, 1);
350 XMapWindow(win
->dpy
, win
->win
);
354 GP_DEBUG(2, "Opening window '%s' %ix%i-%ux%u",
355 wreq
->caption
, wreq
->x
, wreq
->y
, wreq
->w
, wreq
->h
);
357 win
->win
= XCreateWindow(win
->dpy
, DefaultRootWindow(win
->dpy
),
358 wreq
->x
, wreq
->y
, wreq
->w
, wreq
->h
, 0,
359 CopyFromParent
, InputOutput
, CopyFromParent
,
362 /* Set window caption */
363 XmbSetWMProperties(win
->dpy
, win
->win
, wreq
->caption
, wreq
->caption
,
364 NULL
, 0, NULL
, NULL
, NULL
);
366 /* Make the window close button send event */
367 Atom xa
= XInternAtom(win
->dpy
, "WM_DELETE_WINDOW", True
);
370 GP_DEBUG(2, "Setting WM_DELETE_WINDOW Atom to True");
372 XSetWMProtocols(win
->dpy
, win
->win
, &xa
, 1);
374 GP_DEBUG(2, "Failed to set WM_DELETE_WINDOW Atom to True");
380 XMapWindow(win
->dpy
, win
->win
);
385 void x11_win_close(struct x11_win
*win
)
387 XLockDisplay(win
->dpy
);
393 destroy_shm_ximage(self);
395 destroy_ximage(self);
398 XDestroyWindow(win
->dpy
, win
->win
);
400 XUnlockDisplay(win
->dpy
);
402 /* Close connection/Decrease ref count */