Commit 1d88fec0 authored by Bill Allombert's avatar Bill Allombert

consolation 0.0.0

parents
Author:
Bill Allombert
Acknowledgement:
This software relies heavily on the work of the libinput developers:
<http://www.freedesktop.org/wiki/Software/libinput/>
It was influenced by gpm (for GPM history, see
<https://en.wikipedia.org/wiki/GPM_%28software%29>)
and jamd <http://jamd.sourceforge.net> by Jonathan C. Atkins.
Copyright © 2016 Bill Allombert
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
You should have received a copy of the GNU General Public License with
the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL;
if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
Floor, Boston, MA 02110-1301, USA.
This work is based on event-debug from libinput, which is:
Copyright © 2014 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
SUBDIRS = src
dist_man_MANS = consolation.8
EXTRA_DIST = AUTHORS LICENSE
NAME
consolation -- copy-paste for the Linux console
SYNOPSYS
consolation [libinput options]
Run consolation --help for libinput options
DESCRIPTION
Consolation is a daemon that provide copy-paste and scrolling support to the
Linux console.
It is based on the libinput library and supports all pointer devices and
settings provided by this library,
Similar software include gpm and jamd.
Operations:
left button: start selection
middle button: paste selection
right button: set end of selection
wheel: scroll
LICENSE
Copyright © 2016 Bill Allombert
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SEE ALSO
gpm(8)
AUTHOR
Bill Allombert <ballombe@debian.org>
AC_PREREQ([2.69])
AC_INIT([consolation], [0.0.0])
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
# Check for programs
AC_PROG_CC
PKG_PROG_PKG_CONFIG()
PKG_CHECK_MODULES(LIBINPUT, [libinput >= 1.3.3])
PKG_CHECK_MODULES(LIBUDEV, [libudev])
PKG_CHECK_MODULES(LIBEVDEV, [libevdev >= 0.4])
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT
bin_PROGRAMS = consolation
consolation_SOURCES = consolation.c consolation.h selection.c action.c input.c shared.c shared.h
consolation_CFLAGS = $(LIBUDEV_CFLAGS) $(LIBEVDEV_CFLAGS) $(LIBINPUT_CFLAGS)
consolation_LDADD = $(LIBUDEV_LIBS) $(LIBEVDEV_LIBS) $(LIBINPUT_LIBS)
/* Copyright © 2016 Bill Allombert
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
Check the License for details. You should have received a copy of it, along
with the package; see the file 'COPYING'. If not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "consolation.h"
static double xx=1, yy=1, x0=-1, y0=-1, x1=-1, y1=-1;
static int mode = 0;
void
set_pointer(double x, double y)
{
xx = x+1; yy = y+1;
if (xx < 1) xx = 1; else if (xx > screen_width) xx = screen_width;
if (yy < 1) yy = 1; else if (yy > screen_height) yy = screen_height;
if (x0 >= 0 && y0 >= 0)
select_region((int)xx,(int)yy,(int)x0,(int)y0);
else
draw_pointer((int)xx,(int)yy);
}
void
move_pointer(double x, double y)
{
xx += x/20; yy += y/20;
if (xx < 1) xx = 1; else if (xx > screen_width) xx = screen_width;
if (yy < 1) yy = 1; else if (yy > screen_height) yy = screen_height;
if (x0 >= 0 && y0 >= 0)
select_region((int)xx,(int)yy,(int)x0,(int)y0);
else
draw_pointer((int)xx,(int)yy);
}
void
press_left_button(void)
{
if ((int)x1==(int)xx && (int)y1==(int)yy)
{
mode = (mode+1)%3;
switch(mode)
{
case 0:
select_region((int)xx,(int)yy,(int)xx,(int)yy);
break;
case 1:
select_word((int)xx,(int)yy);
break;
case 2:
select_line((int)xx,(int)yy);
break;
}
}
else
{
x0=xx; y0=yy; x1=x0; y1=y0; mode = 0;
select_region((int)xx,(int)yy,(int)x0,(int)y0);
}
}
void
release_left_button(void)
{
x0=-1; y0=-1;
}
void
press_middle_button(void)
{
paste();
}
void
press_right_button(void)
{
if (x1>=0 && y1>=0)
select_region((int)xx,(int)yy,(int)x1,(int)y1);
}
void
vertical_axis(double v)
{
if (v)
scroll(v > 0 ? 2 : -2);
}
/* Copyright © 2016 Bill Allombert
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
Check the License for details. You should have received a copy of it, along
with the package; see the file 'COPYING'. If not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "consolation.h"
static int csl_daemon(void)
{
pid_t pid = fork();
switch(pid) {
case -1: return 1; /* father, fork failed */
case 0:
(void)setsid(); /* son becomes process group leader */
if (fork()) exit(0); /* now son exits, also when fork fails */
break; /* grandson: its father is the son, which exited,
* hence father becomes 'init', that'll take care of it */
default: /* father, fork succeeded */
(void)waitpid(pid,NULL,0); /* wait for son to exit, immediate */
return 1;
}
/* grandson */
return 0;
}
int main(int argc, char **argv)
{
struct winsize s;
tty0 = open("/dev/tty0", O_RDWR);
if (tty0 < 0) perror("open console");
if (ioctl(0, TIOCGWINSZ, &s)) perror("TIOCGWINSZ");
screen_width = s.ws_col;
screen_height = s.ws_row;
if (!csl_daemon()) event_main(argc, argv);
return 0;
}
/* Copyright © 2016 Bill Allombert
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
Check the License for details. You should have received a copy of it, along
with the package; see the file 'COPYING'. If not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* global state */
int tty0;
unsigned int screen_width;
unsigned int screen_height;
/* selection.c */
void draw_pointer(int x, int y);
void select_region(int x, int y, int x2, int y2);
void select_word(int x, int y);
void select_line(int x, int y);
void paste(void);
void scroll(int sc);
/* action.c */
void set_pointer(double x, double y);
void move_pointer(double x, double y);
void press_left_button(void);
void release_left_button(void);
void press_middle_button(void);
void press_right_button(void);
void vertical_axis(double v);
/* input.c */
int event_main(int argc, char **argv);
/* Adpated from test/event-debug.c from the libinput distribution */
/* test/event-debug.c 1.3.3:
* Copyright © 2014 Red Hat, Inc.
* Modifications: Copyright © 2016 Bill Allombert <ballombe@debian.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <inttypes.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/ioctl.h>
#include <libinput.h>
#include "shared.h"
#include "consolation.h"
struct tools_context context;
static unsigned int stop = 0;
static void
handle_motion_event(struct libinput_event *ev)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
double x = libinput_event_pointer_get_dx(p);
double y = libinput_event_pointer_get_dy(p);
move_pointer(x, y);
}
static void
handle_pointer_button_event(struct libinput_event *ev)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
enum libinput_button_state state;
int button;
button = libinput_event_pointer_get_button(p);
state = libinput_event_pointer_get_button_state(p);
switch(button)
{
case BTN_LEFT:
if (state==LIBINPUT_BUTTON_STATE_PRESSED)
press_left_button();
else
release_left_button();
break;
case BTN_MIDDLE:
if (state==LIBINPUT_BUTTON_STATE_PRESSED)
press_middle_button();
break;
case BTN_RIGHT:
if (state==LIBINPUT_BUTTON_STATE_PRESSED)
press_right_button();
break;
}
}
static void
handle_pointer_axis_event(struct libinput_event *ev)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
double v = 0;
if (libinput_event_pointer_has_axis(p,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
{
v = libinput_event_pointer_get_axis_value(p,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
vertical_axis(v);
}
}
static void
handle_touch_event_down(struct libinput_event *ev)
{
struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
double x = libinput_event_touch_get_x_transformed(t, screen_width);
double y = libinput_event_touch_get_y_transformed(t, screen_height);
set_pointer(x, y);
press_left_button();
}
static void
handle_touch_event_motion(struct libinput_event *ev)
{
struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
double x = libinput_event_touch_get_x_transformed(t, screen_width);
double y = libinput_event_touch_get_y_transformed(t, screen_height);
set_pointer(x, y);
}
static void
handle_touch_event_up(struct libinput_event *ev)
{
release_left_button();
}
static int
handle_and_print_events(struct libinput *li)
{
int rc = -1;
struct libinput_event *ev;
libinput_dispatch(li);
while ((ev = libinput_get_event(li))) {
switch (libinput_event_get_type(ev)) {
case LIBINPUT_EVENT_NONE:
abort();
case LIBINPUT_EVENT_DEVICE_ADDED:
case LIBINPUT_EVENT_DEVICE_REMOVED:
tools_device_apply_config(libinput_event_get_device(ev),
&context.options);
break;
case LIBINPUT_EVENT_POINTER_MOTION:
handle_motion_event(ev);
break;
case LIBINPUT_EVENT_POINTER_BUTTON:
handle_pointer_button_event(ev);
break;
case LIBINPUT_EVENT_POINTER_AXIS:
handle_pointer_axis_event(ev);
break;
case LIBINPUT_EVENT_TOUCH_DOWN:
handle_touch_event_down(ev);
break;
case LIBINPUT_EVENT_TOUCH_MOTION:
handle_touch_event_motion(ev);
break;
case LIBINPUT_EVENT_TOUCH_UP:
handle_touch_event_up(ev);
break;
default:
break;
}
libinput_event_destroy(ev);
libinput_dispatch(li);
rc = 0;
}
return rc;
}
static void
sighandler(int signal, siginfo_t *siginfo, void *userdata)
{
stop = 1;
}
static void
mainloop(struct libinput *li)
{
struct pollfd fds;
struct sigaction act;
fds.fd = libinput_get_fd(li);
fds.events = POLLIN;
fds.revents = 0;
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &act, NULL) == -1) {
fprintf(stderr, "Failed to set up signal handling (%s)\n",
strerror(errno));
return;
}
/* Handle already-pending device added events */
if (handle_and_print_events(li))
fprintf(stderr, "Expected device added events on startup but got none. "
"Maybe you don't have the right permissions?\n");
while (!stop && poll(&fds, 1, -1) > -1)
handle_and_print_events(li);
}
int
event_main(int argc, char **argv)
{
struct libinput *li;
tools_init_context(&context);
if (tools_parse_args(argc, argv, &context))
return 1;
li = tools_open_backend(&context);
if (!li)
return 1;
mainloop(li);
libinput_unref(li);
return 0;
}
/* Copyright © 2016 Bill Allombert
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 General Public License for more details.
Check the License for details. You should have received a copy of it, along
with the package; see the file 'COPYING'. If not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/tiocl.h>
#include "consolation.h"
static void
linux_selection(int xs, int ys, int xe, int ye, int sel_mode)
{
struct {
char argp[2]; /*Force struct alignment*/
struct tiocl_selection sel;
} s;
s.argp[0] = 0; /* unused */
s.argp[1] = TIOCL_SETSEL;
s.sel.xs = xs;
s.sel.ys = ys;
s.sel.xe = xe;
s.sel.ye = ye;
s.sel.sel_mode = sel_mode;
if(ioctl(tty0, TIOCLINUX, ((char*)&s)+1)<0)
perror("selection: TIOCLINUX");
}
void
draw_pointer(int x, int y)
{
linux_selection(x, y, x, y, TIOCL_SELPOINTER);
}
void
select_region(int x, int y, int x2, int y2)
{
if (x2 < 0) x2 = x;
if (y2 < 0) y2 = y;
linux_selection(x, y, x2, y2, TIOCL_SELCHAR);
}
void
select_word(int x, int y)
{
linux_selection(x, y, x, y, TIOCL_SELWORD);
}
void
select_line(int x, int y)
{
linux_selection(x, y, x, y, TIOCL_SELLINE);
}
void paste(void)
{
int fd;
char subcode = TIOCL_PASTESEL;
fd = open("/dev/tty0",O_RDWR);
if(ioctl(fd, TIOCLINUX, &subcode)<0)
perror("paste: TIOCLINUX");
close(fd);
}
void scroll(int sc)
{
struct {
char subcode[4];
int sc;
} scr;
scr.subcode[0] = TIOCL_SCROLLCONSOLE;
scr.subcode[1] = 0;
scr.subcode[2] = 0;
scr.subcode[3] = 0;
scr.sc = sc;
if(ioctl(tty0, TIOCLINUX, &scr)<0)
perror("scroll: TIOCLINUX");
}
This diff is collapsed.
/* Adapted from test/shared.h from the libinput distribution */
/* test/shared.h 1.3.3:
* Copyright © 2014 Red Hat, Inc.
* Modifications: Copyright © 2016 Bill Allombert <ballombe@debian.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _SHARED_H_
#define _SHARED_H_
#include <libinput.h>
enum tools_backend {
BACKEND_DEVICE,
BACKEND_UDEV
};
struct tools_options {
enum tools_backend backend;
const char *device; /* if backend is BACKEND_DEVICE */
const char *seat; /* if backend is BACKEND_UDEV */
int grab; /* EVIOCGRAB */
int verbose;
int tapping;
int drag;
int drag_lock;
int natural_scroll;
int left_handed;
int middlebutton;
enum libinput_config_click_method click_method;
enum libinput_config_scroll_method scroll_method;
int scroll_button;
double speed;
int dwt;
enum libinput_config_accel_profile profile;
};
struct tools_context {
struct tools_options options;
void *user_data;
};
void tools_init_context(struct tools_context *context);
int tools_parse_args(int argc, char **argv, struct tools_context *context);
struct libinput* tools_open_backend(struct tools_context *context);
void tools_device_apply_config(struct libinput_device *device,
struct tools_options *options);
void tools_usage();
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment