fixed comment into code
This commit is contained in:
@@ -6,12 +6,12 @@ using Accessibility;
|
||||
namespace CursorLang.Interop;
|
||||
|
||||
/// <summary>
|
||||
/// Определяет положение каретки в активном поле ввода — в том числе в чужом приложении.
|
||||
/// Locates the caret in the active input field — including one in another application.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Единого способа нет: классические Win32-приложения заводят системную каретку,
|
||||
/// а Chrome, Electron и прочие рисуют её сами и сообщают положение только через
|
||||
/// средства доступности. Поэтому сначала спрашиваем систему, затем — приложение.
|
||||
/// There is no single way to do it: classic Win32 applications create a system caret,
|
||||
/// while Chrome, Electron and others draw it themselves and report its position only
|
||||
/// through accessibility interfaces. So we ask the system first, then the application.
|
||||
/// </remarks>
|
||||
internal static class CaretNative
|
||||
{
|
||||
@@ -32,8 +32,8 @@ internal static class CaretNative
|
||||
private const int CHILDID_SELF = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Прямоугольник каретки в пикселях экрана или <c>null</c>, если активное
|
||||
/// приложение не сообщает её положение.
|
||||
/// The caret rectangle in screen pixels, or <c>null</c> when the active
|
||||
/// application does not report its position.
|
||||
/// </summary>
|
||||
internal static PopupWindowNative.Rect? TryGetCaretRect()
|
||||
{
|
||||
@@ -50,13 +50,13 @@ internal static class CaretNative
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отсеивает заведомо неверные координаты.
|
||||
/// Filters out obviously wrong coordinates.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Часть приложений отдаёт положение каретки в своей системе координат либо
|
||||
/// без учёта масштаба экрана, и подсказка уезжает далеко от поля ввода.
|
||||
/// Каретка обязана находиться внутри окна ввода — это и проверяем, а перед
|
||||
/// отказом пробуем истолковать координаты как немасштабированные.
|
||||
/// Some applications report the caret position in their own coordinate system or
|
||||
/// without accounting for display scaling, and the popup ends up far from the input
|
||||
/// field. The caret must be inside the input window — that is what we check, and
|
||||
/// before giving up we try to read the coordinates as unscaled ones.
|
||||
/// </remarks>
|
||||
private static PopupWindowNative.Rect? Validate(PopupWindowNative.Rect caret, IntPtr hwndFocus)
|
||||
{
|
||||
@@ -86,16 +86,16 @@ internal static class CaretNative
|
||||
inner.Left >= outer.Left && inner.Right <= outer.Right &&
|
||||
inner.Top >= outer.Top && inner.Bottom <= outer.Bottom;
|
||||
|
||||
/// <summary>Сколько ждём ответа от чужого приложения по UI Automation.</summary>
|
||||
/// <summary>How long we wait for another application to answer over UI Automation.</summary>
|
||||
private static readonly TimeSpan AutomationTimeout = TimeSpan.FromMilliseconds(150);
|
||||
|
||||
// Браузеры и другие приложения на своих движках рисуют каретку сами и
|
||||
// сообщают её положение только через UI Automation. Запрос идёт в чужой
|
||||
// процесс, поэтому он самый медленный и стоит последним
|
||||
// Browsers and other applications with their own rendering engines draw the caret
|
||||
// themselves and report its position only through UI Automation. The request goes
|
||||
// into another process, so it is the slowest one and comes last
|
||||
private static PopupWindowNative.Rect? TryGetAutomationCaret()
|
||||
{
|
||||
// Зависшее приложение не должно подвешивать подсказку вместе с собой:
|
||||
// ждём ответ ограниченное время, иначе показываем у курсора
|
||||
// A hung application must not hang the popup along with it: we wait for the
|
||||
// answer for a limited time, otherwise we show the popup at the cursor
|
||||
Task<PopupWindowNative.Rect?> query = Task.Run(QueryAutomationCaret);
|
||||
return query.Wait(AutomationTimeout) ? query.Result : null;
|
||||
}
|
||||
@@ -117,8 +117,8 @@ internal static class CaretNative
|
||||
return null;
|
||||
}
|
||||
|
||||
// У каретки выделение пустое и прямоугольника не имеет,
|
||||
// поэтому расширяем его до ближайшего символа
|
||||
// The caret has an empty selection and therefore no rectangle,
|
||||
// so we expand it to the nearest character
|
||||
TextPatternRange range = selection[0].Clone();
|
||||
range.ExpandToEnclosingUnit(TextUnit.Character);
|
||||
|
||||
@@ -141,12 +141,12 @@ internal static class CaretNative
|
||||
or InvalidOperationException
|
||||
or COMException)
|
||||
{
|
||||
// Приложение закрылось или не отвечает — подсказку это ронять не должно
|
||||
// The application closed or stopped responding — that must not take the popup down
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Системная каретка: координаты приходят относительно окна, которому она принадлежит
|
||||
// The system caret: its coordinates come relative to the window that owns it
|
||||
private static PopupWindowNative.Rect? TryGetSystemCaret(ForegroundInputNative.GuiThreadInfo info)
|
||||
{
|
||||
if (info.hwndCaret == IntPtr.Zero || IsEmpty(info.rcCaret))
|
||||
@@ -170,7 +170,7 @@ internal static class CaretNative
|
||||
};
|
||||
}
|
||||
|
||||
// Каретка через средства доступности: сюда попадают браузеры и Electron
|
||||
// The caret through accessibility interfaces: this is where browsers and Electron land
|
||||
private static PopupWindowNative.Rect? TryGetAccessibleCaret(IntPtr hwndFocus)
|
||||
{
|
||||
if (hwndFocus == IntPtr.Zero)
|
||||
@@ -199,7 +199,7 @@ internal static class CaretNative
|
||||
}
|
||||
catch (COMException)
|
||||
{
|
||||
// Приложение объявило поддержку, но положение не отдало
|
||||
// The application declared support but did not report the position
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
@@ -208,7 +208,7 @@ internal static class CaretNative
|
||||
}
|
||||
}
|
||||
|
||||
// Когда каретки нет, её прямоугольник приходит нулевой высоты.
|
||||
// Судим только по высоте: нулевые координаты — это обычное начало пустого поля
|
||||
private static bool IsEmpty(PopupWindowNative.Rect rect) => rect.Bottom - rect.Top <= 0;
|
||||
// When there is no caret, its rectangle comes back with zero height.
|
||||
// We judge by height alone: zero coordinates are a normal start of an empty field
|
||||
internal static bool IsEmpty(PopupWindowNative.Rect rect) => rect.Bottom - rect.Top <= 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user