Кадр-часовой механизм
Все приложения GTK управляются циклом обработки событий (mainloop), что означает, что большая часть времени приложение простаивает внутри цикла, просто ожидая, что произойдет какое-либо событие, а затем обращается к соответствующему месту, когда это происходит. Помимо этого, GTK имеет кадр-часовой механизм, который посылает «пульс» приложению. Этот механизм отбивает с постоянной скоростью, которая связана с частотой кадров вывода (это синхронизировано с монитором через менеджер окон/композитор). Типичная частота обновления составляет 60 кадров в секунду, поэтому новый «пульс» происходит примерно каждые 16 миллисекунд.
Часовой механизм имеет несколько фаз:
События
Обновление
Разметка
Рисование
Фазы происходят в этом порядке, и мы всегда выполним каждую фазу до возвращения к началу.
Фаза событий — это промежуток времени между каждым перерисовкой, когда GTK обрабатывает входные события от пользователя и другие события (например, сетевой ввод-вывод). Некоторые события, такие как движение мыши, сжимаются, так что для обработки требуется только одно событие движения мыши за цикл.
По завершении фазы событий внешние события приостанавливаются, и выполняется цикл перерисовки. Сначала выполняется фаза обновления, где все анимации выполняются для расчета нового состояния на основе приблизительного времени отображения следующего кадра (доступно через кадр-часовой механизм). Это часто включает изменения геометрии, которые приводят к следующей фазе — разметке. Если есть какие-либо изменения в требованиях к размеру виджетов, вычисляется новая разметка для иерархии виджетов (т.е. определяются размеры и позиции всех виджетов). Затем наступает фаза рисования, где перерисовываются области окна, которые требуют перерисовки.
Если фазы обновления/разметки/рисования не требуются, мы останемся в фазе событий навсегда, так как не хотим перерисовывать, если ничего не изменилось. Каждая фаза может запросить дальнейшую обработку в последующих фазах (например, фаза обновления вызовет работу по разметке, а изменения разметки вызовут перерисовки).
Существует несколько способов управления часовым механизмом. На самом низком уровне вы можете запросить конкретную фазу с помощью gdk_frame_clock_request_phase(), что запланирует удар часов по мере необходимости, чтобы он в конечном итоге достиг запрошенной фазы. Однако на практике большинство вещей происходит на более высоких уровнях:
Если вы выполняете анимацию, вы можете использовать
gtk_widget_add_tick_callback(), что вызовет регулярные удары часов с обратным вызовом в фазе обновления до тех пор, пока вы не остановите отсчет.Если какие-то изменения состояния приводят к изменению размера вашего виджета, вы вызываете
gtk_widget_queue_resize(), который запросит фазу разметки и отметит ваш виджет как требующий переразметки.Если какие-то изменения состояния требуют перерисовки какой-либо области вашего виджета, вы используете обычные функции
gtk_widget_queue_draw(). Они запросят фазу рисования и отметят регион как требующий перерисовки.
Также существует множество неявных триггеров этих событий со стороны слоя CSS (который выполняет анимации, изменения размеров и перерисовки по мере необходимости).
© 2005–2020 The GNOME Project
Licensed under the GNU Lesser General Public License version 2.1 or later.
https://developer-old.gnome.org/gtk4/4.0/frameclock.html