int Screen::availTop() const { if (!m_frame) return 0; FrameHost* host = m_frame->host(); if (host && host->settings().reportScreenSizeInPhysicalPixelsQuirk()) return lroundf(screenAvailableRect(m_frame->view()).y() * host->deviceScaleFactor()); return static_cast<int>(screenAvailableRect(m_frame->view()).y()); }
int Screen::availLeft() const { if (!m_frame) return 0; #ifdef LOG_MODS_FP logFPCalls(m_frame, "Screen::availLeft"); #endif return static_cast<int>(screenAvailableRect(m_frame->view()).x()); }
unsigned Screen::availWidth() const { if (!m_frame) return 0; #ifdef LOG_MODS_FP logFPCalls(m_frame, "Screen::availWidth"); #endif return static_cast<unsigned>(screenAvailableRect(m_frame->view()).width()); }
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntSize& transformOffset, const IntPoint& popupInitialCoordinate) { // Reset the max width and height to their default values, they will be // recomputed below if necessary. m_listBox->setMaxHeight(PopupListBox::defaultMaxHeight); m_listBox->setMaxWidth(std::numeric_limits<int>::max()); // Lay everything out to figure out our preferred size, then tell the view's // WidgetClient about it. It should assign us a client. m_listBox->layout(); fitToListBox(); bool isRTL = this->isRTL(); // Compute the starting x-axis for a normal RTL or right-aligned LTR // dropdown. For those, the right edge of dropdown box should be aligned // with the right edge of <select>/<input> element box, and the dropdown box // should be expanded to the left if more space is needed. // m_originalFrameRect.width() is the width of the target <select>/<input> // element. int rtlOffset = m_controlPosition.p2().x() - m_controlPosition.p1().x() - (m_listBox->width() + borderSize * 2); int rightOffset = isRTL ? rtlOffset : 0; // Compute the y-axis offset between the bottom left and bottom right // points. If the <select>/<input> is transformed, they are not the same. int verticalOffset = - m_controlPosition.p4().y() + m_controlPosition.p3().y(); int verticalForRTLOffset = isRTL ? verticalOffset : 0; // Assume m_listBox size is already calculated. IntSize targetSize(m_listBox->width() + borderSize * 2, m_listBox->height() + borderSize * 2); IntRect widgetRectInScreen; // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(m_frameView.get()); // Use popupInitialCoordinate.x() + rightOffset because RTL position // needs to be considered. float pageScaleFactor = m_frameView->frame().page()->pageScaleFactor(); int popupX = round((popupInitialCoordinate.x() + rightOffset) * pageScaleFactor); int popupY = round((popupInitialCoordinate.y() + verticalForRTLOffset) * pageScaleFactor); widgetRectInScreen = chromeClient().rootViewToScreen(IntRect(popupX, popupY, targetSize.width(), targetSize.height())); // If we have multiple screens and the browser rect is in one screen, we // have to clip the window width to the screen width. // When clipping, we also need to set a maximum width for the list box. FloatRect windowRect = chromeClient().windowRect(); bool needToResizeView = false; widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen, targetControlHeight, windowRect, screen, isRTL, rtlOffset, verticalOffset, transformOffset, m_listBox.get(), needToResizeView); if (needToResizeView) fitToListBox(); return widgetRectInScreen; }
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate) { // Reset the max width and height to their default values, they will be recomputed below // if necessary. m_listBox->setMaxHeight(kMaxHeight); m_listBox->setMaxWidth(std::numeric_limits<int>::max()); // Lay everything out to figure out our preferred size, then tell the view's // WidgetClient about it. It should assign us a client. int rtlOffset = layoutAndGetRTLOffset(); bool isRTL = this->isRTL(); int rightOffset = isRTL ? rtlOffset : 0; // Assume m_listBox size is already calculated. IntSize targetSize(m_listBox->width() + kBorderSize * 2, m_listBox->height() + kBorderSize * 2); IntRect widgetRectInScreen; ChromeClientChromium* chromeClient = chromeClientChromium(); if (chromeClient) { // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(m_frameView.get()); // Use popupInitialCoordinate.x() + rightOffset because RTL position // needs to be considered. widgetRectInScreen = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height())); // If we have multiple screens and the browser rect is in one screen, we have // to clip the window width to the screen width. // When clipping, we also need to set a maximum width for the list box. FloatRect windowRect = chromeClient->windowRect(); bool needToResizeView = false; widgetRectInScreen = layoutAndCalculateWidgetRectInternal(widgetRectInScreen, targetControlHeight, windowRect, screen, isRTL, rtlOffset, m_listBox.get(), needToResizeView); if (needToResizeView) fitToListBox(); } return widgetRectInScreen; }
static JSValuePtr showModalDialog(ExecState* exec, Frame* frame, const String& url, JSValuePtr dialogArgs, const String& featureArgs) { if (!canShowModalDialogNow(frame) || !allowPopUp(exec)) return jsUndefined(); const HashMap<String, String> features = parseModalDialogFeatures(featureArgs); const bool trusted = false; // The following features from Microsoft's documentation are not implemented: // - default font settings // - width, height, left, and top specified in units other than "px" // - edge (sunken or raised, default is raised) // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?) // - unadorned: trusted && boolFeature(features, "unadorned"); if (!frame) return jsUndefined(); FloatRect screenRect = screenAvailableRect(frame->view()); WindowFeatures wargs; wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE wargs.widthSet = true; wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE wargs.heightSet = true; wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1); wargs.xSet = wargs.x > 0; wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1); wargs.ySet = wargs.y > 0; if (WindowFeatures::boolFeature(features, "center", true)) { if (!wargs.xSet) { wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2; wargs.xSet = true; } if (!wargs.ySet) { wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2; wargs.ySet = true; } } wargs.dialog = true; wargs.resizable = WindowFeatures::boolFeature(features, "resizable"); wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true); wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted); wargs.menuBarVisible = false; wargs.toolBarVisible = false; wargs.locationBarVisible = false; wargs.fullscreen = false; Frame* dialogFrame = createWindow(exec, frame, url, "", wargs, dialogArgs); if (!dialogFrame) return jsUndefined(); JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame); // Get the return value either just before clearing the dialog window's // properties (in JSDOMWindowBase::clear), or when on return from runModal. JSValuePtr returnValue = noValue(); dialogWindow->setReturnValueSlot(&returnValue); dialogFrame->page()->chrome()->runModal(); dialogWindow->setReturnValueSlot(0); // If we don't have a return value, get it now. // Either JSDOMWindowBase::clear was not called yet, or there was no return value, // and in that case, there's no harm in trying again (no benefit either). if (!returnValue) returnValue = dialogWindow->getDirect(Identifier(exec, "returnValue")); return returnValue ? returnValue : jsUndefined(); }
IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate) { // Reset the max width and height to their default values, they will be recomputed below // if necessary. m_listBox->setMaxHeight(kMaxHeight); m_listBox->setMaxWidth(std::numeric_limits<int>::max()); // Lay everything out to figure out our preferred size, then tell the view's // WidgetClient about it. It should assign us a client. int rtlOffset = layoutAndGetRTLOffset(); bool isRTL = this->isRTL(); int rightOffset = isRTL ? rtlOffset : 0; // Assume m_listBox size is already calculated. IntSize targetSize(m_listBox->width() + kBorderSize * 2, m_listBox->height() + kBorderSize * 2); IntRect widgetRect; ChromeClientChromium* chromeClient = chromeClientChromium(); if (chromeClient) { // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(m_frameView.get()); // Use popupInitialCoordinate.x() + rightOffset because RTL position // needs to be considered. widgetRect = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + rightOffset, popupInitialCoordinate.y(), targetSize.width(), targetSize.height())); // If we have multiple screens and the browser rect is in one screen, we have // to clip the window width to the screen width. // When clipping, we also need to set a maximum width for the list box. FloatRect windowRect = chromeClient->windowRect(); if (windowRect.x() >= screen.x() && windowRect.maxX() <= screen.maxX() && (widgetRect.x() < screen.x() || widgetRect.maxX() > screen.maxX())) { // First, inverse the popup alignment if it does not fit the screen - this might fix things (or make them better). IntRect inverseWidgetRect = chromeClient->rootViewToScreen(IntRect(popupInitialCoordinate.x() + (isRTL ? 0 : rtlOffset), popupInitialCoordinate.y(), targetSize.width(), targetSize.height())); IntRect enclosingScreen = enclosingIntRect(screen); unsigned originalCutoff = max(enclosingScreen.x() - widgetRect.x(), 0) + max(widgetRect.maxX() - enclosingScreen.maxX(), 0); unsigned inverseCutoff = max(enclosingScreen.x() - inverseWidgetRect.x(), 0) + max(inverseWidgetRect.maxX() - enclosingScreen.maxX(), 0); // Accept the inverse popup alignment if the trimmed content gets shorter than that in the original alignment case. if (inverseCutoff < originalCutoff) widgetRect = inverseWidgetRect; if (widgetRect.x() < screen.x()) { unsigned widgetRight = widgetRect.maxX(); widgetRect.setWidth(widgetRect.maxX() - screen.x()); widgetRect.setX(widgetRight - widgetRect.width()); listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorderSize * 2, 0)); } else if (widgetRect.maxX() > screen.maxX()) { widgetRect.setWidth(screen.maxX() - widgetRect.x()); listBox()->setMaxWidthAndLayout(max(widgetRect.width() - kBorderSize * 2, 0)); } } // Calculate Y axis size. if (widgetRect.maxY() > static_cast<int>(screen.maxY())) { if (widgetRect.y() - widgetRect.height() - targetControlHeight > 0) { // There is enough room to open upwards. widgetRect.move(0, -(widgetRect.height() + targetControlHeight)); } else { // Figure whether upwards or downwards has more room and set the // maximum number of items. int spaceAbove = widgetRect.y() - targetControlHeight; int spaceBelow = screen.maxY() - widgetRect.y(); if (spaceAbove > spaceBelow) m_listBox->setMaxHeight(spaceAbove); else m_listBox->setMaxHeight(spaceBelow); layoutAndGetRTLOffset(); // Our height has changed, so recompute only Y axis of widgetRect. // We don't have to recompute X axis, so we only replace Y axis // in widgetRect. IntRect frameInScreen = chromeClient->rootViewToScreen(frameRect()); widgetRect.setY(frameInScreen.y()); widgetRect.setHeight(frameInScreen.height()); // And move upwards if necessary. if (spaceAbove > spaceBelow) widgetRect.move(0, -(widgetRect.height() + targetControlHeight)); } } } return widgetRect; }
JSValue JSDOMWindow::showModalDialog(ExecState* exec) { String url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)); JSValue dialogArgs = exec->argument(1); String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2)); Frame* frame = impl()->frame(); if (!frame) return jsUndefined(); Frame* lexicalFrame = toLexicalFrame(exec); if (!lexicalFrame) return jsUndefined(); Frame* dynamicFrame = toDynamicFrame(exec); if (!dynamicFrame) return jsUndefined(); if (!DOMWindow::canShowModalDialogNow(frame) || !domWindowAllowPopUp(dynamicFrame)) return jsUndefined(); HashMap<String, String> features; DOMWindow::parseModalDialogFeatures(featureArgs, features); const bool trusted = false; // The following features from Microsoft's documentation are not implemented: // - default font settings // - width, height, left, and top specified in units other than "px" // - edge (sunken or raised, default is raised) // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?) // - unadorned: trusted && boolFeature(features, "unadorned"); FloatRect screenRect = screenAvailableRect(frame->view()); WindowFeatures wargs; wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE wargs.widthSet = true; wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE wargs.heightSet = true; wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1); wargs.xSet = wargs.x > 0; wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1); wargs.ySet = wargs.y > 0; if (WindowFeatures::boolFeature(features, "center", true)) { if (!wargs.xSet) { wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2; wargs.xSet = true; } if (!wargs.ySet) { wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2; wargs.ySet = true; } } wargs.dialog = true; wargs.resizable = WindowFeatures::boolFeature(features, "resizable"); wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true); wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted); wargs.menuBarVisible = false; wargs.toolBarVisible = false; wargs.locationBarVisible = false; wargs.fullscreen = false; Frame* dialogFrame = createWindow(exec, lexicalFrame, dynamicFrame, frame, url, "", wargs, dialogArgs); if (!dialogFrame) return jsUndefined(); JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame, currentWorld(exec)); dialogFrame->page()->chrome()->runModal(); Identifier returnValue(exec, "returnValue"); if (dialogWindow->allowsAccessFromNoErrorMessage(exec)) { PropertySlot slot; // This is safe, we have already performed the origin security check and we are // not interested in any of the DOM properties of the window. if (dialogWindow->JSGlobalObject::getOwnPropertySlot(exec, returnValue, slot)) return slot.getValue(exec, returnValue); } return jsUndefined(); }
JSValue JSDOMWindow::open(ExecState* exec) { String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0)); AtomicString frameName = exec->argument(1).isUndefinedOrNull() ? "_blank" : ustringToAtomicString(exec->argument(1).toString(exec)); WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2))); Frame* frame = impl()->frame(); if (!frame) return jsUndefined(); Frame* lexicalFrame = toLexicalFrame(exec); if (!lexicalFrame) return jsUndefined(); Frame* dynamicFrame = toDynamicFrame(exec); if (!dynamicFrame) return jsUndefined(); Page* page = frame->page(); // Because FrameTree::find() returns true for empty strings, we must check for empty framenames. // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker. if (!domWindowAllowPopUp(dynamicFrame) && (frameName.isEmpty() || !frame->tree()->find(frameName))) return jsUndefined(); // Get the target frame for the special cases of _top and _parent. In those // cases, we can schedule a location change right now and return early. bool topOrParent = false; if (frameName == "_top") { frame = frame->tree()->top(); topOrParent = true; } else if (frameName == "_parent") { if (Frame* parent = frame->tree()->parent()) frame = parent; topOrParent = true; } if (topOrParent) { String completedURL; if (!urlString.isEmpty()) completedURL = completeURL(exec, urlString).string(); if (!shouldAllowNavigation(exec, frame)) return jsUndefined(); const JSDOMWindow* targetedWindow = toJSDOMWindow(frame, currentWorld(exec)); if (!completedURL.isEmpty() && (!protocolIsJavaScript(completedURL) || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) { bool userGesture = processingUserGesture(); // For whatever reason, Firefox uses the dynamicGlobalObject to // determine the outgoingReferrer. We replicate that behavior // here. String referrer = dynamicFrame->loader()->outgoingReferrer(); frame->redirectScheduler()->scheduleLocationChange(completedURL, referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture); } return toJS(exec, frame->domWindow()); } // In the case of a named frame or a new window, we'll use the createWindow() helper FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0, windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0); DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect); windowFeatures.x = windowRect.x(); windowFeatures.y = windowRect.y(); windowFeatures.height = windowRect.height(); windowFeatures.width = windowRect.width(); frame = createWindow(exec, lexicalFrame, dynamicFrame, frame, urlString, frameName, windowFeatures, JSValue()); if (!frame) return jsUndefined(); return toJS(exec, frame->domWindow()); }
unsigned Screen::availWidth() const { if (!m_frame) return 0; return static_cast<unsigned>(screenAvailableRect(m_frame->view()).width()); }
int Screen::availTop() const { if (!m_frame) return 0; return static_cast<int>(screenAvailableRect(m_frame->view()).y()); }