WebCore:
2007-08-10 Holger Hans Peter Freyther <zecke@selfish.org>
Reviewed by Adam.
Use the ScrollView/Widget design of the Windows port to only use one
native window for the whole page. This will make it possible to implement
FrameLoaderClientGdk::createFrame.
In contrast to the windows port the ScrollBars are GtkWidgets. To paint them
at the right position we need to position them correctly. To not scroll the
ScrollBar's belonging to the ScrollView a ScrollViewScrollbar is introduced with
a different geometryChanged method.
To allow the Gtk+ way of scrolling the ScrollView allows to get GtkAdjustments
set. In this case no ScrollViewScrollbar will be created.
* platform/ScrollView.h:
* platform/Widget.h:
* platform/gdk/PlatformScreenGdk.cpp:
(WebCore::screenDepth):
* platform/gdk/PlatformScrollBar.h:
* platform/gdk/PlatformScrollBarGdk.cpp:
(PlatformScrollbar::PlatformScrollbar):
(PlatformScrollbar::~PlatformScrollbar):
(PlatformScrollbar::setRect):
(PlatformScrollbar::geometryChanged):
* platform/gdk/ScrollViewGdk.cpp:
(WebCore::ScrollView::ScrollViewPrivate::ScrollViewPrivate):
(WebCore::ScrollView::ScrollViewPrivate::~ScrollViewPrivate):
(WebCore::ScrollViewScrollbar::ScrollViewScrollbar):
(WebCore::ScrollViewScrollbar::geometryChanged):
(WebCore::ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar):
(WebCore::ScrollView::ScrollViewPrivate::setHasVerticalScrollbar):
(WebCore::ScrollView::ScrollViewPrivate::scrollBackingStore):
(WebCore::ScrollView::ScrollViewPrivate::adjustmentChanged):
(WebCore::ScrollView::ScrollViewPrivate::valueChanged):
(WebCore::ScrollView::ScrollViewPrivate::windowClipRect):
(WebCore::ScrollView::setGtkAdjustments):
(WebCore::ScrollView::updateContents):
(WebCore::ScrollView::update):
(WebCore::ScrollView::visibleWidth):
(WebCore::ScrollView::resizeContents):
(WebCore::ScrollView::contentsX):
(WebCore::ScrollView::scrollOffset):
(WebCore::ScrollView::maximumScroll):
(WebCore::ScrollView::scrollBy):
(WebCore::ScrollView::suppressScrollbars):
(WebCore::ScrollView::setHScrollbarMode):
(WebCore::ScrollView::setVScrollbarMode):
(WebCore::ScrollView::setScrollbarsMode):
(WebCore::ScrollView::setFrameGeometry):
(WebCore::ScrollView::addChild):
(WebCore::ScrollView::removeChild):
(WebCore::ScrollView::scrollRectIntoViewRecursively):
(WebCore::ScrollView::wheelEvent):
(WebCore::ScrollView::updateScrollbars):
(WebCore::ScrollView::windowToContents):
(WebCore::ScrollView::contentsToWindow):
(WebCore::ScrollView::scrollbarUnderMouse):
(WebCore::ScrollView::convertChildToSelf):
(WebCore::ScrollView::convertSelfToChild):
(WebCore::ScrollView::paint):
(WebCore::ScrollView::geometryChanged):
(WebCore::ScrollView::scroll):
(WebCore::ScrollView::addToDirtyRegion):
(WebCore::ScrollView::scrollBackingStore):
(WebCore::ScrollView::updateBackingStore):
* platform/gdk/WidgetGdk.cpp:
(WebCore::WidgetPrivate::gdkDrawable):
(WebCore::Widget::Widget):
(WebCore::Widget::setContainingWindow):
(WebCore::Widget::containingWindow):
(WebCore::Widget::frameGeometry):
(WebCore::Widget::setFrameGeometry):
(WebCore::Widget::setParent):
(WebCore::Widget::parent):
(WebCore::Widget::setCursor):
(WebCore::Widget::show):
(WebCore::Widget::hide):
(WebCore::Widget::removeFromParent):
(WebCore::Widget::paint):
(WebCore::Widget::invalidate):
(WebCore::Widget::invalidateRect):
(WebCore::Widget::convertToContainingWindow):
(WebCore::Widget::convertFromContainingWindow):
(WebCore::Widget::convertChildToSelf):
(WebCore::Widget::convertSelfToChild):
(WebCore::Widget::suppressInvalidation):
(WebCore::Widget::setSuppressInvalidation):
WebKit/gtk:
2007-08-10 Holger Hans Peter Freyther <zecke@selfish.org>
Reviewed by Adam.
Follow the changes of ScrollView in WebCore and call setContainingWindow, set the
GtkAdjustment of the GtkLayout and reimplement the set_scroll_adjustments method and pass
the GtkAdjustments to ScrollView.
This makes having one GdkWindow for the complete FrameTree possible.
* gtk/Api/webkitgtkframe.cpp:
* gtk/Api/webkitgtkpage.cpp:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@24963 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 1a688bc..d632703 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,94 @@
+2007-08-10 Holger Hans Peter Freyther <zecke@selfish.org>
+
+ Reviewed by Adam.
+
+ Use the ScrollView/Widget design of the Windows port to only use one
+ native window for the whole page. This will make it possible to implement
+ FrameLoaderClientGdk::createFrame.
+
+ In contrast to the windows port the ScrollBars are GtkWidgets. To paint them
+ at the right position we need to position them correctly. To not scroll the
+ ScrollBar's belonging to the ScrollView a ScrollViewScrollbar is introduced with
+ a different geometryChanged method.
+
+ To allow the Gtk+ way of scrolling the ScrollView allows to get GtkAdjustments
+ set. In this case no ScrollViewScrollbar will be created.
+
+
+ * platform/ScrollView.h:
+ * platform/Widget.h:
+ * platform/gdk/PlatformScreenGdk.cpp:
+ (WebCore::screenDepth):
+ * platform/gdk/PlatformScrollBar.h:
+ * platform/gdk/PlatformScrollBarGdk.cpp:
+ (PlatformScrollbar::PlatformScrollbar):
+ (PlatformScrollbar::~PlatformScrollbar):
+ (PlatformScrollbar::setRect):
+ (PlatformScrollbar::geometryChanged):
+ * platform/gdk/ScrollViewGdk.cpp:
+ (WebCore::ScrollView::ScrollViewPrivate::ScrollViewPrivate):
+ (WebCore::ScrollView::ScrollViewPrivate::~ScrollViewPrivate):
+ (WebCore::ScrollViewScrollbar::ScrollViewScrollbar):
+ (WebCore::ScrollViewScrollbar::geometryChanged):
+ (WebCore::ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar):
+ (WebCore::ScrollView::ScrollViewPrivate::setHasVerticalScrollbar):
+ (WebCore::ScrollView::ScrollViewPrivate::scrollBackingStore):
+ (WebCore::ScrollView::ScrollViewPrivate::adjustmentChanged):
+ (WebCore::ScrollView::ScrollViewPrivate::valueChanged):
+ (WebCore::ScrollView::ScrollViewPrivate::windowClipRect):
+ (WebCore::ScrollView::setGtkAdjustments):
+ (WebCore::ScrollView::updateContents):
+ (WebCore::ScrollView::update):
+ (WebCore::ScrollView::visibleWidth):
+ (WebCore::ScrollView::resizeContents):
+ (WebCore::ScrollView::contentsX):
+ (WebCore::ScrollView::scrollOffset):
+ (WebCore::ScrollView::maximumScroll):
+ (WebCore::ScrollView::scrollBy):
+ (WebCore::ScrollView::suppressScrollbars):
+ (WebCore::ScrollView::setHScrollbarMode):
+ (WebCore::ScrollView::setVScrollbarMode):
+ (WebCore::ScrollView::setScrollbarsMode):
+ (WebCore::ScrollView::setFrameGeometry):
+ (WebCore::ScrollView::addChild):
+ (WebCore::ScrollView::removeChild):
+ (WebCore::ScrollView::scrollRectIntoViewRecursively):
+ (WebCore::ScrollView::wheelEvent):
+ (WebCore::ScrollView::updateScrollbars):
+ (WebCore::ScrollView::windowToContents):
+ (WebCore::ScrollView::contentsToWindow):
+ (WebCore::ScrollView::scrollbarUnderMouse):
+ (WebCore::ScrollView::convertChildToSelf):
+ (WebCore::ScrollView::convertSelfToChild):
+ (WebCore::ScrollView::paint):
+ (WebCore::ScrollView::geometryChanged):
+ (WebCore::ScrollView::scroll):
+ (WebCore::ScrollView::addToDirtyRegion):
+ (WebCore::ScrollView::scrollBackingStore):
+ (WebCore::ScrollView::updateBackingStore):
+ * platform/gdk/WidgetGdk.cpp:
+ (WebCore::WidgetPrivate::gdkDrawable):
+ (WebCore::Widget::Widget):
+ (WebCore::Widget::setContainingWindow):
+ (WebCore::Widget::containingWindow):
+ (WebCore::Widget::frameGeometry):
+ (WebCore::Widget::setFrameGeometry):
+ (WebCore::Widget::setParent):
+ (WebCore::Widget::parent):
+ (WebCore::Widget::setCursor):
+ (WebCore::Widget::show):
+ (WebCore::Widget::hide):
+ (WebCore::Widget::removeFromParent):
+ (WebCore::Widget::paint):
+ (WebCore::Widget::invalidate):
+ (WebCore::Widget::invalidateRect):
+ (WebCore::Widget::convertToContainingWindow):
+ (WebCore::Widget::convertFromContainingWindow):
+ (WebCore::Widget::convertChildToSelf):
+ (WebCore::Widget::convertSelfToChild):
+ (WebCore::Widget::suppressInvalidation):
+ (WebCore::Widget::setSuppressInvalidation):
+
2007-08-09 Adele Peterson <adele@apple.com>
Fix by Brady, reviewed by me.
diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h
index 1c5cdc5..8c09e9c 100644
--- a/WebCore/platform/ScrollView.h
+++ b/WebCore/platform/ScrollView.h
@@ -32,7 +32,7 @@
#include <wtf/HashSet.h>
#if PLATFORM(GDK)
-typedef struct _GtkLayout GtkLayout;
+typedef struct _GtkAdjustment GtkAdjustment;
#endif
#if PLATFORM(WIN)
@@ -152,12 +152,22 @@
ScrollView();
~ScrollView();
- virtual void setGtkWidget(GtkLayout* layout);
+ virtual void setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj);
+ virtual IntPoint convertChildToSelf(const Widget*, const IntPoint&) const;
+ virtual IntPoint convertSelfToChild(const Widget*, const IntPoint&) const;
+ virtual void geometryChanged() const;
+
+ virtual void paint(GraphicsContext*, const IntRect&);
virtual void setFrameGeometry(const IntRect&);
- virtual void updateGeometry(int width, int height);
+
+ void addToDirtyRegion(const IntRect&);
+ void scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect);
+ void updateBackingStore();
private:
- void updateView(const IntRect&, bool now = false);
- void updateScrollbars();
+ IntSize maximumScroll() const;
+ void updateScrollbars(const IntSize& desiredOffset);
+ HashSet<Widget*>* children();
+
class ScrollViewPrivate;
ScrollViewPrivate* m_data;
#endif
diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h
index 1371fe9..9aa2845 100644
--- a/WebCore/platform/Widget.h
+++ b/WebCore/platform/Widget.h
@@ -43,6 +43,7 @@
#if PLATFORM(GDK)
typedef struct _GdkDrawable GdkDrawable;
typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkLayout GtkLayout;
#endif
#if PLATFORM(QT)
@@ -136,10 +137,27 @@
#endif
#if PLATFORM(GDK)
- Widget(GtkWidget*);
- virtual void setGtkWidget(GtkWidget*);
- GdkDrawable* gdkDrawable() const;
+ virtual void setParent(ScrollView*);
+ ScrollView* parent() const;
+
+ void setContainingWindow(GtkLayout*);
+ GtkLayout* containingWindow() const;
+
+ virtual void geometryChanged() const;
+
+ IntRect convertToContainingWindow(const IntRect&) const;
+ IntPoint convertToContainingWindow(const IntPoint&) const;
+ IntPoint convertFromContainingWindow(const IntPoint&) const;
+
+ virtual IntPoint convertChildToSelf(const Widget*, const IntPoint&) const;
+ virtual IntPoint convertSelfToChild(const Widget*, const IntPoint&) const;
+
+ bool suppressInvalidation() const;
+ void setSuppressInvalidation(bool);
+
GtkWidget* gtkWidget() const;
+protected:
+ void setGtkWidget(GtkWidget*);
#endif
#if PLATFORM(QT)
diff --git a/WebCore/platform/gdk/PlatformScreenGdk.cpp b/WebCore/platform/gdk/PlatformScreenGdk.cpp
index f378215..ccb6766 100644
--- a/WebCore/platform/gdk/PlatformScreenGdk.cpp
+++ b/WebCore/platform/gdk/PlatformScreenGdk.cpp
@@ -30,7 +30,8 @@
#include "NotImplemented.h"
#include "Widget.h"
-#include <gdk/gdk.h>
+
+#include <gtk/gtk.h>
#include <stdio.h>
#include <wtf/Assertions.h>
@@ -38,10 +39,10 @@
int screenDepth(Widget* widget)
{
- ASSERT(widget->gdkDrawable());
+ ASSERT(widget->containingWindow() && widget->containingWindow()->bin_window);
gint dummy, depth;
- gdk_window_get_geometry(widget->gdkDrawable(), &dummy, &dummy, &dummy, &dummy, &depth);
+ gdk_window_get_geometry(widget->containingWindow()->bin_window, &dummy, &dummy, &dummy, &dummy, &depth);
return depth;
}
diff --git a/WebCore/platform/gdk/PlatformScrollBar.h b/WebCore/platform/gdk/PlatformScrollBar.h
index d68e26c..bad421f 100644
--- a/WebCore/platform/gdk/PlatformScrollBar.h
+++ b/WebCore/platform/gdk/PlatformScrollBar.h
@@ -53,6 +53,7 @@
protected:
virtual void updateThumbPosition();
virtual void updateThumbProportion();
+ virtual void geometryChanged();
private:
static void gtkValueChanged(GtkAdjustment*, PlatformScrollbar*);
diff --git a/WebCore/platform/gdk/PlatformScrollBarGdk.cpp b/WebCore/platform/gdk/PlatformScrollBarGdk.cpp
index a0032de..09f871f 100644
--- a/WebCore/platform/gdk/PlatformScrollBarGdk.cpp
+++ b/WebCore/platform/gdk/PlatformScrollBarGdk.cpp
@@ -29,6 +29,7 @@
#include "PlatformScrollBar.h"
#include "IntRect.h"
#include "GraphicsContext.h"
+#include "FrameView.h"
#include "NotImplemented.h"
#include <gtk/gtk.h>
@@ -47,6 +48,7 @@
GTK_SCROLLBAR(::gtk_hscrollbar_new(m_adjustment)) :
GTK_SCROLLBAR(::gtk_vscrollbar_new(m_adjustment));
gtk_widget_show(GTK_WIDGET(scrollBar));
+ g_object_ref(G_OBJECT(scrollBar));
g_signal_connect(G_OBJECT(scrollBar), "value-changed", G_CALLBACK(PlatformScrollbar::gtkValueChanged), this);
setGtkWidget(GTK_WIDGET(scrollBar));
@@ -57,9 +59,6 @@
*/
resize(PlatformScrollbar::horizontalScrollbarHeight(),
PlatformScrollbar::verticalScrollbarWidth());
-
- g_object_ref(G_OBJECT(scrollBar));
- gtk_object_sink(GTK_OBJECT(scrollBar));
}
PlatformScrollbar::~PlatformScrollbar()
@@ -68,7 +67,6 @@
* the Widget does not take over ownership.
*/
g_signal_handlers_disconnect_by_func(G_OBJECT(gtkWidget()), (gpointer)PlatformScrollbar::gtkValueChanged, this);
- gtk_widget_destroy(gtkWidget());
g_object_unref(G_OBJECT(gtkWidget()));
}
@@ -112,6 +110,20 @@
void PlatformScrollbar::setRect(const IntRect& rect)
{
setFrameGeometry(rect);
+ geometryChanged();
+}
+
+void PlatformScrollbar::geometryChanged()
+{
+ if (!parent())
+ return;
+
+ ASSERT(parent()->isFrameView());
+
+ FrameView* frameView = static_cast<FrameView*>(parent());
+ IntRect windowRect = IntRect(frameView->contentsToWindow(frameGeometry().location()), frameGeometry().size());
+ GtkAllocation allocation = { windowRect.x(), windowRect.y(), windowRect.width(), windowRect.height() };
+ gtk_widget_size_allocate(gtkWidget(), &allocation);
}
void PlatformScrollbar::gtkValueChanged(GtkAdjustment*, PlatformScrollbar* that)
diff --git a/WebCore/platform/gdk/ScrollViewGdk.cpp b/WebCore/platform/gdk/ScrollViewGdk.cpp
index 3af89cc..6a9d2cb 100644
--- a/WebCore/platform/gdk/ScrollViewGdk.cpp
+++ b/WebCore/platform/gdk/ScrollViewGdk.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007 Holger Hans Peter Freyther
*
@@ -36,6 +36,10 @@
#include "GraphicsContext.h"
#include "IntRect.h"
#include "NotImplemented.h"
+#include "PlatformMouseEvent.h"
+#include "PlatformWheelEvent.h"
+#include "PlatformScrollBar.h"
+#include "Page.h"
#include "RenderLayer.h"
#include <gdk/gdk.h>
@@ -43,32 +47,200 @@
using namespace std;
+static const int MagicGtkScrollConstant = 13;
+
namespace WebCore {
-class ScrollView::ScrollViewPrivate
-{
+class ScrollViewScrollbar : public PlatformScrollbar {
public:
- ScrollViewPrivate()
- : hasStaticBackground(false)
- , suppressScrollbars(false)
- , vScrollbarMode(ScrollbarAuto)
- , hScrollbarMode(ScrollbarAuto)
- , layout(0)
- , scrollBarsNeedUpdate(false)
- { }
+ ScrollViewScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
- bool hasStaticBackground;
- bool suppressScrollbars;
- ScrollbarMode vScrollbarMode;
- ScrollbarMode hScrollbarMode;
- GtkLayout *layout;
- IntSize contentsSize;
- IntSize viewPortSize;
- bool scrollBarsNeedUpdate;
+protected:
+ void geometryChanged();
};
+class ScrollView::ScrollViewPrivate : public ScrollbarClient
+{
+public:
+ ScrollViewPrivate(ScrollView* _view)
+ : view(_view)
+ , hasStaticBackground(false)
+ , scrollbarsSuppressed(false)
+ , vScrollbarMode(ScrollbarAuto)
+ , hScrollbarMode(ScrollbarAuto)
+ , inUpdateScrollbars(false)
+ , horizontalAdjustment(0)
+ , verticalAdjustment(0)
+ {}
+
+ ~ScrollViewPrivate()
+ {
+ setHasHorizontalScrollbar(false);
+ setHasVerticalScrollbar(false);
+
+ if (horizontalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(horizontalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, this);
+ g_object_unref(horizontalAdjustment);
+ }
+
+ if (verticalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(verticalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, this);
+ g_object_unref(verticalAdjustment);
+ }
+ }
+
+ void scrollBackingStore(const IntSize& scrollDelta);
+
+ void setHasHorizontalScrollbar(bool hasBar);
+ void setHasVerticalScrollbar(bool hasBar);
+
+ virtual void valueChanged(Scrollbar*);
+ virtual IntRect windowClipRect() const;
+
+ static void adjustmentChanged(GtkAdjustment*, gpointer);
+
+ ScrollView* view;
+ bool hasStaticBackground;
+ bool scrollbarsSuppressed;
+ ScrollbarMode vScrollbarMode;
+ ScrollbarMode hScrollbarMode;
+ RefPtr<ScrollViewScrollbar> vBar;
+ RefPtr<ScrollViewScrollbar> hBar;
+ IntSize scrollOffset;
+ IntSize contentsSize;
+ IntSize viewPortSize;
+ bool inUpdateScrollbars;
+ HashSet<Widget*> children;
+ GtkAdjustment* horizontalAdjustment;
+ GtkAdjustment* verticalAdjustment;
+};
+
+ScrollViewScrollbar::ScrollViewScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size)
+ : PlatformScrollbar(client, orientation, size)
+{
+}
+
+void ScrollViewScrollbar::geometryChanged()
+{
+ if (!parent())
+ return;
+
+ ASSERT(parent()->isFrameView());
+
+ FrameView* frameView = static_cast<FrameView*>(parent());
+ IntRect windowRect = IntRect(frameView->convertToContainingWindow(frameGeometry().location()), frameGeometry().size());
+ GtkAllocation allocation = { windowRect.x(), windowRect.y(), windowRect.width(), windowRect.height() };
+ gtk_widget_size_allocate(gtkWidget(), &allocation);
+}
+
+void ScrollView::ScrollViewPrivate::setHasHorizontalScrollbar(bool hasBar)
+{
+ if (Scrollbar::hasPlatformScrollbars()) {
+ if (hasBar && !hBar && !horizontalAdjustment) {
+ hBar = new ScrollViewScrollbar(this, HorizontalScrollbar, RegularScrollbar);
+ view->addChild(hBar.get());
+ } else if (!hasBar && hBar) {
+ view->removeChild(hBar.get());
+ hBar = 0;
+ }
+ }
+}
+
+void ScrollView::ScrollViewPrivate::setHasVerticalScrollbar(bool hasBar)
+{
+ if (Scrollbar::hasPlatformScrollbars()) {
+ if (hasBar && !vBar && !verticalAdjustment) {
+ vBar = new ScrollViewScrollbar(this, VerticalScrollbar, RegularScrollbar);
+ view->addChild(vBar.get());
+ } else if (!hasBar && vBar) {
+ view->removeChild(vBar.get());
+ vBar = 0;
+ }
+ }
+}
+
+
+void ScrollView::ScrollViewPrivate::scrollBackingStore(const IntSize& scrollDelta)
+{
+ // Since scrolling is double buffered, we will be blitting the scroll view's intersection
+ // with the clip rect every time to keep it smooth.
+ IntRect clipRect = view->windowClipRect();
+ IntRect scrollViewRect = view->convertToContainingWindow(IntRect(0, 0, view->visibleWidth(), view->visibleHeight()));
+
+ IntRect updateRect = clipRect;
+ updateRect.intersect(scrollViewRect);
+
+ //FIXME update here?
+
+ if (!hasStaticBackground) // The main frame can just blit the WebView window
+ // FIXME: Find a way to blit subframes without blitting overlapping content
+ view->scrollBackingStore(-scrollDelta.width(), -scrollDelta.height(), scrollViewRect, clipRect);
+ else {
+ // We need to go ahead and repaint the entire backing store. Do it now before moving the
+ // plugins.
+ view->addToDirtyRegion(updateRect);
+ view->updateBackingStore();
+ }
+
+ view->geometryChanged();
+
+ // Now update the window (which should do nothing but a blit of the backing store's updateRect and so should
+ // be very fast).
+ view->update();
+}
+
+void ScrollView::ScrollViewPrivate::adjustmentChanged(GtkAdjustment* adjustment, gpointer _that)
+{
+ ScrollViewPrivate* that = reinterpret_cast<ScrollViewPrivate*>(_that);
+
+ // Figure out if we really moved.
+ IntSize newOffset = that->scrollOffset;
+ if (adjustment == that->horizontalAdjustment)
+ newOffset.setWidth(static_cast<int>(gtk_adjustment_get_value(adjustment)));
+ else if (adjustment == that->verticalAdjustment)
+ newOffset.setHeight(static_cast<int>(gtk_adjustment_get_value(adjustment)));
+
+ IntSize scrollDelta = newOffset - that->scrollOffset;
+ if (scrollDelta == IntSize())
+ return;
+ that->scrollOffset = newOffset;
+
+ if (that->scrollbarsSuppressed)
+ return;
+
+ that->scrollBackingStore(scrollDelta);
+ static_cast<FrameView*>(that->view)->frame()->sendScrollEvent();
+}
+
+void ScrollView::ScrollViewPrivate::valueChanged(Scrollbar* bar)
+{
+ // Figure out if we really moved.
+ IntSize newOffset = scrollOffset;
+ if (bar) {
+ if (bar == hBar)
+ newOffset.setWidth(bar->value());
+ else if (bar == vBar)
+ newOffset.setHeight(bar->value());
+ }
+ IntSize scrollDelta = newOffset - scrollOffset;
+ if (scrollDelta == IntSize())
+ return;
+ scrollOffset = newOffset;
+
+ if (scrollbarsSuppressed)
+ return;
+
+ scrollBackingStore(scrollDelta);
+ static_cast<FrameView*>(view)->frame()->sendScrollEvent();
+}
+
+IntRect ScrollView::ScrollViewPrivate::windowClipRect() const
+{
+ return static_cast<const FrameView*>(view)->windowClipRect(false);
+}
+
ScrollView::ScrollView()
- : m_data(new ScrollViewPrivate)
+ : m_data(new ScrollViewPrivate(this))
{}
ScrollView::~ScrollView()
@@ -76,40 +248,84 @@
delete m_data;
}
-void ScrollView::updateView(const IntRect& updateRect, bool now)
+/*
+ * The following is assumed:
+ * (hadj && vadj) || (!hadj && !vadj)
+ */
+void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj)
{
- GdkRectangle rect = { updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height() };
- GdkDrawable* gdkdrawable = Widget::gdkDrawable();
- if (GDK_IS_WINDOW(gdkdrawable)) {
- GdkWindow* window = GDK_WINDOW(gdkdrawable);
- gdk_window_invalidate_rect(window, &rect, true);
- if (now)
- gdk_window_process_updates(window, true);
+ ASSERT(!hadj == !vadj);
+
+ if (m_data->horizontalAdjustment) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_data->horizontalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, m_data);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(m_data->verticalAdjustment), (gpointer)ScrollViewPrivate::adjustmentChanged, m_data);
+ g_object_unref(m_data->horizontalAdjustment);
+ g_object_unref(m_data->verticalAdjustment);
}
+
+ m_data->horizontalAdjustment = hadj;
+ m_data->verticalAdjustment = vadj;
+
+ if (m_data->horizontalAdjustment) {
+ g_signal_connect(m_data->horizontalAdjustment, "value-changed", G_CALLBACK(ScrollViewPrivate::adjustmentChanged), m_data);
+ g_signal_connect(m_data->verticalAdjustment, "value-changed", G_CALLBACK(ScrollViewPrivate::adjustmentChanged), m_data);
+
+ /*
+ * disable the scrollbars (if we have any) as the GtkAdjustment over
+ */
+ m_data->setHasVerticalScrollbar(false);
+ m_data->setHasHorizontalScrollbar(false);
+
+ g_object_ref(m_data->horizontalAdjustment);
+ gtk_object_sink(GTK_OBJECT(m_data->horizontalAdjustment));
+ g_object_ref(m_data->verticalAdjustment);
+ gtk_object_sink(GTK_OBJECT(m_data->verticalAdjustment));
+ }
+
+ updateScrollbars(m_data->scrollOffset);
}
void ScrollView::updateContents(const IntRect& updateRect, bool now)
{
- updateView(updateRect, now);
+ if (updateRect.isEmpty())
+ return;
+
+ IntPoint windowPoint = contentsToWindow(updateRect.location());
+ IntRect containingWindowRect = updateRect;
+ containingWindowRect.setLocation(windowPoint);
+
+ GdkRectangle rect = { containingWindowRect.x(),
+ containingWindowRect.y(),
+ containingWindowRect.width(),
+ containingWindowRect.height() };
+ GdkWindow* window = containingWindow()->bin_window;
+
+ if (window)
+ gdk_window_invalidate_rect(window, &rect, true);
+
+ // Cache the dirty spot.
+ addToDirtyRegion(containingWindowRect);
+
+ if (now && window)
+ gdk_window_process_updates(window, true);
}
void ScrollView::update()
{
- ASSERT(gtkWidget());
- gtk_widget_queue_draw(gtkWidget());
+ ASSERT(containingWindow());
- if (m_data->scrollBarsNeedUpdate)
- updateScrollbars();
+ GdkRectangle rect = { 0, 0, m_data->contentsSize.width(), m_data->contentsSize.height() };
+ gdk_window_invalidate_rect(containingWindow()->bin_window, &rect, true);
}
int ScrollView::visibleWidth() const
{
- return m_data->viewPortSize.width();
+ return width() - (m_data->vBar ? m_data->vBar->width() : 0);
}
int ScrollView::visibleHeight() const
{
- return m_data->viewPortSize.height();
+ return height() - (m_data->hBar ? m_data->hBar->height() : 0);
}
// Region of the content currently visible in the viewport in the content view's coordinate system.
@@ -138,23 +354,17 @@
return;
m_data->contentsSize = newSize;
-
- if (m_data->layout) {
- gtk_layout_set_size(m_data->layout, w, h);
- m_data->scrollBarsNeedUpdate = true;
- }
+ updateScrollbars(m_data->scrollOffset);
}
int ScrollView::contentsX() const
{
- g_return_val_if_fail(gtk_layout_get_hadjustment(m_data->layout), 0);
- return static_cast<int>(gtk_adjustment_get_value(gtk_layout_get_hadjustment(m_data->layout)));
+ return scrollOffset().width();
}
int ScrollView::contentsY() const
{
- g_return_val_if_fail(gtk_layout_get_vadjustment(m_data->layout), 0);
- return static_cast<int>(gtk_adjustment_get_value(gtk_layout_get_vadjustment(m_data->layout)));
+ return scrollOffset().height();
}
int ScrollView::contentsWidth() const
@@ -169,27 +379,26 @@
IntSize ScrollView::scrollOffset() const
{
- g_return_val_if_fail(m_data, IntSize());
- return IntSize(contentsX(), contentsY());
+ return m_data->scrollOffset;
+}
+
+IntSize ScrollView::maximumScroll() const
+{
+ IntSize delta = (m_data->contentsSize - IntSize(visibleWidth(), visibleHeight())) - scrollOffset();
+ delta.clampNegativeToZero();
+ return delta;
}
void ScrollView::scrollBy(int dx, int dy)
{
- GtkAdjustment* hadj = gtk_layout_get_hadjustment(m_data->layout);
- GtkAdjustment* vadj = gtk_layout_get_vadjustment(m_data->layout);
- g_return_if_fail(hadj);
- g_return_if_fail(vadj);
+ IntSize scrollOffset = m_data->scrollOffset;
+ IntSize newScrollOffset = scrollOffset + IntSize(dx, dy).shrunkTo(maximumScroll());
+ newScrollOffset.clampNegativeToZero();
+
+ if (newScrollOffset == scrollOffset)
+ return;
- int current_x = contentsX();
- int current_y = contentsY();
-
-
- gtk_adjustment_set_value(hadj,
- CLAMP(current_x+dx, hadj->lower,
- MAX(0.0, hadj->upper - hadj->page_size)));
- gtk_adjustment_set_value(vadj,
- CLAMP(current_y+dy, vadj->lower,
- MAX(0.0, vadj->upper - vadj->page_size)));
+ updateScrollbars(newScrollOffset);
}
ScrollbarMode ScrollView::hScrollbarMode() const
@@ -204,16 +413,16 @@
void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnSuppress)
{
- m_data->suppressScrollbars = suppressed;
+ m_data->scrollbarsSuppressed = suppressed;
if (repaintOnSuppress)
- updateScrollbars();
+ updateScrollbars(m_data->scrollOffset);
}
void ScrollView::setHScrollbarMode(ScrollbarMode newMode)
{
if (m_data->hScrollbarMode != newMode) {
m_data->hScrollbarMode = newMode;
- updateScrollbars();
+ updateScrollbars(m_data->scrollOffset);
}
}
@@ -221,14 +430,14 @@
{
if (m_data->vScrollbarMode != newMode) {
m_data->vScrollbarMode = newMode;
- updateScrollbars();
+ updateScrollbars(m_data->scrollOffset);
}
}
void ScrollView::setScrollbarsMode(ScrollbarMode newMode)
{
m_data->hScrollbarMode = m_data->vScrollbarMode = newMode;
- updateScrollbars();
+ updateScrollbars(m_data->scrollOffset);
}
void ScrollView::setStaticBackground(bool flag)
@@ -240,44 +449,50 @@
* only update the adjustments, the GtkLayout is doing the work
* for us (assuming it is in a box...).
*/
-void ScrollView::setFrameGeometry(const IntRect& r)
+void ScrollView::setFrameGeometry(const IntRect& newGeometry)
{
- Widget::setFrameGeometry(r);
- updateGeometry(r.width(), r.height());
+ ASSERT(isFrameView());
+ IntRect oldGeometry = frameGeometry();
+ Widget::setFrameGeometry(newGeometry);
+
+ if (newGeometry == oldGeometry)
+ return;
+ if (newGeometry.width() != oldGeometry.width() || newGeometry.height() != oldGeometry.height()) {
+ updateScrollbars(m_data->scrollOffset);
+ static_cast<FrameView*>(this)->setNeedsLayout();
+ }
+
+ geometryChanged();
}
-void ScrollView::updateGeometry(int width, int height)
-{
- m_data->viewPortSize = IntSize(width,height);
-}
-
-void ScrollView::setGtkWidget(GtkLayout* layout)
-{
- g_return_if_fail(GTK_LAYOUT(layout));
- m_data->layout = layout;
-
- Widget::setGtkWidget(GTK_WIDGET(layout));
-}
-
-void ScrollView::addChild(Widget* w)
+void ScrollView::addChild(Widget* child)
{
- ASSERT(w->gtkWidget());
- ASSERT(m_data->layout);
+ child->setParent(this);
+ child->setContainingWindow(containingWindow());
+ m_data->children.add(child);
- gtk_layout_put(m_data->layout, w->gtkWidget(), 0, 0);
+ if (child->gtkWidget())
+ gtk_container_add(GTK_CONTAINER(containingWindow()), child->gtkWidget());
}
-void ScrollView::removeChild(Widget* w)
+void ScrollView::removeChild(Widget* child)
{
- ASSERT(w->gtkWidget());
- ASSERT(m_data->layout);
+ child->setParent(0);
+ m_data->children.remove(child);
- gtk_container_remove(GTK_CONTAINER(m_data->layout), w->gtkWidget());
+ if (child->gtkWidget() && GTK_WIDGET(containingWindow()) == GTK_WIDGET(child->gtkWidget())->parent)
+ gtk_container_remove(GTK_CONTAINER(containingWindow()), child->gtkWidget());
}
-void ScrollView::scrollRectIntoViewRecursively(const IntRect&)
+void ScrollView::scrollRectIntoViewRecursively(const IntRect& r)
{
- notImplemented();
+ IntPoint p(max(0, r.x()), max(0, r.y()));
+ ScrollView* view = this;
+ while (view) {
+ view->setContentsPos(p.x(), p.y());
+ p.move(view->x() - view->scrollOffset().width(), view->y() - view->scrollOffset().height());
+ view = static_cast<ScrollView*>(view->parent());
+ }
}
bool ScrollView::inWindow() const
@@ -286,48 +501,311 @@
return true;
}
-void ScrollView::wheelEvent(PlatformWheelEvent&)
+void ScrollView::wheelEvent(PlatformWheelEvent& e)
{
- notImplemented();
+ // Determine how much we want to scroll. If we can move at all, we will accept the event.
+ IntSize maxScrollDelta = maximumScroll();
+ if ((e.deltaX() < 0 && maxScrollDelta.width() > 0) ||
+ (e.deltaX() > 0 && scrollOffset().width() > 0) ||
+ (e.deltaY() < 0 && maxScrollDelta.height() > 0) ||
+ (e.deltaY() > 0 && scrollOffset().height() > 0))
+ e.accept();
+
+ scrollBy(e.deltaX() * LINE_STEP, e.deltaY() * LINE_STEP);
}
-void ScrollView::updateScrollbars()
+void ScrollView::updateScrollbars(const IntSize& desiredOffset)
{
- GtkAdjustment* hadj = gtk_layout_get_hadjustment(m_data->layout);
- GtkAdjustment* vadj = gtk_layout_get_vadjustment(m_data->layout);
+ // Don't allow re-entrancy into this function.
+ if (m_data->inUpdateScrollbars)
+ return;
- g_return_if_fail(hadj);
- g_return_if_fail(vadj);
-
- hadj->page_size = visibleWidth();
- hadj->step_increment = 13;
-
- vadj->page_size = visibleHeight();
- vadj->step_increment = 13;
-
- gtk_adjustment_changed(hadj);
- gtk_adjustment_value_changed(hadj);
-
- gtk_adjustment_changed(vadj);
- gtk_adjustment_value_changed(vadj);
+ // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
+ // In the end, FrameView should just merge with ScrollView.
+ if (static_cast<const FrameView*>(this)->frame()->prohibitsScrolling())
+ return;
- m_data->scrollBarsNeedUpdate = false;
+ m_data->inUpdateScrollbars = true;
+
+ bool hasVerticalScrollbar = m_data->vBar;
+ bool hasHorizontalScrollbar = m_data->hBar;
+ bool oldHasVertical = hasVerticalScrollbar;
+ bool oldHasHorizontal = hasHorizontalScrollbar;
+ ScrollbarMode hScroll = m_data->hScrollbarMode;
+ ScrollbarMode vScroll = m_data->vScrollbarMode;
+
+ const int cVerticalWidth = PlatformScrollbar::verticalScrollbarWidth();
+ const int cHorizontalHeight = PlatformScrollbar::horizontalScrollbarHeight();
+
+ for (int pass = 0; pass < 2; pass++) {
+ bool scrollsVertically;
+ bool scrollsHorizontally;
+
+ if (!m_data->scrollbarsSuppressed && (hScroll == ScrollbarAuto || vScroll == ScrollbarAuto)) {
+ // Do a layout if pending before checking if scrollbars are needed.
+ if (hasVerticalScrollbar != oldHasVertical || hasHorizontalScrollbar != oldHasHorizontal)
+ static_cast<FrameView*>(this)->layout();
+
+ scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() > height());
+ if (scrollsVertically)
+ scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() + cVerticalWidth > width());
+ else {
+ scrollsHorizontally = (hScroll == ScrollbarAlwaysOn) || (hScroll == ScrollbarAuto && contentsWidth() > width());
+ if (scrollsHorizontally)
+ scrollsVertically = (vScroll == ScrollbarAlwaysOn) || (vScroll == ScrollbarAuto && contentsHeight() + cHorizontalHeight > height());
+ }
+ }
+ else {
+ scrollsHorizontally = (hScroll == ScrollbarAuto) ? hasHorizontalScrollbar : (hScroll == ScrollbarAlwaysOn);
+ scrollsVertically = (vScroll == ScrollbarAuto) ? hasVerticalScrollbar : (vScroll == ScrollbarAlwaysOn);
+ }
+
+ if (hasVerticalScrollbar != scrollsVertically) {
+ m_data->setHasVerticalScrollbar(scrollsVertically);
+ hasVerticalScrollbar = scrollsVertically;
+ }
+
+ if (hasHorizontalScrollbar != scrollsHorizontally) {
+ m_data->setHasHorizontalScrollbar(scrollsHorizontally);
+ hasHorizontalScrollbar = scrollsHorizontally;
+ }
+ }
+
+ // Set up the range (and page step/line step).
+ IntSize maxScrollPosition(contentsWidth() - visibleWidth(), contentsHeight() - visibleHeight());
+ IntSize scroll = desiredOffset.shrunkTo(maxScrollPosition);
+ scroll.clampNegativeToZero();
+
+ if (m_data->horizontalAdjustment) {
+ m_data->horizontalAdjustment->page_size = visibleWidth();
+ m_data->horizontalAdjustment->step_increment = MagicGtkScrollConstant;
+ m_data->horizontalAdjustment->upper = contentsWidth();
+ gtk_adjustment_changed(m_data->horizontalAdjustment);
+
+ if (m_data->scrollOffset.width() != scroll.width()) {
+ m_data->horizontalAdjustment->value = scroll.width();
+ gtk_adjustment_value_changed(m_data->horizontalAdjustment);
+ }
+ } else if (m_data->hBar) {
+ int clientWidth = visibleWidth();
+ m_data->hBar->setEnabled(contentsWidth() > clientWidth);
+ int pageStep = (clientWidth - PAGE_KEEP);
+ if (pageStep < 0) pageStep = clientWidth;
+ IntRect oldRect(m_data->hBar->frameGeometry());
+ IntRect hBarRect = IntRect(0,
+ height() - m_data->hBar->height(),
+ width() - (m_data->vBar ? m_data->vBar->width() : 0),
+ m_data->hBar->height());
+ m_data->hBar->setRect(hBarRect);
+ if (!m_data->scrollbarsSuppressed && oldRect != m_data->hBar->frameGeometry())
+ m_data->hBar->invalidate();
+
+ if (m_data->scrollbarsSuppressed)
+ m_data->hBar->setSuppressInvalidation(true);
+ m_data->hBar->setSteps(LINE_STEP, pageStep);
+ m_data->hBar->setProportion(clientWidth, contentsWidth());
+ m_data->hBar->setValue(scroll.width());
+ if (m_data->scrollbarsSuppressed)
+ m_data->hBar->setSuppressInvalidation(false);
+ }
+
+ if (m_data->verticalAdjustment) {
+ m_data->verticalAdjustment->page_size = visibleHeight();
+ m_data->verticalAdjustment->step_increment = MagicGtkScrollConstant;
+ m_data->verticalAdjustment->upper = contentsHeight();
+ gtk_adjustment_changed(m_data->verticalAdjustment);
+
+ if (m_data->scrollOffset.height() != scroll.height()) {
+ m_data->verticalAdjustment->value = scroll.height();
+ gtk_adjustment_value_changed(m_data->verticalAdjustment);
+ }
+ } else if (m_data->vBar) {
+ int clientHeight = visibleHeight();
+ m_data->vBar->setEnabled(contentsHeight() > clientHeight);
+ int pageStep = (clientHeight - PAGE_KEEP);
+ if (pageStep < 0) pageStep = clientHeight;
+ IntRect oldRect(m_data->vBar->frameGeometry());
+ IntRect vBarRect = IntRect(width() - m_data->vBar->width(),
+ 0,
+ m_data->vBar->width(),
+ height() - (m_data->hBar ? m_data->hBar->height() : 0));
+ m_data->vBar->setRect(vBarRect);
+ if (!m_data->scrollbarsSuppressed && oldRect != m_data->vBar->frameGeometry())
+ m_data->vBar->invalidate();
+
+ if (m_data->scrollbarsSuppressed)
+ m_data->vBar->setSuppressInvalidation(true);
+ m_data->vBar->setSteps(LINE_STEP, pageStep);
+ m_data->vBar->setProportion(clientHeight, contentsHeight());
+ m_data->vBar->setValue(scroll.height());
+ if (m_data->scrollbarsSuppressed)
+ m_data->vBar->setSuppressInvalidation(false);
+ }
+
+ if (oldHasVertical != (m_data->vBar != 0) || oldHasHorizontal != (m_data->hBar != 0))
+ geometryChanged();
+
+ // See if our offset has changed in a situation where we might not have scrollbars.
+ // This can happen when editing a body with overflow:hidden and scrolling to reveal selection.
+ // It can also happen when maximizing a window that has scrollbars (but the new maximized result
+ // does not).
+ IntSize scrollDelta = scroll - m_data->scrollOffset;
+ if (scrollDelta != IntSize()) {
+ m_data->scrollOffset = scroll;
+ m_data->scrollBackingStore(scrollDelta);
+ }
+
+ m_data->inUpdateScrollbars = false;
}
-IntPoint ScrollView::windowToContents(const IntPoint& point) const
+IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
{
- return point;
+ IntPoint viewPoint = convertFromContainingWindow(windowPoint);
+ return viewPoint + scrollOffset();
}
-IntPoint ScrollView::contentsToWindow(const IntPoint& point) const
+IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
{
- return point;
+ IntPoint viewPoint = contentsPoint - scrollOffset();
+ return convertToContainingWindow(viewPoint);
}
PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
{
- notImplemented();
+ IntPoint viewPoint = convertFromContainingWindow(mouseEvent.pos());
+ if (m_data->hBar && m_data->hBar->frameGeometry().contains(viewPoint))
+ return m_data->hBar.get();
+ if (m_data->vBar && m_data->vBar->frameGeometry().contains(viewPoint))
+ return m_data->vBar.get();
return 0;
}
+IntPoint ScrollView::convertChildToSelf(const Widget* child, const IntPoint& point) const
+{
+ IntPoint newPoint = point;
+ if (child != m_data->hBar && child != m_data->vBar)
+ newPoint = point - scrollOffset();
+ return Widget::convertChildToSelf(child, newPoint);
+}
+
+IntPoint ScrollView::convertSelfToChild(const Widget* child, const IntPoint& point) const
+{
+ IntPoint newPoint = point;
+ if (child != m_data->hBar && child != m_data->vBar)
+ newPoint = point + scrollOffset();
+ return Widget::convertSelfToChild(child, newPoint);
+}
+
+void ScrollView::paint(GraphicsContext* context, const IntRect& rect)
+{
+ // FIXME: This code is here so we don't have to fork FrameView.h/.cpp.
+ // In the end, FrameView should just merge with ScrollView.
+ ASSERT(isFrameView());
+
+ if (context->paintingDisabled())
+ return;
+
+ IntRect documentDirtyRect = rect;
+ documentDirtyRect.intersect(frameGeometry());
+
+ context->save();
+
+ context->translate(x(), y());
+ documentDirtyRect.move(-x(), -y());
+
+ context->translate(-contentsX(), -contentsY());
+ documentDirtyRect.move(contentsX(), contentsY());
+
+ context->clip(enclosingIntRect(visibleContentRect()));
+ static_cast<const FrameView*>(this)->frame()->paint(context, documentDirtyRect);
+ context->restore();
+
+ // Now paint the scrollbars.
+ if (!m_data->scrollbarsSuppressed && (m_data->hBar || m_data->vBar)) {
+ context->save();
+ IntRect scrollViewDirtyRect = rect;
+ scrollViewDirtyRect.intersect(frameGeometry());
+ context->translate(x(), y());
+ scrollViewDirtyRect.move(-x(), -y());
+ if (m_data->hBar)
+ m_data->hBar->paint(context, scrollViewDirtyRect);
+ if (m_data->vBar)
+ m_data->vBar->paint(context, scrollViewDirtyRect);
+
+ /*
+ * FIXME: TODO: Check if that works with RTL
+ */
+ // Fill the scroll corner with white.
+ IntRect hCorner;
+ if (m_data->hBar && width() - m_data->hBar->width() > 0) {
+ hCorner = IntRect(m_data->hBar->width(),
+ height() - m_data->hBar->height(),
+ width() - m_data->hBar->width(),
+ m_data->hBar->height());
+ if (hCorner.intersects(scrollViewDirtyRect))
+ context->fillRect(hCorner, Color::white);
+ }
+
+ if (m_data->vBar && height() - m_data->vBar->height() > 0) {
+ IntRect vCorner(width() - m_data->vBar->width(),
+ m_data->vBar->height(),
+ m_data->vBar->width(),
+ height() - m_data->vBar->height());
+ if (vCorner != hCorner && vCorner.intersects(scrollViewDirtyRect))
+ context->fillRect(vCorner, Color::white);
+ }
+
+ context->restore();
+ }
+}
+
+/*
+ * update children but nor our scrollbars. They should not scroll when
+ * we scroll our content.
+ */
+void ScrollView::geometryChanged() const
+{
+ HashSet<Widget*>::const_iterator end = m_data->children.end();
+ for (HashSet<Widget*>::const_iterator current = m_data->children.begin(); current != end; ++current)
+ (*current)->geometryChanged();
+}
+
+void ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity)
+{
+ if ((direction == ScrollUp || direction == ScrollDown) && m_data->vBar)
+ m_data->vBar->scroll(direction, granularity);
+ else if (m_data->hBar)
+ m_data->hBar->scroll(direction, granularity);
+}
+
+void ScrollView::addToDirtyRegion(const IntRect& containingWindowRect)
+{
+ ASSERT(isFrameView());
+ const FrameView* frameView = static_cast<const FrameView*>(this);
+ Page* page = frameView->frame() ? frameView->frame()->page() : 0;
+ if (!page)
+ return;
+ page->chrome()->addToDirtyRegion(containingWindowRect);
+}
+
+void ScrollView::scrollBackingStore(int dx, int dy, const IntRect& scrollViewRect, const IntRect& clipRect)
+{
+ ASSERT(isFrameView());
+ const FrameView* frameView = static_cast<const FrameView*>(this);
+ Page* page = frameView->frame() ? frameView->frame()->page() : 0;
+ if (!page)
+ return;
+ page->chrome()->scrollBackingStore(dx, dy, scrollViewRect, clipRect);
+}
+
+void ScrollView::updateBackingStore()
+{
+ ASSERT(isFrameView());
+ const FrameView* frameView = static_cast<const FrameView*>(this);
+ Page* page = frameView->frame() ? frameView->frame()->page() : 0;
+ if (!page)
+ return;
+ page->chrome()->updateBackingStore();
+}
+
}
diff --git a/WebCore/platform/gdk/WidgetGdk.cpp b/WebCore/platform/gdk/WidgetGdk.cpp
index 9c8f061..3d858ca 100644
--- a/WebCore/platform/gdk/WidgetGdk.cpp
+++ b/WebCore/platform/gdk/WidgetGdk.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007 Holger Hans Peter Freyther
* All rights reserved.
@@ -30,11 +30,11 @@
#include "Widget.h"
#include "Cursor.h"
-#include "Font.h"
+#include "FrameView.h"
#include "GraphicsContext.h"
#include "IntRect.h"
-#include "RenderObject.h"
#include "NotImplemented.h"
+#include "RenderObject.h"
#include <gdk/gdk.h>
#include <gtk/gtk.h>
@@ -43,31 +43,27 @@
class WidgetPrivate {
public:
- GdkDrawable* drawable;
GtkWidget* widget;
WidgetClient* client;
- IntRect geometry;
- Font font;
+ IntRect frameRect;
+
+ ScrollView* parent;
+ GtkLayout* containingWindow;
+ bool suppressInvalidation;
+
+ GdkDrawable* gdkDrawable() const
+ {
+ return widget ? widget->window : 0;
+ }
};
Widget::Widget()
: data(new WidgetPrivate)
{
- data->drawable = 0;
data->widget = 0;
-}
-
-Widget::Widget(GtkWidget* widget)
- : data(new WidgetPrivate)
-{
- setGtkWidget(widget);
-}
-
-GdkDrawable* Widget::gdkDrawable() const
-{
- if (!data->drawable && data->widget)
- data->drawable = GTK_IS_LAYOUT(data->widget) ? GTK_LAYOUT(data->widget)->bin_window : data->widget->window;
- return data->drawable;
+ data->parent = 0;
+ data->containingWindow = 0;
+ data->suppressInvalidation = false;
}
GtkWidget* Widget::gtkWidget() const
@@ -77,7 +73,6 @@
void Widget::setGtkWidget(GtkWidget* widget)
{
- data->drawable = 0;
data->widget = widget;
}
@@ -86,6 +81,16 @@
delete data;
}
+void Widget::setContainingWindow(GtkLayout* containingWindow)
+{
+ data->containingWindow = containingWindow;
+}
+
+GtkLayout* Widget::containingWindow() const
+{
+ return data->containingWindow;
+}
+
void Widget::setClient(WidgetClient* c)
{
data->client = c;
@@ -98,15 +103,27 @@
IntRect Widget::frameGeometry() const
{
- return data->geometry;
+ return data->frameRect;
}
+void Widget::setFrameGeometry(const IntRect& r)
+{
+ data->frameRect = r;
+}
+
+void Widget::setParent(ScrollView* v)
+{
+ data->parent = v;
+}
+
+ScrollView* Widget::parent() const
+{
+ return data->parent;
+}
+
void Widget::setFocus()
{
- GtkWidget *widget = data->widget;
- if (!widget)
- return;
- gtk_widget_grab_focus(widget);
+ gtk_widget_grab_focus(gtkWidget() ? gtkWidget() : GTK_WIDGET(containingWindow()));
}
void Widget::setCursor(const Cursor& cursor)
@@ -114,40 +131,21 @@
GdkCursor* pcur = cursor.impl();
if (!pcur)
return;
-
- GdkDrawable* drawable = gdkDrawable();
- if (!drawable || !GDK_IS_WINDOW(drawable))
- return;
- GdkWindow* window = GDK_WINDOW(drawable);
- gdk_window_set_cursor(window, pcur);
-
+ gdk_window_set_cursor(data->gdkDrawable() ? GDK_WINDOW(data->gdkDrawable()) : containingWindow()->bin_window, pcur);
}
void Widget::show()
{
- GdkDrawable* drawable = gdkDrawable();
- if (!drawable || !GDK_IS_WINDOW(drawable))
- return;
- GdkWindow* window = GDK_WINDOW(drawable);
- gdk_window_show(window);
+ if (!gtkWidget())
+ return;
+ gtk_widget_show(gtkWidget());
}
void Widget::hide()
{
- GdkDrawable* drawable = gdkDrawable();
- if (!drawable || !GDK_IS_WINDOW(drawable))
- return;
- GdkWindow* window = GDK_WINDOW(drawable);
- gdk_window_hide(window);
-}
-
-void Widget::setFrameGeometry(const IntRect& r)
-{
- data->geometry = r;
- g_return_if_fail(data->widget);
-
- GtkAllocation allocation = { r.x(), r.y(), r.width(), r.height() };
- gtk_widget_size_allocate(data->widget, &allocation);
+ if (!gtkWidget())
+ return;
+ gtk_widget_hide(gtkWidget());
}
void Widget::setEnabled(bool)
@@ -163,16 +161,15 @@
void Widget::removeFromParent()
{
- notImplemented();
+ if (parent())
+ parent()->removeChild(this);
}
/*
* Strategy to painting a Widget:
* 1.) do not paint if there is no GtkWidget set
- * 2.) We manipulate the GtkAllocation.{x,y} to take the
- * GraphicsContext translation into account. This works as long as we assume
- * that our GtkWidgets have GTK_NO_WINDOW set. This holds true
- * for the PlatformScrollbar.
+ * 2.) We assume that GTK_NO_WINDOW is set and that geometryChanged positioned
+ * the widget correctly. ATM we do not honor the GraphicsContext translation.
*/
void Widget::paint(GraphicsContext* context, const IntRect&)
{
@@ -182,16 +179,10 @@
GtkWidget* widget = gtkWidget();
ASSERT(GTK_WIDGET_NO_WINDOW(widget));
- IntPoint originalPosition = IntPoint(widget->allocation.x, widget->allocation.y);
- IntPoint translatedPosition = context->translatePoint(originalPosition);
- widget->allocation.x = translatedPosition.x();
- widget->allocation.y = translatedPosition.y();
-
GdkEvent* event = gdk_event_new(GDK_EXPOSE);
event->expose = *context->gdkExposeEvent();
event->expose.region = gtk_widget_region_intersect(widget, event->expose.region);
-
/*
* This will be unref'ed by gdk_event_free.
*/
@@ -205,8 +196,6 @@
gtk_widget_send_expose(widget, event);
}
- widget->allocation.x = originalPosition.x();
- widget->allocation.y = originalPosition.y();
gdk_event_free(event);
}
@@ -217,15 +206,83 @@
void Widget::invalidate()
{
- if (data->widget)
- gtk_widget_queue_draw(data->widget);
+ invalidateRect(IntRect(0, 0, width(), height()));
}
void Widget::invalidateRect(const IntRect& rect)
{
- if (data->widget)
- gtk_widget_queue_draw_area(data->widget, rect.x(), rect.y(),
+ if (data->suppressInvalidation)
+ return;
+
+ if (!parent()) {
+ gtk_widget_queue_draw_area(GTK_WIDGET(containingWindow()), rect.x(), rect.y(),
rect.width(), rect.height());
+ if (isFrameView())
+ static_cast<FrameView*>(this)->addToDirtyRegion(rect);
+ return;
+ }
+
+ // Get the root widget.
+ ScrollView* outermostView = parent();
+ while (outermostView && outermostView->parent())
+ outermostView = outermostView->parent();
+ if (!outermostView)
+ return;
+
+ IntRect windowRect = convertToContainingWindow(rect);
+ gtk_widget_queue_draw_area(GTK_WIDGET(containingWindow()), windowRect.x(), windowRect.y(),
+ windowRect.width(), windowRect.height());
+ outermostView->addToDirtyRegion(windowRect);
}
+IntPoint Widget::convertToContainingWindow(const IntPoint& point) const
+{
+ IntPoint windowPoint = point;
+ for (const Widget *parentWidget = parent(), *childWidget = this;
+ parentWidget;
+ childWidget = parentWidget, parentWidget = parentWidget->parent())
+ windowPoint = parentWidget->convertChildToSelf(childWidget, windowPoint);
+ return windowPoint;
+}
+
+IntPoint Widget::convertFromContainingWindow(const IntPoint& point) const
+{
+ IntPoint widgetPoint = point;
+ for (const Widget *parentWidget = parent(), *childWidget = this;
+ parentWidget;
+ childWidget = parentWidget, parentWidget = parentWidget->parent())
+ widgetPoint = parentWidget->convertSelfToChild(childWidget, widgetPoint);
+ return widgetPoint;
+}
+
+IntRect Widget::convertToContainingWindow(const IntRect& rect) const
+{
+ IntRect convertedRect = rect;
+ convertedRect.setLocation(convertToContainingWindow(convertedRect.location()));
+ return convertedRect;
+}
+
+IntPoint Widget::convertChildToSelf(const Widget* child, const IntPoint& point) const
+{
+ return IntPoint(point.x() + child->x(), point.y() + child->y());
+}
+
+IntPoint Widget::convertSelfToChild(const Widget* child, const IntPoint& point) const
+{
+ return IntPoint(point.x() - child->x(), point.y() - child->y());
+}
+
+bool Widget::suppressInvalidation() const
+{
+ return data->suppressInvalidation;
+}
+
+void Widget::setSuppressInvalidation(bool suppress)
+{
+ data->suppressInvalidation = suppress;
+}
+
+void Widget::geometryChanged() const
+{
+}
}
diff --git a/WebKit/gtk/Api/webkitgtkframe.cpp b/WebKit/gtk/Api/webkitgtkframe.cpp
index 686848b..8982dc4 100644
--- a/WebKit/gtk/Api/webkitgtkframe.cpp
+++ b/WebKit/gtk/Api/webkitgtkframe.cpp
@@ -133,9 +133,10 @@
frameData->frame = new Frame(pageData->page, 0, frameData->client);
FrameView* frameView = new FrameView(frameData->frame);
+ frameView->setContainingWindow(GTK_LAYOUT(page));
+ frameView->setGtkAdjustments(gtk_layout_get_hadjustment(GTK_LAYOUT(page)),
+ gtk_layout_get_vadjustment(GTK_LAYOUT(page)));
frameData->frame->setView(frameView);
-
- frameView->setGtkWidget(GTK_LAYOUT(page));
frameData->frame->init();
frameData->page = page;
diff --git a/WebKit/gtk/Api/webkitgtkpage.cpp b/WebKit/gtk/Api/webkitgtkpage.cpp
index 984877f..33391bb 100644
--- a/WebKit/gtk/Api/webkitgtkpage.cpp
+++ b/WebKit/gtk/Api/webkitgtkpage.cpp
@@ -82,7 +82,7 @@
if (frame->view()->needsLayout())
frame->view()->layout();
IntRect rect(clip.x, clip.y, clip.width, clip.height);
- frame->paint(&ctx, rect);
+ frame->view()->paint(&ctx, rect);
}
cairo_destroy(cr);
@@ -129,7 +129,7 @@
GTK_WIDGET_CLASS(webkit_gtk_page_parent_class)->size_allocate(widget,allocation);
Frame* frame = core(getFrameFromPage(WEBKIT_GTK_PAGE(widget)));
- frame->view()->updateGeometry(allocation->width, allocation->height);
+ frame->view()->resize(allocation->width, allocation->height);
frame->forceLayout();
frame->view()->adjustViewSize();
frame->sendResizeEvent();
@@ -153,6 +153,12 @@
| GDK_BUTTON3_MOTION_MASK));
}
+static void webkit_gtk_page_set_scroll_adjustments(GtkLayout* layout, GtkAdjustment* hadj, GtkAdjustment* vadj)
+{
+ FrameView* view = core(getFrameFromPage(WEBKIT_GTK_PAGE(layout)))->view();
+ view->setGtkAdjustments(hadj, vadj);
+}
+
static WebKitGtkFrame* webkit_gtk_page_real_create_frame(WebKitGtkPage*, WebKitGtkFrame* parent, WebKitGtkFrameData*)
{
notImplemented();
@@ -341,6 +347,8 @@
widgetClass->motion_notify_event = webkit_gtk_page_motion_event;
widgetClass->scroll_event = webkit_gtk_page_scroll_event;
widgetClass->size_allocate = webkit_gtk_page_size_allocate;
+
+ GTK_LAYOUT_CLASS(pageClass)->set_scroll_adjustments = webkit_gtk_page_set_scroll_adjustments;
}
static void webkit_gtk_page_init(WebKitGtkPage* page)
diff --git a/WebKit/gtk/ChangeLog b/WebKit/gtk/ChangeLog
new file mode 100644
index 0000000..a8e272c
--- /dev/null
+++ b/WebKit/gtk/ChangeLog
@@ -0,0 +1,13 @@
+2007-08-10 Holger Hans Peter Freyther <zecke@selfish.org>
+
+ Reviewed by Adam.
+
+ Follow the changes of ScrollView in WebCore and call setContainingWindow, set the
+ GtkAdjustment of the GtkLayout and reimplement the set_scroll_adjustments method and pass
+ the GtkAdjustments to ScrollView.
+ This makes having one GdkWindow for the complete FrameTree possible.
+
+
+ * gtk/Api/webkitgtkframe.cpp:
+ * gtk/Api/webkitgtkpage.cpp:
+