Compare commits
5 Commits
hidpi
...
hidpiscale
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae87885ffa | ||
|
|
65021416b3 | ||
|
|
305e76ee6e | ||
|
|
ef0029d10e | ||
|
|
36c68c4802 |
@@ -8,6 +8,7 @@ src = [
|
||||
'src/device.c',
|
||||
'src/fpscounter.c',
|
||||
'src/frames.c',
|
||||
'src/hidpi.c',
|
||||
'src/inputmanager.c',
|
||||
'src/lockutil.c',
|
||||
'src/net.c',
|
||||
|
||||
@@ -136,6 +136,7 @@ SDL_bool input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||
|
||||
SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||
struct size screen_size,
|
||||
struct hidpi_scale *hidpi_scale,
|
||||
struct control_event *to) {
|
||||
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
||||
|
||||
@@ -145,21 +146,30 @@ SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||
|
||||
to->mouse_event.buttons = convert_mouse_buttons(SDL_BUTTON(from->button));
|
||||
to->mouse_event.position.screen_size = screen_size;
|
||||
to->mouse_event.position.point.x = (Uint16) from->x;
|
||||
to->mouse_event.position.point.y = (Uint16) from->y;
|
||||
|
||||
Sint32 x = from->x;
|
||||
Sint32 y = from->y;
|
||||
hidpi_unscale_coordinates(hidpi_scale, &x, &y);
|
||||
to->mouse_event.position.point.x = (Uint16) x;
|
||||
to->mouse_event.position.point.y = (Uint16) y;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||
struct size screen_size,
|
||||
struct hidpi_scale *hidpi_scale,
|
||||
struct control_event *to) {
|
||||
to->type = CONTROL_EVENT_TYPE_MOUSE;
|
||||
to->mouse_event.action = AMOTION_EVENT_ACTION_MOVE;
|
||||
to->mouse_event.buttons = convert_mouse_buttons(from->state);
|
||||
to->mouse_event.position.screen_size = screen_size;
|
||||
to->mouse_event.position.point.x = from->x;
|
||||
to->mouse_event.position.point.y = from->y;
|
||||
|
||||
Sint32 x = from->x;
|
||||
Sint32 y = from->y;
|
||||
hidpi_unscale_coordinates(hidpi_scale, &x, &y);
|
||||
to->mouse_event.position.point.x = (Uint16) x;
|
||||
to->mouse_event.position.point.y = (Uint16) y;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
|
||||
#include <SDL2/SDL_stdinc.h>
|
||||
#include <SDL2/SDL_events.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "controlevent.h"
|
||||
#include "hidpi.h"
|
||||
|
||||
struct complete_mouse_motion_event {
|
||||
SDL_MouseMotionEvent *mouse_motion_event;
|
||||
@@ -19,12 +22,14 @@ SDL_bool input_key_from_sdl_to_android(const SDL_KeyboardEvent *from,
|
||||
struct control_event *to);
|
||||
SDL_bool mouse_button_from_sdl_to_android(const SDL_MouseButtonEvent *from,
|
||||
struct size screen_size,
|
||||
struct hidpi_scale *hidpi_scale,
|
||||
struct control_event *to);
|
||||
|
||||
// the video size may be different from the real device size, so we need the size
|
||||
// to which the absolute position apply, to scale it accordingly
|
||||
SDL_bool mouse_motion_from_sdl_to_android(const SDL_MouseMotionEvent *from,
|
||||
struct size screen_size,
|
||||
struct hidpi_scale *hidpi_scale,
|
||||
struct control_event *to);
|
||||
|
||||
// on Android, a scroll event requires the current mouse position
|
||||
|
||||
16
app/src/hidpi.c
Normal file
16
app/src/hidpi.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "hidpi.h"
|
||||
|
||||
void hidpi_get_scale(struct screen *screen, struct hidpi_scale *scale) {
|
||||
SDL_GL_GetDrawableSize(screen->window, &scale->horizontal.num, &scale->vertical.num);
|
||||
SDL_GetWindowSize(screen->window, &scale->horizontal.div, &scale->vertical.div);
|
||||
}
|
||||
|
||||
void hidpi_unscale_coordinates(struct hidpi_scale *scale, Sint32 *x, Sint32 *y) {
|
||||
// to unscale, we devide by the ratio (so num and div are reversed)
|
||||
if (scale->horizontal.num) {
|
||||
*x = ((Sint64) *x) * scale->horizontal.div / scale->horizontal.num;
|
||||
}
|
||||
if (scale->vertical.num) {
|
||||
*y = ((Sint64) *y) * scale->vertical.div / scale->vertical.num;
|
||||
}
|
||||
}
|
||||
24
app/src/hidpi.h
Normal file
24
app/src/hidpi.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef HIDPI_H
|
||||
#define HIDPI_H
|
||||
|
||||
#include "common.h"
|
||||
#include "screen.h"
|
||||
|
||||
// rational number p/q
|
||||
struct rational {
|
||||
int num;
|
||||
int div;
|
||||
};
|
||||
|
||||
struct hidpi_scale {
|
||||
struct rational horizontal; // drawable.width / window.width
|
||||
struct rational vertical; // drawable.height / window.height
|
||||
};
|
||||
|
||||
void hidpi_get_scale(struct screen *screen, struct hidpi_scale *hidpi_scale);
|
||||
|
||||
// mouse location need to be "unscaled" if hidpi is enabled
|
||||
// <https://nlguillemot.wordpress.com/2016/12/11/high-dpi-rendering/>
|
||||
void hidpi_unscale_coordinates(struct hidpi_scale *hidpi_scale, Sint32 *x, Sint32 *y);
|
||||
|
||||
#endif
|
||||
@@ -1,13 +1,37 @@
|
||||
#include "inputmanager.h"
|
||||
|
||||
#include "convert.h"
|
||||
#include "hidpi.h"
|
||||
#include "lockutil.h"
|
||||
#include "log.h"
|
||||
|
||||
static struct point get_mouse_point(void) {
|
||||
int x;
|
||||
int y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
// Convert window coordinates (as provided by SDL_GetMouseState() to renderer coordinates (as provided in SDL mouse events)
|
||||
//
|
||||
// See my question:
|
||||
// <https://stackoverflow.com/questions/49111054/how-to-get-mouse-position-on-mouse-wheel-event>
|
||||
static void convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int *y) {
|
||||
SDL_Rect viewport;
|
||||
float scale_x, scale_y;
|
||||
SDL_RenderGetViewport(renderer, &viewport);
|
||||
SDL_RenderGetScale(renderer, &scale_x, &scale_y);
|
||||
*x = (int) (*x / scale_x) - viewport.x;
|
||||
*y = (int) (*y / scale_y) - viewport.y;
|
||||
}
|
||||
|
||||
static struct point get_mouse_point(struct screen *screen) {
|
||||
int mx;
|
||||
int my;
|
||||
SDL_GetMouseState(&mx, &my);
|
||||
convert_to_renderer_coordinates(screen->renderer, &mx, &my);
|
||||
|
||||
struct hidpi_scale hidpi_scale;
|
||||
hidpi_get_scale(screen, &hidpi_scale);
|
||||
|
||||
// SDL sometimes uses "int", sometimes "Sint32"
|
||||
Sint32 x = mx;
|
||||
Sint32 y = my;
|
||||
hidpi_unscale_coordinates(&hidpi_scale, &x, &y);
|
||||
|
||||
SDL_assert_release(x >= 0 && x < 0x10000 && y >= 0 && y < 0x10000);
|
||||
return (struct point) {
|
||||
.x = (Uint16) x,
|
||||
@@ -178,8 +202,12 @@ void input_manager_process_mouse_motion(struct input_manager *input_manager,
|
||||
// do not send motion events when no button is pressed
|
||||
return;
|
||||
}
|
||||
|
||||
struct hidpi_scale hidpi_scale;
|
||||
hidpi_get_scale(input_manager->screen, &hidpi_scale);
|
||||
|
||||
struct control_event control_event;
|
||||
if (mouse_motion_from_sdl_to_android(event, input_manager->screen->frame_size, &control_event)) {
|
||||
if (mouse_motion_from_sdl_to_android(event, input_manager->screen->frame_size, &hidpi_scale, &control_event)) {
|
||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
||||
LOGW("Cannot send mouse motion event");
|
||||
}
|
||||
@@ -192,8 +220,12 @@ void input_manager_process_mouse_button(struct input_manager *input_manager,
|
||||
turn_screen_on(input_manager->controller);
|
||||
return;
|
||||
};
|
||||
|
||||
struct hidpi_scale hidpi_scale;
|
||||
hidpi_get_scale(input_manager->screen, &hidpi_scale);
|
||||
|
||||
struct control_event control_event;
|
||||
if (mouse_button_from_sdl_to_android(event, input_manager->screen->frame_size, &control_event)) {
|
||||
if (mouse_button_from_sdl_to_android(event, input_manager->screen->frame_size, &hidpi_scale, &control_event)) {
|
||||
if (!controller_push_event(input_manager->controller, &control_event)) {
|
||||
LOGW("Cannot send mouse button event");
|
||||
}
|
||||
@@ -204,7 +236,7 @@ void input_manager_process_mouse_wheel(struct input_manager *input_manager,
|
||||
const SDL_MouseWheelEvent *event) {
|
||||
struct position position = {
|
||||
.screen_size = input_manager->screen->frame_size,
|
||||
.point = get_mouse_point(),
|
||||
.point = get_mouse_point(input_manager->screen),
|
||||
};
|
||||
struct control_event control_event;
|
||||
if (mouse_wheel_from_sdl_to_android(event, position, &control_event)) {
|
||||
|
||||
@@ -35,21 +35,6 @@ static struct input_manager input_manager = {
|
||||
.screen = &screen,
|
||||
};
|
||||
|
||||
static void hidpi_fix_coordinates(Sint32 *x, Sint32 *y) {
|
||||
struct screen_sizes sizes = screen_get_sizes(&screen);
|
||||
Uint16 ww = sizes.window_size.width;
|
||||
Uint16 wh = sizes.window_size.height;
|
||||
Uint16 dw = sizes.drawable_size.width;
|
||||
Uint16 dh = sizes.drawable_size.height;
|
||||
printf("window=%dx%d; drawable=%dx%d\n", (int) ww, (int) wh, (int) dw, (int) dh);
|
||||
if (dw && dw != ww) {
|
||||
*x = ((Sint64) *x) * ww / dw;
|
||||
}
|
||||
if (dh && dh != wh) {
|
||||
*y = ((Sint64) *y) * wh / dh;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_loop(void) {
|
||||
SDL_Event event;
|
||||
while (SDL_WaitEvent(&event)) {
|
||||
@@ -87,17 +72,14 @@ static void event_loop(void) {
|
||||
input_manager_process_key(&input_manager, &event.key);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
hidpi_fix_coordinates(&event.motion.x, &event.motion.y);
|
||||
input_manager_process_mouse_motion(&input_manager, &event.motion);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL: {
|
||||
hidpi_fix_coordinates(&event.wheel.x, &event.wheel.y);
|
||||
input_manager_process_mouse_wheel(&input_manager, &event.wheel);
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP: {
|
||||
hidpi_fix_coordinates(&event.button.y, &event.button.y);
|
||||
input_manager_process_mouse_button(&input_manager, &event.button);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -45,27 +45,6 @@ static struct size get_native_window_size(SDL_Window *window) {
|
||||
return size;
|
||||
}
|
||||
|
||||
// get the size of the window underlying drawable in pixels
|
||||
// may differ from get_native_window_size() if hi-dpi is enabled
|
||||
static struct size get_native_drawable_size(SDL_Window *window) {
|
||||
int width;
|
||||
int height;
|
||||
SDL_GL_GetDrawableSize(window, &width, &height);
|
||||
|
||||
struct size size;
|
||||
size.width = width;
|
||||
size.height = height;
|
||||
return size;
|
||||
}
|
||||
|
||||
// return both the native window size and native drawable size
|
||||
struct screen_sizes screen_get_sizes(const struct screen *screen) {
|
||||
struct screen_sizes sizes;
|
||||
sizes.window_size = get_native_window_size(screen->window);
|
||||
sizes.drawable_size = get_native_drawable_size(screen->window);
|
||||
return sizes;
|
||||
}
|
||||
|
||||
// get the windowed window size
|
||||
static struct size get_window_size(const struct screen *screen) {
|
||||
if (screen->fullscreen) {
|
||||
|
||||
@@ -34,15 +34,6 @@ struct screen {
|
||||
.fullscreen = SDL_FALSE, \
|
||||
}
|
||||
|
||||
// the window and drawable size may differ if hi-dpi is enabled
|
||||
struct screen_sizes {
|
||||
// the size of the window client area, as reported by SDL_GetWindowSize()
|
||||
struct size window_size;
|
||||
// the size of the window underlying drawable, as reported by
|
||||
// SDL_GL_GetDrawableSize()
|
||||
struct size drawable_size;
|
||||
};
|
||||
|
||||
// init SDL and set appropriate hints
|
||||
SDL_bool sdl_init_and_configure(void);
|
||||
|
||||
@@ -75,6 +66,4 @@ void screen_resize_to_fit(struct screen *screen);
|
||||
// resize window to 1:1 (pixel-perfect)
|
||||
void screen_resize_to_pixel_perfect(struct screen *screen);
|
||||
|
||||
struct screen_sizes screen_get_sizes(const struct screen *screen);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,6 +71,7 @@ static socket_t listen_on_port(Uint16 port) {
|
||||
|
||||
static void close_socket(socket_t *socket) {
|
||||
SDL_assert(*socket != INVALID_SOCKET);
|
||||
net_shutdown(*socket, SHUT_RDWR);
|
||||
if (!net_close(*socket)) {
|
||||
LOGW("Cannot close socket");
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user