С Новым годом! Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/9: Рейтинг темы: голосов - 9, средняя оценка - 5.00
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88

Как получить заголовки активного приложения в Linux?

15.05.2024, 13:14. Показов 3137. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте ребята. У меня есть такая задача: мне нужно раз в некоторое время (в 4 секунды) получать информацию о приложении с которым сейчас работает пользователь. Нужно знать заголовок окна, путь процесса в системе и на какой хост отправляет данные приложение. Я написала (с помощью статей со stackowrflow) следующий код:

файл ActiveApplication.hpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//
// Created by tania on 13.05.24.
//
 
#ifndef NFLDMODULE_ACTIVEAPPLICATION_HPP
#define NFLDMODULE_ACTIVEAPPLICATION_HPP
 
#include <Poco/SharedPtr.h>
#include <Poco/Logger.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <tasks/window/WindowInfo.h>
#include <list>
#include <array>
 
using namespace tasks::window;
 
class ActiveApplication {
 
public:
 
    /* конструктор класса
         @param logger тип Poco::Logger - ссылка на Poco::Logger для ведения логов внутри класса
         * */
    explicit ActiveApplication(Poco::Logger& logger);
 
    // деструктор класса
    ~ActiveApplication() = default;
 
    /* метод получающий нужную нам информацию из активного окна
         @return Poco::SharedPtr<WindowInfo> - возвращает умный указатель на структуру хранящую сведения об окне
         * */
    Poco::SharedPtr<WindowInfo> getActiveWindowInfo();
 
    /* метод получающий окно верхнего уровня
         @return X11::Window - возвращает одно из открытых окон приложений
         * */
    Poco::SharedPtr<WindowInfo> getTopWindow();
 
private:
 
    /**
        Приватный метод получающий некоторое свойство окна
        @param xWindow указатель на тип Window из xLib - корневое окно
         @param xPropertyType тип Atom из xLib - тип свойства которое нужно получить
         @param propertyName тип const char* - имя свойства которое нужно получить
        @return const char* - массив бай содержащий информацию об окне
        */
    unsigned char* getProperty(Window xWindow, Atom xPropertyType, const char* propertyName);
 
    std::string getWindowTitle(Window& xWindow);
 
    int getPidWindow(Window& xWindow);
 
    std::string getPathApp(int pid);
 
    // указатель на главный дисплей ОС, с которого мы будем получать окна приложений
    Display* xDisplay_{};
 
    // ссылка на логгер который ведёт у нас логирование
    Poco::Logger& logger_;
 
    // период по которому мы повторяем действия в runTask
    const int32_t sleep_period_{4000}; // 4 секунды
};
 
#endif    //NFLDMODULE_ACTIVEAPPLICATION_HPP
файл ActiveApplication.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//
// Created by tania on 13.05.24.
//
 
#include "ActiveApplication.hpp"
 
ActiveApplication::ActiveApplication(Poco::Logger& logger)
    : logger_(logger)
{
};
 
Poco::SharedPtr<WindowInfo> ActiveApplication::getActiveWindowInfo()
{
    setenv("DISPLAY", ":0", 1);
    xDisplay_ = ::XOpenDisplay(NULL);
    Window activeWindow = NULL;
 
    unsigned char* property = getProperty(::XDefaultRootWindow(xDisplay_), XA_WINDOW, "_NET_ACTIVE_WINDOW");
 
    if (property != nullptr)
    {
        activeWindow = *(reinterpret_cast<Window*>(property));
    } else
    {
        logger_.information("error get property _NET_ACTIVE_WINDOW");
        ::XCloseDisplay(xDisplay_);
        return nullptr;
    }
 
    // получим нужные нам данные об активном окне приложения заполним нашу структуру эти данными
    Poco::SharedPtr<WindowInfo> windowInfo = Poco::makeShared<WindowInfo>();
 
    // заголовок окна
    windowInfo->name = this->getWindowTitle(activeWindow);
    windowInfo->pid  = this->getPidWindow(activeWindow);
    windowInfo->path = this->getPathApp(windowInfo->pid);
 
    ::XCloseDisplay(xDisplay_);
 
    return windowInfo;
}
 
