f39e99215f95f6584b549f17bf1ac428c6e28756
[lxde/lxpanel.git] / src / plugins / wincmd.c
1 /**
2 * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program 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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <stdlib.h>
20
21 #include <gdk-pixbuf/gdk-pixbuf.h>
22 #include <glib/gi18n.h>
23
24 #include "panel.h"
25 #include "misc.h"
26 #include "plugin.h"
27 //#define DEBUG
28 #include "dbg.h"
29
30
31 typedef struct {
32 GtkTooltips *tips;
33 char* image;
34 int button1, button2;
35 int action1, action2;
36 } wincmd;
37
38 enum { WC_NONE = 1, WC_ICONIFY, WC_SHADE };
39 static pair wincmd_pair [] = {
40 { WC_NONE, "none" },
41 { WC_ICONIFY, "iconify" },
42 { WC_SHADE, "shade" },
43 { 0, NULL },
44 };
45
46
47
48 static void
49 toggle_shaded(wincmd *wc, guint32 action)
50 {
51 Window *win = NULL;
52 int num, i;
53 guint32 tmp2, dno;
54 net_wm_window_type nwwt;
55
56 ENTER;
57 win = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &num);
58 if (!win)
59 RET();
60 if (!num)
61 goto end;
62 //tmp = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, XA_CARDINAL, 0);
63 //dno = *tmp;
64 dno = get_net_current_desktop();
65 DBG("wincmd: #desk=%d\n", dno);
66 //XFree(tmp);
67 for (i = 0; i < num; i++) {
68 int skip;
69
70 tmp2 = get_net_wm_desktop(win[i]);
71 DBG("wincmd: win=0x%x dno=%d...", win[i], tmp2);
72 if ((tmp2 != -1) && (tmp2 != dno)) {
73 DBG("skip - not cur desk\n");
74 continue;
75 }
76 get_net_wm_window_type(win[i], &nwwt);
77 skip = (nwwt.dock || nwwt.desktop || nwwt.splash);
78 if (skip) {
79 DBG("skip - omnipresent window type\n");
80 continue;
81 }
82 Xclimsg(win[i], a_NET_WM_STATE,
83 action ? a_NET_WM_STATE_ADD : a_NET_WM_STATE_REMOVE,
84 a_NET_WM_STATE_SHADED, 0, 0, 0);
85 DBG("ok\n");
86 }
87
88 end:
89 XFree(win);
90 RET();
91 }
92
93
94
95 static void
96 toggle_iconify(wincmd *wc, guint32 action)
97 {
98 Window *win = NULL;
99 int num, i;
100 guint32 tmp2, dno;
101 net_wm_window_type nwwt;
102
103 ENTER;
104 win = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &num);
105 if (!win)
106 RET();
107 if (!num)
108 goto end;
109 //tmp = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, XA_CARDINAL, 0);
110 dno = get_net_current_desktop();
111 DBG("wincmd: #desk=%d\n", dno);
112 //XFree(tmp);
113 for (i = 0; i < num; i++) {
114 int skip;
115
116 tmp2 = get_net_wm_desktop(win[i]);
117 DBG("wincmd: win=0x%x dno=%d...", win[i], tmp2);
118 if ((tmp2 != -1) && (tmp2 != dno)) {
119 DBG("skip - not cur desk\n");
120 continue;
121 }
122 get_net_wm_window_type(win[i], &nwwt);
123 skip = (nwwt.dock || nwwt.desktop || nwwt.splash);
124 if (skip) {
125 DBG("skip - omnipresent window type\n");
126 continue;
127 }
128 if (action)
129 XIconifyWindow(GDK_DISPLAY(), win[i], DefaultScreen(GDK_DISPLAY()));
130 else
131 XMapWindow (GDK_DISPLAY(), win[i]);
132 DBG("ok\n");
133 }
134
135 end:
136 XFree(win);
137 RET();
138 }
139
140 static gint
141 clicked (GtkWidget *widget, GdkEventButton *event, gpointer data)
142 {
143 wincmd *wc = (wincmd *) data;
144
145 ENTER;
146 if (event->type != GDK_BUTTON_PRESS)
147 RET(FALSE);
148
149 if (event->button == 1) {
150 wc->action1 = 1 - wc->action1;
151 toggle_iconify(wc, wc->action1);
152 DBG("wincmd: iconify all\n");
153 } else if (event->button == 2) {
154 wc->action2 = 1 - wc->action2;
155 toggle_shaded(wc, wc->action2);
156 DBG("wincmd: shade all\n");
157 } else {
158 DBG("wincmd: unsupported command\n");
159 }
160
161 RET(FALSE);
162 }
163
164 static void
165 wincmd_destructor(plugin *p)
166 {
167 wincmd *wc = (wincmd *)p->priv;
168
169 ENTER;
170 g_free( wc->image );
171 /* g_object_unref( wc->tips ); */
172 g_free(wc);
173 RET();
174 }
175
176
177
178 static int
179 wincmd_constructor(plugin *p, char **fp)
180 {
181 line s;
182 gchar *fname;
183 wincmd *wc;
184 //GdkPixbuf *gp, *gps;
185 GtkWidget *button;
186 int w, h;
187
188 ENTER;
189 s.len = 256;
190 wc = g_new0(wincmd, 1);
191 g_return_val_if_fail(wc != NULL, 0);
192
193 wc->tips = p->panel->tooltips;
194 /*
195 wc->tips = gtk_tooltips_new();
196 #if GLIB_CHECK_VERSION( 2, 10, 0 )
197 g_object_ref_sink( wc->tips );
198 #else
199 g_object_ref( wc->tips );
200 gtk_object_sink( wc->tips );
201 #endif
202 */
203 p->priv = wc;
204 fname = NULL;
205 if( fp )
206 {
207 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
208 if (s.type == LINE_NONE) {
209 ERR( "wincmd: illegal token %s\n", s.str);
210 goto error;
211 }
212 if (s.type == LINE_VAR) {
213 if (!g_ascii_strcasecmp(s.t[0], "Button1"))
214 wc->button1 = str2num(wincmd_pair, s.t[1], WC_ICONIFY);
215 else if (!g_ascii_strcasecmp(s.t[0], "Button2"))
216 wc->button2 = str2num(wincmd_pair, s.t[1], WC_SHADE);
217 else if (!g_ascii_strcasecmp(s.t[0], "image")) {
218 wc->image = g_strdup( s.t[1] );
219 fname = expand_tilda(s.t[1]);
220 }
221 else {
222 ERR( "wincmd: unknown var %s\n", s.t[0]);
223 goto error;
224 }
225 } else {
226 ERR( "wincmd: illegal in this context %s\n", s.str);
227 goto error;
228 }
229 }
230 }
231 else
232 {
233 wc->button1 = WC_ICONIFY;
234 wc->button2 = WC_SHADE;
235 }
236
237 if( !fname ){
238 fname = g_strdup("gnome-fs-desktop");
239 }
240
241 if (p->panel->orientation == ORIENT_HORIZ) {
242 w = 10000;
243 h = p->panel->ah;
244 } else {
245 w = p->panel->aw;
246 h = 10000;
247 }
248 button = fb_button_new_from_file(fname, w, h, 0x202020, TRUE);
249 gtk_container_set_border_width(GTK_CONTAINER(button), 0);
250 g_signal_connect(G_OBJECT(button), "button_press_event",
251 G_CALLBACK(clicked), (gpointer)wc);
252
253 gtk_widget_show(button);
254
255 g_free(fname);
256 gtk_tooltips_set_tip(GTK_TOOLTIPS (wc->tips), button, _("Left click to iconify all windows. Middle click to shade them"), NULL);
257
258 /* store the created plugin widget in plugin->pwid */
259 p->pwid = button;
260
261 RET(1);
262
263 error:
264 g_free(fname);
265 wincmd_destructor(p);
266 ERR( "%s - exit\n", __FUNCTION__);
267 RET(0);
268 }
269
270 static void save_config( plugin* p, FILE* fp )
271 {
272 wincmd* wc = (wincmd*)p->priv;
273
274 lxpanel_put_str( fp, "image", wc->image );
275 lxpanel_put_str( fp, "Button1", num2str(wincmd_pair, wc->button1, NULL) );
276 lxpanel_put_str( fp, "Button2", num2str(wincmd_pair, wc->button2, NULL) );
277 }
278
279
280 plugin_class wincmd_plugin_class = {
281 fname: NULL,
282 count: 0,
283
284 type : "wincmd",
285 name : N_("Minimize All Windows"),
286 version: "1.0",
287 description : N_("Sends commands to all desktop windows.\nSupported commnds are 1)toggle iconify and 2) toggle shade"),
288
289 constructor : wincmd_constructor,
290 destructor : wincmd_destructor,
291 config : NULL,
292 save : save_config
293 };