Skip to content

Commit ea6ca39

Browse files
authored
Merge pull request #790 from o-sdn-o/gui-bridge
Fix mouse pointer position
2 parents a9595a3 + a908250 commit ea6ca39

File tree

8 files changed

+58
-31
lines changed

8 files changed

+58
-31
lines changed

doc/vt-input-mode.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,23 @@ Anyone who wants to:
1414
- Share applications on LAN (using inetd, netcat, etc).
1515
- Track every key press and key release.
1616
- Track position dependent keys such as WASD.
17-
- Distinguish between Left and Right physical keys.
17+
- Distinguish between physical Left and Right keyboard keys.
1818
- Get consistent output regardless of terminal window resize.
1919
- Track mouse on a pixel-wise level.
2020
- Track mouse outside the terminal window (getting negative coordinates).
21-
- Take advantage of high-resolution wheel scrolling.
21+
- Take advantage of high-resolution (fine) scrolling.
2222
- Track scrollback text manipulation.
2323
- Track application closing and system shutdown.
24-
- Be independent of operating system and third party libraries.
2524

2625
Existing approaches have the following drawbacks:
2726
- There is no uniform way to receive keyboard events.
2827
- Window size tracking requires platform-specific calls with no way to synchronize the output.
29-
- Mouse tracking modes lack support for negative coordinates, and high-resolution wheel scrolling.
28+
- Mouse tracking modes lack support for negative coordinates, and high-resolution scrolling.
3029
- Bracketed paste mode does not support the transfer of binary data and data containing sequences of bracketed paste mode itself.
3130

3231
## Conventions
3332

34-
- We use HEX-form of the uint32 for the 32-bit floating point value representation (IEEE-754 32-bit binary float, Little-Endian).
33+
- We use HEX-form of the uint32 for the 32-bit floating point value representation (IEEE-754 32-bit binary float, Little-Endian). For example, the floating point value `3.1415f` is represented as the unsigned integer in hex `40490E56` (decimal 1078529622).
3534
- Space characters are not used in sequence payloads and are only used for readability of the description.
3635
- //todo: keyboard only: All unescaped symbols outside of this protocol should be treated as clipboard pasted data.
3736

@@ -121,7 +120,7 @@ ESC _ event=keyboard ; id=<ID> ; kbmods=<KeyMods> ; keyid=<KeyId> ; pressed=<Key
121120
122121
Attribute | Description
123122
------------------------------|------------
124-
`id=<ID>` | Device group id (unsigned integer value).
123+
`id=<ID>` | Device group id (unsigned integer).
125124
`kbmods=<KeyMods>` | Keyboard modifiers bit field.
126125
`keyid=<KeyId>` | Physical key ID.
127126
`pressed=<KeyDown>` | Key state:<br>\<KeyDown\>=1 - Pressed.<br>\<KeyDown\>=0 - Released.
@@ -365,12 +364,12 @@ ESC _ event=mouse ; id=<ID> ; kbmods=<KeyMods> ; coor=<X>,<Y> ; buttons=<ButtonS
365364

366365
Attribute | Description
367366
--------------------------------|------------
368-
`id=<ID>` | Device group id (unsigned integer value).
369-
`kbmods=<KeyMods>` | Keyboard modifiers bit field (see Keyboard event).
370-
`coor=<X>,<Y>` | Pixel-wise 32-bit floating point coordinates of the mouse pointer relative to the console's text cell grid. The integer part corresponds to the cell coordinates, and the fractional part corresponds to the normalized position within the cell. The pointer's screen pixel coordinates can be calculated by multiplying these floating point values by the cell size. Receiving a NaN value is a signal that the mouse has left the window or disconnected.
371-
`buttons=<ButtonState>` | Mouse buttons bit field.
372-
`iscroll=<DeltaX>,<DeltaY>` | Low-resolution integer horizontal and vertical scroll deltas (one scroll line corresponds to a value of 1). Low-resolution scroll deltas increase as the values of high-resolution deltas accumulate, and are zeroed when the scroll direction changes.
373-
`fscroll=<DeltaX>,<DeltaY>` | High-resolution 32-bit floating-point horizontal and vertical scroll deltas (one scroll line corresponds to a value of 1.0f).
367+
`id=<ID>` | Device group id (unsigned integer).
368+
`kbmods=<KeyMods>` | Keyboard modifiers bit field (unsigned integer, the same value as in Keyboard event).
369+
`coor=<X>,<Y>` | 32-bit floating point coordinates of the mouse pointer relative to the console's text cell grid. The integer part corresponds to the cell coordinates, and the fractional part corresponds to the normalized position within the cell. The pointer's screen pixel coordinates can be calculated by multiplying these floating point values by the cell size. Receiving a NaN value is a signal that the mouse has left the window or disconnected.
370+
`buttons=<ButtonState>` | Mouse buttons bit field (unsigned integer).
371+
`iscroll=<DeltaX>,<DeltaY>` | Horizontal and vertical low-resolution scroll deltas in form of signed integers (one scroll line corresponds to a value of 1). Low-resolution scroll deltas increase as the values of high-resolution deltas accumulate, and are zeroed when the scroll direction changes.
372+
`fscroll=<DeltaX>,<DeltaY>` | Horizontal and vertical high-resolution scroll deltas in form of 32-bit floating-point values (one scroll line corresponds to a value of 1.0f).
374373