Poco::SharedPtr<WindowInfo> ActiveApplication::getTopWindow()
{
    xDisplay_ = ::XOpenDisplay(NULL);
 
    Poco::SharedPtr<WindowInfo> windowInfo{nullptr};
    Atom prop_NET_CLIENT_LIST = XInternAtom(xDisplay_,"_NET_CLIENT_LIST",False);
    unsigned long len, remain;
    unsigned char *output;
    int i,form;
    Atom type;
    Window *list;
 
    if (Success == XGetWindowProperty(xDisplay_,XDefaultRootWindow(xDisplay_),prop_NET_CLIENT_LIST,0,1024,False,XA_WINDOW,
                                      &type,&form,&len,&remain,&output))
    {
        list = (Window*)output;
        std::cout<<"len = "<<(int)len<<std::endl;
        const int count = (int)len;
        long item_user_time {1000000};
        int index{-1};
 
        for (i=0;i<count;i++)
        {
            std::cout << "i = " << i << std::endl;
 
            unsigned char* property = getProperty(::XDefaultRootWindow(xDisplay_), XA_WINDOW, "_NET_WM_USER_TIME");
 
            if (property != nullptr)
            {
                unsigned long long_property = static_cast<unsigned long>(property[0] + (property[1] << 8) + (property[2] << 16) + (property[3] << 24));
                logger_.information("user_time=[%hu]", long_property);
 
                if (long_property < item_user_time)
                {
                    item_user_time = long_property;
                    index = i;
                }
            }
        }
 
        if (index >= 0)
        {
            // получим нужные нам данные об активном окне приложения заполним нашу структуру эти данными
            windowInfo = Poco::makeShared<WindowInfo>();
 
            // заголовок окна
            windowInfo->name = this->getWindowTitle(list[index]);
            windowInfo->pid  = this->getPidWindow(list[index]);
            windowInfo->path = this->getPathApp(windowInfo->pid);
        }
    }
 
    ::XCloseDisplay(xDisplay_);
    return windowInfo;
}
 
// метод получающий некоторое свойство окна
unsigned char* ActiveApplication::getProperty(Window xWindow, Atom xPropertyType, const char* propertyName)
{
    Atom xProperty = ::XInternAtom(xDisplay_,propertyName,False);
 
    if (xProperty == None)
    {
        logger_.information("error get property - %s",propertyName);
        return nullptr;
    }
 
    Atom xActualType = None;
    int actualFormat = 0;
 
    unsigned long  itemsNumber     = 0;
    unsigned long  remainigBytes   = 0;
    unsigned char *pProperty       = NULL;
    const long     maxPropertySize = 4096;
 
    try {
        int result = ::XGetWindowProperty(xDisplay_,
                                          xWindow,
                                          xProperty,
                                          0,
                                          maxPropertySize / 4,
                                          False,
                                          xPropertyType,
                                          &xActualType,
                                          &actualFormat,
                                          &itemsNumber,
                                          &remainigBytes,
                                          &pProperty);
 
        if (result != Success) {
            logger_.information("error get property window - %s", propertyName);
            return nullptr;
        }
    }
    catch (std::exception& ex)
    {
        logger_.critical("Critical error in ActiveApplication::getProperty: %s", std::string(ex.what()));
    }
 
    return  pProperty;
}
 
std::string ActiveApplication::getWindowTitle(Window& xWindow)
{
    unsigned char* netwmName = getProperty(xWindow,
                                           ::XInternAtom(xDisplay_, "UTF8_STRING", False),
                                           "_NET_WM_NAME");
 
    if (netwmName == nullptr)
            netwmName = getProperty(xWindow,
                                ::XInternAtom(xDisplay_, "UTF8_STRING", False),
                                "WM_NAME");
 
    if (netwmName != nullptr)
        return std::string((char*)netwmName);
    else
        return "";
}
 
int ActiveApplication::getPidWindow(Window& xWindow)
{
    unsigned char* wmPid = getProperty(xWindow,
                                       AnyPropertyType,
                                       "_NET_WM_PID");
 
    if (wmPid != nullptr)
    {
        // PID процесса, которому принадлежит это окно
        unsigned long long_property = static_cast<unsigned long>(wmPid[0] + (wmPid[1] << 8) + (wmPid[2] << 16) + (wmPid[3] << 24));
        return (int)long_property;
    }
    return -1;
}
 
