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