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/events/MouseEvent.h" 29 #include "core/frame/LocalFrame.h" 30 #include "core/html/HTMLDimension.h" 31 #include "core/html/HTMLFrameSetElement.h" 32 #include "core/page/EventHandler.h" 33 #include "core/rendering/GraphicsContextAnnotator.h" 34 #include "core/rendering/PaintInfo.h" 35 #include "core/rendering/RenderFrame.h" 36 #include "core/rendering/RenderView.h" 37 #include "platform/Cursor.h" 38 #include "platform/graphics/GraphicsContext.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 toHTMLFrameSetElement(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 ASSERT(needsLayout()); 441 442 bool doFullRepaint = selfNeedsLayout() && checkForPaintInvalidationDuringLayout(); 443 LayoutRect oldBounds; 444 const RenderLayerModelObject* repaintContainer = 0; 445 if (doFullRepaint) { 446 repaintContainer = containerForPaintInvalidation(); 447 oldBounds = boundsRectForPaintInvalidation(repaintContainer); 448 } 449 450 if (!parent()->isFrameSet() && !document().printing()) { 451 setWidth(view()->viewWidth()); 452 setHeight(view()->viewHeight()); 453 } 454 455 unsigned cols = frameSet()->totalCols(); 456 unsigned rows = frameSet()->totalRows(); 457 458 if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) { 459 m_rows.resize(rows); 460 m_cols.resize(cols); 461 } 462 463 LayoutUnit borderThickness = frameSet()->border(); 464 layOutAxis(m_rows, frameSet()->rowLengths(), height() - (rows - 1) * borderThickness); 465 layOutAxis(m_cols, frameSet()->colLengths(), width() - (cols - 1) * borderThickness); 466 467 positionFrames(); 468 469 RenderBox::layout(); 470 471 computeEdgeInfo(); 472 473 updateLayerTransformAfterLayout(); 474 475 if (doFullRepaint) { 476 invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds), InvalidationSelfLayout); 477 LayoutRect newBounds = boundsRectForPaintInvalidation(repaintContainer); 478 if (newBounds != oldBounds) 479 invalidatePaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds), InvalidationSelfLayout); 480 } 481 482 clearNeedsLayout(); 483 } 484 485 static void clearNeedsLayoutOnHiddenFrames(RenderBox* frame) 486 { 487 for (; frame; frame = frame->nextSiblingBox()) { 488 frame->setWidth(0); 489 frame->setHeight(0); 490 frame->clearNeedsLayout(); 491 clearNeedsLayoutOnHiddenFrames(frame->firstChildBox()); 492 } 493 } 494 495 void RenderFrameSet::positionFrames() 496 { 497 RenderBox* child = firstChildBox(); 498 if (!child) 499 return; 500 501 int rows = frameSet()->totalRows(); 502 int cols = frameSet()->totalCols(); 503 504 int yPos = 0; 505 int borderThickness = frameSet()->border(); 506 for (int r = 0; r < rows; r++) { 507 int xPos = 0; 508 int height = m_rows.m_sizes[r]; 509 for (int c = 0; c < cols; c++) { 510 child->setLocation(IntPoint(xPos, yPos)); 511 int width = m_cols.m_sizes[c]; 512 513 // has to be resized and itself resize its contents 514 if (width != child->width() || height != child->height()) { 515 child->setWidth(width); 516 child->setHeight(height); 517 child->setNeedsLayoutAndFullPaintInvalidation(); 518 child->layout(); 519 } 520 521 xPos += width + borderThickness; 522 523 child = child->nextSiblingBox(); 524 if (!child) 525 return; 526 } 527 yPos += height + borderThickness; 528 } 529 530 // All the remaining frames are hidden to avoid ugly spurious unflowed frames. 531 clearNeedsLayoutOnHiddenFrames(child); 532 } 533 534 void RenderFrameSet::startResizing(GridAxis& axis, int position) 535 { 536 int split = hitTestSplit(axis, position); 537 if (split == noSplit || axis.m_preventResize[split]) { 538 axis.m_splitBeingResized = noSplit; 539 return; 540 } 541 axis.m_splitBeingResized = split; 542 axis.m_splitResizeOffset = position - splitPosition(axis, split); 543 } 544 545 void RenderFrameSet::continueResizing(GridAxis& axis, int position) 546 { 547 if (needsLayout()) 548 return; 549 if (axis.m_splitBeingResized == noSplit) 550 return; 551 int currentSplitPosition = splitPosition(axis, axis.m_splitBeingResized); 552 int delta = (position - currentSplitPosition) - axis.m_splitResizeOffset; 553 if (!delta) 554 return; 555 axis.m_deltas[axis.m_splitBeingResized - 1] += delta; 556 axis.m_deltas[axis.m_splitBeingResized] -= delta; 557 setNeedsLayoutAndFullPaintInvalidation(); 558 } 559 560 bool RenderFrameSet::userResize(MouseEvent* evt) 561 { 562 if (!m_isResizing) { 563 if (needsLayout()) 564 return false; 565 if (evt->type() == EventTypeNames::mousedown && evt->button() == LeftButton) { 566 FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms); 567 startResizing(m_cols, localPos.x()); 568 startResizing(m_rows, localPos.y()); 569 if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) { 570 setIsResizing(true); 571 return true; 572 } 573 } 574 } else { 575 if (evt->type() == EventTypeNames::mousemove || (evt->type() == EventTypeNames::mouseup && evt->button() == LeftButton)) { 576 FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms); 577 continueResizing(m_cols, localPos.x()); 578 continueResizing(m_rows, localPos.y()); 579 if (evt->type() == EventTypeNames::mouseup && evt->button() == LeftButton) { 580 setIsResizing(false); 581 return true; 582 } 583 } 584 } 585 586 return false; 587 } 588 589 void RenderFrameSet::setIsResizing(bool isResizing) 590 { 591 m_isResizing = isResizing; 592 for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { 593 if (ancestor->isFrameSet()) 594 toRenderFrameSet(ancestor)->m_isChildResizing = isResizing; 595 } 596 if (LocalFrame* frame = this->frame()) 597 frame->eventHandler().setResizingFrameSet(isResizing ? frameSet() : 0); 598 } 599 600 bool RenderFrameSet::canResizeRow(const IntPoint& p) const 601 { 602 int r = hitTestSplit(m_rows, p.y()); 603 return r != noSplit && !m_rows.m_preventResize[r]; 604 } 605 606 bool RenderFrameSet::canResizeColumn(const IntPoint& p) const 607 { 608 int c = hitTestSplit(m_cols, p.x()); 609 return c != noSplit && !m_cols.m_preventResize[c]; 610 } 611 612 int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const 613 { 614 if (needsLayout()) 615 return 0; 616 617 int borderThickness = frameSet()->border(); 618 619 int size = axis.m_sizes.size(); 620 if (!size) 621 return 0; 622 623 int position = 0; 624 for (int i = 0; i < split && i < size; ++i) 625 position += axis.m_sizes[i] + borderThickness; 626 return position - borderThickness; 627 } 628 629 int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const 630 { 631 if (needsLayout()) 632 return noSplit; 633 634 int borderThickness = frameSet()->border(); 635 if (borderThickness <= 0) 636 return noSplit; 637 638 size_t size = axis.m_sizes.size(); 639 if (!size) 640 return noSplit; 641 642 int splitPosition = axis.m_sizes[0]; 643 for (size_t i = 1; i < size; ++i) { 644 if (position >= splitPosition && position < splitPosition + borderThickness) 645 return i; 646 splitPosition += borderThickness + axis.m_sizes[i]; 647 } 648 return noSplit; 649 } 650 651 bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle*) const 652 { 653 return child->isFrame() || child->isFrameSet(); 654 } 655 656 CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& cursor) const 657 { 658 IntPoint roundedPoint = roundedIntPoint(point); 659 if (canResizeRow(roundedPoint)) { 660 cursor = rowResizeCursor(); 661 return SetCursor; 662 } 663 if (canResizeColumn(roundedPoint)) { 664 cursor = columnResizeCursor(); 665 return SetCursor; 666 } 667 return RenderBox::getCursor(point, cursor); 668 } 669 670 } // namespace WebCore 671