Skip to content

Commit 58b8504

Browse files
committed
Fix initial rendering and mouse scaling in fbdev
This replaces hard-coded 32767 with device-specific absolute axis ranges queried via EVIOCGABS ioctl. This fixes coordinate scaling for devices with different ABS_X/ABS_Y maxima. It moves first_run flag to twin_fbdev_t structure to support proper reinitialization when backend is torn down and recreated, preventing blank screens on subsequent initializations. Close #62
1 parent 16193dc commit 58b8504

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

backend/fbdev.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ typedef struct {
3939
uint16_t cmap[3][256];
4040
uint8_t *fb_base;
4141
size_t fb_len;
42+
43+
/* Initialization state */
44+
bool first_run; /* Track first work queue execution for initial damage */
4245
} twin_fbdev_t;
4346

4447
/* color conversion */
@@ -201,6 +204,16 @@ static bool twin_fbdev_work(void *closure)
201204
twin_fbdev_t *tx = PRIV(closure);
202205
twin_screen_t *screen = SCREEN(closure);
203206

207+
/* Mark entire screen as damaged on first run to ensure initial rendering.
208+
* This is necessary because the screen content is not automatically
209+
* rendered when the application starts. Using per-context state allows
210+
* proper reinitialization if the backend is torn down and recreated.
211+
*/
212+
if (tx->first_run) {
213+
tx->first_run = false;
214+
twin_screen_damage(screen, 0, 0, screen->width, screen->height);
215+
}
216+
204217
if (tx->vt_active && (tx->fb_base != MAP_FAILED)) {
205218
/* Unmap the fbdev */
206219
munmap(tx->fb_base, tx->fb_len);
@@ -240,6 +253,9 @@ twin_context_t *twin_fbdev_init(int width, int height)
240253

241254
twin_fbdev_t *tx = ctx->priv;
242255

256+
/* Initialize first_run flag for initial screen damage */
257+
tx->first_run = true;
258+
243259
/* Open the framebuffer device */
244260
tx->fb_fd = open(fbdev_path, O_RDWR);
245261
if (tx->fb_fd == -1) {

backend/linux_input.c

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ typedef struct {
3636
int fd;
3737
int btns;
3838
int x, y;
39+
int abs_x_max, abs_y_max; /* Maximum value for ABS_X/ABS_Y from device */
3940
} twin_linux_input_t;
4041

4142
static void check_mouse_bounds(twin_linux_input_t *tm)
@@ -79,16 +80,21 @@ static void twin_linux_input_events(struct input_event *ev,
7980
}
8081
break;
8182
case EV_ABS:
82-
if (ev->code == ABS_X) {
83-
tm->x = ev->value;
83+
/* Scale absolute coordinates to screen resolution.
84+
* The range is dynamically queried from each device using EVIOCGABS.
85+
* If no device reported ABS info, we fall back to the common default
86+
* of 32767 for touchscreens and absolute pointing devices.
87+
*/
88+
if (ev->code == ABS_X && tm->abs_x_max > 0) {
89+
tm->x = ((int64_t) ev->value * tm->screen->width) / tm->abs_x_max;
8490
check_mouse_bounds(tm);
8591
tev.kind = TwinEventMotion;
8692
tev.u.pointer.screen_x = tm->x;
8793
tev.u.pointer.screen_y = tm->y;
8894
tev.u.pointer.button = tm->btns;
8995
twin_screen_dispatch(tm->screen, &tev);
90-
} else if (ev->code == ABS_Y) {
91-
tm->y = ev->value;
96+
} else if (ev->code == ABS_Y && tm->abs_y_max > 0) {
97+
tm->y = ((int64_t) ev->value * tm->screen->height) / tm->abs_y_max;
9298
check_mouse_bounds(tm);
9399
tev.kind = TwinEventMotion;
94100
tev.u.pointer.screen_x = tm->x;
@@ -169,6 +175,26 @@ static bool twin_linux_udev_update(struct udev_monitor *mon)
169175
return false;
170176
}
171177

178+
/* Query absolute axis information from an input device */
179+
static void twin_linux_input_query_abs(int fd, twin_linux_input_t *tm)
180+
{
181+
struct input_absinfo abs_info;
182+
183+
/* Query ABS_X maximum value */
184+
if (ioctl(fd, EVIOCGABS(ABS_X), &abs_info) == 0 && abs_info.maximum > 0) {
185+
/* Update global maximum if this device has a larger range */
186+
if (abs_info.maximum > tm->abs_x_max)
187+
tm->abs_x_max = abs_info.maximum;
188+
}
189+
190+
/* Query ABS_Y maximum value */
191+
if (ioctl(fd, EVIOCGABS(ABS_Y), &abs_info) == 0 && abs_info.maximum > 0) {
192+
/* Update global maximum if this device has a larger range */
193+
if (abs_info.maximum > tm->abs_y_max)
194+
tm->abs_y_max = abs_info.maximum;
195+
}
196+
}
197+
172198
static void twin_linux_edev_open(struct pollfd *pfds, twin_linux_input_t *tm)
173199
{
174200
/* New event device list */
@@ -201,6 +227,8 @@ static void twin_linux_edev_open(struct pollfd *pfds, twin_linux_input_t *tm)
201227
/* Open the file if it is not on the list */
202228
int fd = open(evdev_name, O_RDWR | O_NONBLOCK);
203229
if (fd > 0 && !opened) {
230+
/* Query absolute axis info for newly opened devices */
231+
twin_linux_input_query_abs(fd, tm);
204232
evdevs[new_evdev_cnt].idx = i;
205233
evdevs[new_evdev_cnt].fd = fd;
206234
new_evdev_cnt++;
@@ -293,6 +321,11 @@ void *twin_linux_input_create(twin_screen_t *screen)
293321

294322
tm->screen = screen;
295323

324+
/* Initialize ABS axis ranges to common touchscreen default.
325+
* These will be updated to actual device values when devices are opened.
326+
*/
327+
tm->abs_x_max = tm->abs_y_max = 32767;
328+
296329
/* Centering the cursor position */
297330
tm->x = screen->width / 2;
298331
tm->y = screen->height / 2;

0 commit comments

Comments
 (0)