aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java2
-rw-r--r--src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java131
-rw-r--r--src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java8
3 files changed, 109 insertions, 32 deletions
diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java
index 05fe771..cae3ada 100644
--- a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java
+++ b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java
@@ -185,7 +185,7 @@ public final class TrayMenuFactory
+ "CHAT_PRESENCE_DISABLED",
false);
- if (!chatPresenceDisabled.booleanValue())
+ if (!chatPresenceDisabled.booleanValue() && accountMenuSupported)
{
add(
trayMenu,
diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java
index a5bbee1..12334f3 100644
--- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java
+++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java
@@ -71,6 +71,8 @@ class AppIndicatorTrayIcon implements TrayIcon
private PopupMenuPeer popupPeer;
private AppIndicator1.AppIndicator appIndicator;
+ private PopupMenuPeer defaultMenuPeer;
+
public AppIndicatorTrayIcon(ImageIcon mainIcon, String title,
JPopupMenu popup)
{
@@ -98,6 +100,16 @@ class AppIndicatorTrayIcon implements TrayIcon
}
}
+ @Override
+ protected void finalize() throws Throwable
+ {
+ super.finalize();
+ if (isDefaultMenuItem)
+ {
+ gobject.g_object_unref(gtkMenuItem);
+ }
+ }
+
public List<PopupMenuPeer> children = new ArrayList<>();
public Pointer gtkMenuItem;
public Pointer gtkMenu;
@@ -107,6 +119,7 @@ class AppIndicatorTrayIcon implements TrayIcon
public Component menuItem;
public MenuItemSignalHandler signalHandler;
public long gtkSignalHandler;
+ public boolean isDefaultMenuItem;
@Override
public void componentAdded(ContainerEvent e)
@@ -151,19 +164,15 @@ class AppIndicatorTrayIcon implements TrayIcon
public void createTray()
{
- File iconFile = new File(imageIconToPath(mainIcon));
- appIndicator = ai.app_indicator_new_with_path(
- "jitsi",
- iconFile.getName().replaceFirst("[.][^.]+$", ""),
- AppIndicator1.APP_INDICATOR_CATEGORY.COMMUNICATIONS.ordinal(),
- iconFile.getParent());
-
- ai.app_indicator_set_title(appIndicator, title);
- setupGtkMenu();
-
- ai.app_indicator_set_status(
- appIndicator,
- AppIndicator1.APP_INDICATOR_STATUS.ACTIVE.ordinal());
+ gtk.gdk_threads_enter();
+ try
+ {
+ setupGtkMenu();
+ }
+ finally
+ {
+ gtk.gdk_threads_leave();
+ }
new Thread()
{
@@ -176,6 +185,19 @@ class AppIndicatorTrayIcon implements TrayIcon
private void setupGtkMenu()
{
+ File iconFile = new File(imageIconToPath(mainIcon));
+ appIndicator = ai.app_indicator_new_with_path(
+ "jitsi",
+ iconFile.getName().replaceFirst("[.][^.]+$", ""),
+ AppIndicator1.APP_INDICATOR_CATEGORY.COMMUNICATIONS.ordinal(),
+ iconFile.getParent());
+
+ ai.app_indicator_set_title(appIndicator, title);
+ ai.app_indicator_set_icon_full(
+ appIndicator,
+ iconFile.getAbsolutePath(),
+ "Jitsi");
+
// create root menu
popupPeer = new PopupMenuPeer(null, popup);
popupPeer.gtkMenu = gtk.gtk_menu_new();
@@ -186,11 +208,14 @@ class AppIndicatorTrayIcon implements TrayIcon
// attach the menu to the indicator
ai.app_indicator_set_menu(appIndicator, popupPeer.gtkMenu);
+ ai.app_indicator_set_status(
+ appIndicator,
+ AppIndicator1.APP_INDICATOR_STATUS.ACTIVE.ordinal());
}
private void cleanMenu(PopupMenuPeer peer)
{
- logger.debug("Clean requested for: " + peer.menuItem);
+ assert !peer.isDefaultMenuItem;
for (PopupMenuPeer p : peer.children)
{
cleanMenu(p);
@@ -308,7 +333,6 @@ class AppIndicatorTrayIcon implements TrayIcon
null,
null,
0);
- logger.debug("Signal for " + ((JMenuItem)m).getText() + " is " + peer.gtkSignalHandler);
}
}
@@ -459,9 +483,18 @@ class AppIndicatorTrayIcon implements TrayIcon
// gtk.gtk_image_menu_item_set_image(gtkMenuItem, image);
// break;
case AccessibleContext.ACCESSIBLE_STATE_PROPERTY:
- gtk.gtk_widget_set_sensitive(
- peer.gtkMenuItem,
- AccessibleState.ENABLED.equals(evt.getNewValue()) ? 1 : 0);
+ gtk.gdk_threads_enter();
+ try
+ {
+ gtk.gtk_widget_set_sensitive(
+ peer.gtkMenuItem,
+ AccessibleState.ENABLED.equals(
+ evt.getNewValue()) ? 1 : 0);
+ }
+ finally
+ {
+ gtk.gdk_threads_leave();
+ }
break;
}
}
@@ -510,6 +543,7 @@ class AppIndicatorTrayIcon implements TrayIcon
// already the same. Setting the selected state on the
// GTK sends the "activate" event, and would cause
// a loop
+ logger.debug("Checking selected state on: " + menu.getText());
if (menu.isSelected() == isGtkSelected())
{
return;
@@ -525,35 +559,63 @@ class AppIndicatorTrayIcon implements TrayIcon
private boolean isGtkSelected()
{
- return (gtk.gtk_check_menu_item_get_active(peer.gtkMenuItem) == 1);
+ gtk.gdk_threads_enter();
+ try
+ {
+ return gtk.gtk_check_menu_item_get_active(peer.gtkMenuItem) == 1;
+ }
+ finally
+ {
+ gtk.gdk_threads_leave();
+ }
}
}
@Override
public void setDefaultAction(Object menuItem)
{
- Pointer gtkMenuItem = findMenuItem(popupPeer, menuItem);
- if (gtkMenuItem != null)
+ // It shouldn't be necessary that we hold a reference to the
+ // default item, it is contained in the menu. It might even create
+ // a memory leak. But if not set, the indicator loses track of it
+ // (at least on Debian). Unref an existing item, then ref the newly
+ // set
+ if (defaultMenuPeer != null)
+ {
+ gobject.g_object_unref(defaultMenuPeer.gtkMenuItem);
+ }
+
+ PopupMenuPeer peer = findMenuItem(popupPeer, menuItem);
+ if (peer != null && peer.gtkMenuItem != null)
{
- ai.app_indicator_set_secondary_activate_target(
- appIndicator,
- gtkMenuItem);
+ gtk.gdk_threads_enter();
+ try
+ {
+ defaultMenuPeer = peer;
+ gobject.g_object_ref(peer.gtkMenuItem);
+ ai.app_indicator_set_secondary_activate_target(
+ appIndicator,
+ peer.gtkMenuItem);
+ }
+ finally
+ {
+ gtk.gdk_threads_leave();
+ }
}
}
- private Pointer findMenuItem(PopupMenuPeer peer, Object menuItem)
+ private PopupMenuPeer findMenuItem(PopupMenuPeer peer, Object menuItem)
{
if (peer.menuItem == menuItem)
{
logger.debug("Setting default action to: "
+ ((JMenuItem)menuItem).getText()
+ " @" + peer.gtkMenuItem);
- return peer.gtkMenuItem;
+ return peer;
}
for (PopupMenuPeer p : peer.children)
{
- Pointer found = findMenuItem(p, menuItem);
+ PopupMenuPeer found = findMenuItem(p, menuItem);
if (found != null)
{
return found;
@@ -582,10 +644,17 @@ class AppIndicatorTrayIcon implements TrayIcon
mainIcon = icon;
if (appIndicator != null)
{
- ai.app_indicator_set_icon_full(
- appIndicator,
- imageIconToPath(icon),
- "Jitsi");
+ gtk.gdk_threads_enter();
+ try
+ {
+ ai.app_indicator_set_icon(
+ appIndicator,
+ imageIconToPath(icon));
+ }
+ finally
+ {
+ gtk.gdk_threads_leave();
+ }
}
}
diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java
index 72c96cb..cfc7805 100644
--- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java
+++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java
@@ -79,4 +79,12 @@ interface Gobject extends Library
* @param object a GObject.
*/
void g_object_unref(Pointer object);
+
+ /**
+ * Increases the reference count of object.
+ *
+ * @param object a GObject.
+ * @return the same object.
+ */
+ Pointer g_object_ref(Pointer object);
}