| 1 | ///////////////////////////////////////////////////////////////////////// |
| 2 | // File: taskbar.cpp |
| 3 | // Purpose: wxTaskBarIcon (src/unix/taskbarx11.cpp) helper for GTK2 |
| 4 | // Author: Vaclav Slavik |
| 5 | // Modified by: |
| 6 | // Created: 2004/05/29 |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) Vaclav Slavik, 2004 |
| 9 | // Licence: wxWindows licence |
| 10 | ///////////////////////////////////////////////////////////////////////// |
| 11 | |
| 12 | #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) |
| 13 | #pragma implementation "taskbarpriv.h" |
| 14 | #endif |
| 15 | |
| 16 | // For compilers that support precompilation, includes "wx.h". |
| 17 | #include "wx/wxprec.h" |
| 18 | |
| 19 | #include "wx/gtk/taskbarpriv.h" |
| 20 | #include "wx/log.h" |
| 21 | #include "wx/frame.h" |
| 22 | #include "wx/menu.h" |
| 23 | |
| 24 | #include <gdk/gdkx.h> |
| 25 | |
| 26 | #ifdef __WXGTK20__ |
| 27 | #include <gtk/gtkversion.h> |
| 28 | #if GTK_CHECK_VERSION(2, 1, 0) |
| 29 | |
| 30 | #include "gtk/gtk.h" |
| 31 | |
| 32 | #include "eggtrayicon.h" |
| 33 | |
| 34 | wxTaskBarIconAreaBase::wxTaskBarIconAreaBase() |
| 35 | { |
| 36 | if (IsProtocolSupported()) |
| 37 | { |
| 38 | m_widget = GTK_WIDGET(egg_tray_icon_new("systray icon")); |
| 39 | gtk_window_set_resizable(GTK_WINDOW(m_widget), false); |
| 40 | |
| 41 | wxLogTrace(_T("systray"), _T("using freedesktop.org systray spec")); |
| 42 | } |
| 43 | |
| 44 | wxTopLevelWindow::Create( |
| 45 | NULL, wxID_ANY, _T("systray icon"), |
| 46 | wxDefaultPosition, wxDefaultSize, |
| 47 | wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR | wxSIMPLE_BORDER | |
| 48 | wxFRAME_SHAPED, |
| 49 | wxEmptyString /*eggtray doesn't like setting wmclass*/); |
| 50 | |
| 51 | m_invokingWindow = NULL; |
| 52 | } |
| 53 | |
| 54 | bool wxTaskBarIconAreaBase::IsProtocolSupported() |
| 55 | { |
| 56 | static int s_supported = -1; |
| 57 | if (s_supported == -1) |
| 58 | { |
| 59 | Display *display = GDK_DISPLAY(); |
| 60 | Screen *screen = DefaultScreenOfDisplay(display); |
| 61 | |
| 62 | wxString name; |
| 63 | name.Printf(_T("_NET_SYSTEM_TRAY_S%d"), XScreenNumberOfScreen(screen)); |
| 64 | Atom atom = XInternAtom(display, name.ToAscii(), False); |
| 65 | |
| 66 | Window manager = XGetSelectionOwner(display, atom); |
| 67 | |
| 68 | s_supported = (manager != None); |
| 69 | } |
| 70 | |
| 71 | return (bool)s_supported; |
| 72 | } |
| 73 | |
| 74 | //----------------------------------------------------------------------------- |
| 75 | // Pop-up menu stuff |
| 76 | //----------------------------------------------------------------------------- |
| 77 | |
| 78 | extern "C" void gtk_pop_hide_callback( GtkWidget *widget, bool* is_waiting ); |
| 79 | |
| 80 | extern void SetInvokingWindow( wxMenu *menu, wxWindow* win ); |
| 81 | |
| 82 | extern "C" void wxPopupMenuPositionCallback( GtkMenu *menu, |
| 83 | gint *x, gint *y, |
| 84 | gboolean * WXUNUSED(whatever), |
| 85 | gpointer user_data ); |
| 86 | |
| 87 | #if wxUSE_MENUS_NATIVE |
| 88 | bool wxTaskBarIconAreaBase::DoPopupMenu( wxMenu *menu, int x, int y ) |
| 89 | { |
| 90 | wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") ); |
| 91 | |
| 92 | wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") ); |
| 93 | |
| 94 | // NOTE: if you change this code, you need to update |
| 95 | // the same code in window.cpp as well. This |
| 96 | // is ugly code duplication, I know, |
| 97 | |
| 98 | SetInvokingWindow( menu, this ); |
| 99 | |
| 100 | menu->UpdateUI( m_invokingWindow ); |
| 101 | |
| 102 | bool is_waiting = true; |
| 103 | |
| 104 | gulong handler = gtk_signal_connect( GTK_OBJECT(menu->m_menu), |
| 105 | "hide", |
| 106 | GTK_SIGNAL_FUNC(gtk_pop_hide_callback), |
| 107 | (gpointer)&is_waiting ); |
| 108 | |
| 109 | wxPoint pos; |
| 110 | gpointer userdata; |
| 111 | GtkMenuPositionFunc posfunc; |
| 112 | if ( x == -1 && y == -1 ) |
| 113 | { |
| 114 | // use GTK's default positioning algorithm |
| 115 | userdata = NULL; |
| 116 | posfunc = NULL; |
| 117 | } |
| 118 | else |
| 119 | { |
| 120 | pos = ClientToScreen(wxPoint(x, y)); |
| 121 | userdata = &pos; |
| 122 | posfunc = wxPopupMenuPositionCallback; |
| 123 | } |
| 124 | |
| 125 | gtk_menu_popup( |
| 126 | GTK_MENU(menu->m_menu), |
| 127 | (GtkWidget *) NULL, // parent menu shell |
| 128 | (GtkWidget *) NULL, // parent menu item |
| 129 | posfunc, // function to position it |
| 130 | userdata, // client data |
| 131 | 0, // button used to activate it |
| 132 | gtk_get_current_event_time() |
| 133 | ); |
| 134 | |
| 135 | while (is_waiting) |
| 136 | { |
| 137 | gtk_main_iteration(); |
| 138 | } |
| 139 | |
| 140 | gtk_signal_disconnect(GTK_OBJECT(menu->m_menu), handler); |
| 141 | |
| 142 | return true; |
| 143 | } |
| 144 | #endif // wxUSE_MENUS_NATIVE |
| 145 | |
| 146 | #endif // __WXGTK20__ |
| 147 | #endif // GTK_CHECK_VERSION(2, 1, 0) |