LINUX.ORG.RU

C++ Окно, интерфейс.

 ,


1

3

Здравствуйте. Я новичок в линуксе, программировании, С++, вообще во всем. У меня слабый ПК(ноут с селероном) и линукс минт на нем. Мне для моих экспериментов нужно желательно прямо из консоли(с помощью g++ например), скомпилировать бинарный файлик, который откроет окно на который выбрасывается массив пикселлей, вычесленный этой же програмкой. У меня freeGlut, но на данный момент библиотеки openGL избыточны. Но если не найду ответа, останусь на нем. Знаю про Qt - тяжело, комп с трудом тянет, Processing - это прекрасный инструмент, есть, пользуюсь, но это не С++, Jetpack Multiplatform, и прочие фреймфорки - не то. Очень тяжелые. Хотелось бы чтоб как в glut, дал пару директив, инициализировал окно и пользуйся.

Не думаю что есть ответ, но спрошу еще: если у кого есть шаблон или ссылка на него, как просто в файле *.cpp без тоннны сторонних библиотек запустить окошко в линуксе, да еще, пикселль повесить туда по заданным координатам, то буду благодарен.(где-то в книжке по С видел такое, попытался повтоить, компилятор меня не понял)

$ cat hello.c
#include <X11/Xlib.h>
#include <unistd.h>

int main()
{
    Display* MainDisplay = XOpenDisplay(0);
    Window RootWindow = XDefaultRootWindow(MainDisplay);
    
    Window MainWindow = XCreateSimpleWindow(MainDisplay, RootWindow, 0, 0, 800, 600, 0, 0, 0x00aade87);
    XMapWindow(MainDisplay, MainWindow);
    XFlush(MainDisplay);

    for(;;) { sleep(1); }
}
$ gcc hello.c -lX11
$ ./a.out
^C
fluorite ★★★★★
()
Последнее исправление: fluorite (всего исправлений: 2)
Ответ на: комментарий от Ygor

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

Usuk_Ikota
() автор топика

Знаю про Qt - тяжело, комп с трудом тянет

Наверно все же Qt Creator? Да, бывает тяжеловато, но зато легче разрабатывать: всякие подсказки, встроенная справка и подсветка ошибок. На первых порах можно не задумываться о том, как приложение собирается.

anonymous
()
Ответ на: комментарий от anonymous

Было бы неплохо на самом деле, но я намекал хотя бы на питон. Для новичка накидать простенькое рабочее проще в нем. Готовые рабочие решения, все в одной упаковке. Минимум ручной работы.

Но раст к слову тоже все это может, но синтаксис посложнее для новичка.

Но уж точно не плюсы.

Или вон простейшее:

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    visible: true
    width: 256
    height: 256

    Canvas {
        id: canvas
        anchors.fill: parent

        onPaint: {
            var ctx = getContext("2d");
            for (var y = 0; y < height; y++) {
                for (var x = 0; x < width; x++) {
                    ctx.fillStyle = Qt.rgba(x / 255, y / 255, (x + y) / 510, 1);
                    ctx.fillRect(x, y, 1, 1);
                }
            }
        }
    }
}

Из плюсов - ничего постороннего не надо, если у тебя кеды. Никакой сборки и прочего.

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

моя задача буквально самому софтверным рендерингом рисовать всякую примитивную хрень.

FLTK тулкит, достаточно простой лёгкий и мощный. ИМХО как раз под твои задачи.

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

Я очень мало знаю о перечисленных языках, но мне кажется что питон и вот это все это слишком просто, до такой степени просто что аж сложно. Вообще нихрена не понятно. Все за тебя делает. Си подобные языки прозрачны. Я хотел с Котлина начать, он под явой, компиляция занимает вечность, а котлин нэтив я вообще не понял.

Usuk_Ikota
() автор топика
Ответ на: комментарий от Usuk_Ikota

Питон прост именно что в синтаксисе. Убраны лишние скобки, проверки, внешний мусор. Почти человеко-читаемым языком накидал нужное и оно работает.

