Linux: строим своё рабочее окружение
Здравствуй мой уважаемый читатель. Этой статьёй я начну цикл, посвященный построению собственного окружения рабочего стола Linux. Не знаю как вы, но я в детстве очень любил разного рода конструкторы и эту любовь, по всей видимости, перенёс на свои современные увлечения. Мой конструктор сейчас — это операционная система Linux и различные электронные компоненты, собранные в единое целое. Если вам тоже нравится делать всё самому, что-то придумывать и с чем-то разбираться, при этом постоянно развиваясь — милости прошу под кат. Итак, приступим.
Прежде всего обозначим цели и задачи. Мы будем строить свой собственный рабочий стол, используя различные готовые программные компоненты. Весь комплект на выходе должен быть лёгким, красивым и функциональным. Linux предлагает нам многочисленные варианты решения одной и той же задачи, вот этим-то многообразием мы и воспользуемся.
Для начала пара слов о том, из каких компонентов состоит то, что мы называем рабочим столом. Базовый функционал работы с окнами (и не только, но сейчас это не важно) предоставляет X server или идущий ему на смену Wayland . Он непосредственно взаимодействует с аппаратной частью (видеокартой) через соответствующие модули (или драйвера). Поверх него работает менеджер окон. От этого компонента зависит то, как будут выглядеть сами окна, их границы, заголовки и декорации. Следующий компонент — композитный менеджер. Он отвечает за прозрачность и тени. Все элементы рабочего стола являются приложениями, запущенными в собственных окнах но не обычных, а с определенными атрибутами. И это логично. Ну зачем, скажите, какой-то панели, виджету или доку нужны декорации окна? Да, вы сделали правильный вывод, окна бывают разные 😉
Все компоненты могут иметь очень разные возможности и, в следствии этого, отличаются аппетитом к ресурсам компьютера, в частности к количеству памяти, производительности процессора и видеокарты. Также на их аппетит влияет включение и выключение различных функций.
Итак, первым в нашем творении компонентом будет менеджер окон. Одним из самых лёгких и гибких в настройке является OpenBox . Его мы и будем использовать. Не важно какой дистрибутив Linux вы используете, вы можете установить несколько различных менеджеров окон. Для Debian — подобных дистрибутивов для установки OpenBox выполним команду:
sudo apt install openbox
Далее делаем logout из вашего текущего окружения, в меню приветствия вводим логин с паролем и выбираем тип сессии openbox .
Что мы видим? Да, серый экран и ничего более. Тем не менее этим сверхминималистичным окружением уже можно пользоваться. Нажимаем правую кнопку мышки в любом месте экрана и видим меню с базовым набором пунктов. Находим в этом меню терминал и запускаем. Отлично, теперь у нас есть нужный инструмент. Для удобства работы в терминале я использую консольный файловый менеджер Midnight Commander, что и вам рекомендую. Установить его можно командой
в терминале набираем команду
В результате будет запущен файловый менеджер. Смотрим на наш домашний каталог. Нас интересует папка .config . В основном все приложения хранят свои настройки в этой папке, в том числе и openbox . Используя стрелки курсора на клавиатуре переместим курсор Midnight Commander на папку .config и нажмём клавишу ENTER . Мы вошли в каталог и попутно начали учиться использовать файловый менеджер mc (если, конечно, раньше не умели. К стати, он очень похож на FAR в Windows). Теперь перейдём в каталог с именем openbox . Это будет одна из самых используемых нами директорий. Внутри каталога мы видим файл с именем rc.xml . Это и есть конфигурационный файл, в котором openbox хранит свои настройки. Его можно править вручную, но пока мы этого делать не будем, так как у нас есть графическая утилита для конфигурирования openbox . Ищем её в меню по правому клику мыши или просто пишем команду в терминале:
obconf
Создание GUI в Linux. Часть 1
В этой статье мы поговорим о создании графического интерфейса для вашей Linux-программы. Как вы знаете, средствами одного С нормальный GUI (Graphical User Interface – Графический интерфейс пользователя, ГИП) не построишь, тем более что после Windows пользователь очень требователен не только к наличию этого самого GUI, но еще и к дизайну формы (окна программы). Поэтому без дополнительных библиотек вам не обойтись. Самыми распространенными библиотеками для создания GUI являются библиотеки GTK и Qt. Рекомендуется использовать только эти библиотеки, поскольку велика вероятность того, что они уже будут установлены у пользователя (уж GNOME и KDE установлены почти у всех), чтобы не сложилась такая ситуация, когда размер вашей программы 300К, а используемая нею библиотека «весит» 20М. Вот подумайте, зачем пользователю ваша программа и станет ли он закачивать ее из сети? Конечно, если для вашего шедевра нет аналогов в мире, вы можете изрядно поиздеваться над пользователем, используя нестандартную библиотеку GUI. В первой части этой статьи будет рассмотрена библиотека GTK, а во второй – Qt. Сразу следует заметить, что эта статья – не русскоязычное руководство по библиотекам GTK и Qt. Это, скорее, небольшой обзор возможностей библиотек.
Скорее всего, GTK уже будет у вас установлена, но вам нужно будет установить пакет gtk+-devel, содержащий необходимые файлы для разработки GTK-программ.
Не хочется в этой статье рассматривать банальный пример окошка с кнопкой hello world!. Уж слишком уж это просто, да и этот пример вы сможете найти в документации по Gtk.
Сейчас напишем небольшой конфигуратор, который будет вносить изменения в файл /etc/resolv.conf. Напомню вам формат этого файла:
domain firma.ru nameserver 192.168.0.1 nameserver 192.168.0.2
Директива domain определяет наш домен, а две директивы nameserver – первый и второй DNS-серверы, соответственно. Вместо директивы domain можно использовать директиву search, но это кому как нравится. Файл может содержать до 4 директив nameserver, но обычно указываются только два сервера DNS, поэтому мы не будем перегружать себя лишней работой. Но файл resolv.conf не главное в нашей статье – ведь мы разрабатываем GUI. Наш конфигуратор не будет вносить изменения в настоящий файл /etc/resolv.conf – для этого нужны права root, можно, конечно, вызвать auth для аутентификации, но мы не будем этого делать, чтобы не усложнять код программы.
Теперь небольшое вступление в GTK. Элементы ГИП – кнопки, поля ввода, переключатели и тому подобное называется виджитами. Если вы когда-нибудь работали в Delphi, виджиты подобны визуальным компонентам Delphi.
Как и в Delphi, основным элементом GUI является окно (форма в Delphi). Виджиты для размещения в окне помещаются в контейнер. В самом окне выравнивать виджиты можно с помощью вертикальных/горизонтальных боксов или же таблиц. Мне больше нравится второй способ, поэтому мы будем использовать именно таблицы.
Виджиты могут реагировать на сигналы, например, щелчок мышью. При этом вызывается функция-обработчик события (сигнала), если вы определили ее.
В качестве примера нарисуем кнопку и определим обработчик ее нажатия:
/* Рисуем кнопочку с надписью Hello, All */ button = gtk_button_new_with_label ("Hello, All"); /* При нажатии кнопки будет вызвана функция hello() */ gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (hello), NULL); /* Помещаем кнопку в контейнер */ gtk_container_add (GTK_CONTAINER (window), button); /* Отображаем кнопку. Без этого вы ее просто не увидите. Кстати, не забудьте отобразить окно. Порядок отображения виджитов особой роли не играет, но рекомендуется окно отображать в последнюю очередь */ gtk_widget_show (button);
/* Тип gpointer – это указатель. Тип gint – целое число, gchar – символ и т.д. */ void hello( GtkWidget *widget, gpointer data )
Хватит теории, перейдем к практике. На рисунке 1 изображена уже готовая программа. Работает она так. Когда пользователь введет что-нибудь в поле ввода и нажмет Enter, программа отобразит введенный им текст на консоли. Когда пользователь нажмет Ок, введенная им информация будет еще раз выведена на консоль и записана в файл. При нажатии кнопки Quit программа завершит свою работу. Она должна также завершить работу при нажатии кнопки закрытия окна – в GTK программист сам определяет реакции на стандартные кнопки.
Вот текст программы. Внимательно читайте комментарии.
#include #include #include gchar *domain, *dns1, *dns2; /* Массив из трех полей ввода. Первое предназначено для ввода имени домена, два вторых – [1] и [2] – для ввода IP-адресов серверов DNS */ GtkWidget *edit[3]; /* Наш файл */ FILE *resolv; /* Функция записи в файл */ void writetofile( GtkWidget *widget, gpointer data ) < /* С помощью функции gtk_entry_get_text() мы получаем введенный пользователем текст из полей ввода */ domain = gtk_entry_get_text(GTK_ENTRY(edit[0])); dns1 = gtk_entry_get_text(GTK_ENTRY(edit[1])); dns2 = gtk_entry_get_text(GTK_ENTRY(edit[2])); /* Выводим прочитанный текст на консоль */ g_print ("Domain %s\n", domain); g_print ("DNS1 %s\n", dns1); g_print ("DNS2 %s\n", dns2); /* Перезаписываем файл resolv.conf в текущем каталоге */ if ((resolv = fopen("resolv.conf","w")) == NULL) < /* Наверное, нет места на диске или прав маловато. */ g_print ("ERR: Cannot to open resolve.conf file\n"); gtk_main_quit (); >/* Запись в файл */ fprintf(resolv,"domain %s\n",domain); fprintf(resolv,"nameserver %s\n",dns1); fprintf(resolv,"nameserver %s\n",dns2); fclose(resolv); > /* Эта функция будет запущена, когда пользователь нажмет кнопку закрытия окна или кнопку Quit */ gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) < /* Функция gtk_main_quit() используется для завершения работы GTK-программы. Не нужно для этого использовать exit() */ gtk_main_quit (); return(FALSE); >/* Когда пользователь введет текст и нажмет Enter, введенный им текст будет выведен на консоль */ void enter_callback( GtkWidget *widget, GtkWidget *entry ) < domain = gtk_entry_get_text(GTK_ENTRY(entry)); printf("Domain: %s\n", domain); >int main( int argc, char *argv[] ) < GtkWidget *window; /* Окно */ GtkWidget *button; /* Кнопка */ GtkWidget *table; /* Таблица для размещения виджитов */ GtkWidget *label; /* Надпись */ /* Как видите, все виджиты одного типа – GtkWidget, поэтому мы могли бы обойтись даже тремя виджитами – для окна, таблицы и для всех остальных элементов GUI*/ int i; /* Инициализация любой GTK-программы */ gtk_init (&argc, &argv); /* Создаем новое окно */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* Устанавливаем заголовок окна */ gtk_window_set_title (GTK_WINDOW (window), "Resolver"); /* Устанавливаем реакцию на кнопку закрытия окна. Сигнал – delete_event Вызываем функцию delete_event(), которая описана выше */ gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL); /* Устанавливаем рамку окна */ gtk_container_set_border_width (GTK_CONTAINER (window), 20); /* Создаем таблицу 3x3 */ table = gtk_table_new (3, 3, TRUE); /* Помещаем таблицу в контейнер. Обязательно! */ gtk_container_add (GTK_CONTAINER (window), table); /* Рисуем надписи, помещаем их в ТАБЛИЦУ и отображаем. Обратите внимание, что в этом случае нам не нужно объявлять отдельную переменную для каждой надписи*/ label = gtk_label_new("Domain: "); /* О координатах ячеек поговорим после этого листинга */ gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 0, 1); gtk_widget_show (label); label = gtk_label_new("DNS #1: "); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 1, 2); gtk_widget_show (label); label = gtk_label_new("DNS #2: "); gtk_table_attach_defaults (GTK_TABLE(table), label, 0, 1, 2, 3); gtk_widget_show (label); /* Заполняем наш массив полей ввода. По аналогии с Delphi, я назвал массив edit[]*/ for(i=0; i/* Создаем кнопку "Ok", помещаем в таблицу, определяем реакцию на нажатие и показываем */ button = gtk_button_new_with_label ("Ok"); gtk_table_attach_defaults (GTK_TABLE(table), button, 2, 3, 0, 1); gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(writetofile),NULL); gtk_widget_show (button); /* Тоже самое для кнопки Quit */ button = gtk_button_new_with_label ("Quit"); gtk_table_attach_defaults (GTK_TABLE(table), button, 2, 3, 2, 3); gtk_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(delete_event),NULL); gtk_widget_show (button); gtk_widget_show (table); /* Показываем таблицу */ gtk_widget_show (window); /* Показываем окно */ /* Запускаем GTK-программу */ gtk_main (); return 0; >
Я старался писать подробные комментарии, но все же кое-что осталось в тумане. Это координаты ячеек. Рассмотрим нашу таблицу 3х3:
0 1 2 3 Domain Поле Ок 1 DNS1 Поле 2 DNS2 Поле Quit 3
Сначала указываются координаты по X, затем – по Y. Вот координаты кнопки Ok: 2,3,0,1. Это означает, что кнопка будет расположена в последнем столбике (2,3), но в первом ряду (0,1). Чтобы было понятнее: ОК по Х находится между 2 и 3, а по Y – между 0 и 1.
Теперь откомпилируем нашу программу:
gcc -g resolv.c -o resolv `gtk-config --cflags` `gtk-config --libs`
Можно не использовать опцию -g, добавляющую отладочную информацию – размер файла станет меньше. Программа gtk-config сообщает компилятору всю необходимую информацию о библиотеке gtk. Обратите внимание на директиву #include . Обычно файлы заголовков gtk находятся в другом каталоге, например, gtk-1.2, но это совсем не имеет значения – все необходимые параметры укажет программа gtk-config.
У вас некорректно отображаются русские названия надписей и кнопок? Эта проблема очень быстро устраняется с помощью GNOME Control Center – вам всего лишь нужно выбрать другой шрифт.
Вот теперь этот небольшой обзор можно считать полным. Конечно, я не рассмотрел еще много чего – переключатели, графические кнопки (аналог SpeedButton в Delphi), . но помните – это всего лишь статья, а не руководство по GTK! Если вы заинтересовались, прочитайте документацию по GTK – file:/usr/share/doc/gtk+-devel-1.2.10/html/gtk_tut-2.html#ss2.1 Ваши вопросы и комментарии можно отправлять по адресу dhsilabs@mail.ru.
Создаем приложение используя GTK в Линуксе
Разрабатывать приложения в Линуксе можно с помощью фреймворка GTK. Эта библиотека предназначенная для построения графического интерфейса пользователя. GTK — это свободное программное обеспечение, которое распространяется по лицензии GNU LGPL, что позволяет создавать как бесплатные так и коммерческие приложения.
С документациею и описанием библиотеки, Вы можете ознакомиться по следующей ссылке: https://www.gtk.org
Перед написанием приложения необходимо подготовить среду разработки. Для этих целей буду использовать ОС Ubuntu 22.04. Так как приложение будет разрабатываться на языке программирования Си необходимо установить необходимые пакеты и компилятор.
Откройте терминал от имени пользователя root и введите следующую команду:
sudo apt-get install build-essential
Также нам необходимо установить пакеты GTK для разработки приложения. Вводим следующую команду в терминале:
sudo apt-get install -y libgtk-3-dev
Теперь все готово для написания первого приложения. Открываем любой текстовый редактор и пишем следующий код:
#include int main (int argc, char *argv[])
Этот код создает окно. Но прежде чем выполнить приложение, давайте разберемся немного с кодом.
#include — здесь мы подключаем библиотеку gtk. Без этой библиотеки не будет работать графическое окно и мы не сможем запустить приложение;
GtkWidget *window; — задаем имя/метку окна;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); — эта строка создает стандартное окно с рамкой;
gtk_widget_show(window); — отображаем окно на дисплее.
Теперь давайте запустим приложение. Я сохранил код приложения в файле ex1.c в домашней папки.
Открывает терминал и вводим следующие команды:
gcc ex1.c -o ex1 `pkg-config —cflags —libs gtk+-3.0
Теперь давайте улучшим код и создадим текстовую метку.
#include int main (int argc, char *argv[])
GtkWidget *label1; — задаем имя текстовой метки;
label1 = gtk_label_new(«Hello! My first Program»); — создаем текстовую метку;
gtk_container_add(GTK_CONTAINER(window), label1); — эта строка кода добавляет метку в контейнер;
gtk_widget_show(label1); — отображаем метку в окне.
Надеюсь эта публикация была полезная. Так как фреймворк GTK имеет очень много полезных и интересных функций, что не дает возможности объяснить все в одной публикации.