375374
The mouse tracking event fires on any mouse activity, as well as on keyboard modifier changes.
376375

@@ -396,7 +395,7 @@ ESC _ event=focus ; id=<ID> ; state=<FocusState> ESC \
396395

397396
Attribute | Description
398397
---------------------|------------
399-
`id=<ID>` | Device group id (unsigned integer value).
398+
`id=<ID>` | Device group id (unsigned integer).
400399
`state=<FocusState>` | Terminal window focus:<br>\<FocusState\>=1 - Focused.<br>\<FocusState\>=0 - Unfocused.
401400

402401
In response to the activation of `focus` tracking, the application receives a vt-sequence containing current focus state.
@@ -423,7 +422,7 @@ ESC _ event=clipboard ; id=<ID> ; format=<ClipFormat> ; security=<SecLevel> ; da
423422

424423
Attribute | Description
425424
----------------------|------------
426-
`id=<ID>` | Device group id (unsigned integer value).
425+
`id=<ID>` | Device group id (unsigned integer).
427426
`format=<ClipFormat>` | Clipboard data format.
428427
`security=<SecLevel>` | Security level.
429428
`data=<Data>` | Base64 encoded data.

src/netxs/desktopio/ansivt.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,8 +626,16 @@ namespace netxs::ansi
626626
//todo make it fp2d
627627
auto x = ui32{};
628628
auto y = ui32{};
629-
::memcpy(&x, &coor.x, sizeof(x));
630-
::memcpy(&y, &coor.y, sizeof(y));
629+
if (gear.mouse_disabled)
630+
{
631+
::memcpy(&x, &fp32nan, sizeof(x));
632+
::memcpy(&y, &fp32nan, sizeof(y));
633+
}
634+
else
635+
{
636+
::memcpy(&x, &coor.x, sizeof(x));
637+
::memcpy(&y, &coor.y, sizeof(y));
638+
}
631639
auto iv = gear.m_sys.wheelsi;
632640
auto ih = 0;
633641
auto fh = ui32{};

src/netxs/desktopio/application.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace netxs::app
2222

