]> git.saurik.com Git - wxWidgets.git/commitdiff
new wxTaskBarIcon implementation for GTK2
authorPaul Cornett <paulcor@bullseye.com>
Sun, 8 Feb 2009 22:21:24 +0000 (22:21 +0000)
committerPaul Cornett <paulcor@bullseye.com>
Sun, 8 Feb 2009 22:21:24 +0000 (22:21 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58777 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

build/bakefiles/files.bkl
include/wx/gtk/taskbar.h [new file with mode: 0644]
include/wx/gtk/taskbarpriv.h [deleted file]
include/wx/gtk/window.h
include/wx/taskbar.h
src/gtk/taskbar.cpp
src/gtk/window.cpp
src/unix/taskbarx11.cpp

index 29978103fc44592d6e0e6bcb52ae578b0fc99df9..49d6da1959e007d65164b375c7762e2f6791cfcf 100644 (file)
@@ -3007,6 +3007,7 @@ src/osx/iphone/window.mm
 </set>
 <set var="ADVANCED_GTK_HDR" hints="files">
     wx/gtk/hildon/notifmsg.h
+    wx/gtk/taskbar.h
 </set>
 
 <set var="ADVANCED_GTK_NATIVE_SRC" hints="files">
diff --git a/include/wx/gtk/taskbar.h b/include/wx/gtk/taskbar.h
new file mode 100644 (file)
index 0000000..b46758a
--- /dev/null
@@ -0,0 +1,34 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        wx/gtk/taskbar.h
+// Purpose:     wxTaskBarIcon class for GTK2
+// Author:      Paul Cornett
+// Created:     2009-02-08
+// RCS-ID:      $Id$
+// Copyright:   (c) 2009 Paul Cornett
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_GTK_TASKBARICON_H_
+#define _WX_GTK_TASKBARICON_H_
+
+class WXDLLIMPEXP_ADV wxTaskBarIcon: public wxTaskBarIconBase
+{
+public:
+    wxTaskBarIcon();
+    ~wxTaskBarIcon();
+    virtual bool SetIcon(const wxIcon& icon, const wxString& tooltip = wxString());
+    virtual bool RemoveIcon();
+    virtual bool PopupMenu(wxMenu* menu);
+    bool IsOk() const { return true; }
+    bool IsIconInstalled() const;
+
+    class Private;
+
+private:
+    Private* m_priv;
+
+    DECLARE_DYNAMIC_CLASS(wxTaskBarIcon)
+    DECLARE_NO_COPY_CLASS(wxTaskBarIcon)
+};
+
+#endif // _WX_GTK_TASKBARICON_H_
diff --git a/include/wx/gtk/taskbarpriv.h b/include/wx/gtk/taskbarpriv.h
deleted file mode 100644 (file)
index 242d3c6..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/////////////////////////////////////////////////////////////////////////
-// File:        wx/gtk/taskbarpriv.h
-// Purpose:     wxTaskBarIcon (src/unix/taskbarx11.cpp) helper for GTK2
-// Author:      Vaclav Slavik
-// Modified by:
-// Created:     2004/05/29
-// RCS-ID:      $Id$
-// Copyright:   (c) Vaclav Slavik, 2004
-// Licence:     wxWindows licence
-/////////////////////////////////////////////////////////////////////////
-
-#ifndef _WX_GTK_TASKBARPRIV_H_
-#define _WX_GTK_TASKBARPRIV_H_
-
-#include "wx/toplevel.h"
-
-class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxTopLevelWindow
-{
-public:
-    wxTaskBarIconAreaBase();
-
-    // Returns true if SYSTRAY protocol is supported by the desktop
-    static bool IsProtocolSupported();
-
-    wxEvtHandler *m_invokingWindow;
-
-protected:
-#if wxUSE_MENUS_NATIVE
-    virtual void DoPopupMenuUpdateUI(wxMenu* menu);
-#endif // wxUSE_MENUS_NATIVE
-};
-
-#endif // _WX_GTK_TASKBARPRIV_H_
index 9f6a26f437f64f901614592ede1bb39b835db21d..4cd39e93db53a7e4a9d4ee5052c819fa1aeb2140 100644 (file)
@@ -316,7 +316,6 @@ protected:
 
 #if wxUSE_MENUS_NATIVE
     virtual bool DoPopupMenu( wxMenu *menu, int x, int y );
-    virtual void DoPopupMenuUpdateUI(wxMenu* menu);
 #endif // wxUSE_MENUS_NATIVE
 
     virtual void DoCaptureMouse();
index 8c789f09f457b3ff75567e6f4f13d466ef40941e..fdc2ea0f3a0b4f9344a112445897addf67240ce5 100644 (file)
@@ -65,6 +65,8 @@ private:
     #include "wx/palmos/taskbar.h"
 #elif defined(__WXMSW__)
     #include "wx/msw/taskbar.h"
+#elif defined(__WXGTK20__)
+    #include "wx/gtk/taskbar.h"
 #elif defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__)
     #include "wx/unix/taskbarx11.h"
 #elif defined (__WXMAC__)
index ee192ae7b92c0f220f0d38145bdd5310da7a7300..03bee569c733bbdbe9fb954ca1106481f1557b03 100644 (file)
@@ -1,8 +1,8 @@
 /////////////////////////////////////////////////////////////////////////
 // File:        src/gtk/taskbar.cpp
-// Purpose:     wxTaskBarIcon (src/unix/taskbarx11.cpp) helper for GTK2
+// Purpose:     wxTaskBarIcon
 // Author:      Vaclav Slavik
-// Modified by:
+// Modified by: Paul Cornett
 // Created:     2004/05/29
 // RCS-ID:      $Id$
 // Copyright:   (c) Vaclav Slavik, 2004
 
 #if wxUSE_TASKBARICON
 
-#include "wx/gtk/taskbarpriv.h"
+#include "wx/taskbar.h"
 
 #ifndef WX_PRECOMP
-    #include "wx/log.h"
-    #include "wx/frame.h"
+    #include "wx/toplevel.h"
     #include "wx/menu.h"
+    #include "wx/icon.h"
 #endif
 
+#include "eggtrayicon.h"
 #include <gtk/gtk.h>
-#include <gdk/gdkx.h>
 
-#include "eggtrayicon.h"
+class wxTaskBarIcon::Private
+{
+public:
+    Private(wxTaskBarIcon* taskBarIcon);
+    ~Private();
+    void SetIcon();
+    void size_allocate(int width, int height);
+
+    // owning wxTaskBarIcon
+    wxTaskBarIcon* m_taskBarIcon;
+    // used when GTK+ >= 2.10
+    GtkStatusIcon* m_statusIcon;
+    // used when GTK+ < 2.10
+    GtkWidget* m_eggTrayIcon;
+    // for PopupMenu
+    wxWindow* m_win;
+    // for tooltip when GTK+ < 2.10
+    GtkTooltips* m_tooltips;
+    wxBitmap m_bitmap;
+    wxString m_tipText;
+    // width and height of available space, only used when GTK+ < 2.10
+    int m_size;
+};
+//-----------------------------------------------------------------------------
 
-wxTaskBarIconAreaBase::wxTaskBarIconAreaBase()
+extern "C" {
+static void
+icon_size_allocate(GtkWidget*, GtkAllocation* alloc, wxTaskBarIcon::Private* priv)
 {
-    if (IsProtocolSupported())
-    {
-        m_widget = GTK_WIDGET(egg_tray_icon_new("systray icon"));
-        g_object_ref(m_widget);
-        gtk_window_set_resizable(GTK_WINDOW(m_widget), false);
+    priv->size_allocate(alloc->width, alloc->height);
+}
 
-        wxLogTrace(_T("systray"), _T("using freedesktop.org systray spec"));
-    }
+static void
+icon_destroy(GtkWidget*, wxTaskBarIcon::Private* priv)
+{
+    // Icon window destroyed, probably because tray program has died.
+    // Recreate icon so it will appear if tray program is restarted.
+    priv->m_eggTrayIcon = NULL;
+    priv->SetIcon();
+}
 
-    wxTopLevelWindow::Create(
-            NULL, wxID_ANY, _T("systray icon"),
-            wxDefaultPosition, wxDefaultSize,
-            wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR | wxSIMPLE_BORDER |
-            wxFRAME_SHAPED,
-            wxEmptyString /*eggtray doesn't like setting wmclass*/);
+static void
+icon_activate(void*, wxTaskBarIcon* taskBarIcon)
+{
+    // activate occurs from single click with GTK+
+    wxTaskBarIconEvent event(wxEVT_TASKBAR_LEFT_DOWN, taskBarIcon);
+    if (!taskBarIcon->SafelyProcessEvent(event))
+    {
+        // if single click not handled, send double click for compatibility
+        event.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK);
+        taskBarIcon->SafelyProcessEvent(event);
+    }
+}
 
-    // WM frame extents are not useful for wxTaskBarIcon
-    m_deferShow = false;
-    gulong handler_id = g_signal_handler_find(
-        m_widget,
-        GSignalMatchType(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA),
-        g_signal_lookup("property_notify_event", GTK_TYPE_WIDGET),
-        0, NULL, NULL, this);
-    if (handler_id != 0)
-        g_signal_handler_disconnect(m_widget, handler_id);
+static gboolean
+icon_popup_menu(GtkWidget*, wxTaskBarIcon* taskBarIcon)
+{
+    wxTaskBarIconEvent event(wxEVT_TASKBAR_CLICK, taskBarIcon);
+    taskBarIcon->SafelyProcessEvent(event);
+    return true;
+}
 
-    m_invokingWindow = NULL;
+static gboolean
+icon_button_press_event(GtkWidget*, GdkEventButton* event, wxTaskBarIcon* taskBarIcon)
+{
+    if (event->type == GDK_BUTTON_PRESS)
+    {
+        if (event->button == 1)
+            icon_activate(NULL, taskBarIcon);
+        else if (event->button == 3)
+            icon_popup_menu(NULL, taskBarIcon);
+    }
+    return false;
 }
 
-bool wxTaskBarIconAreaBase::IsProtocolSupported()
+#if GTK_CHECK_VERSION(2,10,0)
+static void
+status_icon_popup_menu(GtkStatusIcon*, guint, guint, wxTaskBarIcon* taskBarIcon)
 {
-    Display *display = GDK_DISPLAY();
-    Screen *screen = DefaultScreenOfDisplay(display);
+    icon_popup_menu(NULL, taskBarIcon);
+}
+#endif
+} // extern "C"
+//-----------------------------------------------------------------------------
 
