Bug 303048: GTK scrollbar does not have normal GTK right-click behavior, patch by Adam Guthrie <ispiked@gmail.com>, r=neil, sr=roc

This commit is contained in:
gavin%gavinsharp.com 2006-07-18 17:01:40 +00:00
Родитель 67f3db491c
Коммит b3d292772f
7 изменённых файлов: 168 добавлений и 66 удалений

Просмотреть файл

@ -238,6 +238,7 @@ GK_ATOM(decimalFormat, "decimal-format")
GK_ATOM(decimalSeparator, "decimal-separator")
GK_ATOM(deck, "deck")
GK_ATOM(declare, "declare")
GK_ATOM(decrement, "decrement")
GK_ATOM(_default, "default")
GK_ATOM(headerDefaultStyle, "default-style")
GK_ATOM(defaultAction, "defaultAction")

Просмотреть файл

@ -55,6 +55,7 @@
#include "nsIScrollbarMediator.h"
#include "nsRepeatService.h"
#include "nsGUIEvent.h"
#include "nsILookAndFeel.h"
//
// NS_NewToolbarFrame
@ -85,21 +86,106 @@ nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
nsEventStatus* aEventStatus)
{
// XXX hack until handle release is actually called in nsframe.
if (aEvent->message == NS_MOUSE_EXIT_SYNTH|| aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
if (aEvent->message == NS_MOUSE_EXIT_SYNTH ||
aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP ||
aEvent->message == NS_MOUSE_LEFT_BUTTON_UP ||
aEvent->message == NS_MOUSE_MIDDLE_BUTTON_UP)
HandleRelease(aPresContext, aEvent, aEventStatus);
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
// if we didn't handle the press ourselves, pass it on to the superclass
if (!HandleButtonPress(aPresContext, aEvent, aEventStatus))
return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
}
NS_IMETHODIMP
nsScrollbarButtonFrame::HandlePress(nsPresContext* aPresContext,
PRBool
nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
MouseClicked();
nsRepeatService::GetInstance()->Start(this);
return NS_OK;
// Get the desired action for the scrollbar button.
nsILookAndFeel::nsMetricID tmpAction;
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN)
tmpAction = nsILookAndFeel::eMetric_ScrollButtonLeftMouseButtonAction;
else if (aEvent->message == NS_MOUSE_MIDDLE_BUTTON_DOWN)
tmpAction = nsILookAndFeel::eMetric_ScrollButtonMiddleMouseButtonAction;
else if (aEvent->message == NS_MOUSE_RIGHT_BUTTON_DOWN)
tmpAction = nsILookAndFeel::eMetric_ScrollButtonRightMouseButtonAction;
else
return PR_FALSE;
// Get the button action metric from the pres. shell.
PRInt32 pressedButtonAction;
if (NS_FAILED(aPresContext->LookAndFeel()->GetMetric(tmpAction,
pressedButtonAction)))
return PR_FALSE;
// get the scrollbar control
nsIFrame* scrollbar;
GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar);
if (scrollbar == nsnull)
return PR_FALSE;
// get the scrollbars content node
nsIContent* content = scrollbar->GetContent();
static nsIContent::AttrValuesArray strings[] = { &nsXULAtoms::increment,
&nsXULAtoms::decrement,
nsnull };
PRInt32 index = mContent->FindAttrValueIn(kNameSpaceID_None,
nsHTMLAtoms::type,
strings, eCaseMatters);
PRInt32 direction;
if (index == 0)
direction = 1;
else if (index == 1)
direction = -1;
else
return PR_FALSE;
// Whether or not to repeat the click action.
PRBool repeat = PR_TRUE;
// Use smooth scrolling by default.
PRBool smoothScroll = PR_TRUE;
switch (pressedButtonAction) {
case 0:
#ifdef MOZ_WIDGET_COCOA
// Emulate the Mac IE behavior of scrolling 2 lines instead of 1
// on a button press. This makes scrolling appear smoother and
// keeps us competitive with IE.
mIncrement = direction * nsSliderFrame::GetIncrement(content) * 2;
#else
mIncrement = direction * nsSliderFrame::GetIncrement(content);
#endif
break;
case 1:
mIncrement = direction * nsSliderFrame::GetPageIncrement(content);
break;
case 2:
if (direction == -1)
mIncrement = -nsSliderFrame::GetCurrentPosition(content);
else
mIncrement = nsSliderFrame::GetMaxPosition(content) -
nsSliderFrame::GetCurrentPosition(content);
// Don't repeat or use smooth scrolling if scrolling to beginning or end
// of a page.
repeat = smoothScroll = PR_FALSE;
break;
case 3:
default:
// We were told to ignore this click, or someone assigned a non-standard
// value to the button's action.
return PR_FALSE;
break;
}
// set this attribute so we can style it later
mContent->SetAttr(kNameSpaceID_None, nsXULAtoms::active, NS_LITERAL_STRING("true"), PR_TRUE);
DoButtonAction(smoothScroll);
if (repeat)
nsRepeatService::GetInstance()->Start(this);
return PR_TRUE;
}
NS_IMETHODIMP
@ -107,6 +193,8 @@ nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
// we're not active anymore
mContent->UnsetAttr(kNameSpaceID_None, nsXULAtoms::active, PR_TRUE);
nsRepeatService::GetInstance()->Stop();
return NS_OK;
}
@ -114,7 +202,9 @@ nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
NS_IMETHODIMP nsScrollbarButtonFrame::Notify(nsITimer *timer)
{
MouseClicked();
// Since this is only going to get called if we're scrolling a page length
// or a line increment, we will always use smooth scrolling.
DoButtonAction(PR_TRUE);
return NS_OK;
}
@ -126,71 +216,54 @@ nsScrollbarButtonFrame::MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aE
}
void
nsScrollbarButtonFrame::MouseClicked()
nsScrollbarButtonFrame::DoButtonAction(PRBool aSmoothScroll)
{
// when we are clicked either increment or decrement the slider position.
// get the scrollbar control
nsIFrame* scrollbar;
GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar);
// get the scrollbar control
nsIFrame* scrollbar;
GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar);
if (scrollbar == nsnull)
return;
if (scrollbar == nsnull)
return;
// get the scrollbars content node
nsIContent* content = scrollbar->GetContent();
// get the scrollbars content node
nsIContent* content = scrollbar->GetContent();
// get the current pos
PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
PRInt32 oldpos = curpos;
// get the current pos
PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
PRInt32 oldpos = curpos;
// get the max pos
PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);
// get the max pos
PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);
// increment the given amount
if (mIncrement)
curpos += mIncrement;
// get the increment amount
PRInt32 increment = nsSliderFrame::GetIncrement(content);
#ifdef MOZ_WIDGET_COCOA
// Emulate the Mac IE behavior of scrolling 2 lines instead of 1
// on a button press. This makes scrolling appear smoother and
// keeps us competitive with IE.
increment *= 2;
#endif
// make sure the current position is between the current and max positions
if (curpos < 0)
curpos = 0;
else if (curpos > maxpos)
curpos = maxpos;
nsString value;
mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type, value);
if (!value.IsEmpty())
{
// if our class is DecrementButton subtract the current pos by increment amount
// if our class is IncrementButton increment the current pos by the decrement amount
if (value.EqualsLiteral("decrement"))
curpos -= increment;
else if (value.EqualsLiteral("increment"))
curpos += increment;
// make sure the current position is between the current and max positions
if (curpos < 0)
curpos = 0;
else if (curpos > maxpos)
curpos = maxpos;
nsCOMPtr<nsIScrollbarFrame> sb(do_QueryInterface(scrollbar));
if (sb) {
nsCOMPtr<nsIScrollbarMediator> m;
sb->GetScrollbarMediator(getter_AddRefs(m));
if (m) {
m->ScrollbarButtonPressed(sb, oldpos, curpos);
return;
}
nsCOMPtr<nsIScrollbarFrame> sb(do_QueryInterface(scrollbar));
if (sb) {
nsCOMPtr<nsIScrollbarMediator> m;
sb->GetScrollbarMediator(getter_AddRefs(m));
if (m) {
m->ScrollbarButtonPressed(sb, oldpos, curpos);
return;
}
// set the current position of the slider.
nsAutoString curposStr;
curposStr.AppendInt(curpos);
content->SetAttr(kNameSpaceID_None, nsXULAtoms::smooth, NS_LITERAL_STRING("true"), PR_FALSE);
content->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curposStr, PR_TRUE);
content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::smooth, PR_FALSE);
}
// set the current position of the slider.
nsAutoString curposStr;
curposStr.AppendInt(curpos);
if (aSmoothScroll)
content->SetAttr(kNameSpaceID_None, nsXULAtoms::smooth, NS_LITERAL_STRING("true"), PR_FALSE);
content->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curposStr, PR_TRUE);
if (aSmoothScroll)
content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::smooth, PR_FALSE);
}
nsresult

