LINUX.ORG.RU

Кому шлется сообщение в иксах?

 


0

2

Есть три окна, два имеют первого родителем:

┌─────────────────┐
│ W1              │
│ ┌────┐          │
│ │W2  │          │
│ └────┘          │
│ ┌────┐          │
│ │W3  │          │
│ └────┘          │
└─────────────────┘

Кликнули мышкой на W2, сигнал получило W2. После этого навели курсор мыши на W3 и нажали клавишу на клавиатуре. Сигнал получило W3.

Так и должно быть? Или сигнал должно получить W2, как получившее до этого фокус а я что-то делаю неправильно?

sudo -b cast Zubok

★★

Так и должно быть? Или сигнал должно получить W2, как получившее до этого фокус а я что-то делаю неправильно?

Все правильно. Так и должно быть. Чтобы не пересказывать уже написанное, приведу цитату:

The delivery of keyboard events in X is designed in a way that does not correspond to the typical operation of modern toolkits; instead it seems designed to allow things to allow things to work without either a window manager or a focus handling in the toolkit. Typically, key events are sent to the window which has the X input focus (set with XSetInputFocus()). However, if the mouse pointer is inside that focus window, the event is sent to the subwindow of the focus window that is under the mouse pointer. In modern toolkits, the X input focus is typically left on the toplevel window and a separate logical input focus is implemented within the toolkit. The toolkit ignores the window that the key event is actually sent to (which might be a scrollbar or other random widget within the toplevel, depending on where the mouse pointer is), and distributes key events to widget with the logical input focus.

Zubok ★★★★★
()

Так и должно быть?

It depends. Стоит послушать FocusIn и FocusOut, чтобы узнать, у кого же на самом деле фокус и какой.

ilammy ★★★
()
Ответ на: комментарий от Zubok

Ага, большое спасибо, я несколько дней думал что это у мен косяк.

sambist ★★
() автор топика

Кликнули мышкой на W2, сигнал получило W2.

Или сигнал должно получить W2, как получившее до этого фокус а я что-то делаю неправильно?

То, что ты кликнул, еще не значит, что W2 получило фокус. Фокус, скорее всего, у тебя имеет W1, которому оконный менеджер его дал. W1 — top-level окно. Для того, чтобы W2 получило фокус, надо его ему явно передать при помощи XSetInputFocus по клику в нем. К сожалению, я не вижу кода. Может быть, ты и передаешь фокус W2. но в посте об этом не сказано. А так как W3 не есть подокно W2, то в этом случае я ожидаю, что после XSetInputFocus(...W2...) клавиатура будет все время слать сообщения в W2, пока оно не потеряет фокус.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Ммм! А я вот несколько раз наблюдал решения когда пытаешься поставить в фокус родительское, которое находится под всплывшим, но «оно не даёт», и оставляет в фокусе всплывшее, пока ты в нем что-то там не впишешь или не выберешь (закрыв его). Можешь ссылкой кинуть где почитать про реализацию?

И вообще интересно насчет целой цепочки таких зависимых окон. По идее работать должно. А на деле?

deep-purple ★★★★★
()
Ответ на: комментарий от Zubok

Для того, чтобы W2 получило фокус, надо его ему явно передать при помощи XSetInputFocus по клику в нем.

сненько, спасибо, в моем случае этого не требуетс. Вот к текстовым полм такое применю и попробую, но дл кнопок не вижу смысла - мне проще пробежатьс циклом по элементам смотр у кого кастомный флаг «focus» и получить индекс элемента, чем иметь какие-то подводные камни с XSetInputFocus.

sambist ★★
() автор топика
Ответ на: комментарий от deep-purple

Есть два поведения: первое — флаг override redirect при создании окна (выпадающих меню, например), второе — читать ICCCM на предмет свойства окна WM_TRANSIENT_FOR (обычно диалоговые окна, окна выбора файлов). Для второго есть функция XSetTransientForHint.

А я вот несколько раз наблюдал решения когда пытаешься поставить в фокус родительское, которое находится под всплывшим, но «оно не даёт», и оставляет в фокусе всплывшее, пока ты в нем что-то там не впишешь или не выберешь (закрыв его). Можешь ссылкой кинуть где почитать про реализацию?

Это, скорее всего, WM_TRANSIENT_FOR. Открываешь любое приложение, например, GTK. в терминале пишешь:

$ xprop | grep "WM_TRANSIENT_FOR"

и клацаешь в диалог. В диалогах, которые не дают что-то ввести в родительском окне, это свойство будет, а в обычных окнах эта команда ничего не выдаст. Можешь проверить.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от sambist

Ну это как-то зря :) Если у тебя тулкит, то завести в top-level переменную hasInputFocus, которая содержит текущий window ID, который владеет фокусом. При передаче фокуса между разными полями менять эту переменную. Все приходящие сообщения от клавиатуры, соответственно, перенаправлять в это окно. По виджетам бегать не надо.

Да, а XSetInputFocus не трогать вообще.

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 4)
Ответ на: комментарий от sambist

Есть библиотека libXt (X Toolkit Intrinsics). Она в xorg/lib/libXt идет. На ее основе сделаны lesstif, motif, xaw. Возможно, что кто-то еще. Вот там эта функциональность по отслеживанию и передаче фокуса сделана. Можно подсмотреть, как работает. Ищи по focusWidget, focusKid.

Еще там реализована функция по передаче фокуса *клавиатуры* без XSetInputFocus:

man XtSetKeyboardFocus (страничка должна быть уже в системе)

И вот еще.

http://www.polarhome.com:823/doc/library/SGI_bookshelves/SGI_Developer/books/...

Zubok ★★★★★
()
Последнее исправление: Zubok (всего исправлений: 1)
Ответ на: комментарий от Zubok

Вот там эта функциональность по отслеживанию и передаче фокуса сделана
Если у тебя тулкит, то завести в top-level переменную hasInputFocus, которая содержит текущий window ID, который владеет фокусом.

Почти так - есть «склад», в нем элементы без различи по типам - окна, кнопки, текстуры etc. Кнопка, которой пришел сигнал KeyDown знает индекс своего родительского окна (W), идем циклом по складу, смотрим тип=кнопка, парент=W, стейт&focus=true, перенаправлем мессадж этой кнопке.

Есть у меня еще мысль, чтобы не бегать по всему складу, который иногда разрастаетс на тысчи элементов добавить типу «окно» перменную спискового типа - а туда добавлть индексы всех чайлдов-виджетов.

Ну или да, как вы сказали - вместо всего списка только одна переменна, котора будет содержать индекс текущего окна с фокусом, дешево и сердито.

Спасибо за идею.

sambist ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.