Skip to content

Commit

Permalink
implement input method keyboard grab
Browse files Browse the repository at this point in the history
  • Loading branch information
lilydjwg committed Nov 24, 2023
1 parent 503fc7d commit a70aceb
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 12 deletions.
69 changes: 68 additions & 1 deletion src/core/seat/input-method-relay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ wf::input_method_relay::input_method_relay()
return;
}

LOGI("new input method connected");
input_method = new_input_method;
on_input_method_commit.connect(&input_method->events.commit);
on_input_method_destroy.connect(&input_method->events.destroy);
on_grab_keyboard.connect(&input_method->events.grab_keyboard);

auto *text_input = find_focusable_text_input();
if (text_input)
Expand Down Expand Up @@ -83,7 +85,10 @@ wf::input_method_relay::input_method_relay()

on_input_method_commit.disconnect();
on_input_method_destroy.disconnect();
input_method = nullptr;
on_grab_keyboard.disconnect();
on_grab_keyboard_destroy.disconnect();
input_method = nullptr;
keyboard_grab = nullptr;

auto *text_input = find_focused_text_input();
if (text_input != nullptr)
Expand All @@ -96,6 +101,24 @@ wf::input_method_relay::input_method_relay()
}
});

on_grab_keyboard.set_callback([&] (void *data)
{
if (keyboard_grab != nullptr)
{
LOGI("Attempted to grab input method keyboard twice");
return;
}

keyboard_grab = static_cast<wlr_input_method_keyboard_grab_v2*>(data);
on_grab_keyboard_destroy.connect(&keyboard_grab->events.destroy);
});

on_grab_keyboard_destroy.set_callback([&] (void *data)
{
on_grab_keyboard_destroy.disconnect();
keyboard_grab = nullptr;
});

on_text_input_new.connect(&wf::get_core().protocols.text_input->events.text_input);
on_input_method_new.connect(&wf::get_core().protocols.input_method->events.input_method);
wf::get_core().connect(&keyboard_focus_changed);
Expand Down Expand Up @@ -141,6 +164,50 @@ void wf::input_method_relay::remove_text_input(wlr_text_input_v3 *input)
text_inputs.erase(it, text_inputs.end());
}

bool wf::input_method_relay::should_grab(wlr_keyboard *kbd)
{
if (keyboard_grab == nullptr)
{
return false;
}

// input method sends key via a virtual keyboard
struct wlr_virtual_keyboard_v1 *virtual_keyboard = wlr_input_device_get_virtual_keyboard(&kbd->base);
if (virtual_keyboard &&
(wl_resource_get_client(virtual_keyboard->resource) ==
wl_resource_get_client(input_method->keyboard_grab->resource)))
{
return false;
}

return true;
}

bool wf::input_method_relay::handle_key(struct wlr_keyboard *kbd, uint32_t time, uint32_t key,
uint32_t state)
{
if (!should_grab(kbd))
{
return false;
}

wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab, kbd);
wlr_input_method_keyboard_grab_v2_send_key(keyboard_grab, time, key, state);
return true;
}

bool wf::input_method_relay::handle_modifier(struct wlr_keyboard *kbd)
{
if (!should_grab(kbd))
{
return false;
}

wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab, kbd);
wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab, &kbd->modifiers);
return true;
}

wf::text_input*wf::input_method_relay::find_focusable_text_input()
{
auto it = std::find_if(text_inputs.begin(), text_inputs.end(),
Expand Down
8 changes: 7 additions & 1 deletion src/core/seat/input-method-relay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class input_method_relay
private:

wf::wl_listener_wrapper on_text_input_new,
on_input_method_new, on_input_method_commit, on_input_method_destroy;
on_input_method_new, on_input_method_commit, on_input_method_destroy,
on_grab_keyboard, on_grab_keyboard_destroy;
wlr_input_method_keyboard_grab_v2 *keyboard_grab = nullptr;
text_input *find_focusable_text_input();
text_input *find_focused_text_input();
void set_focus(wlr_surface*);
Expand All @@ -34,6 +36,8 @@ class input_method_relay
}
};

bool should_grab(wlr_keyboard*);

