diff options
author | Hyojung Jo <hj903.jo@samsung.com> | 2015-04-23 15:43:11 +0900 |
---|---|---|
committer | Hyojung Jo <hj903.jo@samsung.com> | 2015-04-23 15:55:41 +0900 |
commit | 3512c416c35405da51837d65f4e8eddec0a3f071 (patch) | |
tree | 37a8b8e370917354f4c5bd05f38777aca43fc779 | |
parent | e54b0ba132352b04d513fcab402e03b02d6439ad (diff) | |
download | autotest-3512c416c35405da51837d65f4e8eddec0a3f071.tar.gz autotest-3512c416c35405da51837d65f4e8eddec0a3f071.tar.bz2 autotest-3512c416c35405da51837d65f4e8eddec0a3f071.zip |
Change-Id: I839307dfded8e5462e0fef6c76103b2c5e12bd59
Signed-off-by: Hyojung Jo <hj903.jo@samsung.com>
-rwxr-xr-x | eventgenerator/CMakeLists.txt | 35 | ||||
-rwxr-xr-x | eventgenerator/build.sh | 9 | ||||
-rwxr-xr-x | eventgenerator/packaging/eventgenerator.spec | 35 | ||||
-rwxr-xr-x | eventgenerator/src/main.cpp | 568 | ||||
-rwxr-xr-x | eventrecorder/CMakeLists.txt | 34 | ||||
-rwxr-xr-x | eventrecorder/build.sh | 9 | ||||
-rwxr-xr-x | eventrecorder/packaging/eventgenerator.spec | 35 | ||||
-rwxr-xr-x | eventrecorder/src/main.cpp | 279 |
8 files changed, 1004 insertions, 0 deletions
diff --git a/eventgenerator/CMakeLists.txt b/eventgenerator/CMakeLists.txt new file mode 100755 index 0000000..501580a --- /dev/null +++ b/eventgenerator/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 2.8) +PROJECT(eventgenerator) + +SET(EVENTGENERATOR_SRCS + ${PROJECT_SOURCE_DIR}/src/main.cpp +) + +SET(EVENTGENERATOR_HEADERS + ${PROJECT_SOURCE_DIR}/include +) + +INCLUDE_DIRECTORIES(${EVENTGENERATOR_HEADERS}) + +INCLUDE(FindPkgConfig) +pkg_check_modules(EVENTGENERATOR_PKGS REQUIRED + glib-2.0 + utilX + x11 + gio-2.0 +) + +FOREACH (flag ${EVENTGENERATOR_PKGS_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_CXX_FLAGS "${EXTRA_CFLAGS} -g") + + +ADD_EXECUTABLE(eventgenerator ${EVENTGENERATOR_SRCS}) +TARGET_LINK_LIBRARIES(eventgenerator ${EVENTGENERATOR_PKGS_LDFLAGS} "-ldl" "-lpthread" ${EVENTGENERATOR_PKGS_LIBRARIES}) +INSTALL(TARGETS eventgenerator DESTINATION /opt/usr/apps/${PROJECT_NAME}/bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + + + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LOCK_PKGS_LDFLAGS}) diff --git a/eventgenerator/build.sh b/eventgenerator/build.sh new file mode 100755 index 0000000..91b133a --- /dev/null +++ b/eventgenerator/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cp -rf ../eventgenerator ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/home/abuild/rpmbuild/BUILD/ + +sudo chroot ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/ /bin/bash -c "cd /home/abuild/rpmbuild/BUILD/eventgenerator/ && cmake . && make" + +sdb root on +sdb push ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/home/abuild/rpmbuild/BUILD/eventgenerator/eventgenerator /home/user/ + diff --git a/eventgenerator/packaging/eventgenerator.spec b/eventgenerator/packaging/eventgenerator.spec new file mode 100755 index 0000000..f2fa5f3 --- /dev/null +++ b/eventgenerator/packaging/eventgenerator.spec @@ -0,0 +1,35 @@ +Name: eventgenerator +Summary: eventgenerator +Version: 0.1 +Release: 1 +Group: Applications/Other +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: x11 +BuildRequires: utilX + +%description +Tizen 3.0 eventgenerator application + +%prep +%setup -q + +%build +export SRC_PWD="$PWD" +%define _build_dir .build-%{name} + +mkdir -p %{_build_dir} +cd %{_build_dir} + +cmake $SRC_PWD -DCMAKE_INSTALL_PREFIX=%{_prefix} +make %{?jobs:-j%jobs} + +%install +cd %{_build_dir} +rm -rf %{buildroot} +%make_install + +%files -n lockscreen +%defattr(-,root,root,-) +/usr/apps/eventgenerator/bin/* diff --git a/eventgenerator/src/main.cpp b/eventgenerator/src/main.cpp new file mode 100755 index 0000000..8246386 --- /dev/null +++ b/eventgenerator/src/main.cpp @@ -0,0 +1,568 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <string> +#include <iostream> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <iostream> +#include <list> +#include <sys/time.h> +#include <unistd.h> +#include <utilX.h> +#include <glib.h> +#include <gerror.h> +#include <gio/gio.h> + +#define DEVICED_PATH_USBHOST "/Org/Tizen/System/DeviceD/Usbhost" +#define DEVICED_INTERFACE_USBHOST "org.tizen.system.deviced.Usbhost" + +#define SIGNAL_USBHOST_CHANGED "ChangedDevice" + +#define MAX_STR_SIZE 256 + +#define COMMAND_GET_IME_WINDOW_ID "xinfo -topwins 2>&1 | grep 'Tizen Keyboard' | awk '{ if ($9 > 0) print $3,$4,$5,$8,$9; else print 0,0,0,0,0}'" + +Window imeWin; +int ime_x, ime_y, ime_w, ime_h; +bool imeInput; +bool end; +GDBusConnection *conn; +GDBusProxy *proxy; +GError *error; + +using namespace std; + +class CKeyEventGenerator { +private: + unsigned long m_RootId; + Display *m_Display; + +public: + CKeyEventGenerator(); + virtual ~CKeyEventGenerator() {} + +public: + void GenerateKeyPressEvent(char *keyname); + void GenerateKeyReleaseEvent(char *keyname); + void GenerateMouseMoveEvent(int x, int y); + void GenerateMousePressEvent(int x, int y, int state, int button); + void GenerateMouseReleaseEvent(int x, int y, int state, int button); +}; + +static void _get_ime_window(void) +{ + FILE *fp; + char str[256]; + + fp = popen(COMMAND_GET_IME_WINDOW_ID, "r"); + if (!fp) { + printf("popen error\n"); + return; + } + + fscanf(fp, "%s %d %d %d %d\n", str, &ime_w, &ime_h, &ime_x, &ime_y); + imeWin = strtol(str, NULL, 16); + + pclose(fp); +} + +static bool _check_ime_input(int x, int y) +{ + if (imeWin && (x > ime_x && x < ime_x + ime_w) + && (y > ime_y && y < ime_y + ime_h)) + return true; + else + return false; +} + +CKeyEventGenerator::CKeyEventGenerator() { + m_Display = XOpenDisplay(0); + m_RootId = XDefaultRootWindow(m_Display); + printf("root: 0x%x\n", m_RootId); +} + +void CKeyEventGenerator::GenerateKeyPressEvent(char *keyname) +{ + XEvent xev; + Window root = (Window)m_RootId; + Display *dpy = m_Display; + Window win; + int revert; + + XGetInputFocus(dpy, &win, &revert); + + xev.xkey.display = dpy; + xev.xkey.window = win; + xev.xkey.root = root; + xev.xkey.subwindow = None; + xev.xkey.time = CurrentTime; + xev.xkey.x = 1; + xev.xkey.y = 1; + xev.xkey.x_root = 540; + xev.xkey.y_root = 960; + xev.xkey.keycode = XKeysymToKeycode(m_Display, XStringToKeysym(keyname)); + xev.xkey.same_screen = 1; + xev.xkey.state = 0; + xev.xkey.type = KeyPress; + + XSendEvent(dpy, win, True, KeyPressMask | KeyReleaseMask, &xev); + XFlush(dpy); +} + + +void CKeyEventGenerator::GenerateKeyReleaseEvent(char *keyname) +{ + XEvent xev; + Window root = (Window)m_RootId; + Display *dpy = m_Display; + Window win; + int revert; + + XGetInputFocus(dpy, &win, &revert); + + xev.xkey.display = dpy; + xev.xkey.window = win; + xev.xkey.root = root; + xev.xkey.subwindow = None; + xev.xkey.time = CurrentTime; + xev.xkey.x = 1; + xev.xkey.y = 1; + xev.xkey.x_root = 540; + xev.xkey.y_root = 960; + xev.xkey.keycode = XKeysymToKeycode(m_Display, XStringToKeysym(keyname)); + xev.xkey.same_screen = 1; + xev.xkey.state = 0; + xev.xkey.type = KeyRelease; + + XSendEvent(dpy, win, True, KeyPressMask | KeyReleaseMask, &xev); + XFlush(dpy); +} + + +void CKeyEventGenerator::GenerateMouseMoveEvent(int x, int y) +{ + XEvent xev; + Window root = (Window)m_RootId; + Display *dpy = m_Display; + Window win; + int revert; + + XGetInputFocus(dpy, &win, &revert); + + xev.xmotion.window = win; + xev.xmotion.root = root; + xev.xmotion.subwindow = None; + xev.xmotion.time = CurrentTime; + xev.xmotion.x = x; + xev.xmotion.y = y; + xev.xmotion.x_root = x; + xev.xmotion.y_root = y; + xev.xmotion.state = 0; + xev.xmotion.is_hint = 0; + xev.xmotion.same_screen = 1; + xev.xmotion.type = MotionNotify; + + XSendEvent(dpy, win, True, PointerMotionMask, &xev); + XFlush(dpy); +} + + +void CKeyEventGenerator::GenerateMousePressEvent(int x, int y, int state, int button) +{ + XEvent xev; + Window root = (Window)m_RootId; + Display *dpy = m_Display; + Window win; + int revert; + + _get_ime_window(); + + if (_check_ime_input(x, y)) { + imeInput = true; + win = imeWin; + } else + XGetInputFocus(dpy, &win, &revert); + + xev.xbutton.window = win; + xev.xbutton.root = root; + xev.xbutton.subwindow = None; + xev.xbutton.time = CurrentTime; + xev.xbutton.x = x; + xev.xbutton.y = y; + xev.xbutton.x_root = x; + xev.xbutton.y_root = y; + xev.xbutton.state = state; + xev.xbutton.button = button; + xev.xbutton.same_screen = 1; + xev.xbutton.type = ButtonPress; + + XSendEvent(dpy, win, True, ButtonPressMask, &xev); + XFlush(dpy); +} + + +void CKeyEventGenerator::GenerateMouseReleaseEvent(int x, int y, int state, int button) +{ + XEvent xev; + Window root = (Window)m_RootId; + Display *dpy = m_Display; + Window win; + int revert; + + if (imeInput) + win = imeWin; + else + XGetInputFocus(dpy, &win, &revert); + + xev.xbutton.window = win; + xev.xbutton.root = root; + xev.xbutton.subwindow = None; + xev.xbutton.time = CurrentTime; + xev.xbutton.x = x; + xev.xbutton.y = y; + xev.xbutton.x_root = x; + xev.xbutton.y_root = y; + xev.xbutton.state = state; + xev.xbutton.button = button; + xev.xbutton.same_screen = 1; + xev.xbutton.type = ButtonRelease; + + XSendEvent(dpy, win, True, ButtonReleaseMask, &xev); + XFlush(dpy); +} + + +static void *_check_event(void *data) +{ + Display *dpy; + Window win; + int revert; + bool event; + + dpy = XOpenDisplay(0); + XGetInputFocus(dpy, &win, &revert); + XSelectInput(dpy, win, KeyPressMask | KeyReleaseMask); + + XAllowEvents(dpy, AsyncBoth, CurrentTime); + XGrabPointer(dpy, win, 1, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, + None, None, + CurrentTime); + + event = false; + while (1) { + if (end) + pthread_exit(NULL); + + if (!XPending(dpy)) + continue; + + XEvent ev; + XNextEvent(dpy, &ev); + + switch (ev.type) { + case KeyPress: + if (imeInput) + break; + + if (ev.xkey.time > 1) + event = true; + break; + case KeyRelease: + if (imeInput) { + imeInput = false; + break; + } + + if (ev.xkey.time > 1) + event = true; + break; + case MotionNotify: + if (ev.xmotion.time) + event = true; + break; + case ButtonPress: + case ButtonRelease: + if (ev.xbutton.time) + event = true; + break; + default: + break; + } + + if (event) + break; + } + + + end = true; + + pthread_exit(NULL); +} + +static bool _usb_initialize(void) +{ + conn = NULL; + proxy = NULL; + error = NULL; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!conn) { + printf("get connection failed\n"); + g_error_free(error); + return false; + } + + return true; +} + +static void _usb_finalize(void) +{ + g_object_unref(conn); +} + +static void _usb_connect(const char *name, const char *serial) +{ + GVariant *param; + int r; + + param = g_variant_new("(isiiiiisss)", 1, "devpath", 0x08, + 0, 0, 0, 0, "manufacturer", name, serial); + + r = g_dbus_connection_emit_signal(conn, NULL, DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, + SIGNAL_USBHOST_CHANGED, + param, &error); + + if (!r) { + printf("connect signal (%s, %s) emit failed\n", name, serial); + g_error_free(error); + } +} + +static void _usb_disconnect(const char *name, const char *serial) +{ + GVariant *param; + int r; + + param = g_variant_new("(isiiiiisss)", 0, "devpath", 0x08, + 0, 0, 0, 0, "manufacturer", name, serial); + + r = g_dbus_connection_emit_signal(conn, NULL, DEVICED_PATH_USBHOST, + DEVICED_INTERFACE_USBHOST, + SIGNAL_USBHOST_CHANGED, + param, &error); + + if (!r) { + printf("disconnect signal (%s, %s) emit failed\n", name, serial); + g_error_free(error); + } +} + +static bool _run_command(const char *command) +{ + int ret; + + ret = system(command); + + if (ret) { + printf("Exit status: %d\n", ret); + return false; + } + + return true; +} + +int main(int argc, char *argv[]) +{ + CKeyEventGenerator *keygen = new CKeyEventGenerator; + char file[MAX_STR_SIZE]; + char dev[MAX_STR_SIZE], str[MAX_STR_SIZE]; + char op[MAX_STR_SIZE], sym[MAX_STR_SIZE]; + char name[MAX_STR_SIZE], serial[MAX_STR_SIZE]; + unsigned int time; + int r; + pthread_t thread_id; + FILE *fp_list, *fp; + + if (argc == 1) { + printf("Please enter input file name.\n"); + printf("Usage: eventgenerator [file name]\n"); + return -1; + } + + fp_list = fopen(argv[1], "r"); + if (!fp_list) { + printf("file %s open error\n", argv[1]); + return -1; + } + + if (!_usb_initialize()) { + printf("Usb init failed\n"); + return -1; + } + + thread_id = 0; + + r = pthread_create(&thread_id, NULL, _check_event, (void *)NULL); + if (r != 0) { + printf("pthread create failed\n"); + return -1; + } + + end = false; + + unsigned int interval; + int x = 0, y = 0; + int state = 0, button = 0; + int move_offset = 10000; + int button_offset = 100000; + int usb_offset = 100000; + int command_interval = 500000; + + printf("========================\n"); + while (1) { + if (fscanf(fp_list, "%s\n", file) == EOF) + break; + + printf("****************************************\n"); + printf("Testcase file: %s\n", file); + printf("****************************************\n"); + + fp = fopen(file, "r"); + if (!fp) { + printf("file %s open error\n", file); + fclose(fp_list); + return -1; + } + + while (1) { + if (end) { + printf("User input is detected.\n" + "Eventgenerator is terminated.\n"); + break; + } + + if (fscanf(fp, "%s", dev) == EOF) + break; + + if (dev[0] == '#') { + fgets(str, MAX_STR_SIZE, fp); + printf("%s%s", dev, str); + printf("========================\n"); + continue; + } + + if (!strcmp(dev, "Command")) { + fscanf(fp, "\n"); + fgets(str, MAX_STR_SIZE, fp); + + if (!_run_command(str)) { + printf("Execute command failed.\n"); + break; + } + + printf("%s\n%s", dev, str); + + usleep(command_interval); + + printf("Time for sleep: %u ms\n", command_interval / 1000); + printf("========================\n"); + } else if (!strcmp(dev, "Key")) { + fscanf(fp, "%s\n", op); + printf("%s %s\n", dev, op); + + fscanf(fp, "%s %u\n", sym, &interval); + + printf("%s\n", sym); + printf("Time for sleep: %u ms\n", interval); + + usleep(interval * 1000 + button_offset); + + if (!strcmp(op, "Pressed")) + keygen->GenerateKeyPressEvent(sym); + else if (!strcmp(op, "Released")) + keygen->GenerateKeyReleaseEvent(sym); + + printf("Send Event\n"); + printf("========================\n"); + } else if (!strcmp(dev, "Mouse")) { + fscanf(fp, "%s\n", op); + printf("%s %s\n", dev, op); + + if (!strcmp(op, "Move")) { + fscanf(fp, "%d %d %u\n", &x, &y, &interval); + + printf("x: %d, y: %d\n", x, y); + printf("Time for sleep: %u ms\n", interval); + + usleep(interval * 1000 + move_offset); + keygen->GenerateMouseMoveEvent(x, y); + } else if (!strcmp(op, "Pressed")) { + fscanf(fp, "%d %d %d %d %u\n", &x, &y, &state, &button, &interval); + + printf("x: %d, y: %d\n", x, y); + printf("Time for sleep: %u ms\n", interval); + + usleep(interval * 1000 + button_offset); + keygen->GenerateMousePressEvent(x, y, state, button); + } else if (!strcmp(op, "Released")) { + fscanf(fp, "%d %d %d %d %u\n", &x, &y, &state, &button, &interval); + + printf("x: %d, y: %d\n", x, y); + printf("Time for sleep: %u ms\n", interval); + + usleep(interval * 1000 + button_offset); + keygen->GenerateMouseReleaseEvent(x, y, state, button); + } + + printf("Send Event\n"); + printf("========================\n"); + } else if (!strcmp(dev, "Usb")) { + fscanf(fp, "%s\n", op); + printf("%s %s\n", dev, op); + + fscanf(fp, "%s %s %u\n", name, serial, &interval); + printf("name: %s, serial: %s\n", name, serial); + printf("Time for sleep: %u ms\n", interval); + + usleep(interval * 1000 + usb_offset); + + if (!strcmp(op, "Connect")) { + _usb_connect(name, serial); + } else if (!strcmp(op, "Disconnect")) { + _usb_disconnect(name, serial); + } + + printf("Send Signal\n"); + printf("========================\n"); + } + } + + if (end) + break; + + printf("****************************************\n"); + printf("Test %s complete.\n", file); + printf("****************************************\n"); + + fclose(fp); + } + + if (!end) { + end = true; + + pthread_join(thread_id, (void **)&r); + } + + _usb_finalize(); + + fclose(fp_list); + + delete keygen; + + return 0; +} diff --git a/eventrecorder/CMakeLists.txt b/eventrecorder/CMakeLists.txt new file mode 100755 index 0000000..9f51b28 --- /dev/null +++ b/eventrecorder/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 2.8) +PROJECT(eventrecorder) + +SET(EVENTGENERATOR_SRCS + ${PROJECT_SOURCE_DIR}/src/main.cpp +) + +SET(EVENTGENERATOR_HEADERS + ${PROJECT_SOURCE_DIR}/include +) + +INCLUDE_DIRECTORIES(${EVENTGENERATOR_HEADERS}) + +INCLUDE(FindPkgConfig) +pkg_check_modules(EVENTGENERATOR_PKGS REQUIRED + glib-2.0 + utilX + x11 +) + +FOREACH (flag ${EVENTGENERATOR_PKGS_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_CXX_FLAGS "${EXTRA_CFLAGS}") + + +ADD_EXECUTABLE(eventrecorder ${EVENTGENERATOR_SRCS}) +TARGET_LINK_LIBRARIES(eventrecorder ${EVENTGENERATOR_PKGS_LDFLAGS} "-ldl" ${EVENTGENERATOR_PKGS_LIBRARIES}) +INSTALL(TARGETS eventrecorder DESTINATION /opt/usr/apps/${PROJECT_NAME}/bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + + + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LOCK_PKGS_LDFLAGS}) diff --git a/eventrecorder/build.sh b/eventrecorder/build.sh new file mode 100755 index 0000000..89104a3 --- /dev/null +++ b/eventrecorder/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cp -rf ../eventrecorder ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/home/abuild/rpmbuild/BUILD/ + +sudo chroot ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/ /bin/bash -c "cd /home/abuild/rpmbuild/BUILD/eventrecorder/ && cmake . && make" + +sdb root on +sdb push ~/GBS-ROOT/local/BUILD-ROOTS/scratch.armv7l.0/home/abuild/rpmbuild/BUILD/eventrecorder/eventrecorder /home/user/ + diff --git a/eventrecorder/packaging/eventgenerator.spec b/eventrecorder/packaging/eventgenerator.spec new file mode 100755 index 0000000..a14a560 --- /dev/null +++ b/eventrecorder/packaging/eventgenerator.spec @@ -0,0 +1,35 @@ +Name: eventrecorder +Summary: eventrecorder +Version: 0.1 +Release: 1 +Group: Applications/Other +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: x11 +BuildRequires: utilX + +%description +Tizen 3.0 eventrecorder application + +%prep +%setup -q + +%build +export SRC_PWD="$PWD" +%define _build_dir .build-%{name} + +mkdir -p %{_build_dir} +cd %{_build_dir} + +cmake $SRC_PWD -DCMAKE_INSTALL_PREFIX=%{_prefix} +make %{?jobs:-j%jobs} + +%install +cd %{_build_dir} +rm -rf %{buildroot} +%make_install + +%files -n lockscreen +%defattr(-,root,root,-) +/usr/apps/eventrecorder/bin/* diff --git a/eventrecorder/src/main.cpp b/eventrecorder/src/main.cpp new file mode 100755 index 0000000..2169a0e --- /dev/null +++ b/eventrecorder/src/main.cpp @@ -0,0 +1,279 @@ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <signal.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +#define INTERVAL_DEFAULT 1000 + +#define COMMAND_GET_IME_WINDOW_ID "xinfo -topwins 2>&1 | grep 'Tizen Keyboard' | awk '{ if ($9 > 0) print $3,$4,$5,$8,$9; else print 0,0,0,0,0}'" + +Window imeWin; +int ime_x, ime_y, ime_w, ime_h; +bool end; + +static XErrorHandler old_handler = (XErrorHandler) 0; + +static int _xerror_handler(Display *display, XErrorEvent *theEvent) +{ + return 0; +} + +static void _sigint_handler(int signo) +{ + printf("Ctrl + C Pressed\n"); + end = true; +} + +static void _get_ime_window(void) +{ + FILE *fp; + char str[256]; + + fp = popen(COMMAND_GET_IME_WINDOW_ID, "r"); + if (!fp) { + printf("popen error\n"); + return; + } + + fscanf(fp, "%s %d %d %d %d\n", str, &ime_w, &ime_h, &ime_x, &ime_y); + imeWin = strtol(str, NULL, 16); + + pclose(fp); +} + +static bool _check_ime_input(int x, int y) +{ + if (imeWin && (x > ime_x && x < ime_x + ime_w) + && (y > ime_y && y < ime_y + ime_h)) + return true; + else + return false; +} + +int main(int argc, char *argv[]) +{ + Display* d; + Window root; + Window curFocus; + Window initFocusWin; + KeySym ks; + XComposeStatus comp; + char buf[17]; + const char *sym; + int len; + int revert; + static int motionRecord; + bool pressed; + bool imeInput; + unsigned int prevTime, curTime; + unsigned int interval; + FILE *fp; + + if (argc == 1) { + printf("Please enter output file name.\n"); + printf("Usage: eventrecorder [file name]\n"); + return -1; + } + + fp = fopen(argv[1], "w"); + if (!fp) { + printf("file %s open error\n", argv[1]); + return -1; + } + + signal(SIGINT, _sigint_handler); + + old_handler = XSetErrorHandler(_xerror_handler); + + d = XOpenDisplay(NULL); + root = XDefaultRootWindow(d); + + XGetInputFocus(d, &curFocus, &revert); + initFocusWin = curFocus; + printf("initFocusWin = 0x%x\n",initFocusWin); + printf("=====================================\n"); + XSelectInput(d, curFocus, KeyPressMask | KeyReleaseMask | SubstructureNotifyMask); + + XAllowEvents(d, AsyncBoth, CurrentTime); + XGrabPointer(d, curFocus, 1, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, + None, None, + CurrentTime); + + end = false; + motionRecord = 0; + prevTime = 0; + curTime = 0; + interval = 0; + imeInput = 0; + + while (1) { + XGetInputFocus(d, &curFocus, &revert); + XSelectInput(d, curFocus, KeyPressMask | KeyReleaseMask | SubstructureNotifyMask); + + XAllowEvents(d, AsyncBoth, CurrentTime); + XGrabPointer(d, curFocus, 1, + PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, + None, None, + CurrentTime); + + if (end) { + printf("EventRecorder is terminated.\n"); + break; + } + + if (!XPending(d)) + continue; + + XEvent ev; + XNextEvent(d, &ev); + + switch (ev.type) { + case DestroyNotify: + printf("destroyedWin = 0x%x\n", ev.xdestroywindow.event); + if(initFocusWin == ev.xdestroywindow.event) + end = true; + break; + // Key Event + case KeyPress: + if (pressed) + continue; + + if (ev.xkey.time == 1) + continue; + + len = XLookupString(&ev.xkey, buf, 16, &ks, &comp); + sym = XKeysymToString(ks); + + printf("Key Pressed\n"); + printf("%s\n", sym); + + fprintf(fp, "Key Pressed\n"); + fprintf(fp, "%s ", sym); + + curTime = ev.xkey.time; + + pressed = true; + break; + case KeyRelease: + if (!pressed) + continue; + + if (ev.xkey.time == 1) + continue; + + len = XLookupString(&ev.xkey, buf, 16, &ks, &comp); + sym = XKeysymToString(ks); + + printf("Key Released\n"); + printf("%s\n", sym); + + fprintf(fp, "Key Released\n"); + fprintf(fp, "%s ", sym); + + curTime = ev.xkey.time; + + pressed = false; + break; + // Mouse Event + case MotionNotify: + ++motionRecord %= 2; + if (!motionRecord) { // Record once in two + XSendEvent(d, curFocus, True, + PointerMotionMask, (XEvent *)&ev); + continue; + } + + printf("Mouse Move\n"); + printf("x: %d, y: %d\n", + ev.xmotion.x_root, ev.xmotion.y_root); + + fprintf(fp, "Mouse Move\n"); + fprintf(fp, "%d %d ", + ev.xmotion.x_root, ev.xmotion.y_root); + + curTime = ev.xmotion.time; + + XSendEvent(d, curFocus, True, + PointerMotionMask, (XEvent *)&ev); + + break; + case ButtonPress: + printf("Mouse Pressed\n"); + printf("x: %d, y: %d\n", + ev.xbutton.x_root, ev.xbutton.y_root); + + fprintf(fp, "Mouse Pressed\n"); + fprintf(fp, "%d %d %d %d ", + ev.xbutton.x_root, ev.xbutton.y_root, + ev.xbutton.state, ev.xbutton.button); + + curTime = ev.xbutton.time; + imeInput = false; + + _get_ime_window(); + + if (_check_ime_input(ev.xbutton.x_root, + ev.xbutton.y_root)) { + imeInput = true; + + ev.xbutton.window = imeWin; + XSendEvent(d, imeWin, True, + ButtonPressMask, (XEvent *)&ev); + } else + XSendEvent(d, curFocus, True, + ButtonPressMask, (XEvent *)&ev); + break; + case ButtonRelease: + printf("Mouse Released\n"); + printf("x: %d, y: %d\n", + ev.xbutton.x_root, ev.xbutton.y_root); + + fprintf(fp, "Mouse Released\n"); + fprintf(fp, "%d %d %d %d ", + ev.xbutton.x_root, ev.xbutton.y_root, + ev.xbutton.state, ev.xbutton.button); + + curTime = ev.xbutton.time; + + if (imeInput) { + ev.xbutton.window = imeWin; + XSendEvent(d, imeWin, True, + ButtonReleaseMask, (XEvent *)&ev); + } else + XSendEvent(d, curFocus, True, + ButtonReleaseMask, (XEvent *)&ev); + break; + default: + break; + } + + if (!curTime) + continue; + + if (prevTime) + interval = curTime - prevTime; + else + interval = INTERVAL_DEFAULT; + + printf("Time interval: %u\n", interval); + printf("=====================================\n"); + fprintf(fp, "%u\n", interval); + + prevTime = curTime; + curTime = 0; + } + + if (pressed) { + fprintf(fp, "Key Released\n"); + fprintf(fp, "Escape 120\n"); + } + + fclose(fp); + + return 0; +} |