Better mouse input handling
This commit is contained in:
@@ -71,10 +71,10 @@ namespace OpenRA
|
|||||||
public int2 lastMousePos;
|
public int2 lastMousePos;
|
||||||
public bool HandleInput(World world, MouseInput mi)
|
public bool HandleInput(World world, MouseInput mi)
|
||||||
{
|
{
|
||||||
if (selectedWidget != null && selectedWidget.HandleInput(mi))
|
if (selectedWidget != null && selectedWidget.HandleMouseInputOuter(mi))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (rootWidget.HandleInput(mi))
|
if (rootWidget.HandleMouseInputOuter(mi))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (mi.Event == MouseInputEvent.Move)
|
if (mi.Event == MouseInputEvent.Move)
|
||||||
@@ -89,9 +89,9 @@ namespace OpenRA
|
|||||||
public bool HandleKeyPress(System.Windows.Forms.KeyPressEventArgs e, Modifiers modifiers)
|
public bool HandleKeyPress(System.Windows.Forms.KeyPressEventArgs e, Modifiers modifiers)
|
||||||
{
|
{
|
||||||
if (selectedWidget != null)
|
if (selectedWidget != null)
|
||||||
return selectedWidget.HandleKeyPress(e, modifiers);
|
return selectedWidget.HandleKeyPressOuter(e, modifiers);
|
||||||
|
|
||||||
if (rootWidget.HandleKeyPress(e, modifiers))
|
if (rootWidget.HandleKeyPressOuter(e, modifiers))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,26 +149,17 @@ namespace OpenRA.Widgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleInput(MouseInput mi)
|
public override bool HandleInput(MouseInput mi)
|
||||||
{
|
{
|
||||||
// Are we able to handle this event?
|
if (mi.Event != MouseInputEvent.Down)
|
||||||
if (!IsVisible() || !GetEventBounds().Contains(mi.Location.X,mi.Location.Y))
|
return false;
|
||||||
return base.HandleInput(mi);
|
|
||||||
|
|
||||||
if (base.HandleInput(mi))
|
var action = buttons.Where(a => a.First.Contains(mi.Location.ToPoint()))
|
||||||
return true;
|
.Select(a => a.Second).FirstOrDefault();
|
||||||
|
if (action == null)
|
||||||
if (mi.Event == MouseInputEvent.Down)
|
return false;
|
||||||
{
|
|
||||||
var action = buttons.Where(a => a.First.Contains(mi.Location.ToPoint()))
|
action(mi);
|
||||||
.Select(a => a.Second).FirstOrDefault();
|
return true;
|
||||||
if (action == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
action(mi);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawInner(World world)
|
public override void DrawInner(World world)
|
||||||
|
|||||||
@@ -46,38 +46,30 @@ namespace OpenRA.Widgets
|
|||||||
GetText = (widget as ButtonWidget).GetText;
|
GetText = (widget as ButtonWidget).GetText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleInput(MouseInput mi)
|
public override bool LoseFocus (MouseInput mi)
|
||||||
{
|
{
|
||||||
if (Chrome.selectedWidget == this)
|
Depressed = false;
|
||||||
Depressed = (GetEventBounds().Contains(mi.Location.X,mi.Location.Y)) ? true : false;
|
return base.LoseFocus(mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool HandleInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Event == MouseInputEvent.Down && !TakeFocus(mi))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Relinquish focus
|
// Only fire the onMouseUp order if we successfully lost focus, and were pressed
|
||||||
if (Chrome.selectedWidget == this && mi.Event == MouseInputEvent.Up)
|
if (Focused && mi.Event == MouseInputEvent.Up)
|
||||||
{
|
{
|
||||||
Chrome.selectedWidget = null;
|
var wasPressed = Depressed;
|
||||||
Depressed = false;
|
return (LoseFocus(mi) && wasPressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we able to handle this event?
|
|
||||||
if (!Visible || !GetEventBounds().Contains(mi.Location.X,mi.Location.Y))
|
|
||||||
return base.HandleInput(mi);
|
|
||||||
|
|
||||||
|
|
||||||
if (base.HandleInput(mi))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Give button focus only while the mouse is down
|
|
||||||
// This is a bit of a hack: it will become cleaner soonish
|
|
||||||
// It will also steal events from any potential children
|
|
||||||
// We also want to play a click sound
|
|
||||||
if (mi.Event == MouseInputEvent.Down)
|
if (mi.Event == MouseInputEvent.Down)
|
||||||
{
|
|
||||||
Chrome.selectedWidget = this;
|
|
||||||
Depressed = true;
|
Depressed = true;
|
||||||
return true;
|
else if (mi.Event == MouseInputEvent.Move && Focused)
|
||||||
}
|
Depressed = RenderBounds.Contains(mi.Location.X,mi.Location.Y);
|
||||||
|
|
||||||
return false;
|
return Depressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawInner(World world)
|
public override void DrawInner(World world)
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ namespace OpenRA.Widgets
|
|||||||
Game.chrome.lineRenderer.Flush();
|
Game.chrome.lineRenderer.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public override bool HandleInput(MouseInput mi) { return true; }
|
||||||
|
|
||||||
public CheckboxWidget() : base() { }
|
public CheckboxWidget() : base() { }
|
||||||
|
|
||||||
|
|||||||
@@ -88,40 +88,27 @@ namespace OpenRA.Widgets
|
|||||||
if (DownPressed) ListOffset -= ScrollVelocity;
|
if (DownPressed) ListOffset -= ScrollVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleInput(MouseInput mi)
|
public override bool LoseFocus (MouseInput mi)
|
||||||
{
|
{
|
||||||
if (Chrome.selectedWidget == this)
|
UpPressed = DownPressed = false;
|
||||||
{
|
return base.LoseFocus(mi);
|
||||||
UpPressed = upButtonRect.Contains(mi.Location.X,mi.Location.Y);
|
}
|
||||||
DownPressed = downButtonRect.Contains(mi.Location.X,mi.Location.Y);
|
|
||||||
}
|
public override bool HandleInput(MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Event == MouseInputEvent.Down && !TakeFocus(mi))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Relinquish focus
|
if (!Focused)
|
||||||
if (Chrome.selectedWidget == this && mi.Event == MouseInputEvent.Up)
|
return false;
|
||||||
{
|
|
||||||
Chrome.selectedWidget = null;
|
UpPressed = upButtonRect.Contains(mi.Location.X,mi.Location.Y);
|
||||||
UpPressed = DownPressed = false;
|
DownPressed = downButtonRect.Contains(mi.Location.X,mi.Location.Y);
|
||||||
}
|
|
||||||
|
|
||||||
// Are we able to handle this event?
|
if (Focused && mi.Event == MouseInputEvent.Up)
|
||||||
if (!Visible || !GetEventBounds().Contains(mi.Location.X,mi.Location.Y))
|
LoseFocus(mi);
|
||||||
return base.HandleInput(mi);
|
|
||||||
|
|
||||||
|
return (UpPressed || DownPressed);
|
||||||
if (base.HandleInput(mi))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Give button focus only while the mouse is down
|
|
||||||
// This is a bit of a hack: it will become cleaner soonish
|
|
||||||
// It will also steal events from any potential children
|
|
||||||
// We also want to play a click sound
|
|
||||||
if (mi.Event == MouseInputEvent.Down)
|
|
||||||
{
|
|
||||||
Chrome.selectedWidget = this;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Widget Clone() { return new ListBoxWidget(this); }
|
public override Widget Clone() { return new ListBoxWidget(this); }
|
||||||
|
|||||||
@@ -137,13 +137,6 @@ namespace OpenRA.Widgets
|
|||||||
|
|
||||||
public override bool HandleInput(MouseInput mi)
|
public override bool HandleInput(MouseInput mi)
|
||||||
{
|
{
|
||||||
// Are we able to handle this event?
|
|
||||||
if (!Visible || !GetEventBounds().Contains(mi.Location.X, mi.Location.Y))
|
|
||||||
return base.HandleInput(mi);
|
|
||||||
|
|
||||||
if (base.HandleInput(mi))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (mi.Event == MouseInputEvent.Down)
|
if (mi.Event == MouseInputEvent.Down)
|
||||||
{
|
{
|
||||||
var action = buttons.Where(a => a.First.Contains(mi.Location.ToPoint()))
|
var action = buttons.Where(a => a.First.Contains(mi.Location.ToPoint()))
|
||||||
|
|||||||
@@ -63,9 +63,7 @@ namespace OpenRA.Widgets
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleInput(MouseInput mi)
|
public override bool HandleInput(MouseInput mi)
|
||||||
{
|
{
|
||||||
if (!IsVisible()) return false;
|
|
||||||
|
|
||||||
if (mi.Event == MouseInputEvent.Down)
|
if (mi.Event == MouseInputEvent.Down)
|
||||||
{
|
{
|
||||||
var action = buttons.Where(a => a.First.Contains(mi.Location.ToPoint()))
|
var action = buttons.Where(a => a.First.Contains(mi.Location.ToPoint()))
|
||||||
|
|||||||
@@ -46,47 +46,33 @@ namespace OpenRA.Widgets
|
|||||||
Bold = (widget as TextFieldWidget).Bold;
|
Bold = (widget as TextFieldWidget).Bold;
|
||||||
VisualHeight = (widget as TextFieldWidget).VisualHeight;
|
VisualHeight = (widget as TextFieldWidget).VisualHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool LoseFocus(MouseInput mi)
|
||||||
|
{
|
||||||
|
OnLoseFocus();
|
||||||
|
var lose = base.LoseFocus(mi);
|
||||||
|
System.Console.WriteLine("{1} asked to lose focus; returning {0}",lose, this.Id);
|
||||||
|
return lose;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool HandleInput(MouseInput mi)
|
public override bool HandleInput(MouseInput mi)
|
||||||
{
|
{
|
||||||
// We get this first if we are focussed; if the click was somewhere else remove focus
|
// Lose focus if they click outside the box; return false so the next widget can grab this event
|
||||||
if (Chrome.selectedWidget == this && mi.Event == MouseInputEvent.Down && !GetEventBounds().Contains(mi.Location.X,mi.Location.Y))
|
if (mi.Event == MouseInputEvent.Down && !RenderBounds.Contains(mi.Location.X,mi.Location.Y) && LoseFocus(mi))
|
||||||
{
|
|
||||||
OnLoseFocus();
|
|
||||||
Chrome.selectedWidget = null;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Are we able to handle this event?
|
|
||||||
if (!Visible || !GetEventBounds().Contains(mi.Location.X,mi.Location.Y))
|
|
||||||
return base.HandleInput(mi);
|
|
||||||
|
|
||||||
if (base.HandleInput(mi))
|
if (mi.Event == MouseInputEvent.Down && !TakeFocus(mi))
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
if (mi.Event == MouseInputEvent.Down)
|
|
||||||
{
|
|
||||||
Focus();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Focus()
|
|
||||||
{
|
|
||||||
Chrome.selectedWidget = this;
|
|
||||||
blinkCycle = 10;
|
blinkCycle = 10;
|
||||||
showCursor = true;
|
showCursor = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleKeyPress(System.Windows.Forms.KeyPressEventArgs e, Modifiers modifiers)
|
public override bool HandleKeyPress(System.Windows.Forms.KeyPressEventArgs e, Modifiers modifiers)
|
||||||
{
|
{
|
||||||
if (base.HandleKeyPress(e,modifiers))
|
// Only take input if we are focused
|
||||||
return true;
|
if (!Focused)
|
||||||
|
|
||||||
// Only take input if we are selected
|
|
||||||
if (Chrome.selectedWidget != this)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (e.KeyChar == '\r' && OnEnterKey())
|
if (e.KeyChar == '\r' && OnEnterKey())
|
||||||
@@ -131,7 +117,7 @@ namespace OpenRA.Widgets
|
|||||||
{
|
{
|
||||||
int margin = 5;
|
int margin = 5;
|
||||||
var font = (Bold) ? Game.chrome.renderer.BoldFont : Game.chrome.renderer.RegularFont;
|
var font = (Bold) ? Game.chrome.renderer.BoldFont : Game.chrome.renderer.RegularFont;
|
||||||
var cursor = (showCursor && Chrome.selectedWidget == this) ? "|" : "";
|
var cursor = (showCursor && Focused) ? "|" : "";
|
||||||
var textSize = font.Measure(Text + "|");
|
var textSize = font.Measure(Text + "|");
|
||||||
var pos = RenderOrigin;
|
var pos = RenderOrigin;
|
||||||
|
|
||||||
@@ -144,7 +130,7 @@ namespace OpenRA.Widgets
|
|||||||
// Right align when editing and scissor when the text overflows
|
// Right align when editing and scissor when the text overflows
|
||||||
if (textSize.X > Bounds.Width - 2*margin)
|
if (textSize.X > Bounds.Width - 2*margin)
|
||||||
{
|
{
|
||||||
if (Chrome.selectedWidget == this)
|
if (Focused)
|
||||||
textPos += new int2(Bounds.Width - 2*margin - textSize.X,0);
|
textPos += new int2(Bounds.Width - 2*margin - textSize.X,0);
|
||||||
|
|
||||||
Game.chrome.renderer.Device.EnableScissor(pos.X + margin, pos.Y, Bounds.Width - 2*margin, Bounds.Bottom);
|
Game.chrome.renderer.Device.EnableScissor(pos.X + margin, pos.Y, Bounds.Width - 2*margin, Bounds.Bottom);
|
||||||
|
|||||||
@@ -150,34 +150,73 @@ namespace OpenRA.Widgets
|
|||||||
.Select(c => c.GetEventBounds())
|
.Select(c => c.GetEventBounds())
|
||||||
.Aggregate(RenderBounds, Rectangle.Union);
|
.Aggregate(RenderBounds, Rectangle.Union);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool HandleInput(MouseInput mi)
|
|
||||||
|
public bool Focused { get { return Chrome.selectedWidget == this; } }
|
||||||
|
public virtual bool TakeFocus(MouseInput mi)
|
||||||
|
{
|
||||||
|
if (Focused)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (Chrome.selectedWidget != null && !Chrome.selectedWidget.LoseFocus(mi))
|
||||||
|
return false;
|
||||||
|
Chrome.selectedWidget = this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove focus from this widget; return false if you don't want to give it up
|
||||||
|
public virtual bool LoseFocus(MouseInput mi)
|
||||||
|
{
|
||||||
|
if (Chrome.selectedWidget == this)
|
||||||
|
Chrome.selectedWidget = null;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool HandleInput(MouseInput mi) { return false; }
|
||||||
|
public bool HandleMouseInputOuter(MouseInput mi)
|
||||||
{
|
{
|
||||||
// Are we able to handle this event?
|
// Are we able to handle this event?
|
||||||
if (!IsVisible() || !GetEventBounds().Contains(mi.Location.X,mi.Location.Y))
|
if (!(Focused || (IsVisible() && GetEventBounds().Contains(mi.Location.X,mi.Location.Y))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Send the event to the deepest children first and bubble up if unhandled
|
||||||
|
foreach (var child in Children)
|
||||||
|
if (child.HandleMouseInputOuter(mi))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Do any widgety behavior (button click etc)
|
||||||
|
// Return false if it can't handle any user actions
|
||||||
|
if (!HandleInput(mi))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Apply any special logic added by delegates; they return true if they caught the input
|
||||||
|
if (mi.Event == MouseInputEvent.Down && OnMouseDown(mi)) return true;
|
||||||
|
if (mi.Event == MouseInputEvent.Up && OnMouseUp(mi)) return true;
|
||||||
|
if (mi.Event == MouseInputEvent.Move && OnMouseMove(mi)) return true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual bool HandleKeyPress(System.Windows.Forms.KeyPressEventArgs e, Modifiers modifiers) { return false; }
|
||||||
|
public virtual bool HandleKeyPressOuter(System.Windows.Forms.KeyPressEventArgs e, Modifiers modifiers)
|
||||||
|
{
|
||||||
|
if (!IsVisible())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Can any of our children handle this?
|
// Can any of our children handle this?
|
||||||
foreach (var child in Children)
|
foreach (var child in Children)
|
||||||
if (child.HandleInput(mi))
|
if (child.HandleKeyPressOuter(e, modifiers))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (mi.Event == MouseInputEvent.Down) return OnMouseDown(mi);
|
// Do any widgety behavior (enter text etc)
|
||||||
if (mi.Event == MouseInputEvent.Up) return OnMouseUp(mi);
|
var handled = HandleKeyPress(e,modifiers);
|
||||||
if (mi.Event == MouseInputEvent.Move) return OnMouseMove(mi);
|
|
||||||
|
// Apply any special logic added by delegates; they return true if they caught the input
|
||||||
throw new InvalidOperationException("Impossible");
|
if (OnKeyPress(e,modifiers)) return true;
|
||||||
}
|
|
||||||
|
return handled;
|
||||||
public virtual bool HandleKeyPress(System.Windows.Forms.KeyPressEventArgs e, Modifiers modifiers)
|
|
||||||
{
|
|
||||||
// Can any of our children handle this?
|
|
||||||
foreach (var child in Children)
|
|
||||||
if (child.HandleKeyPress(e, modifiers))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Have we been assigned an action?
|
|
||||||
return OnKeyPress(e,modifiers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void DrawInner( World world );
|
public abstract void DrawInner( World world );
|
||||||
|
|||||||
Reference in New Issue
Block a user