mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:17:44 +00:00
LibGUI+WindowServer: Implement drag-to-select behavior in GTextEditor.
To make this feel right, I needed to start passing keyboard modifiers along with mouse events. That allows shift-clicking to extend the selection. :^)
This commit is contained in:
parent
6d172725c0
commit
f40d11f06d
11 changed files with 73 additions and 21 deletions
|
@ -109,6 +109,7 @@ struct WSAPI_ServerMessage {
|
|||
WSAPI_Point position;
|
||||
WSAPI_MouseButton button;
|
||||
unsigned buttons;
|
||||
byte modifiers;
|
||||
} mouse;
|
||||
struct {
|
||||
char character;
|
||||
|
|
|
@ -513,11 +513,12 @@ private:
|
|||
|
||||
class WSMouseEvent final : public WSMessage {
|
||||
public:
|
||||
WSMouseEvent(Type type, const Point& position, unsigned buttons, MouseButton button = MouseButton::None)
|
||||
WSMouseEvent(Type type, const Point& position, unsigned buttons, MouseButton button, unsigned modifiers)
|
||||
: WSMessage(type)
|
||||
, m_position(position)
|
||||
, m_buttons(buttons)
|
||||
, m_button(button)
|
||||
, m_modifiers(modifiers)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -526,11 +527,13 @@ public:
|
|||
int y() const { return m_position.y(); }
|
||||
MouseButton button() const { return m_button; }
|
||||
unsigned buttons() const { return m_buttons; }
|
||||
unsigned modifiers() const { return m_modifiers; }
|
||||
|
||||
private:
|
||||
Point m_position;
|
||||
unsigned m_buttons { 0 };
|
||||
MouseButton m_button { MouseButton::None };
|
||||
unsigned m_modifiers { 0 };
|
||||
};
|
||||
|
||||
class WSResizeEvent final : public WSMessage {
|
||||
|
|
|
@ -69,14 +69,14 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, unsigned buttons)
|
|||
auto post_mousedown_or_mouseup_if_needed = [&] (MouseButton button) {
|
||||
if (!(changed_buttons & (unsigned)button))
|
||||
return;
|
||||
auto message = make<WSMouseEvent>(buttons & (unsigned)button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, button);
|
||||
auto message = make<WSMouseEvent>(buttons & (unsigned)button ? WSMessage::MouseDown : WSMessage::MouseUp, m_cursor_location, buttons, button, m_modifiers);
|
||||
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
|
||||
};
|
||||
post_mousedown_or_mouseup_if_needed(MouseButton::Left);
|
||||
post_mousedown_or_mouseup_if_needed(MouseButton::Right);
|
||||
post_mousedown_or_mouseup_if_needed(MouseButton::Middle);
|
||||
if (m_cursor_location != prev_location) {
|
||||
auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons);
|
||||
auto message = make<WSMouseEvent>(WSMessage::MouseMove, m_cursor_location, buttons, MouseButton::None, m_modifiers);
|
||||
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
|
||||
}
|
||||
// NOTE: Invalidate the cursor if it moved, or if the left button changed state (for the cursor color inversion.)
|
||||
|
@ -86,6 +86,7 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, unsigned buttons)
|
|||
|
||||
void WSScreen::on_receive_keyboard_data(KeyEvent kernel_event)
|
||||
{
|
||||
m_modifiers = kernel_event.modifiers();
|
||||
auto message = make<WSKeyEvent>(kernel_event.is_press() ? WSMessage::KeyDown : WSMessage::KeyUp, kernel_event.key, kernel_event.character, kernel_event.modifiers());
|
||||
WSMessageLoop::the().post_message(WSWindowManager::the(), move(message));
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ private:
|
|||
|
||||
Point m_cursor_location;
|
||||
unsigned m_mouse_button_state { 0 };
|
||||
unsigned m_modifiers { 0 };
|
||||
};
|
||||
|
||||
inline RGBA32* WSScreen::scanline(int y)
|
||||
|
|
|
@ -82,18 +82,21 @@ void WSWindow::on_message(WSMessage& message)
|
|||
server_message.mouse.position = static_cast<WSMouseEvent&>(message).position();
|
||||
server_message.mouse.button = WSAPI_MouseButton::NoButton;
|
||||
server_message.mouse.buttons = static_cast<WSMouseEvent&>(message).buttons();
|
||||
server_message.mouse.modifiers = static_cast<WSMouseEvent&>(message).modifiers();
|
||||
break;
|
||||
case WSMessage::MouseDown:
|
||||
server_message.type = WSAPI_ServerMessage::Type::MouseDown;
|
||||
server_message.mouse.position = static_cast<WSMouseEvent&>(message).position();
|
||||
server_message.mouse.button = to_api(static_cast<WSMouseEvent&>(message).button());
|
||||
server_message.mouse.buttons = static_cast<WSMouseEvent&>(message).buttons();
|
||||
server_message.mouse.modifiers = static_cast<WSMouseEvent&>(message).modifiers();
|
||||
break;
|
||||
case WSMessage::MouseUp:
|
||||
server_message.type = WSAPI_ServerMessage::Type::MouseUp;
|
||||
server_message.mouse.position = static_cast<WSMouseEvent&>(message).position();
|
||||
server_message.mouse.button = to_api(static_cast<WSMouseEvent&>(message).button());
|
||||
server_message.mouse.buttons = static_cast<WSMouseEvent&>(message).buttons();
|
||||
server_message.mouse.modifiers = static_cast<WSMouseEvent&>(message).modifiers();
|
||||
break;
|
||||
case WSMessage::WindowEntered:
|
||||
server_message.type = WSAPI_ServerMessage::Type::WindowEntered;
|
||||
|
|
|
@ -762,7 +762,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
|
|||
continue;
|
||||
ASSERT(window->is_visible()); // Maybe this should be supported? Idk. Let's catch it and think about it later.
|
||||
Point position { event.x() - window->rect().x(), event.y() - window->rect().y() };
|
||||
auto local_event = make<WSMouseEvent>(event.type(), position, event.buttons(), event.button());
|
||||
auto local_event = make<WSMouseEvent>(event.type(), position, event.buttons(), event.button(), event.modifiers());
|
||||
window->on_message(*local_event);
|
||||
}
|
||||
|
||||
|
@ -815,7 +815,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_
|
|||
if (!window.global_cursor_tracking()) {
|
||||
// FIXME: Should we just alter the coordinates of the existing MouseEvent and pass it through?
|
||||
Point position { event.x() - window.rect().x(), event.y() - window.rect().y() };
|
||||
auto local_event = make<WSMouseEvent>(event.type(), position, event.buttons(), event.button());
|
||||
auto local_event = make<WSMouseEvent>(event.type(), position, event.buttons(), event.button(), event.modifiers());
|
||||
window.on_message(*local_event);
|
||||
}
|
||||
return IterationDecision::Abort;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue