00001
00002
00003
00004
00005
00006 #include "thing.h"
00007
00008 #include "client.h"
00009 #include "cursors.h"
00010 #include "draw.h"
00011 #include "font.h"
00012 #include "frame.h"
00013 #include "kernel.h"
00014 #include "label.h"
00015 #include "logger.h"
00016 #include "monitor.h"
00017 #include "theme.h"
00018 #include "workspace.h"
00019 #include "xcore.h"
00020 #include "xfont.h"
00021
00022 Thing::Thing(Monitor *monitor, Rectangle *rect, Type type)
00023 : Rectangle(*rect)
00024 {
00025 monitor_ = monitor;
00026 type_ = type;
00027 isVisible_ = false;
00028 hasDecoration_ = false;
00029 clientAreaRect_ = Rectangle(*rect);
00030 name_ = "";
00031
00032
00033 theme_ = monitor_->theme();
00034
00035 areButtonsVisible_ =
00036 (Util::get(KERNEL->commonSettings(), "frame.buttons") == "yes");
00037
00038 cursor_ = Cursors::NORMAL_CURSOR;
00039 prevRect_ = new Rectangle(*rect);
00040 buttonState_ = NONE;
00041
00042
00043 if (type == FRAME) {
00044 initFrameWindow();
00045 fitClientArea();
00046 }
00047 else {
00048 frameWindow_ = 0;
00049 gc_ = 0;
00050 label_ = 0;
00051 titleBarHeight_ = 0;
00052 borderWidth_ = 0;
00053 }
00054 }
00055
00056 Thing::~Thing() {
00057 delete prevRect_;
00058
00059 if (frameWindow_) {
00060 delete label_;
00061 XCORE->free(gc_);
00062 XCORE->destroy(frameWindow_);
00063 LOGDEBUG("frame destroyed");
00064 }
00065 }
00066
00067 void Thing::initFrameWindow() {
00068
00069 titleBarHeight_ =
00070 (Util::get(KERNEL->commonSettings(), "default.bar-mode")
00071 == "show") ? monitor_->titleBarHeight() : 0;
00072 borderWidth_ =
00073 (Util::get(KERNEL->commonSettings(), "default.border-mode")
00074 == "show") ? KERNEL->borderWidth() : 0;
00075
00076 if (type_ == CLIENT) {
00077 setX(x() - borderWidth_);
00078 setY(y() - titleBarHeight_ - borderWidth_ - 1);
00079 setWidth(width() + 2 * borderWidth_);
00080 setHeight(height() + titleBarHeight_ + 2 * borderWidth_ + 1);
00081 }
00082
00083 XSetWindowAttributes attr;
00084 attr.background_pixmap = ParentRelative;
00085 attr.override_redirect = 1;
00086 frameWindow_ = XCORE->createWindow(this->monitor()->rootWindow(), &attr,
00087 x(), y(), width(), height(),
00088 CWOverrideRedirect | CWBackPixmap);
00089
00090 LOGDEBUG("init GC for frame");
00091 initGC();
00092 label_ = new Label(this->monitor(), frameWindow_, Label::CENTER, gc_);
00093 label_->setY(borderWidth_);
00094 label_->setHeight(titleBarHeight_);
00095
00096 XCORE->selectEvents(frameWindow_,
00097 ExposureMask | SubstructureRedirectMask | SubstructureNotifyMask |
00098 ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
00099
00100 KERNEL->installCursor(Cursors::NORMAL_CURSOR, frameWindow_);
00101 hasDecoration_ = true;
00102 }
00103
00104 Thing::Type Thing::type() const {
00105 return type_;
00106 }
00107
00108 Monitor *Thing::monitor() const {
00109 return monitor_;
00110 }
00111
00112 bool Thing::isVisible() const {
00113 return isVisible_;
00114 }
00115
00116 void Thing::initGC() {
00117
00118 if (frameWindow_) {
00119 unsigned long mask =
00120 GCForeground | GCBackground |
00121 GCFunction | GCLineWidth | GCLineStyle;
00122
00123 XGCValues gcv;
00124 gcv.function = GXcopy;
00125 gcv.line_width = 1;
00126 gcv.line_style = LineSolid;
00127 if (monitor()->font()->type() == WFont::NORMAL) {
00128 gcv.font = ((XFont *)monitor()->font())->font()->fid;
00129 mask |= GCFont;
00130 }
00131 gc_ = XCORE->createGC(frameWindow_, mask, &gcv);
00132 }
00133 }
00134
00135 void Thing::illuminateBorder() {
00136
00137 if (!isVisible_ || !frameWindow_) {
00138 return;
00139 }
00140
00141 bool focused = isFocused();
00142
00143 if (titleBarHeight_) {
00144 label_->setText("");
00145 label_->setX(borderWidth_);
00146 label_->setWidth(width() - 2 * borderWidth_);
00147
00148 if (focused) {
00149 label_->update(theme_->FRAME_BACKGROUND_FOCUSSED, 0,
00150 theme_->FRAME_SHINE_FOCUSSED,
00151 theme_->FRAME_SHADOW_FOCUSSED);
00152 }
00153 else {
00154 label_->update(theme_->FRAME_BACKGROUND_NORMAL, 0,
00155 theme_->FRAME_SHINE_NORMAL,
00156 theme_->FRAME_SHADOW_NORMAL);
00157 }
00158 }
00159
00160 LOGDEBUG("drawing border");
00161 if (focused) {
00162 Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this,
00163 theme_->FRAME_BACKGROUND_FOCUSSED,
00164 theme_->FRAME_SHINE_FOCUSSED,
00165 theme_->FRAME_SHADOW_FOCUSSED,
00166 titleBarHeight_ + borderWidth_,
00167 borderWidth_);
00168 }
00169 else {
00170 Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this,
00171 theme_->FRAME_BACKGROUND_NORMAL,
00172 theme_->FRAME_SHINE_NORMAL,
00173 theme_->FRAME_SHADOW_NORMAL,
00174 titleBarHeight_ + borderWidth_,
00175 borderWidth_);
00176 }
00177
00178 if (titleBarHeight_ && areButtonsVisible_ && focused) {
00179
00180 if (type_ == FRAME && !((Frame *)this)->size()) {
00181
00182 return;
00183 }
00184
00185
00186 label_->setText("");
00187 label_->setX(width() - borderWidth_ - 3 * monitor_->buttonWidth());
00188 label_->setWidth(monitor_->buttonWidth());
00189 if (buttonState_ != MINCLIENT) {
00190
00191 Draw::drawDetachButton(frameWindow_, gc_, label_,
00192 theme_->BUTTON_BACKGROUND_NORMAL,
00193 theme_->BUTTON_SHINE_BORDER_NORMAL,
00194 theme_->BUTTON_SHADOW_BORDER_NORMAL,
00195 theme_->BUTTON_SHINE_FIGURE_NORMAL,
00196 theme_->BUTTON_SHADOW_FIGURE_NORMAL);
00197 }
00198 else {
00199
00200 Draw::drawDetachButton(frameWindow_, gc_, label_,
00201 theme_->BUTTON_BACKGROUND_PRESSED,
00202 theme_->BUTTON_SHINE_BORDER_PRESSED,
00203 theme_->BUTTON_SHADOW_BORDER_PRESSED,
00204 theme_->BUTTON_SHINE_FIGURE_PRESSED,
00205 theme_->BUTTON_SHADOW_FIGURE_PRESSED);
00206 }
00207
00208
00209 label_->setX(label_->x() + monitor_->buttonWidth());
00210
00211 if (buttonState_ != DEMAX) {
00212
00213 if (type_ == CLIENT) {
00214
00215 Draw::drawMaxButton(frameWindow_, gc_, label_,
00216 theme_->BUTTON_BACKGROUND_NORMAL,
00217 theme_->BUTTON_SHINE_BORDER_NORMAL,
00218 theme_->BUTTON_SHADOW_BORDER_NORMAL,
00219 theme_->BUTTON_SHINE_FIGURE_NORMAL,
00220 theme_->BUTTON_SHADOW_FIGURE_NORMAL);
00221 }
00222 else {
00223
00224 Draw::drawFloatButton(frameWindow_, gc_, label_,
00225 theme_->BUTTON_BACKGROUND_NORMAL,
00226 theme_->BUTTON_SHINE_BORDER_NORMAL,
00227 theme_->BUTTON_SHADOW_BORDER_NORMAL,
00228 theme_->BUTTON_SHINE_FIGURE_NORMAL,
00229 theme_->BUTTON_SHADOW_FIGURE_NORMAL);
00230 }
00231 }
00232 else {
00233
00234 if (type_ == CLIENT) {
00235
00236 Draw::drawMaxButton(frameWindow_, gc_, label_,
00237 theme_->BUTTON_BACKGROUND_PRESSED,
00238 theme_->BUTTON_SHINE_BORDER_PRESSED,
00239 theme_->BUTTON_SHADOW_BORDER_PRESSED,
00240 theme_->BUTTON_SHINE_FIGURE_PRESSED,
00241 theme_->BUTTON_SHADOW_FIGURE_PRESSED);
00242 }
00243 else {
00244
00245 Draw::drawFloatButton(frameWindow_, gc_, label_,
00246 theme_->BUTTON_BACKGROUND_PRESSED,
00247 theme_->BUTTON_SHINE_BORDER_PRESSED,
00248 theme_->BUTTON_SHADOW_BORDER_PRESSED,
00249 theme_->BUTTON_SHINE_FIGURE_PRESSED,
00250 theme_->BUTTON_SHADOW_FIGURE_PRESSED);
00251 }
00252
00253 }
00254
00255
00256 label_->setX(label_->x() + monitor_->buttonWidth());
00257 if (buttonState_ != CLOSE) {
00258
00259 Draw::drawCloseButton(frameWindow_, gc_, label_,
00260 theme_->BUTTON_BACKGROUND_NORMAL,
00261 theme_->BUTTON_SHINE_BORDER_NORMAL,
00262 theme_->BUTTON_SHADOW_BORDER_NORMAL,
00263 theme_->BUTTON_SHINE_FIGURE_NORMAL,
00264 theme_->BUTTON_SHADOW_FIGURE_NORMAL);
00265 }
00266 else {
00267
00268 Draw::drawCloseButton(frameWindow_, gc_, label_,
00269 theme_->BUTTON_BACKGROUND_PRESSED,
00270 theme_->BUTTON_SHINE_BORDER_PRESSED,
00271 theme_->BUTTON_SHADOW_BORDER_PRESSED,
00272 theme_->BUTTON_SHINE_FIGURE_PRESSED,
00273 theme_->BUTTON_SHADOW_FIGURE_PRESSED);
00274
00275 }
00276 }
00277 }
00278
00279 void Thing::handleMotionNotify(XMotionEvent *event) {
00280
00281 if (monitor()->isThingMaximized()) {
00282 return;
00283 }
00284
00285 Cursor cursor = cursorForXY(event->x, event->y);
00286
00287 if (cursor != cursor_) {
00288 cursor_ = cursor;
00289 KERNEL->installCursor(cursor, frameWindow_);
00290 }
00291
00292 if (buttonState_ != NONE) {
00293 buttonState_ = NONE;
00294 illuminate();
00295 }
00296 }
00297
00298 void Thing::setTitleBarHeight(unsigned int titleBarHeight) {
00299 titleBarHeight_ = titleBarHeight;
00300 }
00301
00302 void Thing::setBorderWidth(unsigned int borderWidth) {
00303 borderWidth_ = borderWidth;
00304 }
00305
00306 unsigned int Thing::borderWidth() const {
00307 return borderWidth_;
00308 }
00309
00310 unsigned int Thing::titleBarHeight() const {
00311 return titleBarHeight_;
00312 }
00313
00314 Rectangle *Thing::prevRectangle() const {
00315 return prevRect_;
00316 }
00317
00318 Thing::InvertButton Thing::buttonState() const {
00319 return buttonState_;
00320 }
00321
00322 void Thing::setButtonState(InvertButton state) {
00323 buttonState_ = state;
00324 }
00325
00326 void Thing::show() {
00327 if (frameWindow_) {
00328 XCORE->show(frameWindow_);
00329 isVisible_ = true;
00330 }
00331 }
00332
00333 void Thing::hide() {
00334 if (frameWindow_) {
00335 XCORE->hide(frameWindow_);
00336 isVisible_ = false;
00337 }
00338 }
00339
00340 void Thing::fitClientArea() {
00341
00342 clientAreaRect_.setX(borderWidth_);
00343 clientAreaRect_.setY(titleBarHeight_ + borderWidth_ +
00344 (titleBarHeight_ ? 1 : 0));
00345 clientAreaRect_.setWidth(width() - 2 * borderWidth_);
00346 clientAreaRect_.setHeight(height() - titleBarHeight_
00347 - 2 * borderWidth_
00348 - (titleBarHeight_ ? 1 : 0));
00349 }
00350
00351 void Thing::setName(string name) {
00352 name_ = name;
00353 }
00354
00355 string Thing::name() const {
00356 return name_;
00357 }
00358
00359 bool Thing::hasDecoration() const {
00360 return hasDecoration_;
00361 }