1 /************************************************************************
5 * A command line tool to interact with an EWMH/NetWM compatible X Window Manager.
7 * Copyright 2003 Tomas Styblo <tripie@cpan.org>
8 * Copyright 2011 Tim Blechmann (tim@klingt.org)
9 * Copyright 2011 Jakob Leben (jakob.leben@gmail.com)
11 * This file is part of SuperCollider Qt GUI.
13 * This program is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 ************************************************************************/
28 #include "hacks_x11.hpp"
35 #include <X11/Xatom.h>
37 #define MAX_PROPERTY_VALUE_LEN 4096
39 static inline void p_verbose(...)
44 #define g_malloc (char*)malloc
47 static gchar
*get_property (Display
*disp
, Window win
,
48 Atom xa_prop_type
, const gchar
*prop_name
, unsigned long *size
) {
52 unsigned long ret_nitems
;
53 unsigned long ret_bytes_after
;
54 unsigned long tmp_size
;
55 unsigned char *ret_prop
;
58 xa_prop_name
= XInternAtom(disp
, prop_name
, False
);
60 /* MAX_PROPERTY_VALUE_LEN / 4 explanation (XGetWindowProperty manpage):
62 * long_length = Specifies the length in 32-bit multiples of the
63 * data to be retrieved.
65 if (XGetWindowProperty(disp
, win
, xa_prop_name
, 0, MAX_PROPERTY_VALUE_LEN
/ 4, False
,
66 xa_prop_type
, &xa_ret_type
, &ret_format
,
67 &ret_nitems
, &ret_bytes_after
, &ret_prop
) != Success
) {
68 p_verbose("Cannot get %s property.\n", prop_name
);
72 if (xa_ret_type
!= xa_prop_type
) {
73 p_verbose("Invalid type of %s property.\n", prop_name
);
78 /* null terminate the result to make string handling easier */
79 tmp_size
= (ret_format
/ 8) * ret_nitems
;
80 ret
= g_malloc(tmp_size
+ 1);
81 memcpy(ret
, ret_prop
, tmp_size
);
92 static int client_msg(Display
*disp
, Window win
, const char *msg
, /* {{{ */
93 unsigned long data0
, unsigned long data1
,
94 unsigned long data2
, unsigned long data3
,
95 unsigned long data4
) {
97 long mask
= SubstructureRedirectMask
| SubstructureNotifyMask
;
99 event
.xclient
.type
= ClientMessage
;
100 event
.xclient
.serial
= 0;
101 event
.xclient
.send_event
= True
;
102 event
.xclient
.message_type
= XInternAtom(disp
, msg
, False
);
103 event
.xclient
.window
= win
;
104 event
.xclient
.format
= 32;
105 event
.xclient
.data
.l
[0] = data0
;
106 event
.xclient
.data
.l
[1] = data1
;
107 event
.xclient
.data
.l
[2] = data2
;
108 event
.xclient
.data
.l
[3] = data3
;
109 event
.xclient
.data
.l
[4] = data4
;
111 if (XSendEvent(disp
, DefaultRootWindow(disp
), False
, mask
, &event
)) {
115 fprintf(stderr
, "Cannot send %s event.\n", msg
);
120 static int activate_window (Display
*disp
, Window win
, /* {{{ */
121 gboolean switch_desktop
) {
122 unsigned long *desktop
;
125 if ((desktop
= (unsigned long *)get_property(disp
, win
,
126 XA_CARDINAL
, "_NET_WM_DESKTOP", NULL
)) == NULL
) {
127 if ((desktop
= (unsigned long *)get_property(disp
, win
,
128 XA_CARDINAL
, "_WIN_WORKSPACE", NULL
)) == NULL
) {
129 p_verbose("Cannot find desktop ID of the window.\n");
133 if (switch_desktop
&& desktop
) {
134 if (client_msg(disp
, DefaultRootWindow(disp
),
135 "_NET_CURRENT_DESKTOP",
136 *desktop
, 0, 0, 0, 0) != EXIT_SUCCESS
) {
137 p_verbose("Cannot switch desktop.\n");
143 client_msg(disp
, win
, "_NET_ACTIVE_WINDOW",
145 XMapRaised(disp
, win
);
156 bool raise_window(Display
* display
, QWidget
* win
)
158 Window window
= win
->winId();
159 int raised_via_xlib_error
= XRaiseWindow(display
, window
);
160 if (raised_via_xlib_error
== 0)
163 int raised_via_ewmh_error
= activate_window(display
, window
, true);
164 return raised_via_ewmh_error
== 0;