【问题标题】:Is it possible to use GtkPopover while writing a xfce4 panel plugin编写 xfce4 面板插件时是否可以使用 GtkPopover
【发布时间】:2020-02-21 11:37:39
【问题描述】:

我正在尝试为 xfce4 面板编写插件。它应该显示一个带有复杂容器(如 GtkBox)的弹出窗口。

我在 vala 中的代码是:

using Xfce;

public class ButtonPlugin : Xfce.PanelPlugin {
    private Gtk.MenuButton button;
    private Gtk.Popover popover;
    public override void @construct () {

        button = new Gtk.MenuButton();
        popover = new Gtk.Popover(button);

        button.set_image(
            new Gtk.Image.from_icon_name (
                "open-menu-symbolic",
                Gtk.IconSize.LARGE_TOOLBAR
            )
        );
        var menu_container = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
        menu_container.pack_start(new Gtk.Label("Hello World 1"));
        menu_container.pack_start(new Gtk.Label("Hello World 2"));
        menu_container.pack_start(new Gtk.Label("Hello World 3"));
        popover.add(menu_container);
        popover.show_all ();
        popover.hide();
        button.popover = popover;
        add (button);
        //button.show ();

        add_action_widget (button);

        save.connect (() => { message ("save yourself"); });
        free_data.connect (() => { message ("free yourself"); });
        size_changed.connect (() => { message ("panel size changed"); return false; });

        menu_show_about ();
        about.connect (() => {
                Gtk.show_about_dialog (null,
                    "program-name", "Button",
                    "comments", "Test plugin for the Xfce 4.14 Panel",
                    null);
            });
        destroy.connect (() => { Gtk.main_quit (); });
        show_all();
    }
}

[ModuleInit]
public Type xfce_panel_module_init (TypeModule module) {
    return typeof (ButtonPlugin);
}

插件启动,但点击时不显示弹出框。

是否可以使用 Popover 或者我应该切换到另一个小部件?

【问题讨论】:

  • 你为什么要把你的menu_container 打包在一个弹出框里?
  • @AlexanderDmitriev Gtk.Menu 是否支持将Gtk.Box 添加为孩子?
  • @Mubashshir 能否提供一个带有构建脚本的mcve 存储库的链接?
  • @AndreLDM repo with buildscript。

标签: gtk3 vala xfce


【解决方案1】:

据我了解,不,弹出框在 Xfce 面板插件中不起作用。

看看这个要点:https://gist.github.com/andreldm/83c9b99e7aa133c924fb4165acc8427a

独立应用程序正确显示了弹出框,但尝试将窗口设置为与按钮一样小,弹出框没有剩余空间,这与面板插件中的问题相同。如果我没记错的话,上下文菜单可以工作,因为它们是全新的窗口,而弹出窗口不是。

在同一要点中,您可以找到与 xfce4-sample-plugin 的差异,其代码与您正在尝试的代码相似。

