Коварный тачпад
- Подробности
- Просмотров: 8711
Всем известно, что ноутбуки чуть чаще чем всегда оснащаются тачпадом. Очень полезная штука знаете-ли. И мышь уже не нужна. Правда при интенсивной работе мышь всё равно приходится подключать, поскольку как ни крути - а мышь удобнее. Работая интенсивно перестаешь обращать внимание на тачпад, забываешь что он есть. Тут набираешь текст, случайно коснулся его поверхности и замечаешь что целый блок кода написано уже где-то не там или нету вообще...

Конечно проблема решима простым отключением тачпада, но иногда это наталкивается на определённые трудности. Хорошо когда есть кнопка отключения тачпада, нажал - включил, нажал - выключил. Удобно. Но вот в моём Dell Inspiron 1525 такой кнопки нету. Это значит, что отключение тачпада нужно проводить в системных настройках, устройство выключить например. Когда там ещё была винда, то стандартные драйвера шли в комплекте с утилитой, которая при подключении внешней мишы автоматически отключала тачпад. Вроде как удобнее даже чем с кнопкой - не надо думать о том нажал или не нажал - всё автоматом. Но это же не предел совершенства, ибо всегда бывают случаи, когда тачпад мне не нужен даже при отсутсвии мишы, например сидишь и програмишь - нужна только клава, а команды редактора все равно вызываются горячими клавишами. Ходить в настройки не есть удобно.
Когда же перешёл на Linux, то там вообще не обнаружилось подобной утилиты - тачпад всегда включён. И это очень не удобно. Настройка на отключение тачпада хоть и находится не очень далеко, но всё равно ходить туда каждый раз рано или поздно заколебает кого угодно. А когда обновился до GNOME 3, то обнаружил, что эта настройка куда-то делась... ещё лучше...

