You are not logged in.
Pages: 1
I've returned to making a standalone popovers with GTK3 after some time.
This time with Xlib as a window.
I know this is hack but I don't understand why one theme works and the other glitches.
It's best noticed on a random video.
With Orchis gtk theme it works fine.
With Adwaita it's drawing a light show, sometimes it's painted black.
From theme to theme, some work fine some don't.
I just can't figure out why.
If I can only find out what line is causing this I would override it with CSS.
And use it as a panel plugin.
code:
// gcc test.c `pkg-config --cflags --libs gtk+-3.0 gdk-3.0 glib-2.0` -lX11 && ./a.out
#include <X11/Xlib.h>
#include <unistd.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <glib.h>
static void my_gtk_realize(GtkWidget* widget, gpointer data)
{
gtk_widget_set_window(widget, (GdkWindow*)data);
}
static void file_quit(GtkWidget* widget, gpointer data)
{
gboolean* running = (gboolean*)data;
*running = FALSE;
}
int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
XVisualInfo vinfo;
GdkDisplay* gd = gdk_display_get_default();
Display* d = GDK_DISPLAY_XDISPLAY(gd);
cairo_rectangle_int_t rect;
XMatchVisualInfo(d, DefaultScreen(d), 32, TrueColor, &vinfo);
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(d, DefaultRootWindow(d), vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0;
Screen *scr = DefaultScreenOfDisplay(d);
Window w = XCreateWindow(d, RootWindowOfScreen(scr), 0, 0, 300, 300, 0, vinfo.depth,
InputOutput, vinfo.visual, CWColormap | CWBorderPixel | CWBackPixel, &attr);
XSelectInput(d, w, StructureNotifyMask);
GC gc = XCreateGC(d, w, 0, 0);
Atom wm_delete_window = XInternAtom(d, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(d, w, &wm_delete_window, 1);
Atom WM_HINTS;
WM_HINTS = XInternAtom(d, "_MOTIF_WM_HINTS", True);
if ( WM_HINTS != None ) {
#define MWM_DECOR_NONE 0
#define MWM_HINTS_DECORATIONS (1L << 1)
struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} MWMHints = { MWM_HINTS_DECORATIONS, 0,
MWM_DECOR_NONE, 0, 0 };
XChangeProperty(d, w, WM_HINTS, WM_HINTS, 32,
PropModeReplace, (unsigned char *)&MWMHints,
sizeof(MWMHints)/4);
}
XMapRaised(d, w);
GdkWindow* gw = gdk_x11_window_foreign_new_for_display(gd, w);
gdk_window_set_pass_through (gw, TRUE);
gdk_window_set_type_hint (gw, GDK_WINDOW_TYPE_HINT_POPUP_MENU);
GtkWidget* gtk = gtk_widget_new(GTK_TYPE_WINDOW, NULL);
GtkWidget *close_button;
GtkWidget *box;
GtkStyleProvider *style_provider;
g_signal_connect(gtk, "realize", G_CALLBACK(my_gtk_realize), gw);
gtk_widget_set_has_window(gtk, TRUE);
gtk_widget_realize(gtk);
GtkWidget* popover = gtk_popover_new(gtk);
gtk_popover_set_constrain_to(GTK_POPOVER(popover),
GTK_POPOVER_CONSTRAINT_NONE);
rect.x = 5;
rect.y = 500;
rect.height = 35;
rect.width = 35;
gtk_popover_set_pointing_to(GTK_POPOVER(popover), &rect);
gtk_popover_set_position(GTK_POPOVER(popover), GTK_POS_TOP);
gtk_popover_set_modal(GTK_POPOVER(popover), FALSE);
style_provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
gtk_style_context_add_provider (gtk_widget_get_style_context (popover),
style_provider,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
char *css_text;
css_text = g_strdup_printf ("popover.background {\n"
" border: solid 2px;\n"
"}\n");
gtk_css_provider_load_from_data (GTK_CSS_PROVIDER
(style_provider),
css_text, -1, NULL);
g_free (css_text);
box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
close_button = gtk_button_new_with_label("Close");
gtk_widget_set_sensitive (close_button, TRUE);
gtk_box_pack_start (GTK_BOX(box), close_button, TRUE, FALSE, 10);
gtk_container_add(GTK_CONTAINER(popover), box);
gtk_container_add(GTK_CONTAINER(gtk), popover);
gtk_container_set_border_width (GTK_CONTAINER(gtk),
0);
gboolean running = TRUE;
g_signal_connect(G_OBJECT(popover), "closed", G_CALLBACK(file_quit), &running);
g_signal_connect(G_OBJECT(close_button), "clicked", G_CALLBACK(file_quit), &running);
gtk_widget_show_all(gtk);
while (running)
{
Window focus;
int revert_to;
XGetInputFocus(d, &focus, &revert_to);
if (focus != w)
running = FALSE;
while (g_main_context_pending(NULL))
{
g_main_context_iteration(NULL,FALSE);
}
}
XDestroyWindow(d, w);
XCloseDisplay(d);
}
The window closes when it looses focus or on Close button.
MOTIF_WM_HINTS are set to make the Xwindow undecorated.
Next lines in the code above set the arrow position:
rect.x = 5;
rect.y = 500;
rect.height = 35;
rect.width = 35;
gtk_popover_set_pointing_to(GTK_POPOVER(popover), &rect);
gtk_popover_set_position(GTK_POPOVER(popover), GTK_POS_TOP);
GTK_POS_TOP is bottom GTK_POS_LEFT is right, so it's opposite.
Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c
Offline
It's best noticed on a random video.
With Orchis gtk theme it works fine.
https://imgur.com/Fg764Cg.png
With Adwaita it's drawing a light show, sometimes it's painted black.
https://imgur.com/9TIIuAO.png
Did you intend to post a video or some images to show the issue?
BTW, welcome back.
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
Misko_2083 wrote:It's best noticed on a random video.
With Orchis gtk theme it works fine.
https://imgur.com/Fg764Cg.png
With Adwaita it's drawing a light show, sometimes it's painted black.
https://imgur.com/9TIIuAO.pngDid you intend to post a video or some images to show the issue?
BTW, welcome back.
Images, but here is video if it helps: https://youtu.be/B2QT-HmGH5U
xfwm4 --version
This is xfwm4 version 4.16.1 (revision 5f61a84ad) for Xfce 4.16
Released under the terms of the GNU General Public License.
Compiled against GTK+-3.24.24, using GTK+-3.24.24.
Build configuration and supported features:
- Startup notification support: Yes
- XSync support: Yes
- Render support: Yes
- Xrandr support: Yes
- Xpresent support: Yes
- X Input 2 support: No
- Embedded compositor: Yes
- Epoxy support: Yes
- KDE systray proxy (deprecated): No
BTW, welcome back.
Thank you Tony. It's good to be back.
Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c
Offline
I've tested your code on two separate computers. One the first one (long time install), I can see the artifacts - but not with Orchis theme. On the second one (new fresh install), I don't see any artifacts using the built-in adwaita theme (haven't tried any other themes yet).
Can you try with the built in adwaita theme?
xfconf-query -c xsettings -p /Net/ThemeName -s ""
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
I've tested your code on two separate computers. One the first one (long time install), I can see the artifacts - but not with Orchis theme. On the second one (new fresh install), I don't see any artifacts using the built-in adwaita theme (haven't tried any other themes yet).
Can you try with the built in adwaita theme?
xfconf-query -c xsettings -p /Net/ThemeName -s ""
Just tried and it still exists.
----
Finally, I think I got it. Need to tell GTK+ that we want to draw the window's background ourselfs.
https://docs.gtk.org/gtk3/method.Widget … table.html
After this line:
GtkWidget* gtk = gtk_widget_new(GTK_TYPE_WINDOW, NULL);
add next line:
gtk_widget_set_app_paintable(gtk, TRUE);
Now it doesn't appear with Adwaita for me.
Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c
Offline
Interesting. Thanks for sharing the solution - though I don't understand why I wasn't experiencing the issue on my new laptop build.
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
^It happens if it's spawned very fast.
Although this with Xlib works very well I would prefer it with Gtk window.
That way it would work without the compositor. However that creates other issues.
If you wan't to try out here it is.
Create /usr/share/xfce4/panel/plugins/desktop-icons-applet.desktop
with next content:
[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
Save this as desktop-icons-plugin.c
/*
* Copyright © 2022 misko_2083
*
* Distributed under terms of the GPL2 license.
*
* compile
* gcc -Wall -s -shared -fPIC -g desktop-icons-plugin.c -o libdicons.so $(pkg-config --libs --cflags gtk+-3.0 libxfce4util-1.0 libxfce4panel-2.0 libxfconf-0)
* move to libdir (debian 64bit)
* sudo mv libdicons.so $(pkg-config --variable=libdir libxfce4panel-2.0)/xfce4/panel/plugins/libdicons.so
*/
#include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h>
#include <libxfce4panel/libxfce4panel.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.3"
/* prototypes */
static void
dicons_construct (XfcePanelPlugin *plugin);
/* register the plugin */
XFCE_PANEL_PLUGIN_REGISTER (dicons_construct);
typedef struct _DiconsPlugin {
XfcePanelPlugin *plugin;
GtkWidget *ebox;
GtkWidget *hvbox;
GtkWidget *button;
gchar *icon_name;
GtkWidget *icon;
GtkWidget *window;
GtkWidget *popover;
} DiconsPlugin;
struct icon {
char home[42];
char trash[42];
char filesystem[42];
char removable[42];
};
static const struct icon icon = {
.home = "/desktop-icons/file-icons/show-home",
.trash = "/desktop-icons/file-icons/show-trash",
.filesystem = "/desktop-icons/file-icons/show-filesystem",
.removable = "/desktop-icons/file-icons/show-removable"
};
static void
button_clicked_cb (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 *ico;
ico = xfce_panel_pixbuf_from_source("emblem-desktop", NULL, 32);
gtk_show_about_dialog(NULL,
"logo", ico,
"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 (ico)
g_object_unref(G_OBJECT(ico));
}
static void
_quit_cb (GtkWidget *button, GtkWidget *window, gpointer data)
{
gtk_window_close (GTK_WINDOW (window));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
return;
}
static gboolean
on_popup_focus_out (GtkWidget *widget,
GdkEventFocus *event,
gpointer data)
{
DiconsPlugin *dicons = (DiconsPlugin *) data;
gtk_window_close (GTK_WINDOW (dicons->window));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dicons->button), FALSE);
return TRUE;
}
static gboolean
on_key_pressed (GtkWidget *widget,
GdkEventKey *event,
gpointer data)
{
if (event->keyval == GDK_KEY_Escape){
gtk_window_close (GTK_WINDOW (widget));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), FALSE);
return TRUE;
}
return FALSE;
}
static gboolean
on_switch (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, user_data, TRUE);
else
xfconf_channel_set_bool(channel, user_data, FALSE);
xfconf_shutdown();
return FALSE;
}
static gboolean
dicons_size_changed (XfcePanelPlugin *plugin,
gint size,
DiconsPlugin *dicons)
{
gint icon_size;
/* The plugin only occupies a single row */
size /= xfce_panel_plugin_get_nrows(plugin);
#if LIBXFCE4PANEL_CHECK_VERSION (4, 13, 0)
icon_size = xfce_panel_plugin_get_icon_size (plugin);
#else
// fall-back for older panel versions
icon_size = size;
icon_size -= 4;
if (icon_size < 24)
icon_size = 16;
else if (icon_size < 32)
icon_size = 24;
else if (icon_size < 36)
icon_size = 32;
#endif
gtk_widget_set_size_request (GTK_WIDGET (dicons->button), size, icon_size);
return TRUE;
}
static void popover_size_changed (DiconsPlugin *dicons)
{
/*here react to size change*/
g_print("size changed\n");
}
static void button_clicked_cb(GtkWidget *button,
DiconsPlugin *dicons)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dicons->button)))
{
GtkWidget *cancel_button;
GtkStyleProvider *style_provider;
GtkWidget *box;
GtkWidget *box_a;
GtkWidget *box_b;
GtkWidget *boxl;
GtkWidget *scrolled_window;
GtkWidget *about_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;
XfconfChannel *channel;
gint x, y;
gint wx, wy, offset_x, offset_y, win_x, win_y;
XfceScreenPosition position;
cairo_rectangle_int_t rect;
gint width, height;
GdkDisplay *display = gdk_display_get_default();
GdkSeat *seat = gdk_display_get_default_seat(display);
GdkDevice *device = gdk_seat_get_pointer(seat);
gtk_init(NULL, NULL);
dicons->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
dicons->popover = gtk_popover_new(dicons->window);
gtk_window_set_type_hint (GTK_WINDOW(dicons->window),
GDK_WINDOW_TYPE_HINT_POPUP_MENU);
gtk_widget_set_app_paintable (GTK_WIDGET(dicons->window), TRUE); //must be set to true
gtk_widget_set_size_request(dicons->window, 400, 250);
gtk_window_set_resizable (GTK_WINDOW(dicons->window), TRUE);
gtk_window_set_keep_above (GTK_WINDOW (dicons->window), TRUE);
gtk_window_set_decorated (GTK_WINDOW (dicons->window), FALSE);
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), "Xfce Desktop Icons");
gtk_widget_set_events (dicons->window, GDK_FOCUS_CHANGE_MASK);
gtk_widget_set_events (GTK_WIDGET(dicons->window), GDK_KEY_PRESS_MASK);
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_BUTTON);
question = gtk_label_new ("Desktop 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 ();
xfconf_init(NULL);
channel = xfconf_channel_get("xfce4-desktop");
/* set initial switches */
if (xfconf_channel_get_bool(channel, icon.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, icon.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, icon.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, icon.removable, TRUE))
gtk_switch_set_state (GTK_SWITCH(switch_removable), TRUE);
else
gtk_switch_set_state (GTK_SWITCH(switch_removable), FALSE);
xfconf_shutdown();
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);
style_provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
gtk_style_context_add_provider (gtk_widget_get_style_context (dicons->popover),
style_provider,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
char *css_text;
css_text = g_strdup_printf ("popover {\n"
" padding: 0px;\n"
" border: solid 2px;\n"
"}\n");
gtk_css_provider_load_from_data (GTK_CSS_PROVIDER
(style_provider),
css_text, -1, NULL);
g_free (css_text);
gtk_container_add (GTK_CONTAINER (dicons->window), dicons->popover);
gtk_container_set_border_width (GTK_CONTAINER(dicons->window),
0);
gtk_container_set_border_width (GTK_CONTAINER(dicons->popover),
10);
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scrolled_window),
GTK_SHADOW_ETCHED_OUT);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
gtk_widget_set_size_request (scrolled_window, 400, 250);
gtk_container_add (GTK_CONTAINER (scrolled_window), boxl);
gtk_container_add (GTK_CONTAINER (dicons->popover), scrolled_window);
gtk_box_pack_start (GTK_BOX(box_a), label_home, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box_b), switch_home, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box_a), label_trash, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box_b), switch_trash, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box_a), label_filesystem, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box_b), switch_filesystem, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box_a), label_removable, TRUE, FALSE, 10);
gtk_box_pack_start (GTK_BOX(box_b), switch_removable, TRUE, FALSE, 10);
about_button = gtk_button_new_with_label("About");
cancel_button = gtk_button_new_with_label("Cancel");
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, FALSE, 5);
gtk_box_pack_start (GTK_BOX(boxl), box_b, FALSE, FALSE, 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, FALSE, FALSE, 10);
gtk_widget_set_sensitive(scrolled_window, TRUE);
g_signal_connect (G_OBJECT (GTK_WINDOW (dicons->window)),
"focus-out-event",
G_CALLBACK (on_popup_focus_out),
dicons);
g_signal_connect (G_OBJECT (GTK_WINDOW (dicons->window)),
"key-press-event",
G_CALLBACK (on_key_pressed),
dicons->button);
g_signal_connect (G_OBJECT (switch_home),
"state-set",
G_CALLBACK (on_switch),
(void *)icon.home);
g_signal_connect (G_OBJECT (switch_trash),
"state-set",
G_CALLBACK (on_switch),
(void *)icon.trash);
g_signal_connect (G_OBJECT (switch_filesystem),
"state-set",
G_CALLBACK (on_switch),
(void *)icon.filesystem);
g_signal_connect (G_OBJECT (switch_removable),
"state-set",
G_CALLBACK (on_switch),
(void *)icon.removable);
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),
dicons->plugin);
g_signal_connect (G_OBJECT (dicons->popover),
"size-allocate",
G_CALLBACK (popover_size_changed),
dicons);
xfce_panel_plugin_block_autohide(dicons->plugin, TRUE);
gtk_widget_get_allocation(dicons->button, &rect);
if (GTK_IS_TOGGLE_BUTTON (button)) {
gtk_widget_show_all(GTK_WIDGET(dicons->window));
xfce_panel_plugin_position_widget (dicons->plugin,
dicons->window,
NULL,
&x,
&y);
} else {
gdk_window_get_device_position(gdk_get_default_root_window(),
device, &x, &y, NULL);
}
position = xfce_panel_plugin_get_screen_position(dicons->plugin);
offset_x = 0;
offset_y = 0;
gint root_x, root_y, win_width, win_height;
gtk_window_get_size (GTK_WINDOW (dicons->window), &win_width, &win_height);
gtk_widget_realize (dicons->window);
GdkRectangle workarea = {0};
gdk_monitor_get_workarea(
gdk_display_get_primary_monitor(gdk_display_get_default()), &workarea);
gtk_window_get_position (GTK_WINDOW (dicons->window), &win_x, &win_y);
GtkWidget *toplevel = gtk_widget_get_toplevel (dicons->button);
gtk_widget_translate_coordinates (dicons->button, toplevel, 0, 0, &wx, &wy);
if (gtk_widget_is_toplevel (toplevel))
{
gtk_window_get_size(GTK_WINDOW (toplevel), &width, &height);
gtk_window_get_position (GTK_WINDOW (toplevel),
&root_x,
&root_y);
}
if (xfce_screen_position_is_horizontal(position)) {
/* horizontal */
if (win_width/2 > (root_x + wx)){
offset_x = x + 10;
rect.x = wx + 10;
}
else if ((win_width) > (workarea.width - (root_x + wx))) {
offset_x = - 10;
rect.x = (win_width - (workarea.width - (root_x + wx + offset_x)));
if ((workarea.width - (root_x + wx)) > win_width/2) {
offset_x = workarea.width - (root_x + wx) - win_width/2 - rect.width/2;
rect.x = win_width/2 - rect.width/2;
}
}
else {
offset_x = win_width/2 - rect.width/2;
rect.x = win_width/2 - rect.width/2;
}
if (win_y > (root_y + wy)) {
/* top panel position */
gtk_popover_set_position(GTK_POPOVER(dicons->popover), GTK_POS_BOTTOM);
rect.y = 0;
}
if (win_y < (root_y + wy)) {
/* bottom */
gtk_popover_set_position(GTK_POPOVER(dicons->popover), GTK_POS_TOP);
rect.y = win_height + rect.height;
}
} else {
if (win_height/2 > (root_y + wy)){
offset_y = y + 10;
rect.y = wy + 10;
}
else if (win_height > (workarea.height - (root_y + wy))) {
offset_y = - 10;
rect.y = (win_height - (workarea.height - (root_y + wy + offset_y)));
if ((workarea.height - (root_y + wy)) > win_height/2) {
offset_y = workarea.height - (root_y + wy) - win_height/2 - rect.height/2;
rect.y = win_height/2 - rect.height/2;
}
}
else {
offset_y = win_height/2 - rect.height/2;
rect.y = win_height/2 - rect.height/2;
}
/* vertical */
if (win_x < (root_x + wx)) {
/* left */
gtk_popover_set_position(GTK_POPOVER(dicons->popover), GTK_POS_RIGHT);
rect.x = 0;
}
if (win_x < (root_x + wx)) {
/* right */
gtk_popover_set_position(GTK_POPOVER(dicons->popover), GTK_POS_LEFT);
rect.x = win_width + rect.width;
}
}
gtk_window_move (GTK_WINDOW (dicons->window), x - offset_x, y - offset_y);
gtk_popover_set_pointing_to (GTK_POPOVER (dicons->popover), &rect);
gtk_popover_popup (GTK_POPOVER (dicons->popover));
gtk_widget_set_sensitive (cancel_button, TRUE);
gtk_widget_grab_focus (cancel_button);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dicons->button), TRUE);
} else {
_quit_cb(dicons->button, dicons->window, NULL);
if (GTK_IS_TOGGLE_BUTTON (button))
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(dicons->button), FALSE);
xfce_panel_plugin_block_autohide(dicons->plugin, FALSE);
gtk_popover_popdown (GTK_POPOVER (dicons->popover));
}
}
static DiconsPlugin *dicons_init(XfcePanelPlugin *plugin)
{
GtkOrientation orientation;
DiconsPlugin *dicons = g_slice_new0(DiconsPlugin);
dicons->plugin = plugin;
dicons->icon_name = g_strdup(DEFAULT_ICON_NAME);
dicons->ebox = gtk_event_box_new ();
gtk_event_box_set_visible_window (GTK_EVENT_BOX (dicons->ebox), FALSE);
gtk_widget_show (dicons->ebox);
orientation = xfce_panel_plugin_get_orientation (plugin);
dicons->hvbox = gtk_box_new (orientation, 2);
gtk_widget_show (dicons->hvbox);
gtk_container_add (GTK_CONTAINER (dicons->ebox), dicons->hvbox);
dicons->button = xfce_panel_create_toggle_button();
gtk_widget_show (dicons->button);
gtk_box_pack_start (GTK_BOX (dicons->hvbox), dicons->button, FALSE, FALSE, 0);
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);
gtk_widget_set_tooltip_text (GTK_WIDGET(dicons->hvbox),
DEFAULT_TOOLTIP_MESSAGE);
g_signal_connect (G_OBJECT(dicons->button), "toggled",
G_CALLBACK(button_clicked_cb), dicons);
return dicons;
}
static void dicons_free(XfcePanelPlugin *plugin, DiconsPlugin *dicons)
{
gtk_widget_destroy(dicons->button);
gtk_widget_destroy(dicons->icon);
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_cb (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_cb (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->ebox);
xfce_panel_plugin_add_action_widget(plugin, dicons->ebox);
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);
}
Compile with:
gcc -Wall -s -shared -fPIC -g desktop-icons-plugin.c -o libdicons.so $(pkg-config --libs --cflags gtk+-3.0 libxfce4util-1.0 libxfce4panel-2.0 libxfconf-0)
Then move libdicons.so to libdir.
sudo mv libdicons.so $(pkg-config --variable=libdir libxfce4panel-2.0)/xfce4/panel/plugins/libdicons.so
Add "Desktop Icons" to the panel.
It will close if clicked outside (looses focus) or panel button is clicked, or escape key is pressed.
Can launch with this from terminal:
xfce4-panel --plugin-event=desktop-icons-applet-6:popup:bool:false
What I can't figure out is how to close the window if popover's arrow is clicked.
Also if on popover is clicked, that small area between the scrolled window inside the popover and popover's outer border.
Then a black popover is painted.
Edit:
And video: https://www.youtube.com/watch?v=nFLXxA0i1dg
Last edited by Misko_2083 (2022-05-25 13:45:29)
Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c
Offline
Pages: 1
[ Generated in 0.011 seconds, 7 queries executed - Memory usage: 706.88 KiB (Peak: 754.49 KiB) ]