summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Ewmh.cc72
1 files changed, 58 insertions, 14 deletions
diff --git a/src/Ewmh.cc b/src/Ewmh.cc
index 14c74c6..2a9e1ab 100644
--- a/src/Ewmh.cc
+++ b/src/Ewmh.cc
@@ -76,16 +76,30 @@ namespace {
76 * byte being B. The first two cardinals are width, height. Data is in rows, 76 * byte being B. The first two cardinals are width, height. Data is in rows,
77 * left to right and top to bottom. 77 * left to right and top to bottom.
78 * 78 *
79 ***
80 *
81 * NOTE: the returned data for XA_CARDINAL is long if the rfmt equals
82 * 32. sizeof(long) on 64bit machines is 8. to quote from
83 * "man XGetWindowProperty":
84 *
85 * If the returned format is 32, the property data will be stored as
86 * an array of longs (which in a 64-bit application will be 64-bit
87 * values that are padded in the upper 4 bytes).
88 *
89 * this is especially true on 64bit machines when some of the clients
90 * (eg: tvtime, konqueror3) have problems to feed in the right data
91 * into the _NET_WM_ICON property. we faced some segfaults because
92 * width and height were not quite right because of ignoring 64bit
93 * behaviour on client side.
94 *
79 * TODO: maybe move the pixmap-creation code to FbTk? */ 95 * TODO: maybe move the pixmap-creation code to FbTk? */
80void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) { 96void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
81 97
82 typedef std::pair<int, int> Size; 98 typedef std::pair<int, int> Size;
83 typedef std::map<Size, const unsigned long*> IconContainer; 99 typedef std::map<Size, const unsigned long*> IconContainer;
84 100
85 // attention: the returned data for XA_CARDINAL is long if the rfmt equals
86 // 32. sizeof(long) on 64bit machines is 8.
87 unsigned long* raw_data = 0; 101 unsigned long* raw_data = 0;
88 long nr_icon_data = 0; 102 unsigned long nr_icon_data = 0;
89 103
90 { 104 {
91 Atom rtype; 105 Atom rtype;
@@ -106,7 +120,10 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
106 120
107 // actually there is some data in _NET_WM_ICON 121 // actually there is some data in _NET_WM_ICON
108 nr_icon_data = nr_bytes_left / sizeof(CARD32); 122 nr_icon_data = nr_bytes_left / sizeof(CARD32);
109 123#ifdef DEBUG
124 std::cerr << "extractNetWmIcon: " << winclient.title() << "\n";
125 std::cerr << "nr_icon_data: " << nr_icon_data << "\n";
126#endif
110 // read all the icons stored in _NET_WM_ICON 127 // read all the icons stored in _NET_WM_ICON
111 if (raw_data) 128 if (raw_data)
112 XFree(raw_data); 129 XFree(raw_data);
@@ -118,30 +135,57 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
118 135
119 return; 136 return;
120 } 137 }
138#ifdef DEBUG
139 std::cerr << "nr_read: " << nr_read << "|" << nr_bytes_left << "\n";
140#endif
121 } 141 }
122 142
123 IconContainer icon_data; // stores all available data, sorted by size (width x height) 143 IconContainer icon_data; // stores all available data, sorted by size (width x height)
124 int width; 144 unsigned long width;
125 int height; 145 unsigned long height;
126 146
127 // analyze the available icons 147 // analyze the available icons
128 long i; 148 //
129 149 // check also for invalid values coming in from "bad" applications
150 unsigned long i;
130 for (i = 0; i + 2 < nr_icon_data; i += width * height ) { 151 for (i = 0; i + 2 < nr_icon_data; i += width * height ) {
131 152
132 width = raw_data[i++]; 153 width = raw_data[i++];
154 if (width >= nr_icon_data) {
155#ifdef DEBUG
156 std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON width ("
157 << width << ") for " << winclient.title() << "\n";
158#endif
159 break;
160 }
161
133 height = raw_data[i++]; 162 height = raw_data[i++];
163 if (height >= nr_icon_data) {
164#ifdef DEBUG
165 std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON height ("
166 << height << ") for " << winclient.title() << "\n";
167#endif
168 break;
169 }
134 170
135 // strange values stored in the NETWM_ICON 171 // strange values stored in the NETWM_ICON
136 if (width <= 0 || height <= 0 || i + width * height > nr_icon_data) { 172 if (i + width * height > nr_icon_data) {
137 std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON dimensions for " << winclient.title() << "\n"; 173#ifdef DEBUG
138 XFree(raw_data); 174 std::cerr << "Ewmh.cc extractNetWmIcon found strange _NET_WM_ICON dimensions ("
139 return; 175 << width << "x" << height << ")for " << winclient.title() << "\n";
176#endif
177 break;
140 } 178 }
141 179
142 icon_data[Size(width, height)] = &raw_data[i]; 180 icon_data[Size(width, height)] = &raw_data[i];
143 } 181 }
144 182
183 // no valid icons found at all
184 if (icon_data.empty()) {
185 XFree(raw_data);
186 return;
187 }
188
145 Display* dpy = FbTk::App::instance()->display(); 189 Display* dpy = FbTk::App::instance()->display();
146 int scrn = winclient.screen().screenNumber(); 190 int scrn = winclient.screen().screenNumber();
147 191
@@ -178,8 +222,8 @@ void extractNetWmIcon(Atom net_wm_icon, WinClient& winclient) {
178 const unsigned long* src = icon_data.begin()->second; 222 const unsigned long* src = icon_data.begin()->second;
179 unsigned int rgba; 223 unsigned int rgba;
180 unsigned long pixel; 224 unsigned long pixel;
181 int x; 225 unsigned long x;
182 int y; 226 unsigned long y;
183 unsigned char r, g, b, a; 227 unsigned char r, g, b, a;
184 228
185 for (y = 0; y < height; y++) { 229 for (y = 0; y < height; y++) {