std::string ActiveApplication::getPathApp(int pid)
{
    //получим путь к исполняемому файлу процесса, которому принадлежит активное окно
    char path[32];
    sprintf(path, "/proc/%d/exe", pid);
 
    // вызов системной функции Linux, возвращающей путь в системе до исполняемого файла
    return realpath(path,NULL);
}
Мой класс хорошо справляется со своей задачей и получает заголовки окон. Но он работает только если графическая оболочка X11 по умолчанию выбрана. При тестировании на ubuntu и kubuntu я имею разные показатели работы. На kubuntu всё хорошо работает, так как там по умолчанию используется Xorg. А вот на ubuntu 24 код не заработал, приложение всё время крашилось при попытки обращения к библиотеки xlib (хотя я её статически линкую). Стали разбираться почему такое поведение. Попробовали в консоли выполнить команду получения активного окна через свойства _NET_ACTIVE_WINDOW и получили ошибку -
Немного погуглив нашли на одном форуме ответ, что в новых версиях ubuntu по умолчанию используется wayland графическая оболочка - https://superuser.com/question... me-windows

Перед нами стала задача, а возможно ли как-то абстрагироваться от типов оболочки и получать заголовки окон независимо от используемой графической подсистемы ? Вдруг через месяц выйдет новая подсистема и получается что нам придётся и под неё писать свою реализацию. Может кто знает способ универсальный ? Может можно как-то на уровне ядра ОС реализовать мою задачу ? Может можно, как антивирусы подключиться в системе к событию запуска приложения ? И перехватывать информацию о нём ? Кто-нибудь может подсказать решение ?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.05.2024, 13:14
Ответы с готовыми решениями:

Как получить параметры активного приложения windows
Здравствуйте, задача следующая, нужно получить данные открытого приложения по нажатию hotkey. Т.е. я работаю с word файлом, нажимаю...

Как получить имя активного приложения переднего плана Android?
Использовались getRunningTasks(int) и getRunningAppProcesses(), которые после Android 5.0+ выдают только мое приложение. Также пробовала...

Получить имя активного приложения
Добрый день! Подскажите советом, мне нужно получить имя приложения активного в данный момент (т.е. того, с которым сейчас работает...

25
 Аватар для Azathtot
754 / 351 / 90
Регистрация: 07.01.2023
Сообщений: 1,451
15.05.2024, 13:21
Цитата Сообщение от tiny developer Посмотреть сообщение
Перед нами стала задача, а возможно ли как-то абстрагироваться от типов оболочки и получать заголовки окон независимо от используемой графической подсистемы ?
Не-а... разные наборы "базовых" элементов
Цитата Сообщение от tiny developer Посмотреть сообщение
Кто-нибудь может подсказать решение ?
Писать две ветки кода - для иксов и для вяленого...
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
15.05.2024, 13:43
Цитата Сообщение от Azathtot Посмотреть сообщение
и для вяленого...
Насколько я помню, там это проблематично (нужно, чтоб поддерживалось спец. расширение).
Так что вторая ветка разрастается во много веток под каждый DE.
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
19.05.2024, 21:19  [ТС]
Благодарю вас за ответы! Я прочитала несколько статей о том, как мне получить активное окна на wayland. И к сожалению поняла что это почти не возможно, так как у них другая политика безопасности. Мне не удалось найти ни одного примера, ни одной библиотеки...
Единственное решение какое мы нашли с другим разработчиком, так это то что мы на ubuntu включили в настройках Xorg по умолчанию и наша программа заработала. И вот я думаю как это можно сделать из приложения ? Может кто сможет подсказать мне ?

Есть у меня и ещё вопрос) поступил запрос реализовать некоторую ещё функциональность:
чтобы каждое окно вело отдельно логи нажатых клавиш(достаточно Ру Англ) и
передавало по накоплению или времени событие с текстом, имя окна и имя процесса


Я хотела спросить у вас как лучше реализовать это ? Мне получается нужно будет в системе подписаться на события клавиатуры ? Интересно как сделать такое наблюдение за окнами...
У меня есть такая идея: подписаться на события клавиатуры и при получения события нажатия клавиши получать в этот момент активное окно и сохранять в некоторый стек нажатых клавиши для этого окна. Затем по истечении некоторого времени - отправляем событие. Хороший ли это будет способ реализации ? Где мне взять пример почитать как подписаться на события клавиатуры ?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
19.05.2024, 21:34
Цитата Сообщение от tiny developer Посмотреть сообщение
И вот я думаю как это можно сделать из приложения ?
Для смены бэкэнда нужно выходить из сессии (перезапускать Display Manager), так просто не переключить.
0
 Аватар для Azathtot
