При попыткее установить сертификат с носителя при отсутствии носителя должно появляться сообщение "Не найдено ни одного носителя секретного ключа". В wine это сообщение появляется под другими окнами. /var/ftp/pvt/Windows/Учётные, бухгалтерские/SBIS/demo 2.3.38 /var/ftp/pvt/Windows/Учётные, бухгалтерские/CryptoPro CSP/3.6/csp-win32-kc1-rus.msi Контрагенты -> Налогоплательщики -> Изменить -> Создать новый сертификат -> Установить с носителя -> Загрузить с носителя
Откладываем в связи с временным отсутствием исполнителя bugs@
В eterhack для СБИС 2.4.43 сообщение появляется поверх окон и удерживает фокус до уничтожения, а окно Мастера создания сертификатов (видимо окно-владелец сообщения об ошибке) может менять свой Z-order, хотя не должно. Такая-же ситуация с диалогом Контрагенты -> Налогоплательщики
Проверим оконные классы диалогов.
Проблемные окна - системные диалоги, класс #32770
СБИС устраивает сабклассинг для диалогов. Нужно просмотреть в Windows последовательности оконных сообщений, которые получает обычный модальный диалог без сабклассинга и диалог СБИС.
Если изменить стиль окна диалога через SetWindowLong() во время WM_INITDIALOG, то в Wine диалог прорисовывается как неактивный и сохраняется таким пока клиентская область не получит клик мышью. Возможно есть связь с текущей проблемой.
Принципиальной разницы в сообщениях получаемых DefDlgProc под Windows для СБИС и приложения с диалогом без сабклассинга нет.
При попытке активировать окно-владелец модального диалога в Wine, диалог вообще не получает сообщений, а владелец получает только WM_SETCURSOR (Для обычного диалога, созданного через DialogBoxParam). Возможно проблемный участок находится в обработчике этого сообщения.
В DefDlgProc нет мер к предотвращению изменения Z-order'a диалога, кроме того окно-владелец получает WM_SETCURSOR с параметром HTERROR. Получается, что к этому моменту системе известно о существовании диалога. Вероятно за расположение окон отвечает код, генерирующий WM_SETCURSOR для окна-владельца.
В Windows при попытке активирования окна-владельца кроме WM_SETCURSOR передается WM_WINDOWPOSCHANGING СО СБРОШЕННЫМ SWP_NOZORDER, который затем устанавливает DefWindowProc (т.к. WM_WINDOWPOSCHANGED не отправляется). В Wine этих сообщений нет вообще.
Создана тестовая программа с поведением, подобным поведению СБИС. Тест создает главное окно стиля WS_OVERLAPPEDWINDOW | WS_VISIBLE, затем создается СКРЫТОЕ дочернее окно (owned. стиль WS_OVERLAPPEDWINDOW)). При создании диалога в качестве родителя указываем скрытое дочернее окно. Под Windows главное окно может получить фокус, но при этом диалог все равно остается выше него в Z-ordere'e. Под Wine диалог проваливается под главное окно.
Под Wine не наблюдается сообщений, связанных с изменением положения окна. Видимо система сама решает вопросы связанные с позиционированием диалогов и скрывает это от приложения. Нужно вывести WM_WINDOWPOSCHANGING наружу.
Поиск участка изменяющего положение диалога пока не дал результатов. Как вариант можно попробовать ставить для диалога WS_EX_TOPMOST пока приложение активно и сразу удалять этот стиль при активировании другого приложения.
В некоторых случаях диалог уплывает под главное окно после получения WM_WINDOWPOSCHANGING. (Оно все-таки принимается, но расположено далеко от сообщений мышиных кнопок, поэтому и не было замечено сразу)
Диалог проваливается получая WM_POSCHANGING с флагом SWP_NOZORDER : (hChild - родитель g_hDlg) Dialog: msg=0046 wParam=00000000 lParam=0032F714 g_hwnd -> hChild -> g_hDlg -> screen /* Reverse Z-order */ hWndAfter=00000000 Flags=00000015 /* SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE */ Dialog: msg=0047 wParam=00000000 lParam=0032F714 g_hwnd -> screen /* Reverse Z-order */ Флаги примерно такие и должны быть, но результат совсем не тот что просили.
В стеке вызовов к моменту перемещения диалога имеется SetForegroundWindow(). Простой вызов этой функции ведет к тому же эффекту, что и активирование главного окна, т.е. под Windows окно становится активным и находится под диалогом, а в Wine диалог уходит под главное окно.
При перемещении диалога под главное окно происходит вызов SetForegroundWindow(), параметром передается дескриптор диалога. Получается, что функция не ставит диалог поверх остальных окон (или ее работу сразу скрывает результат другой функции). Судя по трейсу подъем главного окна по z-order'y осуществляется функцией типа SetWindowPos() (нужно уточнить)
Пробуем разыскать участок отвечающий за удерживание диалога "на плаву". Поиск в цикле сообщений модальных диалогов и IsDialogMessage() пока безрезультатен. Более того в Windows IsDialogMessage() можно выбросить из цикла обработки сообщений и диалог (правда немодальный) все равно остается над главным окном приложения.
Проблема не связана только с диалогами. Создаем невидимое owned окно, от него производим еще одно такое-же, но видимое. Т.е. MainAppWnd >> Owned_1level (invisible) >> Owned_2level В Windows Owned_2level всегда держится поверх MainAppWindow. В Wine плавает.
Шунтирование SetForeground() и других функций, которые потенциально могут заниматься перемещением окна не дало результатов. В трейсе видно, что перемещение окна сопровождается вызовом RedrawWindow(). В стеке вызовов перед ней идет process_events(). Причем отладчик не смог опознать ее аргументы, а в теле этой функции нет явных вызовов RedrawWindow().
Попытался сделать хак, перемещая окно-предок под все видимые окна-потомки сразу после set_foreground_window(), set_focus()... В итоге ничего хорошего не вышло: вайн зацикливается постоянно пытаясь вернуть окно на передний план. Нужно попробовать решить задачу на уровне X Window, т.к. неправильное поведение начинается именно там.
Иксовые окна создаются только если они должны быть видимыми. Т.е. CreateWindowEx() без WS_VISIBLE не создает Х-окно. Т.е. крайние окна из комментария 19 оказываются несвязанными на Х-уровне. Потому и ведут себя как siblings.
Попытки поднять главное окно через SetWindowPos(), SetForegroundWindow() не работают, т.е. все так как и должно быть. Если поставить останов на X11DRV_ButtonPress() то к моменту срабатывания отладчика главное окно уже поднялось. Трейс по каналам win x11drv не дал ничего существенного. Можно предположить, что окно выше которого подниматься нельзя задается во время CreateWindow().
В Windows owned-окно всегда находится над самым верхним видимым окном в цепочке owned-окон. По этому поводу сделаны исправления в set_wm_hints(). Проблема частично ушла: теперь диалог "Налогоплательщики" держится на нужном месте. Сообщение "Не найдено ни одного носителя секретного ключа" продолжает плавать. Но здесь дело в том, что перед тем как выбросить это сообщение, СБИС запрещает "Мастер создания сертификата" через EnableWindows(). После этого запрещенное окно не должно принимать ввод, а значит и двигаться в Z-order'e. Для Вайна это не выполняется.
Заблокировать окно во время EnableWindow() проблематично. Пытаюсь сделать хак, который будет подменять действительное окно-хозяин на самое верхнее видимое в цепочке owned-окон или же самое верхнее запрещенное окно ( что раньше найдется ) для установки WM_TRANSIENT_FOR.
Решил.
wine@eter-2 bottle SBIS/5671 WINE@Etersoft SQL 2.0.0-eter4.23/14 Все в порядке. Принято.
Откатил из-за больших изменений в этом месте. Revert "winex11.drv: Hack for SBIS windows positioning (eterbug #5671)" This reverts commit e9da76d94dbc5d95614470b1fe8bd5e80bade930.
(В ответ на comment #28) > Откатил из-за больших изменений в этом месте. > Revert "winex11.drv: Hack for SBIS windows positioning (eterbug #5671)" > > This reverts commit e9da76d94dbc5d95614470b1fe8bd5e80bade930. В таком случае уместно было бы сделать общее решение для подобных проблем (нарушения zorder'a при наличии невидимых окон в ownership chain), пригодное для свободного вайна. Пытаюсь найти подходящую стратегию.
(В ответ на comment #29) > Пытаюсь найти подходящую стратегию. Провел небольшое исследование для создания тестов.
(В ответ на comment #30) > (В ответ на comment #29) > > Пытаюсь найти подходящую стратегию. > > Провел небольшое исследование для создания тестов. Работаю над тестами.
Работаю над задачей.
> (В ответ на comment #28) > > Откатил из-за больших изменений в этом месте. > > Revert "winex11.drv: Hack for SBIS windows positioning (eterbug #5671)" > > > > This reverts commit e9da76d94dbc5d95614470b1fe8bd5e80bade930. > > В таком случае уместно было бы сделать общее решение для подобных проблем > (нарушения zorder'a при наличии невидимых окон в ownership chain), пригодное > для свободного вайна. > Пытаюсь найти подходящую стратегию. В принципе, достаточно было бы обновить патч, но так как срочность отпала, можно было бы закончить с тестами. Как успехи? Может быть, Дмитрий поможет, если у него спросить? Может быть, для нынешнего eterhack всё уже лучше?
Откладываем задачи, к которым не обращались более 100 дней.
Релиз 1.0.12 больше не актуален и не отгружается. Работа по поддержке СБиС++ больше не ведётся. Если потребуется продолжить работу, то перетест уже будет в актуальной сборке. Закрываю.