Fix rotation while the window is maximized

Keep the windowed window size to handle maximized window the same way as
fullscreen window.

Fixes <https://github.com/Genymobile/scrcpy/issues/750>
This commit is contained in:
Romain Vimont 2019-11-11 21:26:35 +01:00
parent f6f2868868
commit 35c05bb3ce
2 changed files with 73 additions and 34 deletions

View file

@ -30,23 +30,28 @@ get_window_size(SDL_Window *window) {
// get the windowed window size // get the windowed window size
static struct size static struct size
get_windowed_window_size(const struct screen *screen) { get_windowed_window_size(const struct screen *screen) {
if (screen->fullscreen) { if (screen->fullscreen || screen->maximized) {
return screen->windowed_window_size; return screen->windowed_window_size;
} }
return get_window_size(screen->window); return get_window_size(screen->window);
} }
// apply the windowed window size if fullscreen and maximized are disabled
static void
apply_windowed_size(struct screen *screen) {
if (!screen->fullscreen && !screen->maximized) {
SDL_SetWindowSize(screen->window, screen->windowed_window_size.width,
screen->windowed_window_size.height);
}
}
// set the window size to be applied when fullscreen is disabled // set the window size to be applied when fullscreen is disabled
static void static void
set_window_size(struct screen *screen, struct size new_size) { set_window_size(struct screen *screen, struct size new_size) {
// setting the window size during fullscreen is implementation defined, // setting the window size during fullscreen is implementation defined,
// so apply the resize only after fullscreen is disabled // so apply the resize only after fullscreen is disabled
if (screen->fullscreen) { screen->windowed_window_size = new_size;
// SDL_SetWindowSize will be called when fullscreen will be disabled apply_windowed_size(screen);
screen->windowed_window_size = new_size;
} else {
SDL_SetWindowSize(screen->window, new_size.width, new_size.height);
}
} }
// get the preferred display bounds (i.e. the screen bounds with some margins) // get the preferred display bounds (i.e. the screen bounds with some margins)
@ -194,6 +199,8 @@ screen_init_rendering(struct screen *screen, const char *window_title,
return false; return false;
} }
screen->windowed_window_size = window_size;
return true; return true;
} }
@ -287,10 +294,6 @@ screen_render(struct screen *screen) {
void void
screen_switch_fullscreen(struct screen *screen) { screen_switch_fullscreen(struct screen *screen) {
if (!screen->fullscreen) {
// going to fullscreen, store the current windowed window size
screen->windowed_window_size = get_window_size(screen->window);
}
uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP; uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
if (SDL_SetWindowFullscreen(screen->window, new_mode)) { if (SDL_SetWindowFullscreen(screen->window, new_mode)) {
LOGW("Could not switch fullscreen mode: %s", SDL_GetError()); LOGW("Could not switch fullscreen mode: %s", SDL_GetError());
@ -298,11 +301,7 @@ screen_switch_fullscreen(struct screen *screen) {
} }
screen->fullscreen = !screen->fullscreen; screen->fullscreen = !screen->fullscreen;
if (!screen->fullscreen) { apply_windowed_size(screen);
// fullscreen disabled, restore expected windowed window size
SDL_SetWindowSize(screen->window, screen->windowed_window_size.width,
screen->windowed_window_size.height);
}
LOGD("Switched to %s mode", screen->fullscreen ? "fullscreen" : "windowed"); LOGD("Switched to %s mode", screen->fullscreen ? "fullscreen" : "windowed");
screen_render(screen); screen_render(screen);
@ -310,7 +309,7 @@ screen_switch_fullscreen(struct screen *screen) {
void void
screen_resize_to_fit(struct screen *screen) { screen_resize_to_fit(struct screen *screen) {
if (!screen->fullscreen) { if (!screen->fullscreen && !screen->maximized) {
struct size optimal_size = get_optimal_window_size(screen, struct size optimal_size = get_optimal_window_size(screen,
screen->frame_size); screen->frame_size);
SDL_SetWindowSize(screen->window, optimal_size.width, SDL_SetWindowSize(screen->window, optimal_size.width,
@ -321,7 +320,7 @@ screen_resize_to_fit(struct screen *screen) {
void void
screen_resize_to_pixel_perfect(struct screen *screen) { screen_resize_to_pixel_perfect(struct screen *screen) {
if (!screen->fullscreen) { if (!screen->fullscreen && !screen->maximized) {
SDL_SetWindowSize(screen->window, screen->frame_size.width, SDL_SetWindowSize(screen->window, screen->frame_size.width,
screen->frame_size.height); screen->frame_size.height);
LOGD("Resized to pixel-perfect"); LOGD("Resized to pixel-perfect");
@ -333,8 +332,39 @@ screen_handle_window_event(struct screen *screen,
const SDL_WindowEvent *event) { const SDL_WindowEvent *event) {
switch (event->event) { switch (event->event) {
case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_EXPOSED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
screen_render(screen); screen_render(screen);
break; break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
if (!screen->fullscreen && !screen->maximized) {
// Backup the previous size: if we receive the MAXIMIZED event,
// then the new size must be ignored (it's the maximized size).
// We could not rely on the window flags due to race conditions
// (they could be updated asynchronously, at least on X11).
screen->windowed_window_size_backup =
screen->windowed_window_size;
// Save the windowed size, so that it is available once the
// window is maximized or fullscreen is enabled.
screen->windowed_window_size = get_window_size(screen->window);
}
screen_render(screen);
break;
case SDL_WINDOWEVENT_MAXIMIZED:
// The backup size must be non-nul.
SDL_assert(screen->windowed_window_size_backup.width);
SDL_assert(screen->windowed_window_size_backup.height);
// Revert the last size, it was updated while screen was maximized.
screen->windowed_window_size = screen->windowed_window_size_backup;
#ifdef DEBUG
// Reset the backup to invalid values to detect unexpected usage
screen->windowed_window_size_backup.width = 0;
screen->windowed_window_size_backup.height = 0;
#endif
screen->maximized = true;
break;
case SDL_WINDOWEVENT_RESTORED:
screen->maximized = false;
apply_windowed_size(screen);
break;
} }
} }

View file

@ -15,28 +15,37 @@ struct screen {
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Texture *texture; SDL_Texture *texture;
struct size frame_size; struct size frame_size;
//used only in fullscreen mode to know the windowed window size // The window size the last time it was not maximized or fullscreen.
struct size windowed_window_size; struct size windowed_window_size;
// Since we receive the event SIZE_CHANGED before MAXIMIZED, we must be
// able to revert the size to its non-maximized value.
struct size windowed_window_size_backup;
bool has_frame; bool has_frame;
bool fullscreen; bool fullscreen;
bool maximized;
bool no_window; bool no_window;
}; };
#define SCREEN_INITIALIZER { \ #define SCREEN_INITIALIZER { \
.window = NULL, \ .window = NULL, \
.renderer = NULL, \ .renderer = NULL, \
.texture = NULL, \ .texture = NULL, \
.frame_size = { \ .frame_size = { \
.width = 0, \ .width = 0, \
.height = 0, \ .height = 0, \
}, \ }, \
.windowed_window_size = { \ .windowed_window_size = { \
.width = 0, \ .width = 0, \
.height = 0, \ .height = 0, \
}, \ }, \
.has_frame = false, \ .windowed_window_size_backup = { \
.fullscreen = false, \ .width = 0, \
.no_window = false, \ .height = 0, \
}, \
.has_frame = false, \
.fullscreen = false, \
.maximized = false, \
.no_window = false, \
} }
// initialize default values // initialize default values