[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kfm-devel
Subject:    Re: Recent selection regressions/showstoppers
From:       Stephan Kulow <coolo () kde ! org>
Date:       2004-08-09 8:48:22
Message-ID: 200408091048.22140.coolo () kde ! org
[Download RAW message or body]

Am Samstag 07 August 2004 22:03 schrieb bj@altern.org:
> On Saturday 07 August 2004 17.35, Germain Garand wrote:
> > I think with all due respect for the nice cleanup attempt of Tobias, that
> > rushing such a huge change to the event handling days before a release
> > candidate was really asking for troubles ;(
> > Is there any good reason why this couldn't be postponed until it can
> > safely undergo full testing? there's not even a ChangeLog entry.
>
> I think it is probably better. My fix doesn't seem to cover all issues, and
> I found at least 2 more regressions:
I reverted the attached patch in HEAD and will backport after some testing

Greetings, Stephan

["events.patch" (text/x-diff)]

? patch
Index: khtmlview.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/khtmlview.cpp,v
retrieving revision 1.662
diff -u -3 -p -u -r1.662 khtmlview.cpp
--- khtmlview.cpp	9 Aug 2004 08:39:46 -0000	1.662
+++ khtmlview.cpp	9 Aug 2004 08:41:12 -0000
@@ -888,9 +888,8 @@ static inline void forwardPeripheralEven
     r->absolutePosition(absx, absy);
     QPoint p(x-absx, y-absy);
     QMouseEvent fw(me->type(), p, me->button(), me->state());
-    QWidget* w = r->widget();
-    if(w)
-        static_cast<khtml::RenderWidget::EventPropagator*>(w)->sendEvent(&fw);
+    if (r->element())
+	r->element()->dispatchMouseEvent(&fw);
 }
 
 void KHTMLView::viewportMouseMoveEvent( QMouseEvent * _mouse )
@@ -1374,11 +1373,8 @@ void KHTMLView::keyPressEvent( QKeyEvent
         default:
             if (d->scrollTimerId)
                 d->newScrollTimer(this, 0);
-	    _ke->ignore();
-            return;
         }
-
-    _ke->accept();
+    QScrollView::keyPressEvent(_ke);
 }
 
 #ifndef KHTML_NO_TYPE_AHEAD_FIND
@@ -1507,7 +1503,7 @@ bool KHTMLView::focusNextPrevChild( bool
     if (m_part->parentPart() && m_part->parentPart()->view())
         return m_part->parentPart()->view()->focusNextPrevChild(next);
 
-    return QWidget::focusNextPrevChild(next);
+    return false;
 }
 
 void KHTMLView::doAutoScroll()
@@ -1640,37 +1636,6 @@ bool KHTMLView::eventFilter(QObject *o, 
  				    pe->rect().width(), pe->rect().height());
 		}
 		break;
-	    case QEvent::MouseMove:
-	    case QEvent::MouseButtonPress:
-	    case QEvent::MouseButtonRelease:
-	    case QEvent::MouseButtonDblClick: {
-		if (w->parentWidget() == view && !::qt_cast<QScrollBar *>(w)) {
-		    QMouseEvent *me = static_cast<QMouseEvent *>(e);
-		    QPoint pt = (me->pos() + w->pos());
-		    QMouseEvent me2(me->type(), pt, me->button(), me->state());
-
-		    if (e->type() == QEvent::MouseMove)
-			viewportMouseMoveEvent(&me2);
-		    else if(e->type() == QEvent::MouseButtonPress)
-			viewportMousePressEvent(&me2);
-		    else if(e->type() == QEvent::MouseButtonRelease)
-			viewportMouseReleaseEvent(&me2);
-		    else
-			viewportMouseDoubleClickEvent(&me2);
-		    block = true;
-                }
-		break;
-	    }
-	    case QEvent::KeyPress:
-	    case QEvent::KeyRelease:
-		if (w->parentWidget() == view && !::qt_cast<QScrollBar *>(w)) {
-		    QKeyEvent *ke = static_cast<QKeyEvent *>(e);
-		    if (e->type() == QEvent::KeyPress)
-			keyPressEvent(ke);
-		    else
-			keyReleaseEvent(ke);
-		    block = true;
-		}
 	    default:
 		break;
 	    }
