Skip to content

Conversation

@yulian5
Copy link

@yulian5 yulian5 commented Oct 2, 2025

Summary

The PR introduces a new feature to Far Manager: panel resizing with mouse.

References

Checklist

  • [ X] I have followed the contributing guidelines.
  • I have discussed this with project maintainers:

    If not checked, I accept that this work might be rejected in favor of a different grand plan.

Details

This feature introduces the ability to resize file panels in Far Manager using the mouse.

Users can now:

  • Hover over the border between the left and right panels to see visual feedback indicating a resizable area (grip).
  • Click and drag the border left or right to dynamically adjust the width of the panels.
  • Double-click on the border to quickly restore the default 50/50 equal width split for the panels.
  • The color of the dragging border between panels can be changed to user's preferences

This enhancement provides a more intuitive and efficient way to manage panel layouts, improving user experience for those who prefer mouse-driven interactions.

It includes updates to:

FarColorW.pas and farcolor.hpp: Defines a new palette color COL_PANELDRAGBORDER for the visual feedback during resizing.

farlang.templ.m4: Adds new localization strings for the "Dragging border" text.

filepanels.cpp and filepanels.hpp: Implements the core logic for mouse event handling, border detection, resizing, and drawing the visual feedback. This includes new MouseState enum, IsMouseOverPanelBorder, DrawBorderFeedback, ClearBorderFeedback, and ResetAllMouseStates functions.

palette.cpp and setcolor.cpp: Initializes and integrates the new COL_PANELDRAGBORDER color into the color palette and settings.

*.hlf.m4 files (e.g., FarEng.hlf.m4, FarRus.hlf.m4): Updates help files for various languages to document the new mouse resizing functionality.

@yulian5
Copy link
Author

yulian5 commented Oct 2, 2025

Do I need to fix any of SonarQubeCloud suggestions?
Thanks!

@alabuzhev
Copy link
Contributor

@yulian5, thanks for your PR.
I haven't looked at the changes yet, just some general comments:

gh-1021.mp4

Functional:

  • It conflicts with the left panel scrollbar.
  • It triggers too early, when the mouse is over the cells adjacent to the panel border:
    • It conflicts with the right panel sort indicator (another way to call Sort Menu & Disk Menu).
    • It conflicts with clicks on file names in both panels.

Visual:

  • It assumes that both panels are of the same height, which is not always the case.
  • Panels can refresh while hovering and partially or fully overwrite the indicator.

It's an interesting feature, but, as you can see, the place is pretty crowded already.
Which is one of the reasons we didn't implement something like this years ago.

@yulian5
Copy link
Author

yulian5 commented Oct 2, 2025

@alabuzhev thank you very much for your testing and valuable inputs. Let me work on remaining issues. Thanks!

@yulian5
Copy link
Author

yulian5 commented Oct 3, 2025

Hi @alabuzhev, I have the working code which addressed all mentioned issues:

far-panels-resizing2

The scrollbar is excluded from mouse resize detection and works as expected, but even with the scrollbar there is still enough grip area for effective resizing even in case of a single panel (what as I see ConEmu cannot do). For next PR I need to finish vertical resizing to complete the task where option for single panel resizing will be useful as well.

I need to clean up the code, add comments, check it for optimization, and then commit new changes. Do I need to modify changelog and vbuild.m4 again or it'll be done during the merge?

Thanks!

@yegor-mialyk
Copy link
Contributor

Do we really want to introduce a new color for this? It would be a breaking change for all custom themes.

@HamRusTal
Copy link
Contributor

HamRusTal commented Oct 3, 2025

there is still enough grip area for effective resizing even in case of a single panel

