diff --git a/bin/linux/libnotifywrapper.so b/bin/linux/libnotifywrapper.so deleted file mode 100755 index 7ed0beb2ceb7..000000000000 Binary files a/bin/linux/libnotifywrapper.so and /dev/null differ diff --git a/bin/linux/libnotifywrapper64.so b/bin/linux/libnotifywrapper64.so deleted file mode 100755 index d78fba9c994e..000000000000 Binary files a/bin/linux/libnotifywrapper64.so and /dev/null differ diff --git a/native/libnotifywrapper/LibNotifyWrapper.c b/native/libnotifywrapper/LibNotifyWrapper.c deleted file mode 100644 index e612f8b387b3..000000000000 --- a/native/libnotifywrapper/LibNotifyWrapper.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "com_intellij_ui_LibNotifyWrapper.h" -#include - -/* - * Class: com_intellij_ui_LibNotifyWrapper - * Method: showNotification - * Signature: (Ljava/lang/String;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_com_intellij_ui_LibNotifyWrapper_showNotification - (JNIEnv * jEnv, jclass c, jstring jTitle, jstring jDescription, jstring jLogoPath) { - - void *handle; - gboolean (*notify_init_func)(const char *app_name); - void (*notify_uninit_func)(); - NotifyNotification* (*notify_notification_new_func) (const char *summary, - const char *body, - const char *icon); - gboolean (*notify_notification_show_func) (NotifyNotification *notification, - GError **error); - char *error; - - dlerror(); - - handle = dlopen("libnotify.so", RTLD_LAZY); - - if ((error = dlerror()) != NULL) - { - (*jEnv)->ThrowNew(jEnv, (*jEnv)->FindClass(jEnv, "java/lang/UnsatisfiedLinkError"), error); - return; - } - - dlerror(); - - *(void **) (¬ify_init_func) = dlsym(handle, "notify_init"); - *(void **) (¬ify_uninit_func) = dlsym(handle, "notify_init"); - *(void **) (¬ify_notification_new_func) = dlsym(handle, "notify_notification_new"); - *(void **) (¬ify_notification_show_func) = dlsym(handle, "notify_notification_show"); - - (*notify_init_func) ("JetBrains"); - - const char *title = (*jEnv)->GetStringUTFChars(jEnv, jTitle, 0); - const char *description = (*jEnv)->GetStringUTFChars(jEnv, jDescription, 0); - const char *logoPath = (*jEnv)->GetStringUTFChars(jEnv, jLogoPath, 0); - NotifyNotification * notification = (*notify_notification_new_func) (title, description, logoPath); - (*notify_notification_show_func) (notification, NULL); - (*notify_uninit_func)(); - (*jEnv)->ReleaseStringUTFChars(jEnv, jTitle, title); - (*jEnv)->ReleaseStringUTFChars(jEnv, jDescription, description); - (*jEnv)->ReleaseStringUTFChars(jEnv, jLogoPath, logoPath); - - dlclose(handle); -} diff --git a/native/libnotifywrapper/com_intellij_ui_LibNotifyWrapper.h b/native/libnotifywrapper/com_intellij_ui_LibNotifyWrapper.h deleted file mode 100644 index cb55eca09ccb..000000000000 --- a/native/libnotifywrapper/com_intellij_ui_LibNotifyWrapper.h +++ /dev/null @@ -1,22 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -#include -/* Header for class com_intellij_ui_LibNotifyWrapper */ - -#ifndef _Included_com_intellij_ui_LibNotifyWrapper -#define _Included_com_intellij_ui_LibNotifyWrapper -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: com_intellij_ui_LibNotifyWrapper - * Method: showNotification - * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_com_intellij_ui_LibNotifyWrapper_showNotification - (JNIEnv *, jclass, jstring, jstring, jstring); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/platform/platform-impl/src/com/intellij/ui/GrowlNotifications.java b/platform/platform-impl/src/com/intellij/ui/GrowlNotifications.java index 9c681bcaf55e..b5c298a3787a 100644 --- a/platform/platform-impl/src/com/intellij/ui/GrowlNotifications.java +++ b/platform/platform-impl/src/com/intellij/ui/GrowlNotifications.java @@ -27,56 +27,45 @@ import java.util.TreeSet; /** * @author mike */ -class GrowlNotifications implements MacNotifications { +class GrowlNotifications implements SystemNotificationsImpl.Notifier { private static final Logger LOG = Logger.getInstance("#com.intellij.ui.GrowlNotifications"); private static GrowlNotifications ourNotifications; - private final Set myNotifications = new TreeSet(); - private Growl myGrowl; - public GrowlNotifications() { - this(ApplicationNamesInfo.getInstance().getFullProductName()); - } - - GrowlNotifications(String fullProductName) { - myGrowl = new Growl(fullProductName); - register(); - } - - private String[] getAllNotifications() { - return ArrayUtil.toStringArray(myNotifications); - } - - public static synchronized GrowlNotifications getNotifications() { + public static synchronized GrowlNotifications getInstance() { if (ourNotifications == null) { ourNotifications = new GrowlNotifications(); } - return ourNotifications; } - public void notify(Set allNotifications, @NotNull String notificationName, String title, String description) { - if (!myNotifications.equals(allNotifications)) { - myNotifications.addAll(allNotifications); - register(); - } + private final Growl myGrowl; + private final Set myNotifications; - try { - myGrowl.notifyGrowlOf(notificationName, title, description); - } - catch (Exception e) { - LOG.error(e); - } + private GrowlNotifications() { + myGrowl = new Growl(ApplicationNamesInfo.getInstance().getFullProductName()); + myNotifications = new TreeSet(); + register(); } private void register() { - myGrowl.setAllowedNotifications(getAllNotifications()); - try { - myGrowl.setDefaultNotifications(getAllNotifications()); - } - catch (Exception e) { - LOG.error(e); - } + myGrowl.setAllowedNotifications(ArrayUtil.toStringArray(myNotifications)); + myGrowl.setDefaultNotifications(ArrayUtil.toStringArray(myNotifications)); myGrowl.register(); } + + @Override + public void notify(@NotNull Set allNames, @NotNull String name, @NotNull String title, @NotNull String description) { + try { + if (!myNotifications.equals(allNames)) { + myNotifications.addAll(allNames); + register(); + } + + myGrowl.notifyGrowlOf(name, title, description); + } + catch (Exception e) { + LOG.warn(e); + } + } } diff --git a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java index fcc0f65e9314..6baba567bc41 100644 --- a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java +++ b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java @@ -15,53 +15,63 @@ */ package com.intellij.ui; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationGroup; -import com.intellij.notification.NotificationType; -import com.intellij.notification.Notifications; +import com.intellij.ide.AppLifecycleListener; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.application.PathManager; -import com.intellij.util.lang.UrlClassLoader; +import com.intellij.util.messages.MessageBusConnection; +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; /** * @author Denis Fokin */ -public class LibNotifyWrapper { +class LibNotifyWrapper implements SystemNotificationsImpl.Notifier { + private static LibNotifyWrapper ourInstance; - private final static String message = "Looks like you have run 32-bit Java on a 64-bit version of OS " + - "or just have not installed appropriate libnotify.so library"; - - private static boolean available = true; - - static{ - UrlClassLoader.loadPlatformLibrary("notifywrapper"); - } - - native private static void showNotification(final String title, final String description, final String iconPath); - - public static void show(final String title, final String description, final String iconPath) { - if (! available) return; - try { - showNotification(title, description, iconPath); - } catch (UnsatisfiedLinkError ule) { - available = false; - NotificationGroup.balloonGroup("Linux configuration messages"); - Notifications.Bus.notify( - new Notification("Linux configuration messages", - "Notification library has not been installed", - message, NotificationType.INFORMATION) - ); + public static synchronized LibNotifyWrapper getInstance() { + if (ourInstance == null) { + ourInstance = new LibNotifyWrapper(); } + return ourInstance; } - /** - * Shows a libnotify notification with an icon from the ide bin directory. - * If there is no such icon a default information icon is shown. - * @param title notification title - * @param description notification description - */ - public static void showWithAppIcon(final String title, final String description) { - String iconPath = AppUIUtil.findIcon(PathManager.getBinPath()); - show(title, description, (iconPath == null) ? "dialog-information" : iconPath); + @SuppressWarnings("SpellCheckingInspection") + private interface LibNotify extends Library { + int notify_init(String appName); + void notify_uninit(); + Pointer notify_notification_new(String summary, String body, String icon); + int notify_notification_show(Pointer notification, Pointer error); } + private final LibNotify myLibNotify; + + private LibNotifyWrapper() { + myLibNotify = (LibNotify)Native.loadLibrary("notify", LibNotify.class); + + String appName = ApplicationNamesInfo.getInstance().getProductName(); + if (myLibNotify.notify_init(appName) == 0) { + throw new IllegalStateException("notify_init failed"); + } + + MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); + connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() { + @Override + public void appClosing() { + myLibNotify.notify_uninit(); + } + }); + } + + @Override + public void notify(@NotNull Set allNames, @NotNull String name, @NotNull String title, @NotNull String description) { + String icon = AppUIUtil.findIcon(PathManager.getBinPath()); + if (icon == null) icon = "dialog-information"; + Pointer notification = myLibNotify.notify_notification_new(title, description, icon); + myLibNotify.notify_notification_show(notification, null); + } } diff --git a/platform/platform-impl/src/com/intellij/ui/MacNotifications.java b/platform/platform-impl/src/com/intellij/ui/MacNotifications.java deleted file mode 100644 index d8c4711e4f25..000000000000 --- a/platform/platform-impl/src/com/intellij/ui/MacNotifications.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.ui; - -import org.jetbrains.annotations.NotNull; - -import java.util.Set; - -/** - * @author Dennis.Ushakov - */ -public interface MacNotifications { - void notify(Set allNotifications, @NotNull String notificationName, String title, String description); -} diff --git a/platform/platform-impl/src/com/intellij/ui/MountainLionNotifications.java b/platform/platform-impl/src/com/intellij/ui/MountainLionNotifications.java index 20e5c1a094ba..955b38f9e340 100644 --- a/platform/platform-impl/src/com/intellij/ui/MountainLionNotifications.java +++ b/platform/platform-impl/src/com/intellij/ui/MountainLionNotifications.java @@ -33,19 +33,23 @@ import static com.intellij.ui.mac.foundation.Foundation.nsString; /** * @author Dennis.Ushakov */ -public class MountainLionNotifications implements MacNotifications { - private static MountainLionNotifications ourNotifications; +class MountainLionNotifications implements SystemNotificationsImpl.Notifier { + private static MountainLionNotifications ourInstance; - public MountainLionNotifications() { + public static synchronized MountainLionNotifications getInstance() { + if (ourInstance == null) { + ourInstance = new MountainLionNotifications(); + } + return ourInstance; + } + + private MountainLionNotifications() { final MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(); - connection.subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener() { + connection.subscribe(ApplicationActivationListener.TOPIC, new ApplicationActivationListener.Adapter() { @Override public void applicationActivated(IdeFrame ideFrame) { cleanupDeliveredNotifications(); } - - @Override - public void applicationDeactivated(IdeFrame ideFrame) {} }); connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() { @Override @@ -55,24 +59,16 @@ public class MountainLionNotifications implements MacNotifications { }); } - public static synchronized MacNotifications getNotifications() { - if (ourNotifications == null) { - ourNotifications = new MountainLionNotifications(); - } - - return ourNotifications; - } - @Override - public void notify(Set allNotifications, @NotNull String notificationName, String title, String description) { + public void notify(@NotNull Set allNames, @NotNull String name, @NotNull String title, @NotNull String description) { final ID notification = invoke(Foundation.getObjcClass("NSUserNotification"), "new"); - invoke(notification, "setTitle:", nsString(StringUtil.stripHtml(title == null ? "" : title, true).replace("%", "%%"))); - invoke(notification, "setInformativeText:", nsString(StringUtil.stripHtml(description == null ? "" : description, true).replace("%", "%%"))); + invoke(notification, "setTitle:", nsString(StringUtil.stripHtml(title, true).replace("%", "%%"))); + invoke(notification, "setInformativeText:", nsString(StringUtil.stripHtml(description, true).replace("%", "%%"))); final ID center = invoke(Foundation.getObjcClass("NSUserNotificationCenter"), "defaultUserNotificationCenter"); invoke(center, "deliverNotification:", notification); } - public static void cleanupDeliveredNotifications() { + private static void cleanupDeliveredNotifications() { final ID center = invoke(Foundation.getObjcClass("NSUserNotificationCenter"), "defaultUserNotificationCenter"); invoke(center, "removeAllDeliveredNotifications"); } diff --git a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java index 3240b3eb0434..597301bb1a2d 100644 --- a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java @@ -20,6 +20,7 @@ import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import org.jetbrains.annotations.NotNull; @@ -33,65 +34,58 @@ import java.util.Set; @State( name = "SystemNotifications", storages = { - @Storage( - file = StoragePathMacros.APP_CONFIG + "/other.xml" - )} + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") + } ) public class SystemNotificationsImpl extends SystemNotifications implements PersistentStateComponent { + public static class State { + public Set NOTIFICATIONS = new HashSet(); + } + + interface Notifier { + void notify(@NotNull Set allNames, @NotNull String name, @NotNull String title, @NotNull String description); + } + + private final Notifier myNotifier = getPlatformNotifier(); private State myState = new State(); - private boolean myGrowlDisabled = false; - - public void notify(@NotNull String notificationName, @NotNull String title, @NotNull String text) { - if (!areNotificationsEnabled() || ApplicationManager.getApplication().isActive()) return; - - if (SystemInfo.isLinux && Registry.is("ide.linux.gtk.notifications.enabled") ) { - LibNotifyWrapper.showWithAppIcon(title, text); - return; - } - - final MacNotifications notifications; - try { - notifications = getMacNotifications(); - } - catch (Throwable e) { - myGrowlDisabled = true; - return; - } - - myState.NOTIFICATIONS.add(notificationName); - notifications.notify(myState.NOTIFICATIONS, notificationName, title, text); - } - - private static MacNotifications getMacNotifications() { - return SystemInfo.isMacOSMountainLion && Registry.is("ide.mac.mountain.lion.notifications.enabled") ? - MountainLionNotifications.getNotifications() : GrowlNotifications.getNotifications(); - } - - private boolean areNotificationsEnabled() { - boolean enabled = false; - - if (SystemInfo.isMac) { - enabled = !(myGrowlDisabled || "true".equalsIgnoreCase(System.getProperty("growl.disable"))); - if (!enabled) { - enabled = SystemInfo.isMacOSMountainLion && Registry.is("ide.mac.mountain.lion.notifications.enabled"); - } - } else { - enabled = SystemInfo.isLinux && Registry.is("ide.linux.gtk.notifications.enabled"); - } - - return enabled; - } + @Override public State getState() { return myState; } + @Override public void loadState(final State state) { myState = state; } + @Override + public void notify(@NotNull String notificationName, @NotNull String title, @NotNull String text) { + if (myNotifier != null && !ApplicationManager.getApplication().isActive()) { + myState.NOTIFICATIONS.add(notificationName); + myNotifier.notify(myState.NOTIFICATIONS, notificationName, title, text); + } + } - public static class State { - public Set NOTIFICATIONS = new HashSet(); + private static Notifier getPlatformNotifier() { + try { + if (SystemInfo.isMac) { + if (SystemInfo.isMacOSMountainLion && Registry.is("ide.mac.mountain.lion.notifications.enabled")) { + return MountainLionNotifications.getInstance(); + } + if (!Boolean.getBoolean("growl.disable")) { + return GrowlNotifications.getInstance(); + } + } + + if (SystemInfo.isXWindow && Registry.is("ide.libnotify.enabled") ) { + return LibNotifyWrapper.getInstance(); + } + } + catch (Throwable t) { + Logger.getInstance(SystemNotifications.class).error(t); + } + + return null; } } diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 46bc20de8193..5e0501c23f06 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -354,8 +354,9 @@ bigger.font.in.project.view.description=Increases font size in Project View darcula.use.native.fonts.on.linux=true darcula.use.native.fonts.on.linux.description=If false, uses DejaVu Sans 13pt idea.4.5.laf.enabled=false -ide.linux.gtk.notifications.enabled=true -ide.linux.gtk.notifications.enabled.description=Enables GTK notifications on linux +ide.libnotify.enabled=true +# suppress inspection "UnusedProperty" +ide.libnotify.enabled.description=Enables notifications via LibNotify cvs.roots.refresh.uses.vfs=true cvs.roots.refresh.uses.vfs.description=Should CVS roots refresh after update use VFS editor.wrap.collapsed.region.at.line.start=false