Hello community,
here is the log from the commit of package headmore for openSUSE:Factory checked in at 2016-11-03 11:14:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/headmore (Old)
and /work/SRC/openSUSE:Factory/.headmore.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "headmore"
Changes:
--------
--- /work/SRC/openSUSE:Factory/headmore/headmore.changes 2016-10-31 09:54:53.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.headmore.new/headmore.changes 2016-11-03 11:14:12.000000000 +0100
@@ -1,0 +2,11 @@
+Tue Nov 1 14:19:32 UTC 2016 - hguo@suse.com
+
+- Upgrade to release 1.1.1 with accumulated feature enhancements:
+ * Do not use the log file (.headmore.log) under home directory
+ anymore. Connection log is now directly printed in terminal.
+ * Use F10 key instead of escape key to quit the viewer.
+ * Draw VNC mouse cursor locally when zoomed out far.
+ * Improve handling of rapid input of Alt key combinations.
+ * Improve handling of viewer controls at lower FPS.
+
+-------------------------------------------------------------------
Old:
----
headmore-1.0.tar.gz
New:
----
headmore-1.1.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ headmore.spec ++++++
--- /var/tmp/diff_new_pack.gE8dyp/_old 2016-11-03 11:14:15.000000000 +0100
+++ /var/tmp/diff_new_pack.gE8dyp/_new 2016-11-03 11:14:15.000000000 +0100
@@ -1,6 +1,7 @@
#
# spec file for package headmore
#
+# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2016 Howard Guo
#
# All modifications and additions to the file contributed by third parties
@@ -15,17 +16,22 @@
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
+
Name: headmore
-Version: 1.0
+Version: 1.1.1
Release: 0
-License: GPL-3.0
Summary: VNC client for character terminals
-Url: https://github.com/HouzuoGuo/headmore
+License: GPL-3.0
Group: Productivity/Networking/Other
+Url: https://github.com/HouzuoGuo/headmore
Source: %{name}-%{version}.tar.gz
+BuildRequires: libgcrypt-devel
+BuildRequires: libjpeg8-devel
+BuildRequires: libopenssl-devel
+BuildRequires: libpng16-compat-devel
BuildRequires: pkg-config
-BuildRequires: pkgconfig(caca) pkgconfig(libvncclient)
-BuildRequires: libgcrypt-devel libjpeg8-devel libopenssl-devel libpng16-compat-devel
+BuildRequires: pkgconfig(caca)
+BuildRequires: pkgconfig(libvncclient)
%description
headmore is a client for Virtual Network Computing (VNC),
@@ -38,14 +44,12 @@
%setup -q
%build
-gzip %{name}.1
+gzip headmore.1
make
%install
-mkdir -p %{buildroot}/%{_bindir}/
-install -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}
-mkdir -p %{buildroot}/%{_mandir}/man1/
-install -m 0644 %{name}.1.gz %{buildroot}/%{_mandir}/man1/%{name}.1.gz
+install -D -m 0755 %{name} %{buildroot}/%{_bindir}/%{name}
+install -D -m 0644 %{name}.1.gz %{buildroot}/%{_mandir}/man1/%{name}.1.gz
%files
%defattr(-,root,root)
++++++ headmore-1.0.tar.gz -> headmore-1.1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/headmore-1.0/geo.c new/headmore-1.1.1/geo.c
--- old/headmore-1.0/geo.c 1970-01-01 01:00:00.000000000 +0100
+++ new/headmore-1.1.1/geo.c 2016-11-02 09:26:31.000000000 +0100
@@ -0,0 +1,150 @@
+#include
+#include "geo.h"
+
+struct geo_facts geo_facts_of(struct vnc *vnc, caca_display_t * disp,
+ caca_canvas_t * view)
+{
+ struct geo_facts ret;
+ ret.px_width = caca_get_display_width(disp);
+ ret.px_height = caca_get_display_height(disp);
+ ret.ch_width = caca_get_canvas_width(view);
+ ret.ch_height = caca_get_canvas_height(view);
+ ret.vnc_width = vnc->conn->width;
+ ret.vnc_height = vnc->conn->height;
+ return ret;
+}
+
+void geo_init(struct geo *g, struct geo_facts facts)
+{
+ memset(g, 0, sizeof(struct geo));
+ /* Fill the zoom table */
+ int i;
+ g->zoom_lvls[0] = 1.0;
+ for (i = 0; i < GEO_ZOOM_MAX_LVL; i++) {
+ g->zoom_lvls[i + 1] = g->zoom_lvls[i] * GEO_ZOOM_STEP;
+ }
+ /*
+ * Mouse speed is the inverse of zoom.
+ * At maximum zoom, mouse moves slowest at speed of 1px/move.
+ * Each zoom step lower speeds up mouse movement by 2px/move.
+ */
+ for (i = 0; i < GEO_ZOOM_MAX_LVL + 1; i++) {
+ g->mouse_speed[i] = 1 + (GEO_ZOOM_MAX_LVL - i) * 2;
+ }
+
+ /* Begin by placing image right at the centre */
+ g->view_x = 0.5;
+ g->view_y = 0.5;
+ geo_zoom(g, facts, 0);
+
+ /* Place mouse pointer at centre of screen and depress all buttons */
+ g->mouse_x = facts.vnc_width / 2;
+ g->mouse_y = facts.vnc_height / 2;
+}
+
+void geo_zoom(struct geo *g, struct geo_facts facts, int offset)
+{
+ g->zoom += offset;
+ if (g->zoom < 0) {
+ g->zoom = 0;
+ } else if (g->zoom > GEO_ZOOM_MAX_LVL) {
+ g->zoom = GEO_ZOOM_MAX_LVL;
+ }
+
+ g->zoom_x =
+ (g->zoom <
+ 0) ? 1.0 / g->zoom_lvls[-g->zoom] : g->zoom_lvls[g->zoom];
+ g->zoom_y =
+ g->zoom_x * facts.ch_width / facts.ch_height *
+ facts.vnc_height / facts.vnc_width * facts.ch_height /
+ facts.ch_width * facts.px_width / facts.px_height;
+
+ if (g->zoom_y > g->zoom_x) {
+ float tmp = g->zoom_x;
+ g->zoom_x = tmp * tmp / g->zoom_y;
+ g->zoom_y = tmp;
+ }
+}
+
+void geo_pan(struct geo *g, int pan_x, int pan_y)
+{
+ if (pan_x != 0) {
+ if (g->zoom_x > 1.0) {
+ g->view_x += pan_x * (GEO_PAN_STEP / g->zoom_x);
+ }
+ if (g->view_x < 0.0) {
+ g->view_x = 0.0;
+ } else if (g->view_x > 1.0) {
+ g->view_x = 1.0;
+ }
+ }
+ if (pan_y != 0) {
+ if (g->zoom_y > 1.0) {
+ g->view_y += pan_y * (GEO_PAN_STEP / g->zoom_y);
+ }
+ if (g->view_y < 0.0) {
+ g->view_y = 0.0;
+ } else if (g->view_y > 1.0) {
+ g->view_y = 1.0;
+ }
+ }
+}
+
+void geo_move_mouse(struct geo *g, struct geo_facts facts, int step_x,
+ int step_y)
+{
+ int speed = g->mouse_speed[g->zoom];
+ g->mouse_x += step_x * speed;
+ if (g->mouse_x < 0) {
+ g->mouse_x = 0;
+ } else if (g->mouse_x >= facts.vnc_width) {
+ g->mouse_x = facts.vnc_width - 1;
+ }
+ g->mouse_y += step_y * speed;
+ if (g->mouse_y < 0) {
+ g->mouse_y = 0;
+ } else if (g->mouse_y >= facts.vnc_height) {
+ g->mouse_y = facts.vnc_height - 1;
+ }
+}
+
+void geo_zoom_to_cursor(struct geo *g, struct geo_facts facts)
+{
+ /* Zoom in to approximately 67% of maximum zoom level */
+ geo_zoom(g, facts, GEO_ZOOM_CURSOR_LVL - g->zoom);
+ /* Calculate position of mouse cursor relative to the entire canvas */
+ g->view_x = (float)g->mouse_x / (float)facts.vnc_width;
+ g->view_y = (float)g->mouse_y / (float)facts.vnc_height;
+}
+
+struct geo_dither_params geo_get_dither_params(struct geo *g,
+ struct geo_facts facts)
+{
+ struct geo_dither_params ret;
+ ret.facts = facts;
+ float delta_x = (g->zoom_x > 1.0) ? g->view_x : 0.5;
+ float delta_y = (g->zoom_y > 1.0) ? g->view_y : 0.5;
+ ret.x = facts.ch_width * (1.0 - g->zoom_x) * delta_x;
+ ret.y = facts.ch_height * (1.0 - g->zoom_y) * delta_y;
+ ret.width = facts.ch_width * g->zoom_x + 1;
+ ret.height = facts.ch_height * g->zoom_y + 1;
+ return ret;
+}
+
+int geo_dither_ch_px_x(struct geo_dither_params *params, int px_x)
+{
+ float dx = (float)px_x / params->facts.vnc_width;
+ return dx * params->width + params->x;
+}
+
+int geo_dither_ch_px_y(struct geo_dither_params *params, int px_y)
+{
+ float dy = (float)px_y / params->facts.vnc_height;
+ return dy * params->height + params->y;
+}
+
+int geo_dither_numch_x(struct geo_dither_params *params, int num_pixels_x)
+{
+ return geo_dither_ch_px_x(params,
+ num_pixels_x) - geo_dither_ch_px_x(params, 0);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/headmore-1.0/geo.h new/headmore-1.1.1/geo.h
--- old/headmore-1.0/geo.h 1970-01-01 01:00:00.000000000 +0100
+++ new/headmore-1.1.1/geo.h 2016-11-02 09:26:31.000000000 +0100
@@ -0,0 +1,60 @@
+#ifndef GEO_H
+#define GEO_H
+
+#include
+#include "vnc.h"
+
+#define GEO_PAN_STEP 0.20
+#define GEO_ZOOM_STEP 1.20f
+#define GEO_ZOOM_MAX_LVL 15
+#define GEO_ZOOM_CURSOR_LVL 11 /* zoom level for zooming into mouse cursor */
+
+/* Geometry facts of terminal emulator and VNC connection. */
+struct geo_facts {
+ int px_width, px_height;
+ int ch_width, ch_height;
+ int vnc_width, vnc_height;
+};
+
+/* Return geometry facts of the VNC connection and caca terminal. */
+struct geo_facts geo_facts_of(struct vnc *vnc, caca_display_t * disp,
+ caca_canvas_t * canvas);
+
+/* Keep track of geometry of remote frame-buffer and canvas. */
+struct geo {
+ float view_x, zoom_x, view_y, zoom_y;
+ int zoom;
+ float zoom_lvls[GEO_ZOOM_MAX_LVL + 1];
+
+ int mouse_speed[GEO_ZOOM_MAX_LVL + 1];
+ int mouse_x, mouse_y;
+};
+
+/* Initialise geometry structure. */
+void geo_init(struct geo *g, struct geo_facts facts);
+/* Calculate geometry after zooming in (+) or out (-). */
+void geo_zoom(struct geo *g, struct geo_facts facts, int offset);
+/* Pan the canvas several steps up (-y), down (+y), left (-x), or right (+x). */
+void geo_pan(struct geo *g, int pan_x, int pan_y);
+/* Move mouse pointer several steps up (-y) down (+y), left (-x) or right (+x).*/
+void geo_move_mouse(struct geo *g, struct geo_facts facts, int step_x,
+ int step_y);
+/* Move view to the location of mouse cursor and zoom in there. */
+void geo_zoom_to_cursor(struct geo *g, struct geo_facts facts);
+
+/* Calculated parameters for dithering algorithm. */
+struct geo_dither_params {
+ struct geo_facts facts;
+ int x, y, width, height;
+};
+/* Calculate and return input parameters for dithering algorithm. */
+struct geo_dither_params geo_get_dither_params(struct geo *g,
+ struct geo_facts facts);
+/* Return the the character location of the VNC pixel on X axis. */
+int geo_dither_ch_px_x(struct geo_dither_params *params, int px_x);
+/* Return the the character location of the VNC pixel on Y axis. */
+int geo_dither_ch_px_y(struct geo_dither_params *params, int px_y);
+/* Return (approx.) number of characters it would take to draw those pixels on X axis. */
+int geo_dither_numch_x(struct geo_dither_params *params, int num_pixels_x);
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/headmore-1.0/headmore.1 new/headmore-1.1.1/headmore.1
--- old/headmore-1.0/headmore.1 2016-10-18 09:22:01.000000000 +0200
+++ new/headmore-1.1.1/headmore.1 2016-11-02 09:26:31.000000000 +0100
@@ -19,10 +19,6 @@
For QWERTY keyboard users, the left hand side controls are:
.TP
-.B Escape
-Disconnect from VNC server and leave the viewer immediately.
-.
-.TP
.B Back-tick (`)
Switch keyboard input between viewer/mouse control and VNC desktop. When you have just connected, your keyboard input is directed at viewer/mouse control.
.
@@ -43,6 +39,10 @@
And the right hand side controls are:
.TP
+.B F10
+Disconnect from VNC server and leave the viewer immediately.
+.
+.TP
.B I, J, K, L
Move mouse cursor up, left, down, or right. Cursor speed is determined by current zoom, it move slower when zoomed in.
.
@@ -85,14 +85,20 @@
.SH INPUT QUIRKS
-While nearly all keyboard input will be successfully sent to VNC desktop, there are however several quirks to bear in mind:
+While nearly all keyboard input will be successfully sent to VNC desktop, bear in mind several quirks caused by limitations of character terminal, universal to all terminal emulators:
.IP \[bu]
-If you have a computer mouse and your terminal emulator somehow forwards mouse clicks to headmore, headmore may do random things or quit unexpectedly.
+If you have a computer mouse and your terminal forwards mouse input headmore, headmore may react with random key input or quit unexpectedly.
+.IP \[bu]
+Meta key combinations such as Meta+D cannot be directly typed into VNC, you have to toggle hold Meta key and then type the modified key.
+.IP \[bu]
+Other modifier keys (Control and Alt) only work with lower case letters a-z. For other combinations such as Alt+F4 or Ctrl+Shift+A, toggle hold the modifier key and then press the modified key.
+.IP \[bu]
+Rapid input of Alt key combinations may occasionally result in the modified being typed without Alt modifier. Type Alt key combinations slowly to avoid encountering this issue.
.IP \[bu]
-All modifier keys only work with lower case letters a-z. For other combinations such as Alt+F4, toggle hold Alt key and then type F4 in VNC.
+Typing escape key and another key in short succession may result in an Alt combination being typed unexpectedly. Wait a short while after the escape key to avoid encountering this issue.
.IP \[bu]
-While most control characters such as Ctrl+C and Ctrl+D work reliably in VNC input, a few of them (such as Ctrl+Z) do not work in certain terminal emulators, you have to toggle hold control key and then press the other character individually.
+While most control characters such as Ctrl+C and Ctrl+D work reliably in VNC input, a few of them (such as Ctrl+Z) do not work in certain terminal emulators, in such cases you have to toggle hold Ctrl and then press the letter key.
.SH DESIGN RATIONALE
.B headmore
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/headmore-1.0/viewer.c new/headmore-1.1.1/viewer.c
--- old/headmore-1.0/viewer.c 2016-10-18 09:22:01.000000000 +0200
+++ new/headmore-1.1.1/viewer.c 2016-11-02 09:26:31.000000000 +0100
@@ -18,12 +18,12 @@
/* Messages to display in a static help menu. */
static char const *viewer_help[] = {
"============ LEFT HAND ============",
- "Esc Disconnect and quit ",
"` Toggle input to viewer/VNC ",
"~ Click back-tick in VNC ",
"wasd Pan viewer ",
"q/e Zoom out/in ",
"============ RIGHT HAND ===========",
+ "F10 Quit ",
"ijkl Move mouse cursor ",
"u/o Click L/R mouse button ",
"789 Toggle hold L/M/R mouse button",
@@ -38,104 +38,91 @@
};
/* Return the RFB client the viewer is connected to. */
-static struct _rfbClient *rfb(struct viewer *viewer)
+static struct _rfbClient *rfb(struct viewer *v)
{
- return viewer->vnc->conn;
+ return v->vnc->conn;
}
-bool viewer_init(struct viewer * viewer, struct vnc * vnc)
+bool viewer_init(struct viewer * v, struct vnc * vnc)
{
- memset(viewer, 0, sizeof(struct viewer));
- /* Fill the zoom table */
- int i;
- viewer->zoom_lvls[0] = 1.0;
- for (i = 0; i < VIEWER_ZOOM_MAX_LVL; i++) {
- viewer->zoom_lvls[i + 1] =
- viewer->zoom_lvls[i] * VIEWER_ZOOM_STEP;
- }
- /*
- * Mouse speed is the inverse of zoom.
- * At maximum zoom, mouse moves slowest at speed of 1px/move.
- * Each zoom step lower speeds up mouse movement by 2px/move.
- */
- for (i = 0; i < VIEWER_ZOOM_MAX_LVL + 1; i++) {
- viewer->mouse_speed[i] = 1 + (VIEWER_ZOOM_MAX_LVL - i) * 2;
- }
- viewer->view = caca_create_canvas(0, 0);
- if (!viewer->view) {
+ memset(v, 0, sizeof(struct viewer));
+ /* Initialise visuals */
+ v->view = caca_create_canvas(0, 0);
+ if (!v->view) {
fprintf(stderr, "Failed to create caca canvas\n");
return false;
}
- viewer->disp = caca_create_display_with_driver(viewer->view, "ncurses");
- if (!viewer->disp) {
+ v->disp = caca_create_display_with_driver(v->view, "ncurses");
+ if (!v->disp) {
fprintf(stderr, "Failed to create caca display\n");
return false;
}
- viewer->vnc = vnc;
- caca_set_display_title(viewer->disp, rfb(viewer)->desktopName);
+ v->vnc = vnc;
+ caca_set_display_title(v->disp, rfb(v)->desktopName);
+
+ /* Initialise parameters for geometry calculation */
+ geo_init(&v->geo, viewer_geo(v));
- /* Begin by placing image right at the centre */
- viewer->view_x = 0.5;
- viewer->view_y = 0.5;
- viewer_zoom(viewer, 0);
-
- /* Place mouse pointer at centre of screen and depress all buttons */
- viewer->mouse_x = rfb(viewer)->width / 2;
- viewer->mouse_y = rfb(viewer)->height / 2;
- viewer_vnc_send_pointer(viewer);
+ /* Tell VNC to place mouse pointer to default position */
+ viewer_vnc_send_pointer(v);
return true;
}
-void viewer_disp_status(struct viewer *viewer)
+struct geo_facts viewer_geo(struct viewer *v)
{
- caca_set_color_ansi(viewer->view, CACA_WHITE, CACA_BLUE);
+ return geo_facts_of(v->vnc, v->disp, v->view);
+}
+
+void viewer_disp_status(struct viewer *v)
+{
+ caca_set_color_ansi(v->view, CACA_WHITE, CACA_BLUE);
char *conn_remark = "";
- if (!viewer->vnc->connected) {
+ if (!v->vnc->connected) {
conn_remark = "(Disconnected)";
}
char *who_has_input = "Input to viewer";
- if (viewer->input2vnc) {
+ if (v->input2vnc) {
who_has_input = "Input to VNC (~ to disengage)";
}
char held_controls[80] = { 0 };
bool disp_held_controls = false;
- if (viewer->mouse_left) {
+ if (v->mouse_left) {
disp_held_controls = true;
strcat(held_controls, " LMouse");
}
- if (viewer->mouse_middle) {
+ if (v->mouse_middle) {
disp_held_controls = true;
strcat(held_controls, " MMouse");
}
- if (viewer->mouse_right) {
+ if (v->mouse_right) {
disp_held_controls = true;
strcat(held_controls, " RMouse");
}
- if (viewer->hold_lctrl) {
+ if (v->hold_lctrl) {
disp_held_controls = true;
strcat(held_controls, " LCtrl");
}
- if (viewer->hold_lshift) {
+ if (v->hold_lshift) {
disp_held_controls = true;
strcat(held_controls, " LShift");
}
- if (viewer->hold_lalt) {
+ if (v->hold_lalt) {
disp_held_controls = true;
strcat(held_controls, " LAlt");
}
- if (viewer->hold_lsuper) {
+ if (v->hold_lsuper) {
disp_held_controls = true;
strcat(held_controls, " LSuper");
}
- if (viewer->hold_ralt) {
+ if (v->hold_ralt) {
disp_held_controls = true;
strcat(held_controls, " RAlt");
}
- if (viewer->hold_rshift) {
+ if (v->hold_rshift) {
disp_held_controls = true;
strcat(held_controls, " RShift");
}
- if (viewer->hold_rctrl) {
+ if (v->hold_rctrl) {
disp_held_controls = true;
strcat(held_controls, " RCtrl");
}
@@ -144,225 +131,136 @@
strcat(held_controls_msg, "| Holding down:");
strcat(held_controls_msg, held_controls);
}
- caca_printf(viewer->view, 0, 0, "h:Help | %s:%d%s | %s %s",
- rfb(viewer)->serverHost, rfb(viewer)->serverPort,
- conn_remark, who_has_input, held_controls_msg);
+ caca_printf(v->view, 0, 0, "h:Help | %s:%d%s | %s %s",
+ rfb(v)->serverHost, rfb(v)->serverPort, conn_remark,
+ who_has_input, held_controls_msg);
}
-void viewer_disp_help(struct viewer *viewer)
+void viewer_disp_help(struct viewer *v)
{
- caca_set_color_ansi(viewer->view, CACA_WHITE, CACA_BLUE);
+ caca_set_color_ansi(v->view, CACA_WHITE, CACA_BLUE);
int i;
for (i = 0; viewer_help[i] != NULL; i++) {
- caca_put_str(viewer->view, 0, 1 + i, viewer_help[i]);
+ caca_put_str(v->view, 0, 1 + i, viewer_help[i]);
}
}
-void viewer_zoom(struct viewer *viewer, int offset)
+void viewer_redraw(struct viewer *v)
{
- viewer->zoom_lvl += offset;
- if (viewer->zoom_lvl < 0) {
- viewer->zoom_lvl = 0;
- } else if (viewer->zoom_lvl > VIEWER_ZOOM_MAX_LVL) {
- viewer->zoom_lvl = VIEWER_ZOOM_MAX_LVL;
- }
-
- int viewer_width = caca_get_canvas_width(viewer->view);
- int viewer_height = caca_get_canvas_height(viewer->view);
- viewer->zoom_x =
- (viewer->zoom_lvl <
- 0) ? 1.0 /
- viewer->zoom_lvls[-viewer->zoom_lvl] : viewer->
- zoom_lvls[viewer->zoom_lvl];
- viewer->zoom_y =
- viewer->zoom_x * viewer_width / viewer_height *
- rfb(viewer)->height / rfb(viewer)->width * viewer_height /
- viewer_width * caca_get_display_width(viewer->disp) /
- caca_get_display_height(viewer->disp);
-
- if (viewer->zoom_y > viewer->zoom_x) {
- float tmp = viewer->zoom_x;
- viewer->zoom_x = tmp * tmp / viewer->zoom_y;
- viewer->zoom_y = tmp;
- }
-}
-
-void viewer_pan(struct viewer *viewer, int pan_x, int pan_y)
-{
- if (pan_x != 0) {
- if (viewer->zoom_x > 1.0) {
- viewer->view_x +=
- pan_x * (VIEWER_PAN_STEP / viewer->zoom_x);
- }
- if (viewer->view_x < 0.0) {
- viewer->view_x = 0.0;
- } else if (viewer->view_x > 1.0) {
- viewer->view_x = 1.0;
- }
- }
- if (pan_y != 0) {
- if (viewer->zoom_y > 1.0) {
- viewer->view_y +=
- pan_y * (VIEWER_PAN_STEP / viewer->zoom_y);
- }
- if (viewer->view_y < 0.0) {
- viewer->view_y = 0.0;
- } else if (viewer->view_y > 1.0) {
- viewer->view_y = 1.0;
- }
- }
-}
-
-void viewer_redraw(struct viewer *viewer)
-{
- caca_set_color_ansi(viewer->view, CACA_WHITE, CACA_BLACK);
- caca_clear_canvas(viewer->view);
+ caca_clear_canvas(v->view);
/*
* Run the latest frame-buffer content through Floyd–Steinberg algorithm -
* it seems to offer higher quality over other algorithm choices.
* The dither parameters are tailored for a connection on 32-bit RGB colours.
*/
- if (viewer->fb_dither != NULL) {
- caca_free_dither(viewer->fb_dither);
+ if (v->fb_dither != NULL) {
+ caca_free_dither(v->fb_dither);
+ }
+ struct geo_facts facts = viewer_geo(v);
+ v->fb_dither =
+ caca_create_dither(32, facts.vnc_width, facts.vnc_height,
+ facts.vnc_width * 4, 0x000000ff, 0x0000ff00,
+ 0x00ff0000, 0);
+ caca_set_dither_algorithm(v->fb_dither, "fstein");
+ caca_set_dither_gamma(v->fb_dither, 1.0);
+ struct geo_dither_params params =
+ geo_get_dither_params(&v->geo, viewer_geo(v));
+ caca_dither_bitmap(v->view, params.x, params.y, params.width,
+ params.height, v->fb_dither, rfb(v)->frameBuffer);
+ /*
+ * Mouse cursors are usually wider than 14 pixels. If it will not take
+ * more than 5 characters to draw the cusor, then consider it very
+ * difficult to spot on the VNC canvas, and draw an easy to spot block
+ * right there.
+ */
+ if (geo_dither_numch_x(¶ms, 12) < 5) {
+ caca_set_color_ansi(v->view, CACA_WHITE, CACA_RED);
+ int ch_x = geo_dither_ch_px_x(¶ms, v->geo.mouse_x);
+ int ch_y = geo_dither_ch_px_y(¶ms, v->geo.mouse_y);
+ caca_fill_box(v->view, ch_x - 1, ch_y - 1, 3, 3, '*');
}
- viewer->fb_dither =
- caca_create_dither(32, rfb(viewer)->width,
- rfb(viewer)->height,
- rfb(viewer)->width * 4, 0x000000ff,
- 0x0000ff00, 0x00ff0000, 0);
- caca_set_dither_algorithm(viewer->fb_dither, "fstein");
- caca_set_dither_gamma(viewer->fb_dither, 1.0);
- int viewer_width = caca_get_canvas_width(viewer->view);
- int viewer_height = caca_get_canvas_height(viewer->view);
- float delta_x = (viewer->zoom_x > 1.0) ? viewer->view_x : 0.5;
- float delta_y = (viewer->zoom_y > 1.0) ? viewer->view_y : 0.5;
-
- /* Draw frame-buffer and other things on the canvas */
- caca_dither_bitmap(viewer->view,
- viewer_width * (1.0 -
- viewer->zoom_x) * delta_x,
- viewer_height * (1.0 -
- viewer->zoom_y) * delta_y,
- viewer_width * viewer->zoom_x + 1,
- viewer_height * viewer->zoom_y + 1,
- viewer->fb_dither, rfb(viewer)->frameBuffer);
- viewer_disp_status(viewer);
- if (viewer->disp_help) {
- viewer_disp_help(viewer);
+ viewer_disp_status(v);
+ if (v->disp_help) {
+ viewer_disp_help(v);
}
- caca_refresh_display(viewer->disp);
+ caca_refresh_display(v->disp);
}
-void viewer_ev_loop(struct viewer *viewer)
+void viewer_ev_loop(struct viewer *v)
{
+ int ev_accept =
+ CACA_EVENT_KEY_PRESS | CACA_EVENT_RESIZE | CACA_EVENT_QUIT;
while (true) {
/* Listen to the latest event */
caca_event_t ev;
- caca_get_event(viewer->disp,
- CACA_EVENT_KEY_PRESS | CACA_EVENT_RESIZE |
- CACA_EVENT_QUIT, &ev, 1000000 / VIEWER_FPS);
+ caca_get_event(v->disp, ev_accept, &ev,
+ VIEWER_FRAME_INTVL_USEC);
/* Certain types of events are caca calling quit */
enum caca_event_type ev_type = caca_get_event_type(&ev);
if (ev_type & CACA_EVENT_QUIT || ev_type & CACA_EVENT_NONE) {
return;
}
/* Handle previously banked escape key (VNC input), send it to VNC. */
- if (viewer->last_vnc_esc != 0
- && get_time_usec() - viewer->last_vnc_esc >=
- 1000000 / VIEWER_FPS) {
- viewer->last_vnc_esc = 0;
- viewer_vnc_click_key(viewer,
- cacakey2vnc(CACA_KEY_ESCAPE));
- }
- /* Handle previously banked escape key (viewer control), stop the viewer. */
- if (viewer->last_viewer_esc != 0
- && get_time_usec() - viewer->last_viewer_esc >=
- 1000000 / VIEWER_FPS) {
- return;
+ if (v->last_vnc_esc != 0
+ && get_time_usec() - v->last_vnc_esc >=
+ VIEWER_FRAME_INTVL_USEC) {
+ v->last_vnc_esc = 0;
+ viewer_vnc_click_key(v, cacakey2vnc(CACA_KEY_ESCAPE));
}
/* Redraw at a constant frame rate when there is no key input */
if (!(ev_type & CACA_EVENT_KEY_PRESS)) {
- viewer_redraw(viewer);
+ viewer_redraw(v);
continue;
}
int ev_char = caca_get_event_key_ch(&ev);
/* Input never gets directed at VNC if it is disconnected */
- if (!viewer->vnc->connected) {
- viewer->input2vnc = false;
+ if (!v->vnc->connected) {
+ v->input2vnc = false;
}
/* A key input is directed at either VNC or viewer controls */
- if (viewer->input2vnc && ev_char != '`') {
- viewer_input_to_vnc(viewer, ev_char);
- } else {
- viewer_handle_control(viewer, ev_char);
+ if (v->input2vnc && ev_char != '`') {
+ viewer_input_to_vnc(v, ev_char);
+ } else if (!viewer_handle_control(v, ev_char)) {
+ return;
}
}
}
-void viewer_vnc_click_key(struct viewer *viewer, int vnc_key)
+void viewer_vnc_click_key(struct viewer *v, int vnc_key)
{
- SendKeyEvent(rfb(viewer), vnc_key, TRUE);
- SendKeyEvent(rfb(viewer), vnc_key, FALSE);
+ SendKeyEvent(rfb(v), vnc_key, TRUE);
+ SendKeyEvent(rfb(v), vnc_key, FALSE);
}
-void viewer_vnc_click_ctrl_key_combo(struct viewer *viewer, int vnc_key)
+void viewer_vnc_click_ctrl_key_combo(struct viewer *v, int vnc_key)
{
- SendKeyEvent(rfb(viewer), XK_Control_L, TRUE);
- SendKeyEvent(rfb(viewer), vnc_key, TRUE);
- SendKeyEvent(rfb(viewer), vnc_key, FALSE);
- SendKeyEvent(rfb(viewer), XK_Control_L, FALSE);
+ SendKeyEvent(rfb(v), XK_Control_L, TRUE);
+ SendKeyEvent(rfb(v), vnc_key, TRUE);
+ SendKeyEvent(rfb(v), vnc_key, FALSE);
+ SendKeyEvent(rfb(v), XK_Control_L, FALSE);
}
-void viewer_vnc_toggle_key(struct viewer *viewer, int vnc_key, bool key_down)
+void viewer_vnc_toggle_key(struct viewer *v, int vnc_key, bool key_down)
{
- SendKeyEvent(rfb(viewer), vnc_key, key_down ? TRUE : FALSE);
+ SendKeyEvent(rfb(v), vnc_key, key_down ? TRUE : FALSE);
}
-void viewer_vnc_send_pointer(struct viewer *viewer)
+void viewer_vnc_send_pointer(struct viewer *v)
{
int mask = 0;
- if (viewer->mouse_left) {
+ if (v->mouse_left) {
mask |= rfbButton1Mask;
}
- if (viewer->mouse_middle) {
+ if (v->mouse_middle) {
mask |= rfbButton2Mask;
}
- if (viewer->mouse_right) {
+ if (v->mouse_right) {
mask |= rfbButton3Mask;
}
- SendPointerEvent(rfb(viewer), viewer->mouse_x, viewer->mouse_y, mask);
-}
-
-void viewer_move_mouse(struct viewer *viewer, int step_x, int step_y)
-{
- int speed = viewer->mouse_speed[viewer->zoom_lvl];
- viewer->mouse_x += step_x * speed;
- viewer->mouse_y += step_y * speed;
- if (viewer->mouse_x < 0) {
- viewer->mouse_x = 0;
- } else if (viewer->mouse_x > rfb(viewer)->width - 1) {
- viewer->mouse_x = rfb(viewer)->width - 1;
- }
- if (viewer->mouse_y < 0) {
- viewer->mouse_y = 0;
- } else if (viewer->mouse_y > rfb(viewer)->height - 1) {
- viewer->mouse_y = rfb(viewer)->height - 1;
- }
- viewer_vnc_send_pointer(viewer);
-}
-
-void viewer_zoom_to_cursor(struct viewer *viewer)
-{
- /* Zoom in to approximately 67% of maximum zoom level */
- viewer_zoom(viewer, VIEWER_ZOOM_MAX_LVL * 2 / 3 - viewer->zoom_lvl);
- /* Calculate position of mouse cursor relative to the entire canvas */
- viewer->view_x = (float)viewer->mouse_x / (float)rfb(viewer)->width;
- viewer->view_y = (float)viewer->mouse_y / (float)rfb(viewer)->height;
- /* Pan several steps to place the mouse cursor closer to view's centre */
- viewer_redraw(viewer);
+ SendPointerEvent(rfb(v), v->geo.mouse_x, v->geo.mouse_y, mask);
}
-void viewer_input_to_vnc(struct viewer *viewer, int caca_key)
+void viewer_input_to_vnc(struct viewer *v, int caca_key)
{
/*
* Escape key could mean two things, either it is a key press by itself, or it
@@ -372,7 +270,7 @@
* dealt with later.
*/
if (caca_key == CACA_KEY_ESCAPE) {
- viewer->last_vnc_esc = get_time_usec();
+ v->last_vnc_esc = get_time_usec();
return;
}
/*
@@ -404,24 +302,23 @@
case 24:
case 25:
case 26: /* (missing S) Ctrl+TUVWXYZ */
- viewer_vnc_click_ctrl_key_combo(viewer,
- caca_key - 1 + 'a');
+ viewer_vnc_click_ctrl_key_combo(v, caca_key - 1 + 'a');
return;
case 8: /* H and an extra backspace */
- viewer->void_backsp = true;
- viewer_vnc_click_ctrl_key_combo(viewer, 'h');
+ v->void_backsp = true;
+ viewer_vnc_click_ctrl_key_combo(v, 'h');
return;
case 9: /* I and an extra tab */
- viewer->void_tab = true;
- viewer_vnc_click_ctrl_key_combo(viewer, 'i');
+ v->void_tab = true;
+ viewer_vnc_click_ctrl_key_combo(v, 'i');
return;
case 13: /* M and an extra enter */
- viewer->void_ret = true;
- viewer_vnc_click_ctrl_key_combo(viewer, 'm');
+ v->void_ret = true;
+ viewer_vnc_click_ctrl_key_combo(v, 'm');
return;
case 19: /* S and an extra pause */
- viewer->void_pause = true;
- viewer_vnc_click_ctrl_key_combo(viewer, 's');
+ v->void_pause = true;
+ viewer_vnc_click_ctrl_key_combo(v, 's');
return;
}
}
@@ -431,25 +328,25 @@
*/
switch (caca_key) {
case CACA_KEY_BACKSPACE:
- if (viewer->void_backsp) {
- viewer->void_backsp = false;
+ if (v->void_backsp) {
+ v->void_backsp = false;
return;
}
break;
case CACA_KEY_TAB:
- if (viewer->void_tab) {
- viewer->void_tab = false;
+ if (v->void_tab) {
+ v->void_tab = false;
return;
}
break;
case CACA_KEY_RETURN:
- if (viewer->void_ret) {
- viewer->void_ret = false;
+ if (v->void_ret) {
+ v->void_ret = false;
return;
}
case CACA_KEY_PAUSE:
- if (viewer->void_pause) {
- viewer->void_pause = false;
+ if (v->void_pause) {
+ v->void_pause = false;
return;
}
}
@@ -460,175 +357,196 @@
return;
}
/*
- * In case there was a banked escape key, the Alt combination key shall arrive
- * in an instant within 2000 microseconds.
+ * In case there was a banked escape key, the Alt combination key shall
+ * arrive pretty soon, and most definitely before the next frame refresh.
+ * Occasionally it takes even longer to arrive but there is no way to
+ * work around it.
*/
- if (get_time_usec() - viewer->last_vnc_esc < 2000) {
- viewer_vnc_toggle_key(viewer, XK_Alt_L, true);
- viewer_vnc_click_key(viewer, translated_ch);
- viewer_vnc_toggle_key(viewer, XK_Alt_L, false);
- viewer->last_vnc_esc = 0;
+ suseconds_t elapsed = get_time_usec() - v->last_vnc_esc;
+ if (elapsed < VIEWER_FRAME_INTVL_USEC
+ && elapsed < VIEWER_MAX_INPUT_INTVL_USEC) {
+ viewer_vnc_toggle_key(v, XK_Alt_L, true);
+ viewer_vnc_click_key(v, translated_ch);
+ viewer_vnc_toggle_key(v, XK_Alt_L, false);
+ v->last_vnc_esc = 0;
return;
}
/* Finally the key code can be sent to VNC! */
- viewer_vnc_click_key(viewer, translated_ch);
+ viewer_vnc_click_key(v, translated_ch);
}
-void viewer_handle_control(struct viewer *viewer, int caca_key)
+bool viewer_handle_control(struct viewer * v, int caca_key)
{
/*
- * Similar to the case with viewer_input_to_vnc, if user accidentally types an
- * Alt key combination in the viewer, the first key event - an escape key will
- * mislead viewer into quitting.
- * Instead of quitting immediately, an escape key will be banked and the viewer
- * awaits one more key event to arrive. If it indeed arrives and within 2000
- * microseconds, then the user must have mistakenly typed Alt key combination,
- * in which case the viewer shall not quit.
- * If the latter key event does not arrive, the escape key must have been an
- * intention to quit the viewer and event loop will do that job.
+ * When the canvas is too busy panning/zooming, causing very low FPS,
+ * the terminal occasionally generates repeatitive key input seemingly
+ * out of nowhere, in very short successions. To work around it, this
+ * condition caps number of viewe controls to approximately 10 per second.
*/
- if (get_time_usec() - viewer->last_viewer_esc < 2000) {
- viewer->last_viewer_esc = 0;
+ suseconds_t elapsed = get_time_usec() - v->last_viewer_control;
+ if (v->last_viewer_control != 0
+ && elapsed < VIEWER_MAX_INPUT_INTVL_USEC) {
+ return true;
}
+ /*
+ * In order to avoid redrawing too rapidly, only viewer zoom/pan
+ * actions redraw immediately.
+ * VNC input has to wait for main loop to redraw at an interval.
+ */
switch (caca_key) {
case 'h':
case 'H':
- viewer->disp_help = !viewer->disp_help;
- break;
- case CACA_KEY_ESCAPE:
- /* Escape key is banked, its meaning will be determined soon later, */
- viewer->last_viewer_esc = get_time_usec();
+ v->disp_help = !v->disp_help;
break;
+ case CACA_KEY_F10:
+ return false;
/* Left hand */
case 'w':
case 'W':
- viewer_pan(viewer, 0, -1);
+ geo_pan(&v->geo, 0, -1);
+ viewer_redraw(v);
break;
case 'a':
case 'A':
- viewer_pan(viewer, -1, 0);
+ geo_pan(&v->geo, -1, 0);
+ viewer_redraw(v);
break;
case 's':
case 'S':
- viewer_pan(viewer, 0, 1);
+ geo_pan(&v->geo, 0, 1);
+ viewer_redraw(v);
break;
case 'd':
case 'D':
- viewer_pan(viewer, 1, 0);
+ geo_pan(&v->geo, 1, 0);
+ viewer_redraw(v);
break;
case 'q':
case 'Q':
- viewer_zoom(viewer, -1);
+ geo_zoom(&v->geo, viewer_geo(v), -1);
+ viewer_redraw(v);
break;
case 'e':
case 'E':
- viewer_zoom(viewer, 1);
+ geo_zoom(&v->geo, viewer_geo(v), 1);
+ viewer_redraw(v);
break;
case '`':
- if (viewer->vnc->connected) {
- viewer->input2vnc = !viewer->input2vnc;
+ if (v->vnc->connected) {
+ v->input2vnc = !v->input2vnc;
}
break;
case '~':
- viewer_vnc_click_key(viewer, 96); /* click back-tick (96 in ASCII) in VNC */
+ /* Click back-tick (96 in ASCII) in VNC */
+ viewer_vnc_click_key(v, 96);
break;
/* Right hand */
case 'i':
case 'I':
- viewer_move_mouse(viewer, 0, -1);
+ geo_move_mouse(&v->geo, viewer_geo(v), 0, -1);
+ viewer_vnc_send_pointer(v);
break;
case 'j':
case 'J':
- viewer_move_mouse(viewer, -1, 0);
+ geo_move_mouse(&v->geo, viewer_geo(v), -1, 0);
+ viewer_vnc_send_pointer(v);
break;
case 'k':
case 'K':
- viewer_move_mouse(viewer, 0, 1);
+ geo_move_mouse(&v->geo, viewer_geo(v), 0, 1);
+ viewer_vnc_send_pointer(v);
break;
case 'l':
case 'L':
- viewer_move_mouse(viewer, 1, 0);
+ geo_move_mouse(&v->geo, viewer_geo(v), 1, 0);
+ viewer_vnc_send_pointer(v);
break;
case 'u':
case 'U':
- viewer->mouse_left = true;
- viewer_vnc_send_pointer(viewer);
- viewer->mouse_left = false;
- viewer_vnc_send_pointer(viewer);
+ v->mouse_left = true;
+ viewer_vnc_send_pointer(v);
+ v->mouse_left = false;
+ viewer_vnc_send_pointer(v);
break;
case 'o':
case 'O':
- viewer->mouse_right = true;
- viewer_vnc_send_pointer(viewer);
- viewer->mouse_right = false;
- viewer_vnc_send_pointer(viewer);
+ v->mouse_right = true;
+ viewer_vnc_send_pointer(v);
+ v->mouse_right = false;
+ viewer_vnc_send_pointer(v);
break;
case '7':
- viewer->mouse_left = !viewer->mouse_left;
- viewer_vnc_send_pointer(viewer);
+ v->mouse_left = !v->mouse_left;
+ viewer_vnc_send_pointer(v);
break;
case '8':
- viewer->mouse_middle = !viewer->mouse_middle;
- viewer_vnc_send_pointer(viewer);
+ v->mouse_middle = !v->mouse_middle;
+ viewer_vnc_send_pointer(v);
break;
case '9':
- viewer->mouse_right = !viewer->mouse_right;
- viewer_vnc_send_pointer(viewer);
+ v->mouse_right = !v->mouse_right;
+ viewer_vnc_send_pointer(v);
break;
case '0':
- viewer->mouse_middle = true;
- viewer_vnc_send_pointer(viewer);
- viewer->mouse_middle = false;
- viewer_vnc_send_pointer(viewer);
+ v->mouse_middle = true;
+ viewer_vnc_send_pointer(v);
+ v->mouse_middle = false;
+ viewer_vnc_send_pointer(v);
break;
case 'p':
case 'P':
- viewer_zoom_to_cursor(viewer);
+ geo_zoom_to_cursor(&v->geo, viewer_geo(v));
break;
/* Toggle keys */
case 'z':
case 'Z':
- viewer->hold_lctrl = !viewer->hold_lctrl;
- viewer_vnc_toggle_key(viewer, XK_Control_L, viewer->hold_lctrl);
+ v->hold_lctrl = !v->hold_lctrl;
+ viewer_vnc_toggle_key(v, XK_Control_L, v->hold_lctrl);
break;
case 'm':
case 'M':
- viewer->hold_rctrl = !viewer->hold_rctrl;
- viewer_vnc_toggle_key(viewer, XK_Control_R, viewer->hold_rctrl);
+ v->hold_rctrl = !v->hold_rctrl;
+ viewer_vnc_toggle_key(v, XK_Control_R, v->hold_rctrl);
break;
case 'x':
case 'X':
- viewer->hold_lshift = !viewer->hold_lshift;
- viewer_vnc_toggle_key(viewer, XK_Shift_L, viewer->hold_lshift);
+ v->hold_lshift = !v->hold_lshift;
+ viewer_vnc_toggle_key(v, XK_Shift_L, v->hold_lshift);
break;
case 'n':
case 'N':
- viewer->hold_rshift = !viewer->hold_rshift;
- viewer_vnc_toggle_key(viewer, XK_Shift_R, viewer->hold_rshift);
+ v->hold_rshift = !v->hold_rshift;
+ viewer_vnc_toggle_key(v, XK_Shift_R, v->hold_rshift);
break;
case 'c':
case 'C':
- viewer->hold_lalt = !viewer->hold_lalt;
- viewer_vnc_toggle_key(viewer, XK_Alt_L, viewer->hold_lalt);
+ v->hold_lalt = !v->hold_lalt;
+ viewer_vnc_toggle_key(v, XK_Alt_L, v->hold_lalt);
break;
case 'b':
case 'B':
- viewer->hold_ralt = !viewer->hold_ralt;
- viewer_vnc_toggle_key(viewer, XK_Alt_R, viewer->hold_ralt);
+ v->hold_ralt = !v->hold_ralt;
+ viewer_vnc_toggle_key(v, XK_Alt_R, v->hold_ralt);
break;
case 'v':
case 'V':
- viewer->hold_lsuper = !viewer->hold_lsuper;
- viewer_vnc_toggle_key(viewer, XK_Super_L, viewer->hold_lsuper);
+ v->hold_lsuper = !v->hold_lsuper;
+ viewer_vnc_toggle_key(v, XK_Super_L, v->hold_lsuper);
break;
}
+ v->last_viewer_control = get_time_usec();
+ return true;
}
-void viewer_terminate(struct viewer *viewer)
+void viewer_terminate(struct viewer *v)
{
- caca_free_display(viewer->disp);
- caca_free_canvas(viewer->view);
- if (viewer->fb_dither != NULL) {
- caca_free_dither(viewer->fb_dither);
+ if (v->fb_dither != NULL) {
+ caca_free_dither(v->fb_dither);
+ }
+ if (v->disp != NULL) {
+ caca_free_display(v->disp);
+ }
+ if (v->view != NULL) {
+ caca_free_canvas(v->view);
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/headmore-1.0/viewer.h new/headmore-1.1.1/viewer.h
--- old/headmore-1.0/viewer.h 2016-10-18 09:22:01.000000000 +0200
+++ new/headmore-1.1.1/viewer.h 2016-11-02 09:26:31.000000000 +0100
@@ -1,68 +1,64 @@
#ifndef VIEWER_H
#define VIEWER_H
+#include
#include
#include
-#include
+#include "geo.h"
#include "vnc.h"
-#define VIEWER_PAN_STEP 0.20
-#define VIEWER_ZOOM_STEP 1.20f
-#define VIEWER_ZOOM_MAX_LVL 15
-#define VIEWER_FPS 10 /* too high FPS will make control sluggish, never go above 50. */
+/*
+ * The viewer will render frame-buffer content at roughly this many frames per second.
+ * It does not take rendering algorithm itself into account, hence the value is a rough estimate at best.
+ * The perceived FPS decreases as terminal gets larger.
+ * Do not raise the value too high or controls will become very sluggish.
+ */
+#define VIEWER_FPS 10
+#define VIEWER_FRAME_INTVL_USEC (1000000 / VIEWER_FPS)
+#define VIEWER_MAX_INPUT_INTVL_USEC (1000000 / VIEWER_FPS)
-/* Draw remote frame-buffer and handle key/mouse IO. */
+/* Render remote frame-buffer on terminal and handle key/mouse IO. */
struct viewer {
struct vnc *vnc;
- caca_display_t *disp;
+ struct geo geo;
+ caca_display_t *disp;
caca_canvas_t *view;
struct caca_dither *fb_dither;
- float view_x, zoom_x, view_y, zoom_y;
- int zoom_lvl;
- float zoom_lvls[VIEWER_ZOOM_MAX_LVL + 1];
- int mouse_speed[VIEWER_ZOOM_MAX_LVL + 1];
- int mouse_x, mouse_y;
- bool mouse_left, mouse_middle, mouse_right;
-
- suseconds_t last_vnc_esc, last_viewer_esc;
+ suseconds_t last_vnc_esc, last_viewer_control;
bool void_backsp, void_tab, void_ret, void_pause, void_esc, void_del;
bool disp_help, input2vnc;
bool hold_lctrl, hold_lshift, hold_lalt, hold_lsuper, hold_ralt,
hold_rshift, hold_rctrl;
+ bool mouse_left, mouse_middle, mouse_right;
};
-/* Initialise canvas and its driver for the VNC connection. */
-bool viewer_init(struct viewer *viewer, struct vnc *vnc);
+/* Initialise viewer and its driver for the VNC connection. */
+bool viewer_init(struct viewer *v, struct vnc *vnc);
+/* Return geometry facts of the viewer. */
+struct geo_facts viewer_geo(struct viewer *v);
/* Display a status row at 0,0. */
-void viewer_disp_status(struct viewer *viewer);
+void viewer_disp_status(struct viewer *v);
/* Display a static help menu at 0,1. */
-void viewer_disp_help(struct viewer *viewer);
-/* Zoom in (+) or out (-) on the canvas. Remember to redraw! */
-void viewer_zoom(struct viewer *viewer, int offset);
-/* Pan the canvas several steps up (-y), down (+y), left (-x), or right (+x). Remember to redraw! */
-void viewer_pan(struct viewer *viewer, int pan_x, int pan_y);
+void viewer_disp_help(struct viewer *v);
/* Redraw the content from the latest frame-buffer of VNC connection. */
-void viewer_redraw(struct viewer *viewer);
+void viewer_redraw(struct viewer *v);
/* Handle keyboard input and canvas events. Block caller until quit key is pressed and handled. */
-void viewer_ev_loop(struct viewer *viewer);
+void viewer_ev_loop(struct viewer *v);
/* Click (press and release) a keyboard key in VNC. */
-void viewer_vnc_click_key(struct viewer *viewer, int vnc_key);
+void viewer_vnc_click_key(struct viewer *v, int vnc_key);
/* Hold control key and then click the specified key in VNC, then release control key. */
-void viewer_vnc_click_ctrl_key_combo(struct viewer *viewer, int vnc_key);
+void viewer_vnc_click_ctrl_key_combo(struct viewer *v, int vnc_key);
/* Toggle (press or release) a keyboard key in VNC. */
-void viewer_vnc_toggle_key(struct viewer *viewer, int vnc_key, bool key_down);
+void viewer_vnc_toggle_key(struct viewer *v, int vnc_key, bool key_down);
/* Send the latest pointer location and button mask to VNC. */
-void viewer_vnc_send_pointer(struct viewer *viewer);
-/* Move mouse pointer several steps up (-y) down (+y), left (-x) or right (+x).*/
-void viewer_move_mouse(struct viewer *viewer, int step_x, int step_y);
-/* Move view to the location of mouse cursor and zoom in there to a pre-defined level. */
-void viewer_zoom_to_cursor(struct viewer *viewer);
+void viewer_vnc_send_pointer(struct viewer *v);
/* Translate caca key stroke to VNC key symbol and send it over VNC. */
-void viewer_input_to_vnc(struct viewer *viewer, int caca_key);
-/* Interpret and act on caca key stroke as a viewer control command. */
-void viewer_handle_control(struct viewer *viewer, int caca_key);
+void viewer_input_to_vnc(struct viewer *v, int caca_key);
+/* Interpret and act on caca key stroke as a viewer control command. Return false only if viewer should quit. */
+bool viewer_handle_control(struct viewer *v, int caca_key);
/* Release all resources held by the viewer, but do not terminate the VNC connection. */
-void viewer_terminate(struct viewer *viewer);
+void viewer_terminate(struct viewer *v);
+
#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/headmore-1.0/vnc.c new/headmore-1.1.1/vnc.c
--- old/headmore-1.0/vnc.c 2016-10-18 09:22:01.000000000 +0200
+++ new/headmore-1.1.1/vnc.c 2016-11-02 09:26:31.000000000 +0100
@@ -1,8 +1,6 @@
-#include
#include
#include
#include
-#include
#include
#include
#include
@@ -11,26 +9,6 @@
#include
#include "vnc.h"
-static FILE *vnc_dbg_log = NULL; /* direct VNC library log to a tmp file */
-
-/* Write a log line into log file. */
-static void vnc_log2file(const char *format, ...)
-{
- if (!rfbEnableClientLogging || vnc_dbg_log == NULL) {
- return;
- }
- time_t now;
- time(&now);
- char timestamp[100];
- strftime(timestamp, 100 - 1, "%Y-%m-%d %X ", localtime(&now));
- fprintf(vnc_dbg_log, "%s", timestamp);
- va_list args;
- va_start(args, format);
- vfprintf(vnc_dbg_log, format, args);
- va_end(args);
- fflush(vnc_dbg_log);
-}
-
/* Process RFB server messages, block caller. Return NULL. */
static void *io_loop_fun(void *struct_vnc)
{
@@ -50,60 +28,38 @@
return NULL;
}
-bool vnc_init(struct vnc * vnc, int argc, char **argv)
+bool vnc_init(struct vnc * v, int argc, char **argv)
{
- memset(vnc, 0, sizeof(struct vnc));
- /* A debug log file is created under user's home directory */
- char *home_dir_path = getenv("HOME");
- if (home_dir_path != NULL) {
- char *log_file_path =
- (char *)calloc(strlen(home_dir_path) + strlen(VNC_DBG_LOG) +
- 2, sizeof(char));
- if (!log_file_path) {
- fprintf(stderr, "Out of memory");
- return false;
- }
- strcat(log_file_path, home_dir_path);
- strcat(log_file_path, "/");
- strcat(log_file_path, VNC_DBG_LOG);
- printf("Log file is located at %s\n", log_file_path);
- vnc_dbg_log = fopen(log_file_path, "a");
- free(log_file_path);
- }
- /* libvncserver shares logging functions across all connections */
- rfbClientLog = vnc_log2file;
- rfbClientErr = vnc_log2file;
+ memset(v, 0, sizeof(struct vnc));
/*
* The connection asks server for 32-bit RGB colours.
* Take note that VNC does not use alpha channel, hence the most significant 2 bytes are useless.
* I think 256-colours should be more than sufficient for this VNC client, but somehow I could not
* get a sufficiently good quality out of dithering process, perhaps I got the bit-masks wrong?
*/
- vnc->conn = rfbGetClient(8, 3, 4);
- vnc->conn->canHandleNewFBSize = FALSE;
- printf("Establishing VNC connection...\n");
- if (!rfbInitClient(vnc->conn, &argc, argv)) {
+ v->conn = rfbGetClient(8, 3, 4);
+ v->conn->canHandleNewFBSize = FALSE;
+ if (!rfbInitClient(v->conn, &argc, argv)) {
return false;
}
- printf("Connection is successfully established!\n");
- vnc->cont_io_loop = true;
- vnc->connected = true;
- if (pthread_create(&vnc->io_loop, NULL, io_loop_fun, (void *)vnc) != 0) {
+ v->cont_io_loop = true;
+ v->connected = true;
+ if (pthread_create(&v->io_loop, NULL, io_loop_fun, (void *)v) != 0) {
fprintf(stderr, "Failed to create message loop thread\n");
return false;
}
return true;
}
-void vnc_destroy(struct vnc *vnc)
+void vnc_destroy(struct vnc *v)
{
- vnc->cont_io_loop = false;
- vnc->connected = false;
- if (pthread_join(vnc->io_loop, NULL) != 0) {
+ v->cont_io_loop = false;
+ v->connected = false;
+ if (pthread_join(v->io_loop, NULL) != 0) {
fprintf(stderr, "Failed to join message loop thread\n");
}
- uint8_t *fb = vnc->conn->frameBuffer;
- rfbClientCleanup(vnc->conn);
+ uint8_t *fb = v->conn->frameBuffer;
+ rfbClientCleanup(v->conn);
free(fb);
rfbClientLog("VNC connection has been terminated\n");
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/headmore-1.0/vnc.h new/headmore-1.1.1/vnc.h
--- old/headmore-1.0/vnc.h 2016-10-18 09:22:01.000000000 +0200
+++ new/headmore-1.1.1/vnc.h 2016-11-02 09:26:31.000000000 +0100
@@ -4,9 +4,7 @@
#include
#include
-#define VNC_POLL_TIMEOUT_USEC 100000 /* keep it under a second */
-#define VNC_DBG_LOG ".headmore.log" /* name of log file under user's home directory */
-#define VNC_PASS_MAX 256 /* maximum length of input password */
+#define VNC_POLL_TIMEOUT_USEC 100000 /* A lower value enables faster termination of VNC IO loop */
/* Connect to remote frame-buffer and handle control/image IO. */
struct vnc {
@@ -16,9 +14,9 @@
};
/* Connect to server and immediately begin message loop in a separate thread. Return false only on failure. */
-bool vnc_init(struct vnc *vnc, int argc, char **argv);
+bool vnc_init(struct vnc *v, int argc, char **argv);
/* Close VNC connection and free all resources, including the VNC client itself. */
-void vnc_destroy(struct vnc *vnc);
+void vnc_destroy(struct vnc *v);
/* Translate a key code as read by libcaca to its corresponding VNC key code. Return -1 only if no translation. */
int cacakey2vnc(int keych);