754 / 351 / 90
Регистрация: 07.01.2023
Сообщений: 1,451
20.05.2024, 07:01
Цитата Сообщение от tiny developer Посмотреть сообщение
Я хотела спросить у вас как лучше реализовать это ?
Ну что бы получить события клавиатуры/указателей без разделения по окнам, то просто читайте все события из /dev/input/eventX, а далее по активному окну "раскладывайте" их
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
28.05.2024, 20:14  [ТС]
Добрый вечер дорогие ребята. Я всё ещё ищу решения кейлоггера для своей программы. Чтение директории /dev/input/eventX не очень хорошо работает у меня. Иногда подвисает. Я стала искать другие способы решения и нашла один пример - https://stackoverflow.com/ques... rd-hooking
Мне понравилось что в этом примере мы подписываемся на события X сервера и нам очень удобно получить и активное окно в котором была нажата клавиша. Но мне не удаётся заставить работтаь данный код... подскажите, пожалуйста, как исправить ошибку?
Я получаю вот такую ошибку -
C++
1
2
error: reference to non-static member function must be called
   33 |         XRecordEnableContext(dpy, rc, keyPressed, NULL);


Ругается на фнукцию keyPressed
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
28.05.2024, 21:44
Цитата Сообщение от tiny developer Посмотреть сообщение
Ругается на фнукцию keyPressed
keyPressed не может быть нестатической функцией членом.
Контекст (this) нужно передавать через аргумент closure.
Напр.:
C++
1
2
3
4
5
6
7
8
9
10
11
12
class Some
{
  void keyPressed(XRecordInterceptData *data);
 
  void foo()
  {
    //...
    auto callback = [](XPointer closure, XRecordInterceptData *data){ ((Some*)closure)->keyPressed(data); };
    Status st = XRecordEnableContext(dpy, rc, callback, (XPointer)this);
    //...
  }
};
Добавлено через 1 час 13 минут
Пардон, XPointer это алиас для char*, а не void*, так что нужно явное преобразование (код примера подправил).
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
30.05.2024, 22:03  [ТС]
Очень благодарна вам за ответ! Но к сожалению я столкнулась теперь с другими ошибками... и мне кажется что что-то в системе у меня отломалось. Я приведу вам код своего файл main.cpp
Очень прошу вас помочь мне сделать этот маленький рабочий пример кейлоггера.
Я так же нашла в интернете интересный код и старалась его изучить, чтобы по нему и написать свой простой кейлоггер.
Приведу ссылку на статью - https://github.com/espanso/esp... native.cpp

Код моего файла main.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <Poco/AutoPtr.h>
#include <Poco/ConsoleChannel.h>
#include <Poco/FormattingChannel.h>
#include <Poco/PatternFormatter.h>
#include <Poco/Util/JSONConfiguration.h>
#include <Poco/Util/LayeredConfiguration.h>
 
#include <net/NetClient.hpp>
#include <storage/DbContext.hpp>
#include <tasks/process/ProcessTask.hpp>
#include <tasks/schedule/ScheduleTask.hpp>
#include <tasks/screenshot/ScreenshotTask.hpp>
#include <tasks/window/WindowTask.hpp>
#include <X11/Xlibint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/keysymdef.h>
#include <X11/keysym.h>
#include <X11/extensions/record.h>
#include <X11/extensions/XTest.h>
#include <X11/XKBlib.h>
#include <X11/Xatom.h>
 
using namespace storage::entities;
 
void initLogger() {
    // Инициализация логгера
    Poco::AutoPtr<Poco::PatternFormatter> pattern_formatter(new Poco::PatternFormatter());
    pattern_formatter->setProperty(Poco::PatternFormatter::PROP_PATTERN, "%L%Y-%m-%d %L%H:%M:%S [%s-%I] [%p] %t");
    Poco::AutoPtr<Poco::ConsoleChannel> console_channel(new Poco::ConsoleChannel);
    Poco::AutoPtr<Poco::FormattingChannel> log_console_channel(
        new Poco::FormattingChannel(pattern_formatter, console_channel));
 
    Poco::Logger::root().setChannel(log_console_channel);    // log_channel
 
#ifdef _DEBUG
    Poco::Logger::root().setLevel(Poco::Message::Priority::PRIO_TRACE);
#else
    Poco::Logger::root().setLevel(Poco::Message::Priority::PRIO_INFORMATION);
#endif
}
 
 
void key_pressed_cb(XPointer arg, XRecordInterceptData *d);
 
