widget/headless/HeadlessThemeGTK.cpp
author Andreas Tolfsen <ato@sny.no>
Thu, 11 Oct 2018 16:40:36 +0000
changeset 443621 9ca2c179e63e292808918158eb778b16bf18e67f
parent 442272 bacc9594a048c0cde34745393361c55bcc159f39
child 444810 d5879bff1a027d610a506e113d41eacce7cd8f6c
permissions -rw-r--r--
bug 1492499: marionette: warn on TimedPromise bailing; r=automatedtester We often use TimedPromise to ensure Marionette does not unexpectedly block on a promise that, for whatever reason, does not resolve. It can however be useful to be alerted when they don't, as it quite often means there is an underlying problem. Depends on D8406 Differential Revision: https://phabricator.services.mozilla.com/D8407

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "HeadlessThemeGTK.h"

#include "mozilla/StaticPrefs.h"
#include "nsStyleConsts.h"
#include "nsIFrame.h"


namespace mozilla {
namespace widget {

NS_IMPL_ISUPPORTS_INHERITED(HeadlessThemeGTK, nsNativeTheme, nsITheme)

NS_IMETHODIMP
HeadlessThemeGTK::DrawWidgetBackground(gfxContext* aContext,
                                       nsIFrame* aFrame,
                                       WidgetType aWidgetType,
                                       const nsRect& aRect,
                                       const nsRect& aDirtyRect)
{
  return NS_OK;
}

LayoutDeviceIntMargin
HeadlessThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
                                  WidgetType aWidgetType)
{
  if (aWidgetType == StyleAppearance::MenulistButton &&
      StaticPrefs::layout_css_webkit_appearance_enabled()) {
    aWidgetType = StyleAppearance::Menulist;
  }

  LayoutDeviceIntMargin result;
  // The following values are generated from the Ubuntu GTK theme.
  switch (aWidgetType) {
    case StyleAppearance::Button:
    case StyleAppearance::Toolbarbutton:
      result.top = 6;
      result.right = 7;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::FocusOutline:
    case StyleAppearance::MenulistTextfield:
    case StyleAppearance::NumberInput:
    case StyleAppearance::Textfield:
      result.top = 5;
      result.right = 7;
      result.bottom = 5;
      result.left = 7;
      break;
    case StyleAppearance::Statusbarpanel:
    case StyleAppearance::Resizerpanel:
    case StyleAppearance::Listbox:
    case StyleAppearance::Treeview:
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::Progressbar:
    case StyleAppearance::ProgressbarVertical:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
    case StyleAppearance::SpinnerTextfield:
    case StyleAppearance::TextfieldMultiline:
    case StyleAppearance::Menupopup:
    case StyleAppearance::MozGtkInfoBar:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 1;
      break;
    case StyleAppearance::Treeheadercell:
      result.top = 5;
      result.right = 7;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::Tab:
      result.top = 4;
      result.right = 7;
      result.bottom = 2;
      result.left = 7;
      break;
    case StyleAppearance::Tooltip:
      result.top = 6;
      result.right = 6;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::Menulist:
      result.top = 6;
      result.right = 22;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::MenulistButton:
    case StyleAppearance::MozMenulistButton:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 0;
      break;
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
      if (IsRegularMenuItem(aFrame)) {
        break;
      }
      result.top = 3;
      result.right = 5;
      result.bottom = 3;
      result.left = 5;
      break;
    default:
      break;
  }
  return result;
}

bool
HeadlessThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
                                   nsIFrame* aFrame, WidgetType aWidgetType,
                                   LayoutDeviceIntMargin* aResult)
{
  if (aWidgetType == StyleAppearance::MenulistButton &&
      StaticPrefs::layout_css_webkit_appearance_enabled()) {
    aWidgetType = StyleAppearance::Menulist;
  }

  // The following values are generated from the Ubuntu GTK theme.
  switch (aWidgetType) {
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
    case StyleAppearance::Toolbarbutton:
    case StyleAppearance::Dualbutton:
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
    case StyleAppearance::MenulistButton:
    case StyleAppearance::MozMenulistButton:
    case StyleAppearance::RangeThumb:
    case StyleAppearance::ButtonFocus:
      aResult->top = 0;
      aResult->right = 0;
      aResult->bottom = 0;
      aResult->left = 0;
      return true;
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
      if (!IsRegularMenuItem(aFrame)) {
        return false;
      }
      aResult->top = 3;
      aResult->right = 5;
      aResult->bottom = 3;
      aResult->left = 5;
      return true;
    default:
      break;
  }
  return false;
}