public:

wlr_input_method_v2 *input_method = nullptr;
Expand All @@ -43,6 +47,8 @@ class input_method_relay
void send_im_state(wlr_text_input_v3*);
void disable_text_input(wlr_text_input_v3*);
void remove_text_input(wlr_text_input_v3*);
bool handle_key(struct wlr_keyboard*, uint32_t, uint32_t, uint32_t);
bool handle_modifier(struct wlr_keyboard*);
~input_method_relay();
};

Expand Down
29 changes: 20 additions & 9 deletions src/core/seat/keyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "cursor.hpp"
#include "touch.hpp"
#include "input-manager.hpp"
#include "input-method-relay.hpp"
#include "wayfire/compositor-view.hpp"
#include "wayfire/signal-definitions.hpp"

Expand All @@ -37,7 +38,8 @@ void wf::keyboard_t::setup_listeners()
}

seat->priv->set_keyboard(this);
if (!handle_keyboard_key(ev->keycode, ev->state) && (mode == input_event_processing_mode_t::FULL))
if (!handle_keyboard_key(ev->time_msec, ev->keycode,
ev->state) && (mode == input_event_processing_mode_t::FULL))
{
if (ev->state == WL_KEYBOARD_KEY_STATE_PRESSED)
{
Expand Down Expand Up @@ -71,8 +73,12 @@ void wf::keyboard_t::setup_listeners()
auto kbd = static_cast<wlr_keyboard*>(data);
auto seat = wf::get_core().get_current_seat();

wlr_seat_set_keyboard(seat, kbd);
wlr_seat_keyboard_send_modifiers(seat, &kbd->modifiers);
if (!wf::get_core_impl().im_relay->handle_modifier(kbd))
{
wlr_seat_set_keyboard(seat, kbd);
wlr_seat_keyboard_send_modifiers(seat, &kbd->modifiers);
}

wlr_idle_notify_activity(wf::get_core().protocols.idle, seat);
});

Expand Down Expand Up @@ -281,15 +287,15 @@ bool wf::keyboard_t::has_only_modifiers()
return true;
}

bool wf::keyboard_t::handle_keyboard_key(uint32_t key, uint32_t state)
bool wf::keyboard_t::handle_keyboard_key(uint32_t time, uint32_t key, uint32_t state)
{
using namespace std::chrono;

auto& input = wf::get_core_impl().input;
auto& seat = wf::get_core_impl().seat;

bool handled_in_plugin = false;
auto mod = mod_from_key(key);
bool handled = false;
auto mod = mod_from_key(key);
input->locked_mods = this->get_locked_mods();

if (state == WLR_KEY_PRESSED)
Expand All @@ -315,7 +321,7 @@ bool wf::keyboard_t::handle_keyboard_key(uint32_t key, uint32_t state)
mod_binding_key = 0;
}

handled_in_plugin |= wf::get_core().bindings->handle_key(
handled |= wf::get_core().bindings->handle_key(
wf::keybinding_t{get_modifiers(), key}, mod_binding_key);
} else
{
Expand All @@ -328,13 +334,18 @@ bool wf::keyboard_t::handle_keyboard_key(uint32_t key, uint32_t state)

if ((timeout <= 0) || (time_elapsed < milliseconds(timeout)))
{
handled_in_plugin |= wf::get_core().bindings->handle_key(
handled |= wf::get_core().bindings->handle_key(
wf::keybinding_t{get_modifiers() | mod, 0}, mod_binding_key);
}
}

mod_binding_key = 0;
}

return handled_in_plugin;
if (!handled)
{
handled |= wf::get_core_impl().im_relay->handle_key(handle, time, key, state);
}

return handled;
}
2 changes: 1 addition & 1 deletion src/core/seat/keyboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class keyboard_t

std::chrono::steady_clock::time_point mod_binding_start;

bool handle_keyboard_key(uint32_t key, uint32_t state);
bool handle_keyboard_key(uint32_t time, uint32_t key, uint32_t state);

/** Get the current locked mods */
uint32_t get_locked_mods();
Expand Down

0 comments on commit a70aceb

Please sign in to comment.