Тебе не нужно думать об управлении памятью, не нужно практически думать о переменных. Есть готовые структуры, вроде таблиц. Просто делаешь что нужно. Никакой компиляции и прочего. Есть кучи готовых модулей и решений. При этом модули тоже искат не надо, все ставится одной командой. Очень удобный инструмент на самом деле.

Выбирая для таких простейших задач си, ты сам себе создаешь проблемы, которых могло бы и не быть на самом деле.

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

не нужно практически думать о переменных

Как раз в питоне тебе только и нужно что думать о переменных, держать в голове их типы, мутабельность/иммутабельность. От этого удовольствия писать на питоне ноль.

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

В мои задачи входиь еще и чуть глубже понять комп. Я не спорю есть куча способов решить озвученные задачи гараздо дешевле. Но мне дофига всего нужно понять пусть и не на профессиональном уровне даже близко. Но переменные в си это да…

Usuk_Ikota
() автор топика
Ответ на: комментарий от Usuk_Ikota

Так что ж ты раньше молчал! Тебе прямой путь в раст. Я суперсурьезно. Там собрано все что ты хочешь - и получше понять комп и удобство работы, и модули и удобство работы с переменными.

По сути там собраны все плюсы си в сочетании со всеми плюсами питона.

Ладно я зря вообще в эту беседу влез. Самоустраняюсь.

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

Если всетаки будешь смотреть, смотри в сочетании с egui.

https://www.egui.rs/

Вот тут потыкать можешь и 2д и 3д. Там примеры есть. И интерфейсов. Сайт, к слову, тоже написан на раст.

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

Сильно зависит от версии. Ну и ты не описал своё железо, хотя бы объём памяти. Да и селероны бывают очень разные.

Ну и у меня был опыт работы с Qt на сильно слабом железе вообще без Qt Creator. Сильно помогает разобраться, что к чему.

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

В раст все управляется единым инструментом - cargo.

Сначала создание проекта: cargo new project_name

В созданной директории будет файли к Cargo.toml

там вставляем вот так например:

[dependencies]
eframe = "0.31.1" # Фреймворк для создания окон с egui
egui = "0.31.1"   # Сама библиотека egui

Собственно все. Дальше он сам подтянет нужные модули и зависимости:

cargo run и проект запутсится.

Код в каталоге src - src/main.rs

например так:

use eframe::egui;

fn main() {
    let options = eframe::NativeOptions::default();
    eframe::run_native(
        "Pixel Art House", // Название окна
        options,
        Box::new(|_cc| Ok(Box::new(MyApp {}))), // Оборачиваем MyApp в Ok
    )
    .expect("Failed to start eframe application");
}

struct MyApp {}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            // Получаем холст для рисования
            let painter = ui.painter();

            // Размеры холста
            let canvas_width = 200.0;
            let canvas_height = 200.0;

            // Очищаем фон (трава)
            painter.rect_filled(
                egui::Rect::from_min_size(egui::pos2(0.0, 0.0), egui::vec2(canvas_width, canvas_height)),
                0.0,
                egui::Color32::from_rgb(34, 139, 34), // Зеленый цвет травы
            );

            // Рисуем домик пикселями
            draw_house(painter);
        });
    }
}

// Функция для рисования домика
fn draw_house(painter: &egui::Painter) {
    // Крыша (треугольник)
    painter.add(egui::Shape::convex_polygon(
        vec![
            egui::pos2(80.0, 40.0),  // Верхняя точка крыши
            egui::pos2(50.0, 80.0),  // Левый угол
            egui::pos2(110.0, 80.0), // Правый угол
        ],
        egui::Color32::from_rgb(255, 69, 0), // Оранжевый цвет крыши
        egui::Stroke::NONE,
    ));

    // Стены дома (прямоугольник)
    painter.rect_filled(
        egui::Rect::from_min_size(egui::pos2(50.0, 80.0), egui::vec2(60.0, 60.0)),
        0.0,
        egui::Color32::from_rgb(139, 69, 19), // Коричневый цвет стен
    );

    // Окно
    painter.rect_filled(
        egui::Rect::from_min_size(egui::pos2(60.0, 100.0), egui::vec2(20.0, 20.0)),
        0.0,
        egui::Color32::from_rgb(173, 216, 230), // Светло-голубой цвет окна
    );

    // Дверь
    painter.rect_filled(
        egui::Rect::from_min_size(egui::pos2(85.0, 120.0), egui::vec2(10.0, 20.0)),
        0.0,
        egui::Color32::from_rgb(139, 0, 0), // Темно-красный цвет двери
    );
}
LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от Usuk_Ikota

