Fixed issues with spacer images, fixed issues with adding images to a
menu entry after adding it to a menu. Removed GTK event dispatch queue, properly fixed out-of-order menu creation. During entry removal, the native peer takes care of cleaning up the native bits.
This commit is contained in:
parent
740348b6c4
commit
e1cca820c3
|
@ -81,7 +81,7 @@ class Entry {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes this menu entry from the menu and releases all system resources associated with this menu entry
|
* Removes this menu entry from the menu and releases all system resources associated with this menu entry.
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
void remove() {
|
void remove() {
|
||||||
|
|
|
@ -408,33 +408,15 @@ class Menu extends MenuItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This removes all menu entries from this menu
|
|
||||||
*/
|
|
||||||
public
|
|
||||||
void clear() {
|
|
||||||
List<Entry> copy;
|
|
||||||
synchronized (menuEntries) {
|
|
||||||
// access on this object must be synchronized for object visibility
|
|
||||||
// a copy is made to prevent deadlocks from occurring when operating in different threads
|
|
||||||
// have to make copy because we are deleting all of them, and sub-menus remove themselves from parents
|
|
||||||
copy = new ArrayList<Entry>(menuEntries);
|
|
||||||
menuEntries.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Entry entry : copy) {
|
|
||||||
entry.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This removes all menu entries from this menu AND this menu from it's parent
|
* This removes all menu entries from this menu AND this menu from it's parent
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void remove() {
|
void remove() {
|
||||||
clear();
|
synchronized (menuEntries) {
|
||||||
|
menuEntries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
super.remove();
|
super.remove();
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,16 +387,4 @@ class MenuItem extends Entry {
|
||||||
String getTooltip() {
|
String getTooltip() {
|
||||||
return this.tooltip;
|
return this.tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
void remove() {
|
|
||||||
if (peer != null) {
|
|
||||||
setImage_(null);
|
|
||||||
setText(null);
|
|
||||||
setCallback(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import dorkbox.systemTray.ui.gtk._AppIndicatorNativeTray;
|
||||||
import dorkbox.systemTray.ui.gtk._GtkStatusIconNativeTray;
|
import dorkbox.systemTray.ui.gtk._GtkStatusIconNativeTray;
|
||||||
import dorkbox.systemTray.ui.swing.SwingUIFactory;
|
import dorkbox.systemTray.ui.swing.SwingUIFactory;
|
||||||
import dorkbox.systemTray.ui.swing._SwingTray;
|
import dorkbox.systemTray.ui.swing._SwingTray;
|
||||||
|
import dorkbox.systemTray.util.EventDispatch;
|
||||||
import dorkbox.systemTray.util.ImageResizeUtil;
|
import dorkbox.systemTray.util.ImageResizeUtil;
|
||||||
import dorkbox.systemTray.util.LinuxSwingUI;
|
import dorkbox.systemTray.util.LinuxSwingUI;
|
||||||
import dorkbox.systemTray.util.SizeAndScalingUtil;
|
import dorkbox.systemTray.util.SizeAndScalingUtil;
|
||||||
|
@ -226,7 +227,7 @@ class SystemTray {
|
||||||
OSUtil.DesktopEnv.Env de = OSUtil.DesktopEnv.get();
|
OSUtil.DesktopEnv.Env de = OSUtil.DesktopEnv.get();
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
logger.debug("Currently using the '{}' desktop environment", de);
|
logger.debug("Currently using the '{}' desktop environment" + OS.LINE_SEPARATOR + OSUtil.Linux.getInfo(), de);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (de) {
|
switch (de) {
|
||||||
|
@ -310,6 +311,19 @@ class SystemTray {
|
||||||
// kde 5.8+ is "high DPI", so we need to adjust the scale. Image resize will do that
|
// kde 5.8+ is "high DPI", so we need to adjust the scale. Image resize will do that
|
||||||
}
|
}
|
||||||
case Unity: {
|
case Unity: {
|
||||||
|
try {
|
||||||
|
String ubuntuVersion = OSUtil.Linux.getUbuntuVersion();
|
||||||
|
String[] split = ubuntuVersion.split(".");
|
||||||
|
int major = Integer.parseInt(split[0]);
|
||||||
|
int minor = Integer.parseInt(split[1]);
|
||||||
|
|
||||||
|
// <=16.04 it is better to use GtkStatusIcons.
|
||||||
|
if (major < 16 || (major == 16 && minor <= 4)) {
|
||||||
|
return selectTypeQuietly(TrayType.GtkStatusIcon);
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
// Ubuntu Unity is a weird combination. It's "Gnome", but it's not "Gnome Shell".
|
// Ubuntu Unity is a weird combination. It's "Gnome", but it's not "Gnome Shell".
|
||||||
return selectTypeQuietly(TrayType.AppIndicator);
|
return selectTypeQuietly(TrayType.AppIndicator);
|
||||||
}
|
}
|
||||||
|
@ -393,6 +407,19 @@ class SystemTray {
|
||||||
logger.error("Error detecting gnome version", e);
|
logger.error("Error detecting gnome version", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OS.isLinux()) {
|
||||||
|
// now just blanket query what we are to guess...
|
||||||
|
if (OSUtil.Linux.isUbuntu()) {
|
||||||
|
return selectTypeQuietly(TrayType.AppIndicator);
|
||||||
|
}
|
||||||
|
else if (OSUtil.Linux.isFedora()) {
|
||||||
|
return selectTypeQuietly(TrayType.AppIndicator);
|
||||||
|
} else {
|
||||||
|
// AppIndicators are now the "default" for most linux distro's.
|
||||||
|
return selectTypeQuietly(TrayType.AppIndicator);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -1025,13 +1052,14 @@ class SystemTray {
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
// this will call "dispatchAndWait()" behind the scenes, so it is thread-safe
|
// this is thread-safe
|
||||||
final Menu menu = systemTrayMenu;
|
final Menu menu = systemTrayMenu;
|
||||||
if (menu != null) {
|
if (menu != null) {
|
||||||
menu.remove();
|
menu.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
systemTrayMenu = null;
|
systemTrayMenu = null;
|
||||||
|
EventDispatch.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,7 +30,7 @@ abstract
|
||||||
class GtkBaseMenuItem implements EntryPeer {
|
class GtkBaseMenuItem implements EntryPeer {
|
||||||
// these are necessary BECAUSE GTK menus look funky as hell when there are some menu entries WITH icons and some WITHOUT
|
// these are necessary BECAUSE GTK menus look funky as hell when there are some menu entries WITH icons and some WITHOUT
|
||||||
private static final File transparentIcon = ImageResizeUtil.getTransparentImage();
|
private static final File transparentIcon = ImageResizeUtil.getTransparentImage();
|
||||||
private volatile boolean hasLegitImage = true;
|
private volatile boolean hasLegitImage = false; // default is to not have an image assigned
|
||||||
|
|
||||||
// these have to be volatile, because they can be changed from any thread
|
// these have to be volatile, because they can be changed from any thread
|
||||||
private volatile Pointer spacerImage;
|
private volatile Pointer spacerImage;
|
||||||
|
@ -51,6 +51,39 @@ class GtkBaseMenuItem implements EntryPeer {
|
||||||
hasLegitImage = isLegit;
|
hasLegitImage = isLegit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* always remove a spacer image.
|
||||||
|
* <p>
|
||||||
|
* called on the DISPATCH thread
|
||||||
|
*/
|
||||||
|
protected
|
||||||
|
void removeSpacerImage() {
|
||||||
|
if (spacerImage != null) {
|
||||||
|
Gtk2.gtk_container_remove(_native, spacerImage); // will automatically get destroyed if no other references to it
|
||||||
|
spacerImage = null;
|
||||||
|
Gtk2.gtk_widget_show_all(_native);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* always add a spacer image.
|
||||||
|
* <p>
|
||||||
|
* called on the DISPATCH thread
|
||||||
|
*/
|
||||||
|
protected
|
||||||
|
void addSpacerImage() {
|
||||||
|
if (spacerImage == null) {
|
||||||
|
spacerImage = Gtk2.gtk_image_new_from_file(transparentIcon.getAbsolutePath());
|
||||||
|
Gtk2.gtk_image_menu_item_set_image(_native, spacerImage);
|
||||||
|
|
||||||
|
// must always re-set always-show after setting the image
|
||||||
|
Gtk2.gtk_image_menu_item_set_always_show_image(_native, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the menu entry looks FUNKY when there are a mis-match of entries WITH and WITHOUT images.
|
* the menu entry looks FUNKY when there are a mis-match of entries WITH and WITHOUT images.
|
||||||
* This is primarily only with AppIndicators, although not always.
|
* This is primarily only with AppIndicators, although not always.
|
||||||
|
@ -64,18 +97,10 @@ class GtkBaseMenuItem implements EntryPeer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spacerImage != null) {
|
removeSpacerImage();
|
||||||
Gtk2.gtk_container_remove(_native, spacerImage); // will automatically get destroyed if no other references to it
|
|
||||||
spacerImage = null;
|
|
||||||
Gtk2.gtk_widget_show_all(_native);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (everyoneElseHasImages) {
|
if (everyoneElseHasImages) {
|
||||||
spacerImage = Gtk2.gtk_image_new_from_file(transparentIcon.getAbsolutePath());
|
addSpacerImage();
|
||||||
Gtk2.gtk_image_menu_item_set_image(_native, spacerImage);
|
|
||||||
|
|
||||||
// must always re-set always-show after setting the image
|
|
||||||
Gtk2.gtk_image_menu_item_set_always_show_image(_native, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Gtk2.gtk_widget_show_all(_native);
|
Gtk2.gtk_widget_show_all(_native);
|
||||||
|
|
|
@ -197,7 +197,7 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void add(final Menu parentMenu, final Entry entry, final int index) {
|
void add(final Menu parentMenu, final Entry entry, final int index) {
|
||||||
// must always be called on the GTK dispatch. This must be dispatchAndWait
|
// must always be called on the GTK dispatch. This must be dispatchAndWait() so it will properly executed immediately
|
||||||
GtkEventDispatch.dispatchAndWait(new Runnable() {
|
GtkEventDispatch.dispatchAndWait(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
|
@ -206,35 +206,50 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
// To work around this issue, we destroy then recreate the menu every time something is changed.
|
||||||
deleteMenu();
|
deleteMenu();
|
||||||
|
|
||||||
|
GtkBaseMenuItem item = null;
|
||||||
|
|
||||||
if (entry instanceof Menu) {
|
if (entry instanceof Menu) {
|
||||||
// some implementations of appindicator, do NOT like having a menu added, which has no menu items yet.
|
// some implementations of appindicator, do NOT like having a menu added, which has no menu items yet.
|
||||||
// see: https://bugs.launchpad.net/glipper/+bug/1203888
|
// see: https://bugs.launchpad.net/glipper/+bug/1203888
|
||||||
GtkMenu item = new GtkMenu(GtkMenu.this);
|
item = new GtkMenu(GtkMenu.this);
|
||||||
menuEntries.add(index, item);
|
menuEntries.add(index, item);
|
||||||
((Menu) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
|
||||||
}
|
}
|
||||||
else if (entry instanceof Separator) {
|
else if (entry instanceof Separator) {
|
||||||
GtkMenuItemSeparator item = new GtkMenuItemSeparator(GtkMenu.this);
|
item = new GtkMenuItemSeparator(GtkMenu.this);
|
||||||
menuEntries.add(index, item);
|
menuEntries.add(index, item);
|
||||||
entry.bind(item, parentMenu, parentMenu.getSystemTray());
|
|
||||||
}
|
}
|
||||||
else if (entry instanceof Checkbox) {
|
else if (entry instanceof Checkbox) {
|
||||||
GtkMenuItemCheckbox item = new GtkMenuItemCheckbox(GtkMenu.this);
|
item = new GtkMenuItemCheckbox(GtkMenu.this);
|
||||||
menuEntries.add(index, item);
|
menuEntries.add(index, item);
|
||||||
((Checkbox) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
|
||||||
}
|
}
|
||||||
else if (entry instanceof Status) {
|
else if (entry instanceof Status) {
|
||||||
GtkMenuItemStatus item = new GtkMenuItemStatus(GtkMenu.this);
|
item = new GtkMenuItemStatus(GtkMenu.this);
|
||||||
menuEntries.add(index, item);
|
menuEntries.add(index, item);
|
||||||
((Status) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
|
||||||
}
|
}
|
||||||
else if (entry instanceof MenuItem) {
|
else if (entry instanceof MenuItem) {
|
||||||
GtkMenuItem item = new GtkMenuItem(GtkMenu.this);
|
item = new GtkMenuItem(GtkMenu.this);
|
||||||
menuEntries.add(index, item);
|
menuEntries.add(index, item);
|
||||||
((MenuItem) entry).bind(item, parentMenu, parentMenu.getSystemTray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createMenu();
|
createMenu();
|
||||||
|
|
||||||
|
// we must create the menu BEFORE binding the menu, otherwise the menus' children's GTK element can be added before
|
||||||
|
// their parent GTK elements are added (and the menu won't show up)
|
||||||
|
if (entry instanceof Menu) {
|
||||||
|
((Menu) entry).bind((GtkMenu) item, parentMenu, parentMenu.getSystemTray());
|
||||||
|
}
|
||||||
|
else if (entry instanceof Separator) {
|
||||||
|
((Separator)entry).bind((GtkMenuItemSeparator) item, parentMenu, parentMenu.getSystemTray());
|
||||||
|
}
|
||||||
|
else if (entry instanceof Checkbox) {
|
||||||
|
((Checkbox) entry).bind((GtkMenuItemCheckbox) item, parentMenu, parentMenu.getSystemTray());
|
||||||
|
}
|
||||||
|
else if (entry instanceof Status) {
|
||||||
|
((Status) entry).bind((GtkMenuItemStatus) item, parentMenu, parentMenu.getSystemTray());
|
||||||
|
}
|
||||||
|
else if (entry instanceof MenuItem) {
|
||||||
|
((MenuItem) entry).bind((GtkMenuItem) item, parentMenu, parentMenu.getSystemTray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -252,7 +267,7 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
// is overridden by system tray
|
// is overridden by system tray
|
||||||
setLegitImage(menuItem.getImage() != null);
|
setLegitImage(menuItem.getImage() != null);
|
||||||
|
|
||||||
Runnable runnable = new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
|
@ -263,8 +278,7 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menuItem.getImage() != null) {
|
if (menuItem.getImage() != null) {
|
||||||
image = Gtk2.gtk_image_new_from_file(menuItem.getImage()
|
image = Gtk2.gtk_image_new_from_file(menuItem.getImage().getAbsolutePath());
|
||||||
.getAbsolutePath());
|
|
||||||
Gtk2.gtk_image_menu_item_set_image(_native, image);
|
Gtk2.gtk_image_menu_item_set_image(_native, image);
|
||||||
|
|
||||||
// must always re-set always-show after setting the image
|
// must always re-set always-show after setting the image
|
||||||
|
@ -273,14 +287,7 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
|
|
||||||
Gtk2.gtk_widget_show_all(_native);
|
Gtk2.gtk_widget_show_all(_native);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
if (GtkEventDispatch.isDispatch.get()) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GtkEventDispatch.dispatch(runnable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// is overridden in tray impl
|
// is overridden in tray impl
|
||||||
|
@ -385,7 +392,7 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void remove() {
|
void remove() {
|
||||||
Runnable runnable = new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
|
@ -408,13 +415,6 @@ class GtkMenu extends GtkBaseMenuItem implements MenuPeer {
|
||||||
parent.createMenu(); // must be on EDT
|
parent.createMenu(); // must be on EDT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
if (GtkEventDispatch.isDispatch.get()) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GtkEventDispatch.dispatch(runnable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void setImage(final MenuItem menuItem) {
|
void setImage(final MenuItem menuItem) {
|
||||||
|
final boolean hadImage = hasImage();
|
||||||
setLegitImage(menuItem.getImage() != null);
|
setLegitImage(menuItem.getImage() != null);
|
||||||
|
|
||||||
GtkEventDispatch.dispatch(new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
|
@ -86,6 +87,9 @@ class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (menuItem.getImage() != null) {
|
if (menuItem.getImage() != null) {
|
||||||
|
// always remove the spacer image in case it's there. The spacer image will correctly added when the menu is created.
|
||||||
|
removeSpacerImage();
|
||||||
|
|
||||||
image = Gtk2.gtk_image_new_from_file(menuItem.getImage()
|
image = Gtk2.gtk_image_new_from_file(menuItem.getImage()
|
||||||
.getAbsolutePath());
|
.getAbsolutePath());
|
||||||
Gtk2.gtk_image_menu_item_set_image(_native, image);
|
Gtk2.gtk_image_menu_item_set_image(_native, image);
|
||||||
|
@ -93,6 +97,11 @@ class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback {
|
||||||
// must always re-set always-show after setting the image
|
// must always re-set always-show after setting the image
|
||||||
Gtk2.gtk_image_menu_item_set_always_show_image(_native, true);
|
Gtk2.gtk_image_menu_item_set_always_show_image(_native, true);
|
||||||
}
|
}
|
||||||
|
else if (hadImage) {
|
||||||
|
// if at one point, we had an image, we should set the spacer image back, so that menu spacing looks correct.
|
||||||
|
// since we USED to have an image, it is safe to assume that we should have a spacer image.
|
||||||
|
addSpacerImage();
|
||||||
|
}
|
||||||
|
|
||||||
Gtk2.gtk_widget_show_all(_native);
|
Gtk2.gtk_widget_show_all(_native);
|
||||||
}
|
}
|
||||||
|
@ -205,14 +214,16 @@ class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void remove() {
|
void remove() {
|
||||||
Runnable runnable = new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
Gtk2.gtk_container_remove(parent._nativeMenu, _native); // will automatically get destroyed if no other references to it
|
|
||||||
|
|
||||||
GtkMenuItem.super.remove();
|
GtkMenuItem.super.remove();
|
||||||
|
|
||||||
|
callback = null;
|
||||||
|
|
||||||
|
Gtk2.gtk_container_remove(parent._nativeMenu, _native); // will automatically get destroyed if no other references to it
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
Gtk2.gtk_container_remove(_native, image); // will automatically get destroyed if no other references to it
|
Gtk2.gtk_container_remove(_native, image); // will automatically get destroyed if no other references to it
|
||||||
image = null;
|
image = null;
|
||||||
|
@ -220,13 +231,6 @@ class GtkMenuItem extends GtkBaseMenuItem implements MenuItemPeer, GCallback {
|
||||||
|
|
||||||
parent.remove(GtkMenuItem.this);
|
parent.remove(GtkMenuItem.this);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
if (GtkEventDispatch.isDispatch.get()) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GtkEventDispatch.dispatch(runnable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -297,14 +297,16 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void remove() {
|
void remove() {
|
||||||
Runnable runnable = new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
Gtk2.gtk_container_remove(parent._nativeMenu, _native); // will automatically get destroyed if no other references to it
|
|
||||||
|
|
||||||
GtkMenuItemCheckbox.super.remove();
|
GtkMenuItemCheckbox.super.remove();
|
||||||
|
|
||||||
|
callback = null;
|
||||||
|
|
||||||
|
Gtk2.gtk_container_remove(parent._nativeMenu, _native); // will automatically get destroyed if no other references to it
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
Gtk2.gtk_container_remove(_native, image); // will automatically get destroyed if no other references to it
|
Gtk2.gtk_container_remove(_native, image); // will automatically get destroyed if no other references to it
|
||||||
image = null;
|
image = null;
|
||||||
|
@ -312,13 +314,6 @@ class GtkMenuItemCheckbox extends GtkBaseMenuItem implements CheckboxPeer, GCall
|
||||||
|
|
||||||
parent.remove(GtkMenuItemCheckbox.this);
|
parent.remove(GtkMenuItemCheckbox.this);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
if (GtkEventDispatch.isDispatch.get()) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GtkEventDispatch.dispatch(runnable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ package dorkbox.systemTray.ui.gtk;
|
||||||
|
|
||||||
import static dorkbox.util.jna.linux.Gtk.Gtk2;
|
import static dorkbox.util.jna.linux.Gtk.Gtk2;
|
||||||
|
|
||||||
import dorkbox.systemTray.peer.EntryPeer;
|
import dorkbox.systemTray.peer.SeparatorPeer;
|
||||||
import dorkbox.util.jna.linux.GtkEventDispatch;
|
import dorkbox.util.jna.linux.GtkEventDispatch;
|
||||||
|
|
||||||
class GtkMenuItemSeparator extends GtkBaseMenuItem implements EntryPeer {
|
class GtkMenuItemSeparator extends GtkBaseMenuItem implements SeparatorPeer {
|
||||||
|
|
||||||
private final GtkMenu parent;
|
private final GtkMenu parent;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class GtkMenuItemSeparator extends GtkBaseMenuItem implements EntryPeer {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void remove() {
|
void remove() {
|
||||||
Runnable runnable = new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
|
@ -45,14 +45,7 @@ class GtkMenuItemSeparator extends GtkBaseMenuItem implements EntryPeer {
|
||||||
|
|
||||||
parent.remove(GtkMenuItemSeparator.this);
|
parent.remove(GtkMenuItemSeparator.this);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
if (GtkEventDispatch.isDispatch.get()) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GtkEventDispatch.dispatch(runnable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -61,23 +61,16 @@ class GtkMenuItemStatus extends GtkBaseMenuItem implements StatusPeer {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void remove() {
|
void remove() {
|
||||||
Runnable runnable = new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
Gtk2.gtk_container_remove(parent._nativeMenu, _native); // will automatically get destroyed if no other references to it
|
|
||||||
|
|
||||||
GtkMenuItemStatus.super.remove();
|
GtkMenuItemStatus.super.remove();
|
||||||
|
|
||||||
|
Gtk2.gtk_container_remove(parent._nativeMenu, _native); // will automatically get destroyed if no other references to it
|
||||||
|
|
||||||
parent.remove(GtkMenuItemStatus.this);
|
parent.remove(GtkMenuItemStatus.this);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
if (GtkEventDispatch.isDispatch.get()) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GtkEventDispatch.dispatch(runnable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,25 +197,24 @@ class _AppIndicatorNativeTray extends Tray {
|
||||||
void remove() {
|
void remove() {
|
||||||
// This is required if we have JavaFX or SWT shutdown hooks (to prevent us from shutting down twice...)
|
// This is required if we have JavaFX or SWT shutdown hooks (to prevent us from shutting down twice...)
|
||||||
if (!shuttingDown.getAndSet(true)) {
|
if (!shuttingDown.getAndSet(true)) {
|
||||||
// must happen asap, so our hook properly notices we are in shutdown mode
|
super.remove();
|
||||||
final AppIndicatorInstanceStruct savedAppIndicator = appIndicator;
|
|
||||||
appIndicator = null;
|
|
||||||
|
|
||||||
GtkEventDispatch.dispatch(new Runnable() {
|
GtkEventDispatch.dispatch(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void run() {
|
void run() {
|
||||||
|
// must happen asap, so our hook properly notices we are in shutdown mode
|
||||||
|
final AppIndicatorInstanceStruct savedAppIndicator = appIndicator;
|
||||||
|
appIndicator = null;
|
||||||
|
|
||||||
// STATUS_PASSIVE hides the indicator
|
// STATUS_PASSIVE hides the indicator
|
||||||
AppIndicator.app_indicator_set_status(savedAppIndicator, AppIndicator.STATUS_PASSIVE);
|
AppIndicator.app_indicator_set_status(savedAppIndicator, AppIndicator.STATUS_PASSIVE);
|
||||||
Pointer p = savedAppIndicator.getPointer();
|
Pointer p = savedAppIndicator.getPointer();
|
||||||
Gobject.g_object_unref(p);
|
Gobject.g_object_unref(p);
|
||||||
|
|
||||||
|
GtkEventDispatch.shutdownGui();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
super.remove();
|
|
||||||
|
|
||||||
// does not need to be called on the dispatch (it does that)
|
|
||||||
GtkEventDispatch.shutdownGui();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user