Package: rox-filer
Version: 2.4-1
Severity: wishlist
Forwarded: 
http://sourceforge.net/tracker/index.php?func=detail&aid=1531890&group_id=7023&atid=307023

Pinboard click commands are useful in situations when enabling the
forward-to-WM option isn't practical due to the WM not doing anything useful
with the information. Here, I'm using it to have right-click open the XFCE
menu via a lightly-hacked xfce4-menu-popup (since I happen to prefer
ROX-Filer over Thunar).

It may be worth tweaking the patch to provide a sensible default command to
launch a standalone popup menu program; if so, rox-filer should at least
recommend that package.

(The patch is tested with rox-filer 2.5.)

-- 
| Darren Salt    | linux or ds at              | nr. Ashington, | Toon
| RISC OS, Linux | youmustbejoking,demon,co,uk | Northumberland | Army
| + Output less CO2 => avoid massive flooding.    TIME IS RUNNING OUT *FAST*.

"There's nothing you can do that can't be done." - John Lennon.
diff -urNad rox-filer-2.5~/ROX-Filer/Options.xml 
rox-filer-2.5/ROX-Filer/Options.xml
--- rox-filer-2.5~/ROX-Filer/Options.xml        2006-07-31 17:19:55.000000000 
+0100
+++ rox-filer-2.5/ROX-Filer/Options.xml 2006-07-31 17:20:16.945598165 +0100
@@ -370,6 +370,11 @@
       <toggle name='blackbox_hack' label='Blackbox root menus hack'>Blackbox, 
Fluxbox and similar window managers do not yet work well with the ROX-Filer 
pinboard. This option enables some workarounds. These window managers are 
expected to change their behaviour in new versions so that this isn't 
necessary.</toggle>
       <toggle name='panel_is_dock' label="Panel is a 'dock'">Disable this 
option if the panel stays above other windows against your wishes. Requires a 
restart to take effect.</toggle>
     </frame>
+    <frame label='Pinboard click commands'>
+      <entry name='pinboard_user_defined_command_0' label='Middle-click on 
pinboard or icon:'>The command to be executed when you middle-click on the 
pinboard or a pinboard icon (no distinction is made).</entry>
+      <entry name='pinboard_user_defined_command_1' label='Right-click on 
pinboard:'>The command to be executed when you right-click on the 
pinboard.</entry>
+      <label help='1'>If a command is present, then the button's normal 
behaviour is overridden.</label>
+    </frame> 
     <frame label='Drag and drop'>
       <toggle name='dnd_no_hostnames' label="Don't use hostnames">Some older 
applications don't support XDND fully and may need to have this option turned 
on. Use this if dragging files to an application shows a + sign on the pointer 
but the drop doesn't work.</toggle>
     </frame>
diff -urNad rox-filer-2.5~/ROX-Filer/src/bind.c 
rox-filer-2.5/ROX-Filer/src/bind.c
--- rox-filer-2.5~/ROX-Filer/src/bind.c 2006-07-31 17:19:55.000000000 +0100
+++ rox-filer-2.5/ROX-Filer/src/bind.c  2006-07-31 17:19:58.285335695 +0100
@@ -63,6 +63,8 @@
        gboolean release = event->type == GDK_BUTTON_RELEASE;
        gboolean select = event->button == 1; /* (old RISC OS names) */
        gboolean adjust = event->button != 1;
+       gboolean pinboard = context == BIND_PINBOARD_ICON ||
+                             context == BIND_PINBOARD;
 
        gboolean dclick = event->type == GDK_2BUTTON_PRESS;
        gboolean dclick_mode =
@@ -70,14 +72,17 @@
                (context == BIND_PINBOARD_ICON && !o_single_pinboard.int_value);
 
        if (b > 3)
-               return ACT_IGNORE;
+               return (pinboard && press) ? ACT_PIN_USER_DEFINED : ACT_IGNORE;
 
-       if (context == BIND_PINBOARD_ICON || context == BIND_PINBOARD)
+       if (pinboard)
                menu_button = 3;        /* Must work with window manager */
 
        if (b == menu_button)
                return press ? ACT_POPUP_MENU : ACT_IGNORE;
 
+       if (b == 2 && pinboard)
+               return press ? ACT_PIN_USER_DEFINED : ACT_IGNORE;
+
        if (item && dclick && dclick_mode)
                return shift ? ACT_EDIT_ITEM : ACT_OPEN_ITEM;
 
diff -urNad rox-filer-2.5~/ROX-Filer/src/bind.h 
rox-filer-2.5/ROX-Filer/src/bind.h
--- rox-filer-2.5~/ROX-Filer/src/bind.h 2006-07-31 17:19:55.000000000 +0100
+++ rox-filer-2.5/ROX-Filer/src/bind.h  2006-07-31 17:19:58.285335695 +0100
@@ -34,6 +34,7 @@
        ACT_LASSO_CLEAR,        /* Clear selection, and start lasso drag */
        ACT_LASSO_MODIFY,       /* Start lasso drag without clearing */
        ACT_RESIZE,             /* Auto-resize the filer window */
