aboutsummaryrefslogtreecommitdiff
path: root/src/Ewmh.cc
diff options
context:
space:
mode:
authorMathias Gumz <akira at fluxbox dot org>2008-02-24 20:58:24 (GMT)
committerMathias Gumz <akira at fluxbox dot org>2008-02-24 20:58:24 (GMT)
commit46fdf4d1b4043588b057fcc9a03f5f66b6b09354 (patch)
treece3e8f83a78d0909077e8c79dd45c50d23a65b45 /src/Ewmh.cc
parent611b6aa57e34ed8e52cb6b88c9adbafe4d67c6e2 (diff)
downloadfluxbox-46fdf4d1b4043588b057fcc9a03f5f66b6b09354.zip
fluxbox-46fdf4d1b4043588b057fcc9a03f5f66b6b09354.tar.bz2
use _NET_WM_ICON property as resource for icons, fixed partly #1852693
instead of depending on proper icons in the old icccm wmhints, fluxbox now tries to get the icon data stored in _NET_WM_ICON
Diffstat (limited to 'src/Ewmh.cc')
-rw-r--r--src/Ewmh.cc155
1 files changed, 154 insertions, 1 deletions
diff --git a/src/Ewmh.cc b/src/Ewmh.cc
index 953d474..9db7777 100644
--- a/src/Ewmh.cc
+++ b/src/Ewmh.cc
@@ -35,7 +35,9 @@
35#include "FbTk/I18n.hh" 35#include "FbTk/I18n.hh"
36#include "FbTk/XLayerItem.hh" 36#include "FbTk/XLayerItem.hh"
37#include "FbTk/XLayer.hh" 37#include "FbTk/XLayer.hh"
38#include "FbTk/FbPixmap.hh"
38 39
40#include <X11/Xproto.h>
39#include <X11/Xatom.h> 41#include <X11/Xatom.h>
40#include <iostream> 42#include <iostream>
41#include <algorithm> 43#include <algorithm>
@@ -59,6 +61,149 @@ using std::list;
59#endif 61#endif
60 62
61 63
64namespace {
65
66/* From Extended Window Manager Hints, draft 1.3:
67 *
68 * _NET_WM_ICON CARDINAL[][2+n]/32
69 *
70 * This is an array of possible icons for the client. This specification does
71 * not stipulate what size these icons should be, but individual desktop
72 * environments or toolkits may do so. The Window Manager MAY scale any of
73 * these icons to an appropriate size.
74 *
75 * This is an array of 32bit packed CARDINAL ARGB with high byte being A, low
76 * byte being B. The first two cardinals are width, height. Data is in rows,
77 * left to right and top to bottom.
78 */
79void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
80
81 typedef std::pair<int, int> Size;
82 typedef std::map<Size, const unsigned long*> IconContainer;
83
84 // attention: the returned data for XA_CARDINAL is long if the rfmt equals
85 // 32. sizeof(long) on 64bit machines is 8.
86 unsigned long* raw_data = 0;
87 long nr_icon_data = 0;
88
89 {
90 Atom rtype;
91 int rfmt;
92 unsigned long nr_read;
93 unsigned long nr_bytes_left;
94
95 // no data or no _NET_WM_ICON
96 if (! winclient.property(net_wm_icon, 0L, 0L, False, XA_CARDINAL,
97 &rtype, &rfmt, &nr_read, &nr_bytes_left,
98 reinterpret_cast<unsigned char**>(&raw_data)) || nr_bytes_left == 0) {
99
100 if (raw_data)
101 XFree(raw_data);
102
103 return;
104 }
105
106 // actually there is some data in _NET_WM_ICON
107 nr_icon_data = nr_bytes_left / sizeof(CARD32);
108
109 // read all the icons stored in _NET_WM_ICON
110 winclient.property(net_wm_icon, 0L, nr_icon_data, False, XA_CARDINAL,
111 &rtype, &rfmt, &nr_read, &nr_bytes_left,
112 reinterpret_cast<unsigned char**>(&raw_data));
113 }
114
115 IconContainer icon_data; // stores all available data, sorted by size (width x height)
116 int width;
117 int height;
118
119 // analyze the available icons
120 long i;
121 for (i = 0; i < nr_icon_data; i += width * height ) {
122
123 width = raw_data[i++];
124 height = raw_data[i++];
125
126 icon_data[Size(width, height)] = &raw_data[i];
127 }
128
129 Display* dpy = FbTk::App::instance()->display();
130 int scrn = winclient.screen().screenNumber();
131
132 // pick the smallest icon size atm
133 // TODO: find a better criteria
134 width = icon_data.begin()->first.first;
135 height = icon_data.begin()->first.second;
136
137 // tmp image for the pixmap
138 XImage* img_pm = XCreateImage(dpy, DefaultVisual(dpy, scrn), winclient.depth(),
139 ZPixmap,
140 0, NULL, width, height, 32, 0);
141 if (!img_pm) {
142 XFree(raw_data);
143 return;
144 }
145
146 // tmp image for the mask
147 XImage* img_mask = XCreateImage(dpy, DefaultVisual(dpy, scrn), 1,
148 XYBitmap,
149 0, NULL, width, height, 32, 0);
150
151 if (!img_mask) {
152 XFree(raw_data);
153 XDestroyImage(img_pm);
154 return;
155 }
156
157 // allocate some memory for the icons at client side
158 img_pm->data = new char[img_pm->bytes_per_line * height];
159 img_mask->data = new char[img_mask->bytes_per_line * height];
160
161
162 const unsigned long* src = icon_data.begin()->second;
163 unsigned int pixel;
164 int x;
165 int y;
166 unsigned char r, g, b, a;
167
168 for (y = 0; y < height; y++) {
169 for (x = 0; x < width; x++, src++) {
170
171 pixel = *src; // use only 32bit
172
173 a = ( pixel & 0xff000000 ) >> 24;
174 r = ( pixel & 0x00ff0000 ) >> 16;
175 g = ( pixel & 0x0000ff00 ) >> 8;
176 b = ( pixel & 0x000000ff );
177
178 // transfer color data
179 XPutPixel(img_pm, x, y, pixel & 0x00ffffff ); // TODO: this only works in 24bit depth
180
181 // transfer mask data
182 XPutPixel(img_mask, x, y, a > 127 ? 0 : 1);
183 }
184 }
185
186 // the final icon
187 FbTk::PixmapWithMask icon;
188 icon.pixmap() = FbTk::FbPixmap(winclient.drawable(), width, height, winclient.depth());
189 icon.mask() = FbTk::FbPixmap(winclient.drawable(), width, height, 1);
190
191 FbTk::GContext gc_pm(icon.pixmap());
192 FbTk::GContext gc_mask(icon.mask());
193
194 XPutImage(dpy, icon.pixmap().drawable(), gc_pm.gc(), img_pm, 0, 0, 0, 0, width, height);
195 XPutImage(dpy, icon.mask().drawable(), gc_mask.gc(), img_mask, 0, 0, 0, 0, width, height);
196
197 XDestroyImage(img_pm); // also frees img_pm->data
198 XDestroyImage(img_mask); // also frees img_mask->data
199
200 XFree(raw_data);
201
202 winclient.setIcon(icon);
203}
204
205}; // end anonymous namespace
206
62class Ewmh::EwmhAtoms { 207class Ewmh::EwmhAtoms {
63public: 208public:
64 209
@@ -284,6 +429,7 @@ void Ewmh::initForScreen(BScreen &screen) {
284 m_net->wm_strut, 429 m_net->wm_strut,
285 m_net->wm_state, 430 m_net->wm_state,
286 m_net->wm_name, 431 m_net->wm_name,
432 m_net->wm_icon,
287 m_net->wm_icon_name, 433 m_net->wm_icon_name,
288 434
289 // states that we support: 435 // states that we support:
@@ -386,7 +532,11 @@ void Ewmh::setupClient(WinClient &winclient) {
386 Atom ret_type; 532 Atom ret_type;
387 int fmt; 533 int fmt;
388 unsigned long nitems, bytes_after; 534 unsigned long nitems, bytes_after;
389 unsigned char *data = 0; 535 unsigned char* data = 0;
536
537
538 extractNetWmIcon(m_net->wm_icon, winclient);
539
390 540
391 /* From Extended Window Manager Hints, draft 1.3: 541 /* From Extended Window Manager Hints, draft 1.3:
392 * 542 *
@@ -1052,6 +1202,9 @@ bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) {
1052 } else if (the_property == m_net->wm_icon_name) { 1202 } else if (the_property == m_net->wm_icon_name) {
1053 // we don't use icon title, since we don't show icons 1203 // we don't use icon title, since we don't show icons
1054 return true; 1204 return true;
1205 } else if (the_property == m_net->wm_icon) {
1206 extractNetWmIcon(m_net->wm_icon, winclient);
1207 return true;
1055 } 1208 }
1056 1209
1057 return false; 1210 return false;