Просмотреть файл

@ -60,7 +60,7 @@ public:
// Overrides
virtual void Destroy();
friend nsIFrame* NS_NewScrollBarButtonFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
friend nsIFrame* NS_NewScrollbarButtonFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* aEvent,
@ -70,7 +70,7 @@ public:
nsIAtom* atom, nsIFrame* start, nsIFrame*& result);
static nsresult GetParentWithTag(nsIAtom* atom, nsIFrame* start, nsIFrame*& result);
NS_IMETHOD HandlePress(nsPresContext* aPresContext,
PRBool HandleButtonPress(nsPresContext* aPresContext,
nsGUIEvent * aEvent,
nsEventStatus* aEventStatus);
@ -95,7 +95,8 @@ public:
protected:
virtual void MouseClicked(nsPresContext* aPresContext, nsGUIEvent* aEvent);
virtual void MouseClicked();
void DoButtonAction(PRBool aSmoothScroll);
PRInt32 mIncrement;
}; // class nsTabFrame

Просмотреть файл

@ -492,6 +492,15 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_ScrollSliderStyle:
aMetric = eMetric_ScrollThumbStyleProportional;
break;
case eMetric_ScrollButtonLeftMouseButtonAction:
aMetric = 0;
break;
case eMetric_ScrollButtonMiddleMouseButtonAction:
aMetric = 1;
break;
case eMetric_ScrollButtonRightMouseButtonAction:
aMetric = 2;
break;
case eMetric_TreeOpenDelay:
aMetric = 1000;
break;

