Панель на каждом подключённом дисплее - #60
Merged
Conversation
Разрез проходит по курсору: он в один момент времени ровно на одном экране, поэтому «открыта», «на неё тянут файл» и «держит клавиатуру» переезжают в PanelState, по одному на дисплей, а вкладка, хранилища и сервисы остаются общими в NotchViewModel — одна история буфера, один perl-хелпер Now Playing. Экраны сверяются по CGDirectDisplayID, а не по месту в NSScreen.screens: этот массив на каждую переконфигурацию выдаёт новые объекты и может их переставить. Дисплей, чья чёлка не сдвинулась, сохраняет свою панель открытой. Зеркальные пропускаются — вторая панель поверх той же картинки. Телесуфлёр держит открытым один экран, тот, с которого запустили: пин на всех оставил бы панель раскрытой там, куда никто не смотрит. Если этот дисплей отключили, дубль заканчивается — читать больше некому. Настройки → «Дисплеи» сворачивают всё обратно к одному экрану: с физической чёлкой, если она есть, иначе к главному. Применяется сразу. Архитектура разреза — из PR #13. Co-Authored-By: zhd-dm <64752156+zhd-dm@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Узкая полоска в 8 pt и ожидание в 300 мс написаны под маки без чёлки, где синтетическая лежит на работающем меню-баре и под ней иконки статус-итемов, в которые целится курсор. Условием было «не физическая», хотя причина — «под ней меню-бар». На внешнем мониторе без отдельных Spaces меню-бара нет вовсе: visibleFrame доходит до верхней кромки. Осторожность там ничего не защищала, а стоила всего — панель рисовалась высотой 24 pt и отвечала только верхними 8, и открывалась вшестеро дольше встроенной. Теперь решает guardsMenuBar. Нулевая высота меню-бара значит одно из двух — его нет совсем или он спрятан, — поэтому дисплей, который им владеет (screens.first, главный в «Расположении»), считается несущим меню-бар в любом случае: на маке без чёлки с автоскрытием всё остаётся как было. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Полоска в 8 pt и ожидание 300 мс защищают иконки статус-итемов: на узком экране синтетическая чёлка садится ровно туда, где они начинаются, и разворачивать панель поверх того, куда целится курсор, нельзя. Условие же стояло на «чёлка не физическая» — то есть на следствии, а не на причине, и срабатывало там, где защищать нечего. На внешнем мониторе 1920 pt чёлка занимает 870…1050, а иконки начинаются с 1606 — зазор 556 pt. Панель при этом рисовалась высотой 25 pt и отвечала только верхними 8: наводишь на чёлку, ничего не происходит, открывается лишь когда упрёшься в кромку экрана. Теперь положение иконок измеряется. Статус-итемы — окна на уровне статус-бара, рамка окна публична, даже когда картинка нет, поэтому самый левый из них просто считывается через CGWindowList; разрешений это не требует. Догадка о ширине дисплея не подошла бы: иконки начинаются с x≈757 на одном 13-дюймовом маке и с x≈1158 на другом — это факт о том, сколько их у человека. Замер повторяется, когда панель сворачивается: иконки появляются и исчезают вместе с приложениями, а свёрнутая панель — единственный момент, когда пересборка ничего не стоит. Проверено на двух экранах: на LG панель открывается на 22 pt ниже верхней кромки, в глубине чёлки, — раньше только с 8. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Уровень statusWindow может попросить кто угодно — плавающая панель утилиты посреди экрана лежит на нём же. Фильтр проверял только «окно на этом дисплее», поэтому одно такое окно слева читалось как иконка, дотянувшаяся до чёлки, и зона молча схлопывалась до полоски в 8 pt. Теперь окно должно пересекать полосу меню-бара этого экрана. Пустой список — не доказательство пустого меню-бара: одна Пультовая держит там несколько окон. Значит замер не удался, и это читается как «тесно», с прежней осторожной полоской. Окна window-серверу перечисляются один раз на всю пересборку, а не по разу на экран: вопрос у всех экранов один и тот же. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Конфликт был один и содержательный: #44 чинил залипание раскрытой панели в старом NotchController, а здесь он разобран на общий контроллер и NotchScreenPanel на каждый дисплей. Порядок «сначала клавиатура, потом свёртка» тут уже был; чего не было — явного releaseKey и запроса на перерисовку, потому что acceptsKeyboard перестал отдавать ключ сам. Оба перенесены в NotchScreenPanel, где теперь живёт закрытие. Остальное сошлось само: closeDelay 0.05 и свой стиль тумблера из #42, заготовки из #47 и #49, скрытие из #51. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3.
Четыре коммита про чёлку плюс пятый — встреча с тем, что приехало в
mainза сегодня.Что делают первые четыре
NotchViewModelстал общим состоянием приложения, а всё, что относится к одному экрану(открыта ли панель, тянут ли файл, держит ли клавиатуру), вынесено в
PanelState;NotchControllerдержит поNotchScreenPanelна дисплей, сверяя их по стабильномуCGDirectDisplayID, а не по индексу вNSScreen.screens.перекрытие пунктов меню из На маке без челки синтетическая челка занимает середину меню-бара #3.
Что пришлось разрешить руками
Единственный конфликт —
NotchController: #44 чинил залипание раскрытой панели в старой,односпановой архитектуре, которой здесь больше нет. Порядок «сначала клавиатура, потом свёртка»
в новой уже был и сделан аккуратнее — через
openGeneration. Не было второй половины: после #44acceptsKeyboardбольше не отдаёт ключ сам, это делает явныйreleaseKey(), и в новойархитектуре его никто не звал — панель осталась бы с клавиатурой. Перенёс
releaseKey()и запросна перерисовку в
NotchScreenPanel.collapse()и вsetKeyboard(false)для закрытой панели.Остальные восемь сегодняшних правок сошлись без конфликтов.
Проверено локально:
swift build,./Scripts/bundle.sh release,./Scripts/test-helper.sh(хелпер ответил живым треком), проверка ключей перевода — чисто, 70 ключей.
🤖 Generated with Claude Code