Skip to content

Commit

Permalink
Improves keyboard focus management.
Browse files Browse the repository at this point in the history
Also improves some text field behavior.
  • Loading branch information
deniz1a committed May 10, 2015
1 parent 4b50f34 commit 722b726
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 36 deletions.
2 changes: 1 addition & 1 deletion OpenRA.Game/Game.cs
Expand Up @@ -162,7 +162,7 @@ internal static void StartGame(string mapUID, WorldType type)
return;

Ui.MouseFocusWidget = null;
Ui.KeyboardFocusWidget = null;
Ui.ResetKeyboardFocus();

OrderManager.LocalFrameNumber = 0;
OrderManager.LastTickTime = RunTime;
Expand Down
52 changes: 40 additions & 12 deletions OpenRA.Game/Widgets/Widget.cs
Expand Up @@ -24,9 +24,9 @@ public static class Ui
public static int LastTickTime = Game.RunTime;

static readonly Stack<Widget> WindowList = new Stack<Widget>();
static readonly Stack<Widget> KeyboardFocusList = new Stack<Widget>();

public static Widget MouseFocusWidget;
public static Widget KeyboardFocusWidget;
public static Widget MouseOverWidget;

public static void CloseWindow()
Expand Down Expand Up @@ -110,20 +110,39 @@ public static bool HandleInput(MouseInput mi)

public static bool HandleKeyPress(KeyInput e)
{
if (KeyboardFocusWidget != null)
return KeyboardFocusWidget.HandleKeyPressOuter(e);
if (KeyboardFocusList.Count > 0 && KeyboardFocusList.Peek() != null)
return KeyboardFocusList.Peek().HandleKeyPressOuter(e);

return Root.HandleKeyPressOuter(e);
}

public static bool HandleTextInput(string text)
{
if (KeyboardFocusWidget != null)
return KeyboardFocusWidget.HandleTextInputOuter(text);
if (KeyboardFocusList.Count > 0 && KeyboardFocusList.Peek() != null)
return KeyboardFocusList.Peek().HandleTextInputOuter(text);

return Root.HandleTextInputOuter(text);
}

public static void AddKeyboardFocus(Widget w) { KeyboardFocusList.Push(w); }
public static void RemoveKeyboardFocus() { KeyboardFocusList.Pop(); }
public static void ResetKeyboardFocus() { KeyboardFocusList.Clear(); }
public static bool HasKeyboardFocus(Widget w)
{
if (KeyboardFocusList.Count == 0)
return false;

return KeyboardFocusList.Peek() == w;
}

public static Widget GetCurrentKeyboardFocus()
{
if (KeyboardFocusList.Count == 0)
return null;

return KeyboardFocusList.Peek();
}

public static void ResetAll()
{
Root.RemoveChildren();
Expand Down Expand Up @@ -255,7 +274,7 @@ public virtual Rectangle GetEventBounds()
}

public bool HasMouseFocus { get { return Ui.MouseFocusWidget == this; } }
public bool HasKeyboardFocus { get { return Ui.KeyboardFocusWidget == this; } }
public bool HasKeyboardFocus { get { return Ui.HasKeyboardFocus(this); } }

public virtual bool TakeMouseFocus(MouseInput mi)
{
Expand Down Expand Up @@ -289,25 +308,34 @@ public virtual bool TakeKeyboardFocus()
if (HasKeyboardFocus)
return true;

if (Ui.KeyboardFocusWidget != null && !Ui.KeyboardFocusWidget.YieldKeyboardFocus())
var k = Ui.GetCurrentKeyboardFocus();
if (k != null && !k.TryYieldKeyboardFocus())
return false;

Ui.KeyboardFocusWidget = this;
Ui.AddKeyboardFocus(this);
return true;
}

public virtual bool TryYieldKeyboardFocus()
{
return true;
}

public virtual bool YieldKeyboardFocus()
{
if (Ui.KeyboardFocusWidget == this)
Ui.KeyboardFocusWidget = null;
if (!TryYieldKeyboardFocus())
return false;

if (Ui.GetCurrentKeyboardFocus() == this)
Ui.RemoveKeyboardFocus();

return true;
}

void ForceYieldKeyboardFocus()
{
if (Ui.KeyboardFocusWidget == this && !YieldKeyboardFocus())
Ui.KeyboardFocusWidget = null;
if (Ui.GetCurrentKeyboardFocus() == this && !YieldKeyboardFocus())
Ui.RemoveKeyboardFocus();
}

public virtual string GetCursor(int2 pos) { return "default"; }
Expand Down
9 changes: 7 additions & 2 deletions OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs
Expand Up @@ -109,9 +109,14 @@ public AssetBrowserLogic(Widget widget, Action onExit, World world)
}

filenameInput = panel.Get<TextFieldWidget>("FILENAME_INPUT");
filenameInput.TakeKeyboardFocus();
filenameInput.OnTextEdited = () => ApplyFilter(filenameInput.Text);
filenameInput.OnEscKey = filenameInput.YieldKeyboardFocus;

filenameInput.OnEscKey = () =>
{
filenameInput.Text = null;
filenameInput.OnTextEdited();
return true;
};
var frameContainer = panel.GetOrNull("FRAME_SELECTOR");
if (frameContainer != null)
frameContainer.IsVisible = () => (currentSprites != null && currentSprites.Length > 1) ||
Expand Down
3 changes: 1 addition & 2 deletions OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs
Expand Up @@ -517,9 +517,7 @@ void CloseWindow()

