aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Ewmh.cc155
-rw-r--r--src/WinClient.cc29
-rw-r--r--src/WinClient.hh7
3 files changed, 180 insertions, 11 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;
diff --git a/src/WinClient.cc b/src/WinClient.cc
index b6df606..0295481 100644
--- a/src/WinClient.cc
+++ b/src/WinClient.cc
@@ -358,12 +358,20 @@ void WinClient::updateTitle() {
358 titleSig().notify(); 358 titleSig().notify();
359} 359}
360 360
361void WinClient::setTitle(FbTk::FbString &title) { 361void WinClient::setTitle(const FbTk::FbString &title) {
362 m_title = title; 362 m_title = title;
363 m_title_override = true; 363 m_title_override = true;
364 titleSig().notify(); 364 titleSig().notify();
365} 365}
366 366
367void WinClient::setIcon(const FbTk::PixmapWithMask& pm) {
368
369 m_icon.pixmap().copy(pm.pixmap());
370 m_icon.mask().copy(pm.mask());
371 m_icon_override = true;
372 titleSig().notify();
373}
374
367void WinClient::saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs, int nelements) { 375void WinClient::saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs, int nelements) {
368 changeProperty(FbAtoms::instance()->getFluxboxAttributesAtom(), 376 changeProperty(FbAtoms::instance()->getFluxboxAttributesAtom(),
369 XA_CARDINAL, 32, PropModeReplace, 377 XA_CARDINAL, 32, PropModeReplace,
@@ -429,15 +437,18 @@ void WinClient::updateWMHints() {
429 if (wmhint->flags & WindowGroupHint && !window_group) 437 if (wmhint->flags & WindowGroupHint && !window_group)
430 window_group = wmhint->window_group; 438 window_group = wmhint->window_group;
431 439
432 if ((bool)(wmhint->flags & IconPixmapHint) && wmhint->icon_pixmap != 0) 440 if (! m_icon_override) {
433 m_icon.pixmap().copy(wmhint->icon_pixmap, 0, 0);
434 else
435 m_icon.pixmap().release();
436 441
437 if ((bool)(wmhint->flags & IconMaskHint) && wmhint->icon_mask != 0) 442 if ((bool)(wmhint->flags & IconPixmapHint) && wmhint->icon_pixmap != 0)
438 m_icon.mask().copy(wmhint->icon_mask, 0, 0); 443 m_icon.pixmap().copy(wmhint->icon_pixmap, 0, 0);
439 else 444 else
440 m_icon.mask().release(); 445 m_icon.pixmap().release();
446
447 if ((bool)(wmhint->flags & IconMaskHint) && wmhint->icon_mask != 0)
448 m_icon.mask().copy(wmhint->icon_mask, 0, 0);
449 else
450 m_icon.mask().release();
451 }
441 452
442 if (fbwindow()) { 453 if (fbwindow()) {
443 if (wmhint->flags & XUrgencyHint) { 454 if (wmhint->flags & XUrgencyHint) {
diff --git a/src/WinClient.hh b/src/WinClient.hh
index 4712627..51d5077 100644
--- a/src/WinClient.hh
+++ b/src/WinClient.hh
@@ -59,11 +59,15 @@ public:
59 void updateWMProtocols(); 59 void updateWMProtocols();
60 60
61 // override the title with this 61 // override the title with this
62 void setTitle(FbTk::FbString &title); 62 void setTitle(const FbTk::FbString &title);
63 void updateTitle(); 63 void updateTitle();
64 /// updates transient window information 64 /// updates transient window information
65 void updateTransientInfo(); 65 void updateTransientInfo();
66 66
67 // override the icon with this
68 void setIcon(const FbTk::PixmapWithMask& pm);
69
70 // update some thints
67 void updateMWMHints(); 71 void updateMWMHints();
68 void updateWMHints(); 72 void updateWMHints();
69 void updateWMNormalHints(); 73 void updateWMNormalHints();
@@ -164,6 +168,7 @@ private:
164 int m_win_gravity; 168 int m_win_gravity;
165 169
166 bool m_title_override; 170 bool m_title_override;
171 bool m_icon_override;
167 172
168 Focusable::WindowType m_window_type; 173 Focusable::WindowType m_window_type;
169 MwmHints *m_mwm_hint; 174 MwmHints *m_mwm_hint;