+       ACT_PIN_USER_DEFINED,   /* User-defined action on the pinboard */
 } BindAction;
 
 void bind_init(void);
diff -urNad rox-filer-2.5~/ROX-Filer/src/pinboard.c 
rox-filer-2.5/ROX-Filer/src/pinboard.c
--- rox-filer-2.5~/ROX-Filer/src/pinboard.c     2006-07-31 17:19:56.000000000 
+0100
+++ rox-filer-2.5/ROX-Filer/src/pinboard.c      2006-07-31 17:19:58.285335695 
+0100
@@ -151,6 +151,8 @@
 static Option o_top_margin, o_bottom_margin, o_left_margin, o_right_margin;
 static Option o_pinboard_image_scaling;
 
+static Option o_pinboard_user_cmd[2]; /* index == button number - 2 */
+
 /* Static prototypes */
 static GType pin_icon_get_type(void);
 static void set_size_and_style(PinIcon *pi);
@@ -238,6 +240,8 @@
 
 void pinboard_init(void)
 {
+       int i;
+
        option_add_string(&o_pinboard_fg_colour, "pinboard_fg_colour", "#fff");
        option_add_string(&o_pinboard_bg_colour, "pinboard_bg_colour", "#888");
        option_add_string(&o_pinboard_shadow_colour, "pinboard_shadow_colour",
@@ -265,6 +269,13 @@
 
        option_add_int(&o_pinboard_image_scaling, "pinboard_image_scaling", 0);
 
+       for (i = 0; i < G_N_ELEMENTS (o_pinboard_user_cmd); ++i)
+       {
+               char *opt = g_strdup_printf 
("pinboard_user_defined_command_%d", i);
+               option_add_string(&o_pinboard_user_cmd[i], opt, "");
+               /* string not freed, avoiding use-after-free */
+       }
+
        option_add_notify(pinboard_check_options);
 
        gdk_color_parse(o_pinboard_fg_colour.value, &pin_text_fg_col);
@@ -1174,6 +1185,40 @@
                                   &edge, TRUE);
 }
 
+static inline gboolean is_empty (const char *v)
+{
+       while (isspace (*v))
+               ++v;
+       return !*v;
+}
+
+static gboolean spawn_user_command(int button)
+{
+       GError  *error = NULL;
+       gint    argc;
+       gchar   **argv = NULL;
+       char    *msg;
+
+       button -= 2;
+       if (button < 0 || button >= G_N_ELEMENTS (o_pinboard_user_cmd) ||
+           is_empty (o_pinboard_user_cmd[button].value))
+               return FALSE; /* nothing to do */
+
+       if (!g_shell_parse_argv (o_pinboard_user_cmd[button].value,
+                                &argc, &argv, &error))
+       {
+               delayed_error("%s", error ? error->message : "(null)");
+               g_error_free(error);
+       }
+       else
+       {
+               rox_spawn (home_dir, argv);
+               g_strfreev (argv);
+       }
+
+       return TRUE;
+}
+
 static void perform_action(PinIcon *pi, GdkEventButton *event)
 {
        BindAction      action;
@@ -1196,7 +1241,12 @@
                        return;
                case ACT_POPUP_MENU:
                        dnd_motion_ungrab();
-                       pinboard_show_menu(event, pi);
+                       if (pi || !spawn_user_command(event->button))
+                               pinboard_show_menu(event, pi);
+                       return;
+               case ACT_PIN_USER_DEFINED:
+                       dnd_motion_ungrab();
+                       spawn_user_command(event->button);
                        return;
                case ACT_IGNORE:
                        return;
@@ -1275,8 +1325,19 @@
                ButtonPressMask | ButtonReleaseMask, (XEvent *) &xev);
 }
 
-#define FORWARDED_BUTTON(pi, b) ((b) == 2 || \
-       (((b) == 3 || (b) == 1) && o_forward_buttons_13.int_value && !pi))
+static inline gboolean FORWARDED_BUTTON (const PinIcon *pi, int button)
+{
+       switch (button)
+       {
+       case 1:
+       case 3:
+               return o_forward_buttons_13.int_value && !pi;
+       case 2:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
 
 /* pi is NULL if this is a root event */
 static gboolean button_release_event(GtkWidget *widget,
@@ -1284,7 +1345,10 @@
                                     PinIcon *pi)
 {
        if (FORWARDED_BUTTON(pi, event->button))
-               forward_to_root(event);
+       {
+               if (spawn_user_command (event->button))
+                       forward_to_root(event);
+       }
        else if (dnd_motion_release(event))
        {
                if (motion_buttons_pressed == 0 && lasso_in_progress)

Reply via email to