1
// FbPixmap.cc for FbTk - Fluxbox ToolKit
2
// Copyright (c) 2003 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
4
// Permission is hereby granted, free of charge, to any person obtaining a
5
// copy of this software and associated documentation files (the "Software"),
6
// to deal in the Software without restriction, including without limitation
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
// and/or sell copies of the Software, and to permit persons to whom the
9
// Software is furnished to do so, subject to the following conditions:
11
// The above copyright notice and this permission notice shall be included in
12
// all copies or substantial portions of the Software.
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
// DEALINGS IN THE SOFTWARE.
22
// $Id: FbPixmap.cc 4004 2005-05-10 16:29:00Z simonb $
24
#include "FbPixmap.hh"
26
#include "GContext.hh"
27
#include "Transparent.hh"
29
#include <X11/Xutil.h>
30
#include <X11/Xatom.h>
38
Pixmap *FbPixmap::m_root_pixmaps = 0;
40
const char* FbPixmap::root_prop_ids[] = {
46
// same number as in root_prop_ids
47
Atom FbPixmap::root_prop_atoms[] = {
54
FbPixmap::FbPixmap():m_pm(0),
55
m_width(0), m_height(0),
59
FbPixmap::FbPixmap(const FbPixmap &the_copy):FbDrawable(), m_pm(0),
60
m_width(0), m_height(0),
65
FbPixmap::FbPixmap(Pixmap pm):m_pm(0),
66
m_width(0), m_height(0),
70
// assign X pixmap to this
74
FbPixmap::FbPixmap(const FbDrawable &src,
75
unsigned int width, unsigned int height,
77
m_width(0), m_height(0),
80
create(src.drawable(), width, height, depth);
83
FbPixmap::FbPixmap(Drawable src,
84
unsigned int width, unsigned int height,
86
m_width(0), m_height(0),
89
create(src, width, height, depth);
92
FbPixmap::~FbPixmap() {
96
FbPixmap &FbPixmap::operator = (const FbPixmap &the_copy) {
101
FbPixmap &FbPixmap::operator = (Pixmap pm) {
102
// free pixmap before we set new
108
// get width, height and depth for the pixmap
111
unsigned int border_width, bpp;
112
XGetGeometry(display(),
127
void FbPixmap::copy(const FbPixmap &the_copy) {
129
bool create_new = false;
131
if (the_copy.width() != width() ||
132
the_copy.height() != height() ||
133
the_copy.depth() != depth() ||
140
if (the_copy.drawable() != 0) {
142
create(the_copy.drawable(),
143
the_copy.width(), the_copy.height(),
148
GContext gc(drawable());
150
copyArea(the_copy.drawable(),
159
// screen doesn't count if depth is "zero"...
160
void FbPixmap::copy(Pixmap pm, int depth, int screen_num) {
165
// get width, height and depth for the pixmap
168
unsigned int border_width, bpp;
169
unsigned int new_width, new_height;
171
XGetGeometry(display(),
175
&new_width, &new_height,
182
// create new pixmap and copy area
183
create(root, new_width, new_height, depth);
185
GC gc = XCreateGC(display(), drawable(), 0, 0);
188
XCopyArea(display(), pm, drawable(), gc,
193
XSetForeground(display(), gc, Color("black", screen_num).pixel());
194
XSetBackground(display(), gc, Color("white", screen_num).pixel());
195
XCopyPlane(display(), pm, drawable(), gc,
201
XFreeGC(display(), gc);
204
void FbPixmap::rotate() {
206
// make an image copy
207
XImage *src_image = XGetImage(display(), drawable(),
209
width(), height(), // size
212
// reverse height/width for new pixmap
213
FbPixmap new_pm(drawable(), height(), width(), depth());
215
GContext gc(drawable());
218
for (unsigned int y = 0; y < height(); ++y) {
219
for (unsigned int x = 0; x < width(); ++x) {
220
gc.setForeground(XGetPixel(src_image, x, y));
221
// revers coordinates
222
XDrawPoint(display(), new_pm.drawable(), gc.gc(), y, x);
226
XDestroyImage(src_image);
227
// free old pixmap and set new from new_pm
230
m_width = new_pm.width();
231
m_height = new_pm.height();
232
m_depth = new_pm.depth();
233
m_pm = new_pm.release();
236
void FbPixmap::scale(unsigned int dest_width, unsigned int dest_height) {
238
if (drawable() == 0 ||
239
(dest_width == width() && dest_height == height()))
242
XImage *src_image = XGetImage(display(), drawable(),
244
width(), height(), // size
250
// create new pixmap with dest size
251
FbPixmap new_pm(drawable(), dest_width, dest_height, depth());
253
GContext gc(drawable());
255
float zoom_x = static_cast<float>(width())/static_cast<float>(dest_width);
256
float zoom_y = static_cast<float>(height())/static_cast<float>(dest_height);
259
float src_x = 0, src_y = 0;
260
for (unsigned int tx=0; tx < dest_width; ++tx, src_x += zoom_x) {
262
for (unsigned int ty=0; ty < dest_height; ++ty, src_y += zoom_y) {
263
gc.setForeground(XGetPixel(src_image,
264
static_cast<int>(src_x),
265
static_cast<int>(src_y)));
266
XDrawPoint(display(), new_pm.drawable(), gc.gc(), tx, ty);
270
XDestroyImage(src_image);
272
// free old pixmap and set new from new_pm
275
m_width = new_pm.width();
276
m_height = new_pm.height();
277
m_depth = new_pm.depth();
278
m_pm = new_pm.release();
281
void FbPixmap::tile(unsigned int dest_width, unsigned int dest_height) {
282
if (drawable() == 0 ||
283
(dest_width == width() && dest_height == height()))
286
FbPixmap new_pm(drawable(), width(), height(), depth());
288
new_pm.copy(m_pm, 0, 0);
290
resize(dest_width, dest_height);
292
FbTk::GContext gc(*this);
295
gc.setFillStyle(FillTiled);
297
fillRectangle(gc.gc(), 0, 0, dest_width, dest_height);
303
void FbPixmap::resize(unsigned int width, unsigned int height) {
304
FbPixmap pm(drawable(), width, height, depth());
305
*this = pm.release();
308
Pixmap FbPixmap::release() {
317
void FbPixmap::rootwinPropertyNotify(int screen_num, Atom atom) {
318
if (!FbTk::Transparent::haveRender())
322
for (int i=0; root_prop_ids[i] != 0; ++i) {
323
if (root_prop_atoms[i] == atom) {
324
Pixmap root_pm = None;
327
unsigned long items_read, items_left;
330
unsigned int prop = 0;
331
if (XGetWindowProperty(display(),
332
RootWindow(display(), i),
336
&real_type, &real_format,
337
&items_read, &items_left,
338
(unsigned char **) &data) == Success) {
339
if (real_format == 32 && items_read == 1) {
340
root_pm = (Pixmap) (*data);
344
setRootPixmap(screen_num, root_pm);
351
void FbPixmap::setRootPixmap(int screen_num, Pixmap pm) {
352
if (!m_root_pixmaps) {
353
m_root_pixmaps = new Pixmap[ScreenCount(display())];
356
m_root_pixmaps[screen_num] = pm;
359
Pixmap FbPixmap::getRootPixmap(int screen_num) {
360
if (!FbTk::Transparent::haveRender())
363
if (!m_root_pixmaps) {
364
int numscreens = ScreenCount(display());
365
for (int i=0; i < numscreens; ++i) {
368
unsigned long items_read, items_left;
371
unsigned int prop = 0;
373
static bool print_error = true; // print error_message only once
374
static const char* error_message = { "\n\n !!! WARNING WARNING WARNING WARNING !!!!!\n"
375
" if you experience problems with transparency:\n"
376
" you are using a wallpapersetter that \n"
377
" uses _XSETROOT_ID .. which we do not support.\n"
378
" consult 'fbsetbg -i' or try any other wallpapersetter\n"
379
" that uses _XROOTPMAP_ID !\n"
380
" !!! WARNING WARNING WARNING WARNING !!!!!!\n\n"
383
Pixmap root_pm = None;
384
for (prop = 0; root_prop_ids[prop]; prop++) {
386
if (XGetWindowProperty(display(),
387
RootWindow(display(), i),
391
&real_type, &real_format,
392
&items_read, &items_left,
393
(unsigned char **) &data) == Success) {
394
if (real_format == 32 && items_read == 1) {
395
if (print_error && strcmp(root_prop_ids[prop], "_XSETROOT_ID") == 0) {
399
root_pm = (Pixmap) (*data);
406
setRootPixmap(i, root_pm);
409
return m_root_pixmaps[screen_num];
412
void FbPixmap::checkAtoms() {
413
for (int i=0; root_prop_ids[i] != 0; ++i) {
414
if (root_prop_atoms[i] == None) {
415
root_prop_atoms[i] = XInternAtom(display(), root_prop_ids[i], False);
420
void FbPixmap::free() {
422
XFreePixmap(display(), m_pm);
430
void FbPixmap::create(Drawable src,
431
unsigned int width, unsigned int height,
436
m_pm = XCreatePixmap(display(),
437
src, width, height, depth);
446
}; // end namespace FbTk