Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / QtCollider / hacks / hacks_x11.cpp
blob9c3989a26750c09c0660f826e7d4b928df1b0e1f
1 /************************************************************************
3 * adapted from:
4 * wmctrl
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"
30 #ifdef Q_WS_X11
31 #include <stdlib.h>
32 #include <stdio.h>
34 #include <X11/Xlib.h>
35 #include <X11/Xatom.h>
37 #define MAX_PROPERTY_VALUE_LEN 4096
39 static inline void p_verbose(...)
42 #define gchar char
43 #define gboolean bool
44 #define g_malloc (char*)malloc
45 #define g_free free
47 static gchar *get_property (Display *disp, Window win,
48 Atom xa_prop_type, const gchar *prop_name, unsigned long *size) {
49 Atom xa_prop_name;
50 Atom xa_ret_type;
51 int ret_format;
52 unsigned long ret_nitems;
53 unsigned long ret_bytes_after;
54 unsigned long tmp_size;
55 unsigned char *ret_prop;
56 gchar *ret;
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);
69 return NULL;
72 if (xa_ret_type != xa_prop_type) {
73 p_verbose("Invalid type of %s property.\n", prop_name);
74 XFree(ret_prop);
75 return NULL;
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);
82 ret[tmp_size] = '\0';
84 if (size) {
85 *size = tmp_size;
88 XFree(ret_prop);
89 return ret;
90 }/*}}}*/
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) {
96 XEvent event;
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)) {
112 return EXIT_SUCCESS;
114 else {
115 fprintf(stderr, "Cannot send %s event.\n", msg);
116 return EXIT_FAILURE;
118 }/*}}}*/
120 static int activate_window (Display *disp, Window win, /* {{{ */
121 gboolean switch_desktop) {
122 unsigned long *desktop;
124 /* desktop ID */
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");
140 if (desktop)
141 g_free(desktop);
143 client_msg(disp, win, "_NET_ACTIVE_WINDOW",
144 0, 0, 0, 0, 0);
145 XMapRaised(disp, win);
147 return EXIT_SUCCESS;
148 }/*}}}*/
150 #undef p_verbose
151 #undef gchar
152 #undef gboolean
153 #undef g_malloc
154 #undef g_free
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)
161 return true;
163 int raised_via_ewmh_error = activate_window(display, window, true);
164 return raised_via_ewmh_error == 0;
168 #endif