Xfce Forum

Sub domains
 

You are not logged in.

#1 2020-06-19 16:35:05

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Can GtkPopover work with the xfce panel plugin?

If there is a button in the xfce panel can it launch a popover?
I could not find a gtk3 panel plugin for xfce that uses popover or popover menus.

Of course, constructing a transparent window with a GtkPopover is possible
but that is too hacky and depends on the compositing.
While compositing is on the gtk window will be transparent.
Here's a small py script with the standalone popover:
https://pastebin.com/sV1hKAtm
85147812-a9d9b880-b24f-11ea-84b5-f5e0977e6579.gif


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#2 2020-06-21 01:22:45

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Can GtkPopover work with the xfce panel plugin?

Given up from popover and used C for a panel plugin.
Here's a small video preview for ToZ.
https://www.youtube.com/watch?v=82bCIkLWsd0

There is a remote-event also, because why not smile

xfce4-panel --plugin-event=desktop-icons-applet-X:popup:bool:false
xfce4-panel --plugin-event=desktop-icons-applet-X:popup:bool:true

https://github.com/Misko-2083/desktop-icons-applet

p.s. Forgot to add the prefix in autogen command.

./autogen.sh --prefix=/usr

This is Gtk3 only and on mx 19 libs for commiling are
libxfce4panel-2.0-dev and libxfconf-0-dev

Last edited by Misko_2083 (2020-06-21 01:25:14)


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#3 2020-06-21 02:06:45

ToZ
Administrator
From: Canada
Registered: 2011-06-02
Posts: 10,948

Re: Can GtkPopover work with the xfce panel plugin?

Very interesting Misko_2083. So you're using a window as opposed to the popover? Too bad GtkPopover doesn't work - it would be an interesting look.

Thanks for sharing.


Please remember to mark your thread [SOLVED] to make it easier for others to find
--- How To Ask For Help | FAQ | Developer Wiki  |  Community | Contribute ---

Offline

#4 2020-06-21 17:24:02

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Can GtkPopover work with the xfce panel plugin?

GtkPopover doesn't have it's own window like menus.
When the window is small there is no space for gtkpopover, and the panels are ussualy small.
Popover would have to be on a transparent window.
Or perhaps on xfdesktop via inter process communication, which is not implemented in xfdesktop.
Something like with jgmenu plugin which sends the location of the xfce button and panel to the jgmenu.

Xfce panel plugin sets env variables
https://github.com/johanmalm/jgmenu/blo … let.c#L207
Jgmenu receives them
https://github.com/johanmalm/jgmenu/blo … ipc.c#L185

And jgmenu opens a X11 window. Jgmenu doesn't even use Gtk or Qt, only cairo and pango.
I do wonder if we could make Jgmenu look like a GtkPopover. big_smile
Just don't know if Johan would want to go in that direction.

Last edited by Misko_2083 (2020-06-21 17:39:22)


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#5 2020-06-27 02:17:54

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Can GtkPopover work with the xfce panel plugin?

Oh, I was wrong it is possible. smile
I've tried it in C and popover is working.
It still needs a full GtkWindow, however without window transparency.
The tricky part were arrows not pointing to the toggle button in the panel, since the button is outside of the window.
Arrows were on the wrong side of the popover and pointing to the wrong direction.

I figured if I It will need a few transparent 1x1 pixel GtkImages arround the window so that the popower can point to them.
Not quite right yet but at least it's pointing in the right direction. :-)
GAaPJx7m.png


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#6 2020-06-27 02:30:55

ToZ
Administrator
From: Canada
Registered: 2011-06-02
Posts: 10,948

Re: Can GtkPopover work with the xfce panel plugin?

Cool. I'll have to find time to review your code.


Please remember to mark your thread [SOLVED] to make it easier for others to find
--- How To Ask For Help | FAQ | Developer Wiki  |  Community | Contribute ---

Offline

#7 2020-06-27 11:41:35

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Can GtkPopover work with the xfce panel plugin?

Thanks.

Andre told me it's hard to position a menu relative next to the panel button.
I can see this going to be harder.
So far I've setup the dummy images (1 pixel - 68 bytes) at the window's top and bottom.
Left and right panel positions are not yet set.

And there are also floating panel positions where it will have to check the relative button position on screen (top, bottom, left and right).
Depending on that popover_set_pointing_to would set correct dummy image.
A small video of the concept.
https://youtu.be/eXZzwDDQlZ8

Of course this is hack and expect this warning: gtkpopup is not a  popover of window.

If you'd like a quick peek here is it,
but first create a 1 pixel transparent png and chage the DUMMY_PNG in desktop-icons-applet.c:

you will need desktop file too

/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

desktop-icons-applet.c
(change the path here to a 1 pixel transparent png)

/*
* 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);

Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#8 2020-06-29 14:52:36

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Can GtkPopover work with the xfce panel plugin?

A different approach without the dummy widgets.
The implementation is horrible but it's sort of there next to button.
https://www.youtube.com/watch?v=A_LbqaOEsy0

https://gist.github.com/Misko-2083/28b4 … cced383dcb

It will not position correctly on theme change.
Noticed that the window size changes when the theme changes.
Maybe there is a way to hadle that.


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#9 2021-04-23 23:29:20

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Can GtkPopover work with the xfce panel plugin?

I've finally managed to sort out the positioning of a GtkPopover next to the panel plugin.
So, this helper function suggests where to place the window.

           xfce_panel_plugin_position_widget (dicons->plugin,
                                              dicons->window,
                                              NULL,
                                              &x,
                                              &y);

And then the rest of the code makes adjustments based on the position of the button on screen, how close is it near the edge of the screen.

Keeping it centered until the popover reaches the border of the screen.
When there is no more room for the popover it will stop. The arrow will continue too follow the button.
But there are a couple of issues I could not sort out.
Clicking the arrow or border makes the popover go blank. - Could not solve this.
There is no shadow, therefore it's impossible to see popover on top of the window with the same background color. - I've resorted in styling the border to mitigate.
There are glitches when changing themes, popover plays well only with the new ones.

And of course, like everything else, gtk_popover_set_pointing_to function is also deprecated in the new Gtk version 3.99.something.
I've also heard that Xfce will be moving to Wayland and merging the panel and the xfdesktop into one app.
Then there will be enough space for the popover to be drawn.

Final verdict: Popover is not meant for this.

At least I can recycle some of the code. The window is there just need to remove the popover and attach it's children to window.
https://gist.github.com/Misko-2083/28b4 … cced383dcb


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

Board footer

Powered by FluxBB