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