diff options
author | Ben Murdoch <benm@google.com> | 2011-05-16 16:25:10 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-23 18:54:14 +0100 |
commit | ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb (patch) | |
tree | db769fadd053248f85db67434a5b275224defef7 /Source/WebCore/platform/gtk | |
parent | 52e2557aeb8477967e97fd24f20f8f407a10fa15 (diff) | |
download | external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.zip external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.gz external_webkit-ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb.tar.bz2 |
Merge WebKit at r76408: Initial merge by git.
Change-Id: I5b91decbd693ccbf5c1b8354b37cd68cc9a1ea53
Diffstat (limited to 'Source/WebCore/platform/gtk')
-rw-r--r-- | Source/WebCore/platform/gtk/ClipboardGtk.h | 1 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/DragDataGtk.cpp | 12 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/KeyEventGtk.cpp | 3 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/MainFrameScrollbarGtk.cpp | 11 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/MainFrameScrollbarGtk.h | 5 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/RenderThemeGtk.cpp | 68 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/RenderThemeGtk.h | 32 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/RenderThemeGtk2.cpp | 477 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/RenderThemeGtk3.cpp | 36 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/WidgetRenderingContext.cpp | 65 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/WidgetRenderingContext.h | 6 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/gtk2drawing.c | 820 | ||||
-rw-r--r-- | Source/WebCore/platform/gtk/gtkdrawing.h | 74 |
13 files changed, 567 insertions, 1043 deletions
diff --git a/Source/WebCore/platform/gtk/ClipboardGtk.h b/Source/WebCore/platform/gtk/ClipboardGtk.h index e14a583..0c07c07 100644 --- a/Source/WebCore/platform/gtk/ClipboardGtk.h +++ b/Source/WebCore/platform/gtk/ClipboardGtk.h @@ -39,6 +39,7 @@ namespace WebCore { // State available during IE's events for drag and drop and copy/paste // Created from the EventHandlerGtk to be used by the dom class ClipboardGtk : public Clipboard, public CachedResourceClient { + WTF_MAKE_FAST_ALLOCATED; public: static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, GtkClipboard* clipboard, Frame* frame) { diff --git a/Source/WebCore/platform/gtk/DragDataGtk.cpp b/Source/WebCore/platform/gtk/DragDataGtk.cpp index 3a1daf1..cc9a208 100644 --- a/Source/WebCore/platform/gtk/DragDataGtk.cpp +++ b/Source/WebCore/platform/gtk/DragDataGtk.cpp @@ -66,13 +66,21 @@ bool DragData::containsCompatibleContent() const return containsPlainText() || containsURL(0) || m_platformDragData->hasMarkup() || containsColor() || containsFiles(); } -bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) const +bool DragData::containsURL(Frame* frame, FilenameConversionPolicy filenamePolicy) const { - return m_platformDragData->hasURL(); + return !asURL(frame, filenamePolicy).isEmpty(); } String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const { + if (!m_platformDragData->hasURL()) + return String(); + if (filenamePolicy != ConvertFilenames) { + KURL url(KURL(), m_platformDragData->url()); + if (url.isLocalFile()) + return String(); + } + String url(m_platformDragData->url()); if (title) *title = m_platformDragData->urlLabel(); diff --git a/Source/WebCore/platform/gtk/KeyEventGtk.cpp b/Source/WebCore/platform/gtk/KeyEventGtk.cpp index 50dfa4c..5a034d6 100644 --- a/Source/WebCore/platform/gtk/KeyEventGtk.cpp +++ b/Source/WebCore/platform/gtk/KeyEventGtk.cpp @@ -583,8 +583,7 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCom bool PlatformKeyboardEvent::currentCapsLockState() { - notImplemented(); - return false; + return gdk_keymap_get_caps_lock_state(gdk_keymap_get_default()); } void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) diff --git a/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.cpp b/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.cpp index c2e24e0..d1571a5 100644 --- a/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.cpp +++ b/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.cpp @@ -25,13 +25,14 @@ #include "GraphicsContext.h" #include "GtkVersioning.h" #include "IntRect.h" +#include "ScrollableArea.h" #include <gtk/gtk.h> using namespace WebCore; -PassRefPtr<MainFrameScrollbarGtk> MainFrameScrollbarGtk::create(ScrollbarClient* client, ScrollbarOrientation orientation, GtkAdjustment* adj) +PassRefPtr<MainFrameScrollbarGtk> MainFrameScrollbarGtk::create(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, GtkAdjustment* adj) { - return adoptRef(new MainFrameScrollbarGtk(client, orientation, adj)); + return adoptRef(new MainFrameScrollbarGtk(scrollableArea, orientation, adj)); } // Main frame scrollbars are slaves to a GtkAdjustment. If a main frame @@ -41,8 +42,8 @@ PassRefPtr<MainFrameScrollbarGtk> MainFrameScrollbarGtk::create(ScrollbarClient* // state. These scrollbars are never painted, as the container takes care of // that. They exist only to shuttle data from the GtkWidget container into // WebCore and vice-versa. -MainFrameScrollbarGtk::MainFrameScrollbarGtk(ScrollbarClient* client, ScrollbarOrientation orientation, GtkAdjustment* adjustment) - : Scrollbar(client, orientation, RegularScrollbar) +MainFrameScrollbarGtk::MainFrameScrollbarGtk(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, GtkAdjustment* adjustment) + : Scrollbar(scrollableArea, orientation, RegularScrollbar) , m_adjustment(0) { attachAdjustment(adjustment); @@ -108,7 +109,7 @@ void MainFrameScrollbarGtk::updateThumbProportion() void MainFrameScrollbarGtk::gtkValueChanged(GtkAdjustment*, MainFrameScrollbarGtk* that) { - that->setValue(static_cast<int>(gtk_adjustment_get_value(that->m_adjustment.get())), NotFromScrollAnimator); + that->scrollableArea()->scrollToOffsetWithoutAnimation(that->orientation(), static_cast<int>(gtk_adjustment_get_value(that->m_adjustment.get()))); } void MainFrameScrollbarGtk::paint(GraphicsContext* context, const IntRect& rect) diff --git a/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.h b/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.h index f184425..f104f81 100644 --- a/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.h +++ b/Source/WebCore/platform/gtk/MainFrameScrollbarGtk.h @@ -30,18 +30,19 @@ namespace WebCore { class MainFrameScrollbarGtk : public Scrollbar { public: + static PassRefPtr<MainFrameScrollbarGtk> create(ScrollableArea*, ScrollbarOrientation, GtkAdjustment*); + ~MainFrameScrollbarGtk(); virtual void paint(GraphicsContext*, const IntRect&); void detachAdjustment(); void attachAdjustment(GtkAdjustment*); - static PassRefPtr<MainFrameScrollbarGtk> create(ScrollbarClient*, ScrollbarOrientation, GtkAdjustment*); protected: virtual void updateThumbPosition(); virtual void updateThumbProportion(); private: - MainFrameScrollbarGtk(ScrollbarClient*, ScrollbarOrientation, GtkAdjustment*); + MainFrameScrollbarGtk(ScrollableArea*, ScrollbarOrientation, GtkAdjustment*); static void gtkValueChanged(GtkAdjustment*, MainFrameScrollbarGtk*); GRefPtr<GtkAdjustment> m_adjustment; diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp index 97c966d..bfe3901 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -41,6 +41,10 @@ #include <gdk/gdk.h> #include <gtk/gtk.h> +#if ENABLE(PROGRESS_TAG) +#include "RenderProgress.h" +#endif + namespace WebCore { using namespace HTMLNames; @@ -305,6 +309,24 @@ bool RenderThemeGtk::paintSearchField(RenderObject* o, const PaintInfo& i, const return paintTextField(o, i, rect); } +bool RenderThemeGtk::paintCapsLockIndicator(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect) +{ + // The other paint methods don't need to check whether painting is disabled because RenderTheme already checks it + // before calling them, but paintCapsLockIndicator() is called by RenderTextControlSingleLine which doesn't check it. + if (paintInfo.context->paintingDisabled()) + return true; + + GRefPtr<GdkPixbuf> icon = getStockIcon(GTK_TYPE_ENTRY, GTK_STOCK_CAPS_LOCK_WARNING, + gtkTextDirection(renderObject->style()->direction()), + gtkIconState(this, renderObject), GTK_ICON_SIZE_MENU); + + // GTK+ locates the icon right aligned in the entry. The given rectangle is already + // centered vertically by RenderTextControlSingleLine. + IntPoint iconPosition(rect.x() + rect.width() - gdk_pixbuf_get_width(icon.get()), rect.y()); + paintGdkPixbuf(paintInfo.context, icon.get(), iconPosition); + return true; +} + void RenderThemeGtk::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { style->setBoxShadow(0); @@ -330,7 +352,7 @@ double RenderThemeGtk::caretBlinkInterval() const return time / 2000.; } -static double getScreenDPI() +double RenderThemeGtk::getScreenDPI() { // FIXME: Really this should be the widget's screen. GdkScreen* screen = gdk_screen_get_default(); @@ -543,6 +565,50 @@ void RenderThemeGtk::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle* styl { style->setBoxShadow(0); } + +// These values have been copied from RenderThemeChromiumSkia.cpp +static const int progressActivityBlocks = 5; +static const int progressAnimationFrames = 10; +static const double progressAnimationInterval = 0.125; +double RenderThemeGtk::animationRepeatIntervalForProgressBar(RenderProgress*) const +{ + return progressAnimationInterval; +} + +double RenderThemeGtk::animationDurationForProgressBar(RenderProgress*) const +{ + return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth; +} + +IntRect RenderThemeGtk::calculateProgressRect(RenderObject* renderObject, const IntRect& fullBarRect) +{ + IntRect progressRect(fullBarRect); + RenderProgress* renderProgress = toRenderProgress(renderObject); + if (renderProgress->isDeterminate()) { + int progressWidth = progressRect.width() * renderProgress->position(); + if (renderObject->style()->direction() == RTL) + progressRect.setX(progressRect.x() + progressRect.width() - progressWidth); + progressRect.setWidth(progressWidth); + return progressRect; + } + + double animationProgress = renderProgress->animationProgress(); + + // Never let the progress rect shrink smaller than 2 pixels. + int newWidth = max(2, progressRect.width() / progressActivityBlocks); + int movableWidth = progressRect.width() - newWidth; + progressRect.setWidth(newWidth); + + // We want the first 0.5 units of the animation progress to represent the + // forward motion and the second 0.5 units to represent the backward motion, + // thus we multiply by two here to get the full sweep of the progress bar with + // each direction. + if (animationProgress < 0.5) + progressRect.setX(progressRect.x() + (animationProgress * 2 * movableWidth)); + else + progressRect.setX(progressRect.x() + ((1.0 - animationProgress) * 2 * movableWidth)); + return progressRect; +} #endif } diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.h b/Source/WebCore/platform/gtk/RenderThemeGtk.h index 90113e5..5765782 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk.h +++ b/Source/WebCore/platform/gtk/RenderThemeGtk.h @@ -169,13 +169,21 @@ protected: virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&); #endif + virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&); + private: void platformInit(); + static void setTextInputBorders(RenderStyle*); + GRefPtr<GdkPixbuf> getStockIcon(GType, const char* iconName, gint direction, gint state, gint iconSize); + static double getScreenDPI(); + #if ENABLE(VIDEO) bool paintMediaButton(RenderObject*, GraphicsContext*, const IntRect&, const char* iconName); #endif - static void setTextInputBorders(RenderStyle*); - GRefPtr<GdkPixbuf> getStockIcon(GType, const char* iconName, gint direction, gint state, gint iconSize); + +#if ENABLE(PROGRESS_TAG) + static IntRect calculateProgressRect(RenderObject*, const IntRect&); +#endif mutable Color m_panelColor; mutable Color m_sliderColor; @@ -188,13 +196,26 @@ private: #ifdef GTK_API_VERSION_2 void setupWidgetAndAddToContainer(GtkWidget*, GtkWidget*) const; bool paintRenderObject(GtkThemeWidgetType, RenderObject*, GraphicsContext*, const IntRect&, int flags = 0); + void refreshComboBoxChildren() const; + void getComboBoxPadding(RenderStyle*, int& left, int& top, int& right, int& bottom) const; + int getComboBoxSeparatorWidth() const; + int comboBoxArrowSize(RenderStyle*) const; GtkThemeParts m_themeParts; + GtkWidget* gtkButton() const; GtkWidget* gtkEntry() const; GtkWidget* gtkTreeView() const; GtkWidget* gtkVScale() const; GtkWidget* gtkHScale() const; GtkWidget* gtkContainer() const; + GtkWidget* gtkRadioButton() const; + GtkWidget* gtkCheckButton() const; + GtkWidget* gtkProgressBar() const; + GtkWidget* gtkComboBox() const; + GtkWidget* gtkComboBoxButton() const; + GtkWidget* gtkComboBoxArrow() const; + GtkWidget* gtkComboBoxSeparator() const; + mutable GtkWidget* m_gtkWindow; mutable GtkWidget* m_gtkContainer; mutable GtkWidget* m_gtkButton; @@ -202,6 +223,13 @@ private: mutable GtkWidget* m_gtkTreeView; mutable GtkWidget* m_gtkVScale; mutable GtkWidget* m_gtkHScale; + mutable GtkWidget* m_gtkRadioButton; + mutable GtkWidget* m_gtkCheckButton; + mutable GtkWidget* m_gtkProgressBar; + mutable GtkWidget* m_gtkComboBox; + mutable GtkWidget* m_gtkComboBoxButton; + mutable GtkWidget* m_gtkComboBoxArrow; + mutable GtkWidget* m_gtkComboBoxSeparator; bool m_themePartsHaveRGBAColormap; friend class WidgetRenderingContext; #endif diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp index e01508e..de4195d 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp +++ b/Source/WebCore/platform/gtk/RenderThemeGtk2.cpp @@ -27,6 +27,10 @@ #ifdef GTK_API_VERSION_2 +// We need this to allow building while using GTK_WIDGET_SET_FLAGS. It's deprecated +// but some theme engines require it to ensure proper rendering of focus indicators. +#undef GTK_DISABLE_DEPRECATED + #include "CSSValueKeywords.h" #include "GraphicsContext.h" #include "GtkVersioning.h" @@ -41,10 +45,6 @@ #include <gdk/gdk.h> #include <gtk/gtk.h> -#if ENABLE(PROGRESS_TAG) -#include "RenderProgress.h" -#endif - namespace WebCore { // This is not a static method, because we want to avoid having GTK+ headers in RenderThemeGtk.h. @@ -61,6 +61,13 @@ void RenderThemeGtk::platformInit() m_gtkTreeView = 0; m_gtkVScale = 0; m_gtkHScale = 0; + m_gtkRadioButton = 0; + m_gtkCheckButton = 0; + m_gtkProgressBar = 0; + m_gtkComboBox = 0; + m_gtkComboBoxButton = 0; + m_gtkComboBoxArrow = 0; + m_gtkComboBoxSeparator = 0; memset(&m_themeParts, 0, sizeof(GtkThemeParts)); GdkColormap* colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default()); @@ -99,8 +106,34 @@ void RenderThemeGtk::initMediaColors() } #endif -void RenderThemeGtk::adjustRepaintRect(const RenderObject*, IntRect&) +static void adjustRectForFocus(GtkWidget* widget, IntRect& rect, bool ignoreInteriorFocusProperty = false) +{ + gint focusWidth, focusPad; + gboolean interiorFocus = 0; + gtk_widget_style_get(widget, + "interior-focus", &interiorFocus, + "focus-line-width", &focusWidth, + "focus-padding", &focusPad, NULL); + if (!ignoreInteriorFocusProperty && interiorFocus) + return; + rect.inflate(focusWidth + focusPad); +} + +void RenderThemeGtk::adjustRepaintRect(const RenderObject* renderObject, IntRect& rect) { + ControlPart part = renderObject->style()->appearance(); + switch (part) { + case CheckboxPart: + case RadioPart: { + // We ignore the interior focus property and always expand the focus rect. In GTK+, the + // focus indicator is usually on the text next to a checkbox or radio button, but that doesn't + // happen in WebCore. By expanding the focus rectangle unconditionally we increase its prominence. + adjustRectForFocus(part == CheckboxPart ? gtkCheckButton() : gtkRadioButton(), rect, true); + return; + } + default: + return; + } } static GtkStateType getGtkStateType(RenderThemeGtk* theme, RenderObject* object) @@ -142,56 +175,89 @@ bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* re gtkTextDirection(renderObject->style()->direction())); } -void RenderThemeGtk::getIndicatorMetrics(ControlPart part, int& indicatorSize, int& indicatorSpacing) +static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, GtkWidget* widget) { - ASSERT(part == CheckboxPart || part == RadioPart); - if (part == CheckboxPart) { - moz_gtk_checkbox_get_metrics(&indicatorSize, &indicatorSpacing); + // The width and height are both specified, so we shouldn't change them. + if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) return; - } - // RadioPart - moz_gtk_radio_get_metrics(&indicatorSize, &indicatorSpacing); + gint indicatorSize; + gtk_widget_style_get(widget, "indicator-size", &indicatorSize, NULL); + if (style->width().isIntrinsicOrAuto()) + style->setWidth(Length(indicatorSize, Fixed)); + if (style->height().isAuto()) + style->setHeight(Length(indicatorSize, Fixed)); } -static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, ControlPart appearance) +static void paintToggle(RenderThemeGtk* theme, RenderObject* renderObject, const PaintInfo& info, const IntRect& rect, GtkWidget* widget) { - // The width and height are both specified, so we shouldn't change them. - if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) - return; + // We do not call gtk_toggle_button_set_active here, because some themes begin a series of + // animation frames in a "toggled" signal handler. This puts some checkboxes in a half-way + // checked state. Every GTK+ theme I tested merely looks at the shadow type (and not the + // 'active' property) to determine whether or not to draw the check. + gtk_widget_set_sensitive(widget, theme->isEnabled(renderObject) && !theme->isReadOnlyControl(renderObject)); + gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style()->direction())); - // FIXME: This is probably not correct use of indicatorSize and indicatorSpacing. - gint indicatorSize, indicatorSpacing; - RenderThemeGtk::getIndicatorMetrics(appearance, indicatorSize, indicatorSpacing); + bool indeterminate = theme->isIndeterminate(renderObject); + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), indeterminate); - // Other ports hard-code this to 13, but GTK+ users tend to demand the native look. - // It could be made a configuration option values other than 13 actually break site compatibility. - int length = indicatorSize + indicatorSpacing; - if (style->width().isIntrinsicOrAuto()) - style->setWidth(Length(length, Fixed)); + GtkShadowType shadowType = GTK_SHADOW_OUT; + if (indeterminate) // This originates from the Mozilla code. + shadowType = GTK_SHADOW_ETCHED_IN; + else if (theme->isChecked(renderObject)) + shadowType = GTK_SHADOW_IN; - if (style->height().isAuto()) - style->setHeight(Length(length, Fixed)); + WidgetRenderingContext widgetContext(info.context, rect); + IntRect buttonRect(IntPoint(), rect.size()); + GtkStateType toggleState = getGtkStateType(theme, renderObject); + const char* detail = 0; + if (GTK_IS_RADIO_BUTTON(widget)) { + detail = "radiobutton"; + widgetContext.gtkPaintOption(buttonRect, widget, toggleState, shadowType, detail); + } else { + detail = "checkbutton"; + widgetContext.gtkPaintCheck(buttonRect, widget, toggleState, shadowType, detail); + } + + if (theme->isFocused(renderObject)) { + IntRect focusRect(buttonRect); + adjustRectForFocus(widget, focusRect, true); + widgetContext.gtkPaintFocus(focusRect, widget, toggleState, detail); + } } void RenderThemeGtk::setCheckboxSize(RenderStyle* style) const { - setToggleSize(this, style, RadioPart); + setToggleSize(this, style, gtkCheckButton()); } -bool RenderThemeGtk::paintCheckbox(RenderObject* object, const PaintInfo& info, const IntRect& rect) +bool RenderThemeGtk::paintCheckbox(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect) { - return paintRenderObject(MOZ_GTK_CHECKBUTTON, object, info.context, rect, isChecked(object)); + paintToggle(this, renderObject, info, rect, gtkCheckButton()); + return false; } void RenderThemeGtk::setRadioSize(RenderStyle* style) const { - setToggleSize(this, style, RadioPart); + setToggleSize(this, style, gtkRadioButton()); +} + +bool RenderThemeGtk::paintRadio(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect) +{ + paintToggle(this, renderObject, info, rect, gtkRadioButton()); + return false; } -bool RenderThemeGtk::paintRadio(RenderObject* object, const PaintInfo& info, const IntRect& rect) +static void setWidgetHasFocus(GtkWidget* widget, gboolean hasFocus) { - return paintRenderObject(MOZ_GTK_RADIOBUTTON, object, info.context, rect, isChecked(object)); + g_object_set(widget, "has-focus", hasFocus, NULL); + + // These functions are deprecated in GTK+ 2.22, yet theme engines still look + // at these flags when determining if a widget has focus, so we must use them. + if (hasFocus) + GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS); + else + GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS); } bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect) @@ -208,12 +274,7 @@ bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, co gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction())); if (isFocused(object)) { - if (isEnabled(object)) { -#if !GTK_CHECK_VERSION(2, 22, 0) - GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS); -#endif - g_object_set(widget, "has-focus", TRUE, NULL); - } + setWidgetHasFocus(widget, TRUE); gboolean interiorFocus = 0, focusWidth = 0, focusPadding = 0; gtk_widget_style_get(widget, @@ -239,21 +300,74 @@ bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, co if (isFocused(object)) widgetContext.gtkPaintFocus(focusRect, widget, state, "button"); -#if !GTK_CHECK_VERSION(2, 22, 0) - GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS); -#endif - g_object_set(widget, "has-focus", FALSE, NULL); + setWidgetHasFocus(widget, FALSE); return false; } -static void getComboBoxPadding(RenderStyle* style, int& left, int& top, int& right, int& bottom) +int RenderThemeGtk::getComboBoxSeparatorWidth() const +{ + GtkWidget* separator = gtkComboBoxSeparator(); + if (!separator) + return 0; + + gboolean hasWideSeparators = FALSE; + gint separatorWidth = 0; + gtk_widget_style_get(separator, + "wide-separators", &hasWideSeparators, + "separator-width", &separatorWidth, + NULL); + if (hasWideSeparators) + return separatorWidth; + return gtk_widget_get_style(separator)->xthickness; +} + +int RenderThemeGtk::comboBoxArrowSize(RenderStyle* style) const +{ + // Taking the font size and reversing the DPI conversion seems to match + // GTK+ rendering as closely as possible. + return style->font().size() * (72.0 / RenderThemeGtk::getScreenDPI()); +} + +static void getButtonInnerBorder(GtkWidget* button, int& left, int& top, int& right, int& bottom) +{ + GtkStyle* style = gtk_widget_get_style(button); + int outerBorder = gtk_container_get_border_width(GTK_CONTAINER(button)); + static GtkBorder defaultInnerBorder = {1, 1, 1, 1}; + GtkBorder* innerBorder; + gtk_widget_style_get(button, "inner-border", &innerBorder, NULL); + if (!innerBorder) + innerBorder = &defaultInnerBorder; + + left = outerBorder + innerBorder->left + style->xthickness; + right = outerBorder + innerBorder->right + style->xthickness; + top = outerBorder + innerBorder->top + style->ythickness; + bottom = outerBorder + innerBorder->bottom + style->ythickness; + + if (innerBorder != &defaultInnerBorder) + gtk_border_free(innerBorder); +} + + +void RenderThemeGtk::getComboBoxPadding(RenderStyle* style, int& left, int& top, int& right, int& bottom) const { // If this menu list button isn't drawn using the native theme, we // don't add any extra padding beyond what WebCore already uses. if (style->appearance() == NoControlPart) return; - moz_gtk_get_widget_border(MOZ_GTK_DROPDOWN, &left, &top, &right, &bottom, - gtkTextDirection(style->direction()), TRUE); + + // A combo box button is a button with widgets packed into it. + GtkStyle* buttonWidgetStyle = gtk_widget_get_style(gtkComboBoxButton()); + getButtonInnerBorder(gtkComboBoxButton(), left, top, right, bottom); + + // Add xthickness amount of padding for each side of the separator. This ensures + // that the text does not bump up against the separator. + int arrowAndSeperatorLength = comboBoxArrowSize(style) + + getComboBoxSeparatorWidth() + (3 * buttonWidgetStyle->xthickness); + + if (style->direction() == RTL) + left += arrowAndSeperatorLength; + else + right += arrowAndSeperatorLength; } int RenderThemeGtk::popupInternalPaddingLeft(RenderStyle* style) const @@ -286,12 +400,102 @@ int RenderThemeGtk::popupInternalPaddingBottom(RenderStyle* style) const bool RenderThemeGtk::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect) { - return paintRenderObject(MOZ_GTK_DROPDOWN, object, info.context, rect); + if (paintButton(object, info, rect)) + return true; + + // Menu list button painting strategy. + // For buttons with appears-as-list set to false (having a separator): + // | left border | Button text | xthickness | vseparator | xthickness | arrow | xthickness | right border | + // For buttons with appears-as-list set to true (not having a separator): + // | left border | Button text | arrow | xthickness | right border | + + int leftBorder = 0, rightBorder = 0, bottomBorder = 0, topBorder = 0; + getButtonInnerBorder(gtkComboBoxButton(), leftBorder, topBorder, rightBorder, bottomBorder); + RenderStyle* style = object->style(); + int arrowSize = comboBoxArrowSize(style); + GtkStyle* buttonStyle = gtk_widget_get_style(gtkComboBoxButton()); + + IntRect arrowRect(0, (rect.height() - arrowSize) / 2, arrowSize, arrowSize); + if (style->direction() == RTL) + arrowRect.setX(leftBorder + buttonStyle->xthickness); + else + arrowRect.setX(rect.width() - rightBorder - buttonStyle->xthickness - arrowSize); + GtkShadowType shadowType = isPressed(object) ? GTK_SHADOW_IN : GTK_SHADOW_OUT; + + WidgetRenderingContext widgetContext(info.context, rect); + GtkStateType stateType = getGtkStateType(this, object); + widgetContext.gtkPaintArrow(arrowRect, gtkComboBoxArrow(), stateType, shadowType, GTK_ARROW_DOWN, "arrow"); + + // Some combo boxes do not have a separator. + GtkWidget* separator = gtkComboBoxSeparator(); + if (!separator) + return false; + + // We want to decrease the height of the separator based on the focus padding of the button. + gint focusPadding = 0, focusWidth = 0; + gtk_widget_style_get(gtkComboBoxButton(), + "focus-line-width", &focusWidth, + "focus-padding", &focusPadding, NULL); + topBorder += focusPadding + focusWidth; + bottomBorder += focusPadding + focusWidth; + int separatorWidth = getComboBoxSeparatorWidth(); + IntRect separatorRect(0, topBorder, separatorWidth, rect.height() - topBorder - bottomBorder); + if (style->direction() == RTL) + separatorRect.setX(arrowRect.x() + arrowRect.width() + buttonStyle->xthickness + separatorWidth); + else + separatorRect.setX(arrowRect.x() - buttonStyle->xthickness - separatorWidth); + + gboolean hasWideSeparators = FALSE; + gtk_widget_style_get(separator, "wide-separators", &hasWideSeparators, NULL); + if (hasWideSeparators) + widgetContext.gtkPaintBox(separatorRect, separator, GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT, "vseparator"); + else + widgetContext.gtkPaintVLine(separatorRect, separator, GTK_STATE_NORMAL, "vseparator"); + + return false; } -bool RenderThemeGtk::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect) +bool RenderThemeGtk::paintTextField(RenderObject* renderObject, const PaintInfo& info, const IntRect& rect) { - return paintRenderObject(MOZ_GTK_ENTRY, object, info.context, rect); + GtkWidget* widget = gtkEntry(); + + bool enabled = isEnabled(renderObject) && !isReadOnlyControl(renderObject); + GtkStateType backgroundState = enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; + gtk_widget_set_sensitive(widget, enabled); + gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style()->direction())); + setWidgetHasFocus(widget, isFocused(renderObject)); + + WidgetRenderingContext widgetContext(info.context, rect); + IntRect textFieldRect(IntPoint(), rect.size()); + + // The entry background is only painted over the interior part of the GTK+ entry, not + // the entire frame. This happens in the Mozilla theme drawing code as well. + IntRect interiorRect(textFieldRect); + GtkStyle* style = gtk_widget_get_style(widget); + interiorRect.inflateX(-style->xthickness); + interiorRect.inflateY(-style->ythickness); + widgetContext.gtkPaintFlatBox(interiorRect, widget, backgroundState, GTK_SHADOW_NONE, "entry_bg"); + + // This is responsible for drawing the actual frame. + widgetContext.gtkPaintShadow(textFieldRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry"); + + gboolean interiorFocus; + gint focusWidth; + gtk_widget_style_get(widget, + "interior-focus", &interiorFocus, + "focus-line-width", &focusWidth, NULL); + if (isFocused(renderObject) && !interiorFocus) { + // When GTK+ paints a text entry with focus, it shrinks the size of the frame area by the + // focus width and paints over the previously unfocused text entry. We need to emulate that + // by drawing both the unfocused frame above and the focused frame here. + IntRect shadowRect(textFieldRect); + shadowRect.inflate(-focusWidth); + widgetContext.gtkPaintShadow(shadowRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "entry"); + + widgetContext.gtkPaintFocus(textFieldRect, widget, GTK_STATE_NORMAL, "entry"); + } + + return false; } bool RenderThemeGtk::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect) @@ -382,45 +586,25 @@ void RenderThemeGtk::adjustSliderThumbSize(RenderObject* o) const } #if ENABLE(PROGRESS_TAG) -double RenderThemeGtk::animationRepeatIntervalForProgressBar(RenderProgress*) const -{ - // FIXME: It doesn't look like there is a good way yet to support animated - // progress bars with the Mozilla theme drawing code. - return 0; -} - -double RenderThemeGtk::animationDurationForProgressBar(RenderProgress*) const -{ - // FIXME: It doesn't look like there is a good way yet to support animated - // progress bars with the Mozilla theme drawing code. - return 0; -} - bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect) { - if (!renderObject->isProgress()) - return true; + GtkWidget* widget = gtkProgressBar(); + gtk_widget_set_direction(widget, gtkTextDirection(renderObject->style()->direction())); - GtkWidget* progressBarWidget = moz_gtk_get_progress_widget(); - if (!progressBarWidget) - return true; + WidgetRenderingContext widgetContext(paintInfo.context, rect); + IntRect fullProgressBarRect(IntPoint(), rect.size()); + widgetContext.gtkPaintBox(fullProgressBarRect, widget, GTK_STATE_NORMAL, GTK_SHADOW_IN, "trough"); - if (paintRenderObject(MOZ_GTK_PROGRESSBAR, renderObject, paintInfo.context, rect)) - return true; + GtkStyle* style = gtk_widget_get_style(widget); + IntRect progressRect(fullProgressBarRect); + progressRect.inflateX(-style->xthickness); + progressRect.inflateY(-style->ythickness); + progressRect = RenderThemeGtk::calculateProgressRect(renderObject, progressRect); - IntRect chunkRect(rect); - RenderProgress* renderProgress = toRenderProgress(renderObject); + if (!progressRect.isEmpty()) + widgetContext.gtkPaintBox(progressRect, widget, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, "bar"); - GtkStyle* style = gtk_widget_get_style(progressBarWidget); - chunkRect.setHeight(chunkRect.height() - (2 * style->ythickness)); - chunkRect.setY(chunkRect.y() + style->ythickness); - chunkRect.setWidth((chunkRect.width() - (2 * style->xthickness)) * renderProgress->position()); - if (renderObject->style()->direction() == RTL) - chunkRect.setX(rect.x() + rect.width() - chunkRect.width() - style->xthickness); - else - chunkRect.setX(chunkRect.x() + style->xthickness); - - return paintRenderObject(MOZ_GTK_PROGRESS_CHUNK, renderObject, paintInfo.context, chunkRect); + return false; } #endif @@ -503,11 +687,16 @@ static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, RenderThe renderTheme->platformColorsDidChange(); } -void RenderThemeGtk::setupWidgetAndAddToContainer(GtkWidget* widget, GtkWidget* window) const +static void setupWidget(GtkWidget* widget) { - gtk_container_add(GTK_CONTAINER(window), widget); gtk_widget_realize(widget); g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); +} + +void RenderThemeGtk::setupWidgetAndAddToContainer(GtkWidget* widget, GtkWidget* window) const +{ + gtk_container_add(GTK_CONTAINER(window), widget); + setupWidget(widget); // FIXME: Perhaps this should only be called for the containing window or parent container. g_signal_connect(widget, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this)); @@ -520,7 +709,7 @@ GtkWidget* RenderThemeGtk::gtkContainer() const m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP); gtk_widget_set_colormap(m_gtkWindow, m_themeParts.colormap); - gtk_widget_realize(m_gtkWindow); + setupWidget(m_gtkWindow); gtk_widget_set_name(m_gtkWindow, "MozillaGtkWidget"); m_gtkContainer = gtk_fixed_new(); @@ -573,6 +762,126 @@ GtkWidget* RenderThemeGtk::gtkHScale() const return m_gtkHScale; } +GtkWidget* RenderThemeGtk::gtkRadioButton() const +{ + if (m_gtkRadioButton) + return m_gtkRadioButton; + m_gtkRadioButton = gtk_radio_button_new(0); + setupWidgetAndAddToContainer(m_gtkRadioButton, gtkContainer()); + return m_gtkRadioButton; +} + +GtkWidget* RenderThemeGtk::gtkCheckButton() const +{ + if (m_gtkCheckButton) + return m_gtkCheckButton; + m_gtkCheckButton = gtk_check_button_new(); + setupWidgetAndAddToContainer(m_gtkCheckButton, gtkContainer()); + return m_gtkCheckButton; +} + +GtkWidget* RenderThemeGtk::gtkProgressBar() const +{ + if (m_gtkProgressBar) + return m_gtkProgressBar; + m_gtkProgressBar = gtk_progress_bar_new(); + setupWidgetAndAddToContainer(m_gtkProgressBar, gtkContainer()); + return m_gtkProgressBar; +} + +static void getGtkComboBoxButton(GtkWidget* widget, gpointer target) +{ + if (!GTK_IS_TOGGLE_BUTTON(widget)) + return; + GtkWidget** widgetTarget = static_cast<GtkWidget**>(target); + *widgetTarget = widget; +} + +typedef struct { + GtkWidget* arrow; + GtkWidget* separator; +} ComboBoxWidgetPieces; + +static void getGtkComboBoxPieces(GtkWidget* widget, gpointer data) +{ + if (GTK_IS_ARROW(widget)) { + static_cast<ComboBoxWidgetPieces*>(data)->arrow = widget; + return; + } + if (GTK_IS_SEPARATOR(widget)) + static_cast<ComboBoxWidgetPieces*>(data)->separator = widget; +} + +GtkWidget* RenderThemeGtk::gtkComboBox() const +{ + if (m_gtkComboBox) + return m_gtkComboBox; + m_gtkComboBox = gtk_combo_box_new(); + setupWidgetAndAddToContainer(m_gtkComboBox, gtkContainer()); + return m_gtkComboBox; +} + +void RenderThemeGtk::refreshComboBoxChildren() const +{ + gtkComboBox(); // Ensure that we've initialized the combo box. + + // Some themes look at widget ancestry to determine how to render widgets, so + // get the GtkButton that is the actual child of the combo box. + gtk_container_forall(GTK_CONTAINER(m_gtkComboBox), getGtkComboBoxButton, &m_gtkComboBoxButton); + ASSERT(m_gtkComboBoxButton); + setupWidget(m_gtkComboBoxButton); + g_object_add_weak_pointer(G_OBJECT(m_gtkComboBoxButton), reinterpret_cast<gpointer*>(&m_gtkComboBoxButton)); + + ComboBoxWidgetPieces pieces = { 0, 0 }; + GtkWidget* buttonChild = gtk_bin_get_child(GTK_BIN(gtkComboBoxButton())); + if (GTK_IS_HBOX(buttonChild)) + gtk_container_forall(GTK_CONTAINER(buttonChild), getGtkComboBoxPieces, &pieces); + else if (GTK_IS_ARROW(buttonChild)) + pieces.arrow = buttonChild; + + ASSERT(pieces.arrow); + m_gtkComboBoxArrow = pieces.arrow; + setupWidget(m_gtkComboBoxArrow); + // When the style changes, the combo box may destroy its children. + g_object_add_weak_pointer(G_OBJECT(m_gtkComboBoxArrow), reinterpret_cast<gpointer*>(&m_gtkComboBoxArrow)); + + m_gtkComboBoxSeparator = pieces.separator; + if (m_gtkComboBoxSeparator) { + setupWidget(m_gtkComboBoxSeparator); + // When the style changes, the combo box may destroy its children. + g_object_add_weak_pointer(G_OBJECT(m_gtkComboBoxSeparator), reinterpret_cast<gpointer*>(&m_gtkComboBoxSeparator)); + } +} + +GtkWidget* RenderThemeGtk::gtkComboBoxButton() const +{ + if (m_gtkComboBoxButton) + return m_gtkComboBoxButton; + refreshComboBoxChildren(); + ASSERT(m_gtkComboBoxButton); + return m_gtkComboBoxButton; +} + +GtkWidget* RenderThemeGtk::gtkComboBoxArrow() const +{ + if (m_gtkComboBoxArrow) + return m_gtkComboBoxArrow; + refreshComboBoxChildren(); + ASSERT(m_gtkComboBoxArrow); + return m_gtkComboBoxArrow; +} + +GtkWidget* RenderThemeGtk::gtkComboBoxSeparator() const +{ + // m_gtkComboBoxSeparator may be null either because we haven't initialized the combo box + // or because the combo boxes in this theme don't have separators. If m_gtkComboBoxArrow + // arrow isn't null, we definitely have initialized the combo box. + if (m_gtkComboBoxArrow || m_gtkComboBoxButton) + return m_gtkComboBoxSeparator; + refreshComboBoxChildren(); + return m_gtkComboBoxSeparator; +} + GtkWidget* RenderThemeGtk::gtkScrollbar() { return moz_gtk_get_scrollbar_widget(); diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp index 212e29d..1a9f445 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp +++ b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp @@ -41,10 +41,6 @@ #include <gdk/gdk.h> #include <gtk/gtk.h> -#if ENABLE(PROGRESS_TAG) -#include "RenderProgress.h" -#endif - namespace WebCore { // This is the default value defined by GTK+, where it was defined as MIN_ARROW_SIZE in gtkarrow.c. @@ -690,20 +686,6 @@ void RenderThemeGtk::adjustSliderThumbSize(RenderObject* renderObject) const } #if ENABLE(PROGRESS_TAG) -// These values have been copied from RenderThemeChromiumSkia.cpp -static const int progressActivityBlocks = 5; -static const int progressAnimationFrames = 10; -static const double progressAnimationInterval = 0.125; -double RenderThemeGtk::animationRepeatIntervalForProgressBar(RenderProgress*) const -{ - return progressAnimationInterval; -} - -double RenderThemeGtk::animationDurationForProgressBar(RenderProgress*) const -{ - return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth; -} - bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect) { if (!renderObject->isProgress()) @@ -722,34 +704,18 @@ bool RenderThemeGtk::paintProgressBar(RenderObject* renderObject, const PaintInf gtk_style_context_save(context); gtk_style_context_add_class(context, GTK_STYLE_CLASS_PROGRESSBAR); - RenderProgress* renderProgress = toRenderProgress(renderObject); GtkBorder padding; gtk_style_context_get_padding(context, static_cast<GtkStateFlags>(0), &padding); IntRect progressRect(rect.x() + padding.left, rect.y() + padding.top, rect.width() - (padding.left + padding.right), rect.height() - (padding.top + padding.bottom)); - - if (renderProgress->isDeterminate()) { - progressRect.setWidth(progressRect.width() * renderProgress->position()); - if (renderObject->style()->direction() == RTL) - progressRect.setX(rect.x() + rect.width() - progressRect.width() - padding.right); - } else { - double animationProgress = renderProgress->animationProgress(); - - progressRect.setWidth(max(2, progressRect.width() / progressActivityBlocks)); - int movableWidth = rect.width() - progressRect.width(); - if (animationProgress < 0.5) - progressRect.setX(progressRect.x() + (animationProgress * 2 * movableWidth)); - else - progressRect.setX(progressRect.x() + ((1.0 - animationProgress) * 2 * movableWidth)); - } + progressRect = RenderThemeGtk::calculateProgressRect(renderObject, progressRect); if (!progressRect.isEmpty()) gtk_render_activity(context, paintInfo.context->platformContext(), progressRect.x(), progressRect.y(), progressRect.width(), progressRect.height()); gtk_style_context_restore(context); - return false; } #endif diff --git a/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp b/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp index 6d1be31..51b32ea 100644 --- a/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp +++ b/Source/WebCore/platform/gtk/WidgetRenderingContext.cpp @@ -65,21 +65,6 @@ static void scheduleScratchBufferPurge() purgeScratchBufferTimer.startOneShot(2); } -static IntSize getExtraSpaceForWidget(RenderThemeGtk* theme) -{ - // Checkboxes and scrollbar thumbs often draw outside their boundaries. Here we figure out - // the maximum amount of space we need for any type of widget and use that to increase the - // size of the scratch buffer, while preserving the final widget position. - - // The checkbox extra space is calculated by looking at the widget style. - int indicatorSize, indicatorSpacing; - theme->getIndicatorMetrics(CheckboxPart, indicatorSize, indicatorSpacing); - IntSize extraSpace(indicatorSpacing, indicatorSpacing); - - // Scrollbar thumbs need at least an extra pixel along their movement axis. - return extraSpace.expandedTo(IntSize(1, 1)); -} - WidgetRenderingContext::WidgetRenderingContext(GraphicsContext* graphicsContext, const IntRect& targetRect) : m_graphicsContext(graphicsContext) , m_targetRect(targetRect) @@ -96,8 +81,9 @@ WidgetRenderingContext::WidgetRenderingContext(GraphicsContext* graphicsContext, return; } - // Some widgets render outside their rectangles. We need to account for this. - m_extraSpace = getExtraSpaceForWidget(theme); + // Widgets sometimes need to draw outside their boundaries for things such as + // exterior focus. We want to allocate a some extra pixels in our surface for this. + m_extraSpace = IntSize(15, 15); // Offset the target rectangle so that the extra space is within the boundaries of the scratch buffer. m_paintRect = IntRect(IntPoint(m_extraSpace.width(), m_extraSpace.height()), @@ -173,10 +159,17 @@ void WidgetRenderingContext::gtkPaintBox(const IntRect& rect, GtkWidget* widget, widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height); } +void WidgetRenderingContext::gtkPaintFlatBox(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail) +{ + GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() }; + gtk_paint_flat_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect, + widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height); +} + void WidgetRenderingContext::gtkPaintFocus(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, const gchar* detail) { GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() }; - gtk_paint_focus(gtk_widget_get_style(widget), m_target, stateType, &m_paintRect, widget, + gtk_paint_focus(gtk_widget_get_style(widget), m_target, stateType, &paintRect, widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height); } @@ -187,6 +180,42 @@ void WidgetRenderingContext::gtkPaintSlider(const IntRect& rect, GtkWidget* widg detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height, orientation); } +void WidgetRenderingContext::gtkPaintCheck(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail) +{ + GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() }; + gtk_paint_check(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect, widget, + detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height); +} + +void WidgetRenderingContext::gtkPaintOption(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail) +{ + GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() }; + gtk_paint_option(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect, widget, + detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height); +} + +void WidgetRenderingContext::gtkPaintShadow(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail) +{ + GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() }; + gtk_paint_shadow(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect, widget, + detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height); +} + +void WidgetRenderingContext::gtkPaintArrow(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, int arrowDirection, const gchar* detail) +{ + GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() }; + gtk_paint_arrow(gtk_widget_get_style(widget), m_target, stateType, shadowType, &paintRect, widget, detail, + static_cast<GtkArrowType>(arrowDirection), TRUE, paintRect.x, paintRect.y, paintRect.width, paintRect.height); +} + +void WidgetRenderingContext::gtkPaintVLine(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, const gchar* detail) +{ + GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() }; + gtk_paint_vline(gtk_widget_get_style(widget), m_target, stateType, &paintRect, widget, detail, + paintRect.y, paintRect.y + paintRect.height, paintRect.x); + +} + } #endif // GTK_API_VERSION_2 diff --git a/Source/WebCore/platform/gtk/WidgetRenderingContext.h b/Source/WebCore/platform/gtk/WidgetRenderingContext.h index 8b2a0e2..e248f04 100644 --- a/Source/WebCore/platform/gtk/WidgetRenderingContext.h +++ b/Source/WebCore/platform/gtk/WidgetRenderingContext.h @@ -39,8 +39,14 @@ public: bool paintMozillaWidget(GtkThemeWidgetType, GtkWidgetState*, int flags, GtkTextDirection = GTK_TEXT_DIR_NONE); void gtkPaintBox(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*); + void gtkPaintFlatBox(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*); void gtkPaintFocus(const IntRect&, GtkWidget*, GtkStateType, const gchar*); void gtkPaintSlider(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*, GtkOrientation); + void gtkPaintCheck(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*); + void gtkPaintOption(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*); + void gtkPaintShadow(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*); + void gtkPaintArrow(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, int arrowDirection, const gchar*); + void gtkPaintVLine(const IntRect&, GtkWidget*, GtkStateType, const gchar*); private: GraphicsContext* m_graphicsContext; diff --git a/Source/WebCore/platform/gtk/gtk2drawing.c b/Source/WebCore/platform/gtk/gtk2drawing.c index 3ebd332..3979b7f 100644 --- a/Source/WebCore/platform/gtk/gtk2drawing.c +++ b/Source/WebCore/platform/gtk/gtk2drawing.c @@ -60,7 +60,6 @@ static GtkThemeParts *gParts = NULL; static style_prop_t style_prop_func; -static gboolean have_arrow_scaling; static gboolean is_initialized; void @@ -116,61 +115,6 @@ setup_widget_prototype(GtkWidget* widget) } static gint -ensure_button_widget() -{ - if (!gParts->buttonWidget) { - gParts->buttonWidget = gtk_button_new_with_label("M"); - setup_widget_prototype(gParts->buttonWidget); - } - return MOZ_GTK_SUCCESS; -} - -static gint -ensure_toggle_button_widget() -{ - if (!gParts->toggleButtonWidget) { - gParts->toggleButtonWidget = gtk_toggle_button_new(); - setup_widget_prototype(gParts->toggleButtonWidget); - /* toggle button must be set active to get the right style on hover. */ - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gParts->toggleButtonWidget), TRUE); - } - return MOZ_GTK_SUCCESS; -} - -static gint -ensure_button_arrow_widget() -{ - if (!gParts->buttonArrowWidget) { - ensure_toggle_button_widget(); - - gParts->buttonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); - gtk_container_add(GTK_CONTAINER(gParts->toggleButtonWidget), gParts->buttonArrowWidget); - gtk_widget_realize(gParts->buttonArrowWidget); - } - return MOZ_GTK_SUCCESS; -} - -static gint -ensure_checkbox_widget() -{ - if (!gParts->checkboxWidget) { - gParts->checkboxWidget = gtk_check_button_new_with_label("M"); - setup_widget_prototype(gParts->checkboxWidget); - } - return MOZ_GTK_SUCCESS; -} - -static gint -ensure_radiobutton_widget() -{ - if (!gParts->radiobuttonWidget) { - gParts->radiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M"); - setup_widget_prototype(gParts->radiobuttonWidget); - } - return MOZ_GTK_SUCCESS; -} - -static gint ensure_scrollbar_widget() { if (!gParts->vertScrollbarWidget) { @@ -185,129 +129,6 @@ ensure_scrollbar_widget() } static gint -ensure_entry_widget() -{ - if (!gParts->entryWidget) { - gParts->entryWidget = gtk_entry_new(); - setup_widget_prototype(gParts->entryWidget); - } - return MOZ_GTK_SUCCESS; -} - -/* We need to have pointers to the inner widgets (button, separator, arrow) - * of the ComboBox to get the correct rendering from theme engines which - * special cases their look. Since the inner layout can change, we ask GTK - * to NULL our pointers when they are about to become invalid because the - * corresponding widgets don't exist anymore. It's the role of - * g_object_add_weak_pointer(). - * Note that if we don't find the inner widgets (which shouldn't happen), we - * fallback to use generic "non-inner" widgets, and they don't need that kind - * of weak pointer since they are explicit children of gParts->protoWindow and as - * such GTK holds a strong reference to them. */ -static void -moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data) -{ - if (GTK_IS_TOGGLE_BUTTON(widget)) { - gParts->comboBoxButtonWidget = widget; - g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gParts->comboBoxButtonWidget); - gtk_widget_realize(widget); - g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); - } -} - -static void -moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget, - gpointer client_data) -{ - if (GTK_IS_SEPARATOR(widget)) { - gParts->comboBoxSeparatorWidget = widget; - g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gParts->comboBoxSeparatorWidget); - } else if (GTK_IS_ARROW(widget)) { - gParts->comboBoxArrowWidget = widget; - g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gParts->comboBoxArrowWidget); - } else - return; - gtk_widget_realize(widget); - g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); -} - -static gint -ensure_combo_box_widgets() -{ - GtkWidget* buttonChild; - - if (gParts->comboBoxButtonWidget && gParts->comboBoxArrowWidget) - return MOZ_GTK_SUCCESS; - - /* Create a ComboBox if needed */ - if (!gParts->comboBoxWidget) { - gParts->comboBoxWidget = gtk_combo_box_new(); - setup_widget_prototype(gParts->comboBoxWidget); - } - - /* Get its inner Button */ - gtk_container_forall(GTK_CONTAINER(gParts->comboBoxWidget), - moz_gtk_get_combo_box_inner_button, - NULL); - - if (gParts->comboBoxButtonWidget) { - /* Get the widgets inside the Button */ - buttonChild = gtk_bin_get_child(GTK_BIN(gParts->comboBoxButtonWidget)); - if (GTK_IS_HBOX(buttonChild)) { - /* appears-as-list = FALSE, cell-view = TRUE; the button - * contains an hbox. This hbox is there because the ComboBox - * needs to place a cell renderer, a separator, and an arrow in - * the button when appears-as-list is FALSE. */ - gtk_container_forall(GTK_CONTAINER(buttonChild), - moz_gtk_get_combo_box_button_inner_widgets, - NULL); - } else if(GTK_IS_ARROW(buttonChild)) { - /* appears-as-list = TRUE, or cell-view = FALSE; - * the button only contains an arrow */ - gParts->comboBoxArrowWidget = buttonChild; - g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer) - &gParts->comboBoxArrowWidget); - gtk_widget_realize(gParts->comboBoxArrowWidget); - g_object_set_data(G_OBJECT(gParts->comboBoxArrowWidget), - "transparent-bg-hint", GINT_TO_POINTER(TRUE)); - } - } else { - /* Shouldn't be reached with current internal gtk implementation; we - * use a generic toggle button as last resort fallback to avoid - * crashing. */ - ensure_toggle_button_widget(); - gParts->comboBoxButtonWidget = gParts->toggleButtonWidget; - } - - if (!gParts->comboBoxArrowWidget) { - /* Shouldn't be reached with current internal gtk implementation; - * we gParts->buttonArrowWidget as last resort fallback to avoid - * crashing. */ - ensure_button_arrow_widget(); - gParts->comboBoxArrowWidget = gParts->buttonArrowWidget; - } - - /* We don't test the validity of gParts->comboBoxSeparatorWidget since there - * is none when "appears-as-list" = TRUE or "cell-view" = FALSE; if it - * is invalid we just won't paint it. */ - - return MOZ_GTK_SUCCESS; -} - -static gint -ensure_progress_widget() -{ - if (!gParts->progresWidget) { - gParts->progresWidget = gtk_progress_bar_new(); - setup_widget_prototype(gParts->progresWidget); - } - return MOZ_GTK_SUCCESS; -} - -static gint ensure_scrolled_window_widget() { if (!gParts->scrolledWindowWidget) { @@ -355,93 +176,12 @@ TSOffsetStyleGCs(GtkStyle* style, gint xorigin, gint yorigin) return MOZ_GTK_SUCCESS; } -static gint -moz_gtk_button_paint(GdkDrawable* drawable, GdkRectangle* rect, - GdkRectangle* cliprect, GtkWidgetState* state, - GtkReliefStyle relief, GtkWidget* widget, - GtkTextDirection direction) -{ - GtkShadowType shadow_type; - GtkStyle* style = gtk_widget_get_style(widget); - GtkStateType button_state = ConvertGtkState(state); - gint x = rect->x, y=rect->y, width=rect->width, height=rect->height; - - gboolean interior_focus; - gint focus_width, focus_pad; - - moz_gtk_widget_get_focus(widget, &interior_focus, &focus_width, &focus_pad); - - gtk_widget_set_state(widget, button_state); - gtk_widget_set_direction(widget, direction); - - if (state->isDefault) - GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_DEFAULT); - - gtk_button_set_relief(GTK_BUTTON(widget), relief); - - /* Some theme engines love to cause us pain in that gtk_paint_focus is a - no-op on buttons and button-like widgets. They only listen to this flag. */ - if (state->focused && !state->disabled) - GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS); - - if (!interior_focus && state->focused) { - x += focus_width + focus_pad; - y += focus_width + focus_pad; - width -= 2 * (focus_width + focus_pad); - height -= 2 * (focus_width + focus_pad); - } - - shadow_type = button_state == GTK_STATE_ACTIVE || - state->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT; - - if (state->isDefault && relief == GTK_RELIEF_NORMAL) { - gtk_paint_box(style, drawable, button_state, shadow_type, cliprect, - widget, "buttondefault", x, y, width, height); - } - - if (relief != GTK_RELIEF_NONE || state->depressed || - (button_state != GTK_STATE_NORMAL && - button_state != GTK_STATE_INSENSITIVE)) { - TSOffsetStyleGCs(style, x, y); - /* the following line can trigger an assertion (Crux theme) - file ../../gdk/gdkwindow.c: line 1846 (gdk_window_clear_area): - assertion `GDK_IS_WINDOW (window)' failed */ - gtk_paint_box(style, drawable, button_state, shadow_type, cliprect, - widget, "button", x, y, width, height); - } - - if (state->focused) { - if (interior_focus) { - GtkStyle* style = gtk_widget_get_style(widget); - x += style->xthickness + focus_pad; - y += style->ythickness + focus_pad; - width -= 2 * (style->xthickness + focus_pad); - height -= 2 * (style->ythickness + focus_pad); - } else { - x -= focus_width + focus_pad; - y -= focus_width + focus_pad; - width += 2 * (focus_width + focus_pad); - height += 2 * (focus_width + focus_pad); - } - - TSOffsetStyleGCs(style, x, y); - gtk_paint_focus(style, drawable, button_state, cliprect, - widget, "button", x, y, width, height); - } - - GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_DEFAULT); - GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS); - return MOZ_GTK_SUCCESS; -} - gint moz_gtk_init() { GtkWidgetClass *entry_class; is_initialized = TRUE; - have_arrow_scaling = (gtk_major_version > 2 || - (gtk_major_version == 2 && gtk_minor_version >= 12)); /* Add style property to GtkEntry. * Adding the style property to the normal GtkEntry class means that it @@ -457,215 +197,6 @@ moz_gtk_init() return MOZ_GTK_SUCCESS; } -gint -moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing) -{ - ensure_checkbox_widget(); - - gtk_widget_style_get (gParts->checkboxWidget, - "indicator_size", indicator_size, - "indicator_spacing", indicator_spacing, - NULL); - - return MOZ_GTK_SUCCESS; -} - -gint -moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing) -{ - ensure_radiobutton_widget(); - - gtk_widget_style_get (gParts->radiobuttonWidget, - "indicator_size", indicator_size, - "indicator_spacing", indicator_spacing, - NULL); - - return MOZ_GTK_SUCCESS; -} - -gint -moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus, - gint* focus_width, gint* focus_pad) -{ - gtk_widget_style_get (widget, - "interior-focus", interior_focus, - "focus-line-width", focus_width, - "focus-padding", focus_pad, - NULL); - - return MOZ_GTK_SUCCESS; -} - -gint -moz_gtk_button_get_inner_border(GtkWidget* widget, GtkBorder* inner_border) -{ - static const GtkBorder default_inner_border = { 1, 1, 1, 1 }; - GtkBorder *tmp_border; - - gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL); - - if (tmp_border) { - *inner_border = *tmp_border; - gtk_border_free(tmp_border); - } - else - *inner_border = default_inner_border; - - return MOZ_GTK_SUCCESS; -} - -static gint -moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect, - GdkRectangle* cliprect, GtkWidgetState* state, - gboolean selected, gboolean inconsistent, - gboolean isradio, GtkTextDirection direction) -{ - GtkStateType state_type = ConvertGtkState(state); - GtkShadowType shadow_type = (selected)?GTK_SHADOW_IN:GTK_SHADOW_OUT; - gint indicator_size, indicator_spacing; - gint x, y, width, height; - gint focus_x, focus_y, focus_width, focus_height; - GtkWidget *w; - GtkStyle *style; - - if (isradio) { - moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing); - w = gParts->radiobuttonWidget; - } else { - moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing); - w = gParts->checkboxWidget; - } - - // "GetMinimumWidgetSize was ignored" - // FIXME: This assert causes a build failure in WebKitGTK+ debug - // builds, because it uses 'false' in its definition. We may want - // to force this file to be built with g++, by renaming it. - // ASSERT(rect->width == indicator_size); - - /* - * vertically center in the box, since XUL sometimes ignores our - * GetMinimumWidgetSize in the vertical dimension - */ - x = rect->x; - y = rect->y + (rect->height - indicator_size) / 2; - width = indicator_size; - height = indicator_size; - - focus_x = x - indicator_spacing; - focus_y = y - indicator_spacing; - focus_width = width + 2 * indicator_spacing; - focus_height = height + 2 * indicator_spacing; - - style = gtk_widget_get_style(w); - TSOffsetStyleGCs(style, x, y); - - gtk_widget_set_sensitive(w, !state->disabled); - gtk_widget_set_direction(w, direction); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), selected); - - if (isradio) { - gtk_paint_option(style, drawable, state_type, shadow_type, cliprect, - gParts->radiobuttonWidget, "radiobutton", x, y, - width, height); - if (state->focused) { - gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect, - gParts->radiobuttonWidget, "radiobutton", focus_x, focus_y, - focus_width, focus_height); - } - } - else { - /* - * 'indeterminate' type on checkboxes. In GTK, the shadow type - * must also be changed for the state to be drawn. - */ - if (inconsistent) { - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gParts->checkboxWidget), TRUE); - shadow_type = GTK_SHADOW_ETCHED_IN; - } else { - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gParts->checkboxWidget), FALSE); - } - - gtk_paint_check(style, drawable, state_type, shadow_type, cliprect, - gParts->checkboxWidget, "checkbutton", x, y, width, height); - if (state->focused) { - gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect, - gParts->checkboxWidget, "checkbutton", focus_x, focus_y, - focus_width, focus_height); - } - } - - return MOZ_GTK_SUCCESS; -} - -static gint -calculate_button_inner_rect(GtkWidget* button, GdkRectangle* rect, - GdkRectangle* inner_rect, - GtkTextDirection direction, - gboolean ignore_focus) -{ - GtkBorder inner_border; - gboolean interior_focus; - gint focus_width, focus_pad; - GtkStyle* style; - - style = gtk_widget_get_style(button); - - /* This mirrors gtkbutton's child positioning */ - moz_gtk_button_get_inner_border(button, &inner_border); - moz_gtk_widget_get_focus(button, &interior_focus, - &focus_width, &focus_pad); - - if (ignore_focus) - focus_width = focus_pad = 0; - - inner_rect->x = rect->x + XTHICKNESS(style) + focus_width + focus_pad; - inner_rect->x += direction == GTK_TEXT_DIR_LTR ? - inner_border.left : inner_border.right; - inner_rect->y = rect->y + inner_border.top + YTHICKNESS(style) + - focus_width + focus_pad; - inner_rect->width = MAX(1, rect->width - inner_border.left - - inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2); - inner_rect->height = MAX(1, rect->height - inner_border.top - - inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2); - - return MOZ_GTK_SUCCESS; -} - - -static gint -calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect, - GdkRectangle* arrow_rect, GtkTextDirection direction) -{ - /* defined in gtkarrow.c */ - gfloat arrow_scaling = 0.7; - gfloat xalign, xpad; - gint extent; - GtkMisc* misc = GTK_MISC(arrow); - gfloat misc_xalign, misc_yalign; - gint misc_xpad, misc_ypad; - - if (have_arrow_scaling) - gtk_widget_style_get(arrow, "arrow_scaling", &arrow_scaling, NULL); - - gtk_misc_get_padding(misc, &misc_xpad, &misc_ypad); - gtk_misc_get_alignment(misc, &misc_xalign, &misc_yalign); - - extent = MIN((rect->width - misc_xpad * 2), - (rect->height - misc_ypad * 2)) * arrow_scaling; - - xalign = direction == GTK_TEXT_DIR_LTR ? misc_xalign : 1.0 - misc_xalign; - xpad = misc_xpad + (rect->width - extent) * xalign; - - arrow_rect->x = direction == GTK_TEXT_DIR_LTR ? - floor(rect->x + xpad) : ceil(rect->x + xpad); - arrow_rect->y = floor(rect->y + misc_ypad + - ((rect->height - extent) * misc_yalign)); - - arrow_rect->width = arrow_rect->height = extent; - - return MOZ_GTK_SUCCESS; -} - static gint moz_gtk_scrolled_window_paint(GdkDrawable* drawable, GdkRectangle* rect, GdkRectangle* cliprect, GtkWidgetState* state) @@ -906,226 +437,6 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget, return MOZ_GTK_SUCCESS; } -static gint -moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect, - GdkRectangle* cliprect, GtkWidgetState* state, - GtkWidget* widget, GtkTextDirection direction) -{ - GtkStateType bg_state = state->disabled ? - GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL; - gint x, y, width = rect->width, height = rect->height; - GtkStyle* style; - gboolean interior_focus; - gboolean theme_honors_transparency = FALSE; - gint focus_width; - - gtk_widget_set_direction(widget, direction); - - style = gtk_widget_get_style(widget); - - gtk_widget_style_get(widget, - "interior-focus", &interior_focus, - "focus-line-width", &focus_width, - "honors-transparent-bg-hint", &theme_honors_transparency, - NULL); - - /* gtkentry.c uses two windows, one for the entire widget and one for the - * text area inside it. The background of both windows is set to the "base" - * color of the new state in gtk_entry_state_changed, but only the inner - * textarea window uses gtk_paint_flat_box when exposed */ - - TSOffsetStyleGCs(style, rect->x, rect->y); - - /* This gets us a lovely greyish disabledish look */ - gtk_widget_set_sensitive(widget, !state->disabled); - - /* GTK fills the outer widget window with the base color before drawing the widget. - * Some older themes rely on this behavior, but many themes nowadays use rounded - * corners on their widgets. While most GTK apps are blissfully unaware of this - * problem due to their use of the default window background, we render widgets on - * many kinds of backgrounds on the web. - * If the theme is able to cope with transparency, then we can skip pre-filling - * and notify the theme it will paint directly on the canvas. */ - if (theme_honors_transparency) { - g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); - } else { - gdk_draw_rectangle(drawable, style->base_gc[bg_state], TRUE, - cliprect->x, cliprect->y, cliprect->width, cliprect->height); - g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(FALSE)); - } - - /* Get the position of the inner window, see _gtk_entry_get_borders */ - x = XTHICKNESS(style); - y = YTHICKNESS(style); - - if (!interior_focus) { - x += focus_width; - y += focus_width; - } - - /* Simulate an expose of the inner window */ - gtk_paint_flat_box(style, drawable, bg_state, GTK_SHADOW_NONE, - cliprect, widget, "entry_bg", rect->x + x, - rect->y + y, rect->width - 2*x, rect->height - 2*y); - - /* Now paint the shadow and focus border. - * We do like in gtk_entry_draw_frame, we first draw the shadow, a tad - * smaller when focused if the focus is not interior, then the focus. */ - x = rect->x; - y = rect->y; - - if (state->focused && !state->disabled) { - /* This will get us the lit borders that focused textboxes enjoy on - * some themes. */ - GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS); - - if (!interior_focus) { - /* Indent the border a little bit if we have exterior focus - (this is what GTK does to draw native entries) */ - x += focus_width; - y += focus_width; - width -= 2 * focus_width; - height -= 2 * focus_width; - } - } - - gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, - cliprect, widget, "entry", x, y, width, height); - - if (state->focused && !state->disabled) { - if (!interior_focus) { - gtk_paint_focus(style, drawable, GTK_STATE_NORMAL, cliprect, - widget, "entry", - rect->x, rect->y, rect->width, rect->height); - } - - /* Now unset the focus flag. We don't want other entries to look - * like they're focused too! */ - GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS); - } - - return MOZ_GTK_SUCCESS; -} - -static gint -moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect, - GdkRectangle* cliprect, GtkWidgetState* state, - gboolean ishtml, GtkTextDirection direction) -{ - GdkRectangle arrow_rect, real_arrow_rect; - gint /* arrow_size, */ separator_width; - gboolean wide_separators; - GtkStateType state_type = ConvertGtkState(state); - GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT; - GtkStyle* style; - GtkRequisition arrow_req; - - ensure_combo_box_widgets(); - - /* Also sets the direction on gParts->comboBoxButtonWidget, which is then - * inherited by the separator and arrow */ - moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL, - gParts->comboBoxButtonWidget, direction); - - calculate_button_inner_rect(gParts->comboBoxButtonWidget, - rect, &arrow_rect, direction, ishtml); - /* Now arrow_rect contains the inner rect ; we want to correct the width - * to what the arrow needs (see gtk_combo_box_size_allocate) */ - gtk_widget_size_request(gParts->comboBoxArrowWidget, &arrow_req); - if (direction == GTK_TEXT_DIR_LTR) - arrow_rect.x += arrow_rect.width - arrow_req.width; - arrow_rect.width = arrow_req.width; - - calculate_arrow_rect(gParts->comboBoxArrowWidget, - &arrow_rect, &real_arrow_rect, direction); - - style = gtk_widget_get_style(gParts->comboBoxArrowWidget); - TSOffsetStyleGCs(style, rect->x, rect->y); - - gtk_widget_size_allocate(gParts->comboBoxWidget, rect); - - gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect, - gParts->comboBoxArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE, - real_arrow_rect.x, real_arrow_rect.y, - real_arrow_rect.width, real_arrow_rect.height); - - - /* If there is no separator in the theme, there's nothing left to do. */ - if (!gParts->comboBoxSeparatorWidget) - return MOZ_GTK_SUCCESS; - - style = gtk_widget_get_style(gParts->comboBoxSeparatorWidget); - TSOffsetStyleGCs(style, rect->x, rect->y); - - gtk_widget_style_get(gParts->comboBoxSeparatorWidget, - "wide-separators", &wide_separators, - "separator-width", &separator_width, - NULL); - - if (wide_separators) { - if (direction == GTK_TEXT_DIR_LTR) - arrow_rect.x -= separator_width; - else - arrow_rect.x += arrow_rect.width; - - gtk_paint_box(style, drawable, - GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT, - cliprect, gParts->comboBoxSeparatorWidget, "vseparator", - arrow_rect.x, arrow_rect.y, - separator_width, arrow_rect.height); - } else { - if (direction == GTK_TEXT_DIR_LTR) - arrow_rect.x -= XTHICKNESS(style); - else - arrow_rect.x += arrow_rect.width; - - gtk_paint_vline(style, drawable, GTK_STATE_NORMAL, cliprect, - gParts->comboBoxSeparatorWidget, "vseparator", - arrow_rect.y, arrow_rect.y + arrow_rect.height, - arrow_rect.x); - } - - return MOZ_GTK_SUCCESS; -} - -static gint -moz_gtk_progressbar_paint(GdkDrawable* drawable, GdkRectangle* rect, - GdkRectangle* cliprect, GtkTextDirection direction) -{ - GtkStyle* style; - - ensure_progress_widget(); - gtk_widget_set_direction(gParts->progresWidget, direction); - - style = gtk_widget_get_style(gParts->progresWidget); - - TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, - cliprect, gParts->progresWidget, "trough", rect->x, rect->y, - rect->width, rect->height); - - return MOZ_GTK_SUCCESS; -} - -static gint -moz_gtk_progress_chunk_paint(GdkDrawable* drawable, GdkRectangle* rect, - GdkRectangle* cliprect, GtkTextDirection direction) -{ - GtkStyle* style; - - ensure_progress_widget(); - gtk_widget_set_direction(gParts->progresWidget, direction); - - style = gtk_widget_get_style(gParts->progresWidget); - - TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - cliprect, gParts->progresWidget, "bar", rect->x, rect->y, - rect->width, rect->height); - - return MOZ_GTK_SUCCESS; -} - gint moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, gint* right, gint* bottom, GtkTextDirection direction, @@ -1135,99 +446,12 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, GtkStyle *style; switch (widget) { - case MOZ_GTK_BUTTON: - { - GtkBorder inner_border; - gboolean interior_focus; - gint focus_width, focus_pad; - GtkStyle *style; - - ensure_button_widget(); - *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gParts->buttonWidget)); - - /* Don't add this padding in HTML, otherwise the buttons will - become too big and stuff the layout. */ - if (!inhtml) { - moz_gtk_widget_get_focus(gParts->buttonWidget, &interior_focus, &focus_width, &focus_pad); - moz_gtk_button_get_inner_border(gParts->buttonWidget, &inner_border); - *left += focus_width + focus_pad + inner_border.left; - *right += focus_width + focus_pad + inner_border.right; - *top += focus_width + focus_pad + inner_border.top; - *bottom += focus_width + focus_pad + inner_border.bottom; - } - - style = gtk_widget_get_style(gParts->buttonWidget); - *left += style->xthickness; - *right += style->xthickness; - *top += style->ythickness; - *bottom += style->ythickness; - return MOZ_GTK_SUCCESS; - } - case MOZ_GTK_ENTRY: - ensure_entry_widget(); - w = gParts->entryWidget; - break; - case MOZ_GTK_DROPDOWN: - { - /* We need to account for the arrow on the dropdown, so text - * doesn't come too close to the arrow, or in some cases spill - * into the arrow. */ - gboolean ignored_interior_focus, wide_separators; - gint focus_width, focus_pad, separator_width; - GtkRequisition arrow_req; - GtkStyle* style; - - ensure_combo_box_widgets(); - - *left = gtk_container_get_border_width(GTK_CONTAINER(gParts->comboBoxButtonWidget)); - - if (!inhtml) { - moz_gtk_widget_get_focus(gParts->comboBoxButtonWidget, - &ignored_interior_focus, - &focus_width, &focus_pad); - *left += focus_width + focus_pad; - } - - style = gtk_widget_get_style(gParts->comboBoxButtonWidget); - *top = *left + style->ythickness; - *left += style->xthickness; - - *right = *left; *bottom = *top; - - /* If there is no separator, don't try to count its width. */ - separator_width = 0; - if (gParts->comboBoxSeparatorWidget) { - gtk_widget_style_get(gParts->comboBoxSeparatorWidget, - "wide-separators", &wide_separators, - "separator-width", &separator_width, - NULL); - - if (!wide_separators) - separator_width = - XTHICKNESS(style); - } - - gtk_widget_size_request(gParts->comboBoxArrowWidget, &arrow_req); - if (direction == GTK_TEXT_DIR_RTL) - *left += separator_width + arrow_req.width; - else - *right += separator_width + arrow_req.width; - - return MOZ_GTK_SUCCESS; - } - case MOZ_GTK_PROGRESSBAR: - ensure_progress_widget(); - w = gParts->progresWidget; - break; /* These widgets have no borders, since they are not containers. */ - case MOZ_GTK_CHECKBUTTON: - case MOZ_GTK_RADIOBUTTON: case MOZ_GTK_SCROLLBAR_BUTTON: case MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL: case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL: case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL: case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL: - case MOZ_GTK_PROGRESS_CHUNK: *left = *top = *right = *bottom = 0; return MOZ_GTK_SUCCESS; default: @@ -1269,26 +493,6 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, GtkTextDirection direction) { switch (widget) { - case MOZ_GTK_BUTTON: - if (state->depressed) { - ensure_toggle_button_widget(); - return moz_gtk_button_paint(drawable, rect, cliprect, state, - (GtkReliefStyle) flags, - gParts->toggleButtonWidget, direction); - } - ensure_button_widget(); - return moz_gtk_button_paint(drawable, rect, cliprect, state, - (GtkReliefStyle) flags, gParts->buttonWidget, - direction); - break; - case MOZ_GTK_CHECKBUTTON: - case MOZ_GTK_RADIOBUTTON: - return moz_gtk_toggle_paint(drawable, rect, cliprect, state, - !!(flags & MOZ_GTK_WIDGET_CHECKED), - !!(flags & MOZ_GTK_WIDGET_INCONSISTENT), - (widget == MOZ_GTK_RADIOBUTTON), - direction); - break; case MOZ_GTK_SCROLLBAR_BUTTON: return moz_gtk_scrollbar_button_paint(drawable, rect, cliprect, state, (GtkScrollbarButtonFlags) flags, @@ -1307,22 +511,6 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, case MOZ_GTK_SCROLLED_WINDOW: return moz_gtk_scrolled_window_paint(drawable, rect, cliprect, state); break; - case MOZ_GTK_ENTRY: - ensure_entry_widget(); - return moz_gtk_entry_paint(drawable, rect, cliprect, state, - gParts->entryWidget, direction); - break; - case MOZ_GTK_DROPDOWN: - return moz_gtk_combo_box_paint(drawable, rect, cliprect, state, - (gboolean) flags, direction); - break; - case MOZ_GTK_PROGRESSBAR: - return moz_gtk_progressbar_paint(drawable, rect, cliprect, direction); - break; - case MOZ_GTK_PROGRESS_CHUNK: - return moz_gtk_progress_chunk_paint(drawable, rect, cliprect, - direction); - break; default: g_warning("Unknown widget type: %d", widget); } @@ -1361,12 +549,4 @@ void moz_gtk_destroy_theme_parts_widgets(GtkThemeParts* parts) } } -GtkWidget* moz_gtk_get_progress_widget() -{ - if (!is_initialized) - return NULL; - ensure_progress_widget(); - return gParts->progresWidget; -} - #endif // GTK_API_VERSION_2 diff --git a/Source/WebCore/platform/gtk/gtkdrawing.h b/Source/WebCore/platform/gtk/gtkdrawing.h index 412a1f7..cdb343c 100644 --- a/Source/WebCore/platform/gtk/gtkdrawing.h +++ b/Source/WebCore/platform/gtk/gtkdrawing.h @@ -48,6 +48,8 @@ #ifndef _GTK_DRAWING_H_ #define _GTK_DRAWING_H_ +#undef GTK_DISABLE_DEPRECATED + #include <gtk/gtk.h> #ifdef __cplusplus @@ -84,23 +86,8 @@ typedef struct _GtkThemeParts { GdkColormap* colormap; GtkWidget* protoWindow; GtkWidget* protoLayout; - GtkWidget* buttonWidget; - GtkWidget* toggleButtonWidget; - GtkWidget* buttonArrowWidget; - GtkWidget* checkboxWidget; - GtkWidget* radiobuttonWidget; GtkWidget* horizScrollbarWidget; GtkWidget* vertScrollbarWidget; - GtkWidget* entryWidget; - GtkWidget* comboBoxWidget; - GtkWidget* comboBoxButtonWidget; - GtkWidget* comboBoxArrowWidget; - GtkWidget* comboBoxSeparatorWidget; - GtkWidget* comboBoxEntryWidget; - GtkWidget* comboBoxEntryTextareaWidget; - GtkWidget* comboBoxEntryButtonWidget; - GtkWidget* comboBoxEntryArrowWidget; - GtkWidget* progresWidget; GtkWidget* scrolledWindowWidget; } GtkThemeParts; @@ -118,18 +105,10 @@ typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint); #define MOZ_GTK_UNKNOWN_WIDGET -1 #define MOZ_GTK_UNSAFE_THEME -2 -/*** checkbox/radio flags ***/ -#define MOZ_GTK_WIDGET_CHECKED 1 -#define MOZ_GTK_WIDGET_INCONSISTENT (1 << 1) - /*** widget type constants ***/ typedef enum { /* Paints a GtkButton. flags is a GtkReliefStyle. */ MOZ_GTK_BUTTON, - /* Paints a GtkCheckButton. flags is a boolean, 1=checked, 0=not checked. */ - MOZ_GTK_CHECKBUTTON, - /* Paints a GtkRadioButton. flags is a boolean, 1=checked, 0=not checked. */ - MOZ_GTK_RADIOBUTTON, /** * Paints the button of a GtkScrollbar. flags is a GtkArrowType giving * the arrow direction. @@ -143,13 +122,6 @@ typedef enum { MOZ_GTK_SCROLLBAR_THUMB_VERTICAL, /* Paints the background of a scrolled window */ MOZ_GTK_SCROLLED_WINDOW, - MOZ_GTK_ENTRY, - /* Paints a GtkOptionMenu. */ - MOZ_GTK_DROPDOWN, - /* Paints a GtkProgressBar. */ - MOZ_GTK_PROGRESSBAR, - /* Paints a progress chunk of a GtkProgressBar. */ - MOZ_GTK_PROGRESS_CHUNK } GtkThemeWidgetType; /*** General library functions ***/ @@ -223,42 +195,6 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, gint moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, gint* right, gint* bottom, GtkTextDirection direction, gboolean inhtml); - -/** - * Get the desired size of a GtkCheckButton - * indicator_size: [OUT] the indicator size - * indicator_spacing: [OUT] the spacing between the indicator and its - * container - * - * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise - */ -gint -moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing); - -/** - * Get the desired size of a GtkRadioButton - * indicator_size: [OUT] the indicator size - * indicator_spacing: [OUT] the spacing between the indicator and its - * container - * - * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise - */ -gint -moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing); - -/** Get the focus metrics for a treeheadercell, button, checkbox, or radio button. - * widget: [IN] the widget to get the focus metrics for - * interior_focus: [OUT] whether the focus is drawn around the - * label (TRUE) or around the whole container (FALSE) - * focus_width: [OUT] the width of the focus line - * focus_pad: [OUT] the padding between the focus line and children - * - * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise - */ -gint -moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus, - gint* focus_width, gint* focus_pad); - /** * Get the desired metrics for a GtkScrollbar * metrics: [IN] struct which will contain the metrics @@ -274,12 +210,6 @@ moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics* metrics); */ GtkWidget* moz_gtk_get_scrollbar_widget(void); -/** - * Retrieve an actual GTK progress bar widget for style analysis. It will not - * be modified. - */ -GtkWidget* moz_gtk_get_progress_widget(void); - #ifdef __cplusplus } #endif /* __cplusplus */ |