thing.cpp (10483B)
1 // Copyright (c) 2003 - 2009 Anselm R Garbe <anselm@garbe.us> 2 // See LICENSE for license details. 3 4 #include "thing.h" 5 6 #include "client.h" 7 #include "cursors.h" 8 #include "draw.h" 9 #include "font.h" 10 #include "frame.h" 11 #include "kernel.h" 12 #include "label.h" 13 #include "logger.h" 14 #include "monitor.h" 15 #include "theme.h" 16 #include "workspace.h" 17 #include "xcore.h" 18 #include "xfont.h" 19 20 Thing::Thing(Monitor *monitor, Rectangle *rect, Type type) 21 : Rectangle(*rect) 22 { 23 monitor_ = monitor; 24 type_ = type; 25 isVisible_ = false; 26 hasDecoration_ = false; 27 clientAreaRect_ = Rectangle(*rect); 28 name_ = ""; 29 30 // view 31 theme_ = monitor_->theme(); 32 33 areButtonsVisible_ = 34 (Util::get(KERNEL->commonSettings(), "frame.buttons") == "yes"); 35 36 cursor_ = Cursors::NORMAL_CURSOR; 37 prevRect_ = new Rectangle(*rect); 38 buttonState_ = NONE; 39 40 // creates frame window 41 if (type == FRAME) { 42 initFrameWindow(); 43 fitClientArea(); 44 } 45 else { 46 frameWindow_ = 0; 47 gc_ = 0; 48 label_ = 0; 49 titleBarHeight_ = 0; 50 borderWidth_ = 0; 51 } 52 } 53 54 Thing::~Thing() { 55 delete prevRect_; 56 57 if (frameWindow_) { 58 delete label_; 59 XCORE->free(gc_); 60 XCORE->destroy(frameWindow_); 61 LOGDEBUG("frame destroyed"); 62 } 63 } 64 65 void Thing::initFrameWindow() { 66 67 titleBarHeight_ = 68 (Util::get(KERNEL->commonSettings(), "default.bar-mode") 69 == "show") ? monitor_->titleBarHeight() : 0; 70 borderWidth_ = 71 (Util::get(KERNEL->commonSettings(), "default.border-mode") 72 == "show") ? KERNEL->borderWidth() : 0; 73 74 if (type_ == CLIENT) { 75 setX(x() - borderWidth_); 76 setY(y() - titleBarHeight_ - borderWidth_ - 1); 77 setWidth(width() + 2 * borderWidth_); 78 setHeight(height() + titleBarHeight_ + 2 * borderWidth_ + 1); 79 } 80 81 XSetWindowAttributes attr; 82 attr.background_pixmap = ParentRelative; 83 attr.override_redirect = 1; 84 frameWindow_ = XCORE->createWindow(this->monitor()->rootWindow(), &attr, 85 x(), y(), width(), height(), 86 CWOverrideRedirect | CWBackPixmap); 87 88 LOGDEBUG("init GC for frame"); 89 initGC(); 90 label_ = new Label(this->monitor(), frameWindow_, Label::CENTER, gc_); 91 label_->setY(borderWidth_); 92 label_->setHeight(titleBarHeight_); 93 94 XCORE->selectEvents(frameWindow_, 95 ExposureMask | SubstructureRedirectMask | SubstructureNotifyMask | 96 ButtonPressMask | ButtonReleaseMask | PointerMotionMask); 97 98 KERNEL->installCursor(Cursors::NORMAL_CURSOR, frameWindow_); 99 hasDecoration_ = true; 100 } 101 102 Thing::Type Thing::type() const { 103 return type_; 104 } 105 106 Monitor *Thing::monitor() const { 107 return monitor_; 108 } 109 110 bool Thing::isVisible() const { 111 return isVisible_; 112 } 113 114 void Thing::initGC() { 115 116 if (frameWindow_) { 117 unsigned long mask = 118 GCForeground | GCBackground | 119 GCFunction | GCLineWidth | GCLineStyle; 120 121 XGCValues gcv; 122 gcv.function = GXcopy; 123 gcv.line_width = 1; 124 gcv.line_style = LineSolid; 125 if (monitor()->font()->type() == WFont::NORMAL) { 126 gcv.font = ((XFont *)monitor()->font())->font()->fid; 127 mask |= GCFont; 128 } 129 gc_ = XCORE->createGC(frameWindow_, mask, &gcv); 130 } 131 } 132 133 void Thing::illuminateBorder() { 134 135 if (!isVisible_ || !frameWindow_) { 136 return; 137 } 138 139 bool focused = isFocused(); 140 141 if (titleBarHeight_) { 142 label_->setText(""); 143 label_->setX(borderWidth_); 144 label_->setWidth(width() - 2 * borderWidth_); 145 146 if (focused) { 147 label_->update(theme_->FRAME_BACKGROUND_FOCUSSED, 0, 148 theme_->FRAME_SHINE_FOCUSSED, 149 theme_->FRAME_SHADOW_FOCUSSED); 150 } 151 else { 152 label_->update(theme_->FRAME_BACKGROUND_NORMAL, 0, 153 theme_->FRAME_SHINE_NORMAL, 154 theme_->FRAME_SHADOW_NORMAL); 155 } 156 } 157 158 LOGDEBUG("drawing border"); 159 if (focused) { 160 Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this, 161 theme_->FRAME_BACKGROUND_FOCUSSED, 162 theme_->FRAME_SHINE_FOCUSSED, 163 theme_->FRAME_SHADOW_FOCUSSED, 164 titleBarHeight_ + borderWidth_, 165 borderWidth_); 166 } 167 else { 168 Draw::drawBorder(frameWindow_, gc_, monitor()->borderGC(), this, 169 theme_->FRAME_BACKGROUND_NORMAL, 170 theme_->FRAME_SHINE_NORMAL, 171 theme_->FRAME_SHADOW_NORMAL, 172 titleBarHeight_ + borderWidth_, 173 borderWidth_); 174 } 175 176 if (titleBarHeight_ && areButtonsVisible_ && focused) { 177 178 if (type_ == FRAME && !((Frame *)this)->size()) { 179 // no need to draw buttons 180 return; 181 } 182 183 // detach button 184 label_->setText(""); 185 label_->setX(width() - borderWidth_ - 3 * monitor_->buttonWidth()); 186 label_->setWidth(monitor_->buttonWidth()); 187 if (buttonState_ != MINCLIENT) { 188 189 Draw::drawDetachButton(frameWindow_, gc_, label_, 190 theme_->BUTTON_BACKGROUND_NORMAL, 191 theme_->BUTTON_SHINE_BORDER_NORMAL, 192 theme_->BUTTON_SHADOW_BORDER_NORMAL, 193 theme_->BUTTON_SHINE_FIGURE_NORMAL, 194 theme_->BUTTON_SHADOW_FIGURE_NORMAL); 195 } 196 else { 197 198 Draw::drawDetachButton(frameWindow_, gc_, label_, 199 theme_->BUTTON_BACKGROUND_PRESSED, 200 theme_->BUTTON_SHINE_BORDER_PRESSED, 201 theme_->BUTTON_SHADOW_BORDER_PRESSED, 202 theme_->BUTTON_SHINE_FIGURE_PRESSED, 203 theme_->BUTTON_SHADOW_FIGURE_PRESSED); 204 } 205 206 // (de)max client button 207 label_->setX(label_->x() + monitor_->buttonWidth()); 208 209 if (buttonState_ != DEMAX) { 210 211 if (type_ == CLIENT) { 212 213 Draw::drawMaxButton(frameWindow_, gc_, label_, 214 theme_->BUTTON_BACKGROUND_NORMAL, 215 theme_->BUTTON_SHINE_BORDER_NORMAL, 216 theme_->BUTTON_SHADOW_BORDER_NORMAL, 217 theme_->BUTTON_SHINE_FIGURE_NORMAL, 218 theme_->BUTTON_SHADOW_FIGURE_NORMAL); 219 } 220 else { 221 222 Draw::drawFloatButton(frameWindow_, gc_, label_, 223 theme_->BUTTON_BACKGROUND_NORMAL, 224 theme_->BUTTON_SHINE_BORDER_NORMAL, 225 theme_->BUTTON_SHADOW_BORDER_NORMAL, 226 theme_->BUTTON_SHINE_FIGURE_NORMAL, 227 theme_->BUTTON_SHADOW_FIGURE_NORMAL); 228 } 229 } 230 else { 231 232 if (type_ == CLIENT) { 233 234 Draw::drawMaxButton(frameWindow_, gc_, label_, 235 theme_->BUTTON_BACKGROUND_PRESSED, 236 theme_->BUTTON_SHINE_BORDER_PRESSED, 237 theme_->BUTTON_SHADOW_BORDER_PRESSED, 238 theme_->BUTTON_SHINE_FIGURE_PRESSED, 239 theme_->BUTTON_SHADOW_FIGURE_PRESSED); 240 } 241 else { 242 243 Draw::drawFloatButton(frameWindow_, gc_, label_, 244 theme_->BUTTON_BACKGROUND_PRESSED, 245 theme_->BUTTON_SHINE_BORDER_PRESSED, 246 theme_->BUTTON_SHADOW_BORDER_PRESSED, 247 theme_->BUTTON_SHINE_FIGURE_PRESSED, 248 theme_->BUTTON_SHADOW_FIGURE_PRESSED); 249 } 250 251 } 252 253 // close button 254 label_->setX(label_->x() + monitor_->buttonWidth()); 255 if (buttonState_ != CLOSE) { 256 257 Draw::drawCloseButton(frameWindow_, gc_, label_, 258 theme_->BUTTON_BACKGROUND_NORMAL, 259 theme_->BUTTON_SHINE_BORDER_NORMAL, 260 theme_->BUTTON_SHADOW_BORDER_NORMAL, 261 theme_->BUTTON_SHINE_FIGURE_NORMAL, 262 theme_->BUTTON_SHADOW_FIGURE_NORMAL); 263 } 264 else { 265 266 Draw::drawCloseButton(frameWindow_, gc_, label_, 267 theme_->BUTTON_BACKGROUND_PRESSED, 268 theme_->BUTTON_SHINE_BORDER_PRESSED, 269 theme_->BUTTON_SHADOW_BORDER_PRESSED, 270 theme_->BUTTON_SHINE_FIGURE_PRESSED, 271 theme_->BUTTON_SHADOW_FIGURE_PRESSED); 272 273 } 274 } 275 } 276 277 void Thing::handleMotionNotify(XMotionEvent *event) { 278 279 if (monitor()->isThingMaximized()) { 280 return; 281 } 282 283 Cursor cursor = cursorForXY(event->x, event->y); 284 285 if (cursor != cursor_) { 286 cursor_ = cursor; 287 KERNEL->installCursor(cursor, frameWindow_); 288 } 289 290 if (buttonState_ != NONE) { 291 buttonState_ = NONE; 292 illuminate(); 293 } 294 } 295 296 void Thing::setTitleBarHeight(unsigned int titleBarHeight) { 297 titleBarHeight_ = titleBarHeight; 298 } 299 300 void Thing::setBorderWidth(unsigned int borderWidth) { 301 borderWidth_ = borderWidth; 302 } 303 304 unsigned int Thing::borderWidth() const { 305 return borderWidth_; 306 } 307 308 unsigned int Thing::titleBarHeight() const { 309 return titleBarHeight_; 310 } 311 312 Rectangle *Thing::prevRectangle() const { 313 return prevRect_; 314 } 315 316 Thing::InvertButton Thing::buttonState() const { 317 return buttonState_; 318 } 319 320 void Thing::setButtonState(InvertButton state) { 321 buttonState_ = state; 322 } 323 324 void Thing::show() { 325 if (frameWindow_) { 326 XCORE->show(frameWindow_); 327 isVisible_ = true; 328 } 329 } 330 331 void Thing::hide() { 332 if (frameWindow_) { 333 XCORE->hide(frameWindow_); 334 isVisible_ = false; 335 } 336 } 337 338 void Thing::fitClientArea() { 339 340 clientAreaRect_.setX(borderWidth_); 341 clientAreaRect_.setY(titleBarHeight_ + borderWidth_ + 342 (titleBarHeight_ ? 1 : 0)); 343 clientAreaRect_.setWidth(width() - 2 * borderWidth_); 344 clientAreaRect_.setHeight(height() - titleBarHeight_ 345 - 2 * borderWidth_ 346 - (titleBarHeight_ ? 1 : 0)); 347 } 348 349 void Thing::setName(string name) { 350 name_ = name; 351 } 352 353 string Thing::name() const { 354 return name_; 355 } 356 357 bool Thing::hasDecoration() const { 358 return hasDecoration_; 359 }