Просмотреть файл

@ -250,6 +250,17 @@ nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame,
aState->maxpos = CheckIntAttr(tmpFrame, nsWidgetAtoms::maxpos);
}
// In order to simulate native GTK scrollbar click behavior, we set the
// active attribute on the element to true if it's pressed with any mouse
// button. This allows us to show that it's active without setting :active
if (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_UP ||
aWidgetType == NS_THEME_SCROLLBAR_BUTTON_DOWN ||
aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT ||
aWidgetType == NS_THEME_SCROLLBAR_BUTTON_RIGHT) {
if (CheckBooleanAttr(aFrame, nsWidgetAtoms::active))
aState->active = PR_TRUE;
}
// menu item state is determined by the attribute "_moz-menuactive",
// and not by the mouse hovering (accessibility). as a special case,
// menus which are children of a menu bar are only marked as prelight

Просмотреть файл

@ -55,6 +55,7 @@
******/
WIDGET_ATOM(accesskey, "accesskey") // The shortcut key for a menu or menu item
WIDGET_ATOM(active, "active")
WIDGET_ATOM(ascending, "ascending")
WIDGET_ATOM(autocheck, "autocheck")
WIDGET_ATOM(checkbox, "checkbox")

Просмотреть файл

@ -106,6 +106,12 @@ nsLookAndFeelIntPref nsXPLookAndFeel::sIntPrefs[] =
eMetric_TreeScrollLinesMax, PR_FALSE, nsLookAndFeelTypeInt, 0 },
{ "accessibility.tabfocus",
eMetric_TabFocusModel, PR_FALSE, nsLookAndFeelTypeInt, 0 },
{ "ui.scrollbarButtonLeftMouseButtonAction",
eMetric_ScrollButtonLeftMouseButtonAction, PR_FALSE, nsLookAndFeelTypeInt, 0 },
{ "ui.scrollbarButtonMiddleMouseButtonAction",
eMetric_ScrollButtonMiddleMouseButtonAction, PR_FALSE, nsLookAndFeelTypeInt, 3 },
{ "ui.scrollbarButtonRightMouseButtonAction",
eMetric_ScrollButtonRightMouseButtonAction, PR_FALSE, nsLookAndFeelTypeInt, 3 },
};
nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] =