OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Среда, 16 Октябрь, 2019 14:44

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
СообщениеДобавлено: Понедельник, 28 Апрель, 2014 13:47 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2931
Откуда: г. Ярославль
Оконная система поставила в тупик. Как она определяет регионы корневого фрейма документа при наложении двух и более окон?

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

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


Вложения:
bb_overlap.png
bb_overlap.png [ 35.09 КБ | Просмотров: 3712 ]
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 28 Апрель, 2014 16:50 
Аватара пользователя

Зарегистрирован: Среда, 29 Март, 2006 12:09
Сообщения: 495
Смотреть в сторону Ports.OpenBuffer и обработку WM_PAINT. Там есть параметр ps, который PAINTSTRUCT.

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

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 28 Апрель, 2014 18:34 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2931
Откуда: г. Ярославль
Ports.OpenBuffer вызывается уже после того, как все регионы определены, в процедуре Views.RestoreRoot. А вот вычисление областей обновления происходит в Views.UpdateRoot.

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 28 Апрель, 2014 20:18 

Зарегистрирован: Вторник, 30 Июнь, 2009 14:58
Сообщения: 1549
искать: 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 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2931
Откуда: г. Ярославль
Эта штука, винапишная InvalidateRect используется только в одном месте - в реализации Windows.dir.Select.

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

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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Понедельник, 28 Апрель, 2014 20:59 

Зарегистрирован: Вторник, 30 Июнь, 2009 14:58
Сообщения: 1549
Похоже в ББ свой велосипед 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 
Аватара пользователя

Зарегистрирован: Среда, 29 Март, 2006 12:09
Сообщения: 495
Поскольку мне не надо было спускаться ниже, я дальше OpenBuffer особо не разбирался.

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

Как-то так.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 29 Апрель, 2014 13:44 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2931
Откуда: г. Ярославль
Подключил к ББ консольный логгер и посмотрел, как оно работает :)

При каждом движении окна "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 КБ | Просмотров: 3637 ]
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 02 Май, 2014 15:47 

Зарегистрирован: Четверг, 17 Ноябрь, 2005 11:51
Сообщения: 2931
Откуда: г. Ярославль
Внезапно до меня дошло, что SDL самостоятельно и прозрачно для программиста обновляет окна. Если окно не в фокусе, то ему не приходят оконные сообщения из SDL, но зато содержимое окна перерисовывается автоматически.

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


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
cron
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2019, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB