Skip to content

Commit

Permalink
hidpiscale
Browse files Browse the repository at this point in the history
  • Loading branch information
rom1v committed Mar 5, 2018
1 parent 6502141 commit ae87885
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 11 deletions.
1 change: 1 addition & 0 deletions app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
18 changes: 14 additions & 4 deletions app/src/convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
Expand Down
5 changes: 5 additions & 0 deletions app/src/convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions app/src/hidpi.c
Original file line number Diff line number Diff line change
@@ -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 changes: 24 additions & 0 deletions app/src/hidpi.h
Original file line number Diff line number Diff line change
@@ -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
30 changes: 24 additions & 6 deletions app/src/inputmanager.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "inputmanager.h"

#include "convert.h"
#include "hidpi.h"
#include "lockutil.h"
#include "log.h"

Expand All @@ -18,10 +19,19 @@ static void convert_to_renderer_coordinates(SDL_Renderer *renderer, int *x, int
}

static struct point get_mouse_point(struct screen *screen) {
int x;
int y;
SDL_GetMouseState(&x, &y);
convert_to_renderer_coordinates(screen->renderer, &x, &y);
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,
Expand Down Expand Up @@ -192,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");
}
Expand All @@ -206,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");
}
Expand Down
3 changes: 2 additions & 1 deletion app/src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ SDL_bool screen_init_rendering(struct screen *screen, const char *device_name, s

struct size window_size = get_initial_optimal_size(frame_size);
screen->window = SDL_CreateWindow(device_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
window_size.width, window_size.height, SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE);
window_size.width, window_size.height,
SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
if (!screen->window) {
LOGC("Could not create window: %s", SDL_GetError());
return SDL_FALSE;
Expand Down

0 comments on commit ae87885

Please sign in to comment.