OberonCore
https://forum.oberoncore.ru/

Как оконная система BB определяет регионы корневого фрейма?
https://forum.oberoncore.ru/viewtopic.php?f=24&t=5086
Страница 1 из 1

Автор:  Иван Кузьмицкий [ Понедельник, 28 Апрель, 2014 13:47 ]
Заголовок сообщения:  Как оконная система BB определяет регионы корневого фрейма?

Оконная система поставила в тупик. Как она определяет регионы корневого фрейма документа при наложении двух и более окон?

То есть, у нас есть документ, открытый в окне (это основа документо-ориентированного интерфейса ББ). К окну всегда привязан Корневой Фрейм, для которого вычисляется область обновления. То есть, документ будет обновляться не целиком, а только в нужной области, при необходимости. Область обновления аппроксимирует сразу несколько участков (см. прикреплённый рисунок, границы области показаны зелёной рамкой), которые хранятся в массиве window.frame.update.

Области добавляются сразу же, как только наше окно было накрыто другим. Но как наше окно понимает, что надо взять размеры чужого окна?

Вложения:
bb_overlap.png
bb_overlap.png [ 35.09 КБ | Просмотров: 7805 ]

Автор:  Димыч [ Понедельник, 28 Апрель, 2014 16:50 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

Смотреть в сторону Ports.OpenBuffer и обработку WM_PAINT. Там есть параметр ps, который PAINTSTRUCT.

При обработке этого события Windows возвращает кусок окна (rcPaint), который надо обновить.

Подробности, разумеется, в MSDN (BeginPaint/EndPaint).

Автор:  Иван Кузьмицкий [ Понедельник, 28 Апрель, 2014 18:34 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

Ports.OpenBuffer вызывается уже после того, как все регионы определены, в процедуре Views.RestoreRoot. А вот вычисление областей обновления происходит в Views.UpdateRoot.

Причём там идёт работа с фреймами документа, и я не понимаю, каким образом геометрия вышележащего окна учитывается в этих вычислениях.

Автор:  ilovb [ Понедельник, 28 Апрель, 2014 20:18 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

искать: WinApi.InvalidateRect


Ну и о чем Димыч говорил:
Код:
WinApi.WM_PAINT:
            w := ThisWindow(wnd);
            w.GetSize(dx, dy);
            IF ~w.minimized THEN
                (* clip region must be reset to ensure correct ps.paint ! *)
                res := WinApi.SelectClipRgn(w.port(HostPorts.Port).dc, 0);
                x := WinApi.BeginPaint(w.wnd, ps);
                Kernel.Try(InvalidateWin, wnd, x, SYSTEM.ADR(ps.rcPaint));
                res := WinApi.EndPaint(w.wnd, ps);
                Kernel.Try(PaintWin, wnd, 0, 0);
                Controllers.ResetCurrentPath();
                RETURN 0
            END

Автор:  Иван Кузьмицкий [ Понедельник, 28 Апрель, 2014 20:37 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

Эта штука, винапишная InvalidateRect используется только в одном месте - в реализации Windows.dir.Select.

А окно Windows.Window использует платформо-независимые средства Views.UpdateRoot и Views.RestoreRoot. Есть описание этого дела, но кое-чего не хватает.

P.S. Да, похоже, что в w.Restore передаётся нужная область, а перерисовка инициируется как для верхнего окна, так и для нижнего.

Автор:  ilovb [ Понедельник, 28 Апрель, 2014 20:59 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

Похоже в ББ свой велосипед InvalidateWin

Думаю, что нужно курить цепочку:
1. обработка WinApi.WM_PAINT
2. Kernel.Try(InvalidateWin, wnd, x, SYSTEM.ADR(ps.rcPaint));
3. w.Restore(rp.left, rp.top, rp.right, rp.bottom)
4. Views.UpdateRoot(w.frame, l, t, r, b, Views.keepFrames)
5. AddRect(root, root, l, t, r, b, rebuild)

Плюс курить типы:
Код:
Rect = RECORD
    v: View;
    rebuild: BOOLEAN;
    l, t, r, b: INTEGER
END;

Region = POINTER TO RECORD
    n: INTEGER;
    r: ARRAY maxN OF Rect
END;

RootFrame* = POINTER TO RECORD (Frame)
    flags-: SET;
    update: Region    (* allocated lazily by SetRoot *)
END;

Автор:  Димыч [ Вторник, 29 Апрель, 2014 04:11 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

Поскольку мне не надо было спускаться ниже, я дальше OpenBuffer особо не разбирался.

Сейчас посмотрел дальше по цепочке вызовов.
В HostWindows есть процедура InvalidateWin, которая вызывается как раз для каждого обновляемого региона (параметром идет указатель на регион).
Внутри идет вызов w.Restore(), который через Views.UpdateRoot(w.frame, l, t, r, b, Views.keepFrames) производит добавление региона во фрейм. И затем, во время вызова Window.Update производится Views.ValidateRoot().

Как-то так.

Автор:  Иван Кузьмицкий [ Вторник, 29 Апрель, 2014 13:44 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

Подключил к ББ консольный логгер и посмотрел, как оно работает :)

При каждом движении окна "bb.open", вызывается InvalidateWin для нижележащих окон "(Host)Ports" и "(Host)Windows". В логе, кстати, заметно небольшое приращение координат области перерисовки для окна "(Host)Windows" - это я аккуратно двигал окно консоли слева направо по горизонтали.

Интересно заметить, что накопление областей перерисовки и сама перерисовка окна разнесены по разным процедурам: w.Restore и w.Update. Это значит, что определение конечной области перерисовки, внутри ББ может происходить в несколько приёмов, и становится понятным назначение структуры модуля Views
Код:
Region = POINTER TO RECORD
   n: INTEGER;
   r: ARRAY maxN OF Rect
END;
...это буфер! Переменная n здесь обозначает количество накопленных областей. Причём сброс n происходит только в Views.ValidateRoot (и в SetRoot, но это в данный момент неважно).

Здесь есть некоторая тонкость. Views.ValidateRoot использует процедуру Views.RestoreRoot для перерисовки каждой области буфера (к слову, количество этих областей ограничено числом 30, чего вполне достаточно, ведь как правило, перерисовки требует только одна область, вычисленная в Views.AddRect.). А эта процедура публичная, значит - её может нечаянно вызвать клиент, не подозревающий о том, что буфер областей ещё не прошёл обработку с помощью Views.RemoveFrames. Поэтому в RestoreRoot мы видим предусловие
Код:
ASSERT(root.update.n = 0, 22);
..., которое служит причиной возникновения одного неприятного и таинственного трапа, от которого мы никак не можем избавиться при использовании своих отображений.

Ну и теперь я могу сделать самый для меня важный вывод. Если делать оконную систему на базе SDL, то про частичное обновление экрана можно забыть. Насколько я знаю, там нет возможности определения областей перерисовки для окна. Ну, собственно, это не страшно, сделать полное обновление окна по нынешним временам операция почти незаметная )

Вложения:
bb_win_invalidate.png
bb_win_invalidate.png [ 56.88 КБ | Просмотров: 7730 ]

Автор:  Иван Кузьмицкий [ Пятница, 02 Май, 2014 15:47 ]
Заголовок сообщения:  Re: Как оконная система BB определяет регионы корневого фрей

Внезапно до меня дошло, что SDL самостоятельно и прозрачно для программиста обновляет окна. Если окно не в фокусе, то ему не приходят оконные сообщения из SDL, но зато содержимое окна перерисовывается автоматически.

Другими словами, нарисовал и забыл. И это сильно упрощает логику работы с окнами в SDL-хосте для ББ!

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/