NS_IMETHODIMP
HeadlessThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
                                       nsIFrame* aFrame, WidgetType aWidgetType,
                                       LayoutDeviceIntSize* aResult,
                                       bool* aIsOverridable)
{
  aResult->width = aResult->height = 0;
  *aIsOverridable = true;

  if (aWidgetType == StyleAppearance::MenulistButton &&
      StaticPrefs::layout_css_webkit_appearance_enabled()) {
    aWidgetType = StyleAppearance::Menulist;
  }

  // The following values are generated from the Ubuntu GTK theme.
  switch (aWidgetType) {
    case StyleAppearance::Splitter:
      if (IsHorizontal(aFrame)) {
        aResult->width = 6;
        aResult->height = 0;
      } else {
        aResult->width = 0;
        aResult->height = 6;
      }
      *aIsOverridable = false;
      break;
    case StyleAppearance::Button:
    case StyleAppearance::Toolbarbutton:
      aResult->width = 14;
      aResult->height = 12;
      break;
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
      aResult->width = 18;
      aResult->height = 18;
      break;
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::Resizer:
      aResult->width = 15;
      aResult->height = 15;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Separator:
      aResult->width = 12;
      aResult->height = 0;
      break;
    case StyleAppearance::Treetwisty:
    case StyleAppearance::Treetwistyopen:
      aResult->width = 8;
      aResult->height = 8;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Treeheadercell:
      aResult->width = 13;
      aResult->height = 11;
      break;
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
      aResult->width = 14;
      aResult->height = 13;
      break;
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
      aResult->width = 16;
      aResult->height = 16;
      *aIsOverridable = false;
      break;
    case StyleAppearance::InnerSpinButton:
    case StyleAppearance::Spinner:
      aResult->width = 14;
      aResult->height = 26;
      break;
    case StyleAppearance::MenulistTextfield:
    case StyleAppearance::NumberInput:
    case StyleAppearance::Textfield:
      aResult->width = 0;
      aResult->height = 12;
      break;
    case StyleAppearance::ScrollbarHorizontal:
      aResult->width = 31;
      aResult->height = 10;
      break;
    case StyleAppearance::ScrollbarVertical:
      aResult->width = 10;
      aResult->height = 31;
      break;
    case StyleAppearance::ScrollbarbuttonUp:
    case StyleAppearance::ScrollbarbuttonDown:
      aResult->width = 10;
      aResult->height = 13;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarbuttonLeft:
    case StyleAppearance::ScrollbarbuttonRight:
      aResult->width = 13;
      aResult->height = 10;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarthumbHorizontal:
      aResult->width = 31;
      aResult->height = 10;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarthumbVertical:
      aResult->width = 10;
      aResult->height = 31;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Menulist:
      aResult->width = 44;
      aResult->height = 27;
      break;
    case StyleAppearance::MenulistButton:
    case StyleAppearance::MozMenulistButton:
      aResult->width = 29;
      aResult->height = 28;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScalethumbHorizontal:
    case StyleAppearance::RangeThumb:
      aResult->width = 14;
      aResult->height = 18;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScalethumbVertical:
      aResult->width = 18;
      aResult->height = 13;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Range:
      aResult->width = 14;
      aResult->height = 18;
      break;
    case StyleAppearance::Menuseparator:
      aResult->width = 0;
      aResult->height = 8;
      *aIsOverridable = false;
      break;
    default:
      break;
  }
  return NS_OK;
}

NS_IMETHODIMP
HeadlessThemeGTK::WidgetStateChanged(nsIFrame* aFrame, WidgetType aWidgetType,
                                     nsAtom* aAttribute, bool* aShouldRepaint,
                                     const nsAttrValue* aOldValue)
{
  return NS_OK;
}

NS_IMETHODIMP
HeadlessThemeGTK::ThemeChanged()
{
  return NS_OK;
}

static bool IsFrameContentNodeInNamespace(nsIFrame *aFrame, uint32_t aNamespace)
{
  nsIContent *content = aFrame ? aFrame->GetContent() : nullptr;
  if (!content)
    return false;
  return content->IsInNamespace(aNamespace);
}