chatLabel = lobby.Get<LabelWidget>("LABEL_CHATTYPE");
var chatTextField = lobby.Get<TextFieldWidget>("CHAT_TEXTFIELD");

chatTextField.TakeKeyboardFocus();

chatTextField.OnEnterKey = () =>
{
if (chatTextField.Text.Length == 0)
Expand All @@ -543,6 +541,7 @@ void CloseWindow()
else
return true;
};
chatTextField.OnEscKey = () => { chatTextField.Text = null; return true; };

chatPanel = lobby.Get<ScrollPanelWidget>("CHAT_DISPLAY");
chatTemplate = chatPanel.Get("CHAT_TEMPLATE");
Expand Down
24 changes: 15 additions & 9 deletions OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs
Expand Up @@ -272,21 +272,27 @@ public static void SetupEditableNameWidget(Widget parent, Session.Slot s, Sessio
name.IsDisabled = () => orderManager.LocalClient.IsReady;

name.Text = c.Name;
name.OnLoseFocus = () =>
name.OnEscKey = () =>
{
name.Text = c.Name;
name.YieldKeyboardFocus();
return true;
};
name.OnEnterKey = () =>
{
name.Text = name.Text.Trim();
if (name.Text.Length == 0)
name.Text = c.Name;
else if (name.Text != c.Name)
{
orderManager.IssueOrder(Order.Command("name " + name.Text));
Game.Settings.Player.Name = name.Text;
Game.Settings.Save();
}
if (name.Text == c.Name)
return;
orderManager.IssueOrder(Order.Command("name " + name.Text));
Game.Settings.Player.Name = name.Text;
Game.Settings.Save();
name.YieldKeyboardFocus();
return true;
};

name.OnEnterKey = () => { name.YieldKeyboardFocus(); return true; };
}

public static void SetupNameWidget(Widget parent, Session.Slot s, Session.Client c)
Expand Down
38 changes: 29 additions & 9 deletions OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs
Expand Up @@ -190,23 +190,45 @@ Action InitDisplayPanel(Widget panel)

var frameLimitTextfield = panel.Get<TextFieldWidget>("FRAME_LIMIT_TEXTFIELD");
frameLimitTextfield.Text = ds.MaxFramerate.ToString();
frameLimitTextfield.OnLoseFocus = () =>
frameLimitTextfield.OnEnterKey = () =>
{
int fps;
Exts.TryParseIntegerInvariant(frameLimitTextfield.Text, out fps);
ds.MaxFramerate = fps.Clamp(1, 1000);
frameLimitTextfield.Text = ds.MaxFramerate.ToString();
frameLimitTextfield.YieldKeyboardFocus();
return true;
};
frameLimitTextfield.OnEscKey = () =>
{
frameLimitTextfield.Text = ds.MaxFramerate.ToString();
frameLimitTextfield.YieldKeyboardFocus();
return true;
};
frameLimitTextfield.OnEnterKey = () => { frameLimitTextfield.YieldKeyboardFocus(); return true; };
frameLimitTextfield.IsDisabled = () => !ds.CapFramerate;

// Player profile
var ps = Game.Settings.Player;

var nameTextfield = panel.Get<TextFieldWidget>("PLAYERNAME");
nameTextfield.Text = ps.Name;
nameTextfield.OnEnterKey = () => { nameTextfield.YieldKeyboardFocus(); return true; };
nameTextfield.OnLoseFocus = () => { ps.Name = nameTextfield.Text; };
nameTextfield.OnEnterKey = () =>
{
nameTextfield.Text = nameTextfield.Text.Trim();
if (nameTextfield.Text.Length == 0)
nameTextfield.Text = ps.Name;
else
ps.Name = nameTextfield.Text;
nameTextfield.YieldKeyboardFocus();
return true;
};
nameTextfield.OnEscKey = () =>
{
nameTextfield.Text = ps.Name;
nameTextfield.YieldKeyboardFocus();
return true;
};

var colorPreview = panel.Get<ColorPreviewManagerWidget>("COLOR_MANAGER");
colorPreview.Color = ps.Color;
Expand Down Expand Up @@ -472,11 +494,9 @@ Action InitInputPanel(Widget panel)
{
// Remove focus from the selected hotkey widget
// This is a bit of a hack, but works
if (Ui.KeyboardFocusWidget != null && panel.GetOrNull(Ui.KeyboardFocusWidget.Id) != null)
{
Ui.KeyboardFocusWidget.YieldKeyboardFocus();
Ui.KeyboardFocusWidget = null;
}
var k = Ui.GetCurrentKeyboardFocus();
if (k != null && panel.GetOrNull(k.Id) != null)
k.YieldKeyboardFocus();
};
}

Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Widgets/TextFieldWidget.cs
Expand Up @@ -227,7 +227,7 @@ public override void Tick()
if (isDisabled != wasDisabled)
{
wasDisabled = isDisabled;
if (isDisabled && Ui.KeyboardFocusWidget == this)
if (isDisabled && Ui.GetCurrentKeyboardFocus() == this)
YieldKeyboardFocus();
}

Expand Down

0 comments on commit 722b726

Please sign in to comment.