8гб оперативы

На мой взгляд, для кутей это дохрена, вообще-то. Для браузеров да, маловато, но мы вроде не про них говорим.

Вот двухъядерный процессор, да, можно считать узким местом… для сборки проектов из 20 и более модулей. :)))

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

под Linux mint xfce mozilla Firefox просто летает)) Видосы в 1080p, куча вкладок, приложений. Под виндой 480p несмотрибельно.Я аж установил Qt Creator опять.. и обломался. Можно. Но мне тут первым коментом отличный вариантдали для старта. И вот еще раст поковыряю.

Usuk_Ikota
() автор топика
Ответ на: комментарий от Usuk_Ikota

Псс.. Смотри чего еще покажу. Ставишь love методами своего дистрибутива. Например в генту: emerge -av games-engines/love

И вот такой вот код на луа:

-- Функция love.load вызывается один раз при запуске программы
function love.load()
    -- Устанавливаем размер окна
    love.window.setMode(400, 400)
end

-- Функция love.draw вызывается каждый кадр для отрисовки
function love.draw()
    -- Очищаем фон травой (зелёный цвет)
    love.graphics.setColor(34 / 255, 139 / 255, 34 / 255) -- RGB цвет травы
    love.graphics.rectangle("fill", 0, 250, 400, 150)

    -- Рисуем стены дома (коричневый прямоугольник)
    love.graphics.setColor(139 / 255, 69 / 255, 19 / 255) -- RGB цвет стен
    love.graphics.rectangle("fill", 100, 150, 100, 100)

    -- Рисуем крышу (треугольник)
    love.graphics.setColor(255 / 255, 69 / 255, 0 / 255) -- RGB цвет крыши
    love.graphics.polygon("fill", 150, 50, 100, 150, 200, 150)

    -- Рисуем окно (светло-голубой прямоугольник)
    love.graphics.setColor(173 / 255, 216 / 255, 230 / 255) -- RGB цвет окна
    love.graphics.rectangle("fill", 120, 170, 30, 30)

    -- Рисуем дверь (темно-красный прямоугольник)
    love.graphics.setColor(139 / 255, 0 / 255, 0 / 255) -- RGB цвет двери
    love.graphics.rectangle("fill", 155, 200, 20, 50)

    -- Рисуем солнце (жёлтый круг)
    love.graphics.setColor(255 / 255, 215 / 255, 0 / 255) -- RGB цвет солнца
    love.graphics.circle("fill", 350, 50, 30)
end

Присмотрись к коду - это же мечта. Минимализм, никаких управлений переменными, никаких лишних скобок и прочего. Минимализм в потреблении. Никакой сборки. Код кидаешь в файлик main.lua и в том каталоге вызываешь

love .

В итоге в пару строк кода получаешь такое вот окошко: https://iimg.su/s/08/oYSdDZPV5aD40QL6t6rigaVCm4xyQaEWeVWxO8aW.png

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

Просто раст это низкоуровневое и удобное. Он для познания компа. Если хочешь сделать «железное» решение компилируемое.

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

Но из минусов - много кода, нужно все учитывать.

А второй вариант, что я тебе скинул - почти абсолютная противоположность. Высокоуровневое без лишнего кода. Даже мозг включать не надо. Просто строчку прописал - объект нарисовал. Какие окна? Какие переменные? Все в пень. Собирать не надо - запуск так же мгновенный. В этом его плюс.

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