NS_IMETHODIMP_(bool)
HeadlessThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
                                      nsIFrame* aFrame,
                                      WidgetType aWidgetType)
{
  if (aWidgetType == StyleAppearance::MenulistButton &&
      StaticPrefs::layout_css_webkit_appearance_enabled()) {
    aWidgetType = StyleAppearance::Menulist;
  }

  switch (aWidgetType) {
    case StyleAppearance::Button:
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
    case StyleAppearance::FocusOutline:
    case StyleAppearance::Toolbox:
    case StyleAppearance::Toolbar:
    case StyleAppearance::Toolbarbutton:
    case StyleAppearance::Dualbutton:
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::Separator:
    case StyleAppearance::Toolbargripper:
    case StyleAppearance::Splitter:
    case StyleAppearance::Statusbar:
    case StyleAppearance::Statusbarpanel:
    case StyleAppearance::Resizerpanel:
    case StyleAppearance::Resizer:
    case StyleAppearance::Listbox:
    case StyleAppearance::Treeview:
    case StyleAppearance::Treetwisty:
    case StyleAppearance::Treeheadercell:
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::Treetwistyopen:
    case StyleAppearance::Progressbar:
    case StyleAppearance::Progresschunk:
    case StyleAppearance::ProgressbarVertical:
    case StyleAppearance::ProgresschunkVertical:
    case StyleAppearance::Tab:
    case StyleAppearance::Tabpanels:
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
    case StyleAppearance::Tooltip:
    case StyleAppearance::InnerSpinButton:
    case StyleAppearance::Spinner:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
    case StyleAppearance::SpinnerTextfield:
    case StyleAppearance::NumberInput:
    case StyleAppearance::ScrollbarHorizontal:
    case StyleAppearance::ScrollbarVertical:
    case StyleAppearance::ScrollbarbuttonUp:
    case StyleAppearance::ScrollbarbuttonDown:
    case StyleAppearance::ScrollbarbuttonLeft:
    case StyleAppearance::ScrollbarbuttonRight:
    case StyleAppearance::ScrollbartrackHorizontal:
    case StyleAppearance::ScrollbartrackVertical:
    case StyleAppearance::ScrollbarthumbHorizontal:
    case StyleAppearance::ScrollbarthumbVertical:
    case StyleAppearance::Textfield:
    case StyleAppearance::TextfieldMultiline:
    case StyleAppearance::Menulist:
    case StyleAppearance::MenulistText:
    case StyleAppearance::MenulistTextfield:
    case StyleAppearance::ScaleHorizontal:
    case StyleAppearance::ScaleVertical:
    case StyleAppearance::ScalethumbHorizontal:
    case StyleAppearance::ScalethumbVertical:
    case StyleAppearance::Range:
    case StyleAppearance::RangeThumb:
    case StyleAppearance::CheckboxContainer:
    case StyleAppearance::RadioContainer:
    case StyleAppearance::CheckboxLabel:
    case StyleAppearance::RadioLabel:
    case StyleAppearance::ButtonFocus:
    case StyleAppearance::Window:
    case StyleAppearance::Dialog:
    case StyleAppearance::Menubar:
    case StyleAppearance::Menupopup:
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
    case StyleAppearance::Menuseparator:
    case StyleAppearance::Menuarrow:
    case StyleAppearance::MozGtkInfoBar:
      return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
    case StyleAppearance::MenulistButton:
    case StyleAppearance::MozMenulistButton:
      return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
              !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
    default:
      break;
  }
  return false;
}

NS_IMETHODIMP_(bool)
HeadlessThemeGTK::WidgetIsContainer(WidgetType aWidgetType)
{
  if (aWidgetType == StyleAppearance::MenulistButton &&
      StaticPrefs::layout_css_webkit_appearance_enabled()) {
    aWidgetType = StyleAppearance::Menulist;
  }

    if (aWidgetType == StyleAppearance::MenulistButton ||
        aWidgetType == StyleAppearance::MozMenulistButton ||
        aWidgetType == StyleAppearance::Radio ||
        aWidgetType == StyleAppearance::RangeThumb ||
        aWidgetType == StyleAppearance::Checkbox ||
        aWidgetType == StyleAppearance::TabScrollArrowBack ||
        aWidgetType == StyleAppearance::TabScrollArrowForward ||
        aWidgetType == StyleAppearance::ButtonArrowUp ||
        aWidgetType == StyleAppearance::ButtonArrowDown ||
        aWidgetType == StyleAppearance::ButtonArrowNext ||
        aWidgetType == StyleAppearance::ButtonArrowPrevious) {

    return false;
  }
  return true;
}

bool
HeadlessThemeGTK::ThemeDrawsFocusForWidget(WidgetType aWidgetType)
{
   if (aWidgetType == StyleAppearance::Menulist ||
       aWidgetType == StyleAppearance::Button ||
       aWidgetType == StyleAppearance::Treeheadercell) {
    return true;
  }
  return false;
}

bool
HeadlessThemeGTK::ThemeNeedsComboboxDropmarker()
{
  return false;
}


} // namespace widget
} // namespace mozilla