@@ -2549,7 +2514,7 @@ void KHTMLView::viewportWheelEvent(QWhee
         QScrollView::viewportWheelEvent( e );
 
         QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, QPoint(-1,-1), \
                QPoint(-1,-1), Qt::NoButton, e->state() );
-        emit viewportMouseMoveEvent ( tempEvent );
+        viewportMouseMoveEvent ( tempEvent );
         delete tempEvent;
     }
 
Index: html/html_formimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/html/html_formimpl.cpp,v
retrieving revision 1.381
diff -u -3 -p -u -r1.381 html_formimpl.cpp
--- html/html_formimpl.cpp	9 Aug 2004 08:39:46 -0000	1.381
+++ html/html_formimpl.cpp	9 Aug 2004 08:41:12 -0000
@@ -792,22 +792,12 @@ void HTMLGenericFormElementImpl::setDisa
 bool HTMLGenericFormElementImpl::isSelectable() const
 {
     return  m_render && m_render->isWidget() &&
-        static_cast<RenderWidget*>(m_render)->widget() &&
-        static_cast<RenderWidget*>(m_render)->widget()->focusPolicy() >= \
QWidget::TabFocus; +        static_cast<RenderWidget*>(m_render)->widget();
 }
 
-class FocusHandleWidget : public QWidget
-{
-public:
-    void focusNextPrev(bool n) {
-	focusNextPrevChild(n);
-    }
-};
-
 void HTMLGenericFormElementImpl::defaultEventHandler(EventImpl *evt)
 {
-    if (evt->target() == this && renderer() && renderer()->isWidget() &&
-        !static_cast<RenderWidget*>(renderer())->widget()->inherits("QScrollView")) \
{ +    if (evt->target() == this && renderer() && renderer()->isWidget()) {
         switch(evt->id())  {
         case EventImpl::MOUSEDOWN_EVENT:
         case EventImpl::MOUSEUP_EVENT:
@@ -843,25 +833,13 @@ void HTMLGenericFormElementImpl::default
 	    if (m_active)
 	    {
 		setActive(false);
-		setFocus();
+		getDocument()->setFocusNode(this);
 	    }
 	    else {
                 setActive(false);
             }
         }
 
-	if (evt->id() == EventImpl::KHTML_KEYPRESS_EVENT) {
-	    TextEventImpl * k = static_cast<TextEventImpl *>(evt);
-	    int key = k->qKeyEvent ? k->qKeyEvent->key() : 0;
-	    if (m_render && (key == Qt::Key_Tab || key == Qt::Key_BackTab)) {
-		QWidget *widget = static_cast<RenderWidget*>(m_render)->widget();
-		if (widget)
-		    static_cast<FocusHandleWidget *>(widget)
-			->focusNextPrev(key == Qt::Key_Tab);
-	    }
-	}
-
-
 	if (view && evt->id() == EventImpl::DOMFOCUSOUT_EVENT && isEditable() && m_render \
                && m_render->isWidget()) {
 	    KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension \
*>(view->part()->browserExtension());  QWidget *widget = \
                static_cast<RenderWidget*>(m_render)->widget();
Index: rendering/render_form.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_form.cpp,v
retrieving revision 1.270
diff -u -3 -p -u -r1.270 render_form.cpp
--- rendering/render_form.cpp	9 Aug 2004 08:39:46 -0000	1.270
+++ rendering/render_form.cpp	9 Aug 2004 08:41:12 -0000
@@ -114,11 +114,35 @@ short RenderButton::baselinePosition( bo
 
 // -------------------------------------------------------------------------------
 
+CheckBoxWidget::CheckBoxWidget(QWidget *parent)
+    : QCheckBox(parent, "__khtml")
+{
+}
+
+bool CheckBoxWidget::event(QEvent *e)
+{
+    bool retval = QCheckBox::event(e);
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
+    }
+}
+
+// -------------------------------------------------------------------------------
+
 
 RenderCheckBox::RenderCheckBox(HTMLInputElementImpl *element)
     : RenderButton(element)
 {
-    QCheckBox* b = new QCheckBox(view()->viewport(), "__khtml");
+    QCheckBox* b = new CheckBoxWidget(view()->viewport());
     b->setAutoMask(true);
     b->setMouseTracking(true);
     setQWidget(b);
@@ -153,10 +177,34 @@ void RenderCheckBox::slotStateChanged(in
 
 // -------------------------------------------------------------------------------
 
+RadioButtonWidget::RadioButtonWidget(QWidget *parent)
+    : QRadioButton(parent, "__khtml")
+{
+}
+
+bool RadioButtonWidget::event(QEvent *e)
+{
+    bool retval = QRadioButton::event(e);
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
+    }
+}
+
+// -------------------------------------------------------------------------------
+
 RenderRadioButton::RenderRadioButton(HTMLInputElementImpl *element)
     : RenderButton(element)
 {
-    QRadioButton* b = new QRadioButton(view()->viewport(), "__khtml");
+    QRadioButton* b = new RadioButtonWidget(view()->viewport());
     b->setMouseTracking(true);
     setQWidget(b);
 }
@@ -183,11 +231,35 @@ void RenderRadioButton::calcMinMaxWidth(
 
 // -------------------------------------------------------------------------------
 
+FormButtonWidget::FormButtonWidget(QWidget *parent)
+    : QPushButton(parent, "__khtml")
+{
+}
+
+bool FormButtonWidget::event(QEvent *e)
+{
+    bool retval = QPushButton::event(e);
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
+    }
+}
+
+// -------------------------------------------------------------------------------
+
 
 RenderSubmitButton::RenderSubmitButton(HTMLInputElementImpl *element)
     : RenderButton(element)
 {
-    QPushButton* p = new QPushButton(view()->viewport(), "__khtml");
+    QPushButton* p = new FormButtonWidget(view()->viewport());
     setQWidget(p);
     p->setAutoMask(true);
     p->setMouseTracking(true);
@@ -391,9 +463,6 @@ void LineEditWidget::extendedMenuActivat
 
 bool LineEditWidget::event( QEvent *e )
 {
-    if (KLineEdit::event(e))
-	return true;
-
     if ( e->type() == QEvent::AccelAvailable && isReadOnly() ) {
         QKeyEvent* ke = (QKeyEvent*) e;
         if ( ke->state() & ControlButton ) {
@@ -410,7 +479,21 @@ bool LineEditWidget::event( QEvent *e )
             }
         }
     }
-    return false;
+
+    bool retval = KLineEdit::event(e);
+
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
+    }
 }
 
 void LineEditWidget::mouseMoveEvent(QMouseEvent *e)
@@ -704,10 +787,34 @@ void RenderFieldset::setStyle(RenderStyl
 
 // -------------------------------------------------------------------------
 
+FileButtonWidget::FileButtonWidget(QWidget *w, const char *name)
+    : KURLRequester(w, name)
+{
+}
+
+bool FileButtonWidget::event(QEvent *e)
+{
+    bool retval = KURLRequester::event(e);
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
+    }
+}
+
+// -------------------------------------------------------------------------
+
 RenderFileButton::RenderFileButton(HTMLInputElementImpl *element)
     : RenderFormElement(element)
 {
-    KURLRequester* w = new KURLRequester( view()->viewport(), "__khtml" );
+    KURLRequester* w = new FileButtonWidget( view()->viewport(), "__khtml" );
 
     connect(w->lineEdit(), SIGNAL(returnPressed()), this, \
                SLOT(slotReturnPressed()));
     connect(w->lineEdit(), SIGNAL(textChanged(const QString \
&)),this,SLOT(slotTextChanged(const QString &))); @@ -808,8 +915,11 @@ \
ComboBoxWidget::ComboBoxWidget(QWidget *  
 bool ComboBoxWidget::event(QEvent *e)
 {
-    if (KComboBox::event(e))
+    bool retval = KComboBox::event(e);
+
+    if (retval)
 	return true;
+
     if (e->type()==QEvent::KeyPress)
     {
 	QKeyEvent *ke = static_cast<QKeyEvent *>(e);
@@ -821,10 +931,22 @@ bool ComboBoxWidget::event(QEvent *e)
 	    ke->accept();
 	    return true;
 	default:
-	    return false;
+	    break;
 	}
     }
-    return false;
+
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
+    }
 }
 
 bool ComboBoxWidget::eventFilter(QObject *dest, QEvent *e)
@@ -854,6 +976,32 @@ bool ComboBoxWidget::eventFilter(QObject
 
 // -------------------------------------------------------------------------
 
+ListBoxWidget::ListBoxWidget(QWidget *parent, bool multiple)
+    : KListBox(parent, "blah")
+{
+    setMouseTracking(true);
+    setSelectionMode(multiple ? QListBox::Extended : QListBox::Single);
+}
+
+bool ListBoxWidget::event(QEvent *e)
+{
+    bool retval = KListBox::event(e);
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
+    }
+}
+
+// -------------------------------------------------------------------------
+
 RenderSelect::RenderSelect(HTMLSelectElementImpl *element)
     : RenderFormElement(element)
 {
@@ -1143,14 +1291,11 @@ void RenderSelect::setOptionsChanged(boo
 
 KListBox* RenderSelect::createListBox()
 {
-    KListBox *lb = new KListBox(view()->viewport());
-    lb->setSelectionMode(m_multiple ? QListBox::Extended : QListBox::Single);
-    // ### looks broken
-    //lb->setAutoMask(true);
+    KListBox *lb = new ListBoxWidget(view()->viewport(), m_multiple);
     connect( lb, SIGNAL( selectionChanged() ), this, SLOT( slotSelectionChanged() ) \
                );
-//     connect( lb, SIGNAL( clicked( QListBoxItem * ) ), this, SLOT( slotClicked() ) \
); +
+    // ### is this necessary and wanted?
     m_ignoreSelectEvents = false;
-    lb->setMouseTracking(true);
 
     return lb;
 }
@@ -1511,22 +1656,36 @@ void TextAreaWidget::slotReplace()
 bool TextAreaWidget::event( QEvent *e )
 {
     if ( e->type() == QEvent::AccelAvailable && isReadOnly() ) {
-        QKeyEvent* ke = (QKeyEvent*) e;
-        if ( ke->state() & ControlButton ) {
-            switch ( ke->key() ) {
-                case Key_Left:
-                case Key_Right:
-                case Key_Up:
-                case Key_Down:
-                case Key_Home:
-                case Key_End:
-                    ke->accept();
-                default:
-                break;
-            }
-        }
+	QKeyEvent* ke = (QKeyEvent*) e;
+	if ( ke->state() & ControlButton ) {
+	    switch ( ke->key() ) {
+	    case Key_Left:
+	    case Key_Right:
+	    case Key_Up:
+	    case Key_Down:
+	    case Key_Home:
+	    case Key_End:
+		ke->accept();
+	    default:
+		break;
+	    }
+	}
+    }
+    
+    bool retval = KTextEdit::event( e );
+
+    switch(e->type())
+    {
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+	return true;
+    default:
+	return retval;
     }
-    return KTextEdit::event( e );
 }
 
 // -------------------------------------------------------------------------
Index: rendering/render_form.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_form.h,v
retrieving revision 1.114
diff -u -3 -p -u -r1.114 render_form.h
--- rendering/render_form.h	9 Aug 2004 08:39:46 -0000	1.114
+++ rendering/render_form.h	9 Aug 2004 08:41:12 -0000
@@ -127,6 +127,16 @@ protected:
 
 // -------------------------------------------------------------------------
 
+class CheckBoxWidget : public QCheckBox
+{
+public:
+    CheckBoxWidget(QWidget *parent);
+protected:
+    virtual bool event(QEvent *e);
+};
+
+// -------------------------------------------------------------------------
+
 class RenderCheckBox : public RenderButton
 {
     Q_OBJECT
@@ -147,6 +157,16 @@ public slots:
 
 // -------------------------------------------------------------------------
 
+class RadioButtonWidget : public QRadioButton
+{
+public:
+    RadioButtonWidget(QWidget *parent);
+protected:
+    virtual bool event(QEvent *e);
+};
+
+// -------------------------------------------------------------------------
+
 class RenderRadioButton : public RenderButton
 {
 public:
@@ -164,6 +184,16 @@ public:
 
 // -------------------------------------------------------------------------
 
+class FormButtonWidget : public QPushButton
+{
+public:
+    FormButtonWidget(QWidget *parent);
+protected:
+    virtual bool event(QEvent *e);
+};
+
+// -------------------------------------------------------------------------
+
 class RenderSubmitButton : public RenderButton
 {
 public:
@@ -300,6 +330,16 @@ protected:
 
 // -------------------------------------------------------------------------
 
+class FileButtonWidget : public KURLRequester
+{
+public:
+    FileButtonWidget(QWidget *parent, const char *name);
+ protected:
+    virtual bool event(QEvent *);
+};
+
+// -------------------------------------------------------------------------
+
 class RenderFileButton : public RenderFormElement
 {
     Q_OBJECT
@@ -363,6 +403,16 @@ protected:
     virtual bool eventFilter(QObject *dest, QEvent *e);
 };
 
+class ListBoxWidget : public KListBox
+{
+public:
+    ListBoxWidget(QWidget *parent, bool multiple);
+
+protected:
+    virtual bool event(QEvent *);
+};
+
+
 // -------------------------------------------------------------------------
 
 class RenderSelect : public RenderFormElement
Index: rendering/render_frames.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_frames.cpp,v
retrieving revision 1.185
diff -u -3 -p -u -r1.185 render_frames.cpp
--- rendering/render_frames.cpp	9 Aug 2004 08:39:46 -0000	1.185
+++ rendering/render_frames.cpp	9 Aug 2004 08:41:12 -0000
@@ -530,6 +530,14 @@ void RenderPart::setWidget( QWidget *wid
     slotViewCleared();
 }
 
+bool RenderPart::eventFilter(QObject *o, QEvent *e)
+{
+    if (element() && element()->id() == ID_FRAME && e->type()==QEvent::FocusIn) {
+	element()->getDocument()->setFocusNode(element());
+    }
+    return RenderWidget::eventFilter(o, e);
+}
+
 bool RenderPart::partLoadingErrorNotify(khtml::ChildFrame *, const KURL& , const \
QString& )  {
     return false;
Index: rendering/render_frames.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_frames.h,v
retrieving revision 1.58
diff -u -3 -p -u -r1.58 render_frames.h
--- rendering/render_frames.h	9 Aug 2004 08:39:46 -0000	1.58
+++ rendering/render_frames.h	9 Aug 2004 08:41:12 -0000
@@ -102,6 +102,8 @@ public:
 
     virtual void setWidget( QWidget *widget );
 
+    virtual bool eventFilter(QObject *o, QEvent *e);
+
     /**
      * Called by KHTMLPart to notify the frame object that loading the
      * part was not successfuly. (called either asyncroniously after a
Index: rendering/render_replaced.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_replaced.cpp,v
retrieving revision 1.172
diff -u -3 -p -u -r1.172 render_replaced.cpp
--- rendering/render_replaced.cpp	9 Aug 2004 08:39:46 -0000	1.172
+++ rendering/render_replaced.cpp	9 Aug 2004 08:41:12 -0000
@@ -33,15 +33,18 @@
 #include <qevent.h>
 #include <qapplication.h>
 #include <qlineedit.h>
-#include <kglobalsettings.h>
 #include <qobjectlist.h>
+#include <qscrollview.h>
 
+#include <kdebug.h>
+#include <kglobalsettings.h>
 #include "khtml_ext.h"
 #include "khtmlview.h"
 #include "xml/dom2_eventsimpl.h"
 #include "khtml_part.h"
 #include "xml/dom_docimpl.h"
-#include <kdebug.h>
+#include <kurlrequester.h>
+#include <klineedit.h>
 
 bool khtml::allowWidgetPaintEvents = false;
 
@@ -96,6 +99,8 @@ RenderWidget::RenderWidget(DOM::NodeImpl
     m_view = node->getDocument()->view();
     m_resizePending = false;
 
+    m_ignoreEvents = false;
+
     // this is no real reference counting, its just there
     // to make sure that we're not deleted while we're recursed
     // in an eventFilter of the widget
@@ -113,8 +118,18 @@ void RenderWidget::detach()
             m_view->removeChild( m_widget );
         }
 
-        m_widget->removeEventFilter( this );
+	if (m_widget->inherits("QScrollView"))
+	{
+	    m_widget->removeEventFilter(this);
+	    static_cast<QScrollView*>(m_widget)->viewport()->removeEventFilter(this);
+	}
+	else if (m_widget->inherits("KURLRequester"))
+	    static_cast<KURLRequester*>(m_widget)->lineEdit()->removeEventFilter(this);
+	else
+	    m_widget->removeEventFilter(this);
+
         m_widget->setMouseTracking( false );
+	m_ignoreEvents = true;
     }
 
     deref();
@@ -181,7 +196,17 @@ void RenderWidget::setQWidget(QWidget *w
     if (widget != m_widget)
     {
         if (m_widget) {
-            m_widget->removeEventFilter(this);
+
+	    if (m_widget->inherits("QScrollView"))
+	    {
+		m_widget->removeEventFilter(this);
+		static_cast<QScrollView*>(m_widget)->viewport()->removeEventFilter(this);
+	    }
+	    else if (m_widget->inherits("KURLRequester"))
+		static_cast<KURLRequester*>(m_widget)->lineEdit()->removeEventFilter(this);
+	    else
+		m_widget->removeEventFilter(this);
+
             disconnect( m_widget, SIGNAL( destroyed()), this, SLOT( \
slotWidgetDestructed()));  delete m_widget;
             m_widget = 0;
@@ -189,13 +214,23 @@ void RenderWidget::setQWidget(QWidget *w
         m_widget = widget;
         if (m_widget) {
             connect( m_widget, SIGNAL( destroyed()), this, SLOT( \
                slotWidgetDestructed()));
-            m_widget->installEventFilter(this);
+
+	    if (m_widget->inherits("QScrollView"))
+	    {
+		m_widget->installEventFilter(this);
+		static_cast<QScrollView*>(m_widget)->viewport()->installEventFilter(this);
+	    }
+	    else if (m_widget->inherits("KURLRequester"))
+		static_cast<KURLRequester*>(m_widget)->lineEdit()->installEventFilter(this);
+	    else
+		m_widget->installEventFilter(this);
 
             if ( !strcmp(m_widget->name(), "__khtml"))
                 m_widget->setBackgroundMode( QWidget::NoBackground );
 
-            if (m_widget->focusPolicy() > QWidget::StrongFocus)
-                m_widget->setFocusPolicy(QWidget::StrongFocus);
+	    m_widget->setFocusPolicy(QWidget::NoFocus);
+	    m_widget->setMouseTracking(true);
+
             // if we're already layouted, apply the calculated space to the
             // widget immediately
             if (layouted()) {
@@ -455,13 +490,26 @@ void RenderWidget::paintWidget(PaintInfo
     allowWidgetPaintEvents = false;
 }
 
-bool RenderWidget::eventFilter(QObject* /*o*/, QEvent* e)
+/*
+ before an event is received by the widget,
+ we filter it out in RenderWidget::eventFilter() and propagate it through the DOM.
+ When it arrives at the RenderWidget again, handleEvent() converts the DOM event
+ back to a QEvent and sends it to the widget by calling sendEventToWidget().
+ Events dispatched via sendEventToWidget() must not be filtered again,
+ but they have to be sent via QApplication::notify(),
+ so that other existing event filters aren't skipped.
+*/
+
+bool RenderWidget::eventFilter(QObject* o, QEvent* e)
 {
     // no special event processing if this is a frame (in which case KHTMLView \
handles it all)  if ( ::qt_cast<KHTMLView *>( m_widget ) )
         return false;
+
     if ( !element() ) return true;
 
+    if ( m_ignoreEvents ) return false;
+
     ref();
     element()->ref();
 
@@ -475,22 +523,56 @@ bool RenderWidget::eventFilter(QObject* 
         if ( QFocusEvent::reason() != QFocusEvent::Popup )
             handleFocusOut();
         break;
-    case QEvent::FocusIn:
-        //kdDebug(6000) << "RenderWidget::eventFilter captures FocusIn" << endl;
-        element()->getDocument()->setFocusNode(element());
-//         if ( isEditable() ) {
-//             KHTMLPartBrowserExtension *ext = \
static_cast<KHTMLPartBrowserExtension *>( element()->view->part()->browserExtension() \
                );
-//             if ( ext )  ext->editableWidgetFocused( m_widget );
-//         }
-        break;
     case QEvent::KeyPress:
     case QEvent::KeyRelease:
-    // TODO this seems wrong - Qt events are not correctly translated to DOM ones,
-    // like in KHTMLView::dispatchKeyEvent()
-        if (element()->dispatchKeyEvent(static_cast<QKeyEvent*>(e),false))
-            filtered = true;
+        if (element()->getDocument() && element()->getDocument()->view())
+        {
+            qApp->notify(element()->getDocument()->view(), e);
+            if (static_cast<QKeyEvent*>(e)->isAccepted())
+                filtered = true;
+        }
         break;
 
+    case QEvent::MouseMove:
+    case QEvent::MouseButtonPress:
+    case QEvent::MouseButtonRelease:
+    case QEvent::MouseButtonDblClick:
+        if (element()->getDocument() && element()->getDocument()->view())
+        {
+            QWidget *w = ::qt_cast<QWidget*>(o);
+            QMouseEvent *me = static_cast<QMouseEvent *>(e);
+            QPoint pt = me->pos();
+            
+            while (w != element()->getDocument()->view()) {
+                if (element()->getDocument()->view()->childX(w) ||
+                    element()->getDocument()->view()->childY(w))
+                {
+                    pt += QPoint(element()->getDocument()->view()->childX(w), \
element()->getDocument()->view()->childY(w)); +                    break;
+                }
+                pt += w->pos();
+                w = w->parentWidget();
+            }
+            
+            pt = element()->getDocument()->view()->contentsToViewport(pt);
+            
+            // kdDebug(6000)<<"mouse event in RenderWidget with coords (" << \
pt.x()<<"/"<<pt.y()<<")\n"; +            
+            QMouseEvent me2(me->type(), pt, me->button(), me->state());
+            
+            if (e->type() == QEvent::MouseMove)
+                element()->getDocument()->view()->viewportMouseMoveEvent(&me2);
+            else if(e->type() == QEvent::MouseButtonPress)
+                element()->getDocument()->view()->viewportMousePressEvent(&me2);
+            else if(e->type() == QEvent::MouseButtonRelease)
+                element()->getDocument()->view()->viewportMouseReleaseEvent(&me2);
+            else
+                element()->getDocument()->view()->viewportMouseDoubleClickEvent(&me2);
 +            
+            filtered = true;
+            break;
+        }
+
     case QEvent::Wheel:
         if (widget()->parentWidget() == view()->viewport()) {
             // don't allow the widget to react to wheel event unless its
@@ -518,30 +600,7 @@ bool RenderWidget::eventFilter(QObject* 
     return filtered;
 }
 
-void RenderWidget::EventPropagator::sendEvent(QEvent *e) {
-    switch(e->type()) {
-    case QEvent::MouseButtonPress:
-        mousePressEvent(static_cast<QMouseEvent *>(e));
-        break;
-    case QEvent::MouseButtonRelease:
-        mouseReleaseEvent(static_cast<QMouseEvent *>(e));
-        break;
-    case QEvent::MouseButtonDblClick:
-        mouseDoubleClickEvent(static_cast<QMouseEvent *>(e));
-        break;
-    case QEvent::MouseMove:
-        mouseMoveEvent(static_cast<QMouseEvent *>(e));
-        break;
-    case QEvent::KeyPress:
-        keyPressEvent(static_cast<QKeyEvent *>(e));
-        break;
-    case QEvent::KeyRelease:
-        keyReleaseEvent(static_cast<QKeyEvent *>(e));
-        break;
-    default:
-        break;
-    }
-}
+// called from GenericFormElementImpl::defaultEventHandler:
 
 bool RenderWidget::handleEvent(const DOM::EventImpl& ev)
 {
@@ -607,14 +666,14 @@ bool RenderWidget::handleEvent(const DOM
 //                   << " pos=" << p << " type=" << type
 //                   << " button=" << button << " state=" << state << endl;
         QMouseEvent e(type, p, button, state);
-        static_cast<EventPropagator *>(m_widget)->sendEvent(&e);
+	sendEventToWidget(&e);
+
         break;
     }
     case EventImpl::KEYDOWN_EVENT:
     case EventImpl::KEYUP_EVENT: {
         QKeyEvent *ke = static_cast<const TextEventImpl &>(ev).qKeyEvent;
-        if (ke)
-            static_cast<EventPropagator *>(m_widget)->sendEvent(ke);
+	sendEventToWidget(ke);
         break;
     }
     case EventImpl::KHTML_KEYPRESS_EVENT: {
@@ -633,28 +692,41 @@ bool RenderWidget::handleEvent(const DOM
         if (ke && ke->isAutoRepeat()) {
             QKeyEvent releaseEv( QEvent::KeyRelease, ke->key(), ke->ascii(), \
                ke->state(),
                                ke->text(), ke->isAutoRepeat(), ke->count() );
-            static_cast<EventPropagator *>(m_widget)->sendEvent(&releaseEv);
-            static_cast<EventPropagator *>(m_widget)->sendEvent(ke);
-        }
 
+	    sendEventToWidget(&releaseEv);
+	    sendEventToWidget(ke);
+        }
 	break;
     }
     case EventImpl::MOUSEOUT_EVENT: {
 	QEvent moe( QEvent::Leave );
-	QApplication::sendEvent(m_widget, &moe);
+	sendEventToWidget(&moe);
 	break;
     }
     case EventImpl::MOUSEOVER_EVENT: {
 	QEvent moe( QEvent::Enter );
-	QApplication::sendEvent(m_widget, &moe);
+	sendEventToWidget(&moe);
 	break;
     }
     default:
         break;
     }
+
     return true;
 }
 
+void RenderWidget::sendEventToWidget(QEvent *e)
+{
+    m_ignoreEvents = true;
+    if (m_widget->inherits("QScrollView"))
+	qApp->notify(static_cast<QScrollView*>(m_widget)->viewport(), e);
+    else if (m_widget->inherits("KURLRequester"))
+	qApp->notify(static_cast<KURLRequester*>(m_widget)->lineEdit(), e);
+    else
+	qApp->notify(m_widget, e);
+    m_ignoreEvents = false;
+}
+
 void RenderWidget::deref()
 {
     if (_ref) _ref--;
Index: rendering/render_replaced.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/rendering/render_replaced.h,v
retrieving revision 1.77
diff -u -3 -p -u -r1.77 render_replaced.h
--- rendering/render_replaced.h	9 Aug 2004 08:39:47 -0000	1.77
+++ rendering/render_replaced.h	9 Aug 2004 08:41:12 -0000
@@ -123,16 +123,13 @@ protected:
     void setQWidget(QWidget *widget);
     void resizeWidget( int w, int h );
 
+    void sendEventToWidget(QEvent *e);
+
     QWidget *m_widget;
     KHTMLView* m_view;
 
     bool m_resizePending;
-
-public:
-    class EventPropagator : public QWidget {
-    public:
-        void sendEvent(QEvent *e);
-    };
+    bool m_ignoreEvents;
 };
 
 extern bool allowWidgetPaintEvents;
Index: xml/dom_docimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_docimpl.cpp,v
retrieving revision 1.290
diff -u -3 -p -u -r1.290 dom_docimpl.cpp
--- xml/dom_docimpl.cpp	9 Aug 2004 08:39:47 -0000	1.290
+++ xml/dom_docimpl.cpp	9 Aug 2004 08:41:12 -0000
@@ -2051,21 +2051,27 @@ void DocumentImpl::setFocusNode(NodeImpl
             if (m_focusNode != newFocusNode) return;
             m_focusNode->setFocus();
             if (m_focusNode != newFocusNode) return;
+        }
+
+        updateRendering();
+    }
 
-            // eww, I suck. set the qt focus correctly
-            // ### find a better place in the code for this
+    // ### remove this code as soon as the event flow between frames
+    // is completely handled via the DOM event model.
+    // At the moment, this code is required exactly here (not inside the
+    // if (m_focusNode != newFocusNode) clause), because a form element
+    // which the document erroneously considers the focus widget
+    // can receive focus by a mouse click, e.g. if a widget outside
+    // KHTML was focused before.
             if (view()) {
-                if (!m_focusNode->renderer() || \
!m_focusNode->renderer()->isWidget()) +	if (!m_focusNode || !m_focusNode->renderer() \
|| !m_focusNode->renderer()->isWidget())  view()->setFocus();
-                else if \
(static_cast<RenderWidget*>(m_focusNode->renderer())->widget()) +	else if \
(static_cast<RenderWidget*>(m_focusNode->renderer())->widget() && +		 \
                qApp->focusWidget() != \
                static_cast<RenderWidget*>(m_focusNode->renderer())->widget())
                     \
static_cast<RenderWidget*>(m_focusNode->renderer())->widget()->setFocus();  }
         }
 
-        updateRendering();
-    }
-}
-
 void DocumentImpl::attachNodeIterator(NodeIteratorImpl *ni)
 {
     m_nodeIterators.append(ni);



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic