Version: 3.5.1 (using KDE 3.5.1, Debian Package 4:3.5.1-1 (testing/unstable)) Compiler: Target: i486-linux-gnu OS: Linux (i686) release 2.6.14 The mouse wheel can't work in DIV's with scroll bar. For example, go to his page: http://www.musicalibre.es The left and right columns are not frames, they are DIV's. So, put the mouse over each one and try to scroll down the content of the div with the mouse wheel. It's impossible. The only way is to use the mouse wheel just over the scroll bar, that is not very usable. In Firefox this doesn't occur, and it's not necessary to focus the div for scrolling it.
Confirmed. Annoying behaviour. r500000
Note the the page I set as example (http://www.musicalibre.es) has changed so now there are not these DIV's with scroll bar. I'll try to find another web example.
I found some examples of this behaviour which is annoying me too to the point where I have to switch browser because our company uses this. http://www.cssplay.co.uk/layouts/bodyfix.html http://www.cssplay.co.uk/layouts/body2.html http://www.cssplay.co.uk/layouts/body4.html http://www.cssplay.co.uk/layouts/body5.html Note firefox and IE work fine with these pages
*** Bug 126897 has been marked as a duplicate of this bug. ***
SVN commit 626756 by ggarand: implement scrolling of CSS containers with the mousewheel BUG: 121065 M +53 -0 rendering/render_box.cpp M +2 -0 rendering/render_box.h M +2 -0 rendering/render_object.h M +5 -1 xml/dom_nodeimpl.cpp --- trunk/KDE/kdelibs/khtml/rendering/render_box.cpp #626755:626756 @@ -6,6 +6,7 @@ * (C) 2002-2003 Apple Computer, Inc. * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) * (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + * (C) 2007 Germain Garand (germain@ebooksfrance.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,6 +32,7 @@ #include <qpainter.h> #include "misc/loader.h" +#include "rendering/render_form.h" #include "rendering/render_replaced.h" #include "rendering/render_canvas.h" #include "rendering/render_table.h" @@ -41,8 +43,10 @@ #include "misc/htmlhashes.h" #include "xml/dom_nodeimpl.h" #include "xml/dom_docimpl.h" +#include "xml/dom2_eventsimpl.h" #include "html/html_elementimpl.h" +#include <QWheelEvent> #include <khtmlview.h> #include <kdebug.h> #include <kglobal.h> @@ -2204,6 +2208,55 @@ return false; } +bool RenderBox::handleEvent(const DOM::EventImpl& e) +{ + if ( e.id() == EventImpl::KHTML_MOUSEWHEEL_EVENT && scrollsOverflow()) { + + const MouseEventImpl& me = static_cast<const MouseEventImpl&>(e); + Qt::MouseButtons buttons = Qt::NoButton; + Qt::KeyboardModifiers state = 0; + Qt::Orientation orient = Qt::Vertical; + + switch (me.button()) { + case 0: + buttons = Qt::LeftButton; + break; + case 1: + buttons = Qt::MidButton; + break; + case 2: + buttons = Qt::RightButton; + break; + default: + break; + } + + if (me.orientation() == MouseEventImpl::OHorizontal) + orient = Qt::Horizontal; + + int absx = 0; + int absy = 0; + absolutePosition(absx, absy); + absx += borderLeft()+paddingLeft(); + absy += borderTop()+paddingTop(); + QPoint p(me.clientX() - absx + canvas()->view()->contentsX(), + me.clientY() - absy + canvas()->view()->contentsY()); + + QWheelEvent we(p, -me.detail()*40, buttons, state, orient); + KHTMLAssert(layer()); + if (orient == Qt::Vertical) { + if (QWidget* w = dynamic_cast<QWidget*>( layer()->verticalScrollbar() )) + QApplication::sendEvent( w, &we); + } else { + if (QWidget* w = dynamic_cast<QWidget*>( layer()->horizontalScrollbar() )) + QApplication::sendEvent( w, &we); + } + if (we.isAccepted()) + return true; + } + return RenderContainer::handleEvent(e); +} + void RenderBox::caretPos(int /*offset*/, int flags, int &_x, int &_y, int &width, int &height) { #if 0 --- trunk/KDE/kdelibs/khtml/rendering/render_box.h #626755:626756 @@ -120,6 +120,8 @@ virtual int pageTopAfter(int y) const; virtual int crossesPageBreak(int t, int b) const; + + virtual bool handleEvent(const DOM::EventImpl& ev); int calcBoxWidth(int w) const; int calcBoxHeight(int h) const; --- trunk/KDE/kdelibs/khtml/rendering/render_object.h #626755:626756 @@ -317,6 +317,8 @@ DOM::DocumentImpl* document() const; DOM::NodeImpl* element() const { return isAnonymous() ? 0L : m_node; } DOM::NodeImpl* node() const { return m_node; } + + virtual bool handleEvent(const DOM::EventImpl&) { return false; }; /** * returns the object containing this one. can be different from parent for --- trunk/KDE/kdelibs/khtml/xml/dom_nodeimpl.cpp #626755:626756 @@ -623,8 +623,12 @@ } } -void NodeImpl::defaultEventHandler(EventImpl *) +void NodeImpl::defaultEventHandler(EventImpl *e) { + if (e->isMouseEvent() && e->id() == EventImpl::KHTML_MOUSEWHEEL_EVENT && e->target() == this) + if (m_render && m_render->scrollsOverflow()) + if (m_render->handleEvent(*e)) + e->setDefaultHandled(); } unsigned long NodeImpl::childNodeCount()
*** Bug 86224 has been marked as a duplicate of this bug. ***
Note that this only fixes half the bug. You still can't scroll using the keyboard.
mmh, right but then this would only make sense if scrollable layers are made focusable, wouldn't it? I can't seem to find this in any spec, but OTOH as scrollbars are controls, it makes a lot of sense... I'll have a look.
SVN commit 627032 by ggarand: elaborate on scrollable containers event handling: make them focusable and add keyboard events handling so as to make keyboard-only navigation possible. CCBUG: 121065 M +50 -4 rendering/render_box.cpp M +22 -0 xml/dom_elementimpl.cpp M +2 -0 xml/dom_elementimpl.h M +0 -4 xml/dom_nodeimpl.cpp --- trunk/KDE/kdelibs/khtml/rendering/render_box.cpp #627031:627032 @@ -2210,8 +2210,12 @@ bool RenderBox::handleEvent(const DOM::EventImpl& e) { - if ( e.id() == EventImpl::KHTML_MOUSEWHEEL_EVENT && scrollsOverflow()) { + KHTMLAssert( scrollsOverflow() ); + bool accepted = false; + switch ( e.id() ) { + case EventImpl::KHTML_MOUSEWHEEL_EVENT: { + const MouseEventImpl& me = static_cast<const MouseEventImpl&>(e); Qt::MouseButtons buttons = Qt::NoButton; Qt::KeyboardModifiers state = 0; @@ -2239,21 +2243,63 @@ absolutePosition(absx, absy); absx += borderLeft()+paddingLeft(); absy += borderTop()+paddingTop(); + QPoint p(me.clientX() - absx + canvas()->view()->contentsX(), me.clientY() - absy + canvas()->view()->contentsY()); QWheelEvent we(p, -me.detail()*40, buttons, state, orient); KHTMLAssert(layer()); if (orient == Qt::Vertical) { - if (QWidget* w = dynamic_cast<QWidget*>( layer()->verticalScrollbar() )) + if (QWidget* w = layer()->verticalScrollbar()) QApplication::sendEvent( w, &we); } else { - if (QWidget* w = dynamic_cast<QWidget*>( layer()->horizontalScrollbar() )) + if (QWidget* w = layer()->horizontalScrollbar()) QApplication::sendEvent( w, &we); } if (we.isAccepted()) - return true; + accepted = true; + break; + } + case EventImpl::KEYDOWN_EVENT: + case EventImpl::KEYUP_EVENT: + break; + case EventImpl::KEYPRESS_EVENT: + { + if (!e.isKeyRelatedEvent()) break; + const KeyEventBaseImpl& domKeyEv = static_cast<const KeyEventBaseImpl &>(e); + + QKeyEvent* const ke = domKeyEv.qKeyEvent(); + QScrollBar* vbar = layer()->verticalScrollbar(); + QScrollBar* hbar = layer()->horizontalScrollbar(); + switch (ke->key()) { + case Qt::Key_PageUp: + if(vbar) vbar->triggerAction(QScrollBar::SliderPageStepSub); + break; + case Qt::Key_PageDown: + if(vbar) vbar->triggerAction(QScrollBar::SliderPageStepAdd); + break; + case Qt::Key_Up: + if(vbar) vbar->triggerAction(QScrollBar::SliderSingleStepSub); + break; + case Qt::Key_Down: + if(vbar) vbar->triggerAction(QScrollBar::SliderSingleStepAdd); + break; + case Qt::Key_Left: + if (hbar) hbar->triggerAction(QScrollBar::SliderSingleStepSub); + break; + case Qt::Key_Right: + if (hbar) hbar->triggerAction(QScrollBar::SliderSingleStepAdd); + break; + default: + break; + } + break; + } + default: + break; } + if (accepted) + return true; return RenderContainer::handleEvent(e); } --- trunk/KDE/kdelibs/khtml/xml/dom_elementimpl.cpp #627031:627032 @@ -626,6 +626,25 @@ m_prefix->ref(); } +void ElementImpl::defaultEventHandler(EventImpl *e) +{ + if (m_render && m_render->scrollsOverflow()) { + switch( e->id() ) { + case EventImpl::KEYDOWN_EVENT: + case EventImpl::KEYUP_EVENT: + case EventImpl::KEYPRESS_EVENT: + if (!focused() || e->target() != this) + break; + // fall through + case EventImpl::KHTML_MOUSEWHEEL_EVENT: + if (m_render->handleEvent(*e)) + e->setDefaultHandled(); + default: + break; + } + } +} + void ElementImpl::createAttributeMap() const { namedAttrMap = new NamedAttrMapImpl(const_cast<ElementImpl*>(this)); @@ -789,6 +808,9 @@ bool ElementImpl::isFocusable() const { + if (m_render && m_render->scrollsOverflow()) + return true; + // Only make editable elements selectable if its parent element // is not editable. FIXME: this is not 100% right as non-editable elements // within editable elements are focusable too. --- trunk/KDE/kdelibs/khtml/xml/dom_elementimpl.h #627031:627032 @@ -209,6 +209,8 @@ virtual void structureChanged(); virtual void backwardsStructureChanged(); virtual void attributeChanged(NodeImpl::Id attrId); + + virtual void defaultEventHandler(EventImpl *evt); virtual khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent); virtual khtml::RenderObject *createRenderer(khtml::RenderArena *, khtml::RenderStyle *); --- trunk/KDE/kdelibs/khtml/xml/dom_nodeimpl.cpp #627031:627032 @@ -625,10 +625,6 @@ void NodeImpl::defaultEventHandler(EventImpl *e) { - if (e->isMouseEvent() && e->id() == EventImpl::KHTML_MOUSEWHEEL_EVENT && e->target() == this) - if (m_render && m_render->scrollsOverflow()) - if (m_render->handleEvent(*e)) - e->setDefaultHandled(); } unsigned long NodeImpl::childNodeCount()
Has this been committed into the most recent version (3.5.7)? It's not working for me.
It should be in KDE 3.5.7, indeed. So reopening because of comment #10.
Hmm, Germain didn't backport this fix to 3.5-branch, so it's fixed only in KDE4.