| 1 | ///////////////////////////////////////////////////////////////////////// |
| 2 | // File: taskbar.cpp |
| 3 | // Purpose: wxTaskBarIcon class for common Unix desktops |
| 4 | // Author: Vaclav Slavik |
| 5 | // Modified by: |
| 6 | // Created: 04/04/2003 |
| 7 | // RCS-ID: $Id$ |
| 8 | // Copyright: (c) Vaclav Slavik, 2003 |
| 9 | // Licence: wxWindows licence |
| 10 | ///////////////////////////////////////////////////////////////////////// |
| 11 | |
| 12 | #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) |
| 13 | #pragma implementation "taskbarx11.h" |
| 14 | #endif |
| 15 | |
| 16 | |
| 17 | // NB: This implementation does *not* work with every X11 window manager. |
| 18 | // Currently only GNOME 1.2 and KDE 1,2,3 methods are implemented. |
| 19 | // |
| 20 | // FIXME: implement: |
| 21 | // - GNOME 2 support (see www.freedesktop.org for specification; |
| 22 | // KDE 3 uses this method as well, even though legacy KDE |
| 23 | // method we implement works as well) |
| 24 | // - IceWM and XFCE support (?) |
| 25 | // |
| 26 | // Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing |
| 27 | // KDE and GNOME 1.2 methods. |
| 28 | |
| 29 | |
| 30 | // For compilers that support precompilation, includes "wx.h". |
| 31 | #include "wx/wxprec.h" |
| 32 | |
| 33 | #include "wx/taskbar.h" |
| 34 | #include "wx/frame.h" |
| 35 | #include "wx/bitmap.h" |
| 36 | #include "wx/statbmp.h" |
| 37 | |
| 38 | #ifdef __VMS |
| 39 | #pragma message disable nosimpint |
| 40 | #endif |
| 41 | #include <X11/Xlib.h> |
| 42 | #include <X11/Xatom.h> |
| 43 | #ifdef __VMS |
| 44 | #pragma message enable nosimpint |
| 45 | #endif |
| 46 | |
| 47 | // ---------------------------------------------------------------------------- |
| 48 | // toolkit dependent methods to set properties on helper window: |
| 49 | // ---------------------------------------------------------------------------- |
| 50 | |
| 51 | #if defined(__WXGTK__) |
| 52 | #include <gdk/gdk.h> |
| 53 | #include <gdk/gdkx.h> |
| 54 | #include <gtk/gtk.h> |
| 55 | #define GetDisplay() GDK_DISPLAY() |
| 56 | #define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window) |
| 57 | #elif defined(__WXX11__) || defined(__WXMOTIF__) |
| 58 | #include "wx/x11/privx.h" |
| 59 | #define GetDisplay() ((Display*)wxGlobalDisplay()) |
| 60 | #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle()) |
| 61 | #else |
| 62 | #error "You must define X11 accessors for this port!" |
| 63 | #endif |
| 64 | |
| 65 | // ---------------------------------------------------------------------------- |
| 66 | // code for making wxFrame a toolbar icon by setting appropriate properties: |
| 67 | // ---------------------------------------------------------------------------- |
| 68 | |
| 69 | static bool wxMakeTaskBarIcon(wxFrame *wnd) |
| 70 | { |
| 71 | #ifdef __WXGTK__ |
| 72 | gtk_widget_realize(wnd->m_widget); |
| 73 | #endif |
| 74 | |
| 75 | long data[1]; |
| 76 | |
| 77 | // KDE 2 & KDE 3: |
| 78 | Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR = |
| 79 | XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False); |
| 80 | data[0] = 0; |
| 81 | XChangeProperty(GetDisplay(), GetXWindow(wnd), |
| 82 | _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR, |
| 83 | XA_WINDOW, 32, |
| 84 | PropModeReplace, (unsigned char*)data, 1); |
| 85 | |
| 86 | // GNOME 1.2 & KDE 1: |
| 87 | Atom KWM_DOCKWINDOW = |
| 88 | XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False); |
| 89 | data[0] = 1; |
| 90 | XChangeProperty(GetDisplay(), GetXWindow(wnd), |
| 91 | KWM_DOCKWINDOW, |
| 92 | KWM_DOCKWINDOW, 32, |
| 93 | PropModeReplace, (unsigned char*)data, 1); |
| 94 | |
| 95 | return true; |
| 96 | } |
| 97 | |
| 98 | // ---------------------------------------------------------------------------- |
| 99 | // wxTaskBarIconArea is the real window that shows the icon: |
| 100 | // ---------------------------------------------------------------------------- |
| 101 | |
| 102 | class wxTaskBarIconArea : public wxStaticBitmap |
| 103 | { |
| 104 | public: |
| 105 | wxTaskBarIconArea(wxTaskBarIcon *icon, |
| 106 | wxWindow *parent, const wxBitmap &bmp) |
| 107 | : wxStaticBitmap(parent, -1, bmp), m_icon(icon) {} |
| 108 | |
| 109 | protected: |
| 110 | void OnMouseEvent(wxMouseEvent& event); |
| 111 | void OnMenuEvent(wxCommandEvent& event); |
| 112 | |
| 113 | wxTaskBarIcon *m_icon; |
| 114 | |
| 115 | DECLARE_EVENT_TABLE() |
| 116 | }; |
| 117 | |
| 118 | BEGIN_EVENT_TABLE(wxTaskBarIconArea, wxStaticBitmap) |
| 119 | EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent) |
| 120 | EVT_MENU(-1, wxTaskBarIconArea::OnMenuEvent) |
| 121 | END_EVENT_TABLE() |
| 122 | |
| 123 | void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent& event) |
| 124 | { |
| 125 | wxEventType type = 0; |
| 126 | wxEventType mtype = event.GetEventType(); |
| 127 | |
| 128 | if (mtype == wxEVT_LEFT_DOWN) |
| 129 | type = wxEVT_TASKBAR_LEFT_DOWN; |
| 130 | else if (mtype == wxEVT_LEFT_UP) |
| 131 | type = wxEVT_TASKBAR_LEFT_UP; |
| 132 | else if (mtype == wxEVT_LEFT_DCLICK) |
| 133 | type = wxEVT_TASKBAR_LEFT_DCLICK; |
| 134 | else if (mtype == wxEVT_RIGHT_DOWN) |
| 135 | type = wxEVT_TASKBAR_RIGHT_DOWN; |
| 136 | else if (mtype == wxEVT_RIGHT_UP) |
| 137 | type = wxEVT_TASKBAR_RIGHT_UP; |
| 138 | else if (mtype == wxEVT_RIGHT_DCLICK) |
| 139 | type = wxEVT_TASKBAR_RIGHT_DCLICK; |
| 140 | else if (mtype == wxEVT_MOTION) |
| 141 | type = wxEVT_TASKBAR_MOVE; |
| 142 | else |
| 143 | return; |
| 144 | |
| 145 | wxTaskBarIconEvent e(type, m_icon); |
| 146 | m_icon->ProcessEvent(e); |
| 147 | } |
| 148 | |
| 149 | void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent& event) |
| 150 | { |
| 151 | m_icon->ProcessEvent(event); |
| 152 | } |
| 153 | |
| 154 | // ---------------------------------------------------------------------------- |
| 155 | // wxTaskBarIcon class: |
| 156 | // ---------------------------------------------------------------------------- |
| 157 | |
| 158 | IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler) |
| 159 | |
| 160 | wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL) |
| 161 | { |
| 162 | } |
| 163 | |
| 164 | wxTaskBarIcon::~wxTaskBarIcon() |
| 165 | { |
| 166 | if (m_iconWnd) |
| 167 | RemoveIcon(); |
| 168 | } |
| 169 | |
| 170 | bool wxTaskBarIcon::IsOk() const |
| 171 | { |
| 172 | return true; |
| 173 | } |
| 174 | |
| 175 | bool wxTaskBarIcon::IsIconInstalled() const |
| 176 | { |
| 177 | return m_iconWnd != NULL; |
| 178 | } |
| 179 | |
| 180 | bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip) |
| 181 | { |
| 182 | if (m_iconWnd) |
| 183 | RemoveIcon(); |
| 184 | |
| 185 | m_iconWnd = new wxFrame(NULL, -1, wxT("taskbar icon"), |
| 186 | wxDefaultPosition, wxDefaultSize, |
| 187 | wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR); |
| 188 | wxBitmap bmp; |
| 189 | bmp.CopyFromIcon(icon); |
| 190 | wxTaskBarIconArea *area = new wxTaskBarIconArea(this, m_iconWnd, bmp); |
| 191 | m_iconWnd->SetClientSize(area->GetSize()); |
| 192 | #if wxUSE_TOOLTIPS |
| 193 | if (!tooltip.empty()) |
| 194 | area->SetToolTip(tooltip); |
| 195 | #endif |
| 196 | if (wxMakeTaskBarIcon(m_iconWnd)) |
| 197 | { |
| 198 | m_iconWnd->Show(); |
| 199 | m_iconArea = area; |
| 200 | return true; |
| 201 | } |
| 202 | else |
| 203 | { |
| 204 | m_iconWnd->Destroy(); |
| 205 | m_iconWnd = NULL; |
| 206 | return false; |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | bool wxTaskBarIcon::RemoveIcon() |
| 211 | { |
| 212 | if (!m_iconWnd) |
| 213 | return false; |
| 214 | m_iconWnd->Destroy(); |
| 215 | m_iconWnd = NULL; |
| 216 | return true; |
| 217 | } |
| 218 | |
| 219 | bool wxTaskBarIcon::PopupMenu(wxMenu *menu) |
| 220 | { |
| 221 | if (!m_iconWnd) |
| 222 | return false; |
| 223 | wxSize size(m_iconArea->GetSize()); |
| 224 | m_iconArea->PopupMenu(menu, size.x/2, size.y/2); |
| 225 | return true; |
| 226 | } |