On the screenshot, I see that the {left panel's cell below the scroll bar where the “status” area separator joins the right-hand-side frame} is not highlighted yellow whereas the corresponding right panel's cell on its left is (no scrollbar there though). Is it for a purpose or just a bug?

BTW Do we need to highlight both panels' frames? IMHO just the one being dragged is enough (at least while dragging). We might still highlight both frames on hover though to indicate that both will be affected.

Also, it would be nice to handle the Esc key press (or RMB click) while dragging to cancel the resize and restore the initial geometry (similar to Windows' window move/resize except for RMB click).

@HamRusTal
Copy link
Contributor

Do we really want to introduce a new color for this? It would be a breaking change for all custom themes.

New color would be nice and flexible. But the code has to handle the missing color gracefully and use a sensible default replacement from the colors defined by the current theme.

@alabuzhev
Copy link
Contributor

Do I need to modify changelog and vbuild.m4

Don't worry about these for now. There might be more changes requested which might take a few days and resolving conflicts every time someone merges into master doesn't make much sense.
Once we're ready to merge I'll let you know and those files can be updated then.

use a sensible default replacement from the colors defined by the current theme

We do not have such a concept. Palette colors are independent and any missing ones will stay default aqua-on-blue-ish.
It might be useful to discuss and explore this more.
For example, background color in quite a few palette items (e.g. panel borders or column titles) is redundant and can be transparent and inherited from panel text or whatever would be previous in Z-order.
However, it might be too much for this particular PR.
Feel free to create an issue or a discussion.

@yulian5
Copy link
Author

yulian5 commented Oct 4, 2025

@yegor-mialyk

Do we really want to introduce a new color for this? It would be a breaking change for all custom themes.

@alabuzhev

It might be useful to discuss and explore this more.

No, it doesn't break anything. All custom color themes work just fine. Yes, we need a new color. There is enum for it and menu entry. Here is sample, you can compile code and try for yourself.

color_border

I realized from the beginning that custom color themes obviously do not have a new color. But they can define it now. The fallback scheme is following: if color for dragging border is not defined in the theme then we use foreground color from dragging text and background color from normal text (panel background). And all color themes I checked have both colors defined. And in case they don't have them it will be yellow on blue that can be changed easily (but it should be something really broken):

custom

It looks natural and work on all themes included in Far by default. It still may be some problems here but I'm sure it's possible to fix.

@yulian5
Copy link
Author

yulian5 commented Oct 4, 2025

@HamRusTal

New color would be nice and flexible. But the code has to handle the missing color gracefully and use a sensible default replacement from the colors defined by the current theme.

Yes, I explained that. Colors were my first concern in this feature!

@yulian5
Copy link
Author

yulian5 commented Oct 4, 2025

@HamRusTal

On the screenshot, I see that the {left panel's cell below the scroll bar where the “status” area separator joins the right-hand-side frame} is not highlighted yellow whereas the corresponding right panel's cell on its left is (no scrollbar there though). Is it for a purpose or just a bug?

Yes, I notice that. The scrollbar at the bottom actually expands more than it depicted and this area is clickable and it scrolls the context down. This looks like the problem with scrollbar implementation. The top part of scrollbar looks fine. We may need to create new issue for that later.

@yulian5
Copy link
Author

yulian5 commented Oct 4, 2025

@HamRusTal

BTW Do we need to highlight both panels' frames? IMHO just the one being dragged is enough (at least while dragging). We might still highlight both frames on hover though to indicate that both will be affected.

Actually I had the similar concern. I tried to make single lines while dragging but it looked awful. You can change dragging border color to normal color, it works very nice except you cannot see when it hovered (but if you know then it's fine). It's very possible to make separate colors for havering and dragging, not a problem at all. Do we need it? It maybe very confusing.

The single panel can be resized with mouse so to simplify the logic both panel borders are highlighted.

Also, it would be nice to handle the Esc key press (or RMB click) while dragging to cancel the resize and restore the initial geometry (similar to Windows' window move/resize except for RMB click).

Yes, it's a very good idea, but that would be a completely separate task. Mouse and key handling in Far is quite complicated even without plugins and macros. Double click works fine for now.

@HamRusTal
Copy link
Contributor

HamRusTal commented Oct 4, 2025

The scrollbar at the bottom actually expands more than it depicted and this area is clickable and it scrolls the context down. This looks like the problem with scrollbar implementation.

Actually, the entire panel frame below the scrollbar (and above it too) performs scrolling when clicked. It looks like a deliberate feature (with its own bugs though). But it does not justify that the resizing drag-highlight does not cover the cell I'm referring to. IMHO this should be fixed in the PR to get a more consistent look and feel.

I tried to make single lines while dragging but it looked awful.

I am not suggesting to use single-line highlighted borders, I am rather suggesting to highlight only one panel's (double-line) border. This will be consistent with resizing of a single visible panel too.

Double click works fine for now.

Double-click does not address the scenario when there's some non-default panel width already and the user starts dragging the panel border (maybe by a misclick). Unfortunately, double-click will not restore the pre-drag non-default layout.

@yulian5
Copy link
Author

yulian5 commented Oct 4, 2025

@HamRusTal

Actually, the entire panel frame below the scrollbar (and above it too) performs scrolling when clicked.

Yes, I already figured is out. I agreed with you and took one cell from the scrolling area:

scroll_area

It displayed as grip area but not working yet.

I am rather suggesting to highlight only one panel's (double-line) border. This will be consistent with resizing of a single visible panel too.

But which one I have to highlight? If I highlight right border and the right panel is hidden? I need to change left/right highlighting depending which panel is hidden And another question: the grip area is actually 2 borders, displaying only have of grip area will be confusing. If it's so important maybe just make it configurable.

Double-click does not address the scenario when there's some non-default panel width already and the user starts dragging the panel border (maybe by a misclick). Unfortunately, double-click will not restore the pre-drag non-default layout.

I agree. Let me check that. If it's easy to implement I'll add it otherwise it will another PR.

BTW, I added height resizing with mouse:

far-resize.mp4

@yulian5
Copy link
Author

yulian5 commented Oct 5, 2025

@alabuzhev

Don't worry about these for now. ...............

Thank you very much for detailed explanation! I updated the code. It happens to be quite a huge project!

@HamRusTal
I added Esc key feature: it's actually more useful for resizing that I excepted and I fixed multiple issues during its implementation.

@yulian5
Copy link
Author

yulian5 commented Oct 6, 2025

Hi @alabuzhev

I uploaded new code which fixed calculation of bottom border around text area for visual feedback during height resizing and fixed SonarQubeCloud issues.

However CodeFactor marked the code with red cross because of complexity GetInputRecordImpl() in keboard.cpp file. That's not my code and I don't think that I need to fix it now. I just added couple small functions to block all keys during resizing and allow only Esc key to revert resizing. Please help with that!

Thanks!

@alabuzhev
Copy link
Contributor

complexity GetInputRecordImpl() in keboard.cpp file

It's fine to ignore.

@yulian5 yulian5 force-pushed the panel-mouse-resizing branch from b285014 to 6fc16f2 Compare October 8, 2025 04:12
@yulian5
Copy link
Author

yulian5 commented Oct 8, 2025

I merged all my commits into one and updated changelog and vbuild.m4 to the latest. But GitHub doesn't merge it in PR automatically.

@yegor-mialyk
Copy link
Contributor

I think we need to revert all removed empty lines back in fielist.cpp

@yulian5
Copy link
Author

yulian5 commented Oct 8, 2025

@yegor-mialyk

think we need to revert all removed empty lines back in fielist.cpp

I did that 2 days ago. It was my mistake. I tried to remove spaces that VS inserts without any reason.

Do you see any removed single empty lines? But I converted some double empty lines to single empty lines between functions just to be consistent through the file. Only one double empty line is remaining before "namespace".

@yegor-mialyk
Copy link
Contributor

Oops, it's my fault, those removed empty lines are duplicates.

@yulian5
Copy link
Author

yulian5 commented Oct 13, 2025

Hi @yegor-mialyk, I see the review is going to be long. I guess you're very busy. Do you need any help from me? I can briefly describe the algorithm and the main changes to the code. Please let me know. Thanks!


static_assert(static_cast<size_t>(panel_sort::BY_USER) == static_cast<size_t>(OPENPANELINFO_SORTMODES::SM_USER));


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls avoid changing formatting, adding or removing lines etc. if it's not directly related to your change.

It could make sense in isolation, or subjectively look better or whatever, but all these tiny changes here and there distract from the important part and only make the reviewing longer.

@yulian5
Copy link
Author

yulian5 commented Oct 25, 2025

Highlighting borders on hover and drag (visual feedback) is quite convenient and helps users use the function without any instructions. But over time, it starts to get a little annoying. I'm thinking of adding an option to disable visual feedback for experienced users. What are your thoughts on this?

@MKadaner
Copy link
Contributor

I have a somewhat unrelated concern, and I apologize that I have not looked at the actual change. So, here it goes: if I have mouse support turned off in Interface settings, will I incur any performance penalty (besides a bit larger memory footprint) when this feature is merged?

@yulian5
Copy link
Author

yulian5 commented Oct 27, 2025

will I incur any performance penalty (besides a bit larger memory footprint) when this feature is merged?

Hi @MKadaner:

Based on code analysis:

The answer is: NO, there will be NO performance penalty when mouse support is turned off.
The reason is Mouse Event Processing is Conditional in Event-Driven Architecture with No Background Processing.

As for Memory Footprint:
This feature adds approximately < 100 bytes of memory per FilePanels instance.

@HamRusTal
Copy link
Contributor

HamRusTal commented Oct 27, 2025

< 100 bytes of memory per FilePanels instance

I assume you mean the additional data, yet the added instructions code will be larger I believe (still not an issue IMHO).

@yulian5
Copy link
Author

yulian5 commented Oct 27, 2025

@MKadaner and @HamRusTal

Nothing in this life comes for free. Here is the full estimates:

x64 Release Build Footprint Estimate:

Code Segment (.text):
• Average x64 instruction density: ~3-4 bytes per line of optimized C++ code
• 640 lines × 3.5 bytes = ~2,240 bytes (~2.2 KB)
Data Segment (.data/.bss):
• Mouse state variables: ~50 bytes
• Static constants: ~30 bytes
• Total data: ~80 bytes
Virtual Function Table entries:
• New virtual methods: ~40 bytes
Total Memory Footprint: ~2.4 KB per process

This is significantly more than initial "< 100 bytes" estimate, which only considered data variables.
The actual code footprint is ~2.4 KB due to the substantial amount of mouse handling logic added.

@MKadaner
Copy link
Contributor

The actual code footprint is ~2.4 KB...

That is, of course, not a concern. Thank you for the confirmation about run-time performance being unaffected.

P.S. I prefer cats over mice.

@yulian5
Copy link
Author

yulian5 commented Oct 28, 2025

@MKadaner, I myself use Far with a keyboard 95% of the time, but resizing the panels using the keyboard just drives me crazy.

Here is the full code performance analysis for mouse processing from claude-4-sonnet AI comparing 2 branches. It says that now it works faster than before with mouse, except resizing. But we didn't have resizing with mouse before. However I don't know how accurate it is.

Input Caching and Early Returns - optimizations from Copilot AI (however it skewed up a lot, I reverted multiple "optimizations")
Conditional Calculations - optimization from me

ProcessMouse Performance Analysis - FarManager.panel-mouse-resizing vs yulian5.master

Performance Impact Analysis
Original Version (yulian5.master) - 55 Lines
Optimized Version (panel-mouse-resizing) - 363 Lines

Performance Optimizations Added:
1. Input Caching (4 lines)
2. Conditional Calculations - Expensive operations only when needed
3. Early Returns - Avoid unnecessary processing

New Mouse Processing Features Added:
• Width Resizing: 125 lines of panel width resize logic
• Height Resizing: 120 lines of panel height resize logic
• Border Detection: 47 lines for hover/click detection
• Visual Feedback: 67 lines for border highlighting

Performance Impact Assessment

Optimizations Gained:
• Memory Access: ~65% reduction in MouseEvent field access through caching
• Calculation Overhead: ~40% reduction by deferring expensive calculations
• Conditional Branching: ~30% improvement through early returns and state checks

Processing Overhead Added:
• Code Size: 6.6x increase (55 → 363 lines)
• Border Detection: +2-4ms per mouse event for geometric calculations
• State Management: +1-2ms for mouse state tracking
• Visual Feedback: +3-5ms when drawing border highlights

Net Performance Impact:

For Normal Mouse Operations (95% of usage):
• Improvement: 15-25% faster due to input caching and early returns
• Memory: 40% fewer memory accesses to MouseEvent fields

For Border Interactions (5% of usage):
• Cost: 5-10ms additional processing for resize operations
• Benefit: Significantly enhanced user experience with visual feedback

Overall Assessment:

The optimizations provide a net performance gain for typical usage while adding rich mouse interaction features. The caching and conditional logic improvements more than offset the additional border processing overhead for normal operations.

Recommendation: The performance optimizations are well-designed and provide both better performance for common operations and enhanced functionality for power users.

P.S. According to this analysis (if it's true) it make sense to add similar optimizations in other processing code in Far.
P.P.S. Dogs vs cats?

@sonarqubecloud
Copy link

@MKadaner
Copy link
Contributor

P.P.S. Dogs vs cats?

Sorry, it's too personal a question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants