]> git.saurik.com Git - wxWidgets.git/blame - src/unix/taskbarx11.cpp
#9675: wxDataViewModel::Reset() and scrollbar problem (wxMac)
[wxWidgets.git] / src / unix / taskbarx11.cpp
CommitLineData
fb29dcac 1/////////////////////////////////////////////////////////////////////////
7fc65a03 2// File: src/unix/taskbarx11.cpp
fb29dcac
VS
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
65571936 9// Licence: wxWindows licence
fb29dcac
VS
10/////////////////////////////////////////////////////////////////////////
11
fb29dcac 12// NB: This implementation does *not* work with every X11 window manager.
33d4eef0
VS
13// Currently only GNOME 1.2 and KDE 1,2,3 methods are implemented here.
14// Freedesktop.org's System Tray specification is implemented in
15// src/gtk/taskbar.cpp and used from here under wxGTK.
fb29dcac
VS
16//
17// Thanks to Ian Campbell, author of XMMS Status Docklet, for publishing
18// KDE and GNOME 1.2 methods.
19
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
4f167b46 24#if wxUSE_TASKBARICON
f2dc88a0 25
fb29dcac 26#include "wx/taskbar.h"
e4db172a
WS
27
28#ifndef WX_PRECOMP
29 #include "wx/log.h"
76b49cf4 30 #include "wx/frame.h"
ed4b0fdc 31 #include "wx/dcclient.h"
e267406e 32 #include "wx/statbmp.h"
ed2fbeb8 33 #include "wx/sizer.h"
0bca0373 34 #include "wx/bitmap.h"
155ecd4c 35 #include "wx/image.h"
e4db172a
WS
36#endif
37
fb29dcac
VS
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
33d4eef0
VS
47// ----------------------------------------------------------------------------
48// base class that implements toolkit-specific method:
49// ----------------------------------------------------------------------------
50
51#ifdef __WXGTK20__
0304adb1
VS
52 #include <gtk/gtk.h>
53 #if GTK_CHECK_VERSION(2,1,0)
54 #include "wx/gtk/taskbarpriv.h"
55 #define TASKBAR_ICON_AREA_BASE_INCLUDED
56 #endif
57#endif
58
59#ifndef TASKBAR_ICON_AREA_BASE_INCLUDED
33d4eef0
VS
60 class WXDLLIMPEXP_ADV wxTaskBarIconAreaBase : public wxFrame
61 {
62 public:
63 wxTaskBarIconAreaBase()
64 : wxFrame(NULL, wxID_ANY, _T("systray icon"),
65 wxDefaultPosition, wxDefaultSize,
66 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR |
67 wxSIMPLE_BORDER | wxFRAME_SHAPED) {}
68
69 bool IsProtocolSupported() const { return false; }
70 };
71#endif
72
73
fb29dcac
VS
74// ----------------------------------------------------------------------------
75// toolkit dependent methods to set properties on helper window:
76// ----------------------------------------------------------------------------
77
78#if defined(__WXGTK__)
79 #include <gdk/gdk.h>
80 #include <gdk/gdkx.h>
81 #include <gtk/gtk.h>
82 #define GetDisplay() GDK_DISPLAY()
83 #define GetXWindow(wxwin) GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
84#elif defined(__WXX11__) || defined(__WXMOTIF__)
85 #include "wx/x11/privx.h"
86 #define GetDisplay() ((Display*)wxGlobalDisplay())
87 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
88#else
89 #error "You must define X11 accessors for this port!"
90#endif
91
7fc65a03 92
fb29dcac 93// ----------------------------------------------------------------------------
ac258944 94// wxTaskBarIconArea is the real window that shows the icon:
fb29dcac
VS
95// ----------------------------------------------------------------------------
96
33d4eef0 97class WXDLLIMPEXP_ADV wxTaskBarIconArea : public wxTaskBarIconAreaBase
ac258944
VS
98{
99public:
33d4eef0
VS
100 wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp);
101 void SetTrayIcon(const wxBitmap& bmp);
ac258944 102 bool IsOk() { return true; }
7fc65a03 103
ac258944 104protected:
33d4eef0 105 void SetLegacyWMProperties();
7fc65a03 106
33d4eef0 107 void OnSizeChange(wxSizeEvent& event);
ac258944 108 void OnPaint(wxPaintEvent& evt);
ac258944
VS
109 void OnMouseEvent(wxMouseEvent& event);
110 void OnMenuEvent(wxCommandEvent& event);
111
112 wxTaskBarIcon *m_icon;
33d4eef0
VS
113 wxPoint m_pos;
114 wxBitmap m_bmp;
7fc65a03 115
ac258944
VS
116 DECLARE_EVENT_TABLE()
117};
118
33d4eef0
VS
119BEGIN_EVENT_TABLE(wxTaskBarIconArea, wxTaskBarIconAreaBase)
120 EVT_SIZE(wxTaskBarIconArea::OnSizeChange)
ac258944 121 EVT_MOUSE_EVENTS(wxTaskBarIconArea::OnMouseEvent)
e267406e 122 EVT_MENU(wxID_ANY, wxTaskBarIconArea::OnMenuEvent)
ac258944 123 EVT_PAINT(wxTaskBarIconArea::OnPaint)
ac258944 124END_EVENT_TABLE()
7fc65a03 125
33d4eef0 126wxTaskBarIconArea::wxTaskBarIconArea(wxTaskBarIcon *icon, const wxBitmap &bmp)
66ddd8d2 127 : wxTaskBarIconAreaBase(), m_icon(icon), m_bmp(bmp)
33d4eef0 128{
95fd7c35 129#if defined(__WXGTK20__) && defined(TASKBAR_ICON_AREA_BASE_INCLUDED)
0bd3b8ec
RR
130 m_invokingWindow = icon;
131#endif
7fc65a03 132
33d4eef0
VS
133 // Set initial size to bitmap size (tray manager may and often will
134 // change it):
1dd7badd 135 SetClientSize(wxSize(bmp.GetWidth(), bmp.GetHeight()));
7fc65a03 136
33d4eef0 137 SetTrayIcon(bmp);
7d8e5b8f
PC
138
139 if (!IsProtocolSupported())
140 {
141 wxLogTrace(_T("systray"),
142 _T("using legacy KDE1,2 and GNOME 1.2 methods"));
143 SetLegacyWMProperties();
144 }
33d4eef0
VS
145}
146
147void wxTaskBarIconArea::SetTrayIcon(const wxBitmap& bmp)
148{
149 m_bmp = bmp;
7fc65a03 150
33d4eef0 151 // determine suitable bitmap size:
1dd7badd 152 wxSize winsize(GetClientSize());
33d4eef0 153 wxSize bmpsize(m_bmp.GetWidth(), m_bmp.GetHeight());
fe3d568d 154 wxSize iconsize(wxMin(winsize.x, bmpsize.x), wxMin(winsize.y, bmpsize.y));
33d4eef0
VS
155
156 // rescale the bitmap to fit into the tray icon window:
157 if (bmpsize != iconsize)
158 {
159 wxImage img = m_bmp.ConvertToImage();
160 img.Rescale(iconsize.x, iconsize.y);
161 m_bmp = wxBitmap(img);
162 }
ac258944 163
eb03e0e7 164 wxRegion region;
85f6b408 165 region.Union(m_bmp);
33d4eef0
VS
166
167 // if the bitmap is smaller than the window, offset it:
168 if (winsize != iconsize)
169 {
170 m_pos.x = (winsize.x - iconsize.x) / 2;
171 m_pos.y = (winsize.y - iconsize.y) / 2;
172 region.Offset(m_pos.x, m_pos.y);
173 }
174
175 // set frame's shape to correct value and redraw:
176 SetShape(region);
177 Refresh();
178}
179
180void wxTaskBarIconArea::SetLegacyWMProperties()
7fc65a03 181{
fb29dcac 182#ifdef __WXGTK__
ac258944 183 gtk_widget_realize(m_widget);
fb29dcac 184#endif
7fc65a03 185
fb29dcac 186 long data[1];
7fc65a03 187
fb29dcac
VS
188 // KDE 2 & KDE 3:
189 Atom _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR =
190 XInternAtom(GetDisplay(), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
191 data[0] = 0;
ac258944 192 XChangeProperty(GetDisplay(), GetXWindow(this),
fb29dcac
VS
193 _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR,
194 XA_WINDOW, 32,
195 PropModeReplace, (unsigned char*)data, 1);
196
197 // GNOME 1.2 & KDE 1:
198 Atom KWM_DOCKWINDOW =
199 XInternAtom(GetDisplay(), "KWM_DOCKWINDOW", False);
200 data[0] = 1;
ac258944 201 XChangeProperty(GetDisplay(), GetXWindow(this),
fb29dcac
VS
202 KWM_DOCKWINDOW,
203 KWM_DOCKWINDOW, 32,
204 PropModeReplace, (unsigned char*)data, 1);
fb29dcac 205}
7fc65a03
WS
206
207void wxTaskBarIconArea::OnSizeChange(wxSizeEvent& WXUNUSED(event))
fb29dcac 208{
33d4eef0
VS
209 wxLogTrace(_T("systray"), _T("icon size changed to %i x %i"),
210 GetSize().x, GetSize().y);
211 // rescale or reposition the icon as needed:
212 wxBitmap bmp(m_bmp);
213 SetTrayIcon(bmp);
ac258944 214}
fb29dcac 215
ac258944
VS
216void wxTaskBarIconArea::OnPaint(wxPaintEvent& WXUNUSED(event))
217{
218 wxPaintDC dc(this);
33d4eef0 219 dc.DrawBitmap(m_bmp, m_pos.x, m_pos.y, true);
ac258944 220}
7fc65a03 221
fb29dcac
VS
222void wxTaskBarIconArea::OnMouseEvent(wxMouseEvent& event)
223{
224 wxEventType type = 0;
225 wxEventType mtype = event.GetEventType();
33d4eef0 226
fb29dcac
VS
227 if (mtype == wxEVT_LEFT_DOWN)
228 type = wxEVT_TASKBAR_LEFT_DOWN;
229 else if (mtype == wxEVT_LEFT_UP)
230 type = wxEVT_TASKBAR_LEFT_UP;
231 else if (mtype == wxEVT_LEFT_DCLICK)
232 type = wxEVT_TASKBAR_LEFT_DCLICK;
233 else if (mtype == wxEVT_RIGHT_DOWN)
234 type = wxEVT_TASKBAR_RIGHT_DOWN;
235 else if (mtype == wxEVT_RIGHT_UP)
236 type = wxEVT_TASKBAR_RIGHT_UP;
237 else if (mtype == wxEVT_RIGHT_DCLICK)
238 type = wxEVT_TASKBAR_RIGHT_DCLICK;
239 else if (mtype == wxEVT_MOTION)
240 type = wxEVT_TASKBAR_MOVE;
241 else
242 return;
243
244 wxTaskBarIconEvent e(type, m_icon);
245 m_icon->ProcessEvent(e);
246}
247
248void wxTaskBarIconArea::OnMenuEvent(wxCommandEvent& event)
7fc65a03 249{
fb29dcac
VS
250 m_icon->ProcessEvent(event);
251}
252
253// ----------------------------------------------------------------------------
254// wxTaskBarIcon class:
255// ----------------------------------------------------------------------------
256
257IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
258
259wxTaskBarIcon::wxTaskBarIcon() : m_iconWnd(NULL)
260{
261}
262
263wxTaskBarIcon::~wxTaskBarIcon()
264{
265 if (m_iconWnd)
b6819de8 266 {
143f8075
PC
267 m_iconWnd->Disconnect(
268 wxEVT_DESTROY, wxObjectEventFunction(NULL), NULL, this);
fb29dcac 269 RemoveIcon();
b6819de8 270 }
fb29dcac
VS
271}
272
273bool wxTaskBarIcon::IsOk() const
274{
275 return true;
276}
277
278bool wxTaskBarIcon::IsIconInstalled() const
279{
280 return m_iconWnd != NULL;
281}
282
3abc7566
PC
283// Destroy event from wxTaskBarIconArea
284void wxTaskBarIcon::OnDestroy(wxWindowDestroyEvent&)
285{
286 // prevent crash if wxTaskBarIconArea is destroyed by something else,
287 // for example if panel/kicker is killed
288 m_iconWnd = NULL;
289}
290
fb29dcac
VS
291bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
292{
fb29dcac
VS
293 wxBitmap bmp;
294 bmp.CopyFromIcon(icon);
ac258944 295
33d4eef0 296 if (!m_iconWnd)
fb29dcac 297 {
33d4eef0
VS
298 m_iconWnd = new wxTaskBarIconArea(this, bmp);
299 if (m_iconWnd->IsOk())
300 {
3abc7566
PC
301 m_iconWnd->Connect(wxEVT_DESTROY,
302 wxWindowDestroyEventHandler(wxTaskBarIcon::OnDestroy),
303 NULL, this);
33d4eef0
VS
304 m_iconWnd->Show();
305 }
306 else
307 {
308 m_iconWnd->Destroy();
309 m_iconWnd = NULL;
310 return false;
311 }
fb29dcac
VS
312 }
313 else
314 {
33d4eef0 315 m_iconWnd->SetTrayIcon(bmp);
7fc65a03
WS
316 }
317
33d4eef0
VS
318#if wxUSE_TOOLTIPS
319 if (!tooltip.empty())
320 m_iconWnd->SetToolTip(tooltip);
321 else
322 m_iconWnd->SetToolTip(NULL);
7fc65a03
WS
323#else
324 wxUnusedVar(tooltip);
33d4eef0
VS
325#endif
326 return true;
fb29dcac
VS
327}
328
329bool wxTaskBarIcon::RemoveIcon()
330{
331 if (!m_iconWnd)
332 return false;
333 m_iconWnd->Destroy();
334 m_iconWnd = NULL;
335 return true;
336}
337
338bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
339{
340 if (!m_iconWnd)
341 return false;
971562cb 342 m_iconWnd->PopupMenu(menu);
fb29dcac
VS
343 return true;
344}
f2dc88a0 345
4f167b46 346#endif // wxUSE_TASKBARICON