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
43 #define g_malloc (char*)malloc
46 static gchar
*get_property (Display
*disp
, Window win
,
47 Atom xa_prop_type
, const gchar
*prop_name
, unsigned long *size
) {
51 unsigned long ret_nitems
;
52 unsigned long ret_bytes_after
;
53 unsigned long tmp_size
;
54 unsigned char *ret_prop
;
57 xa_prop_name
= XInternAtom(disp
, prop_name
, False
);
59 /* MAX_PROPERTY_VALUE_LEN / 4 explanation (XGetWindowProperty manpage):
61 * long_length = Specifies the length in 32-bit multiples of the
62 * data to be retrieved.
64 if (XGetWindowProperty(disp
, win
, xa_prop_name
, 0, MAX_PROPERTY_VALUE_LEN
/ 4, False
,
65 xa_prop_type
, &xa_ret_type
, &ret_format
,
66 &ret_nitems
, &ret_bytes_after
, &ret_prop
) != Success
) {
67 p_verbose("Cannot get %s property.\n", prop_name
);
71 if (xa_ret_type
!= xa_prop_type
) {
72 p_verbose("Invalid type of %s property.\n", prop_name
);
77 /* null terminate the result to make string handling easier */
78 tmp_size
= (ret_format
/ 8) * ret_nitems
;
79 ret
= g_malloc(tmp_size
+ 1);
80 memcpy(ret
, ret_prop
, tmp_size
);
91 static int client_msg(Display
*disp
, Window win
, const char *msg
, /* {{{ */
92 unsigned long data0
, unsigned long data1
,
93 unsigned long data2
, unsigned long data3
,
94 unsigned long data4
) {
96 long mask
= SubstructureRedirectMask
| SubstructureNotifyMask
;
98 event
.xclient
.type
= ClientMessage
;
99 event
.xclient
.serial
= 0;
100 event
.xclient
.send_event
= True
;
101 event
.xclient
.message_type
= XInternAtom(disp
, msg
, False
);
102 event
.xclient
.window
= win
;
103 event
.xclient
.format
= 32;
104 event
.xclient
.data
.l
[0] = data0
;
105 event
.xclient
.data
.l
[1] = data1
;
106 event
.xclient
.data
.l
[2] = data2
;
107 event
.xclient
.data
.l
[3] = data3
;
108 event
.xclient
.data
.l
[4] = data4
;
110 if (XSendEvent(disp
, DefaultRootWindow(disp
), False
, mask
, &event
)) {
114 fprintf(stderr
, "Cannot send %s event.\n", msg
);
119 static int activate_window (Display
*disp
, Window win
, /* {{{ */
120 gboolean switch_desktop
) {
121 unsigned long *desktop
;
124 if ((desktop
= (unsigned long *)get_property(disp
, win
,
125 XA_CARDINAL
, "_NET_WM_DESKTOP", NULL
)) == NULL
) {
126 if ((desktop
= (unsigned long *)get_property(disp
, win
,
127 XA_CARDINAL
, "_WIN_WORKSPACE", NULL
)) == NULL
) {
128 p_verbose("Cannot find desktop ID of the window.\n");
132 if (switch_desktop
&& desktop
) {
133 if (client_msg(disp
, DefaultRootWindow(disp
),
134 "_NET_CURRENT_DESKTOP",
135 *desktop
, 0, 0, 0, 0) != EXIT_SUCCESS
) {
136 p_verbose("Cannot switch desktop.\n");
142 client_msg(disp
, win
, "_NET_ACTIVE_WINDOW",
144 XMapRaised(disp
, win
);
155 bool raise_window(Display
* display
, QWidget
* win
)
157 Window window
= win
->winId();
158 int raised_via_xlib_error
= XRaiseWindow(display
, window
);
159 if (raised_via_xlib_error
== 0)
162 int raised_via_ewmh_error
= activate_window(display
, window
, true);
163 return raised_via_ewmh_error
== 0;