1 /** 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2000 Simon Hausmann <hausmann (at) kde.org> 4 * (C) 2000 Stefan Schimanski (1Stein (at) gmx.de) 5 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 * 22 */ 23 24 #include "config.h" 25 #include "core/rendering/RenderFrameSet.h" 26 27 #include "core/dom/Document.h" 28 #include "core/dom/EventNames.h" 29 #include "core/dom/MouseEvent.h" 30 #include "core/html/HTMLDimension.h" 31 #include "core/html/HTMLFrameSetElement.h" 32 #include "core/page/EventHandler.h" 33 #include "core/page/Frame.h" 34 #include "core/platform/Cursor.h" 35 #include "core/platform/graphics/GraphicsContext.h" 36 #include "core/rendering/PaintInfo.h" 37 #include "core/rendering/RenderFrame.h" 38 #include "core/rendering/RenderView.h" 39 40 namespace WebCore { 41 42 RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet) 43 : RenderBox(frameSet) 44 , m_isResizing(false) 45 , m_isChildResizing(false) 46 { 47 setInline(false); 48 } 49 50 RenderFrameSet::~RenderFrameSet() 51 { 52 } 53 54 RenderFrameSet::GridAxis::GridAxis() 55 : m_splitBeingResized(noSplit) 56 { 57 } 58 59 inline HTMLFrameSetElement* RenderFrameSet::frameSet() const 60 { 61 return static_cast<HTMLFrameSetElement*>(node()); 62 } 63 64 static Color borderStartEdgeColor() 65 { 66 return Color(170, 170, 170); 67 } 68 69 static Color borderEndEdgeColor() 70 { 71 return Color::black; 72 } 73 74 static Color borderFillColor() 75 { 76 return Color(208, 208, 208); 77 } 78 79 void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect& borderRect) 80 { 81 if (!paintInfo.rect.intersects(borderRect)) 82 return; 83 84 // FIXME: We should do something clever when borders from distinct framesets meet at a join. 85 86 // Fill first. 87 GraphicsContext* context = paintInfo.context; 88 context->fillRect(borderRect, frameSet()->hasBorderColor() ? resolveColor(CSSPropertyBorderLeftColor) : borderFillColor()); 89 90 // Now stroke the edges but only if we have enough room to paint both edges with a little 91 // bit of the fill color showing through. 92 if (borderRect.width() >= 3) { 93 context->fillRect(IntRect(borderRect.location(), IntSize(1, height())), borderStartEdgeColor()); 94 context->fillRect(IntRect(IntPoint(borderRect.maxX() - 1, borderRect.y()), IntSize(1, height())), borderEndEdgeColor()); 95 } 96 } 97 98 void RenderFrameSet::paintRowBorder(const PaintInfo& paintInfo, const IntRect& borderRect) 99 { 100 if (!paintInfo.rect.intersects(borderRect)) 101 return; 102 103 // FIXME: We should do something clever when borders from distinct framesets meet at a join. 104 105 // Fill first. 106 GraphicsContext* context = paintInfo.context; 107 context->fillRect(borderRect, frameSet()->hasBorderColor() ? resolveColor(CSSPropertyBorderLeftColor) : borderFillColor()); 108 109 // Now stroke the edges but only if we have enough room to paint both edges with a little 110 // bit of the fill color showing through. 111 if (borderRect.height() >= 3) { 112 context->fillRect(IntRect(borderRect.location(), IntSize(width(), 1)), borderStartEdgeColor()); 113 context->fillRect(IntRect(IntPoint(borderRect.x(), borderRect.maxY() - 1), IntSize(width(), 1)), borderEndEdgeColor()); 114 } 115 } 116 117 void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) 118 { 119 ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this); 120 121 if (paintInfo.phase != PaintPhaseForeground) 122 return; 123 124 RenderObject* child = firstChild(); 125 if (!child) 126 return; 127 128 LayoutPoint adjustedPaintOffset = paintOffset + location(); 129 130 size_t rows = m_rows.m_sizes.size(); 131 size_t cols = m_cols.m_sizes.size(); 132 LayoutUnit borderThickness = frameSet()->border(); 133 134 LayoutUnit yPos = 0; 135 for (size_t r = 0; r < rows; r++) { 136 LayoutUnit xPos = 0; 137 for (size_t c = 0; c < cols; c++) { 138 child->paint(paintInfo, adjustedPaintOffset); 139 xPos += m_cols.m_sizes[c]; 140 if (borderThickness && m_cols.m_allowBorder[c + 1]) { 141 paintColumnBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x() + xPos, adjustedPaintOffset.y() + yPos, borderThickness, height()))); 142 xPos += borderThickness; 143 } 144 child = child->nextSibling(); 145 if (!child) 146 return; 147 } 148 yPos += m_rows.m_sizes[r]; 149 if (borderThickness && m_rows.m_allowBorder[r + 1]) { 150 paintRowBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x(), adjustedPaintOffset.y() + yPos, width(), borderThickness))); 151 yPos += borderThickness; 152 } 153 } 154 } 155 156 void RenderFrameSet::GridAxis::resize(int size) 157 { 158 m_sizes.resize(size); 159 m_deltas.resize(size); 160 m_deltas.fill(0); 161 162 // To track edges for resizability and borders, we need to be (size + 1). This is because a parent frameset 163 // may ask us for information about our left/top/right/bottom edges in order to make its own decisions about 164 // what to do. We are capable of tainting that parent frameset's borders, so we have to cache this info. 165 m_preventResize.resize(size + 1); 166 m_allowBorder.resize(size + 1); 167 } 168 169 void RenderFrameSet::layOutAxis(GridAxis& axis, const Vector<HTMLDimension>& grid, int availableLen) 170 { 171 availableLen = max(availableLen, 0); 172 173 int* gridLayout = axis.m_sizes.data(); 174 175 if (grid.isEmpty()) { 176 gridLayout[0] = availableLen; 177 return; 178 } 179 180 int gridLen = axis.m_sizes.size(); 181 ASSERT(gridLen); 182 183 int totalRelative = 0; 184 int totalFixed = 0; 185 int totalPercent = 0; 186 int countRelative = 0; 187 int countFixed = 0; 188 int countPercent = 0; 189 190 // First we need to investigate how many columns of each type we have and 191 // how much space these columns are going to require. 192 for (int i = 0; i < gridLen; ++i) { 193 // Count the total length of all of the fixed columns/rows -> totalFixed 194 // Count the number of columns/rows which are fixed -> countFixed 195 if (grid[i].isAbsolute()) { 196 gridLayout[i] = max<int>(grid[i].value(), 0); 197 totalFixed += gridLayout[i]; 198 countFixed++; 199 } 200 201 // Count the total percentage of all of the percentage columns/rows -> totalPercent 202 // Count the number of columns/rows which are percentages -> countPercent 203 if (grid[i].isPercentage()) { 204 gridLayout[i] = max<int>(grid[i].value() * availableLen / 100., 0); 205 totalPercent += gridLayout[i]; 206 countPercent++; 207 } 208 209 // Count the total relative of all the relative columns/rows -> totalRelative 210 // Count the number of columns/rows which are relative -> countRelative 211 if (grid[i].isRelative()) { 212 totalRelative += max<int>(grid[i].value(), 1); 213 countRelative++; 214 } 215 } 216 217 int remainingLen = availableLen; 218 219 // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed 220 // columns/rows we need to proportionally adjust their size. 221 if (totalFixed > remainingLen) { 222 int remainingFixed = remainingLen; 223 224 for (int i = 0; i < gridLen; ++i) { 225 if (grid[i].isAbsolute()) { 226 gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed; 227 remainingLen -= gridLayout[i]; 228 } 229 } 230 } else 231 remainingLen -= totalFixed; 232 233 // Percentage columns/rows are our second priority. Divide the remaining space proportionally 234 // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative 235 // to 100%, but to the total percentage. For example, if there are three columns, each of 75%, 236 // and the available space is 300px, each column will become 100px in width. 237 if (totalPercent > remainingLen) { 238 int remainingPercent = remainingLen; 239 240 for (int i = 0; i < gridLen; ++i) { 241 if (grid[i].isPercentage()) { 242 gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent; 243 remainingLen -= gridLayout[i]; 244 } 245 } 246 } else 247 remainingLen -= totalPercent; 248 249 // Relative columns/rows are our last priority. Divide the remaining space proportionally 250 // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*. 251 if (countRelative) { 252 int lastRelative = 0; 253 int remainingRelative = remainingLen; 254 255 for (int i = 0; i < gridLen; ++i) { 256 if (grid[i].isRelative()) { 257 gridLayout[i] = (max(grid[i].value(), 1.) * remainingRelative) / totalRelative; 258 remainingLen -= gridLayout[i]; 259 lastRelative = i; 260 } 261 } 262 263 // If we could not evenly distribute the available space of all of the relative 264 // columns/rows, the remainder will be added to the last column/row. 265 // For example: if we have a space of 100px and three columns (*,*,*), the remainder will 266 // be 1px and will be added to the last column: 33px, 33px, 34px. 267 if (remainingLen) { 268 gridLayout[lastRelative] += remainingLen; 269 remainingLen = 0; 270 } 271 } 272 273 // If we still have some left over space we need to divide it over the already existing 274 // columns/rows 275 if (remainingLen) { 276 // Our first priority is to spread if over the percentage columns. The remaining 277 // space is spread evenly, for example: if we have a space of 100px, the columns 278 // definition of 25%,25% used to result in two columns of 25px. After this the 279 // columns will each be 50px in width. 280 if (countPercent && totalPercent) { 281 int remainingPercent = remainingLen; 282 int changePercent = 0; 283 284 for (int i = 0; i < gridLen; ++i) { 285 if (grid[i].isPercentage()) { 286 changePercent = (remainingPercent * gridLayout[i]) / totalPercent; 287 gridLayout[i] += changePercent; 288 remainingLen -= changePercent; 289 } 290 } 291 } else if (totalFixed) { 292 // Our last priority is to spread the remaining space over the fixed columns. 293 // For example if we have 100px of space and two column of each 40px, both 294 // columns will become exactly 50px. 295 int remainingFixed = remainingLen; 296 int changeFixed = 0; 297 298 for (int i = 0; i < gridLen; ++i) { 299 if (grid[i].isAbsolute()) { 300 changeFixed = (remainingFixed * gridLayout[i]) / totalFixed; 301 gridLayout[i] += changeFixed; 302 remainingLen -= changeFixed; 303 } 304 } 305 } 306 } 307 308 // If we still have some left over space we probably ended up with a remainder of 309 // a division. We cannot spread it evenly anymore. If we have any percentage 310 // columns/rows simply spread the remainder equally over all available percentage columns, 311 // regardless of their size. 312 if (remainingLen && countPercent) { 313 int remainingPercent = remainingLen; 314 int changePercent = 0; 315 316 for (int i = 0; i < gridLen; ++i) { 317 if (grid[i].isPercentage()) { 318 changePercent = remainingPercent / countPercent; 319 gridLayout[i] += changePercent; 320 remainingLen -= changePercent; 321 } 322 } 323 } else if (remainingLen && countFixed) { 324 // If we don't have any percentage columns/rows we only have 325 // fixed columns. Spread the remainder equally over all fixed 326 // columns/rows. 327 int remainingFixed = remainingLen; 328 int changeFixed = 0; 329 330 for (int i = 0; i < gridLen; ++i) { 331 if (grid[i].isAbsolute()) { 332 changeFixed = remainingFixed / countFixed; 333 gridLayout[i] += changeFixed; 334 remainingLen -= changeFixed; 335 } 336 } 337 } 338 339 // Still some left over. Add it to the last column, because it is impossible 340 // spread it evenly or equally. 341 if (remainingLen) 342 gridLayout[gridLen - 1] += remainingLen; 343 344 // now we have the final layout, distribute the delta over it 345 bool worked = true; 346 int* gridDelta = axis.m_deltas.data(); 347 for (int i = 0; i < gridLen; ++i) { 348 if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0) 349 worked = false; 350 gridLayout[i] += gridDelta[i]; 351 } 352 // if the deltas broke something, undo them 353 if (!worked) { 354 for (int i = 0; i < gridLen; ++i) 355 gridLayout[i] -= gridDelta[i]; 356 axis.m_deltas.fill(0); 357 } 358 } 359 360 void RenderFrameSet::notifyFrameEdgeInfoChanged() 361 { 362 if (needsLayout()) 363 return; 364 // FIXME: We should only recompute the edge info with respect to the frame that changed 365 // and its adjacent frame(s) instead of recomputing the edge info for the entire frameset. 366 computeEdgeInfo(); 367 } 368 369 void RenderFrameSet::fillFromEdgeInfo(const FrameEdgeInfo& edgeInfo, int r, int c) 370 { 371 if (edgeInfo.allowBorder(LeftFrameEdge)) 372 m_cols.m_allowBorder[c] = true; 373 if (edgeInfo.allowBorder(RightFrameEdge)) 374 m_cols.m_allowBorder[c + 1] = true; 375 if (edgeInfo.preventResize(LeftFrameEdge)) 376 m_cols.m_preventResize[c] = true; 377 if (edgeInfo.preventResize(RightFrameEdge)) 378 m_cols.m_preventResize[c + 1] = true; 379 380 if (edgeInfo.allowBorder(TopFrameEdge)) 381 m_rows.m_allowBorder[r] = true; 382 if (edgeInfo.allowBorder(BottomFrameEdge)) 383 m_rows.m_allowBorder[r + 1] = true; 384 if (edgeInfo.preventResize(TopFrameEdge)) 385 m_rows.m_preventResize[r] = true; 386 if (edgeInfo.preventResize(BottomFrameEdge)) 387 m_rows.m_preventResize[r + 1] = true; 388 } 389 390 void RenderFrameSet::computeEdgeInfo() 391 { 392 m_rows.m_preventResize.fill(frameSet()->noResize()); 393 m_rows.m_allowBorder.fill(false); 394 m_cols.m_preventResize.fill(frameSet()->noResize()); 395 m_cols.m_allowBorder.fill(false); 396 397 RenderObject* child = firstChild(); 398 if (!child) 399 return; 400 401 size_t rows = m_rows.m_sizes.size(); 402 size_t cols = m_cols.m_sizes.size(); 403 for (size_t r = 0; r < rows; ++r) { 404 for (size_t c = 0; c < cols; ++c) { 405 FrameEdgeInfo edgeInfo; 406 if (child->isFrameSet()) 407 edgeInfo = toRenderFrameSet(child)->edgeInfo(); 408 else 409 edgeInfo = toRenderFrame(child)->edgeInfo(); 410 fillFromEdgeInfo(edgeInfo, r, c); 411 child = child->nextSibling(); 412 if (!child) 413 return; 414 } 415 } 416 } 417 418 FrameEdgeInfo RenderFrameSet::edgeInfo() const 419 { 420 FrameEdgeInfo result(frameSet()->noResize(), true); 421 422 int rows = frameSet()->totalRows(); 423 int cols = frameSet()->totalCols(); 424 if (rows && cols) { 425 result.setPreventResize(LeftFrameEdge, m_cols.m_preventResize[0]); 426 result.setAllowBorder(LeftFrameEdge, m_cols.m_allowBorder[0]); 427 result.setPreventResize(RightFrameEdge, m_cols.m_preventResize[cols]); 428 result.setAllowBorder(RightFrameEdge, m_cols.m_allowBorder[cols]); 429 result.setPreventResize(TopFrameEdge, m_rows.m_preventResize[0]); 430 result.setAllowBorder(TopFrameEdge, m_rows.m_allowBorder[0]); 431 result.setPreventResize(BottomFrameEdge, m_rows.m_preventResize[rows]); 432 result.setAllowBorder(BottomFrameEdge, m_rows.m_allowBorder[rows]); 433 } 434 435 return result; 436 } 437 438 void RenderFrameSet::layout() 439 { 440 StackStats::LayoutCheckPoint layoutCheckPoint; 441 ASSERT(needsLayout()); 442 443 bool doFullRepaint = selfNeedsLayout() && checkForRepaintDuringLayout(); 444 LayoutRect oldBounds; 445 RenderLayerModelObject* repaintContainer = 0; 446 if (doFullRepaint) { 447 repaintContainer = containerForRepaint(); 448 oldBounds = clippedOverflowRectForRepaint(repaintContainer); 449 } 450 451 if (!parent()->isFrameSet() && !document()->printing()) { 452 setWidth(view()->viewWidth()); 453 setHeight(view()->viewHeight()); 454 } 455 456 unsigned cols = frameSet()->totalCols(); 457 unsigned rows = frameSet()->totalRows(); 458 459 if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) { 460 m_rows.resize(rows); 461 m_cols.resize(cols); 462 } 463 464 LayoutUnit borderThickness = frameSet()->border(); 465 layOutAxis(m_rows, frameSet()->rowLengths(), height() - (rows - 1) * borderThickness); 466 layOutAxis(m_cols, frameSet()->colLengths(), width() - (cols - 1) * borderThickness); 467 468 positionFrames(); 469 470 RenderBox::layout(); 471 472 computeEdgeInfo(); 473 474 updateLayerTransform(); 475 476 if (doFullRepaint) { 477 repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds)); 478 LayoutRect newBounds = clippedOverflowRectForRepaint(repaintContainer); 479 if (newBounds != oldBounds) 480 repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds)); 481 } 482 483 clearNeedsLayout(); 484 } 485 486 void RenderFrameSet::positionFrames() 487 { 488 RenderBox* child = firstChildBox(); 489 if (!child) 490 return; 491 492 int rows = frameSet()->totalRows(); 493 int cols = frameSet()->totalCols(); 494 495 int yPos = 0; 496 int borderThickness = frameSet()->border(); 497 for (int r = 0; r < rows; r++) { 498 int xPos = 0; 499 int height = m_rows.m_sizes[r]; 500 for (int c = 0; c < cols; c++) { 501 child->setLocation(IntPoint(xPos, yPos)); 502 int width = m_cols.m_sizes[c]; 503 504 // has to be resized and itself resize its contents 505 if (width != child->width() || height != child->height()) { 506 child->setWidth(width); 507 child->setHeight(height); 508 child->setNeedsLayout(); 509 child->layout(); 510 } 511 512 xPos += width + borderThickness; 513 514 child = child->nextSiblingBox(); 515 if (!child) 516 return; 517 } 518 yPos += height + borderThickness; 519 } 520 521 // all the remaining frames are hidden to avoid ugly spurious unflowed frames 522 for (; child; child = child->nextSiblingBox()) { 523 child->setWidth(0); 524 child->setHeight(0); 525 child->clearNeedsLayout(); 526 } 527 } 528 529 void RenderFrameSet::startResizing(GridAxis& axis, int position) 530 { 531 int split = hitTestSplit(axis, position); 532 if (split == noSplit || axis.m_preventResize[split]) { 533 axis.m_splitBeingResized = noSplit; 534 return; 535 } 536 axis.m_splitBeingResized = split; 537 axis.m_splitResizeOffset = position - splitPosition(axis, split); 538 } 539 540 void RenderFrameSet::continueResizing(GridAxis& axis, int position) 541 { 542 if (needsLayout()) 543 return; 544 if (axis.m_splitBeingResized == noSplit) 545 return; 546 int currentSplitPosition = splitPosition(axis, axis.m_splitBeingResized); 547 int delta = (position - currentSplitPosition) - axis.m_splitResizeOffset; 548 if (!delta) 549 return; 550 axis.m_deltas[axis.m_splitBeingResized - 1] += delta; 551 axis.m_deltas[axis.m_splitBeingResized] -= delta; 552 setNeedsLayout(); 553 } 554 555 bool RenderFrameSet::userResize(MouseEvent* evt) 556 { 557 if (!m_isResizing) { 558 if (needsLayout()) 559 return false; 560 if (evt->type() == eventNames().mousedownEvent && evt->button() == LeftButton) { 561 FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms); 562 startResizing(m_cols, localPos.x()); 563 startResizing(m_rows, localPos.y()); 564 if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) { 565 setIsResizing(true); 566 return true; 567 } 568 } 569 } else { 570 if (evt->type() == eventNames().mousemoveEvent || (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton)) { 571 FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms); 572 continueResizing(m_cols, localPos.x()); 573 continueResizing(m_rows, localPos.y()); 574 if (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton) { 575 setIsResizing(false); 576 return true; 577 } 578 } 579 } 580 581 return false; 582 } 583 584 void RenderFrameSet::setIsResizing(bool isResizing) 585 { 586 m_isResizing = isResizing; 587 for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { 588 if (ancestor->isFrameSet()) 589 toRenderFrameSet(ancestor)->m_isChildResizing = isResizing; 590 } 591 if (Frame* frame = this->frame()) 592 frame->eventHandler()->setResizingFrameSet(isResizing ? frameSet() : 0); 593 } 594 595 bool RenderFrameSet::isResizingRow() const 596 { 597 return m_isResizing && m_rows.m_splitBeingResized != noSplit; 598 } 599 600 bool RenderFrameSet::isResizingColumn() const 601 { 602 return m_isResizing && m_cols.m_splitBeingResized != noSplit; 603 } 604 605 bool RenderFrameSet::canResizeRow(const IntPoint& p) const 606 { 607 int r = hitTestSplit(m_rows, p.y()); 608 return r != noSplit && !m_rows.m_preventResize[r]; 609 } 610 611 bool RenderFrameSet::canResizeColumn(const IntPoint& p) const 612 { 613 int c = hitTestSplit(m_cols, p.x()); 614 return c != noSplit && !m_cols.m_preventResize[c]; 615 } 616 617 int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const 618 { 619 if (needsLayout()) 620 return 0; 621 622 int borderThickness = frameSet()->border(); 623 624 int size = axis.m_sizes.size(); 625 if (!size) 626 return 0; 627 628 int position = 0; 629 for (int i = 0; i < split && i < size; ++i) 630 position += axis.m_sizes[i] + borderThickness; 631 return position - borderThickness; 632 } 633 634 int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const 635 { 636 if (needsLayout()) 637 return noSplit; 638 639 int borderThickness = frameSet()->border(); 640 if (borderThickness <= 0) 641 return noSplit; 642 643 size_t size = axis.m_sizes.size(); 644 if (!size) 645 return noSplit; 646 647 int splitPosition = axis.m_sizes[0]; 648 for (size_t i = 1; i < size; ++i) { 649 if (position >= splitPosition && position < splitPosition + borderThickness) 650 return i; 651 splitPosition += borderThickness + axis.m_sizes[i]; 652 } 653 return noSplit; 654 } 655 656 bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle*) const 657 { 658 return child->isFrame() || child->isFrameSet(); 659 } 660 661 CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& cursor) const 662 { 663 IntPoint roundedPoint = roundedIntPoint(point); 664 if (canResizeRow(roundedPoint)) { 665 cursor = rowResizeCursor(); 666 return SetCursor; 667 } 668 if (canResizeColumn(roundedPoint)) { 669 cursor = columnResizeCursor(); 670 return SetCursor; 671 } 672 return RenderBox::getCursor(point, cursor); 673 } 674 675 } // namespace WebCore 676