00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "FbWindow.hh"
00025
00026 #include "EventManager.hh"
00027 #include "Color.hh"
00028 #include "App.hh"
00029 #include "Transparent.hh"
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include "config.h"
00033 #endif // HAVE_CONFIG_H
00034
00035 #include <X11/Xatom.h>
00036
00037 #include <cassert>
00038
00039 namespace FbTk {
00040
00041 namespace {
00042 Pixmap getRootPixmap(int screen_num) {
00043 Pixmap root_pm = 0;
00044
00045 Display *disp = FbTk::App::instance()->display();
00046 Atom real_type;
00047 int real_format;
00048 unsigned long items_read, items_left;
00049 unsigned int *data;
00050 if (XGetWindowProperty(disp, RootWindow(disp, screen_num),
00051 XInternAtom(disp, "_XROOTPMAP_ID", false),
00052 0L, 1L,
00053 false, XA_PIXMAP, &real_type,
00054 &real_format, &items_read, &items_left,
00055 (unsigned char **) &data) == Success &&
00056 items_read) {
00057 root_pm = (Pixmap) (*data);
00058 XFree(data);
00059 }
00060
00061 return root_pm;
00062 }
00063
00064 };
00065
00066 Display *FbWindow::s_display = 0;
00067
00068 FbWindow::FbWindow():m_parent(0), m_screen_num(0), m_window(0), m_x(0), m_y(0),
00069 m_width(0), m_height(0), m_border_width(0), m_depth(0), m_destroy(true),
00070 m_buffer_pm(0) {
00071
00072 if (s_display == 0)
00073 s_display = App::instance()->display();
00074 }
00075
00076 FbWindow::FbWindow(const FbWindow& the_copy):m_parent(the_copy.parent()),
00077 m_screen_num(the_copy.screenNumber()), m_window(the_copy.window()),
00078 m_x(the_copy.x()), m_y(the_copy.y()),
00079 m_width(the_copy.width()), m_height(the_copy.height()),
00080 m_border_width(the_copy.borderWidth()),
00081 m_depth(the_copy.depth()), m_destroy(true),
00082 m_buffer_pm(0) {
00083 if (s_display == 0)
00084 s_display = App::instance()->display();
00085
00086 the_copy.m_window = 0;
00087 }
00088
00089 FbWindow::FbWindow(int screen_num,
00090 int x, int y,
00091 unsigned int width, unsigned int height,
00092 long eventmask,
00093 bool override_redirect,
00094 int depth,
00095 int class_type):
00096 m_parent(0),
00097 m_screen_num(screen_num),
00098 m_destroy(true),
00099 m_buffer_pm(0) {
00100
00101 create(RootWindow(FbTk::App::instance()->display(), screen_num),
00102 x, y, width, height, eventmask,
00103 override_redirect, depth, class_type);
00104 };
00105
00106 FbWindow::FbWindow(const FbWindow &parent,
00107 int x, int y, unsigned int width, unsigned int height,
00108 long eventmask,
00109 bool override_redirect,
00110 int depth, int class_type):
00111 m_parent(&parent),
00112 m_screen_num(parent.screenNumber()),
00113 m_destroy(true),
00114 m_buffer_pm(0) {
00115
00116 create(parent.window(), x, y, width, height, eventmask,
00117 override_redirect, depth, class_type);
00118
00119
00120 };
00121
00122 FbWindow::FbWindow(Window client):m_parent(0),
00123 m_screen_num(0),
00124 m_window(0),
00125 m_x(0), m_y(0),
00126 m_width(1), m_height(1),
00127 m_border_width(0),
00128 m_depth(0),
00129 m_destroy(false),
00130 m_buffer_pm(0) {
00131
00132 if (s_display == 0)
00133 s_display = App::instance()->display();
00134
00135 setNew(client);
00136 }
00137
00138 FbWindow::~FbWindow() {
00139
00140 if (m_window != 0) {
00141
00142 FbTk::EventManager::instance()->remove(m_window);
00143 if (m_destroy)
00144 XDestroyWindow(s_display, m_window);
00145 }
00146 }
00147
00148
00149 void FbWindow::setBackgroundColor(const FbTk::Color &bg_color) {
00150 XSetWindowBackground(s_display, m_window, bg_color.pixel());
00151 }
00152
00153 void FbWindow::setBackgroundPixmap(Pixmap bg_pixmap) {
00154 XSetWindowBackgroundPixmap(s_display, m_window, bg_pixmap);
00155 }
00156
00157 void FbWindow::setBorderColor(const FbTk::Color &border_color) {
00158 XSetWindowBorder(s_display, m_window, border_color.pixel());
00159 }
00160
00161 void FbWindow::setBorderWidth(unsigned int size) {
00162 XSetWindowBorderWidth(s_display, m_window, size);
00163 m_border_width = size;
00164 }
00165
00166 void FbWindow::setName(const char *name) {
00167 XStoreName(s_display, m_window, name);
00168 }
00169
00170 void FbWindow::setEventMask(long mask) {
00171 XSelectInput(s_display, m_window, mask);
00172 }
00173
00174 void FbWindow::clear() {
00175 XClearWindow(s_display, m_window);
00176 }
00177
00178 void FbWindow::clearArea(int x, int y,
00179 unsigned int width, unsigned int height,
00180 bool exposures) {
00181 XClearArea(s_display, window(), x, y, width, height, exposures);
00182 }
00183
00184 void FbWindow::updateTransparent(int the_x, int the_y, unsigned int the_width, unsigned int the_height) {
00185 #ifdef HAVE_XRENDER
00186 if (width() == 0 || height() == 0)
00187 return;
00188
00189 if (the_width == 0 || the_height == 0) {
00190 the_width = width();
00191 the_height = height();
00192 }
00193
00194 if (the_x < 0 || the_y < 0) {
00195 the_x = 0;
00196 the_y = 0;
00197 }
00198
00199 if (!m_transparent.get())
00200 return;
00201
00202
00203 Pixmap root = getRootPixmap(screenNumber());
00204 if (m_transparent->source() != root)
00205 m_transparent->setSource(root, screenNumber());
00206
00207 if (m_buffer_pm) {
00208 if (m_transparent->dest() != m_buffer_pm) {
00209 m_transparent->setDest(m_buffer_pm, screenNumber());
00210 }
00211 } else if (m_transparent->dest() != window())
00212 m_transparent->setDest(window(), screenNumber());
00213
00214
00215
00216
00217 const FbWindow *root_parent = parent();
00218
00219 int root_x = x() + borderWidth(), root_y = y() + borderWidth();
00220 if (root_parent != 0) {
00221 root_x += root_parent->x() + root_parent->borderWidth();
00222 root_y += root_parent->y() + root_parent->borderWidth();
00223 while (root_parent->parent() != 0) {
00224 root_parent = root_parent->parent();
00225 root_x += root_parent->x() + root_parent->borderWidth();
00226 root_y += root_parent->y() + root_parent->borderWidth();
00227 }
00228
00229 }
00230
00231
00232 m_transparent->render(root_x + the_x, root_y + the_y,
00233 the_x, the_y,
00234 the_width, the_height);
00235 #endif // HAVE_XRENDER
00236 }
00237
00238 void FbWindow::setAlpha(unsigned char alpha) {
00239 #ifdef HAVE_XRENDER
00240 if (m_transparent.get() == 0 && alpha != 0) {
00241 m_transparent.reset(new Transparent(getRootPixmap(screenNumber()), window(), alpha, screenNumber()));
00242 } else if (alpha != 0 && alpha != m_transparent->alpha())
00243 m_transparent->setAlpha(alpha);
00244 else if (alpha == 0)
00245 m_transparent.reset(0);
00246 #endif // HAVE_XRENDER
00247 }
00248
00249
00250 FbWindow &FbWindow::operator = (const FbWindow &win) {
00251 m_parent = win.parent();
00252 m_screen_num = win.screenNumber();
00253 m_window = win.window();
00254 m_x = win.x();
00255 m_y = win.y();
00256 m_width = win.width();
00257 m_height = win.height();
00258 m_border_width = win.borderWidth();
00259 m_depth = win.depth();
00260
00261 win.m_window = 0;
00262 return *this;
00263 }
00264
00265 FbWindow &FbWindow::operator = (Window win) {
00266 setNew(win);
00267 return *this;
00268 }
00269
00270 void FbWindow::setNew(Window win) {
00271 if (s_display == 0)
00272 s_display = App::instance()->display();
00273
00274 if (m_window != 0 && m_destroy)
00275 XDestroyWindow(s_display, m_window);
00276
00277 m_window = win;
00278
00279 if (m_window != 0) {
00280 updateGeometry();
00281 XWindowAttributes attr;
00282 attr.screen = 0;
00283
00284 if (XGetWindowAttributes(s_display,
00285 m_window,
00286 &attr) != 0 && attr.screen != 0) {
00287 m_screen_num = XScreenNumberOfScreen(attr.screen);
00288 m_width = attr.width;
00289 m_height = attr.height ;
00290 m_x = attr.x;
00291 m_y = attr.y;
00292 m_depth = attr.depth;
00293 m_border_width = attr.border_width;
00294 }
00295
00296 }
00297 }
00298
00299 void FbWindow::show() {
00300 XMapWindow(s_display, m_window);
00301 }
00302
00303 void FbWindow::showSubwindows() {
00304 XMapSubwindows(s_display, m_window);
00305 }
00306
00307 void FbWindow::hide() {
00308 XUnmapWindow(s_display, m_window);
00309 }
00310
00311 void FbWindow::lower() {
00312 XLowerWindow(s_display, window());
00313 }
00314
00315 void FbWindow::raise() {
00316 XRaiseWindow(s_display, window());
00317 }
00318
00319 void FbWindow::setInputFocus(int revert_to, int time) {
00320 XSetInputFocus(s_display, window(), revert_to, time);
00321 }
00322
00323 void FbWindow::setCursor(Cursor cur) {
00324 XDefineCursor(s_display, window(), cur);
00325 }
00326
00327 void FbWindow::unsetCursor() {
00328 XUndefineCursor(s_display, window());
00329 }
00330
00331 void FbWindow::reparent(const FbWindow &parent, int x, int y) {
00332 XReparentWindow(s_display, window(), parent.window(), x, y);
00333 m_parent = &parent;
00334 updateGeometry();
00335 }
00336
00337 bool FbWindow::property(Atom property,
00338 long long_offset, long long_length,
00339 bool do_delete,
00340 Atom req_type,
00341 Atom *actual_type_return,
00342 int *actual_format_return,
00343 unsigned long *nitems_return,
00344 unsigned long *bytes_after_return,
00345 unsigned char **prop_return) const {
00346 if (XGetWindowProperty(s_display, window(),
00347 property, long_offset, long_length, do_delete,
00348 req_type, actual_type_return,
00349 actual_format_return, nitems_return,
00350 bytes_after_return, prop_return) == Success)
00351 return true;
00352
00353 return false;
00354 }
00355
00356 void FbWindow::changeProperty(Atom property, Atom type,
00357 int format,
00358 int mode,
00359 unsigned char *data,
00360 int nelements) {
00361
00362 XChangeProperty(s_display, m_window, property, type,
00363 format, mode,
00364 data, nelements);
00365 }
00366
00367 int FbWindow::screenNumber() const {
00368 return m_screen_num;
00369 }
00370
00371 long FbWindow::eventMask() const {
00372 XWindowAttributes attrib;
00373 if (XGetWindowAttributes(s_display, window(),
00374 &attrib) == Success) {
00375 return attrib.your_event_mask;
00376 }
00377 return 0;
00378 }
00379
00380 void FbWindow::setBufferPixmap(Pixmap pm) {
00381 m_buffer_pm = pm;
00382 }
00383
00384 void FbWindow::updateGeometry() {
00385 if (m_window == 0)
00386 return;
00387
00388 Window root;
00389 unsigned int border_width, depth;
00390 XGetGeometry(s_display, m_window, &root, &m_x, &m_y,
00391 (unsigned int *)&m_width, (unsigned int *)&m_height,
00392 &border_width, &depth);
00393 m_depth = depth;
00394 }
00395
00396 void FbWindow::create(Window parent, int x, int y,
00397 unsigned int width, unsigned int height,
00398 long eventmask, bool override_redirect,
00399 int depth, int class_type) {
00400
00401
00402 if (s_display == 0)
00403 s_display = FbTk::App::instance()->display();
00404
00405 m_border_width = 0;
00406
00407 long valmask = CWEventMask;
00408 XSetWindowAttributes values;
00409 values.event_mask = eventmask;
00410
00411 if (override_redirect) {
00412 valmask |= CWOverrideRedirect;
00413 values.override_redirect = True;
00414 }
00415
00416 m_window = XCreateWindow(s_display, parent, x, y, width, height,
00417 0,
00418 depth,
00419 class_type,
00420 CopyFromParent,
00421 valmask,
00422 &values);
00423
00424 assert(m_window);
00425
00426 updateGeometry();
00427 FbWindow::setBackgroundColor(Color("gray", screenNumber()));
00428 }
00429
00430 bool operator == (Window win, const FbWindow &fbwin) {
00431 return win == fbwin.window();
00432 }
00433
00434 };