да вот это я и понял. Слушай, на том сайте который ты мне дал, есть проект Dancing strings, как его скомпилировать и запустить у себя. Не говори что надо вот все скачать и ковырять все это целиком

Usuk_Ikota
() автор топика

Ты хочешь генерировать данные и просто их смотреть, можешь генерировать в TGA формат например, в файл, это тупо набор пикселей + заголовок, а результат может отображать любой просмоторщик изображений. Это будет самый лёгкий для системы вариант.

Примеры как работать с TGA без регистрации и СМС на C без зависимостей

Или SDL2 взять например, там есть программный рендер

Хотелось бы чтоб как в glut, дал пару директив, инициализировал окно и пользуйся.

Вот это и оно и есть SDL2 или SDL3. В интернете тонны примеров.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LightDiver

Выбирая для таких простейших задач си, ты сам себе создаешь проблемы

Сфигали? =) У него основная задача, это генерация данных. Си это язык обработки данных, буквально, когда ты работаешь с ними как они есть. А окошки это второстепенная задача. Чёт ты это, не то.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от Usuk_Ikota

Ну, например так:

Cargo.toml

[package]
name = "dancing_strings_demo"
version = "0.1.0"
edition = "2021"

[dependencies]
egui = { version = "0.31", features = ["color-hex"] }
eframe = "0.31"

main.rs

use eframe::egui;
use egui::{Rect, emath};

fn main() {
    let options = eframe::NativeOptions::default();
    if let Err(error) = run_app(options) {
        eprintln!("Failed to run app: {error}");
    }
}

fn run_app(options: eframe::NativeOptions) -> Result<(), eframe::Error> {
    eframe::run_native(
        "Dancing Strings",
        options,
        Box::new(|_cc| Ok(Box::new(DancingStrings::default()))),
    )
}

#[derive(Default)]
struct DancingStrings {
    colors: bool,
}

impl eframe::App for DancingStrings {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.vertical_centered(|ui| {
                ui.heading("♫ Dancing Strings");
            });

            ui.checkbox(&mut self.colors, "Colored")
                .on_hover_text("Demonstrates how a path can have varying color across its length.");

            egui::Frame::canvas(ui.style()).show(ui, |ui| {
                ui.ctx().request_repaint();
                let time = ui.input(|i| i.time);

                let desired_size = ui.available_width() * egui::vec2(1.0, 0.35);
                let (_id, rect) = ui.allocate_space(desired_size);

                let to_screen =
                    emath::RectTransform::from_to(Rect::from_x_y_ranges(0.0..=1.0, -1.0..=1.0), rect);

                let mut shapes = vec![];

                for &mode in &[2, 3, 5] {
                    let mode = mode as f64;
                    let n = 120;
                    let speed = 1.5;

                    let points: Vec<egui::Pos2> = (0..=n)
                        .map(|i| {
                            let t = i as f64 / (n as f64);
                            let amp = (time * speed * mode).sin() / mode;
                            let y = amp * (t * std::f64::consts::TAU / 2.0 * mode).sin();
                            to_screen * egui::pos2(t as f32, y as f32)
                        })
                        .collect();

                    let thickness = 10.0 / mode as f32;
                    shapes.push(egui::epaint::Shape::line(
                        points,
                        if self.colors {
                            egui::epaint::PathStroke::new_uv(thickness, move |rect, p| {
                                let t = emath::remap(p.x, rect.x_range(), -1.0..=1.0).abs();
                                let center_color = egui::hex_color!("#5BCEFA");
                                let outer_color = egui::hex_color!("#F5A9B8");

                                egui::Color32::from_rgb(
                                    emath::lerp(center_color.r() as f32..=outer_color.r() as f32, t) as u8,
                                    emath::lerp(center_color.g() as f32..=outer_color.g() as f32, t) as u8,
                                    emath::lerp(center_color.b() as f32..=outer_color.b() as f32, t) as u8,
                                )
                            })
                        } else {
                            egui::epaint::PathStroke::new(
                                thickness,
                                if ui.visuals().dark_mode {
                                    egui::Color32::from_additive_luminance(196)
                                } else {
                                    egui::Color32::from_black_alpha(240)
                                },
                            )
                        },
                    ));
                }

                ui.painter().extend(shapes);
            });
        });
    }
}
LightDiver ★★★★★
()
Ответ на: комментарий от Usuk_Ikota

