/*
    Send Enter key to pointed by mouse window.
    For GNU/Linux 64 bit version.
    Version: 1 (C port).
    Written on C (https://en.wikipedia.org/wiki/C_(programming_language))
    Original Pascal version Copyright (C) 2025 Artyomov Alexander
    C port Copyright (C) 2026

    http://self-made-free.ru/
    aralni@mail.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>

int main() {
    Display *d;
    Window root;
    Window win;
    int root_x, root_y, win_x, win_y;
    unsigned int mask;
    KeyCode keycode;
    XEvent event;
    int xtest_major, xtest_minor;
    int xtest_event_base, xtest_error_base;

    // Открываем соединение с X-сервером
    d = XOpenDisplay(NULL);
    if (d == NULL) {
        fprintf(stderr, "Не удалось подключиться к X-серверу\n");
        return 1;
    }

    // Проверяем доступность XTest
    if (!XTestQueryExtension(d, &xtest_event_base, &xtest_error_base, 
                             &xtest_major, &xtest_minor)) {
        fprintf(stderr, "XTest extension не доступна\n");
        XCloseDisplay(d);
        return 1;
    }

    printf("Нажмите на окно, куда нужно отправить Enter...\n");

    root = DefaultRootWindow(d);

    // Захватываем указатель мыши
    XGrabPointer(d, root, False, ButtonPressMask, GrabModeAsync,
                 GrabModeAsync, None, None, CurrentTime);

    // Выбираем события для корневого окна
    XSelectInput(d, root, ButtonPressMask);

    // Ждём клик мышью
    while (1) {
        XNextEvent(d, &event);

        if (event.type == ButtonPress) {
            win = event.xbutton.subwindow;
            if (win == None) {
                win = root;
            }

            // Получаем координаты для проверки
            XQueryPointer(d, win, &root, &win, &root_x, &root_y,
                         &win_x, &win_y, &mask);
            break;
        }
    }

    XUngrabPointer(d, CurrentTime);

    if (win == None) {
        fprintf(stderr, "Окно не выбрано\n");
        XCloseDisplay(d);
        return 1;
    }

    printf("Отправляем Enter в окно %lu\n", win);

    // Получаем keycode для Enter
    keycode = XKeysymToKeycode(d, XK_Return);

    // Фокусируемся на окне
    XSetInputFocus(d, win, RevertToParent, CurrentTime);
    XFlush(d);

    // Имитируем нажатие Enter через XTest
    XTestFakeKeyEvent(d, keycode, True, 0);   // KeyPress
    XFlush(d);
    XTestFakeKeyEvent(d, keycode, False, 0);  // KeyRelease
    XFlush(d);

    printf("Enter отправлен!\n");

    XCloseDisplay(d);
    return 0;
}