1 /*
2  * Copyright (C) 2006-2008 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
3  *               2006-2008 Jim Huang <jserv.tw@gmail.com>
4  *               2009-2010 Marty Jack <martyj19@comcast.net>
5  *               2014-2016 Andriy Grytsenko <andrej@rep.kiev.ua>
6  *               2015 Hanno Zulla <hhz@users.sf.net>
7  *
8  * This file is a part of LXPanel project.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 #ifndef __PLUGIN_H__
26 #define __PLUGIN_H__ 1
27 
28 #include <libfm/fm.h>
29 
30 #include "panel.h"
31 #include "conf.h"
32 
33 G_BEGIN_DECLS
34 
35 /* New plugins style which uses FmModule loader, our module type is "lxpanel_gtk" */
36 
37 #define FM_MODULE_lxpanel_gtk_VERSION 1 /* version of this API */
38 
39 /**
40  * LXPanelPluginInit:
41  * @init: (allow-none): callback on lxpanel start
42  * @finalize: (allow-none): callback on lxpanel exit
43  * @name: name to represent plugin in lists
44  * @description: tooltip on the plugin in lists
45  * @new_instance: callback to create new plugin instance in panel
46  * @config: (allow-none): callback to show configuration dialog
47  * @reconfigure: (allow-none): callback to apply panel configuration change
48  * @button_press_event: (allow-none): callback on "button-press-event" signal
49  * @show_system_menu: (allow-none): callback to queue show system menu
50  * @update_context_menu: (allow-none): callback to update context menu
51  * @control: (allow-none): callback to pass messages from lxpanelctl
52  * @gettext_package: (allow-none): additional catalog to read translations
53  *
54  * Callback @init is called on module loading, only once per application
55  * lifetime.
56  *
57  * Callback @new_instance is called when panel tries to add some plugin.
58  * It should initialize instance data, prepare widget, and return the
59  * widget or %NULL if something went wrong. The @panel and @settings data
60  * are guaranteed to be valid until gtk_widget_destroy() is called on the
61  * instance. Instance own data should be attached to the instance using
62  * lxpanel_plugin_set_data().
63  *
64  * Callback @config is called when user tries to configure the instance
65  * (either via context menu or from plugins selection dialog). It should
66  * create dialog window with instance configuration options. Returned
67  * dialog will be destroyed on responce or on instance destroy and any
68  * changed settings will be saved to the panel configuration file. See
69  * also lxpanel_generic_config_dlg().
70  *
71  * Callback @reconfigure is called when panel configuration was changed
72  * in the panel configuration dialog so the instance may change layout of
73  * own subwidgets appropriately to new geometry.
74  *
75  * Callback @button_press_event is a handler for "button-press-event"
76  * signal on the plugin instance. This callback would never receive any
77  * right-clicks without modifier keys because panel itself will handle it
78  * showing context menu. This callback should never return %TRUE for the
79  * button 2 (middle-click) because that will disrupt the plugins movement
80  * feature of panel (drag & drop) for that plugin.
81  *
82  * Callback @show_system_menu is called when lxpanel received a message
83  * by 'lxpanelctl menu' command. It will be sent to each instance if more
84  * than one with this callback available exists.
85  *
86  * Callback @update_context_menu is called when panel context menu being
87  * composed. The @menu contains only item for plugin instance config. The
88  * callback can append or prepend own items to the menu. The callback
89  * should return %TRUE if panel's common menu should be moved into the
90  * submenu 'Panel' (therefore context menu will contain 'Settings' item,
91  * any added ones, and 'Panel') and %FALSE if panel's common menu items
92  * should be in this menu after separator.
93  *
94  * Callback @control is called when command was sent via the lxpanelctl.
95  * The message will be sent to only one instance of plugin. Some messages
96  * are handled by lxpanel: "DEL" will remove plugin from panel, "ADD"
97  * will create new instance if there is no instance yet. Due to design
98  * limitations of XClientMessageEvent the size of plugin type and command
99  * cannot exceed 18 characters in total.
100  *
101  * If @gettext_package is not %NULL then it will be used for translation
102  * of @name and @description. (Since: 0.9.0)
103  */
104 typedef struct {
105     /*< public >*/
106     void (*init)(void);         /* optional startup */
107     void (*finalize)(void);     /* optional finalize */
108     char *name;                 /* name to represent in lists */
109     char *description;          /* tooltip text */
110     GtkWidget *(*new_instance)(LXPanel *panel, config_setting_t *settings);
111     GtkWidget *(*config)(LXPanel *panel, GtkWidget *instance);
112     void (*reconfigure)(LXPanel *panel, GtkWidget *instance);
113     gboolean (*button_press_event)(GtkWidget *widget, GdkEventButton *event, LXPanel *panel);
114     void (*show_system_menu)(GtkWidget *widget);
115     gboolean (*update_context_menu)(GtkWidget *plugin, GtkMenu *menu);
116     gboolean (*control)(GtkWidget *plugin, const char *cmd);
117     char *gettext_package;      /* optional: gettext package used to translate name and description */
118     /*< private >*/
119     gpointer _reserved1;
120     gpointer _reserved2;
121     /*< public >*/
122     int one_per_system : 1;     /* True to disable more than one instance */
123     int expand_available : 1;   /* True if "stretch" option is available */
124     int expand_default : 1;     /* True if "stretch" option is default */
125     int superseded : 1;         /* True if plugin was superseded by another */
126 } LXPanelPluginInit; /* constant data */
127 
128 /*
129  * This descriptor instance should be defined in each plugin code as main
130  * entry point for plugin creation. Primitive plugin example follows:
131  *
132  * #include <lxpanel/plugin.h>
133  *
134  * GtkWidget *test_new_instance(LXPanel *panel, config_setting_t *settings)
135  * {
136  *      return gtk_image_new_from_stock(GTK_STOCK_OK, panel_get_icon_size(panel));
137  * }
138  *
139  * FM_DEFINE_MODULE(lxpanel_gtk, test)
140  *
141  * LXPanelPluginInit fm_module_init_lxpanel_gtk = {
142  *      .name = "Test plugin",
143  *      .description = "An image with OK icon",
144  *      .new_instance = test_new_instance
145  * }
146  */
147 extern LXPanelPluginInit fm_module_init_lxpanel_gtk;
148 
149 extern GQuark lxpanel_plugin_qdata; /* access to plugin private data */
150 /**
151  * lxpanel_plugin_get_data
152  * @_i: instance widget
153  *
154  * Retrieves instance data attached to the widget.
155  *
156  * Returns: (transfer none): pointer to the data.
157  */
158 #define lxpanel_plugin_get_data(_i) g_object_get_qdata(G_OBJECT(_i),lxpanel_plugin_qdata)
159 
160 /**
161  * lxpanel_plugin_set_data
162  * @_i: instance widget
163  * @_data: instance data
164  * @_destructor: (allow-none): destructor for @_data
165  *
166  * Attaches data to the widget instance. The @_destructor callback will
167  * be called on @_data when @_i is destroyed and therefore it should free
168  * any allocated data. The instance widget at that moment is already not
169  * available to use in any way so not rely on it or its children.
170  */
171 #define lxpanel_plugin_set_data(_i,_data,_destructor) g_object_set_qdata_full(G_OBJECT(_i),lxpanel_plugin_qdata,_data,_destructor)
172 
173 /**
174  * lxpanel_register_plugin_type
175  * @name: name of new plugin type
176  * @init: plugin-specific type descriptor
177  *
178  * Register new plugin type. Can be called from plugins init() callback too.
179  *
180  * Returns: %TRUE in case of success.
181  */
182 extern gboolean lxpanel_register_plugin_type(const char *name, const LXPanelPluginInit *init);
183 
184 /**
185  * lxpanel_get_plugin_menu
186  * @panel: panel instance pointer
187  * @plugin: plugin instance pointer
188  * @use_sub_menu: %TRUE if panel management options should be in separated submenu
189  *
190  * Creates context menu for given @panel and @plugin.
191  *
192  * Returns: (transfer full): new menu widget.
193  */
194 extern GtkMenu* lxpanel_get_plugin_menu(LXPanel* panel, GtkWidget* plugin, gboolean use_sub_menu);
195 
196 /**
197  * lxpanel_plugin_adjust_popup_position
198  * @popup: a widget to adjust position
199  * @plugin: a plugin instance
200  *
201  * Adjusts the position of a @popup window to ensure that it is not hidden
202  * by the panel and moves @popup near @plugin if possible.
203  */
204 extern void lxpanel_plugin_adjust_popup_position(GtkWidget * popup, GtkWidget * plugin);
205 
206 /**
207  * lxpanel_plugin_popup_set_position_helper
208  * @p: a panel instance
209  * @near: a widget to position the popup
210  * @popup: a widget to calculate position
211  * @px: (out): pointer to receive X coordinate
212  * @py: (out): pointer to receive Y coordinate
213  *
214  * Calculates desired position of @popup to be placed right to the widget
215  * @near accordingly to position of panel @p and returns its coordinates.
216  * Can be used in position-calculation callback for popup menus.
217  */
218 extern void lxpanel_plugin_popup_set_position_helper(LXPanel * p, GtkWidget * near, GtkWidget * popup, gint * px, gint * py);
219 
220 /**
221  * plugin_widget_set_background
222  * @widget: a widget
223  * @p: a panel instance
224  *
225  * Recursively set the background of @widget and its children. Can be
226  * used on a panel background configuration change.
227  */
228 extern void plugin_widget_set_background(GtkWidget * widget, LXPanel * p);
229 
230 /**
231  * lxpanel_launch_path
232  * @panel: a panel instance
233  * @path: a path to launch
234  *
235  * Launches the @path either itself, or using default application.
236  *
237  * Returns: %TRUE if launch was successful.
238  */
239 extern gboolean lxpanel_launch_path(LXPanel *panel, FmPath *path);
240 
241 /**
242  * lxpanel_plugin_show_config_dialog
243  * @plugin: a plugin instance
244  *
245  * Calls config() callback and shows configuration window.
246  */
247 extern void lxpanel_plugin_show_config_dialog(GtkWidget* plugin);
248 
249 /**
250  * PluginConfType:
251  * @CONF_TYPE_STR: string entry, pointer is char **
252  * @CONF_TYPE_INT: spin entry (range 0...1000), pointer is gint *
253  * @CONF_TYPE_BOOL: check button, pointer is gboolean *
254  * @CONF_TYPE_FILE: file chooser, pointer is char **
255  * @CONF_TYPE_FILE_ENTRY: file path entry, pointer is char **
256  * @CONF_TYPE_DIRECTORY_ENTRY: directory path entry, pointer is char **
257  * @CONF_TYPE_TRIM: just a text in italic, pointer is ignored
258  * @CONF_TYPE_EXTERNAL: (since 0.8) provided by caller, pointer is GtkWidget *
259  *
260  * Type of variable passed to lxpanel_generic_config_dlg().
261  */
262 typedef enum {
263     CONF_TYPE_STR,
264     CONF_TYPE_INT,
265     CONF_TYPE_BOOL,
266     CONF_TYPE_FILE,
267     CONF_TYPE_FILE_ENTRY,
268     CONF_TYPE_DIRECTORY_ENTRY,
269     CONF_TYPE_TRIM,
270     CONF_TYPE_EXTERNAL
271 } PluginConfType;
272 
273 /**
274  * lxpanel_generic_config_dlg
275  * @title: (allow-none): optional title of dialog window
276  * @panel: a panel instance
277  * @apply_func: (allow-none): function to apply changes to the plugin
278  * @plugin: (allow-none): an argument for @apply_func
279  * @name: variable-size list of options to configure, terminated with %NULL
280  *
281  * Creates a generic dialog widget to configure the plugin parameters.
282  * The dialog widget may be used for plugin's callback config() then.
283  * Variable-size list of options consists of three arguments for each
284  * option:
285  *   - const char* name: text representing the option in dialog
286  *   - gpointer ret_value: (in out): pointer to the option value
287  *   - PluginConfType type: type of the option
288  * Note that for type CONF_TYPE_EXTERNAL the name argument is ignored and
289  * therefore empty string ("") have to be passed.
290  *
291  * Returns: (tranfer full): new created dialog widget.
292  */
293 /* Parameters: const char* name, gpointer ret_value, PluginConfType type, ....NULL */
294 extern GtkWidget *lxpanel_generic_config_dlg(const char *title, LXPanel *panel,
295                                              GSourceFunc apply_func,
296                                              GtkWidget *plugin,
297                                              const char *name, ...);
298 
299 /**
300  * panel_config_int_button_new
301  * @name: text representing the option in dialog
302  * @min: minimal spin button value
303  * @max: maximal spin button value
304  * @val: (in out): pointer to the option value
305  *
306  * Widget to use as CONF_TYPE_EXTERNAL instead of CONF_TYPE_INT if plugin
307  * wants to customize range for lxpanel_generic_config_dlg(). The default
308  * widget uses range 0...1000 and here you can set custom range. This API
309  * should be never used outside of lxpanel_generic_config_dlg() arguments
310  * since it uses callbacks specific to that API.
311  *
312  * See also: lxpanel_generic_config_dlg().
313  *
314  * Returns: (transfer full): new widget.
315  *
316  * Since: 0.8.0
317  */
318 extern GtkWidget *panel_config_int_button_new(const char *name, gint *val,
319                                               gint min, gint max);
320 
321 /*
322  * panel_config_hotkey_button_new
323  * @label: text representing the option in dialog
324  * @hotkey: (allow-none): current hotkey
325  *
326  * Creates a #GtkFrame derived widget which can select hotkey binding.
327  * The widget emits "changed" signal when some new combination selected
328  *      gboolean callback(PanelCfgInputButton *, char *, gpointer);
329  * Caller should test if keybinding can be used in the callback and then
330  * return test result as %TRUE or %FALSE.
331  * Widget can be used for lxpanel_generic_config_dlg as CONF_TYPE_EXTERNAL
332  *
333  * Returns: (transfer full): a created widget.
334  *
335  * Since: 0.8.0
336  */
337 extern GtkWidget *panel_config_hotkey_button_new(const char *label, const char *hotkey);
338 extern GtkWidget *panel_config_click_button_new(const char *label, const char *click);
339 
340 /**
341  * lxpanel_apply_hotkey
342  * @hkptr: (in out) (transfer full): pointer to hotkey string
343  * @keystring: (allow-none): new hotkey
344  * @handler: callback to assign to hotkey
345  * @user_data: data to provide for @handler
346  * @show_error: %TRUE to show error window if assignment failed
347  *
348  * Function designed to use in callback on "changed" signal from widget
349  * created by panel_config_hotkey_button_new(). Should be also used on
350  * initial binding and on unbinding when module unloaded (in latter case
351  * @keystring should be %NULL). In case of success returns %TRUE, unbinds
352  * previous hotkey from @hkptr, and updates @hkptr. The @hkptr contains
353  * allocated string.
354  *
355  * Returns: %TRUE on success.
356  *
357  * Since: 0.8.0
358  */
359 extern gboolean lxpanel_apply_hotkey(char **hkptr, const char *keystring,
360                                      void (*handler)(const char *keystring, gpointer user_data),
361                                      gpointer user_data, gboolean show_error);
362 
363 /**
364  * panel_config_click_parse
365  * @keystring: string to parse
366  * @mods: (out): return location for modifier
367  *
368  * Parses click string received in "changed" signal emission of widget
369  * created with panel_config_click_button_new() and returns button and
370  * modifier that can be compared with GdkEventButton data when required.
371  *
372  * Returns: button number or 0 if @keystring is invalid.
373  *
374  * Since: 0.8.0
375  */
376 extern guint panel_config_click_parse(const char *keystring, GdkModifierType *mods);
377 
378 /* Add/remove plugin to/from panel */
379 GtkWidget *lxpanel_add_plugin(LXPanel *p, const char *name, config_setting_t *cfg, gint at);
380 void lxpanel_remove_plugin(LXPanel *p, GtkWidget *plugin);
381 
382 G_END_DECLS
383 
384 #endif /* __PLUGIN_H__ */
385