Так ты писал бы сразу что тебе не окошко нужно, а целый GUI, ну бери нуклеар (сразу ссылку на чтиво дам, чтобы вопрсов не было)

Только вот, если ты хочешь полноценный GUI то ты хочешь большую библу, и это закон. По иному не бывает. Ну и то что ты сейчас сказал, полностью противоречит сказанному тобой в самом верху темы.

Ладно, экспериментируй и химич :)

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Потому что он больше будет разбираться как овладеть си, чем работать с кодом. Вон я ему рабочие варианты и на раст и на луа накидал. Просто, удобно, компактно жеж. И главное быстро и без лишней возни.

Ты в первую очередь программист и рассуждаешь с точки зрения программиста. А надо с точки зрения пользователя. Я ж ведь жопой чую, что ему нужен результат и вижу какие сложности он встретит на этом пути. Я ж сам это прошел буквально на днях. Ну почти.

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

Потому что он больше будет разбираться как овладеть си, чем работать с кодом.

Абсолютно с тобой не согласен

Вон я ему рабочие варианты

Он пока не определился что именно хочет, сначала спрашивал про просто окно куда выводит данные без opengl, затем ему стал нужен полноценный GUI с анимациями, и чтобы всё одним cpp файликом и без зависимостей от чего бы то ни было. Такого не существует в природе и существовать не может. Если иксы то самый прямой, лёгкий и адекватным вариант был первым сообщением в этом треде =) Легче только мой, где данные в файл, а смотреть штатно чем угодно.

Ладно, потыкает всё, да выберет.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от Usuk_Ikota

И всетаки глянь еще вариант с луа.

Ставишь в систему games-engines/love, создаешь файлик main.lua:

function love.load()
    width = love.graphics.getWidth()
    height = love.graphics.getHeight()
    centerY = height / 2
    modes = {2, 3, 5}
    nPoints = 120
    speed = 1.5
    thickness = 4
    useColor = true

    colors = {
        center = {75/255, 206/255, 250/255},   -- #5BCEFA
        outer = {245/255, 169/255, 184/255}    -- #F5A9B8
    }
end

function love.update(dt)
    -- место для вашей рекламы
end

function love.draw()
    love.graphics.setBackgroundColor(0.1, 0.1, 0.1) -- тёмный фон

    local time = love.timer.getTime()

    for _, mode in ipairs(modes) do
        local points = {}

        for i = 0, nPoints do
            local t = i / nPoints
            local amp = math.sin(time * speed * mode) / mode
            local y = amp * math.sin(t * math.pi * mode)

            local x_screen = t * width
            local y_screen = centerY + y * 100

            table.insert(points, x_screen)
            table.insert(points, y_screen)
        end

        if useColor then
            love.graphics.setLineWidth(thickness)
            for i = 1, #points - 3, 2 do
                local x1, y1 = points[i], points[i+1]
                local x2, y2 = points[i+2], points[i+3]

                local t = math.abs((x1 / width) * 2 - 1)
                local r = lerp(colors.center[1], colors.outer[1], t)
                local g = lerp(colors.center[2], colors.outer[2], t)
                local b = lerp(colors.center[3], colors.outer[3], t)

                love.graphics.setColor(r, g, b)
                love.graphics.line(x1, y1, x2, y2)
            end
        else
            love.graphics.setColor(1, 1, 1)
            love.graphics.setLineWidth(thickness)
            love.graphics.line(points)
        end
    end

    -- Переключатель цвета
    love.graphics.setColor(1, 1, 1)
    love.graphics.print("Press C to toggle color", 10, 10)
end