2323
namespace netxs::app::shared
2424
{
25-
static const auto version = "v2025.08.15";
25+
static const auto version = "v2025.08.17";
2626
static const auto repository = "https://github.com/directvt/vtm";
2727
static const auto usr_config = "~/.config/vtm/settings.xml"s;
2828
static const auto sys_config = "/etc/vtm/settings.xml"s;

src/netxs/desktopio/console.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ namespace netxs::ui
540540
if (ext_gear_id)
541541
{
542542
auto& gear = *gear_ptr;
543-
if (gear.m_sys.timecod != time{}) // Don't send mouse events if the mouse has not been used yet.
543+
if (gear.m_sys.timecod != time{} || gear.mouse_disabled) // Don't send mouse events if the mouse has not been used yet or disabled.
544544
{
545545
gear.fire_fast();
546546
gear.fire(event_id);
@@ -569,15 +569,15 @@ namespace netxs::ui
569569
static const auto busy = cell{}.bgc(reddk).fgc(0xFFffffff);
570570
auto brush = gear.m_sys.buttons ? cell{ busy }.txt(64 + (char)gear.m_sys.buttons/*A-Z...*/)
571571
: idle;
572-
auto area = rect{ gear.coord, dot_11 };
572+
auto area = rect{ gear.coord + gear.owner.coor(), dot_11 };
573573
parent_canvas.fill(area, cell::shaders::fuse(brush));
574574
}
575575
void draw_mouse_pointer(face& parent_canvas)
576576
{
577577
for (auto& [ext_gear_id, gear_ptr] : gears)
578578
{
579579
auto& gear = *gear_ptr;
580-
if (gear.mouse_disabled) continue;
580+
if (gear.mouse_disabled || std::isnan(gear.coord.x)) continue;
581581
fill_pointer(gear, parent_canvas);
582582
}
583583
}
@@ -589,7 +589,7 @@ namespace netxs::ui
589589
gear.board::shown = !gear.mouse_disabled &&
590590
(props.clip_preview_time == span::zero() ||
591591
props.clip_preview_time > stamp - gear.delta.stamp());
592-
if (gear.board::shown)
592+
if (gear.board::shown && !std::isnan(gear.coord.x))
593593
{
594594
auto coor = twod{ gear.coord } + dot_21 * 2;
595595
auto full = gear.board::image.full();
@@ -609,7 +609,7 @@ namespace netxs::ui
609609
auto& gear = *gear_ptr;
610610
if (gear.mouse_disabled) continue;
611611
auto [tooltip_page_sptr, tooltip_offset] = gear.tooltip.get_render_sptr_and_offset(props.tooltip_colors);
612-
if (tooltip_page_sptr)
612+
if (tooltip_page_sptr && !std::isnan(gear.coord.x))
613613
{
614614
auto& tooltip_page = *tooltip_page_sptr;
615615
auto fs_area = full;
@@ -689,10 +689,6 @@ namespace netxs::ui
689689
{
690690
debug.output(canvas);
691691
}
692-
if (props.legacy_mode & ui::console::mouse) // Render our mouse pointer.
693-
{
694-
draw_mouse_pointer(canvas);
695-
}
696692
if (props.show_regions)
697693
{
698694
canvas.each([](cell& c)
@@ -705,6 +701,10 @@ namespace netxs::ui
705701
});
706702
}
707703
}
704+
if (props.legacy_mode & ui::console::mouse) // Render our mouse pointer.
705+
{
706+
draw_mouse_pointer(canvas);
707+
}
708708
}
709709
else
710710
{

src/netxs/desktopio/consrv.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,10 +966,10 @@ struct impl : consrv
966966
}
967967
void mouse(input::hids& gear, fp2d coord)
968968
{
969-
if (std::isnan(coord.x)) // Forward a mouse halt event.
969+
if (gear.mouse_disabled || std::isnan(coord.x)) // Forward a mouse halt event.
970970
{
971971
auto lock = std::lock_guard{ locker };
972-
auto r2 = nt::console::fp2d_mouse_input{ .coord = coord };
972+
auto r2 = nt::console::fp2d_mouse_input{ .coord = { fp32nan, fp32nan} };
973973
stream.emplace_back(*reinterpret_cast<INPUT_RECORD*>(&r2));
974974
ondata.reset();
975975
signal.notify_one();

src/netxs/desktopio/system.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5740,7 +5740,16 @@ namespace netxs::os
57405740
});
57415741
m.changed++;
57425742
m.timecod = datetime::now();
5743-
mouse(m);
5743+
if (std::isnan(m.coordxy.x))
5744+
{
5745+
m.enabled = input::hids::stat::halt; // Send a mouse halt event.
5746+
mouse(m);
5747+
m.enabled = input::hids::stat::ok;
5748+
}
5749+
else
5750+
{
5751+
mouse(m);
5752+
}
57445753
}
57455754
else if (t == type::mouse) // ESC [ < ctrl ; xpos ; ypos M
57465755
{

src/netxs/desktopio/terminal.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,17 @@ namespace netxs::ui
517517
state = (mode)(state & ~(m));
518518
if (!state) token.clear();
519519
owner.selection_selmod(smode);
520+
auto gates = owner.base::riseup(tier::request, e2::form::state::keybd::enlist); // Take all foci.
521+
for (auto gate_id : gates) // Reset double click state for all gears.
522+
{
523+
if (auto gear_ptr = owner.base::getref<hids>(gate_id))
524+
{
525+
for (auto& [bttn_id, s] : gear_ptr->stamp) // Reset double click state. The issue is related to Far Manager, which changes the mouse tracking mode before releasing the button when double-clicking.
526+
{
527+
s.count = !!s.count; // Set to 1 if non zero.
528+
}
529+
}
530+
}
520531
}
521532
void setmode(prot p) { encod = p; }
522533
};

src/vtm.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,12 +1669,12 @@ namespace netxs::app::vtm
16691669
for (auto& [ext_gear_id, gear_ptr] : usergate.gears)
16701670
{
16711671
auto& gear = *gear_ptr;
1672-
if (gear.mouse_disabled) continue;
1672+
if (gear.mouse_disabled || std::isnan(gear.coord.x)) continue;
16731673
auto coor = twod{ gear.coord } + gear.owner.coor();
16741674
coor.y -= 1;
16751675
coor.x -= half_x;
16761676
user_name.move(coor);
1677-
parent_canvas.fill(user_name, cell::shaders::contrast);
1677+
parent_canvas.fill(user_name, cell::shaders::contrast); //todo revise: segfault?
16781678
usergate.fill_pointer(gear, parent_canvas);
16791679
}
16801680
}

0 commit comments

Comments
 (0)