|
2 | 2 | * linux_mouse.c -- Mouse support for linux.
|
3 | 3 | *
|
4 | 4 | * Copyright (c) 2018, Liu chao <lc-soft@live.cn> All rights reserved.
|
5 |
| - * |
| 5 | + * |
6 | 6 | * Redistribution and use in source and binary forms, with or without
|
7 | 7 | * modification, are permitted provided that the following conditions are met:
|
8 | 8 | *
|
|
28 | 28 | * POSSIBILITY OF SUCH DAMAGE.
|
29 | 29 | */
|
30 | 30 |
|
31 |
| - |
32 | 31 | #include <LCUI_Build.h>
|
33 | 32 | #ifdef LCUI_BUILD_IN_LINUX
|
| 33 | +#include <stdio.h> |
| 34 | +#include <stdlib.h> |
| 35 | +#include <fcntl.h> |
| 36 | +#include <errno.h> |
| 37 | +#include <unistd.h> |
| 38 | +#include <sys/time.h> |
| 39 | +#include <sys/types.h> |
| 40 | +#include <sys/stat.h> |
| 41 | +#include <linux/input.h> |
| 42 | + |
34 | 43 | #include <LCUI/LCUI.h>
|
| 44 | +#include <LCUI/thread.h> |
35 | 45 | #include <LCUI/platform.h>
|
| 46 | +#include <LCUI/display.h> |
36 | 47 | #include LCUI_EVENTS_H
|
37 | 48 | #include LCUI_MOUSE_H
|
38 | 49 |
|
39 |
| -void LCUI_InitLinuxMouse( void ) |
| 50 | +enum MouseButtonId { MOUSE_BUTTON_LEFT = 1, MOUSE_BUTTON_RIGHT = 1 << 1 }; |
| 51 | + |
| 52 | +static struct LCUI_LinuxMouseDriver { |
| 53 | + int x; |
| 54 | + int y; |
| 55 | + int button_state[2]; |
| 56 | + |
| 57 | + int dev_fd; |
| 58 | + const char *dev_path; |
| 59 | + |
| 60 | + LCUI_Thread tid; |
| 61 | + LCUI_BOOL active; |
| 62 | +} mouse; |
| 63 | + |
| 64 | +static void DispathMouseButtonEvent(int button, int state) |
| 65 | +{ |
| 66 | + LCUI_SysEventRec ev = { 0 }; |
| 67 | + if (mouse.button_state[button - 1]) { |
| 68 | + if (!(state & button)) { |
| 69 | + ev.type = LCUI_MOUSEUP; |
| 70 | + ev.button.x = mouse.x; |
| 71 | + ev.button.y = mouse.y; |
| 72 | + ev.button.button = button; |
| 73 | + mouse.button_state[button - 1] = 0; |
| 74 | + LCUI_TriggerEvent(&ev, NULL); |
| 75 | + LCUI_DestroyEvent(&ev); |
| 76 | + } |
| 77 | + } else if (state & button) { |
| 78 | + ev.type = LCUI_MOUSEDOWN; |
| 79 | + ev.button.x = mouse.x; |
| 80 | + ev.button.y = mouse.y; |
| 81 | + ev.button.button = button; |
| 82 | + mouse.button_state[button - 1] = 1; |
| 83 | + LCUI_TriggerEvent(&ev, NULL); |
| 84 | + LCUI_DestroyEvent(&ev); |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +static void DispatchMouseEvent(void *arg1, void *arg2) |
| 89 | +{ |
| 90 | + char *buf = arg1; |
| 91 | + int state = buf[0] & 0x07; |
| 92 | + LCUI_SysEventRec ev = { 0 }; |
| 93 | + |
| 94 | + mouse.x += buf[1]; |
| 95 | + mouse.y -= buf[2]; |
| 96 | + mouse.x = max(0, mouse.x); |
| 97 | + mouse.y = max(0, mouse.y); |
| 98 | + mouse.x = min(LCUIDisplay_GetWidth(), mouse.x); |
| 99 | + mouse.y = min(LCUIDisplay_GetHeight(), mouse.y); |
| 100 | + ev.type = LCUI_MOUSEMOVE; |
| 101 | + ev.motion.x = mouse.x; |
| 102 | + ev.motion.y = mouse.y; |
| 103 | + ev.motion.xrel = buf[1]; |
| 104 | + ev.motion.yrel = -buf[2]; |
| 105 | + LCUI_TriggerEvent(&ev, NULL); |
| 106 | + LCUI_DestroyEvent(&ev); |
| 107 | + DispathMouseButtonEvent(MOUSE_BUTTON_LEFT, state); |
| 108 | + DispathMouseButtonEvent(MOUSE_BUTTON_RIGHT, state); |
| 109 | +} |
| 110 | + |
| 111 | +static void LinuxMouseThread(void *arg) |
| 112 | +{ |
| 113 | + char buf[6]; |
| 114 | + fd_set readfds; |
| 115 | + struct timeval tv; |
| 116 | + LCUI_TaskRec task = { 0 }; |
| 117 | + |
| 118 | + mouse.active = TRUE; |
| 119 | + task.func = DispatchMouseEvent; |
| 120 | + task.destroy_arg[0] = free; |
| 121 | + while (mouse.active) { |
| 122 | + tv.tv_sec = 0; |
| 123 | + tv.tv_usec = 500000; |
| 124 | + |
| 125 | + FD_ZERO(&readfds); |
| 126 | + FD_SET(mouse.dev_fd, &readfds); |
| 127 | + select(mouse.dev_fd + 1, &readfds, NULL, NULL, &tv); |
| 128 | + if (FD_ISSET(mouse.dev_fd, &readfds)) { |
| 129 | + if (read(mouse.dev_fd, buf, 6) <= 0) { |
| 130 | + continue; |
| 131 | + } |
| 132 | + task.arg[0] = malloc(sizeof(char) * 6); |
| 133 | + if (!task.arg[0]) { |
| 134 | + perror("[input] mouse driver"); |
| 135 | + continue; |
| 136 | + } |
| 137 | + memcpy(task.arg[0], buf, sizeof(char) * 6); |
| 138 | + LCUI_PostTask(&task); |
| 139 | + } |
| 140 | + } |
| 141 | +} |
| 142 | + |
| 143 | +static int InitLinuxMouse(void) |
| 144 | +{ |
| 145 | + mouse.x = LCUIDisplay_GetWidth() / 2; |
| 146 | + mouse.y = LCUIDisplay_GetHeight() / 2; |
| 147 | + mouse.dev_path = getenv("LCUI_MOUSE_DEVICE"); |
| 148 | + if (!mouse.dev_path) { |
| 149 | + mouse.dev_path = "/dev/input/mice"; |
| 150 | + } |
| 151 | + LOG("[input] open mouse device: %s\n", mouse.dev_path); |
| 152 | + if ((mouse.dev_fd = open(mouse.dev_path, O_RDONLY)) < 0) { |
| 153 | + perror("[input] open mouse device failed"); |
| 154 | + return -1; |
| 155 | + } |
| 156 | + LCUIThread_Create(&mouse.tid, LinuxMouseThread, NULL); |
| 157 | + LOG("[input] mouse driver thread: %lld\n", mouse.tid); |
| 158 | + return 0; |
| 159 | +} |
| 160 | + |
| 161 | +static void FreeLinuxMouse(void) |
| 162 | +{ |
| 163 | + if (mouse.active) { |
| 164 | + mouse.active = FALSE; |
| 165 | + LCUIThread_Join(mouse.tid, NULL); |
| 166 | + close(mouse.dev_fd); |
| 167 | + } |
| 168 | +} |
| 169 | + |
| 170 | +void LCUI_InitLinuxMouse(void) |
40 | 171 | {
|
41 | 172 | #ifdef LCUI_VIDEO_DRIVER_X11
|
42 |
| - LCUI_BOOL is_x11_mode = TRUE; |
43 |
| - if( is_x11_mode ) { |
| 173 | + if (LCUI_GetAppId() == LCUI_APP_LINUX_X11) { |
44 | 174 | LCUI_InitLinuxX11Mouse();
|
| 175 | + return; |
45 | 176 | }
|
46 | 177 | #endif
|
| 178 | + InitLinuxMouse(); |
47 | 179 | }
|
48 | 180 |
|
49 |
| -void LCUI_ExitLinuxMouse( void ) |
| 181 | +void LCUI_FreeLinuxMouse(void) |
50 | 182 | {
|
51 | 183 | #ifdef LCUI_VIDEO_DRIVER_X11
|
52 |
| - LCUI_BOOL is_x11_mode = TRUE; |
53 |
| - if( is_x11_mode ) { |
54 |
| - LCUI_ExitLinuxX11Mouse(); |
| 184 | + if (LCUI_GetAppId() == LCUI_APP_LINUX_X11) { |
| 185 | + LCUI_FreeLinuxX11Mouse(); |
| 186 | + return; |
55 | 187 | }
|
56 | 188 | #endif
|
| 189 | + FreeLinuxMouse(); |
57 | 190 | }
|
58 | 191 |
|
59 | 192 | #endif
|
0 commit comments