function love.keypressed(key)
    if key == "c" then
        useColor = not useColor
    end
end

-- Вспомогательная функция для интерполяции
function lerp(a, b, t)
    return a + (b - a) * t
end

И запускаешь:

love .

Это та же демка, которую ты хочешь. Но на луа и в читебельном виде для новичка. Вдруг тебе понравится. Сравни коды для себя.

LightDiver ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

в случае с растом меня привлек стнтаксис. И мне с ним дали то чего я просил не давать - огромную библу. Но надо с чего то начинать. Ща я этот проект попытаюсь раздеть и посмотреть что получится.

Вы мне всё правильно советуте: готовые фреймворки, GUI, огромные библитеки, тулкиты. Но с точки зрения разраба. Вы мыслите как разрабы. А чтобы ответить на мой вопрос надо мыслить даже не как пользователь, а как долбанутый. Была бы моя воля я бы на асемблере пикселлы выводил с загрузочной фрешки, но это уже жесткий БДСМ.

Usuk_Ikota
() автор топика
Ответ на: комментарий от Usuk_Ikota

Просто egui это на самом деле не огромная либа, а практически что ты и просил - минимальное удобство за свои ресурсы. Если Qt это 20-100мб, то egui это 1-2 метра буквально - только самое необходимое.

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

Да, пробуй всё, пока сам палочкой не потыкаешь ничего понятно не будет, а так даже если что-то не понравится расширится кругозор, тоже не плохо почему нет.

Ну раз такая пьянка то вот ещё

Специально язык аж целый, и маленький, всё в одном для работы с пикселями и экспериментов с визуальными эффектами.

Ну как мелкий, архив с бинарями на 23 мегабайта, зато там всё в одном, для трёх систем винда, линукс, макось, включая x86 и ARM, аж 8 бинарных готовых вариантов под всё, в 1 архивчике с кучей встроенных демок

Прикольно, может зайдёт :)

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от Usuk_Ikota

Понимаешь в чем беда, тебе всеравно придется через что то рисовать. Через винапи, через х11, через вейленд. Но их писали негуманоидные виды для таких же как они. Причем явно для противоестественного использования.

Вот смотри пример:

Cargo.toml

[package]
name = "dancing_strings_demo"
version = "0.1.0"
edition = "2021"

# Для работы с системными вызовами
[dependencies]
libc = "0.2"

main.rs

use std::ptr::{null, null_mut};
use std::thread;
use std::time::Duration;
use libc::{c_int, c_ulong};

#[repr(C)]
struct XEvent {
    pub type_: c_int,
    pub xany: [u8; 24],
}

// Константы
const KEY_PRESS_MASK: c_int = 1 << 0;
const CLIENT_MESSAGE: c_int = 21;

const WIDTH: usize = 400;
const HEIGHT: usize = 300;

#[link(name = "X11")]
extern "C" {
    fn XOpenDisplay(display_name: *const i8) -> *mut Display;
    fn XDefaultScreen(dpy: *mut Display) -> c_int;
    fn XRootWindow(dpy: *mut Display, screen: c_int) -> Window;
    fn XCreateSimpleWindow(
        dpy: *mut Display,
        parent: Window,
        x: c_int,
        y: c_int,
        width: u32,
        height: u32,
        border_width: u32,
        border: c_ulong,
        background: c_ulong,
    ) -> Window;
    fn XMapWindow(dpy: *mut Display, w: Window);
    fn XSelectInput(dpy: *mut Display, w: Window, event_mask: c_int);
    fn XNextEvent(dpy: *mut Display, event: *mut XEvent) -> c_int;
    fn XFlush(dpy: *mut Display) -> c_int;
    fn XCloseDisplay(dpy: *mut Display) -> c_int;
    fn XCreateGC(dpy: *mut Display, d: Drawable, valuemask: u64, values: *mut ()) -> GC;
    fn XSetForeground(dpy: *mut Display, gc: GC, foreground: c_ulong);
    fn XFillRectangle(
        dpy: *mut Display,
        d: Drawable,
        gc: GC,
        x: c_int,
        y: c_int,
        width: u32,
        height: u32,
    );
    fn XPending(dpy: *mut Display) -> c_int;
}