【讨论】:

    【解决方案2】:

    Popover 并非设计为作为独立菜单使用。 它没有自己的窗口。 必须有一个窗口,并且必须将弹出窗口附加到小部件。 假设虚拟小部件为 1x1 像素透明图像。 这是 C 中的一个独立(某种)弹出框:

    #include <gtk/gtk.h> 
      
    
    /*   save this file as standalone-popover.c
         create a 1x1 pixel transparent png image in the same folder
         and name it dummy.png
         compile with:
              gcc standalone-popover.c -o standalone-popover  `pkg-config --cflags --libs gtk+-3.0`
    */
    
    #define DUMMY_PNG "dummy.png"
    
    
    void destroy(GtkWidget* widget, gpointer data) 
    { 
        gtk_main_quit(); 
    } 
      
    int main(int argc, char* argv[]) 
    { 
      
        GtkWidget  *window; 
        GtkWidget  *popover;
        GtkWidget  *dummy_png_top_left;
        GtkWidget  *dummy_png_top_center;
        GtkWidget  *dummy_png_top_right;
        GtkWidget  *box;
        GtkWidget  *dummy_box_top;
        GtkWidget  *label;
        GtkWidget  *button;
        gtk_init(&argc, &argv); 
      
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
        gtk_window_set_type_hint (GTK_WINDOW(window),
                                  GDK_WINDOW_TYPE_HINT_POPUP_MENU);
        gtk_widget_set_size_request(window, 250, 220);
        gtk_window_set_resizable (GTK_WINDOW(window), TRUE);
        gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
        gtk_window_stick (GTK_WINDOW (window));
        gtk_window_set_decorated (GTK_WINDOW(window), FALSE);
        gtk_window_set_skip_taskbar_hint (GTK_WINDOW (window), TRUE);
    
        gtk_widget_set_events (window, GDK_FOCUS_CHANGE_MASK);
    
        g_signal_connect(window, "destroy", 
                         G_CALLBACK(destroy), NULL);
        g_signal_connect (G_OBJECT (GTK_WINDOW (window)),
                        "focus-out-event",
                        G_CALLBACK (destroy),
                        NULL);
        gtk_window_present (GTK_WINDOW(window));
        gtk_container_set_border_width(GTK_CONTAINER(window), 20); 
      
    
        dummy_png_top_left   =  gtk_image_new_from_file (DUMMY_PNG);
        dummy_png_top_center =  gtk_image_new_from_file (DUMMY_PNG);
        dummy_png_top_right  =  gtk_image_new_from_file (DUMMY_PNG);
    
        dummy_box_top = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
        gtk_box_set_homogeneous (GTK_BOX (dummy_box_top), TRUE);
        gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_left, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_center, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_top), dummy_png_top_right, TRUE, FALSE, 0);
    
        box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
        gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
    
        gtk_widget_show(dummy_png_top_left);
        gtk_widget_show(dummy_png_top_center);
        gtk_widget_show(dummy_png_top_right);
    
        label = gtk_label_new ("Standalone GtkPopover");
        button = gtk_button_new_with_label("OK");
        gtk_box_pack_start (GTK_BOX(box), dummy_box_top, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX(box), label, TRUE, FALSE, 10);
        gtk_box_pack_start (GTK_BOX(box), button, TRUE, FALSE, 10);
    
        /* here we use the dummy widget to position the popover arrows */
        popover = gtk_popover_new(dummy_png_top_center);
    
        gtk_container_add(GTK_CONTAINER(window), popover); 
        gtk_container_add(GTK_CONTAINER(popover), box); 
        gtk_popover_set_modal(GTK_POPOVER(popover), FALSE);
    
        g_signal_connect(G_OBJECT(button),
                         "clicked",
                         G_CALLBACK(destroy),
                         window);
        gtk_widget_show_all(window);
    
        /* need this to focus a window */
        gtk_window_present_with_time(GTK_WINDOW(window),GDK_CURRENT_TIME);
        gtk_window_activate_focus (GTK_WINDOW (window));
        gtk_widget_grab_focus(GTK_WIDGET(window));
        gtk_main(); 
      
        return 0; 
    }
    

    更复杂的是箭头。 您必须计算将窗口放置在面板插件按钮旁边的位置。 在此之上,您必须正确定位箭头,这看起来并不容易。

    https://www.youtube.com/watch?v=eXZzwDDQlZ8

    可能会在弹出框周围放置 8 个或更多虚拟图像,并根据面板的方向和插件在屏幕上的位置指向它们。

    视频中的代码:

    /*
    * Copyright © 2020 misko_2083
    *
    * Distributed under terms of the GPL2 license.
    * 
    * Compile:
    * gcc -Wall -s -shared -fPIC -g desktop-icons-applet.c -o desktop-icons-applet $(pkg-config --libs --cflags gtk+-3.0 libxfce4panel-2.0 libxfconf-0)
    * move to lib dir (Debian 64bit here):
    * mv libdicons.so /usr/lib/x86_64-linux-gnu/xfce4/panel/plugins/libdicons.so
    */
    
    #include <libxfce4util/libxfce4util.h>
    #include <libxfce4panel/xfce-panel-plugin.h>
    #include <xfconf/xfconf.h>
    
    #define DEFAULT_ICON_NAME "emblem-desktop"
    #define DEFAULT_TOOLTIP_MESSAGE "Show/Hide Desktop Icons"
    #define DEFAULT_TITLE "dicons"
    #define XFCE_PLUGIN_VERSION "0.1"
    
    /* change the path here to a 1 pixel transparent png */
    #define DUMMY_PNG "/home/misko/Desktop/null.png"
    
    typedef struct _DiconsPlugin {
        XfcePanelPlugin *plugin;
        GtkWidget        *button;
        GtkWidget        *icon;
        GtkWidget        *window;
        GtkWidget        *popover;
        GtkWidget        *dummy_png_top_left;
        GtkWidget        *dummy_png_top_center;
        GtkWidget        *dummy_png_top_right;
        GtkWidget        *dummy_png_bottom_left;
        GtkWidget        *dummy_png_bottom_center;
        GtkWidget        *dummy_png_bottom_right;
        gchar            *icon_name;
    } DiconsPlugin;
    
    static void
    button_clicked (GtkWidget *button,
                     DiconsPlugin    *dicons);
    static gboolean
    on_popup_focus_out (GtkWidget *widget,
                        GdkEventFocus *event,
                        gpointer data);
                        
    static gboolean
    on_key_pressed (GtkWidget *widget,
                    GdkEventKey *event,
                    gpointer data);
    
    static const char dicons_plugin_copyright[] =
    "Copyright \xc2\xa9 2020 Miloš Pavlović\n";
    
    static void dicons_about(XfcePanelPlugin *plugin)
    {
        const gchar *auth[] = { "Miloš Pavlović", NULL };
        GdkPixbuf *icon;
    
        icon = xfce_panel_pixbuf_from_source("emblem-desktop", NULL, 32);
        gtk_show_about_dialog(NULL,
                      "logo", icon,
                      "license", xfce_get_license_text(XFCE_LICENSE_TEXT_GPL),
                      "version", XFCE_PLUGIN_VERSION,
                      "program-name", "dicons-applet",
                      "comments", _("Opens a configuration menu for desktop icons"),
                      "website", "https://github.com/Misko-2083",
                      "copyright", _(dicons_plugin_copyright),
                      "authors", auth,
                      NULL);
        if (icon)
            g_object_unref(G_OBJECT(icon));
    }
    
    static void
    _quit_cb (GtkWidget *button, GtkWidget *window, gpointer data)
    {
        (void)data; /* Avoid compiler warnings */
        
        gtk_widget_hide (window);
        
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
        
        return;
    }
    
    static gboolean
    on_popup_focus_out (GtkWidget *widget,
                        GdkEventFocus *event,
                        gpointer data)
    {
      gtk_widget_hide (widget);
      
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), FALSE);
      
      return TRUE;
    }
    
    static gboolean
    on_key_pressed    (GtkWidget *widget,
                       GdkEventKey *event,
                       gpointer data)
    {
        if (event->keyval == GDK_KEY_Escape){
            gtk_widget_hide (widget);
            
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), FALSE);
            
            return TRUE;
        }
        return FALSE;
    }
    
    static gboolean
    on_switch_home       (GtkWidget *widget,
                       gboolean *state,
                       gpointer user_data)
    {
        XfconfChannel    *channel;
    
        xfconf_init(NULL);
        
        channel = xfconf_channel_get("xfce4-desktop");
        
        if (state)
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-home", TRUE);
        else
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-home", FALSE);
            
        xfconf_shutdown();
        
        return FALSE;
    }
    
    static gboolean
    on_switch_trash       (GtkWidget *widget,
                       gboolean *state,
                       gpointer user_data)
    {
        XfconfChannel    *channel;
    
        xfconf_init(NULL);
        
        channel = xfconf_channel_get("xfce4-desktop");
        
        if (state)
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-trash", TRUE);
        else
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-trash", FALSE);
            
        xfconf_shutdown();
            
        return FALSE;
    }
    
    static gboolean
    on_switch_filesystem       (GtkWidget *widget,
                       gboolean *state,
                       gpointer user_data)
    {
        XfconfChannel    *channel;
    
        xfconf_init(NULL);
        
        channel = xfconf_channel_get("xfce4-desktop");
        
        if (state)
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-filesystem", TRUE);
        else
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-filesystem", FALSE);
            
        xfconf_shutdown();
            
        return FALSE;
    }
    
    static gboolean
    on_switch_removable       (GtkWidget *widget,
                       gboolean *state,
                       gpointer user_data)
    {
        XfconfChannel    *channel;
    
        xfconf_init(NULL);
        
        channel = xfconf_channel_get("xfce4-desktop");
        
        if (state)
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-removable", TRUE);
        else
            xfconf_channel_set_bool(channel, "/desktop-icons/file-icons/show-removable", FALSE);
            
        xfconf_shutdown();
            
        return FALSE;
    }
    
    static gboolean dicons_size_changed (XfcePanelPlugin *plugin,
                         gint             size,
                         DiconsPlugin    *dicons)
    {
        XfceScreenPosition position;
    
        position = xfce_panel_plugin_get_screen_position(plugin);
        
        if (xfce_screen_position_is_horizontal(position)) {
            /* horizontal */
            if (xfce_screen_position_is_top(position)) {
                /* top panel position */
                gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
            }
            if (xfce_screen_position_is_bottom(position)) {
                /* bottom */
                gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_bottom_left);
            }
            if (xfce_screen_position_is_floating(position)) {
                /* floating */
                gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
                /* TO DO: check if the button is in the top or bottom side
                 *        of the screen and set the correct dummy widget
                 */
            }
        } else {
            /* vertical */
            if (xfce_screen_position_is_left(position)) {
                /* left */
                gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
            }
            if (xfce_screen_position_is_right(position)) {
                /* right */
                gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_top_left);
            }
            if (xfce_screen_position_is_floating(position)) {
                /* floating */
                gtk_popover_set_relative_to(GTK_POPOVER(dicons->popover), dicons->dummy_png_bottom_left);
                /* TO DO: check if the button is in the left or right side
                 *        of the screen and set the correct dummy widget
                 */
            }
        }
    
        size = size / xfce_panel_plugin_get_nrows(plugin);
        gtk_widget_set_size_request (GTK_WIDGET (plugin), size, size);
        return TRUE;
    }
    
    
    static void button_clicked(GtkWidget *button,
                               DiconsPlugin    *dicons)
    {
        gint  x, y;
    
      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dicons->button)))
      {
           dicons_size_changed(dicons->plugin, xfce_panel_plugin_get_size (dicons->plugin), dicons);
           
           xfce_panel_plugin_block_autohide(dicons->plugin, TRUE);
    
           if (GTK_IS_TOGGLE_BUTTON (button)) {
                 
               xfce_panel_plugin_position_widget(XFCE_PANEL_PLUGIN (dicons->plugin),
                                                 GTK_WIDGET(dicons->window),
                                                 button, &x, &y);
           } else {
               
               GdkDisplay *display = gdk_display_get_default();
               
               GdkSeat *seat = gdk_display_get_default_seat(display);
               
               GdkDevice *device = gdk_seat_get_pointer(seat);
               
               gdk_window_get_device_position(gdk_get_default_root_window(),
                                              device, &x, &y, NULL);
           }
    
           gtk_popover_popup(GTK_POPOVER(dicons->popover));
    
           gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dicons->button), TRUE);
           
           if (!gtk_widget_get_mapped(dicons->window))
               gtk_widget_show_all(GTK_WIDGET(dicons->window));
    
           gtk_window_move (GTK_WINDOW(dicons->window), x, y);
           /* fix me: this function is called twice */
      } else {
          
           _quit_cb(dicons->button, dicons->window, NULL);
           if (GTK_IS_TOGGLE_BUTTON (button))
               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
           
           xfce_panel_plugin_block_autohide(dicons->plugin, FALSE);
           gtk_popover_popdown(GTK_POPOVER(dicons->popover));
    
      }
    }
    
    static DiconsPlugin *dicons_init(XfcePanelPlugin *plugin)
    {
        GtkWidget        *box;
        GtkWidget        *box_a;
        GtkWidget        *box_b;
        GtkWidget        *boxl;
        GtkWidget        *about_button;
        GtkWidget        *cancel_button;
        GtkWidget        *question;
        GtkWidget        *label_home;
        GtkWidget        *label_trash;
        GtkWidget        *label_filesystem;
        GtkWidget        *label_removable;
        GtkWidget        *image;
        GtkWidget        *switch_home;
        GtkWidget        *switch_trash;
        GtkWidget        *switch_filesystem;
        GtkWidget        *switch_removable;
        GdkWindow        *pwindow;
        GtkWidget        *dummy_box_top;
        GtkWidget        *dummy_box_bottom;
        XfconfChannel    *channel;
    
        DiconsPlugin *dicons = g_slice_new0(DiconsPlugin);
    
        dicons->plugin = plugin;
        dicons->icon_name = g_strdup(DEFAULT_ICON_NAME);
        dicons->button = xfce_panel_create_toggle_button();
        xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (dicons->plugin),
                                             dicons->button);
        gtk_init(NULL, NULL);
    
        dicons->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        gtk_window_set_type_hint (GTK_WINDOW(dicons->window),
                                  GDK_WINDOW_TYPE_HINT_POPUP_MENU);
        gtk_widget_set_size_request(dicons->window, 250, 220);
        gtk_window_set_resizable (GTK_WINDOW(dicons->window), TRUE);
        gtk_window_set_keep_above (GTK_WINDOW (dicons->window), TRUE);
        gtk_window_stick (GTK_WINDOW (dicons->window));
        gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dicons->window), TRUE);
        gtk_window_set_title (GTK_WINDOW (dicons->window), "Desktop Icons");
        gtk_widget_set_events (dicons->window, GDK_FOCUS_CHANGE_MASK);
        g_signal_connect (G_OBJECT (GTK_WINDOW (dicons->window)),
                        "focus-out-event",
                        G_CALLBACK (on_popup_focus_out),
                        dicons->button);
        gtk_widget_set_events (GTK_WIDGET(dicons->window), GDK_KEY_PRESS_MASK);
        g_signal_connect (G_OBJECT (GTK_WINDOW (dicons->window)),
                        "key-press-event",
                        G_CALLBACK (on_key_pressed),
                        dicons->button);
        box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
        box_a = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
        box_b = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
        boxl = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
    
        gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
    
        image = gtk_image_new_from_icon_name (dicons->icon_name,
                                              GTK_ICON_SIZE_DND);
        question = gtk_label_new ("\nDesktop Icons");
    
        label_home = gtk_label_new ("Home");
        label_trash = gtk_label_new ("Trash");
        label_filesystem = gtk_label_new ("Filesystem");
        label_removable = gtk_label_new ("Removable");
        switch_home = gtk_switch_new ();
        switch_trash = gtk_switch_new ();
        switch_filesystem = gtk_switch_new ();
        switch_removable = gtk_switch_new ();
        
        
        g_signal_connect (G_OBJECT (switch_home),
                         "state-set",
                          G_CALLBACK (on_switch_home),
                          NULL);
        g_signal_connect (G_OBJECT (switch_trash),
                         "state-set",
                          G_CALLBACK (on_switch_trash),
                          NULL);
        g_signal_connect (G_OBJECT (switch_filesystem),
                         "state-set",
                          G_CALLBACK (on_switch_filesystem),
                          NULL);
        g_signal_connect (G_OBJECT (switch_removable),
                         "state-set",
                          G_CALLBACK (on_switch_removable),
                          NULL);
                          
        xfconf_init(NULL);
        
        channel = xfconf_channel_get("xfce4-desktop");
    
        /*  set initial switches */
        if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-home", TRUE))
            gtk_switch_set_state (GTK_SWITCH(switch_home), TRUE);
        else
            gtk_switch_set_state (GTK_SWITCH(switch_home), FALSE);
            
        if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-trash", TRUE))
            gtk_switch_set_state (GTK_SWITCH(switch_trash), TRUE);
        else
            gtk_switch_set_state (GTK_SWITCH(switch_trash), FALSE);
            
        if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-filesystem", TRUE))
            gtk_switch_set_state (GTK_SWITCH(switch_filesystem), TRUE);
        else
            gtk_switch_set_state (GTK_SWITCH(switch_filesystem), FALSE);
    
        if (xfconf_channel_get_bool(channel, "/desktop-icons/file-icons/show-removable", TRUE))
            gtk_switch_set_state (GTK_SWITCH(switch_removable), TRUE);
        else
            gtk_switch_set_state (GTK_SWITCH(switch_removable), FALSE);
    
        xfconf_shutdown();
        
    
        dicons->dummy_png_top_left = gtk_image_new_from_file (DUMMY_PNG);
        dicons->dummy_png_top_center = gtk_image_new_from_file (DUMMY_PNG);
        dicons->dummy_png_top_right = gtk_image_new_from_file (DUMMY_PNG);
    
        dummy_box_top = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_top), dicons->dummy_png_top_left, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_top), dicons->dummy_png_top_center, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_top), dicons->dummy_png_top_right, TRUE, FALSE, 0);
        
        dicons->dummy_png_bottom_left = gtk_image_new_from_file (DUMMY_PNG);
        dicons->dummy_png_bottom_center = gtk_image_new_from_file (DUMMY_PNG);
        dicons->dummy_png_bottom_right = gtk_image_new_from_file (DUMMY_PNG);
    
        dummy_box_bottom = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_bottom), dicons->dummy_png_bottom_left, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_bottom), dicons->dummy_png_bottom_center, TRUE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX(dummy_box_bottom), dicons->dummy_png_bottom_right, TRUE, FALSE, 0);
    
        gtk_widget_show(dicons->dummy_png_top_left);
        gtk_widget_show(dicons->dummy_png_top_center);
        gtk_widget_show(dicons->dummy_png_top_right);
        gtk_widget_show(dicons->dummy_png_bottom_left);
        gtk_widget_show(dicons->dummy_png_bottom_center);
        gtk_widget_show(dicons->dummy_png_bottom_right);
    
        dicons->popover = gtk_popover_new(dicons->dummy_png_top_left);
        gtk_popover_set_constrain_to(GTK_POPOVER(dicons->popover), GTK_POPOVER_CONSTRAINT_NONE);
    
        /* modal blocks the panel preferences process,
         *  it needs to be set to FALSE */
        gtk_popover_set_modal(GTK_POPOVER(dicons->popover), FALSE);
        
        gtk_container_add(GTK_CONTAINER(dicons->window), dicons->popover);
        gtk_container_add(GTK_CONTAINER(dicons->popover), boxl);
    
    
        gtk_box_pack_start (GTK_BOX(box_a), label_home, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(box_a), switch_home, FALSE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(box_a), label_trash, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(box_a), switch_trash, FALSE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(box_b), label_filesystem, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(box_b), switch_filesystem, FALSE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(box_b), label_removable, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(box_b), switch_removable, FALSE, TRUE, 10);
    
        about_button = gtk_button_new_with_label("About");
        cancel_button = gtk_button_new_with_label("Cancel");
        
        g_signal_connect(G_OBJECT(cancel_button),
                         "clicked",
                         G_CALLBACK(_quit_cb),
                         dicons->window);
        g_signal_connect(G_OBJECT(about_button),
                         "clicked",
                         G_CALLBACK(dicons_about),
                         plugin);
    
        gtk_box_pack_start (GTK_BOX(boxl), dummy_box_top, TRUE, TRUE, 0);
    
        gtk_box_pack_start (GTK_BOX(boxl), image, TRUE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX(boxl), question, TRUE, TRUE, 0);
    
        gtk_box_pack_start (GTK_BOX(boxl), box_a, FALSE, TRUE, 5);
        gtk_box_pack_start (GTK_BOX(boxl), box_b, FALSE, TRUE, 5);
        
        gtk_box_pack_start (GTK_BOX(box), about_button, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX (box), cancel_button, TRUE, TRUE, 10);
        gtk_box_pack_start (GTK_BOX(boxl), box, TRUE, TRUE, 10);
        
        gtk_box_pack_end (GTK_BOX(boxl), dummy_box_bottom, TRUE, TRUE, 0);
        gtk_window_set_decorated (GTK_WINDOW(dicons->window), FALSE);
        gtk_widget_show(dicons->button);
        
        /*gtk_window_set_attached_to(GTK_WINDOW(dicons->window),
                                   dicons->button);*/
        pwindow = gtk_widget_get_parent_window(dicons->button);
        
        gtk_window_set_transient_for(GTK_WINDOW(dicons->window),
                                     GTK_WINDOW(pwindow));
    
        g_signal_connect(G_OBJECT(dicons->button), "toggled",
                 G_CALLBACK(button_clicked), dicons);
        gtk_widget_set_tooltip_text (GTK_WIDGET(dicons->button),
                                     DEFAULT_TOOLTIP_MESSAGE);
        dicons->icon = xfce_panel_image_new_from_source(dicons->icon_name);
        gtk_widget_show(dicons->icon);
        gtk_container_add(GTK_CONTAINER(dicons->button), dicons->icon);
    
        return dicons;
    }
    
    static void dicons_free(XfcePanelPlugin *plugin, DiconsPlugin *dicons)
    {
        gtk_widget_destroy(dicons->button);
        
        gtk_widget_destroy(dicons->icon);
        
        if (GTK_IS_WIDGET (dicons->window))
            gtk_widget_destroy(dicons->window);
    
        if (GTK_IS_WIDGET (dicons->popover))
            gtk_widget_destroy(dicons->popover);
    
        g_slice_free(DiconsPlugin, dicons);
    }
    
    static void set_button_active (GtkToggleButton *button)
    {
         if (GTK_IS_TOGGLE_BUTTON(button)) {
         
             if (!gtk_toggle_button_get_active(button)) {
                  gtk_toggle_button_set_active(button, TRUE);
                 }
             else
                 {
                  gtk_toggle_button_set_active(button, FALSE);
                 }
         }
    }
    
    static gboolean dicons_remote (XfcePanelPlugin *plugin,
                                 gchar           *name,
                                 GValue          *value,
                                 DiconsPlugin    *dicons)
    {
        g_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
        
        if (strcmp (name, "popup") == 0
            && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dicons->button)) 
            &&  gtk_widget_get_visible (GTK_WIDGET (plugin)) )
            {
            if (value != NULL
                && G_VALUE_HOLDS_BOOLEAN (value)
                && g_value_get_boolean (value))
                {
                  set_button_active(GTK_TOGGLE_BUTTON(dicons->button));
                    /* popup here at mouse pointer , where X is an internal id
                     * xfce4-panel --plugin-event=desktop-icons-applet-X:popup:bool:true
                     */
                  button_clicked(NULL, dicons);
                }
            else
                {   
                    set_button_active(GTK_TOGGLE_BUTTON(dicons->button));
                    /* popup here, where X is an internal id
                     * xfce4-panel --plugin-event=desktop-icons-applet-X:popup:bool:false
                     */
                  button_clicked(dicons->button, dicons);
                }
           return TRUE;
    
            }
        return FALSE;
    }
    
    
    static void dicons_construct(XfcePanelPlugin *plugin)
    {
        DiconsPlugin *dicons;
        
        dicons = dicons_init(plugin);
        
        gtk_container_add(GTK_CONTAINER(plugin), dicons->button);
        
        xfce_panel_plugin_add_action_widget(plugin, dicons->button);
        
        xfce_panel_plugin_menu_show_about(plugin);
        
        g_signal_connect (G_OBJECT(plugin),
                         "free-data",
                         G_CALLBACK(dicons_free), dicons);
        g_signal_connect (G_OBJECT(plugin),
                         "size-changed",
                         G_CALLBACK(dicons_size_changed), dicons);
        g_signal_connect (G_OBJECT (plugin),
                         "remote-event",
                         G_CALLBACK(dicons_remote), dicons);
        g_signal_connect (G_OBJECT (plugin),
                         "about",
                        G_CALLBACK (dicons_about), dicons);
    }
    XFCE_PANEL_PLUGIN_REGISTER(dicons_construct);
    

    还有桌面文件 /usr/share/xfce4/panel/plugins/desktop-icons-applet.desktop

    [Xfce Panel]
    Type=X-XFCE-PanelPlugin
    Encoding=UTF-8
    Name=Desktop Icons
    Comment=Show and Hide desktop icons
    Icon=emblem-desktop
    X-XFCE-Module=dicons
    X-XFCE-Internal=true
    X-XFCE-Unique=false
    X-XFCE-API=2.0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多