391ca2499814ebf9898471ecdf020868328ce769
[lxde/lxpanel.git] / src / plugins / wincmd.c
1 #include <stdlib.h>
2
3 #include <gdk-pixbuf/gdk-pixbuf.h>
4
5 #include "panel.h"
6 #include "misc.h"
7 #include "plugin.h"
8 #include "gtkbgbox.h"
9 //#define DEBUG
10 #include "dbg.h"
11
12
13 typedef struct {
14 GdkPixmap *pix;
15 GdkBitmap *mask;
16 GtkTooltips *tips;
17 int button1, button2;
18 int action1, action2;
19 } wincmd;
20
21 enum { WC_NONE, WC_ICONIFY, WC_SHADE };
22 static pair wincmd_pair [] = {
23 { WC_NONE, "none" },
24 { WC_ICONIFY, "iconify" },
25 { WC_SHADE, "shade" },
26 { 0, NULL },
27 };
28
29
30
31 static void
32 toggle_shaded(wincmd *wc, guint32 action)
33 {
34 Window *win = NULL;
35 int num, i;
36 guint32 tmp2, dno;
37 net_wm_window_type nwwt;
38
39 ENTER;
40 win = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &num);
41 if (!win)
42 RET();
43 if (!num)
44 goto end;
45 //tmp = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, XA_CARDINAL, 0);
46 //dno = *tmp;
47 dno = get_net_current_desktop();
48 DBG("wincmd: #desk=%d\n", dno);
49 //XFree(tmp);
50 for (i = 0; i < num; i++) {
51 int skip;
52
53 tmp2 = get_net_wm_desktop(win[i]);
54 DBG("wincmd: win=0x%x dno=%d...", win[i], tmp2);
55 if ((tmp2 != -1) && (tmp2 != dno)) {
56 DBG("skip - not cur desk\n");
57 continue;
58 }
59 get_net_wm_window_type(win[i], &nwwt);
60 skip = (nwwt.dock || nwwt.desktop || nwwt.splash);
61 if (skip) {
62 DBG("skip - omnipresent window type\n");
63 continue;
64 }
65 Xclimsg(win[i], a_NET_WM_STATE,
66 action ? a_NET_WM_STATE_ADD : a_NET_WM_STATE_REMOVE,
67 a_NET_WM_STATE_SHADED, 0, 0, 0);
68 DBG("ok\n");
69 }
70
71 end:
72 XFree(win);
73 RET();
74 }
75
76
77
78 static void
79 toggle_iconify(wincmd *wc, guint32 action)
80 {
81 Window *win = NULL;
82 int num, i;
83 guint32 tmp2, dno;
84 net_wm_window_type nwwt;
85
86 ENTER;
87 win = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &num);
88 if (!win)
89 RET();
90 if (!num)
91 goto end;
92 //tmp = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, XA_CARDINAL, 0);
93 dno = get_net_current_desktop();
94 DBG("wincmd: #desk=%d\n", dno);
95 //XFree(tmp);
96 for (i = 0; i < num; i++) {
97 int skip;
98
99 tmp2 = get_net_wm_desktop(win[i]);
100 DBG("wincmd: win=0x%x dno=%d...", win[i], tmp2);
101 if ((tmp2 != -1) && (tmp2 != dno)) {
102 DBG("skip - not cur desk\n");
103 continue;
104 }
105 get_net_wm_window_type(win[i], &nwwt);
106 skip = (nwwt.dock || nwwt.desktop || nwwt.splash);
107 if (skip) {
108 DBG("skip - omnipresent window type\n");
109 continue;
110 }
111 if (action)
112 XIconifyWindow(GDK_DISPLAY(), win[i], DefaultScreen(GDK_DISPLAY()));
113 else
114 XMapWindow (GDK_DISPLAY(), win[i]);
115 DBG("ok\n");
116 }
117
118 end:
119 XFree(win);
120 RET();
121 }
122
123 static gint
124 clicked (GtkWidget *widget, GdkEventButton *event, gpointer data)
125 {
126 wincmd *wc = (wincmd *) data;
127
128 ENTER;
129 if (event->type != GDK_BUTTON_PRESS)
130 RET(FALSE);
131
132 if (event->button == 1) {
133 wc->action1 = 1 - wc->action1;
134 toggle_iconify(wc, wc->action1);
135 DBG("wincmd: iconify all\n");
136 } else if (event->button == 2) {
137 wc->action2 = 1 - wc->action2;
138 toggle_shaded(wc, wc->action2);
139 DBG("wincmd: shade all\n");
140 } else {
141 DBG("wincmd: unsupported command\n");
142 }
143
144 RET(FALSE);
145 }
146
147 static void
148 wincmd_destructor(plugin *p)
149 {
150 wincmd *wc = (wincmd *)p->priv;
151
152 ENTER;
153 if (wc->mask)
154 g_object_unref(wc->mask);
155 if (wc->pix)
156 g_object_unref(wc->pix);
157 //gtk_widget_destroy(wc->tips);
158 g_free(wc);
159 RET();
160 }
161
162
163
164 static int
165 wincmd_constructor(plugin *p)
166 {
167 line s;
168 gchar *tooltip, *fname;
169 wincmd *wc;
170 //GdkPixbuf *gp, *gps;
171 GtkWidget *button;
172 int w, h;
173
174 ENTER;
175 s.len = 256;
176 wc = g_new0(wincmd, 1);
177 g_return_val_if_fail(wc != NULL, 0);
178 wc->tips = gtk_tooltips_new();
179 p->priv = wc;
180 tooltip = fname = 0;
181 while (get_line(p->fp, &s) != LINE_BLOCK_END) {
182 if (s.type == LINE_NONE) {
183 ERR( "wincmd: illegal token %s\n", s.str);
184 goto error;
185 }
186 if (s.type == LINE_VAR) {
187 if (!g_ascii_strcasecmp(s.t[0], "Button1"))
188 wc->button1 = str2num(wincmd_pair, s.t[1], WC_ICONIFY);
189 else if (!g_ascii_strcasecmp(s.t[0], "Button2"))
190 wc->button2 = str2num(wincmd_pair, s.t[1], WC_SHADE);
191 else if (!g_ascii_strcasecmp(s.t[0], "tooltip"))
192 tooltip = g_strdup(s.t[1]);
193 else if (!g_ascii_strcasecmp(s.t[0], "image"))
194 fname = expand_tilda(s.t[1]);
195 else {
196 ERR( "wincmd: unknown var %s\n", s.t[0]);
197 goto error;
198 }
199 } else {
200 ERR( "wincmd: illegal in this context %s\n", s.str);
201 goto error;
202 }
203 }
204 if (p->panel->orientation == ORIENT_HORIZ) {
205 w = 10000;
206 h = p->panel->ah;
207 } else {
208 w = p->panel->aw;
209 h = 10000;
210 }
211 button = fb_button_new_from_file(fname, w, h, 0x202020, TRUE);
212 gtk_container_set_border_width(GTK_CONTAINER(button), 0);
213 g_signal_connect(G_OBJECT(button), "button_press_event",
214 G_CALLBACK(clicked), (gpointer)wc);
215
216 gtk_widget_show(button);
217 gtk_container_add(GTK_CONTAINER(p->pwid), button);
218 if (p->panel->transparent)
219 gtk_bgbox_set_background(button, BG_ROOT, p->panel->tintcolor, p->panel->alpha);
220
221 g_free(fname);
222 if (tooltip) {
223 gtk_tooltips_set_tip(GTK_TOOLTIPS (wc->tips), button, tooltip, NULL);
224 g_free(tooltip);
225 }
226 RET(1);
227
228 error:
229 g_free(fname);
230 g_free(tooltip);
231 wincmd_destructor(p);
232 ERR( "%s - exit\n", __FUNCTION__);
233 RET(0);
234 }
235
236
237 plugin_class wincmd_plugin_class = {
238 fname: NULL,
239 count: 0,
240
241 type : "wincmd",
242 name : "Window Commander ;-)",
243 version: "1.0",
244 description : "Sends commands to all desktop windows.\nSupported commnds are 1)toggle iconify and 2) toggle shade",
245
246
247 constructor : wincmd_constructor,
248 destructor : wincmd_destructor,
249 };