diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | gtk/Makefile.am | 1 | ||||
-rw-r--r-- | gtk/gtkstatusicon-quartz.c | 148 | ||||
-rwxr-xr-x | gtk/gtkstatusicon.c | 104 |
4 files changed, 258 insertions, 2 deletions
@@ -1,3 +1,10 @@ +2006-12-20 Mikael Hallendal <micke@imendio.com> + + * gtk/Makefile.am: Added gtkstatusicon-quartz.c + * gtk/gtkstatusicon-quartz.c: Implements the quartz backend for the + status icon. + * gtk/gtkstatusicon.c: Hooked in the new quartz backend. Bug #387874. + 2006-12-19 Matthias Clasen <mclasen@redhat.com> * gtk/gtkprintunixdialog.c: Add a tooltip explaining the diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 4c07d1e461..36ad0292cb 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -697,6 +697,7 @@ gtk_extra_sources = \ paper_names.c \ paper_names_offsets.c \ gen-paper-names.c \ + gtkstatusicon-quartz.c \ gtk.symbols \ gtkversion.h.in \ gtkmarshalers.list \ diff --git a/gtk/gtkstatusicon-quartz.c b/gtk/gtkstatusicon-quartz.c new file mode 100644 index 0000000000..8f8bb024c8 --- /dev/null +++ b/gtk/gtkstatusicon-quartz.c @@ -0,0 +1,148 @@ +/* gtkstatusicon-quartz.c: + * + * Copyright (C) 2006 Imendio AB + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * GCC on Mac OS X handles inlined objective C in C-files. + * + * Authors: + * Mikael Hallendal <micke@imendio.com> + */ + +#import <Cocoa/Cocoa.h> +#include <quartz/gdkquartz.h> + +#define QUARTZ_POOL_ALLOC NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init] +#define QUARTZ_POOL_RELEASE [pool release] + +@interface GtkQuartzStatusIcon : NSObject +{ + GtkStatusIcon *status_icon; + NSStatusBar *ns_bar; + NSStatusItem *ns_item; + NSImage *current_image; + NSString *ns_tooltip; +} +- (id) initWithStatusIcon:(GtkStatusIcon *)status_icon; +- (void) ensureItem; +- (void) actionCb:(NSObject *)button; +- (void) setImage:(GdkPixbuf *)pixbuf; +- (void) setVisible:(gboolean)visible; +- (void) setToolTip:(const gchar *)tooltip_text; +- (float) getWidth; +- (float) getHeight; +@end + +@implementation GtkQuartzStatusIcon : NSObject +- (id) initWithStatusIcon:(GtkStatusIcon *)icon +{ + [super init]; + status_icon = icon; + ns_bar = [NSStatusBar systemStatusBar]; + + return self; +} + +- (void) ensureItem +{ + if (ns_item != nil) + return; + + ns_item = [ns_bar statusItemWithLength:NSVariableStatusItemLength]; + [ns_item setAction:@selector(actionCb:)]; + [ns_item setTarget:self]; + [ns_item retain]; +} + +- (void) dealloc +{ + g_print ("Deallocating GtkQuartzStatusIcon\n"); + [current_image release]; + [ns_item release]; + [ns_bar release]; + + [super dealloc]; +} + +- (void) actionCb:(NSObject *)button +{ + NSEvent *event = [NSApp currentEvent]; + double time = [event timestamp]; + + g_signal_emit (status_icon, + status_icon_signals [POPUP_MENU_SIGNAL], 0, + 1, + time * 1000.0); +} + +- (void) setImage:(GdkPixbuf *)pixbuf +{ + /* Support NULL */ + [self ensureItem]; + + if (current_image != nil) { + [current_image release]; + current_image = nil; + } + + if (!pixbuf) { + [ns_item release]; + ns_item = nil; + return; + } + + current_image = gdk_quartz_pixbuf_to_ns_image_libgtk_only (pixbuf); + [current_image retain]; + + [ns_item setImage:current_image]; +} + +- (void) setVisible:(gboolean)visible +{ + if (visible) { + [self ensureItem]; + if (ns_item != nil) + [ns_item setImage:current_image]; + if (ns_tooltip != nil) + [ns_item setToolTip:ns_tooltip]; + } else { + [ns_item release]; + ns_item = nil; + } +} + +- (void) setToolTip:(const gchar *)tooltip_text +{ + [ns_tooltip release]; + ns_tooltip = [[NSString stringWithUTF8String:tooltip_text] retain]; + + [ns_item setToolTip:ns_tooltip]; +} + +- (float) getWidth +{ + return [ns_bar thickness]; +} + +- (float) getHeight +{ + return [ns_bar thickness]; +} +@end + + + diff --git a/gtk/gtkstatusicon.c b/gtk/gtkstatusicon.c index 7ed3cb754a..047fd48df1 100755 --- a/gtk/gtkstatusicon.c +++ b/gtk/gtkstatusicon.c @@ -3,6 +3,7 @@ * Copyright (C) 2003 Sun Microsystems, Inc. * Copyright (C) 2005 Hans Breuer <hans@breuer.org> * Copyright (C) 2005 Novell, Inc. + * Copyright (C) 2006 Imendio AB * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,6 +24,7 @@ * Mark McLoughlin <mark@skynet.ie> * Hans Breuer <hans@breuer.org> * Tor Lillqvist <tml@novell.com> + * Mikael Hallendal <micke@imendio.com> */ #include <config.h> @@ -47,6 +49,11 @@ #define WM_GTK_TRAY_NOTIFICATION (WM_USER+1) #endif +#ifdef GDK_WINDOWING_QUARTZ +#include "gtkicontheme.h" +#include "gtklabel.h" +#endif + #include "gtkalias.h" #define BLINK_TIMEOUT 500 @@ -73,6 +80,12 @@ enum LAST_SIGNAL }; +static guint status_icon_signals [LAST_SIGNAL] = { 0 }; + +#ifdef GDK_WINDOWING_QUARTZ +#include "gtkstatusicon-quartz.c" +#endif + struct _GtkStatusIconPrivate { #ifdef GDK_WINDOWING_X11 @@ -85,6 +98,11 @@ struct _GtkStatusIconPrivate GtkWidget *dummy_widget; NOTIFYICONDATAW nid; #endif + +#ifdef GDK_WINDOWING_QUARTZ + GtkWidget *dummy_widget; + GtkQuartzStatusIcon *status_item; +#endif gint size; @@ -130,8 +148,6 @@ static void gtk_status_icon_disable_blinking (GtkStatusIcon *status_icon); static void gtk_status_icon_reset_image_data (GtkStatusIcon *status_icon); -static guint status_icon_signals [LAST_SIGNAL] = { 0 }; - G_DEFINE_TYPE (GtkStatusIcon, gtk_status_icon, G_TYPE_OBJECT) static void @@ -466,6 +482,20 @@ gtk_status_icon_init (GtkStatusIcon *status_icon) priv->nid.hWnd = NULL; } #endif + +#ifdef GDK_WINDOWING_QUARTZ + priv->dummy_widget = gtk_label_new (""); + + QUARTZ_POOL_ALLOC; + + priv->status_item = [[GtkQuartzStatusIcon alloc] initWithStatusIcon:status_icon]; + + priv->image_height = [priv->status_item getHeight]; + priv->image_width = [priv->status_item getWidth]; + + QUARTZ_POOL_RELEASE; + +#endif } static void @@ -496,6 +526,12 @@ gtk_status_icon_finalize (GObject *object) gtk_widget_destroy (priv->dummy_widget); #endif + +#ifdef GDK_WINDOWING_QUARTZ + QUARTZ_POOL_ALLOC; + [priv->status_item release]; + QUARTZ_POOL_RELEASE; +#endif G_OBJECT_CLASS (gtk_status_icon_parent_class)->finalize (object); } @@ -816,6 +852,11 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon) if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid)) g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1); #endif +#ifdef GDK_WINDOWING_QUARTZ + QUARTZ_POOL_ALLOC; + [priv->status_item setImage:gtk_status_icon_blank_icon (status_icon)]; + QUARTZ_POOL_RELEASE; +#endif return; } @@ -857,6 +898,12 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon) if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid)) g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1); #endif +#ifdef GDK_WINDOWING_QUARTZ + QUARTZ_POOL_ALLOC; + [priv->status_item setImage:scaled]; + QUARTZ_POOL_RELEASE; +#endif + g_object_unref (scaled); } else @@ -870,6 +917,9 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon) if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid)) g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1); #endif +#ifdef GDK_WINDOWING_QUARTZ + [priv->status_item setImage:NULL]; +#endif } } break; @@ -897,6 +947,20 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon) g_object_unref (pixbuf); } #endif +#ifdef GDK_WINDOWING_QUARTZ + { + GdkPixbuf *pixbuf; + + pixbuf = gtk_widget_render_icon (priv->dummy_widget, + priv->image_data.stock_id, + GTK_ICON_SIZE_SMALL_TOOLBAR, + NULL); + QUARTZ_POOL_ALLOC; + [priv->status_item setImage:pixbuf]; + QUARTZ_POOL_RELEASE; + g_object_unref (pixbuf); + } +#endif } break; @@ -924,6 +988,22 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon) g_object_unref (pixbuf); } #endif +#ifdef GDK_WINDOWING_QUARTZ + { + GdkPixbuf *pixbuf; + + pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), + priv->image_data.icon_name, + priv->size, + 0, NULL); + + QUARTZ_POOL_ALLOC; + [priv->status_item setImage:pixbuf]; + QUARTZ_POOL_RELEASE; + g_object_unref (pixbuf); + } +#endif + } break; @@ -937,6 +1017,13 @@ gtk_status_icon_update_image (GtkStatusIcon *status_icon) if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid)) g_warning ("%s:%d:Shell_NotifyIcon(NIM_MODIFY) failed", __FILE__, __LINE__-1); #endif +#ifdef GDK_WINDOWING_QUARTZ + { + QUARTZ_POOL_ALLOC; + [priv->status_item setImage:NULL]; + QUARTZ_POOL_RELEASE; + } +#endif break; default: g_assert_not_reached (); @@ -1398,6 +1485,11 @@ gtk_status_icon_set_tooltip (GtkStatusIcon *status_icon, if (!Shell_NotifyIconW (NIM_MODIFY, &priv->nid)) g_warning ("%s:%d:Shell_NotifyIconW(NIM_MODIFY) failed", __FILE__, __LINE__-1); #endif +#ifdef GDK_WINDOWING_QUARTZ + QUARTZ_POOL_ALLOC; + [priv->status_item setToolTip:tooltip_text]; + QUARTZ_POOL_RELEASE; +#endif } static gboolean @@ -1483,6 +1575,11 @@ gtk_status_icon_set_visible (GtkStatusIcon *status_icon, Shell_NotifyIconW (NIM_DELETE, &priv->nid); } #endif +#ifdef GDK_WINDOWING_QUARTZ + QUARTZ_POOL_ALLOC; + [priv->status_item setVisible:visible]; + QUARTZ_POOL_RELEASE; +#endif g_object_notify (G_OBJECT (status_icon), "visible"); } } @@ -1596,6 +1693,9 @@ gtk_status_icon_is_embedded (GtkStatusIcon *status_icon) #ifdef GDK_WINDOWING_WIN32 return TRUE; #endif +#ifdef GDK_WINDOWING_QUARTZ + return TRUE; +#endif } /** |