Aylur / ags

A customizable and extensible shell
GNU General Public License v3.0
2.18k stars 112 forks source link

Removing children from FlowBox breaks the widget #583

Closed Przegryw321 closed 3 weeks ago

Przegryw321 commented 3 weeks ago
const WallpaperList = () => Widget.FlowBox({
  className: 'wallpaper-list',

  setup(self) {
    self.set_min_children_per_line(3);
    self.set_max_children_per_line(3);

    FileMonitor.wallpapers?.forEach(({ thumbnail, path }) => {
      self.add(WallpaperButton(thumbnail, path));
    });

    self.hook(FileMonitor, (self: Gtk.FlowBox, wallpapers: WallpaperInfo[] | null) => {
      if (!wallpapers) return;

      self.get_children().forEach((child: any) => {
        // garbage collector gives errors if i don't destroy these manually
        child.child.child.destroy();
        child.child.destroy();

        self.remove(child);
      });

      wallpapers.forEach(({ thumbnail, path }) => {
        self.add(WallpaperButton(thumbnail, path));
      });

    }, 'wallpapers-changed');
  }
});

I want to make it so that every time the wallpaper directory changes, it updates the contents.

The problem is that after clearing them out, the new children don't appear and the widget just shows nothing. Printing out self.get_children() shows all of them correctly.

kotontrion commented 3 weeks ago

in gtk3 widgets are not visible by default. when using set_children on the box, ags will call show_all() on the box, making all of its children visible. So either add a self.show_all() after adding the children, or use the set_children method instead:

self.children = wallpapers.map(({thumbnail, path}) => WallpaperButton(thumbnail, path));

Also a few notes:

so these are equivalent

self.get_children().forEach((child: any) => {
  // garbage collector gives errors if i don't destroy these manually
  child.child.child.destroy();
  child.child.destroy();

  self.remove(child);
});

self.get_children().forEach((child: any) => {
  child.destroy();
});

but as said this is done by ags, when setting the children property.

Przegryw321 commented 3 weeks ago

Calling show_all did fixed both the main problem and these errors:

(com.github.Aylur.ags:5064): Gjs-CRITICAL **: 12:53:17.528: Attempting to call back into JSAPI during the sweeping phase of GC. This is most likely caused by not destroying a Clutter actor or Gtk+ widget with ::destroy signals connected, but can also be caused by using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked and the JS callback not invoked.
The offending signal was destroy on Ags_Icon 0x5fc82e96c6f0.
== Stack trace for context 0x5fc82d9d7a50 ==
#0   5fc82dacbbc8 i   resource:///org/gnome/gjs/modules/core/overrides/GLib.js:263 (18d28e27c600 @ 139)

(com.github.Aylur.ags:5064): Gjs-CRITICAL **: 12:53:17.528: Attempting to call back into JSAPI during the sweeping phase of GC. This is most likely caused by not destroying a Clutter actor or Gtk+ widget with ::destroy signals connected, but can also be caused by using the destroy(), dispose(), or remove() vfuncs. Because it would crash the application, it has been blocked and the JS callback not invoked.
The offending signal was destroy on Ags_Label 0x5fc82e96d170.
== Stack trace for context 0x5fc82d9d7a50 ==
#0   5fc82dacbbc8 i   resource:///org/gnome/gjs/modules/core/overrides/GLib.js:263 (18d28e27c600 @ 139)

Thanks!