Skip to content

Commit debbb5a

Browse files
Restore cursor shape on exit. (#793) (#794)
Fixed: #792
1 parent ea5f892 commit debbb5a

17 files changed

+96
-90
lines changed

CHANGELOG.md

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,16 @@ current (development)
77
### Component
88
- Feature: Add support for `Input`'s insert mode. Add `InputOption::insert`
99
option. Added by @mingsheng13.
10-
- Feature/Bugfix/Breaking change: `Mouse transition`:
10+
- Bugfix/Breaking change: `Mouse transition`:
11+
- Detect when the mouse move, as opposed to being pressed.
12+
The Mouse::Moved motion was added.
13+
- Dragging the mouse with the left button pressed now avoids activating
14+
multiple checkboxes.
15+
- A couple of components are now activated when the mouse is pressed,
16+
as opposed to being released.
1117
This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/773
12-
Dragging the mouse with the left button pressed now avoids activating multiple
13-
checkboxes.
14-
15-
Add support for detecting mouse press transition. Added:
16-
```cpp
17-
// The previous mouse event.
18-
Mouse Mouse::previous;
19-
20-
// Return whether the mouse transitionned from:
21-
// released to pressed => IsPressed()
22-
// pressed to pressed => IsHeld()
23-
// pressed to released => IsReleased()
24-
bool Mouse::IsPressed(Button button) const;
25-
bool Mouse::IsHeld(Button button) const;
26-
bool Mouse::IsReleased(Button button) const;
27-
```
28-
A couple of components are now activated when the mouse is pressed,
29-
as opposed to released.
18+
This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/792
19+
- Bugfix: mouse.control is now reported correctly.
3020
- Feature: Add `ScreenInteractive::FullscreenPrimaryScreen()`. This allows
3121
displaying a fullscreen component on the primary screen, as opposed to the
3222
alternate screen.

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ add_library(component
123123
src/ftxui/component/maybe.cpp
124124
src/ftxui/component/menu.cpp
125125
src/ftxui/component/modal.cpp
126-
src/ftxui/component/mouse.cpp
127126
src/ftxui/component/radiobox.cpp
128127
src/ftxui/component/radiobox.cpp
129128
src/ftxui/component/renderer.cpp

examples/component/print_key_press.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ std::string Stringify(Event event) {
5555
case Mouse::Released:
5656
out += "_released";
5757
break;
58+
case Mouse::Moved:
59+
out += "_moved";
60+
break;
5861
}
5962
if (event.mouse().control)
6063
out += "_control";

include/ftxui/component/mouse.hpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@ struct Mouse {
2121
enum Motion {
2222
Released = 0,
2323
Pressed = 1,
24+
Moved = 2,
2425
};
2526

26-
// Utility function to check the variations of the mouse state.
27-
bool IsPressed(Button btn = Left) const; // Released => Pressed.
28-
bool IsHeld(Button btn = Left) const; // Pressed => Pressed.
29-
bool IsReleased(Button btn = Left) const; // Pressed => Released.
30-
3127
// Button
3228
Button button = Button::None;
3329

@@ -42,9 +38,6 @@ struct Mouse {
4238
// Coordinates:
4339
int x = 0;
4440
int y = 0;
45-
46-
// Previous mouse event, if any.
47-
Mouse* previous = nullptr;
4841
};
4942

5043
} // namespace ftxui

include/ftxui/component/screen_interactive.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ class ScreenInteractive : public Screen {
117117
// The style of the cursor to restore on exit.
118118
int cursor_reset_shape_ = 1;
119119

120-
Mouse latest_mouse_event_;
121120
friend class Loop;
122121

123122
public:

src/ftxui/component/button.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ class ButtonBase : public ComponentBase, public ButtonOption {
124124
return false;
125125
}
126126

127-
if (event.mouse().IsPressed()) {
127+
if (event.mouse().button == Mouse::Left &&
128+
event.mouse().motion == Mouse::Pressed) {
128129
TakeFocus();
129130
OnClick();
130131
return true;

src/ftxui/component/checkbox.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ class CheckboxBase : public ComponentBase, public CheckboxOption {
6969
return false;
7070
}
7171

72-
if (event.mouse().IsPressed()) {
72+
if (event.mouse().button == Mouse::Left &&
73+
event.mouse().motion == Mouse::Pressed) {
7374
*checked = !*checked;
7475
on_change();
7576
return true;

src/ftxui/component/input.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,10 @@ class InputBase : public ComponentBase, public InputOption {
466466
return false;
467467
}
468468

469-
if (!event.mouse().IsPressed()) {
469+
if (event.mouse().button != Mouse::Left) {
470+
return false;
471+
}
472+
if (event.mouse().motion != Mouse::Pressed) {
470473
return false;
471474
}
472475

src/ftxui/component/menu.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,9 @@ class MenuBase : public ComponentBase, public MenuOption {
318318

319319
TakeFocus();
320320
focused_entry() = i;
321-
if (event.mouse().IsPressed()) {
321+
322+
if (event.mouse().button == Mouse::Left &&
323+
event.mouse().motion == Mouse::Pressed) {
322324
if (selected() != i) {
323325
selected() = i;
324326
selected_previous_ = selected();
@@ -682,7 +684,8 @@ Component MenuEntry(MenuEntryOption option) {
682684
return false;
683685
}
684686

685-
if (event.mouse().IsPressed()) {
687+
if (event.mouse().button == Mouse::Left &&
688+
event.mouse().motion == Mouse::Pressed) {
686689
TakeFocus();
687690
return true;
688691
}

src/ftxui/component/mouse.cpp

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/ftxui/component/radiobox.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ class RadioboxBase : public ComponentBase, public RadioboxOption {
123123

124124
TakeFocus();
125125
focused_entry() = i;
126-
if (event.mouse().IsPressed()) {
126+
if (event.mouse().button == Mouse::Left &&
127+
event.mouse().motion == Mouse::Pressed) {
127128
if (selected() != i) {
128129
selected() = i;
129130
on_change();

src/ftxui/component/resizable_split.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class ResizableSplitBase : public ComponentBase {
4242
return true;
4343
}
4444

45-
if (event.mouse().IsPressed() &&
45+
if (event.mouse().button == Mouse::Left &&
46+
event.mouse().motion == Mouse::Pressed &&
4647
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
4748
!captured_mouse_) {
4849
captured_mouse_ = CaptureMouse(event);

src/ftxui/component/screen_interactive.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -734,17 +734,11 @@ void ScreenInteractive::HandleTask(Component component, Task& task) {
734734
if (arg.is_mouse()) {
735735
arg.mouse().x -= cursor_x_;
736736
arg.mouse().y -= cursor_y_;
737-
arg.mouse().previous = &latest_mouse_event_;
738737
}
739738

740739
arg.screen_ = this;
741740
component->OnEvent(arg);
742741
frame_valid_ = false;
743-
744-
if (arg.is_mouse()) {
745-
latest_mouse_event_ = arg.mouse();
746-
latest_mouse_event_.previous = nullptr;
747-
}
748742
return;
749743
}
750744

src/ftxui/component/slider.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ class SliderBase : public ComponentBase {
174174
return true;
175175
}
176176

177-
if (!event.mouse().IsPressed()) {
177+
if (event.mouse().button != Mouse::Left) {
178+
return false;
179+
}
180+
if (event.mouse().motion != Mouse::Pressed) {
178181
return false;
179182
}
180183

src/ftxui/component/terminal_input_parser.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -410,13 +410,36 @@ TerminalInputParser::Output TerminalInputParser::ParseMouse( // NOLINT
410410
(void)altered;
411411

412412
Output output(MOUSE);
413-
output.mouse.button = Mouse::Button((arguments[0] & 3) + // NOLINT
414-
((arguments[0] & 64) >> 4)); // NOLINT
415-
output.mouse.motion = Mouse::Motion(pressed); // NOLINT
416-
output.mouse.shift = bool(arguments[0] & 4); // NOLINT
417-
output.mouse.meta = bool(arguments[0] & 8); // NOLINT
418-
output.mouse.x = arguments[1]; // NOLINT
419-
output.mouse.y = arguments[2]; // NOLINT
413+
output.mouse.motion = Mouse::Motion(pressed); // NOLINT
414+
415+
// Bits value Modifer Comment
416+
// ---- ----- ------- ---------
417+
// 0 1 1 2 button 0 = Left, 1 = Middle, 2 = Right, 3 = Release
418+
// 2 4 Shift
419+
// 3 8 Meta
420+
// 4 16 Control
421+
// 5 32 Move
422+
// 6 64 Wheel
423+
424+
// clang-format off
425+
const int button = arguments[0] & (1 + 2); // NOLINT
426+
const bool is_shift = arguments[0] & 4; // NOLINT
427+
const bool is_meta = arguments[0] & 8; // NOLINT
428+
const bool is_control = arguments[0] & 16; // NOLINT
429+
const bool is_move = arguments[0] & 32; // NOLINT
430+
const bool is_wheel = arguments[0] & 64; // NOLINT
431+
// clang-format on
432+
433+
output.mouse.motion = is_move ? Mouse::Moved : Mouse::Motion(pressed);
434+
output.mouse.button = is_wheel ? Mouse::Button(Mouse::WheelUp + button) //
435+
: Mouse::Button(button);
436+
output.mouse.shift = is_shift;
437+
output.mouse.meta = is_meta;
438+
output.mouse.control = is_control;
439+
output.mouse.x = arguments[1]; // NOLINT
440+
output.mouse.y = arguments[2]; // NOLINT
441+
442+
// Motion event.
420443
return output;
421444
}
422445

src/ftxui/component/terminal_input_parser_test.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ TEST(Event, MouseLeftClickPressed) {
8282
auto parser = TerminalInputParser(event_receiver->MakeSender());
8383
parser.Add('\x1B');
8484
parser.Add('[');
85-
parser.Add('3');
86-
parser.Add('2');
85+
parser.Add('0');
8786
parser.Add(';');
8887
parser.Add('1');
8988
parser.Add('2');
@@ -103,7 +102,7 @@ TEST(Event, MouseLeftClickPressed) {
103102
EXPECT_FALSE(event_receiver->Receive(&received));
104103
}
105104

106-
TEST(Event, MouseLeftClickReleased) {
105+
TEST(Event, MouseLeftMoved) {
107106
auto event_receiver = MakeReceiver<Task>();
108107
{
109108
auto parser = TerminalInputParser(event_receiver->MakeSender());
@@ -117,6 +116,32 @@ TEST(Event, MouseLeftClickReleased) {
117116
parser.Add(';');
118117
parser.Add('4');
119118
parser.Add('2');
119+
parser.Add('M');
120+
}
121+
122+
Task received;
123+
EXPECT_TRUE(event_receiver->Receive(&received));
124+
EXPECT_TRUE(std::get<Event>(received).is_mouse());
125+
EXPECT_EQ(Mouse::Left, std::get<Event>(received).mouse().button);
126+
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
127+
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
128+
EXPECT_EQ(std::get<Event>(received).mouse().motion, Mouse::Moved);
129+
EXPECT_FALSE(event_receiver->Receive(&received));
130+
}
131+
132+
TEST(Event, MouseLeftClickReleased) {
133+
auto event_receiver = MakeReceiver<Task>();
134+
{
135+
auto parser = TerminalInputParser(event_receiver->MakeSender());
136+
parser.Add('\x1B');
137+
parser.Add('[');
138+
parser.Add('0');
139+
parser.Add(';');
140+
parser.Add('1');
141+
parser.Add('2');
142+
parser.Add(';');
143+
parser.Add('4');
144+
parser.Add('2');
120145
parser.Add('m');
121146
}
122147

src/ftxui/component/window.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,10 @@ class WindowImpl : public ComponentBase, public WindowOptions {
225225
return true;
226226
}
227227

228-
if (!event.mouse().IsPressed()) {
228+
if (event.mouse().button != Mouse::Left) {
229+
return true;
230+
}
231+
if (event.mouse().motion != Mouse::Pressed) {
229232
return true;
230233
}
231234

0 commit comments

Comments
 (0)