+bool wxTaskBarIconBase::IsAvailable()
+{
     char name[32];
     g_snprintf(name, sizeof(name), "_NET_SYSTEM_TRAY_S%d",
-        XScreenNumberOfScreen(screen));
-    Atom atom = XInternAtom(display, name, False);
+        gdk_x11_get_default_screen());
+    Atom atom = gdk_x11_get_xatom_by_name(name);
 
-    Window manager = XGetSelectionOwner(display, atom);
+    Window manager = XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom);
 
-    return (manager != None);
+    return manager != None;
 }
-
 //-----------------------------------------------------------------------------
-// Pop-up menu stuff
+
+wxTaskBarIcon::Private::Private(wxTaskBarIcon* taskBarIcon)
+{
+    m_taskBarIcon = taskBarIcon;
+    m_statusIcon = NULL;
+    m_eggTrayIcon = NULL;
+    m_win = NULL;
+    m_tooltips = NULL;
+    m_size = 0;
+}
+
+wxTaskBarIcon::Private::~Private()
+{
+    if (m_statusIcon)
+        g_object_unref(m_statusIcon);
+    else if (m_eggTrayIcon)
+    {
+        g_signal_handlers_disconnect_by_func(m_eggTrayIcon, (void*)icon_destroy, this);
+        gtk_widget_destroy(m_eggTrayIcon);
+    }
+    if (m_win)
+    {
+        m_win->PopEventHandler();
+        m_win->Destroy();
+    }
+    if (m_tooltips)
+    {
+        gtk_object_destroy(GTK_OBJECT(m_tooltips));
+        g_object_unref(m_tooltips);
+    }
+}
+
+void wxTaskBarIcon::Private::SetIcon()
+{
+#if GTK_CHECK_VERSION(2,10,0)
+    if (gtk_check_version(2,10,0) == NULL)
+    {
+        if (m_statusIcon)
+            gtk_status_icon_set_from_pixbuf(m_statusIcon, m_bitmap.GetPixbuf());
+        else
+        {
+            m_statusIcon = gtk_status_icon_new_from_pixbuf(m_bitmap.GetPixbuf());
+            g_signal_connect(m_statusIcon, "activate",
+                G_CALLBACK(icon_activate), m_taskBarIcon);
+            g_signal_connect(m_statusIcon, "popup_menu",
+                G_CALLBACK(status_icon_popup_menu), m_taskBarIcon);
+        }
+    }
+    else
+#endif
+    {
+        m_size = 0;
+        if (m_eggTrayIcon)
+        {
+            GtkWidget* image = GTK_BIN(m_eggTrayIcon)->child;
+            gtk_image_set_from_pixbuf(GTK_IMAGE(image), m_bitmap.GetPixbuf());
+        }
+        else
+        {
+            m_eggTrayIcon = GTK_WIDGET(egg_tray_icon_new("wxTaskBarIcon"));
+            gtk_widget_add_events(m_eggTrayIcon, GDK_BUTTON_PRESS_MASK);
+            g_signal_connect(m_eggTrayIcon, "size_allocate",
+                G_CALLBACK(icon_size_allocate), this);
+            g_signal_connect(m_eggTrayIcon, "destroy",
+                G_CALLBACK(icon_destroy), this);
+            g_signal_connect(m_eggTrayIcon, "button_press_event",
+                G_CALLBACK(icon_button_press_event), m_taskBarIcon);
+            g_signal_connect(m_eggTrayIcon, "popup_menu",
+                G_CALLBACK(icon_popup_menu), m_taskBarIcon);
+            GtkWidget* image = gtk_image_new_from_pixbuf(m_bitmap.GetPixbuf());
+            gtk_container_add(GTK_CONTAINER(m_eggTrayIcon), image);
+            gtk_widget_show_all(m_eggTrayIcon);
+        }
+    }
+#if wxUSE_TOOLTIPS
+    const char* tip_text = NULL;
+    if (!m_tipText.empty())
+        tip_text = m_tipText;
+
+#if GTK_CHECK_VERSION(2,10,0)
+    if (m_statusIcon)
+        gtk_status_icon_set_tooltip(m_statusIcon, tip_text);
+    else
+#endif
+    {
+        if (tip_text && m_tooltips == NULL)
+        {
+            m_tooltips = gtk_tooltips_new();
+            g_object_ref(m_tooltips);
+            gtk_object_sink(GTK_OBJECT(m_tooltips));
+        }
+        if (m_tooltips)
+            gtk_tooltips_set_tip(m_tooltips, m_eggTrayIcon, tip_text, "");
+    }
+#endif // wxUSE_TOOLTIPS
+}
+
+void wxTaskBarIcon::Private::size_allocate(int width, int height)
+{
+    int size = height;
+    EggTrayIcon* icon = EGG_TRAY_ICON(m_eggTrayIcon);
+    if (egg_tray_icon_get_orientation(icon) == GTK_ORIENTATION_VERTICAL)
+        size = width;
+    if (m_size == size)
+        return;
+    m_size = size;
+    int w = m_bitmap.GetWidth();
+    int h = m_bitmap.GetHeight();
+    if (w > size || h > size)
+    {
+        if (w > size) w = size;
+        if (h > size) h = size;
+        GdkPixbuf* pixbuf =
+            gdk_pixbuf_scale_simple(m_bitmap.GetPixbuf(), w, h, GDK_INTERP_BILINEAR);
+        GtkImage* image = GTK_IMAGE(GTK_BIN(m_eggTrayIcon)->child);
+        gtk_image_set_from_pixbuf(image, pixbuf);
+        g_object_unref(pixbuf);
+    }
+}
 //-----------------------------------------------------------------------------
 
-#if wxUSE_MENUS_NATIVE
-void wxTaskBarIconAreaBase::DoPopupMenuUpdateUI(wxMenu* menu)
+IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
+
+wxTaskBarIcon::wxTaskBarIcon()
+{
+    m_priv = new Private(this);
+}
+
+wxTaskBarIcon::~wxTaskBarIcon()
+{
+    delete m_priv;
+}
+
+bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
+{
+    m_priv->m_bitmap = icon;
+    m_priv->m_tipText = tooltip;
+    m_priv->SetIcon();
+    return true;
+}
+
+bool wxTaskBarIcon::RemoveIcon()
+{
+    delete m_priv;
+    m_priv = new Private(this);
+    return true;
+}
+
+bool wxTaskBarIcon::IsIconInstalled() const
 {
-    menu->UpdateUI(m_invokingWindow);
+    return m_priv->m_statusIcon || m_priv->m_eggTrayIcon;
 }
-#endif // wxUSE_MENUS_NATIVE
+
+bool wxTaskBarIcon::PopupMenu(wxMenu* menu)
+{
+#if wxUSE_MENUS
+    if (m_priv->m_win == NULL)
+    {
+        m_priv->m_win = new wxTopLevelWindow(
+            NULL, wxID_ANY, wxString(), wxDefaultPosition, wxDefaultSize, 0);
+        m_priv->m_win->PushEventHandler(this);
+    }
+    wxPoint point(-1, -1);
+#ifdef __WXUNIVERSAL__
+    point = wxGetMousePosition();
+#endif
+    m_priv->m_win->PopupMenu(menu, point);
+#endif // wxUSE_MENUS
+    return true;
+}
+
 #endif // wxUSE_TASKBARICON
