diff options
author | jmarshallnz <jmarshallnz@svn> | 2010-01-08 04:51:50 +0000 |
---|---|---|
committer | jmarshallnz <jmarshallnz@svn> | 2010-01-08 04:51:50 +0000 |
commit | 91d92b85b573359c2ba6e99f5e0c3203e41431b5 (patch) | |
tree | fd3bec6eff026209937ecd1c7cfd42cf8899656d | |
parent | 04f2f7f645644e7816b326833a7b2f0f2c5d82e6 (diff) |
cleanup: Changed the way controls are selected for focus under the mouse pointer. Fixes potential issues with control groups ignoring anything other than the first possibly focusable control when passing mouse actions.
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@26534 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
-rw-r--r-- | guilib/GUIControl.cpp | 8 | ||||
-rw-r--r-- | guilib/GUIControl.h | 16 | ||||
-rw-r--r-- | guilib/GUIControlGroup.cpp | 15 | ||||
-rw-r--r-- | guilib/GUIControlGroup.h | 2 | ||||
-rw-r--r-- | guilib/GUIControlGroupList.cpp | 15 | ||||
-rw-r--r-- | guilib/GUIControlGroupList.h | 2 | ||||
-rw-r--r-- | guilib/GUIVideoControl.cpp | 12 | ||||
-rw-r--r-- | guilib/GUIVideoControl.h | 2 | ||||
-rw-r--r-- | guilib/GUIVisualisationControl.cpp | 12 | ||||
-rw-r--r-- | guilib/GUIVisualisationControl.h | 2 | ||||
-rw-r--r-- | guilib/GUIWindow.cpp | 23 |
11 files changed, 51 insertions, 58 deletions
diff --git a/guilib/GUIControl.cpp b/guilib/GUIControl.cpp index b573201568..e9611a2764 100644 --- a/guilib/GUIControl.cpp +++ b/guilib/GUIControl.cpp @@ -812,18 +812,12 @@ int CGUIControl::GetNextControl(int direction) const } } -// input the point with respect to this control to hit, and return -// the control and the point with respect to his control if we have a hit -bool CGUIControl::CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const +bool CGUIControl::CanFocusFromPoint(const CPoint &point, CPoint &controlPoint) const { controlPoint = point; m_transform.InverseTransformPosition(controlPoint.x, controlPoint.y); if (CanFocus() && HitTest(controlPoint)) - { - *control = (CGUIControl *)this; return true; - } - *control = NULL; return false; } diff --git a/guilib/GUIControl.h b/guilib/GUIControl.h index 6873da8971..6cc6783be4 100644 --- a/guilib/GUIControl.h +++ b/guilib/GUIControl.h @@ -132,9 +132,19 @@ public: virtual bool OnMouseWheel(char wheel, const CPoint &point) { return false; }; /// \brief Used to test whether the pointer location (fPosX, fPosY) is inside the control. For mouse events. virtual bool HitTest(const CPoint &point) const; - /// \brief Focus a control from a screen location. Returns the coordinates of the screen location relative to the control and a pointer to the control. - virtual bool CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const; - /// \brief Unfocus a control if it's not in a screen location. + + /*! \brief Test whether we can focus a control from a point on screen + \param point the location in skin coordinates from the upper left corner of the parent control. + \param controlPoint [OUT] the location in skin coordinates that will yield the given point on screen under this controls transformation + \return true if the control can be focused from this location + \sa UnfocusFromPoint + */ + virtual bool CanFocusFromPoint(const CPoint &point, CPoint &controlPoint) const; + + /*! \brief Unfocus the control if the given point on screen is not within it's boundary + \param point the location in skin coordinates from the upper left corner of the parent control. + \sa CanFocusFromPoint + */ virtual void UnfocusFromPoint(const CPoint &point); virtual bool OnMessage(CGUIMessage& message); diff --git a/guilib/GUIControlGroup.cpp b/guilib/GUIControlGroup.cpp index 3ddb3517d8..a87700169d 100644 --- a/guilib/GUIControlGroup.cpp +++ b/guilib/GUIControlGroup.cpp @@ -367,19 +367,22 @@ bool CGUIControlGroup::HitTest(const CPoint &point) const return false; } -bool CGUIControlGroup::CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const +void CGUIControlGroup::GetControlsFromPoint(const CPoint &point, vector< std::pair<CGUIControl *, CPoint> > &controls) const { - if (!CGUIControl::CanFocus()) return false; + if (!CGUIControl::CanFocus()) + return; CPoint controlCoords(point); m_transform.InverseTransformPosition(controlCoords.x, controlCoords.y); + controlCoords -= CPoint(m_posX, m_posY); for (crControls it = m_children.rbegin(); it != m_children.rend(); ++it) { CGUIControl *child = *it; - if (child->CanFocusFromPoint(controlCoords - CPoint(m_posX, m_posY), control, controlPoint)) - return true; + CPoint childCoords; + if (child->IsGroup()) + ((CGUIControlGroup *)child)->GetControlsFromPoint(controlCoords, controls); + else if (child->CanFocusFromPoint(controlCoords, childCoords)) + controls.push_back(make_pair(child, childCoords)); } - *control = NULL; - return false; } void CGUIControlGroup::UnfocusFromPoint(const CPoint &point) diff --git a/guilib/GUIControlGroup.h b/guilib/GUIControlGroup.h index 1567fe4b33..8fd14fcb8f 100644 --- a/guilib/GUIControlGroup.h +++ b/guilib/GUIControlGroup.h @@ -52,7 +52,7 @@ public: virtual bool CanFocus() const; virtual bool HitTest(const CPoint &point) const; - virtual bool CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const; + virtual void GetControlsFromPoint(const CPoint &point, std::vector< std::pair<CGUIControl *, CPoint> > &controls) const; virtual void UnfocusFromPoint(const CPoint &point); virtual void SetInitialVisibility(); diff --git a/guilib/GUIControlGroupList.cpp b/guilib/GUIControlGroupList.cpp index b339fa5da6..4670af2afc 100644 --- a/guilib/GUIControlGroupList.cpp +++ b/guilib/GUIControlGroupList.cpp @@ -311,30 +311,31 @@ void CGUIControlGroupList::ScrollTo(float offset) m_scrollSpeed = (m_scrollOffset - m_offset) / m_scrollTime; } -bool CGUIControlGroupList::CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const +void CGUIControlGroupList::GetControlsFromPoint(const CPoint &point, std::vector< std::pair<CGUIControl *, CPoint> > &controls) const { - if (!CGUIControl::CanFocus()) return false; + if (!CGUIControl::CanFocus()) return; float pos = 0; CPoint controlCoords(point); m_transform.InverseTransformPosition(controlCoords.x, controlCoords.y); float alignOffset = GetAlignOffset(); for (ciControls it = m_children.begin(); it != m_children.end(); ++it) { - const CGUIControl *child = *it; + CGUIControl *child = *it; if (child->IsVisible()) { if (pos + Size(child) > m_offset && pos < m_offset + Size()) { // we're on screen float offsetX = m_orientation == VERTICAL ? m_posX : m_posX + alignOffset + pos - m_offset; float offsetY = m_orientation == VERTICAL ? m_posY + alignOffset + pos - m_offset : m_posY; - if (child->CanFocusFromPoint(controlCoords - CPoint(offsetX, offsetY), control, controlPoint)) - return true; + CPoint childCoords; + if (child->IsGroup()) + ((CGUIControlGroup *)child)->GetControlsFromPoint(controlCoords - CPoint(offsetX, offsetY), controls); + else if (child->CanFocusFromPoint(controlCoords - CPoint(offsetX, offsetY), childCoords)) + controls.push_back(std::make_pair(child, childCoords)); } pos += Size(child) + m_itemGap; } } - *control = NULL; - return false; } void CGUIControlGroupList::UnfocusFromPoint(const CPoint &point) diff --git a/guilib/GUIControlGroupList.h b/guilib/GUIControlGroupList.h index 90ccc45569..bb34960ae8 100644 --- a/guilib/GUIControlGroupList.h +++ b/guilib/GUIControlGroupList.h @@ -41,7 +41,7 @@ public: virtual void Render(); virtual bool OnMessage(CGUIMessage& message); - virtual bool CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const; + virtual void GetControlsFromPoint(const CPoint &point, std::vector< std::pair<CGUIControl *, CPoint> > &controls) const; virtual void UnfocusFromPoint(const CPoint &point); virtual void AddControl(CGUIControl *control, int position = -1); diff --git a/guilib/GUIVideoControl.cpp b/guilib/GUIVideoControl.cpp index ff4616910c..f9e8c57818 100644 --- a/guilib/GUIVideoControl.cpp +++ b/guilib/GUIVideoControl.cpp @@ -92,7 +92,7 @@ bool CGUIVideoControl::OnMouseClick(int button, const CPoint &point) bool CGUIVideoControl::OnMouseOver(const CPoint &point) { - // unfocusable, so return true + // unfocusable, so return false CGUIControl::OnMouseOver(point); return false; } @@ -102,15 +102,9 @@ bool CGUIVideoControl::CanFocus() const return false; } -bool CGUIVideoControl::CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const +bool CGUIVideoControl::CanFocusFromPoint(const CPoint &point, CPoint &controlPoint) const { // mouse is allowed to focus this control, but it doesn't actually receive focus controlPoint = point; m_transform.InverseTransformPosition(controlPoint.x, controlPoint.y); - if (HitTest(controlPoint)) - { - *control = (CGUIControl *)this; - return true; - } - *control = NULL; - return false; + return HitTest(controlPoint); } diff --git a/guilib/GUIVideoControl.h b/guilib/GUIVideoControl.h index ef82527b66..0fffcb77e2 100644 --- a/guilib/GUIVideoControl.h +++ b/guilib/GUIVideoControl.h @@ -47,6 +47,6 @@ public: virtual bool OnMouseClick(int button, const CPoint &point); virtual bool OnMouseOver(const CPoint &point); virtual bool CanFocus() const; - virtual bool CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const; + virtual bool CanFocusFromPoint(const CPoint &point, CPoint &controlPoint) const; }; #endif diff --git a/guilib/GUIVisualisationControl.cpp b/guilib/GUIVisualisationControl.cpp index 3e388519a7..1ea4a4a1ab 100644 --- a/guilib/GUIVisualisationControl.cpp +++ b/guilib/GUIVisualisationControl.cpp @@ -466,7 +466,7 @@ CVisualisation *CGUIVisualisationControl::GetVisualisation() bool CGUIVisualisationControl::OnMouseOver(const CPoint &point) { - // unfocusable, so return true + // unfocusable, so return false CGUIControl::OnMouseOver(point); return false; } @@ -476,15 +476,9 @@ bool CGUIVisualisationControl::CanFocus() const return false; } -bool CGUIVisualisationControl::CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const +bool CGUIVisualisationControl::CanFocusFromPoint(const CPoint &point, CPoint &controlPoint) const { // mouse is allowed to focus this control, but it doesn't actually receive focus controlPoint = point; m_transform.InverseTransformPosition(controlPoint.x, controlPoint.y); - if (HitTest(controlPoint)) - { - *control = (CGUIControl *)this; - return true; - } - *control = NULL; - return false; + return HitTest(controlPoint); } diff --git a/guilib/GUIVisualisationControl.h b/guilib/GUIVisualisationControl.h index e9454a1225..b76ea5426f 100644 --- a/guilib/GUIVisualisationControl.h +++ b/guilib/GUIVisualisationControl.h @@ -64,7 +64,7 @@ public: virtual bool OnMessage(CGUIMessage& message); virtual bool OnMouseOver(const CPoint &point); virtual bool CanFocus() const; - virtual bool CanFocusFromPoint(const CPoint &point, CGUIControl **control, CPoint &controlPoint) const; + virtual bool CanFocusFromPoint(const CPoint &point, CPoint &controlPoint) const; CVisualisation *GetVisualisation(); private: diff --git a/guilib/GUIWindow.cpp b/guilib/GUIWindow.cpp index 9f84197c50..fb6830178b 100644 --- a/guilib/GUIWindow.cpp +++ b/guilib/GUIWindow.cpp @@ -397,21 +397,18 @@ bool CGUIWindow::OnMouseAction() CGUIControl *pControl = *i; pControl->UnfocusFromPoint(mousePoint); } - // and find which one is under the pointer - // go through in reverse order to make sure we start with the ones on top + // and find which ones are under the pointer + vector< pair<CGUIControl *, CPoint> > controls; + GetControlsFromPoint(mousePoint, controls); + bool controlUnderPointer(false); - for (vector<CGUIControl *>::reverse_iterator i = m_children.rbegin(); i != m_children.rend(); ++i) + for (vector< pair<CGUIControl *, CPoint> >::iterator i = controls.begin(); i != controls.end(); ++i) { - CGUIControl *pControl = *i; - CGUIControl *focusableControl = NULL; - CPoint controlPoint; - if (pControl->CanFocusFromPoint(mousePoint, &focusableControl, controlPoint)) - { - controlUnderPointer = focusableControl->OnMouseOver(controlPoint); - bHandled = HandleMouse(focusableControl, controlPoint); - if (bHandled || controlUnderPointer) - break; - } + CGUIControl *child = i->first; + controlUnderPointer = child->OnMouseOver(i->second); + bHandled = HandleMouse(child, i->second); + if (bHandled || controlUnderPointer) + break; } if (!bHandled) { // haven't handled this action - call the window message handlers |