diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index 132ca5aaeb..f60056ef2e 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -1,10 +1,8 @@ use conrod_core::{ - builder_methods, color, input::Key, - text::font, widget::{self, Button, Id, List, Rectangle, Text, TextEdit}, position::Dimension, - UiCell, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, + UiCell, widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; use super::{ img_ids::Imgs, @@ -69,12 +67,13 @@ pub struct State { pub enum Event { SendMessage(String), + Focus(Id), } impl<'a> Widget for Chat<'a> { type State = State; type Style = (); - type Event = Option<Event>; + type Event = (bool, Option<Event>); fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { State { @@ -103,10 +102,12 @@ impl<'a> Widget for Chat<'a> { ui.scroll_widget(state.ids.message_box, [0.0, std::f64::MAX]); } + let keyboard_capturer = ui.global_input().current.widget_capturing_keyboard; + let input_focused = keyboard_capturer == Some(state.ids.input); + // Only show if it has the keyboard captured // Chat input with rectangle as background - let keyboard_captured = ui.global_input().current.widget_capturing_keyboard == Some(id); - if keyboard_captured { + if input_focused { let text_edit = TextEdit::new(&state.input) .w(460.0) .restrict_to_height(false) @@ -135,12 +136,10 @@ impl<'a> Widget for Chat<'a> { // Message box Rectangle::fill([470.0, 174.0]) .rgba(0.0, 0.0, 0.0, 0.4) - .and(|r| { - if keyboard_captured { - r.up_from(self.ids.input_bg, 0.0) - } else { - r.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) - } + .and(|r| if input_focused { + r.up_from(state.ids.input_bg, 0.0) + } else { + r.bottom_left_with_margins_on(ui.window, 10.0, 10.0) }) .set(state.ids.message_box_bg, ui); let (mut items, _) = List::flow_down(state.messages.len() + 1) @@ -186,8 +185,13 @@ impl<'a> Widget for Chat<'a> { } } + // If the chat widget is focused return a focus event to pass the focus to the input box + let self_focused = keyboard_capturer == Some(id); + let event = if self_focused { + Some(Event::Focus(state.ids.input)) + } // If enter is pressed and the input box is not empty send the current message - if ui + else if ui .widget_input(state.ids.input) .presses() .key() @@ -198,9 +202,12 @@ impl<'a> Widget for Chat<'a> { { let msg = state.input.clone(); state.update(|s| s.input.clear()); - return Some(Event::SendMessage(msg)) - } + Some(Event::SendMessage(msg)) + } else { + None + }; - None + // Return whether typing and any event that occured + (self_focused || input_focused, event) } } diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 6b625e2e5d..0eb68a22c8 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -30,7 +30,7 @@ use crate::{ GlobalState, }; use conrod_core::{ - widget::{Button, Image, Text, Rectangle}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, color + widget::{Button, Image, Text, Id as WidgId, Rectangle}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, color }; use std::collections::VecDeque; @@ -190,6 +190,8 @@ pub struct Hud { new_messages: VecDeque<String>, inventory_space: u32, show: Show, + to_focus: Option<Option<WidgId>>, + typing: bool, } impl Hud { @@ -221,7 +223,9 @@ impl Hud { ui: true, inventory_test_button: false, mini_map: false, - } + }, + to_focus: None, + typing: false, } } @@ -365,12 +369,16 @@ impl Hud { .set(self.ids.skillbar, ui_widgets); // Chat box - match Chat::new(&mut self.new_messages, &self.imgs, &self.fonts) - .set(self.ids.chat, ui_widgets) - { + let (typing, event) = Chat::new(&mut self.new_messages, &self.imgs, &self.fonts) + .set(self.ids.chat, ui_widgets); + self.typing = typing; + match event { Some(chat::Event::SendMessage(message)) => { events.push(Event::SendMessage(message)); } + Some(chat::Event::Focus(focus_id)) => { + self.to_focus = Some(Some(focus_id)); + } None => {} } self.new_messages = VecDeque::new(); @@ -461,18 +469,11 @@ impl Hud { self.new_messages.push_back(msg); } - fn typing(&self) -> bool { - match self.ui.widget_capturing_keyboard() { - Some(id) if id == self.ids.chat => true, - _ => false, - } - } - pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool { let cursor_grabbed = global_state.window.is_cursor_grabbed(); match event { WinEvent::Ui(event) => { - if (self.typing() && event.is_keyboard() && self.show.ui) + if (self.typing && event.is_keyboard() && self.show.ui) || !(cursor_grabbed && event.is_keyboard_or_mouse()) { self.ui.handle_event(event); @@ -486,19 +487,24 @@ impl Hud { _ if !self.show.ui => false, WinEvent::Zoom(_) => !cursor_grabbed && !self.ui.no_widget_capturing_mouse(), WinEvent::KeyDown(Key::Enter) => { - self.ui.focus_widget(Some(self.ids.chat)); + self.ui.focus_widget(if self.typing { + None + } else { + Some(self.ids.chat) + }); true } WinEvent::KeyDown(Key::Escape) => { - if self.typing() { + if self.typing { self.ui.focus_widget(None); + self.typing = false; } else { // Close windows on esc self.show.toggle_windows(global_state); } true } - WinEvent::KeyDown(key) if !self.typing() => match key { + WinEvent::KeyDown(key) if !self.typing => match key { Key::Map => { self.show.toggle_map(); true @@ -535,9 +541,9 @@ impl Hud { }, WinEvent::KeyDown(key) | WinEvent::KeyUp(key) => match key { Key::ToggleCursor => false, - _ => self.typing(), + _ => self.typing, }, - WinEvent::Char(_) => self.typing(), + WinEvent::Char(_) => self.typing, WinEvent::SettingsChanged => { self.settings = global_state.settings.clone(); true @@ -547,6 +553,9 @@ impl Hud { } pub fn maintain(&mut self, renderer: &mut Renderer, tps: f64) -> Vec<Event> { + if let Some(maybe_id) = self.to_focus.take() { + self.ui.focus_widget(maybe_id); + } let events = self.update_layout(tps); self.ui.maintain(renderer); events