index 1f64d565bdce31a914b48610bbaf3b27cbf3567f..b89ba436cb00ecd98187887b6af7f82490f9d871 100644 (file)
@@ -3962,11 +3962,6 @@ void wxPopupMenuPositionCallback( GtkMenu *menu,
 }
 }
 
-void wxWindowGTK::DoPopupMenuUpdateUI(wxMenu* menu)
-{
-    menu->UpdateUI();
-}
-
 bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 {
     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
@@ -3975,7 +3970,7 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 
     SetInvokingWindow( menu, this );
 
-    DoPopupMenuUpdateUI(menu);
+    menu->UpdateUI();
 
     wxPoint pos;
     gpointer userdata;
index 385f05d46f9ec7f367a26e48c8aaf10c2fad2f27..0978d60c1acb190599b2638afc2db73b1c77fe17 100644 (file)
@@ -21,7 +21,7 @@
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
-#if wxUSE_TASKBARICON
+#if wxUSE_TASKBARICON && !defined(__WXGTK20__)
 
 #include "wx/taskbar.h"
 
 // base class that implements toolkit-specific method:
 // ----------------------------------------------------------------------------
 
-#ifdef __WXGTK20__
-    #include <gtk/gtk.h>
-    #if GTK_CHECK_VERSION(2,1,0)
-        #include "wx/gtk/taskbarpriv.h"
-        #define TASKBAR_ICON_AREA_BASE_INCLUDED
-    #endif
-#endif
-
-#ifndef TASKBAR_ICON_AREA_BASE_INCLUDED
     class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxFrame
     {
     public:
 
         static bool IsProtocolSupported() { return false; }
     };
-#endif
-
 
 // ----------------------------------------------------------------------------
 // toolkit dependent methods to set properties on helper window:
 // ----------------------------------------------------------------------------
 
 #if defined(__WXGTK__)
-    #include <gdk/gdk.h>
-    #include <gdk/gdkx.h>
     #include <gtk/gtk.h>
+    #include <gdk/gdkx.h>
     #define GetDisplay()        GDK_DISPLAY()
     #define GetXWindow(wxwin)   GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
 #elif defined(__WXX11__) || defined(__WXMOTIF__)
@@ -126,10 +114,6 @@ END_EVENT_TABLE()
 wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp)
     : wxTaskBarIconAreaBase(), m_icon(icon), m_bmp(bmp)
 {
-#if defined(__WXGTK20__) && defined(TASKBAR_ICON_AREA_BASE_INCLUDED)
-    m_invokingWindow = icon;
-#endif
-
     // Set initial size to bitmap size (tray manager may and often will
     // change it):
     SetClientSize(wxSize(bmp.GetWidth(), bmp.GetHeight()));