gug-bg-herd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Аналог на GDK_INVERT при cairo/GTK 3


From: Yavor Doganov
Subject: Re: Аналог на GDK_INVERT при cairo/GTK 3
Date: Mon, 11 Nov 2019 01:40:32 +0200
User-agent: Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM/1.14.9 (Gojō) APEL/10.8 EasyPG/1.0.0 Emacs/26 (x86_64-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO)

Kaloian Doganov wrote:
> Малко е неудобно да се чете функция без изрично упоменати входящи
> параметри. :-)

Извинявам се, реших да ги спестя, защото не съм ги променял
и вече дадох връзка към оригиналната функция.  Ето ги:

static void
draw_selection (GtkPlotCanvas *canvas, GtkPlotCanvasChild *child,
                GtkAllocation area)

GtkPlotCanvas е подклас на GtkWidget (в оригиналния код е на
GtkObject, но в GTK 3 този тип обект го няма), аргумента child може да
го игнорираш напълно, а area е структура (реално GdkRectangle, което
пък е cairo_rectangle_t) с 4 члена: x, y, width и height.

> Правилното изпълнение на тази стратегия (с прерисуване на всичко), е
> движението на мишката да тригерира прерисуване на графиката, а веднага
> след прерисуването на графиката да се рисува селекцията отгоре.  Не
> знам как това се прави с GTK и Cairo, но нещо такова трябва да се
> организира.  Представям си, че би могъл да се закачиш за ::draw и, ако
> имаш активна селекция, да си  рисуваш селекцията веднага след като
> стандартния ::draw се изпълни, но това са хвърчащи фантазии.

Проблемът е, че при движението на мишката правоъгълника се променя и
нещо трябва да „трие“ следите.  Точно това прави dovtk-lasso, което ми
изглежа доста сложно, за моя мозък поне.  Състоянието се записва в
серия правоъгълници, които се опресняват при движението,
възстановявайки основата.  Това GDK_INVERT го прави автоматично и то
"under the hood", както се казва.

> Не ми става ясно в какво се изразява премигването -- премигва само
> селекцията или цялата графика?  Ако е само селекцията, този ефект
> сигурно ще изчезне ако рисуваш селекцията веднага след ::draw на
> графиката.

Трепти само селекцията и това е съвсем естествено, понеже след всяко
изпълнение на draw_selection (което е много пъти в рамките на този
motion event), се задейства ::draw, който рисува цялата графика
наново, изтривайки правогълника, очертаващ селекцията.

> При всички положения, обаче, ми се струва добра идея да се закачиш за
> ::draw и да рисуваш селекцията веднага след "стандартния" ::draw на
> графиката (по възможност синхронно, в същия пас на main queue-то).

Това прави dovtk-lasso.  Обектът се закача на собствен ::draw, свързан
с g_signal_connect_after и чрез сложен (за мен) механизъм се грижи за
обновяването и възстановяването на териториите, които засягаш при
чертането на селекцията.  Естествено, трябва да възбуждаш обновяването
чрез dovtk_lasso_update на съответните места в event handler-ите.

> Едва сега попрегледах кода в gtkplotcanvas.c и, честно казано, ми се
> струва, че логиката около рисуването на widget-а поначало е некоректна.
> Авторът има имплементация на draw, която не рисува пълният state на
> widget-а.  Вместо това изглежда, че draw рисува базовата графика, а
> после авторът рисува допълнително в резултат от някакви събития (напр.
> движение на мишката).  Това е доста кофти, защото ако draw бъде извикан
> по друг повод, нарисуваното на екрана ще излезе от синхрон с
> потребителския state.

Да, това е типична практика при много програми, писани за GTK 2 (и
1.2, BTW), работи си без проблем.  Понеже събитието „провлачване с
мишка“ се инвалидира при почти всяко друго събитие, това не е голям
кахър.

> Ето един пример, който е малко измислен, но е първото което се сетих
> докато преглеждах кода: Ако натиснем левия бутон на мишката върху
> графиката, преместим курсора за да се появи селекция, и -- без да
> пускаме левия бутон -- натиснем клавишната комбинация за Maximize на
> текущия прозорец, селекцията се одрисква.

Пробва ли го?  Аз съм на Window Maker и нямам клавишна комбинация за
максимизиране, но пробвах с Alt-Tab да положа друг прозорец върху
графиката -- това незабавано инвалидира селекцията и не се случва
нищо, просто пунктирания правоъгълник изчезва.

> Този ефект е пряко следствие от липсата на читав draw, който да
> отразява текущия модел върху екрана. Изображението на екрана се
> получава от основния draw, плюс още нафлякани неща върху него които се
> рисуват не по време на draw -- при движение на мишката се трие старата
> селекция, рисува се нова, т.н. 

Дори и да се чертае само от ::draw, това няма как да промени нещата и
няма как да ме улесни по никакъв начин.  На практика
gdk_window_begin_draw_frame чертае в offscreen буфер, който след
gdk_window_end_draw_frame се рисува ефективно на екрана.  Ако чертая
само от ::draw и изпълнявам draw_selection оттам на базата на някаква
глобална булева променлива, която се контролира от event handler-ите,
това несъмнено е по-добре, но няма как да реши проблема с
възстановяването на основната графика при движението на мишката.

> Най-простият начин да се организират тези неща е събитията да водят до
> смяна на някакъв невидим state в widget-а (т.нар. модел), а draw да
> рисува на базата на този невидим state.  Напр. event handler-а за
> движение на мишката трябва само да сменя някакви числови координати в
> модела на текущата селекция и да тригерира draw (независимо дали
> синхронно с draw или асинхронно с queue_draw), който да ги нарисува. 
> Това е най-простият начин да се осигури кохерентност.

Това прави dovtk-lasso, хвърли едно око на кода.  Искаше ми се точно
тази сложност да избегна.

> Вярно е, че понякога тригерирането на пълен redraw при всяко събитие
> може да води до големи разходи на ресурси.

Дизайнът на GTK 3 е изцяло подчинен на пестене на ресурси.  Резултатът
е много повече код (като обем, а и понякога като сложност) за
разработчиците на приложения, но за сметка на повече ресурси.  Както
се казваше навремето: казармата е тежка, но за сметка на това
продължителна.

Няма страшно, идва GTK 4, което ще е супер-юбер-хипер версия на
библиотеката.  Толкова гот, че планират да чупят ABI регулярно.

> Струва ми се, че проблемите които срещаш с портването на селекцията
> са следствие от това, че авторът поначало е организирал рисуването
> нехигиенично.

Не, това е генерален проблем при GTK и cairo, който не съществува при
GDK 2.  Както е писал потребителя във връзката, която дадох.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]