int scan(int verbose) {
    XRecordRange* rr;
    XRecordClientSpec rcs;
    XRecordContext rc;
    Display *dpy = XOpenDisplay(NULL);
    rr = XRecordAllocRange();
    rr->device_events.first = KeyPress;
    rr->device_events.last = ButtonReleaseMask;
    rcs = XRecordAllClients;
    rc = XRecordCreateContext (dpy, 0, &rcs, 1, &rr, 1);
    XFree (rr);
    XRecordEnableContext(dpy, rc, key_pressed_cb, NULL);
}
 
 
void key_pressed_cb(XPointer arg, XRecordInterceptData *d) {
    if (d->category != XRecordFromServer)
        return;
 
    int key = ((unsigned char*) d->data)[1];
    int type = ((unsigned char*) d->data)[0] & 0x7F;
    int repeat = d->data[2] & 1;
 
    if(!repeat) {
        switch (type) {
            case KeyPress:
                printf("key press %d\n", key);
                break;
            case KeyRelease:
                printf("key release %d\n", key);
                break;
            case ButtonPress:
                printf("button press %d\n", key);
                break;
            case ButtonRelease:
                printf("button release %d\n", key);
                break;
            default:
                break;
        }
    }
    XRecordFreeData (d);
}
 
int main() {
    initLogger();
    Poco::Logger& logger(Poco::Logger::get("LDModuleTest"));
 
    scan(True);
 
    std::this_thread::sleep_for(std::chrono::seconds(3600));
    return 0;
}
Как вы думаете могу я ожидать от моего кода, что когда я запущу его то он поймает нажатые клавиши в других приложениях и выведет мне их ?
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
30.05.2024, 22:08  [ТС]
Ошибка которую я получаю:



Я использую conan и через него все библиотеки подтягиваю. Я искала по этой ошибке в интернете. Пробовала через conan использовать такие библиотеки:
libevdev/1.13.1
libxslt/1.1.39
они успешно собираются, но не решают ошибки...

Как вы думаете что можно было бы ещё предпринять ?

Работаю я в студии CLion, использую компилятор Clang 17 стандарт. ОС kubuntu 20.04 LTS
Для сборки проекта я использую cMake.
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
30.05.2024, 22:15  [ТС]
@zayats80888 могу я оставить вам мой телегграмм ? Я была бы рада получить оперативную помощь от вас.
мой телеграмм: @OnyfriiEgipet
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
30.05.2024, 22:25
tiny developer, это ошибки линковки, попробуйте в параметры компилятора добавить опцию -lXtst
0
 Аватар для Azathtot
754 / 351 / 90
Регистрация: 07.01.2023
Сообщений: 1,451
30.05.2024, 22:27
tiny developer,
XRecordXXXX хотят либу Xtst
И как бы да, все работает
P.S. Клангом тоже все собирается
clang++ -o xkey xkey.cpp -lX11 -lXtst
Миниатюры
Как получить заголовки активного приложения в Linux?  
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
30.05.2024, 22:29  [ТС]
я очень благодарна вам за ответ! Попробую, поищу где это делается в CLion студии и напишу вам результат)
да вознаградит вас Господь Бог за вашу отзывчивость.
0
 Аватар для Azathtot
754 / 351 / 90
Регистрация: 07.01.2023
Сообщений: 1,451
30.05.2024, 22:37
Цитата Сообщение от tiny developer Посмотреть сообщение
Попробую, поищу где это делается в CLion студии и напишу вам результат)
Вот про это не скажу, но для CMake
Code
1
2
3
4
5
6
7
8
 find_package(PkgConfig REQUIRED)
 pkg_check_modules(X11 REQUIRED x11)
 pkg_check_modules(XTST REQUIRED xtst)
 target_link_libraries (xxxx
  ....
  "${X11_LIBRARIES}"
  "${XTST_LIBRARIES}"
)
Под бубутой/бибизьяном устанавливаем libxtst-dev пакет
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
04.06.2024, 13:30  [ТС]
Добрый день ребята. У меня получилось запустить программу) нажатые клавиши в разных приложениях она отслеживает. И у меня возник вопрос. Как мне получить не код клавиши, а значение ? Если нажали букву, то получить букву ? Учитывая раскладку клавиатуры (русская и английская). Кто может мне подсказать как это сделать?
0
 Аватар для Azathtot