type Display = std::ffi::c_void;
type Window = c_ulong;
type Drawable = c_ulong;
type GC = *mut std::ffi::c_void;

fn main() {
    // Открываем дисплей
    let display = unsafe { XOpenDisplay(null()) };
    if display.is_null() {
        panic!("Не удалось подключиться к X серверу");
    }

    // Получаем корневое окно
    let screen = unsafe { XDefaultScreen(display) };
    let root_window = unsafe { XRootWindow(display, screen) };

    // Создаём наше окно
    let window = unsafe {
        XCreateSimpleWindow(
            display,
            root_window,
            0,
            0,
            WIDTH as u32,
            HEIGHT as u32,
            0,
            0,
            0xff000000, // Чёрный фон
        )
    };

    if window == 0 {
        panic!("Не удалось создать окно!");
    }

    // Подписываемся на события
    unsafe {
        XSelectInput(display, window, KEY_PRESS_MASK | CLIENT_MESSAGE);
        XMapWindow(display, window);
        XFlush(display); // Отправляем команду на экран
    }

    // Создаём графический контекст
    let gc = unsafe { XCreateGC(display, window, 0, null_mut()) };
    if gc.is_null() {
        panic!("Не удалось создать GC");
    }

    // Устанавливаем цвет: красный (RGB: FF0000)
    unsafe {
        XSetForeground(display, gc, 0xFF0000); // красный
    }

    println!("Окно создано. Ждём событий...");

    // Цикл обработки событий
    let mut running = true;
    while running {
        if unsafe { XPending(display) } > 0 {
            let mut event: XEvent = unsafe { std::mem::zeroed() };
            unsafe {
                XNextEvent(display, &mut event);
            }

            match event.type_ {
                2 => {
                    // KeyPress
                    running = false;
                }
                _ => {}
            }
        } else {
            // Рисуем красный квадрат 10x10 по центру
            unsafe {
                XFillRectangle(display, window, gc, 195, 145, 10, 10);
                XFlush(display);
            }

            thread::sleep(Duration::from_millis(100));
        }
    }

    unsafe {
        XCloseDisplay(display);
    }

    println!("Программа завершена.");
}

Это вывод красного квадрата в окне. Работа напрямую через иксы. Понимаешь, егуи добавляет тебе совсем минималистичную либу на 1 метр, зато дает в ней тебе гуи, работу с 2д, работу с 3д. Да вообще полное удобство с минимальными затратами. Оно реально того стоит. Но можешь глянуть пример выше.

И да, в прямой работа навреное действительно лучше сразу си использовать. Ибо всеравно придется. Но как по мне - вместо компактного, быстрого, красивого какая то порнография выходит в таком случае.

И да, я тебя полностью понимаю. Я это прошел. И вариант с ассемблером тоже, кстати. Они забавно, прикольно, но нежизнеспособно в итоге для реальной работы. Игрушки. Когда начинаешь делать практический проект, нужна абстракция кое какая. Затраченные усилия не окупаются, когда вот тут рядом можно сделать быстро и удобно.

Но! Даже в реальных проектах бывают «узкие места», где уже можно запихать конкретно низкоуровневое свое решение урезанное вместо жирного готового - тогда оно оправданно. Только фрагментарно, а не как весь проект.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 6)
Ответ на: комментарий от LINUX-ORG-RU

Слушай, мою старую тему закрыли, но я просто не могу не похвастаться.

Серверная часть: https://pastebin.com/raw/7W3yG5bh

Клиентская часть: https://pastebin.com/raw/k1dmw3Qx

Инициация этого всего функцией командой: sendObfuscatedClass(class1Code)

Ну скажи, кто гений? А? А? Меня прям аж распирает, а своим рассказать не могу, от них ведь этот код и делаю.

Сможешь понять что тут происходит?

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)