mirror of
https://github.com/Wessel/c-websocket-server.git
synced 2026-07-17 14:04:15 +02:00
feat: Populate repo
This commit is contained in:
60
git/wsserver/examples/vtouchpad/CMakeLists.txt
Normal file
60
git/wsserver/examples/vtouchpad/CMakeLists.txt
Normal file
@@ -0,0 +1,60 @@
|
||||
# Copyright (C) 2022 Davidson Francis <davidsondfgl@gmail.com>
|
||||
#
|
||||
# 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 3 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
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
|
||||
add_executable(vtouchpad vtouchpad.c)
|
||||
target_compile_definitions(vtouchpad PRIVATE DISABLE_VERBOSE)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
target_sources(vtouchpad PRIVATE mouse_x11.c)
|
||||
|
||||
#
|
||||
# If FreeBSD, add /usr/local/include to the search path too,
|
||||
# see: https://wiki.freebsd.org/WarnerLosh/UsrLocal
|
||||
#
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
set(CMAKE_REQUIRED_INCLUDES "/usr/local/include;/usr/include")
|
||||
target_link_directories(vtouchpad PUBLIC /usr/local/lib)
|
||||
target_include_directories(vtouchpad PUBLIC /usr/local/include)
|
||||
endif()
|
||||
|
||||
CHECK_INCLUDE_FILES("xdo.h" HAVE_XDO_H)
|
||||
if (NOT HAVE_XDO_H)
|
||||
|
||||
message(WARNING "libxdo/xdotool not found, trying to use XTest exts...")
|
||||
CHECK_INCLUDE_FILES("X11/extensions/XTest.h" HAVE_XTEST_H)
|
||||
|
||||
if (NOT HAVE_XTEST_H)
|
||||
message(WARNING "Unable to find XTest.h, vtouchpad is unable "
|
||||
"to work in your system, disabling build...")
|
||||
set_target_properties(vtouchpad
|
||||
PROPERTIES EXCLUDE_FROM_ALL True)
|
||||
endif ()
|
||||
|
||||
target_link_libraries(vtouchpad X11 Xtst ws pthread)
|
||||
else()
|
||||
target_compile_definitions(vtouchpad PUBLIC HAVE_XDOTOOL)
|
||||
target_link_libraries(vtouchpad X11 xdo ws pthread)
|
||||
endif()
|
||||
|
||||
elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
target_sources(vtouchpad PRIVATE mouse_win.c)
|
||||
target_link_libraries(vtouchpad ws ws2_32)
|
||||
else()
|
||||
message(WARNING "Operating System '${CMAKE_SYSTEM_NAME}' not supported!")
|
||||
set_target_properties(vtouchpad
|
||||
PROPERTIES EXCLUDE_FROM_ALL True)
|
||||
endif ()
|
||||
50
git/wsserver/examples/vtouchpad/README.md
Normal file
50
git/wsserver/examples/vtouchpad/README.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# vtouchpad
|
||||
This example implements a simple 'virtual touchpad' that allows a web client to control a remote computer's mouse via wsServer/websocket.
|
||||
|
||||
## Features
|
||||
<p align="center">
|
||||
<img align="center" src="https://i.imgur.com/sOTqwWI.png" alt="vtouchpad example">
|
||||
<br>
|
||||
vtouchpad example
|
||||
</p>
|
||||
|
||||
The larger area represents the main touchpad, move the cursor over it to move the mouse. Left and right clicks within this area also work as expected.
|
||||
|
||||
The two smaller buttons represent the left and right buttons respectively.
|
||||
|
||||
## Building
|
||||
Since mouse movement is OS-dependent, this example works on a limited number of systems, currently Linux, FreeBSD and Windows.
|
||||
|
||||
**Linux and FreeBSD builds:**
|
||||
|
||||
vtouchpad requires the environment to run under X11, and requires libX11, libXtst or libxdo (comes with xdotool).
|
||||
|
||||
A build for Ubuntu and the like:
|
||||
```bash
|
||||
$ sudo apt install libxdo-dev
|
||||
$ cd wsServer/
|
||||
$ mkdir build && cd build/
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ ./examples/vtouchpad/vtouchpad
|
||||
```
|
||||
FreeBSD (although xdotool is available, the package is currently without maintainer, so its use is discouraged; a normal build already works as expected):
|
||||
```bash
|
||||
$ cd wsServer/
|
||||
$ mkdir build && cd build/
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ ./examples/vtouchpad/vtouchpad
|
||||
```
|
||||
|
||||
**Windows builds:**
|
||||
|
||||
It does not require any special libraries, and should work on any version above Windows 2000.
|
||||
|
||||
```bash
|
||||
$ cd wsServer/
|
||||
$ mkdir build && cd build/
|
||||
$ cmake .. -G "MinGW Makefiles"
|
||||
$ mingw32-make
|
||||
$ ./examples/vtouchpad/vtouchpad.exe
|
||||
```
|
||||
141
git/wsserver/examples/vtouchpad/mouse_win.c
Normal file
141
git/wsserver/examples/vtouchpad/mouse_win.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Davidson Francis <davidsondfgl@gmail.com>
|
||||
*
|
||||
* 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 3 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#error "Expected Windows here!"
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include "vtouchpad.h"
|
||||
|
||||
/**
|
||||
* @dir examples/vtouchpad
|
||||
* @brief Touchpad example directory
|
||||
*
|
||||
* @file mouse_win.c
|
||||
* @brief Mouse windows implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stub structure.
|
||||
*/
|
||||
struct mouse { int stub; };
|
||||
|
||||
/**
|
||||
* @brief Do nothing, stub.
|
||||
*
|
||||
* @return Returns always 0.
|
||||
*/
|
||||
mouse_t *mouse_new(void)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Do nothing, stub.
|
||||
*
|
||||
* @param mouse Mouse structure pointer.
|
||||
*
|
||||
* @return Returns always NULL.
|
||||
*/
|
||||
void *mouse_free(mouse_t *mouse)
|
||||
{
|
||||
((void)mouse);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Moves the mouse pointed by @p mouse to the
|
||||
* offsets @p x_off and @p y_off.
|
||||
*
|
||||
* @param mouse Mouse structure pointer.
|
||||
* @param x_off X-coordinate offset.
|
||||
* @param y_off Y-coordinate offset.
|
||||
*
|
||||
* @return Returns 0 if success, 1 otherwise.
|
||||
*/
|
||||
int mouse_move_relative(mouse_t *mouse, int x_off, int y_off)
|
||||
{
|
||||
((void)mouse);
|
||||
int ret;
|
||||
INPUT input = {0};
|
||||
input.type = INPUT_MOUSE;
|
||||
input.mi.dwFlags = MOUSEEVENTF_MOVE;
|
||||
input.mi.dx = x_off;
|
||||
input.mi.dy = y_off;
|
||||
ret = SendInput(1, &input, sizeof(input));
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Makes a 'button press' event according to the
|
||||
* @p mouse pointer and the @p button (left or right).
|
||||
*
|
||||
* @param mouse Mouse structure pointer.
|
||||
* @param button Which button was pressed (either
|
||||
* MOUSE_BTN_LEFT or MOUSE_BTN_RIGHT).
|
||||
*
|
||||
* @return Returns 0 if success, 1 otherwise.
|
||||
*/
|
||||
int mouse_down(mouse_t *mouse, int button)
|
||||
{
|
||||
((void)mouse);
|
||||
int ret;
|
||||
INPUT input = {0};
|
||||
|
||||
if (button == MOUSE_BTN_LEFT)
|
||||
button = MOUSEEVENTF_LEFTDOWN;
|
||||
else
|
||||
button = MOUSEEVENTF_RIGHTDOWN;
|
||||
|
||||
input.type = INPUT_MOUSE;
|
||||
input.mi.dwFlags = button;
|
||||
ret = SendInput(1, &input, sizeof(input));
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Makes a 'button release' event according to the
|
||||
* @p mouse pointer and the @p button (left or right).
|
||||
*
|
||||
* @param mouse Mouse structure pointer.
|
||||
* @param button Which button was released (either
|
||||
* MOUSE_BTN_LEFT or MOUSE_BTN_RIGHT).
|
||||
*
|
||||
* @return Returns 0 if success, 1 otherwise.
|
||||
*/
|
||||
int mouse_up(mouse_t *mouse, int button)
|
||||
{
|
||||
((void)mouse);
|
||||
int ret;
|
||||
INPUT input = {0};
|
||||
|
||||
if (button == MOUSE_BTN_LEFT)
|
||||
button = MOUSEEVENTF_LEFTUP;
|
||||
else
|
||||
button = MOUSEEVENTF_RIGHTUP;
|
||||
|
||||
input.type = INPUT_MOUSE;
|
||||
input.mi.dwFlags = button;
|
||||
ret = SendInput(1, &input, sizeof(input));
|
||||
return (ret == 0);
|
||||
}
|
||||
179
git/wsserver/examples/vtouchpad/mouse_x11.c
Normal file
179
git/wsserver/examples/vtouchpad/mouse_x11.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Davidson Francis <davidsondfgl@gmail.com>
|
||||
*
|
||||
* 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 3 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(__linux__) && !defined(__FreeBSD__)
|
||||
#error "Expected Linux or FreeBSD here!"
|
||||
#endif
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef HAVE_XDOTOOL
|
||||
#include <xdo.h>
|
||||
#else
|
||||
#include <X11/extensions/XTest.h>
|
||||
#endif
|
||||
|
||||
#include "vtouchpad.h"
|
||||
|
||||
/**
|
||||
* @dir examples/vtouchpad
|
||||
* @brief Touchpad example directory
|
||||
*
|
||||
* @file mouse_x11.c
|
||||
* @brief Mouse X11 implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note:
|
||||
* Although the use of libxdo/xdotool seems unnecessary (since libxdo *also*
|
||||
* uses X11's XTest extension), I believe it can still be interesting: the
|
||||
* xdotool implementation may change in the future, as well as support new
|
||||
* systems, so dealing with libxdo seems to be better than using X11 directly.
|
||||
*
|
||||
* Link:
|
||||
* If libxdo present: -lX11 -lxdo
|
||||
* Else : -lX11 -lXtst
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mouse pointer, hold OS-dependent data structures.
|
||||
*/
|
||||
struct mouse
|
||||
{
|
||||
#ifdef HAVE_XDOTOOL
|
||||
xdo_t *xdo;
|
||||
#else
|
||||
Display *dpy;
|
||||
Window root;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocates a new mouse data structure.
|
||||
*
|
||||
* @return Returns a new mouse_t pointer object.
|
||||
*/
|
||||
mouse_t *mouse_new(void)
|
||||
{
|
||||
struct mouse *mouse;
|
||||
mouse = calloc(1, sizeof(struct mouse));
|
||||
if (!mouse)
|
||||
return (NULL);
|
||||
#ifdef HAVE_XDOTOOL
|
||||
mouse->xdo = xdo_new(NULL);
|
||||
if (!mouse->xdo)
|
||||
return mouse_free(mouse);
|
||||
#else
|
||||
mouse->dpy = XOpenDisplay(0);
|
||||
if (!mouse->dpy)
|
||||
return mouse_free(mouse);
|
||||
mouse->root = XRootWindow(mouse->dpy, DefaultScreen(mouse->dpy));
|
||||
#endif
|
||||
return (mouse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Frees a previously allocated mouse_t pointer.
|
||||
*
|
||||
* @return Always NULL.
|
||||
*/
|
||||
void *mouse_free(mouse_t *mouse)
|
||||
{
|
||||
if (!mouse)
|
||||
goto out;
|
||||
#ifdef HAVE_XDOTOOL
|
||||
if (mouse->xdo)
|
||||
xdo_free(mouse->xdo);
|
||||
#else
|
||||
if (mouse->dpy)
|
||||
XCloseDisplay(mouse->dpy);
|
||||
#endif
|
||||
free(mouse);
|
||||
out:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Moves the mouse pointed by @p mouse to the
|
||||
* offsets @p x_off and @p y_off.
|
||||
*
|
||||
* @param mouse Mouse structure pointer.
|
||||
* @param x_off X-coordinate offset.
|
||||
* @param y_off Y-coordinate offset.
|
||||
*
|
||||
* @return Returns 0 if success, 1 otherwise.
|
||||
*/
|
||||
int mouse_move_relative(mouse_t *mouse, int x_off, int y_off)
|
||||
{
|
||||
#ifdef HAVE_XDOTOOL
|
||||
return xdo_move_mouse_relative(mouse->xdo, x_off, y_off);
|
||||
#else
|
||||
int ret;
|
||||
ret = XTestFakeRelativeMotionEvent(mouse->dpy, x_off, y_off, CurrentTime);
|
||||
XFlush(mouse->dpy);
|
||||
return (ret == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Makes a 'button press' event according to the
|
||||
* @p mouse pointer and the @p button (left or right).
|
||||
*
|
||||
* @param mouse Mouse structure pointer.
|
||||
* @param button Which button was pressed (either
|
||||
* MOUSE_BTN_LEFT or MOUSE_BTN_RIGHT).
|
||||
*
|
||||
* @return Returns 0 if success, 1 otherwise.
|
||||
*/
|
||||
int mouse_down(mouse_t *mouse, int button)
|
||||
{
|
||||
#ifdef HAVE_XDOTOOL
|
||||
return xdo_mouse_down(mouse->xdo, CURRENTWINDOW, button);
|
||||
#else
|
||||
int ret;
|
||||
ret = XTestFakeButtonEvent(mouse->dpy, button, 1, CurrentTime);
|
||||
XFlush(mouse->dpy);
|
||||
return (ret == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Makes a 'button release' event according to the
|
||||
* @p mouse pointer and the @p button (left or right).
|
||||
*
|
||||
* @param mouse Mouse structure pointer.
|
||||
* @param button Which button was released (either
|
||||
* MOUSE_BTN_LEFT or MOUSE_BTN_RIGHT).
|
||||
*
|
||||
* @return Returns 0 if success, 1 otherwise.
|
||||
*/
|
||||
int mouse_up(mouse_t *mouse, int button)
|
||||
{
|
||||
#ifdef HAVE_XDOTOOL
|
||||
return xdo_mouse_up(mouse->xdo, CURRENTWINDOW, button);
|
||||
#else
|
||||
int ret;
|
||||
ret = XTestFakeButtonEvent(mouse->dpy, button, 0, CurrentTime);
|
||||
XFlush(mouse->dpy);
|
||||
return (ret == 0);
|
||||
#endif
|
||||
}
|
||||
210
git/wsserver/examples/vtouchpad/vtouchpad.c
Normal file
210
git/wsserver/examples/vtouchpad/vtouchpad.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Davidson Francis <davidsondfgl@gmail.com>
|
||||
*
|
||||
* 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 3 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ws.h>
|
||||
|
||||
#include "vtouchpad.h"
|
||||
|
||||
/**
|
||||
* @dir examples/vtouchpad
|
||||
* @brief Touchpad example directory
|
||||
*
|
||||
* @file vtouchpad.c
|
||||
* @brief Main file.
|
||||
*/
|
||||
|
||||
/* Mouse global structure. */
|
||||
mouse_t *mouse;
|
||||
|
||||
/**
|
||||
* @brief Given a string @p ev containing a single event,
|
||||
* parses it as expected.
|
||||
*
|
||||
* The event can be (D stands to 'delimiter', currently ';'):
|
||||
* (Mouse Movement): mouse_move D off_X D off_Y, where the offset is an
|
||||
* integer type that represents the amount of pixels
|
||||
* the mouse have to move. Example: mouse_move;10;-20.
|
||||
*
|
||||
* Negative offsets represents movement to the left and
|
||||
* to the top. Positive offsets are the opposite.
|
||||
*
|
||||
* (Mouse Button Press): Represents if a mouse button has been pressed or
|
||||
* released.
|
||||
*
|
||||
* Valid events are:
|
||||
* a) mouse_btn_left_down (left button press)
|
||||
* b) mouse_btn_left_up (left button release)
|
||||
* c) mouse_btn_right_down
|
||||
* d) mouse_btn_right_up
|
||||
*
|
||||
* @param ev String representing the event.
|
||||
* @param error Set to 1 if an error was found, 0 otherwise.
|
||||
*
|
||||
* @returns Returns a mouse_event structure.
|
||||
*/
|
||||
struct mouse_event parse_event(const char *ev, int *error)
|
||||
{
|
||||
struct mouse_event mev = {0};
|
||||
char str[128] = {0};
|
||||
char *saveptr, *s;
|
||||
|
||||
*error = 1;
|
||||
saveptr = NULL;
|
||||
strncpy(str, ev, sizeof(str) - 1);
|
||||
|
||||
s = strtok_r(str, EVENT_DELIMITER, &saveptr);
|
||||
if (!strcmp(s, "mouse_move"))
|
||||
mev.event = MOUSE_MOVE;
|
||||
else if (!strcmp(s, "mouse_btn_left_down"))
|
||||
mev.event = MOUSE_BTN_LEFT_DOWN;
|
||||
else if (!strcmp(s, "mouse_btn_left_up"))
|
||||
mev.event = MOUSE_BTN_LEFT_UP;
|
||||
else if (!strcmp(s, "mouse_btn_right_down"))
|
||||
mev.event = MOUSE_BTN_RIGHT_DOWN;
|
||||
else if (!strcmp(s, "mouse_btn_right_up"))
|
||||
mev.event = MOUSE_BTN_RIGHT_UP;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown event: (%s)\n", s);
|
||||
goto out0;
|
||||
}
|
||||
|
||||
if (mev.event != MOUSE_MOVE)
|
||||
goto out1;
|
||||
|
||||
/* X offset. */
|
||||
s = strtok_r(NULL, EVENT_DELIMITER, &saveptr);
|
||||
if (!s)
|
||||
{
|
||||
fprintf(stderr, "A movement event requires a X/Y offsets, X not found!\n");
|
||||
goto out0;
|
||||
}
|
||||
mev.x_off = atoi(s);
|
||||
|
||||
/* Y offset. */
|
||||
s = strtok_r(NULL, EVENT_DELIMITER, &saveptr);
|
||||
if (!s)
|
||||
{
|
||||
fprintf(stderr, "A movement event requires a X/Y offsets, Y not found!\n");
|
||||
goto out0;
|
||||
}
|
||||
mev.y_off = atoi(s);
|
||||
|
||||
out1:
|
||||
*error = 0;
|
||||
out0:
|
||||
return (mev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief On open event, just signals that a new client has
|
||||
* been connected.
|
||||
*
|
||||
* @param client Client connection.
|
||||
*/
|
||||
void onopen(ws_cli_conn_t *client) {
|
||||
(void)client;
|
||||
printf("Connected!\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief On close event, just signals that a client has
|
||||
* been disconnected.
|
||||
*
|
||||
* @param client Client connection.
|
||||
*/
|
||||
void onclose(ws_cli_conn_t *client) {
|
||||
(void)client;
|
||||
printf("Disconnected!\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For each new event, parses the string as expected all call
|
||||
* the appropriate routines.
|
||||
*
|
||||
* @param client Client connection. (ignored)
|
||||
*
|
||||
* @param msg Received message/event.
|
||||
*
|
||||
* @param size Message size (in bytes). (ignored)
|
||||
*
|
||||
* @param type Message type. (ignored)
|
||||
*/
|
||||
void onmessage(ws_cli_conn_t *client,
|
||||
const unsigned char *msg, uint64_t size, int type)
|
||||
{
|
||||
((void)client);
|
||||
((void)size);
|
||||
((void)type);
|
||||
|
||||
struct mouse_event mev;
|
||||
int err;
|
||||
|
||||
/* Parse the event. */
|
||||
mev = parse_event((const char *)msg, &err);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
/* Call the appropriate routine. */
|
||||
switch (mev.event)
|
||||
{
|
||||
case MOUSE_MOVE:
|
||||
VTOUCH_DEBUG(("move: %d / %d\n", mev.x_off, mev.y_off));
|
||||
mouse_move_relative(mouse, mev.x_off, mev.y_off);
|
||||
break;
|
||||
case MOUSE_BTN_LEFT_DOWN:
|
||||
VTOUCH_DEBUG(("mouse left down\n"));
|
||||
mouse_down(mouse, MOUSE_BTN_LEFT);
|
||||
break;
|
||||
case MOUSE_BTN_LEFT_UP:
|
||||
VTOUCH_DEBUG(("mouse left up\n"));
|
||||
mouse_up(mouse, MOUSE_BTN_LEFT);
|
||||
break;
|
||||
case MOUSE_BTN_RIGHT_DOWN:
|
||||
VTOUCH_DEBUG(("mouse right down\n"));
|
||||
mouse_down(mouse, MOUSE_BTN_RIGHT);
|
||||
break;
|
||||
case MOUSE_BTN_RIGHT_UP:
|
||||
VTOUCH_DEBUG(("mouse right up\n"));
|
||||
mouse_up(mouse, MOUSE_BTN_RIGHT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main routine. */
|
||||
int main(void)
|
||||
{
|
||||
struct ws_events evs;
|
||||
|
||||
/* Register events. */
|
||||
evs.onopen = &onopen;
|
||||
evs.onclose = &onclose;
|
||||
evs.onmessage = &onmessage;
|
||||
|
||||
/* Mouse. */
|
||||
mouse = mouse_new();
|
||||
|
||||
ws_socket(&evs, 8080, 0, 1000);
|
||||
|
||||
mouse_free(mouse);
|
||||
|
||||
return (0);
|
||||
}
|
||||
58
git/wsserver/examples/vtouchpad/vtouchpad.h
Normal file
58
git/wsserver/examples/vtouchpad/vtouchpad.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Davidson Francis <davidsondfgl@gmail.com>
|
||||
*
|
||||
* 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 3 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef VTOUCHPAD_H
|
||||
#define VTOUCHPAD_H
|
||||
|
||||
/* Debug. */
|
||||
#ifndef DISABLE_VERBOSE
|
||||
#define VTOUCH_DEBUG(x) printf x
|
||||
#else
|
||||
#define VTOUCH_DEBUG(x)
|
||||
#endif
|
||||
|
||||
/* Mouse definitions. */
|
||||
#define MOUSE_MOVE 1
|
||||
#define MOUSE_BTN_LEFT_DOWN 2
|
||||
#define MOUSE_BTN_LEFT_UP 4
|
||||
#define MOUSE_BTN_RIGHT_DOWN 8
|
||||
#define MOUSE_BTN_RIGHT_UP 16
|
||||
#define EVENT_DELIMITER "; "
|
||||
|
||||
/* Mouse buttons. */
|
||||
#define MOUSE_BTN_LEFT 1
|
||||
#define MOUSE_BTN_RIGHT 3
|
||||
|
||||
/* Mouse event structure. */
|
||||
struct mouse_event
|
||||
{
|
||||
int event;
|
||||
int x_off;
|
||||
int y_off;
|
||||
};
|
||||
|
||||
/* Opaque type to 'struct mouse'. */
|
||||
typedef struct mouse mouse_t;
|
||||
|
||||
/* External declarations. */
|
||||
extern mouse_t *mouse_new(void);
|
||||
extern void* mouse_free(mouse_t *mouse);
|
||||
extern int mouse_move_relative(mouse_t *mouse, int x_off, int y_off);
|
||||
extern int mouse_down(mouse_t *mouse, int button);
|
||||
extern int mouse_up(mouse_t *mouse, int button);
|
||||
|
||||
#endif /* MAIN_H */
|
||||
227
git/wsserver/examples/vtouchpad/vtouchpad.html
Normal file
227
git/wsserver/examples/vtouchpad/vtouchpad.html
Normal file
@@ -0,0 +1,227 @@
|
||||
<!--
|
||||
Copyright (C) 2022 Davidson Francis <davidsondfgl@gmail.com>
|
||||
|
||||
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 3 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
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
let ws;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let move_counter = 0;
|
||||
let is_connected = false;
|
||||
const THRESHOLD = 1;
|
||||
const DEBUG = true;
|
||||
const DELIMITER = ";";
|
||||
|
||||
function get_touch(e) {
|
||||
const evt = (typeof e.originalEvent === 'undefined') ?
|
||||
e : e.originalEvent;
|
||||
const touch = evt.touches[0] || evt.changedTouches[0];
|
||||
return (touch);
|
||||
}
|
||||
|
||||
function is_touch_device() {
|
||||
return (('ontouchstart' in window) ||
|
||||
(navigator.maxTouchPoints > 0) ||
|
||||
(navigator.msMaxTouchPoints > 0));
|
||||
}
|
||||
|
||||
function fix_num(n) {
|
||||
return (n == NaN ? 0 : Math.round(n));
|
||||
}
|
||||
|
||||
window.addEventListener("load", function () {
|
||||
|
||||
/* Mouse events. */
|
||||
const touch = document.getElementById('touch');
|
||||
touch.addEventListener('mousemove', e => {
|
||||
if (is_touch_device())
|
||||
return;
|
||||
mouse_move(e.offsetX, e.offsetY);
|
||||
});
|
||||
touch.addEventListener('mousedown', e => {
|
||||
mouse_down(e);
|
||||
});
|
||||
touch.addEventListener('mouseup', e => {
|
||||
mouse_up(e);
|
||||
});
|
||||
touch.addEventListener('mouseenter', e => {
|
||||
x = e.offsetX;
|
||||
y = e.offsetY;
|
||||
});
|
||||
|
||||
|
||||
/* Touch events. */
|
||||
touch.addEventListener('touchmove', e => {
|
||||
const touch = get_touch(e);
|
||||
mouse_move(fix_num(touch.pageX), fix_num(touch.pageY));
|
||||
});
|
||||
touch.addEventListener('touchstart', e => {
|
||||
const touch = get_touch(e);
|
||||
x = fix_num(touch.pageX);
|
||||
y = fix_num(touch.pageY);
|
||||
});
|
||||
|
||||
|
||||
/* Button left. */
|
||||
const btn_left = document.getElementById('btn_left');
|
||||
btn_left.addEventListener('mousedown', e => {
|
||||
mouse_down(e, "mouse_btn_left_down");
|
||||
});
|
||||
btn_left.addEventListener('mouseup', e => {
|
||||
mouse_up(e, "mouse_btn_left_up");
|
||||
});
|
||||
|
||||
/* Button right. */
|
||||
const btn_right = document.getElementById('btn_right');
|
||||
btn_right.addEventListener('mousedown', e => {
|
||||
mouse_down(e, "mouse_btn_right_down");
|
||||
});
|
||||
btn_right.addEventListener('mouseup', e => {
|
||||
mouse_up(e, "mouse_btn_right_up");
|
||||
});
|
||||
|
||||
/* Connect button. */
|
||||
document.getElementById("bt_conn").onclick = function(){
|
||||
const addr = document.getElementById("srv_addr").value;
|
||||
toggle_connection(addr);
|
||||
};
|
||||
});
|
||||
|
||||
function toggle_connection(addr) {
|
||||
if (is_connected) {
|
||||
is_connected = false;
|
||||
ws.close();
|
||||
document.getElementById("bt_conn").value = "Disconnect!";
|
||||
return;
|
||||
}
|
||||
ws = new WebSocket(addr);
|
||||
ws.onopen = function(e) {
|
||||
is_connected = true;
|
||||
document.getElementById("bt_conn").value = "Disconnect!";
|
||||
};
|
||||
ws.onclose = function(e) {
|
||||
is_connected = false;
|
||||
document.getElementById("bt_conn").value = "Connect!";
|
||||
};
|
||||
}
|
||||
|
||||
function mouse_move(offX, offY) {
|
||||
if (!is_connected)
|
||||
return;
|
||||
|
||||
/* Do not trigger too much events.. we do not need
|
||||
* to do 'micro movements' */
|
||||
move_counter++;
|
||||
if (move_counter != THRESHOLD)
|
||||
return;
|
||||
move_counter = 0;
|
||||
|
||||
const movX = offX - x;
|
||||
const movY = offY - y;
|
||||
x = offX;
|
||||
y = offY;
|
||||
|
||||
ws.send("mouse_move" + DELIMITER + movX + DELIMITER + movY);
|
||||
if (DEBUG)
|
||||
console.log(movX + " / " + movY);
|
||||
}
|
||||
|
||||
function mouse_down(e, btn) {
|
||||
let event;
|
||||
if (!is_connected)
|
||||
return;
|
||||
|
||||
if (!btn) {
|
||||
if (e.button == 0)
|
||||
event = "mouse_btn_left_down";
|
||||
else if (e.button == 2)
|
||||
event = "mouse_btn_right_down";
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
event = btn;
|
||||
|
||||
if (DEBUG)
|
||||
console.log(event);
|
||||
ws.send(event);
|
||||
}
|
||||
function mouse_up(e, btn) {
|
||||
let event;
|
||||
if (!is_connected)
|
||||
return;
|
||||
|
||||
if (!btn) {
|
||||
if (e.button == 0)
|
||||
event = "mouse_btn_left_up";
|
||||
else if (e.button == 2)
|
||||
event = "mouse_btn_right_up";
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
event = btn;
|
||||
|
||||
if (DEBUG)
|
||||
console.log(event);
|
||||
ws.send(event);
|
||||
}
|
||||
|
||||
</script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
overscroll-behavior-y: contain;
|
||||
}
|
||||
#header { padding-top: 10px; padding-left: 5px; }
|
||||
#touch {
|
||||
background-image: linear-gradient(white, gray);
|
||||
border: solid;
|
||||
border-radius: 5px;
|
||||
width: 80%;
|
||||
height: 78%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
#wrapper { margin: 0 auto; width: 99%; text-align: center; }
|
||||
#btn_left, #btn_right {
|
||||
background-image: linear-gradient(white, gray);
|
||||
border: solid;
|
||||
border-radius: 5px;
|
||||
width: 40%;
|
||||
height: 11%;
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
#btn_right {
|
||||
margin-right: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body oncontextmenu="return false;">
|
||||
<div id="header">
|
||||
Server: <input type="text" id="srv_addr" value="ws://192.168.X.Y:8080">
|
||||
<input type="button" id="bt_conn" name="bt_conn" value="Connect!"><br /><br />
|
||||
</div>
|
||||
|
||||
<div id="touch"></div>
|
||||
<div id="wrapper">
|
||||
<div id="btn_left"></div><div id="btn_right"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user