754 / 351 / 90
Регистрация: 07.01.2023
Сообщений: 1,451
04.06.2024, 15:15
tiny developer, А у вас нет желания потратить пару недель и изучить документацию X11? Или будете с каждым вопросом сюда бегать?
Есть такой объект XIC
Для него применим метод Xutf8LookupString вот его и используйте для преобьразования. Как получить экземпляр XIC для конкретной раскладки (ну и соответственно получить раскладку конкретного окна) - читайте сами. Подскажу, это вызов XkbGetKeyboard()
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
04.06.2024, 16:39  [ТС]
спасибо вам за подсказку))) и за то что всё-таки ответили)
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
21.06.2024, 19:16  [ТС]
Добрый вечер. Прочитала много статей, просмотрела много примеров. Но к сожалению не получается у меня в моём решении получить правильный символьный код клавиши. Я пробовала разные способы из статьи - примеры использования Xutf8LookupString
Эти примеры недописанные, там в почти в каждом необъявленные переменные. Я пыталась адаптировать в свой код. Но я не понимаю откуда мне получить объект XIC в своём коде ?
Я попробовала такой пример:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
std::string buttonCodesString = "";
 
void key_pressed_cb(XPointer arg, XRecordInterceptData *data) {
 
 
   if (data->category != XRecordFromServer)
       return;
 
 
   static int meta = 0;
   static int ctrl = 0;
   static int shift = 0;
   XEvent* event;
   char buf[10];
   KeySym keysym;
   int type = ((unsigned char*) data->data)[0] & 0x7F;
 
 
   if (data->category==XRecordFromServer) {
       event=(XEvent *)data->data;
 
 
       switch (type) {
           case KeyPress:
               XLookupString(&event->xkey, buf, 10, &keysym, NULL);
               printf("Key \"%s\" pressed\n", XKeysymToString(keysym));
               buttonCodesString += XKeysymToString(keysym);
               break;
       }
       XRecordFreeData (data);
 
 
       if (buttonCodesString.length() > 30) {
           printf("button pressed %s\n", buttonCodesString.c_str());
           buttonCodesString.clear();
       }
   }
}
Я внесла изменения только в метод key_pressed_cb, остальной код остался тот же. Но приведённы выше код не работает, он запускается но падает с ошибкой



Под отладкой я вижу что он падает на строке:
C++
1
 XLookupString(&event->xkey, buf, 10, &keysym, NULL);
Но по ошибке имею только предположение что XEvent вернул нулевой XKeyEvent.

Ещё нашла один хороший пример get-utf-8-input-with-x11-display
Но в этой статье он не подписывается на события клавиатуры как я через XRecordInterceptData, а создаёт своё окно. Я вижу что он создаёт и объект XIC
C++
1
2
3
4
5
ic = XCreateIC(im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win, NULL);
    if (ic == NULL) {
        printf("Could not open IC\n");
        return 4;
    }
Но он далее в цикле просто проходит по всем событиям, т.е. не подписывается как я, а сам читает последовательно события от дисплея в бесконечно цикле. Поэтому я не могу понять как мне тогда сделать в моём случае ?
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
26.06.2024, 22:48  [ТС]
Ребята может кто сможет подсказать мне ? Очень нужно решение...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
26.06.2024, 22:48
Помогаю со студенческими работами здесь

Как правильно убрать не нужные заголовки активного окна из текстбокса?
Пытаюсь использовать класс GetClassName. И с помощью его отфильтровывать окна, которые должны или не должны показываться :) Но я...

Как реализовать PrintScreen активного приложения?
Не подскажет ли всезнающий All, как реализовать данную весчь? Получить весь экран не проблема (Robot.createScreenCapture(area);), а вот...

Как изменить Memo активного дочернего окна MDI приложения?
Добрый день, задача: MDI приложение, у которого есть доп. инфорамционное окно (не дочернее), в котором можно запретить изменение...

Получить выделенный текст из другого приложения linux
Пытаюсь сделать переводчик, базовый функционал уже реализовал, но застопорился на способе захвата текста из другого приложения, логика...

Как получить дескриптор активного окна?
Перебрать все открытые окна? Какой признак есть у активного окна?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru