1 /* 2 * Copyright (C) 2003 Apple Computer, Inc. 3 * 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 5 * 6 * Other contributors: 7 * Robert O'Callahan <roc+@cs.cmu.edu> 8 * David Baron <dbaron@fas.harvard.edu> 9 * Christian Biesinger <cbiesinger@web.de> 10 * Randall Jesup <rjesup@wgate.com> 11 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de> 12 * Josh Soref <timeless@mac.com> 13 * Boris Zbarsky <bzbarsky@mit.edu> 14 * 15 * This library is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU Lesser General Public 17 * License as published by the Free Software Foundation; either 18 * version 2.1 of the License, or (at your option) any later version. 19 * 20 * This library is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 * Lesser General Public License for more details. 24 * 25 * You should have received a copy of the GNU Lesser General Public 26 * License along with this library; if not, write to the Free Software 27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28 * 29 * Alternatively, the contents of this file may be used under the terms 30 * of either the Mozilla Public License Version 1.1, found at 31 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public 32 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html 33 * (the "GPL"), in which case the provisions of the MPL or the GPL are 34 * applicable instead of those above. If you wish to allow use of your 35 * version of this file only under the terms of one of those two 36 * licenses (the MPL or the GPL) and not to allow others to use your 37 * version of this file under the LGPL, indicate your decision by 38 * deletingthe provisions above and replace them with the notice and 39 * other provisions required by the MPL or the GPL, as the case may be. 40 * If you do not delete the provisions above, a recipient may use your 41 * version of this file under any of the LGPL, the MPL or the GPL. 42 */ 43 44 #ifndef render_layer_h 45 #define render_layer_h 46 47 #include <QColor> 48 #include <QRect> 49 #include <assert.h> 50 51 #include "render_object.h" 52 53 //template <class T*> class QVector; 54 55 namespace khtml 56 { 57 class RenderObject; 58 class RenderScrollMediator; 59 class ScrollBarWidget; 60 61 class RenderScrollMediator: public QObject 62 { 63 Q_OBJECT 64 public: RenderScrollMediator(RenderLayer * layer)65 RenderScrollMediator(RenderLayer *layer) 66 : m_layer(layer), m_waitingForUpdate(false) {} 67 68 public Q_SLOTS: 69 void slotValueChanged(); 70 71 private: 72 RenderLayer *m_layer; 73 bool m_waitingForUpdate; 74 }; 75 76 // This class handles the auto-scrolling of layers with overflow: marquee. 77 class Marquee: public QObject 78 { 79 Q_OBJECT 80 81 public: 82 Marquee(RenderLayer *l); 83 84 void timerEvent(QTimerEvent *) override; 85 speed()86 int speed() const 87 { 88 return m_speed; 89 } 90 int marqueeSpeed() const; 91 EMarqueeDirection direction() const; reverseDirection()92 EMarqueeDirection reverseDirection() const 93 { 94 return static_cast<EMarqueeDirection>(-direction()); 95 } 96 bool isHorizontal() const; 97 bool isUnfurlMarquee() const; unfurlPos()98 int unfurlPos() const 99 { 100 return m_unfurlPos; 101 } 102 whiteSpace()103 EWhiteSpace whiteSpace() 104 { 105 return KDE_CAST_BF_ENUM(EWhiteSpace, m_whiteSpace); 106 } 107 108 int computePosition(EMarqueeDirection dir, bool stopAtClientEdge); 109 setEnd(int end)110 void setEnd(int end) 111 { 112 m_end = end; 113 } 114 115 void start(); 116 void suspend(); 117 void stop(); 118 119 void updateMarqueeStyle(); 120 void updateMarqueePosition(); 121 122 private: 123 RenderLayer *m_layer; 124 int m_currentLoop; 125 int m_totalLoops; 126 int m_timerId; 127 int m_start; 128 int m_end; 129 int m_speed; 130 int m_unfurlPos; 131 bool m_reset: 1; 132 bool m_suspended: 1; 133 bool m_stopped: 1; 134 KDE_BF_ENUM(EWhiteSpace) m_whiteSpace : 3; 135 KDE_BF_ENUM(EMarqueeDirection) m_direction : 4; 136 }; 137 138 class RenderLayer 139 { 140 public: 141 static ScrollBarWidget *gScrollBar; 142 143 RenderLayer(RenderObject *object); 144 ~RenderLayer(); 145 renderer()146 RenderObject *renderer() const 147 { 148 return m_object; 149 } parent()150 RenderLayer *parent() const 151 { 152 return m_parent; 153 } previousSibling()154 RenderLayer *previousSibling() const 155 { 156 return m_previous; 157 } nextSibling()158 RenderLayer *nextSibling() const 159 { 160 return m_next; 161 } 162 firstChild()163 RenderLayer *firstChild() const 164 { 165 return m_first; 166 } lastChild()167 RenderLayer *lastChild() const 168 { 169 return m_last; 170 } 171 172 void addChild(RenderLayer *newChild, RenderLayer *beforeChild = nullptr); 173 RenderLayer *removeChild(RenderLayer *oldChild); 174 175 void removeOnlyThisLayer(); 176 void insertOnlyThisLayer(); 177 178 void styleChanged(); 179 marquee()180 Marquee *marquee() const 181 { 182 return m_marquee; 183 } 184 void suspendMarquees(); 185 isOverflowOnly()186 bool isOverflowOnly() const 187 { 188 return m_isOverflowOnly; 189 } 190 191 bool isTransparent() const; 192 RenderLayer *transparentAncestor() const; 193 root()194 RenderLayer *root() 195 { 196 RenderLayer *curr = this; 197 while (curr->parent()) { 198 curr = curr->parent(); 199 } 200 return curr; 201 } 202 xPos()203 int xPos() const 204 { 205 return m_x; 206 } yPos()207 int yPos() const 208 { 209 return m_y; 210 } 211 212 int width() const; 213 int height() const; 214 scrollWidth()215 int scrollWidth() const 216 { 217 return m_scrollWidth; 218 } scrollHeight()219 int scrollHeight() const 220 { 221 return m_scrollHeight; 222 } 223 resize(int w,int h)224 void resize(int w, int h) 225 { 226 m_scrollWidth = w; m_scrollHeight = h; 227 } 228 setPos(int xPos,int yPos)229 void setPos(int xPos, int yPos) 230 { 231 m_x = xPos; 232 m_y = yPos; 233 } 234 235 // Scrolling methods for layers that can scroll their overflow. 236 void scrollOffset(int &x, int &y); 237 void subtractScrollOffset(int &x, int &y); 238 void checkInlineRelOffset(const RenderObject *o, int &x, int &y); scrollXOffset()239 int scrollXOffset() 240 { 241 return m_scrollX + m_scrollXOrigin; 242 } scrollYOffset()243 int scrollYOffset() 244 { 245 return m_scrollY; 246 } 247 void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true, bool dispatchEvent = true); scrollToXOffset(int x)248 void scrollToXOffset(int x) 249 { 250 scrollToOffset(x, m_scrollY); 251 } scrollToYOffset(int y)252 void scrollToYOffset(int y) 253 { 254 scrollToOffset(m_scrollX + m_scrollXOrigin, y); 255 } resetXOffset()256 void resetXOffset() 257 { 258 scrollToOffset(0, m_scrollY, false, false, false); 259 } resetYOffset()260 void resetYOffset() 261 { 262 scrollToOffset(m_scrollX + m_scrollXOrigin, 0, false, false, false); 263 } 264 void showScrollbar(Qt::Orientation, bool); horizontalScrollbar()265 ScrollBarWidget *horizontalScrollbar() 266 { 267 return m_hBar; 268 } verticalScrollbar()269 ScrollBarWidget *verticalScrollbar() 270 { 271 return m_vBar; 272 } 273 bool hasReversedScrollbar() const; 274 int verticalScrollbarWidth(); 275 int horizontalScrollbarHeight(); 276 void positionScrollbars(const QRect &damageRect); 277 void paintScrollbars(RenderObject::PaintInfo &pI); 278 void checkScrollbarsAfterLayout(); 279 void slotValueChanged(int); 280 void repaint(Priority p = NormalPriority, bool markForRepaint = false); 281 void updateScrollPositionFromScrollbars(); 282 283 void updateLayerPosition(); 284 void updateLayerPositions(RenderLayer *rootLayer, bool doFullRepaint = false, bool checkForRepaint = false); 285 286 // Get the enclosing stacking context for this layer. A stacking context is a layer 287 // that has a non-auto z-index. 288 RenderLayer *stackingContext() const; isStackingContext()289 bool isStackingContext() const 290 { 291 return !hasAutoZIndex() || renderer()->isCanvas(); 292 } 293 294 void dirtyZOrderLists(); 295 void updateZOrderLists(); posZOrderList()296 QVector<RenderLayer *> *posZOrderList() const 297 { 298 return m_posZOrderList; 299 } negZOrderList()300 QVector<RenderLayer *> *negZOrderList() const 301 { 302 return m_negZOrderList; 303 } 304 305 void dirtyOverflowList(); 306 void updateOverflowList(); overflowList()307 QVector<RenderLayer *> *overflowList() const 308 { 309 return m_overflowList; 310 } 311 hasVisibleContent()312 bool hasVisibleContent() const 313 { 314 return m_hasVisibleContent; 315 } 316 void setHasVisibleContent(bool b); 317 void dirtyVisibleContentStatus(); 318 319 void setHasOverlaidWidgets(bool b = true) 320 { 321 m_hasOverlaidWidgets = b; 322 } hasOverlaidWidgets()323 bool hasOverlaidWidgets() const 324 { 325 return m_hasOverlaidWidgets; 326 } getMask()327 QRegion getMask() const 328 { 329 return m_region; 330 } 331 QRegion paintedRegion(RenderLayer *rootLayer); 332 void updateWidgetMasks(RenderLayer *rootLayer); 333 334 // Gets the nearest enclosing positioned ancestor layer (also includes 335 // the <html> layer and the root layer). 336 RenderLayer *enclosingPositionedAncestor() const; 337 338 void convertToLayerCoords(const RenderLayer *ancestorLayer, int &x, int &y) const; 339 hasAutoZIndex()340 bool hasAutoZIndex() const 341 { 342 return renderer()->style()->hasAutoZIndex(); 343 } zIndex()344 int zIndex() const 345 { 346 return renderer()->style()->zIndex(); 347 } 348 349 // The two main functions that use the layer system. The paint method 350 // paints the layers that intersect the damage rect from back to 351 // front. The nodeAtPoint method looks for mouse events by walking 352 // layers that intersect the point from front to back. 353 KHTML_EXPORT void paint(QPainter *p, const QRect &damageRect, bool selectionOnly = false); 354 bool nodeAtPoint(RenderObject::NodeInfo &info, int x, int y); 355 356 // This method figures out our layerBounds in coordinates relative to 357 // |rootLayer}. It also computes our background and foreground clip rects 358 // for painting/event handling. 359 void calculateRects(const RenderLayer *rootLayer, const QRect &paintDirtyRect, QRect &layerBounds, 360 QRect &backgroundRect, QRect &foregroundRect); 361 void calculateClipRects(const RenderLayer *rootLayer, QRect &overflowClipRect, 362 QRect &posClipRect, QRect &fixedClipRect); 363 364 bool intersectsDamageRect(const QRect &layerBounds, const QRect &damageRect) const; 365 bool containsPoint(int x, int y, const QRect &damageRect) const; 366 367 void updateHoverActiveState(RenderObject::NodeInfo &info); 368 369 void detach(RenderArena *renderArena); 370 371 #ifdef ENABLE_DUMP 372 KHTML_EXPORT void dump(QTextStream &stream, const QString &ind = QString()); 373 #endif 374 375 // Overloaded new operator. Derived classes must override operator new 376 // in order to allocate out of the RenderArena. 377 void *operator new(size_t sz, RenderArena *renderArena) throw(); 378 379 // Overridden to prevent the normal delete from being called. 380 void operator delete(void *ptr, size_t sz); 381 382 private: 383 // The normal operator new is disallowed on all render objects. 384 void *operator new(size_t sz) throw(); 385 386 private: setNextSibling(RenderLayer * next)387 void setNextSibling(RenderLayer *next) 388 { 389 m_next = next; 390 } setPreviousSibling(RenderLayer * prev)391 void setPreviousSibling(RenderLayer *prev) 392 { 393 m_previous = prev; 394 } setParent(RenderLayer * parent)395 void setParent(RenderLayer *parent) 396 { 397 m_parent = parent; 398 } setFirstChild(RenderLayer * first)399 void setFirstChild(RenderLayer *first) 400 { 401 m_first = first; 402 } setLastChild(RenderLayer * last)403 void setLastChild(RenderLayer *last) 404 { 405 m_last = last; 406 } 407 408 void collectLayers(QVector<RenderLayer *> *&, QVector<RenderLayer *> *&); 409 410 KHTML_EXPORT void paintLayer(RenderLayer *rootLayer, QPainter *p, const QRect &paintDirtyRect, bool selectionOnly = false); 411 RenderLayer *nodeAtPointForLayer(RenderLayer *rootLayer, RenderObject::NodeInfo &info, 412 int x, int y, const QRect &hitTestRect); 413 bool shouldBeOverflowOnly() const; 414 415 void childVisibilityChanged(bool newVisibility); 416 void dirtyVisibleDescendantStatus(); 417 void updateVisibilityStatus(); 418 419 protected: 420 void setClip(QPainter *p, const QRect &paintDirtyRect, const QRect &clipRect, bool setup = false); 421 void restoreClip(QPainter *p, const QRect &paintDirtyRect, const QRect &clipRect, bool cleanup = false); 422 423 RenderObject *m_object; 424 425 RenderLayer *m_parent; 426 RenderLayer *m_previous; 427 RenderLayer *m_next; 428 429 RenderLayer *m_first; 430 RenderLayer *m_last; 431 432 // Our (x,y) coordinates are in our parent layer's coordinate space. 433 int m_x; 434 int m_y; 435 436 // Our scroll offsets if the view is scrolled. 437 int m_scrollX; 438 int m_scrollY; 439 440 // the reference for our x offset (will vary depending on layout direction) 441 int m_scrollXOrigin; 442 443 // The width/height of our scrolled area. 444 int m_scrollWidth; 445 int m_scrollHeight; 446 447 // For layers with overflow, we have a pair of scrollbars. 448 ScrollBarWidget *m_hBar; 449 ScrollBarWidget *m_vBar; 450 QPixmap *m_buffer[2]; 451 452 RenderScrollMediator *m_scrollMediator; 453 454 // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the 455 // descendant layers within the stacking context that have z-indices of 0 or greater 456 // (auto will count as 0). m_negZOrderList holds descendants within our stacking context with negative 457 // z-indices. 458 QVector<RenderLayer *> *m_posZOrderList; 459 QVector<RenderLayer *> *m_negZOrderList; 460 461 // This list contains our overflow child layers. 462 QVector<RenderLayer *> *m_overflowList; 463 464 bool m_zOrderListsDirty: 1; 465 bool m_overflowListDirty: 1; 466 bool m_isOverflowOnly: 1; 467 bool m_markedForRepaint: 1; 468 bool m_hasOverlaidWidgets: 1; 469 bool m_visibleContentStatusDirty : 1; 470 bool m_hasVisibleContent : 1; 471 bool m_visibleDescendantStatusDirty : 1; 472 bool m_hasVisibleDescendant : 1; 473 bool m_inScrollbarRelayout : 1; 474 bool m_wasStackingContext : 1; // set to 1 when last style application 475 // establised us as a stacking context 476 477 QRect m_visibleRect; 478 479 QRegion m_region; // used by overlaid (non z-order aware) widgets 480 481 Marquee *m_marquee; // Used by layers with overflow:marquee 482 }; 483 484 } // namespace 485 #endif 486