Adding upstream version 0.9.0.
[debian/lxpanel.git] / plugins / deskno / deskno.c
CommitLineData
0688b017 1/*
2ba86315
DB
2 * Desktop number plugin to lxpanel
3 *
0688b017
AG
4 * Copyright (C) 2006 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
5 * 2006 Jim Huang <jserv.tw@gmail.com>
6 * 2009 Marty Jack <martyj19@comcast.net>
7 * 2014 Andriy Grytsenko <andrej@rep.kiev.ua>
7a1c5048 8 * 2016 Charles Lehner <cel10@users.sf.net>
0688b017
AG
9 *
10 * This file is a part of LXPanel project.
2ba86315
DB
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
6cc5e1a6
DB
28// reused dclock.c and variables from pager.c
29// 11/23/04 by cmeury
30
31#include <sys/types.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <glib/gi18n.h>
35
6cc5e1a6 36#include "plugin.h"
6b775dbb
AG
37#include "misc.h"
38#include "ev.h"
6cc5e1a6 39
2ba86315 40/* Private context for desktop number plugin. */
6cc5e1a6 41typedef struct {
6b775dbb
AG
42 LXPanel * panel; /* Back pointer to Panel */
43 config_setting_t *settings;
2ba86315
DB
44 GtkWidget * label; /* The label */
45 int number_of_desktops; /* Number of desktops */
46 char * * desktop_labels; /* Vector of desktop labels */
47 gboolean bold; /* User preference: True if bold font */
48 gboolean wm_labels; /* User preference: True to display window manager labels */
49} DesknoPlugin;
50
6b775dbb 51static void deskno_destructor(gpointer user_data);
2ba86315
DB
52
53/* Handler for current_desktop event from window manager. */
54static gboolean deskno_name_update(GtkWidget * widget, DesknoPlugin * dc)
55{
56 /* Compute and redraw the desktop number. */
57 int desktop_number = get_net_current_desktop();
58 if (desktop_number < dc->number_of_desktops)
6b775dbb 59 lxpanel_draw_label_text(dc->panel, dc->label, dc->desktop_labels[desktop_number], dc->bold, 1, TRUE);
2ba86315
DB
60 return TRUE;
61}
6cc5e1a6 62
2ba86315
DB
63/* Handler for desktop_name and number_of_desktops events from window manager.
64 * Also used on a configuration change to get a full redraw. */
65static void deskno_redraw(GtkWidget * widget, DesknoPlugin * dc)
6cc5e1a6 66{
2ba86315
DB
67 /* Get the NET_DESKTOP_NAMES property. */
68 dc->number_of_desktops = get_net_number_of_desktops();
69 int number_of_desktop_names;
70 char * * desktop_names;
71 desktop_names = get_utf8_property_list(GDK_ROOT_WINDOW(), a_NET_DESKTOP_NAMES, &number_of_desktop_names);
72
73 /* Reallocate the vector of labels. */
74 if (dc->desktop_labels != NULL)
75 g_strfreev(dc->desktop_labels);
76 dc->desktop_labels = g_new0(gchar *, dc->number_of_desktops + 1);
77
78 /* Loop to copy the desktop names to the vector of labels.
79 * If there are more desktops than labels, label the extras with a decimal number. */
80 int i = 0;
81 if (dc->wm_labels)
82 for ( ; ((desktop_names != NULL) && (i < MIN(dc->number_of_desktops, number_of_desktop_names))); i++)
83 dc->desktop_labels[i] = g_strdup(desktop_names[i]);
84 for ( ; i < dc->number_of_desktops; i++)
85 dc->desktop_labels[i] = g_strdup_printf("%d", i + 1);
86
87 /* Free the property. */
88 if (desktop_names != NULL)
89 g_strfreev(desktop_names);
90
91 /* Redraw the label. */
92 deskno_name_update(widget, dc);
93}
94
95/* Handler for button-press-event on top level widget. */
6b775dbb 96static gboolean deskno_button_press_event(GtkWidget * widget, GdkEventButton * event, LXPanel * p)
2ba86315 97{
2ba86315 98 /* Right-click goes to next desktop, wrapping around to first. */
6cc5e1a6
DB
99 int desknum = get_net_current_desktop();
100 int desks = get_net_number_of_desktops();
2ba86315 101 int newdesk = desknum + 1;
7a1c5048 102 Screen *xscreen = GDK_SCREEN_XSCREEN(gtk_widget_get_screen(widget));
2ba86315
DB
103 if (newdesk >= desks)
104 newdesk = 0;
105
106 /* Ask the window manager to make the new desktop current. */
7a1c5048
AG
107 Xclimsgx(xscreen, RootWindowOfScreen(xscreen), a_NET_CURRENT_DESKTOP, newdesk, 0, 0, 0, 0);
108 return TRUE;
109}
110
111/* Handler for scroll events on the plugin */
112static gboolean deskno_scrolled(GtkWidget * p, GdkEventScroll * ev, DesknoPlugin * dc)
113{
114 int desknum = get_net_current_desktop();
115 int desks = get_net_number_of_desktops();
116 Screen *xscreen = GDK_SCREEN_XSCREEN(gtk_widget_get_screen(p));
117
118 switch (ev->direction) {
119 case GDK_SCROLL_DOWN:
120 desknum++;
121 break;
122 case GDK_SCROLL_UP:
123 desknum--;
124 break;
125 default:
126 return FALSE;
127 }
128
129 if (desknum < 0 || desknum >= desks)
130 return TRUE;
131
132 Xclimsgx(xscreen, RootWindowOfScreen(xscreen), a_NET_CURRENT_DESKTOP, desknum, 0, 0, 0, 0);
2ba86315 133 return TRUE;
6cc5e1a6
DB
134}
135
2ba86315 136/* Plugin constructor. */
6b775dbb 137static GtkWidget *deskno_constructor(LXPanel *panel, config_setting_t *settings)
6cc5e1a6 138{
2ba86315
DB
139 /* Allocate plugin context and set into Plugin private data pointer. */
140 DesknoPlugin * dc = g_new0(DesknoPlugin, 1);
6b775dbb
AG
141 GtkWidget *p;
142 int tmp_int;
143
2ba86315 144 g_return_val_if_fail(dc != NULL, 0);
6b775dbb
AG
145 dc->panel = panel;
146 dc->settings = settings;
2ba86315
DB
147
148 /* Default parameters. */
149 dc->wm_labels = TRUE;
150
151 /* Load parameters from the configuration file. */
6b775dbb
AG
152 if (config_setting_lookup_int(settings, "BoldFont", &tmp_int))
153 dc->bold = tmp_int != 0;
154 if (config_setting_lookup_int(settings, "WMLabels", &tmp_int))
155 dc->wm_labels = tmp_int != 0;
2ba86315
DB
156
157 /* Allocate top level widget and set into Plugin widget pointer. */
6b775dbb
AG
158 p = gtk_event_box_new();
159 lxpanel_plugin_set_data(p, dc, deskno_destructor);
2ba86315
DB
160
161 /* Allocate label widget and add to top level. */
162 dc->label = gtk_label_new(NULL);
6b775dbb 163 gtk_container_add(GTK_CONTAINER(p), dc->label);
2ba86315
DB
164
165 /* Connect signals. Note use of window manager event object. */
6b775dbb
AG
166 g_signal_connect(G_OBJECT(fbev), "current-desktop", G_CALLBACK(deskno_name_update), (gpointer) dc);
167 g_signal_connect(G_OBJECT(fbev), "desktop-names", G_CALLBACK(deskno_redraw), (gpointer) dc);
168 g_signal_connect(G_OBJECT(fbev), "number-of-desktops", G_CALLBACK(deskno_redraw), (gpointer) dc);
2ba86315 169
7a1c5048
AG
170 gtk_widget_add_events(p, GDK_SCROLL_MASK);
171 g_signal_connect(G_OBJECT(p), "scroll-event", G_CALLBACK(deskno_scrolled), (gpointer) dc);
172
2ba86315
DB
173 /* Initialize value and show the widget. */
174 deskno_redraw(NULL, dc);
6b775dbb
AG
175 gtk_widget_show_all(p);
176 return p;
6cc5e1a6
DB
177}
178
2ba86315 179/* Plugin destructor. */
6b775dbb 180static void deskno_destructor(gpointer user_data)
6cc5e1a6 181{
6b775dbb 182 DesknoPlugin * dc = (DesknoPlugin *) user_data;
7a1c5048 183 GtkWidget * p = gtk_widget_get_parent(dc->label);
6cc5e1a6 184
2ba86315
DB
185 /* Disconnect signal from window manager event object. */
186 g_signal_handlers_disconnect_by_func(G_OBJECT(fbev), deskno_name_update, dc);
6b775dbb 187 g_signal_handlers_disconnect_by_func(G_OBJECT(fbev), deskno_redraw, dc);
7a1c5048 188 g_signal_handlers_disconnect_by_func(G_OBJECT(p), deskno_scrolled, dc);
6cc5e1a6 189
2ba86315
DB
190 /* Deallocate all memory. */
191 if (dc->desktop_labels != NULL)
192 g_strfreev(dc->desktop_labels);
193 g_free(dc);
194}
6cc5e1a6 195
2ba86315 196/* Callback when the configuration dialog has recorded a configuration change. */
6b775dbb 197static gboolean deskno_apply_configuration(gpointer user_data)
2ba86315 198{
6b775dbb 199 DesknoPlugin * dc = lxpanel_plugin_get_data(user_data);
2ba86315 200 deskno_redraw(NULL, dc);
6b775dbb
AG
201 config_group_set_int(dc->settings, "BoldFont", dc->bold);
202 config_group_set_int(dc->settings, "WMLabels", dc->wm_labels);
203 return FALSE;
6cc5e1a6
DB
204}
205
2ba86315 206/* Callback when the configuration dialog is to be shown. */
6b775dbb 207static GtkWidget *deskno_configure(LXPanel *panel, GtkWidget *p)
2ba86315 208{
6b775dbb
AG
209 DesknoPlugin * dc = lxpanel_plugin_get_data(p);
210 GtkWidget * dlg = lxpanel_generic_config_dlg(_("Desktop Number / Workspace Name"),
211 panel, deskno_apply_configuration, p,
2ba86315
DB
212 _("Bold font"), &dc->bold, CONF_TYPE_BOOL,
213 _("Display desktop names"), &dc->wm_labels, CONF_TYPE_BOOL,
214 NULL);
215 gtk_widget_set_size_request(GTK_WIDGET(dlg), 400, -1); /* Improve geometry */
6b775dbb 216 return dlg;
2ba86315 217}
6cc5e1a6 218
2ba86315 219/* Callback when panel configuration changes. */
6b775dbb 220static void deskno_panel_configuration_changed(LXPanel *panel, GtkWidget *p)
2ba86315 221{
6b775dbb 222 DesknoPlugin * dc = lxpanel_plugin_get_data(p);
2ba86315 223 deskno_name_update(NULL, dc);
6cc5e1a6
DB
224}
225
6b775dbb 226FM_DEFINE_MODULE(lxpanel_gtk, deskno)
2ba86315 227
6b775dbb
AG
228/* Plugin descriptor. */
229LXPanelPluginInit fm_module_init_lxpanel_gtk = {
230 .name = N_("Desktop Number / Workspace Name"),
231 .description = N_("Display workspace number, by cmeury@users.sf.net"),
232
233 .new_instance = deskno_constructor,
234 .config = deskno_configure,
235 .reconfigure = deskno_panel_configuration_changed,
236 .button_press_event = deskno_button_press_event
6cc5e1a6 237};