Skip to content

Commit

Permalink
Fix OSK issues on electron (#3681)
Browse files Browse the repository at this point in the history
Closes #3580.

Fixes a few issues:
1. The "Interval" field showing the OSK for a split second

2. The "Interval" field (and similar fields) didn't get input changes as
you used the OSK

3. Tabbing from the interval field to the minutes/hours/days field to
its right opened the OSK in number mode.
This was due to `reset` being called between the content type being set
in the state and the state being actually committed, causing Mir to lose
the state and not commit it to the handler, leading to the previous mode
(numbers) carrying over to the new field
  • Loading branch information
tarek-y-ismail authored Dec 16, 2024
2 parents 699dcde + bffd5f1 commit 4178136
Showing 1 changed file with 25 additions and 19 deletions.
44 changes: 25 additions & 19 deletions src/server/frontend_wayland/text_input_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "wl_surface.h"
#include "mir/executor.h"
#include "mir/scene/text_input_hub.h"
#include "mir/wayland/client.h"

#include <memory>
#include <boost/throw_exception.hpp>
Expand Down Expand Up @@ -171,8 +170,13 @@ class TextInputV1
mw::Weak<mf::WlSurface> current_surface;
/// Set to true if and only if the text input has been enabled since the last commit
bool on_new_input_field{false};
/// nullopt if the state is inactive, otherwise holds the pending and/or committed state
std::optional<ms::TextInputState> pending_state;

enum class State
{
active,
inactive,
} state;
ms::TextInputState pending_state;

struct SerialPair
{
Expand Down Expand Up @@ -247,7 +251,8 @@ TextInputV1::TextInputV1(
std::shared_ptr<TextInputV1Ctx> const& ctx)
: mw::TextInputV1{resource, Version<1>()},
ctx{ctx},
handler{std::make_shared<Handler>(this, ctx->wayland_executor)}
handler{std::make_shared<Handler>(this, ctx->wayland_executor)},
state{State::inactive}
{
}

Expand All @@ -258,15 +263,15 @@ TextInputV1::~TextInputV1()
seat.value()->remove_focus_listener(client, this);
}

state = State::inactive;
on_new_input_field = false;
pending_state.reset();
ctx->text_input_hub->deactivate_handler(handler);
}

void TextInputV1::send_text_change(ms::TextInputChange const& change)
{
auto const client_serial = find_client_serial(change.serial);
if (!pending_state || !current_surface || !client_serial)
if (state == State::inactive || !current_surface || !client_serial)
{
// We are no longer enabled, or we don't have a valid serial
return;
Expand Down Expand Up @@ -360,18 +365,19 @@ void TextInputV1::activate(wl_resource *seat_resource, wl_resource *surface)
if (current_surface)
{
on_new_input_field = true;
pending_state.emplace();
state = State::active;
pending_state = {};
}
}

void TextInputV1::deactivate(wl_resource *seat)
{
(void)seat;
on_new_input_field = false;
pending_state.reset();
state = State::inactive;
}

/// Electron appears to call show_input_panel() when commit_state() should be called.
/// Electron appears to call show_input_panel() when commit_state() should be called.
void TextInputV1::show_input_panel()
{
commit_state(0);
Expand All @@ -386,25 +392,25 @@ void TextInputV1::hide_input_panel()

void TextInputV1::reset()
{
pending_state.reset();
pending_state = {};
}

void TextInputV1::set_surrounding_text(const std::string &text, uint32_t cursor, uint32_t anchor)
{
if (pending_state)
if (state == State::active)
{
pending_state->surrounding_text = text;
pending_state->cursor = cursor;
pending_state->anchor = anchor;
pending_state.surrounding_text = text;
pending_state.cursor = cursor;
pending_state.anchor = anchor;
}
}

void TextInputV1::set_content_type(uint32_t hint, uint32_t purpose)
{
if (pending_state)
if (state == State::active)
{
pending_state->content_hint.emplace(wayland_to_mir_content_hint(hint));
pending_state->content_purpose = wayland_to_mir_content_purpose(purpose);
pending_state.content_hint.emplace(wayland_to_mir_content_hint(hint));
pending_state.content_purpose = wayland_to_mir_content_purpose(purpose);
}
}

Expand All @@ -424,9 +430,9 @@ void TextInputV1::set_preferred_language(const std::string &language)

void TextInputV1::commit_state(uint32_t client_serial)
{
if (pending_state && current_surface)
if (state == State::active && current_surface)
{
auto const hub_serial = ctx->text_input_hub->set_handler_state(handler, on_new_input_field, *pending_state);
auto const hub_serial = ctx->text_input_hub->set_handler_state(handler, on_new_input_field, pending_state);
state_serials.push_back({client_serial, hub_serial});
while (state_serials.size() > max_remembered_serials)
{
Expand Down

0 comments on commit 4178136

Please sign in to comment.