Misposition of popup when not grouped (Bug2832762)
[lxde/lxpanel.git] / src / plugins / wincmd.c
CommitLineData
239cb032 1/**
a99ee9e1
JH
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
a52c2257
HJYP
19#include <stdlib.h>
20
21#include <gdk-pixbuf/gdk-pixbuf.h>
e7cb732b 22#include <glib/gi18n.h>
a52c2257
HJYP
23
24#include "panel.h"
25#include "misc.h"
26#include "plugin.h"
a52c2257
HJYP
27#include "dbg.h"
28
2918994e 29/* Commands that can be issued. */
30typedef enum {
31 WC_NONE,
32 WC_ICONIFY,
33 WC_SHADE
34} WindowCommand;
35
36/* Private context for window command plugin. */
a52c2257 37typedef struct {
2918994e 38 char * image; /* Main icon */
39 WindowCommand button_1_command; /* Command for mouse button 1 */
40 WindowCommand button_2_command; /* Command for mouse button 2 */
41} WinCmdPlugin;
42
a52c2257 43
a52c2257
HJYP
44static pair wincmd_pair [] = {
45 { WC_NONE, "none" },
46 { WC_ICONIFY, "iconify" },
47 { WC_SHADE, "shade" },
48 { 0, NULL },
49};
50
2918994e 51static void wincmd_execute(WindowCommand command);
52static gboolean wincmd_button_clicked(GtkWidget * widget, GdkEventButton * event, Plugin * plugin);
53static int wincmd_constructor(Plugin * p, char ** fp);
54static void wincmd_destructor(Plugin * p);
55static void wincmd_save_configuration(Plugin * p, FILE * fp);
8f9e6256 56static void wincmd_panel_configuration_changed(Plugin * p);
57
a52c2257 58
2918994e 59/* Execute a window command. */
60static void wincmd_execute(WindowCommand command)
a52c2257 61{
2918994e 62 /* Get the list of all windows. */
63 int client_count;
64 Window * client_list = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST, XA_WINDOW, &client_count);
65 if (client_list != NULL)
66 {
67 /* Loop over all windows. */
68 guint current_desktop = get_net_current_desktop();
69 int i;
70 for (i = 0; i < client_count; i++)
71 {
72 /* Get the desktop and window type properties. */
73 NetWMWindowType nwwt;
74 guint task_desktop = get_net_wm_desktop(client_list[i]);
75 get_net_wm_window_type(client_list[i], &nwwt);
76
77 /* If the task is visible on the current desktop and it is an ordinary window,
78 * execute the requested Iconify or Shade change. */
18ecfe2a 79 if (((task_desktop == -1) || (task_desktop == current_desktop))
2918994e 80 && (( ! nwwt.dock) && ( ! nwwt.desktop) && ( ! nwwt.splash)))
81 {
82 switch (command)
83 {
18ecfe2a 84 case WC_NONE:
85 break;
86
2918994e 87 case WC_ICONIFY:
88 XIconifyWindow(GDK_DISPLAY(), client_list[i], DefaultScreen(GDK_DISPLAY()));
18ecfe2a 89 break;
2918994e 90
91 case WC_SHADE:
92 Xclimsg(client_list[i], a_NET_WM_STATE,
93 a_NET_WM_STATE_ADD,
94 a_NET_WM_STATE_SHADED, 0, 0, 0);
95 break;
96 }
97 }
a52c2257 98 }
2918994e 99 XFree(client_list);
a52c2257 100 }
a52c2257
HJYP
101}
102
2918994e 103/* Handler for "clicked" signal on main widget. */
104static gboolean wincmd_button_clicked(GtkWidget * widget, GdkEventButton * event, Plugin * plugin)
a52c2257 105{
9dd114c4 106 /* Standard right-click handling. */
107 if (plugin_button_press_event(widget, event, plugin))
108 return TRUE;
7414a73f 109
2918994e 110 /* Left-click to iconify. */
111 if (event->button == 1)
112 wincmd_execute(WC_ICONIFY);
a52c2257 113
2918994e 114 /* Middle-click to shade. */
115 else if (event->button == 2)
116 wincmd_execute(WC_SHADE);
a52c2257 117
2918994e 118 return TRUE;
a52c2257
HJYP
119}
120
2918994e 121/* Plugin constructor. */
122static int wincmd_constructor(Plugin * p, char ** fp)
123{
124 /* Allocate plugin context and set into Plugin private data pointer. */
125 WinCmdPlugin * wc = g_new0(WinCmdPlugin, 1);
126 p->priv = wc;
a52c2257 127
2918994e 128 /* Initialize to defaults. */
129 wc->button_1_command = WC_ICONIFY;
130 wc->button_2_command = WC_SHADE;
a52c2257 131
2918994e 132 /* Load parameters from the configuration file. */
a52c2257 133 line s;
a52c2257 134 s.len = 256;
2918994e 135 if(fp != NULL)
db449f6e 136 {
2918994e 137 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
138 {
139 if (s.type == LINE_NONE)
140 {
141 ERR("wincmd: illegal token %s\n", s.str);
142 return 0;
db449f6e 143 }
2918994e 144 if (s.type == LINE_VAR)
145 {
146 if (g_ascii_strcasecmp(s.t[0], "Button1") == 0)
147 wc->button_1_command = str2num(wincmd_pair, s.t[1], WC_ICONIFY);
148 else if (g_ascii_strcasecmp(s.t[0], "Button2") == 0)
149 wc->button_2_command = str2num(wincmd_pair, s.t[1], WC_SHADE);
150 else if (g_ascii_strcasecmp(s.t[0], "image") == 0)
151 wc->image = expand_tilda(g_strdup(s.t[1]));
152 else
153 ERR("wincmd: unknown var %s\n", s.t[0]);
154 }
155 else
156 {
157 ERR("wincmd: illegal in this context %s\n", s.str);
158 return 0;
a52c2257 159 }
a52c2257
HJYP
160 }
161 }
5297da29 162
2918994e 163 /* Default the image if unspecified. */
164 if (wc->image == NULL)
165 wc->image = g_strdup("window-manager");
fcf6205e 166
2918994e 167 /* Allocate top level widget and set into Plugin widget pointer. */
8f9e6256 168 p->pwid = fb_button_new_from_file(wc->image, p->panel->icon_size, p->panel->icon_size, PANEL_ICON_HIGHLIGHT, TRUE);
2918994e 169 gtk_container_set_border_width(GTK_CONTAINER(p->pwid), 0);
170 g_signal_connect(G_OBJECT(p->pwid), "button_press_event", G_CALLBACK(wincmd_button_clicked), (gpointer) p);
171 gtk_widget_set_tooltip_text(p->pwid, _("Left click to iconify all windows. Middle click to shade them."));
4542c20d 172
2918994e 173 /* Show the widget and return. */
174 gtk_widget_show(p->pwid);
9dd114c4 175 return 1;
a52c2257
HJYP
176}
177
2918994e 178/* Plugin destructor. */
179static void wincmd_destructor(Plugin * p)
9c97f69e 180{
8f9e6256 181 WinCmdPlugin * wc = (WinCmdPlugin *) p->priv;
2918994e 182 g_free(wc->image);
183 g_free(wc);
9c97f69e
HJYP
184}
185
2918994e 186/* Save the configuration to the configuration file. */
187static void wincmd_save_configuration(Plugin * p, FILE * fp)
188{
189 WinCmdPlugin * wc = (WinCmdPlugin *) p->priv;
190 lxpanel_put_str(fp, "image", wc->image);
191 lxpanel_put_str(fp, "Button1", num2str(wincmd_pair, wc->button_1_command, NULL));
192 lxpanel_put_str(fp, "Button2", num2str(wincmd_pair, wc->button_2_command, NULL));
193}
a52c2257 194
8f9e6256 195/* Callback when panel configuration changes. */
196static void wincmd_panel_configuration_changed(Plugin * p)
197{
198 WinCmdPlugin * wc = (WinCmdPlugin *) p->priv;
199 fb_button_set_from_file(p->pwid, wc->image, p->panel->icon_size, p->panel->icon_size, TRUE);
200}
201
2918994e 202/* Plugin descriptor. */
22242ed4 203PluginClass wincmd_plugin_class = {
2918994e 204
205 PLUGINCLASS_VERSIONING,
a52c2257
HJYP
206
207 type : "wincmd",
ce522551 208 name : N_("Minimize All Windows"),
a52c2257 209 version: "1.0",
2918994e 210 description : N_("Sends commands to all desktop windows.\nSupported commands are 1) iconify and 2) shade"),
a52c2257
HJYP
211
212 constructor : wincmd_constructor,
213 destructor : wincmd_destructor,
9c97f69e 214 config : NULL,
8f9e6256 215 save : wincmd_save_configuration,
216 panel_configuration_changed : wincmd_panel_configuration_changed
a52c2257 217};