Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: strelok_krr от Сентябрь 19, 2011, 16:48



Название: Не ожидаемая передача фокуса
Отправлено: strelok_krr от Сентябрь 19, 2011, 16:48
Добрый день.
в первые пришлось столкнуться с Qt и Xlib.
Задача была такая - написать виртуальную клавиатуру для основного приложения (возможность использования точскрина) и оно должно быть постоянно в фокусе, т.е. при нажатии кнопки на виртуальной клавиатуре, фокус должен возвращаться назад.
реализовал это так:
Код:
//-------------------------------------------------------------------------------------------------------------------------------
void SendEvent(XKeyEvent *event, bool press)
{
if (press)
XSendEvent(event->display, event->window, True, KeyPressMask, (XEvent *)event);
else
XSendEvent(event->display, event->window, True, KeyReleaseMask, (XEvent *)event);
XSync(event->display, False);
XAllowEvents( event->display, ReplayKeyboard, CurrentTime);
XFlush( event->display );
}
//-------------------------------------------------------------------------------------------------------------------------------
void CWidget::btnClicked()
{
qDebug( "CWidget::btnClicked" );
Window win = *( m_curW->getLastWindow() );
XSetInputFocus( m_curW->getDisplay(), win, RevertToPointerRoot, CurrentTime );
XKeyEvent event;
event.display = m_curW->getDisplay();
event.window = win;
event.root = RootWindow(event.display, DefaultScreen(event.display));
event.subwindow = win;//None;
event.time = CurrentTime;
event.x = 1;
event.y = 1;
event.x_root = 1;
event.y_root = 1;
event.same_screen = True;
event.type = KeyPress;
event.state = 16;
event.keycode = XKeysymToKeycode(event.display, XStringToKeysym ("F6") );
SendEvent(&event, true);
event.type = KeyRelease;
SendEvent(&event, false);
}
проблема вот в чем. после передачи фокуса с клавиатуры, если в приложении отрыть и закрыть диалоговое окно, фокус возвращается не в "родительское" окно, а в клавиатуру.
Как это можно побороть?
заранее благодарен, за помощь.


Название: Re: Не ожидаемая передача фокуса
Отправлено: strelok_krr от Сентябрь 20, 2011, 17:56
В общем, пока сделал так: при старте виртуальной клавиатуры запоминаются все дескрипторы окон, также запоминается последние "чужие" окна. далее при получении фокуса на клавиатуру возвращаю фокус на последнее существующее окно из стека. решение кривое, но все же.
если, у кого есть другое решение, с удовольствием выслушаю.
Код:
void CCurrentWindow::findAllOurWindows( Window &window )
{
Window rootW, subwindow, *children;
unsigned int children_count;
XQueryTree( m_dsp, window, &rootW, &subwindow, &children, &children_count );

for( unsigned int i = 0; i < children_count; ++i ) {
m_ourW.push_back( children[i] );
findAllOurWindows( children[i] );
}
XFree( children );
}
//-------------------------------------------------------------------------------------------------------------------------------
void CCurrentWindow::loop()
{
if (m_dsp == NULL)
{
qDebug("ERROR! Couldn't connect to display %p.\n", m_dsp );
return ;
}
int revert_to;
*m_cur = DefaultRootWindow(m_dsp);
m_ourW.push_back( *m_cur );
findAllOurWindows( *m_cur );
*m_last = *m_cur;

unsigned int i, size = m_ourW.size();
qDebug( "count our windows=%d", size );
if ( 0 == size ) {
return;
}

const unsigned int stackOutWSize = 5;
m_stackOutW.push_back( DefaultRootWindow(m_dsp) );

Window tmp;
bool fFind = false;
bool fFirstOut = true;
do {
XGetInputFocus( m_dsp, &tmp, &revert_to );
if ( tmp <= 0 ) {
sleep(1);
continue;
}
for( i = 0; i < size; ++i ) {
if ( m_ourW[i] == tmp ) {
fFind = true;
*m_cur = tmp;
if ( !fFirstOut ) {
std::list<Window>::iterator it = m_stackOutW.end(), it_e = m_stackOutW.begin();
if ( it != it_e ) {
XWindowAttributes ret;
--it;
bool fFindWindow = false;
do {
if ( XGetWindowAttributes( m_dsp, *it, &ret ) && ( IsViewable == ret.map_state ) ) {
qDebug( "CCurrentWindow::loop Set out focus winId=%lu", *it );
fFindWindow = true;
break;
}
qDebug( "CCurrentWindow::loop Delete not used window %lu", *it );
m_stackOutW.erase( it );
--it;

} while ( it != it_e );
if ( fFindWindow ) {
XSetInputFocus( m_dsp, *it, RevertToPointerRoot, CurrentTime );
}
}
}
break;
}
}
if ( !fFind && ( *m_last != tmp ) ) {
*m_last = tmp;
fFirstOut = false;
if ( stackOutWSize < m_stackOutW.size() ) {
m_stackOutW.pop_front();
qDebug( "Delete old window" );
}
qDebug( "set new window focus [%lu]", tmp );
m_stackOutW.push_back( tmp );
}
fFind = false;

sleep(1);
} while( true );
}
//-------------------------------------------------------------------------------------------------------------------------------


Название: Re: Не ожидаемая передача фокуса
Отправлено: lit-uriy от Сентябрь 20, 2011, 19:23
можно политику фокуса установить в "Нет фокуса" для клавиатуры


Название: Re: Не ожидаемая передача фокуса
Отправлено: GreatSnake от Сентябрь 20, 2011, 19:32
Цитировать
проблема вот в чем. после передачи фокуса с клавиатуры, если в приложении отрыть и закрыть диалоговое окно, фокус возвращается не в "родительское" окно, а в клавиатуру.
А кто является родителем диалога?


Название: Re: Не ожидаемая передача фокуса
Отправлено: spirt от Сентябрь 21, 2011, 11:25
А еще можно посмотреть QInputContext. И пример его использования: %QTDIR%/examples/tools/inputpanel


Название: Re: Не ожидаемая передача фокуса
Отправлено: strelok_krr от Сентябрь 21, 2011, 14:18
Цитировать
проблема вот в чем. после передачи фокуса с клавиатуры, если в приложении отрыть и закрыть диалоговое окно, фокус возвращается не в "родительское" окно, а в клавиатуру.
А кто является родителем диалога?
стороннее приложение для которого пишется клавиатура.
А еще можно посмотреть QInputContext. И пример его использования:  %QTDIR%/examples/tools/inputpanel
забыл уточнить, в разработке используется Qt3 :(


Название: Re: Не ожидаемая передача фокуса
Отправлено: strelok_krr от Сентябрь 21, 2011, 14:19
можно политику фокуса установить в "Нет фокуса" для клавиатуры
уточните, пожалуйста, не понял о чем идет речь.