Но как оказалось решить проблему очень просто - всего лишь навсего полистать ман по иксах, а точнее по драйвера тачпада synaptics. Там в комплект входит небольшая утилита synclient, которая исполуется для диагностики и настройки параметров тачпада... Вот она очень просто может отключить и включить тачпад. Соответственно применение:
$ synclient TouchpadOff=1 $ synclient TouchpadOff=0
Есстессвенно каждый раз вводить такую команду равносильно, что ходить в настройки или там калацать. Поэтому лучше забиндить даные команды на какие-то кнопки и всё будет окей.
Но мы лёгких путей не ищем. Было бы неплохо, если бы за это отвечала одна комбинация, а не две... да и вообще было бы клёво видеть на экране сообщение о том, что тачпад включён или выключен... Линуксоид сказал - линуксоид сделал. Для решения это задачи нам нужно:
- руки
- голова
- gcc
- редактор кода (gedit, Geany подойдут)
- libnotify
- pkg-config
С руками и головой всё ясно, с компилятором gcc и редактором всё ясно. Посредством libnotify мы будем сообщать пользователю, что тачпад включён/выключен. А pkg-config поможет нам в линковек программы в кучу.
Начнём. Програма состоит из одного файла, ибо больше не нада. Назовём его как то типа main.c (разница не принципиальна). Первый делом включим заголовочные файлы необходимых нам библиотек:
#include <stdio.h>
#include <stdlib.h>
#include <libnotify/notify.h>
#include <signal.h>
#include <syslog.h>
#include <string.h>
Ого... много... но это ещё нечего... Но тут сразу нужно оговорить как программа будет работать. Она будет работать как демон, т.е. постоянно висеть запущеной в процессах. Посылая её сигнал мы будем включать или выключать тачпад. Теперь опеределяем переменные, которые нам нужно использовать:
NotifyNotification *notification; // это указатель на обьект с экранным сообщением
GError *error = NULL; // указатель на обьект с ошибками GLib
gint statusTouchpad = 0; // текущий статус тачпада (0 - включён, 1 - выключен)
gchar memTouchpad[2048]; // адрес к файлу, где запишем последнее состояние тачпада
gchar pidCtrl[2048]; // адрес к файлу, где запишем PID запущеного приложения (нужно для управления им)
Для удобства основные действия определим как отдельные функции. Первая передает synclient'у команду на изменение состояния тачпада:
void sync_touchpad() {
gint exitStatus;
gchar cmd[256]; // буффер, в котором мы сложим команду для выполнения
sprintf(cmd, "synclient TouchpadOff=%d", statusTouchpad); // собственно складываем команду
g_spawn_command_line_sync(cmd, NULL, NULL, &exitStatus, &error); // выполянем
}
Следующая расширяет функционал предыдущей: она ещё и выводит сообщение на екран плюс записыват состояние тачпада в файл:
void toggle_touchpad(int a) {
if(statusTouchpad) {
statusTouchpad = 0; // меняем состояние флага тачпада
notify_notification_update(notification, "Touchpad", "Touchpad have been enabled", "touchpad"); // задаём выводимое сообщние
} else {
statusTouchpad = 1;
notify_notification_update(notification, "Touchpad", "Touchpad have been disabled", "touchpad");
}
sync_touchpad(); // собственно управление тачпадом
notify_notification_show(notification, &error); // вывод сообщения
gchar cnt[4]; // буффер для записи в файл
sprintf(cnt, "%d", statusTouchpad); // заполняем буффер
g_file_set_contents(memTouchpad, cnt, strlen(cnt), &error); // записываем файл
}
Для выхода из программы будем использовать дополнительный обработчик:
void exit_prog(int a) {
g_remove(pidCtrl); // удляем файл с PID демона
exit(EXIT_SUCCESS); // сообщаем ОС, что мы нормально завершили программу
}
Тепер пишем наш main. Тут немного по шагам. Первым делом инициализируем libnotify:
notify_init("Touchpad");
notification = notify_notification_new(" "," ",NULL);
notify_notification_set_timeout(notification, 1000);
Теперь произведём загрузкусостояния тачпада с прошлого сеанса:
sprintf(memTouchpad, "%s/%s", g_get_home_dir(), ".touchpadOff"); // складывем имя файла состояния
if(g_file_test(memTouchpad, G_FILE_TEST_EXISTS)) { // если файл существует
gchar **cnt = g_malloc0(1024); // выделяем память для прочтения
g_file_get_contents(memTouchpad, cnt, NULL, &error); // читаем
gint newst; // сюда запишем состояние из файла
sscanf(*cnt, "%d", &newst); // парсим прочитанное из файла
g_free(cnt); // высвобождаем буффер чтения файла
if(newst != statusTouchpad) { // если мы считали состояние, отличное от текущего
statusTouchpad = newst; // меняем текущее сообщение
sync_touchpad(); // сообщаем это тачпаду (на экран сообщение не выводим)
}
}
Запишем PID программы в файл:
GPid pid = getpid(); // получаем PID
sprintf(pidCtrl, "%s/%s", g_get_home_dir(), ".touchpad.pid"); // складывем имя файла
gchar cnt[32]; // буффер для записи в файл
sprintf(cnt, "%d", pid); // заполняем буффер
g_file_set_contents(pidCtrl, cnt, strlen(cnt), &error); // записываем файл
Тепер самая важная часть - управление программой. Как уже было упомянуто, для этого используется механизм сигналов:
signal(SIGUSR1, toggle_touchpad); // по SIGUSER1 переключаем тачпад
signal(SIGTERM, exit_prog); // по SIGTERM выходим из программы
signal(SIGHUP, SIG_IGN); // SIGHUP игнорим
Ну и поледнее, зависаем и ждём указаний:
while(1)
sleep(10);
return (EXIT_SUCCESS);
Вот и всё программа написана. Компилируется программа просто:
$ gcc `pkg-config --cflags libnotify` `pkg-config --cflags glib-2.0` -o tpad_ctrld main.c
$ strip tpad_ctrld
Данный исполняемый файл забрасываем в автозапуск, и на запуске программа восстановит состояние тачпада с прошлого сеанса. Для управления тачпадом используется скрипт:
#!/bin/bash
FILE=".touchpad.pid"
PID="`dirname ~/$FILE`/$FILE"
if [ ! -f "$PID" ]; then
/usr/local/bin/tpad_ctrld &
elif ! ps -p `cat $PID`; then
/usr/local/bin/tpad_ctrld &
fi
while [ ! -f "$PID" ]; do
sleep 1
done
kill -USR1 `cat $PID`
Подрзувмеватеся, что программу мы разместили в /usr/local/bin/. Если программа не запущена, то скрипт запускает её... Потом посылает сигнал USR1.

Небольшое замечание: если в системе стоит какая то бадяга типа gsynaptics, то нужно организовать запуск нашей программы после него, поскольку он запросто может отменить действия synclient'а.
Скачать исходник