From d8e32e2a0a8dc2b9fd20969628462a1fedf92c5a Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sat, 3 Jun 2023 04:42:14 +0300 Subject: [PATCH 33/33] gtk4: Fix map recenter issues near map wrapping point The bug is not specific to gtk4-client, but the fix (/workaround) is. - Client-common code is improved slightly, so that the recenter works correctly in the special case when cached drawing is disabled - Added means for a gui to disable cached drawing - Made gtk4-client to always disable cached drawing See osdn #48150 Signed-off-by: Marko Lindqvist --- client/gui-gtk-3.22/graphics.c | 8 +++++++ client/gui-gtk-4.0/graphics.c | 8 +++++++ client/gui-qt/graphics.cpp | 8 +++++++ client/gui-qt/qtg_cxxside.cpp | 1 + client/gui-qt/qtg_cxxside.h | 1 + client/gui-sdl2/graphics.c | 8 +++++++ client/gui-stub/graphics.c | 8 +++++++ client/gui_interface.c | 8 +++++++ client/gui_interface.h | 1 + client/include/graphics_g.h | 4 +++- client/mapview_common.c | 41 +++++++++++++++++++++++++--------- 11 files changed, 84 insertions(+), 12 deletions(-) diff --git a/client/gui-gtk-3.22/graphics.c b/client/gui-gtk-3.22/graphics.c index 508a37591f..e456dfd7ef 100644 --- a/client/gui-gtk-3.22/graphics.c +++ b/client/gui-gtk-3.22/graphics.c @@ -74,6 +74,14 @@ void tileset_type_set(enum ts_type type) { } +/***********************************************************************//** + Tell client-common code that it may use cached drawing. +***************************************************************************/ +bool allow_cached_drawing(void) +{ + return TRUE; +} + #define COLOR_MOTTO_FACE_R 0x2D #define COLOR_MOTTO_FACE_G 0x71 #define COLOR_MOTTO_FACE_B 0xE3 diff --git a/client/gui-gtk-4.0/graphics.c b/client/gui-gtk-4.0/graphics.c index 3858ec0387..6d4f5a6628 100644 --- a/client/gui-gtk-4.0/graphics.c +++ b/client/gui-gtk-4.0/graphics.c @@ -74,6 +74,14 @@ void tileset_type_set(enum ts_type type) { } +/***********************************************************************//** + Tell client-common code that cached drawing should never be used. +***************************************************************************/ +bool allow_cached_drawing(void) +{ + return FALSE; +} + #define COLOR_MOTTO_FACE_R 0x2D #define COLOR_MOTTO_FACE_G 0x71 #define COLOR_MOTTO_FACE_B 0xE3 diff --git a/client/gui-qt/graphics.cpp b/client/gui-qt/graphics.cpp index 3b226e8f13..b1d35f4eb2 100644 --- a/client/gui-qt/graphics.cpp +++ b/client/gui-qt/graphics.cpp @@ -44,3 +44,11 @@ bool qtg_is_view_supported(enum ts_type type) void qtg_tileset_type_set(enum ts_type type) { } + +/***********************************************************************//** + Tell client-common code that it may use cached drawing. +***************************************************************************/ +bool qtg_allow_cached_drawing() +{ + return TRUE; +} diff --git a/client/gui-qt/qtg_cxxside.cpp b/client/gui-qt/qtg_cxxside.cpp index 13819ac55b..d5b349aa31 100644 --- a/client/gui-qt/qtg_cxxside.cpp +++ b/client/gui-qt/qtg_cxxside.cpp @@ -42,6 +42,7 @@ void setup_gui_funcs() funcs->is_view_supported = qtg_is_view_supported; funcs->tileset_type_set = qtg_tileset_type_set; + funcs->allow_cached_drawing = qtg_allow_cached_drawing; funcs->load_gfxfile = qtg_load_gfxfile; funcs->load_gfxnumber = qtg_load_gfxnumber; funcs->create_sprite = qtg_create_sprite; diff --git a/client/gui-qt/qtg_cxxside.h b/client/gui-qt/qtg_cxxside.h index 06a9b88018..3251a3772e 100644 --- a/client/gui-qt/qtg_cxxside.h +++ b/client/gui-qt/qtg_cxxside.h @@ -41,6 +41,7 @@ void qtg_real_output_window_append(const char *astring, bool qtg_is_view_supported(enum ts_type type); void qtg_tileset_type_set(enum ts_type type); +bool qtg_allow_cached_drawing(); struct sprite *qtg_load_gfxfile(const char *filename, bool svgflag); struct sprite *qtg_load_gfxnumber(int num); struct sprite *qtg_create_sprite(int width, int height, struct color *pcolor); diff --git a/client/gui-sdl2/graphics.c b/client/gui-sdl2/graphics.c index f9d42a137b..ff417532c3 100644 --- a/client/gui-sdl2/graphics.c +++ b/client/gui-sdl2/graphics.c @@ -1801,6 +1801,14 @@ void tileset_type_set(enum ts_type type) { } +/***********************************************************************//** + Tell client-common code that it may use cached drawing. +***************************************************************************/ +bool allow_cached_drawing(void) +{ + return TRUE; +} + /**********************************************************************//** Create colored frame **************************************************************************/ diff --git a/client/gui-stub/graphics.c b/client/gui-stub/graphics.c index f34371cb24..d9f378906c 100644 --- a/client/gui-stub/graphics.c +++ b/client/gui-stub/graphics.c @@ -41,6 +41,14 @@ void gui_tileset_type_set(enum ts_type type) { } +/***********************************************************************//** + Tell client-common code that it may use cached drawing. +***************************************************************************/ +bool gui_allow_cached_drawing(void) +{ + return TRUE; +} + /************************************************************************//** Load the cursors (mouse substitute sprites), including a goto cursor, an airdrop cursor, a nuke cursor, and a patrol cursor. diff --git a/client/gui_interface.c b/client/gui_interface.c index c61f53d964..0b3cacbb0d 100644 --- a/client/gui_interface.c +++ b/client/gui_interface.c @@ -119,6 +119,14 @@ void tileset_type_set(enum ts_type type) funcs.tileset_type_set(type); } +/**********************************************************************//** + Call allow_cached_drawing callback +**************************************************************************/ +bool allow_cached_drawing(void) +{ + return funcs.allow_cached_drawing(); +} + /**********************************************************************//** Call load_gfxfile callback **************************************************************************/ diff --git a/client/gui_interface.h b/client/gui_interface.h index 9c77a2233b..92982f8c6e 100644 --- a/client/gui_interface.h +++ b/client/gui_interface.h @@ -49,6 +49,7 @@ struct gui_funcs { bool (*is_view_supported)(enum ts_type type); void (*tileset_type_set)(enum ts_type type); + bool (*allow_cached_drawing)(void); struct sprite * (*load_gfxfile)(const char *filename, bool svgflag); struct sprite * (*load_gfxnumber)(int num); struct sprite * (*create_sprite)(int width, int height, struct color *pcolor); diff --git a/client/include/graphics_g.h b/client/include/graphics_g.h index a8c30b7941..7a83e6353e 100644 --- a/client/include/graphics_g.h +++ b/client/include/graphics_g.h @@ -27,6 +27,8 @@ GUI_FUNC_PROTO(bool, is_view_supported, enum ts_type type) GUI_FUNC_PROTO(void, tileset_type_set, enum ts_type type) +GUI_FUNC_PROTO(bool, allow_cached_drawing, void) + GUI_FUNC_PROTO(void, load_cursors, void) -#endif /* FC__GRAPHICS_G_H */ +#endif /* FC__GRAPHICS_G_H */ diff --git a/client/mapview_common.c b/client/mapview_common.c index 56b211fd42..0f96438094 100644 --- a/client/mapview_common.c +++ b/client/mapview_common.c @@ -852,7 +852,6 @@ static void base_set_mapview_origin(float gui_x0, float gui_y0) float dx, dy; const int width = mapview.width, height = mapview.height; int common_x0, common_x1, common_y0, common_y1; - int update_x0, update_x1, update_y0, update_y1; /* Then update everything. This does some tricky math to avoid having * to do unnecessary redraws in update_map_canvas(). This makes for ugly @@ -870,9 +869,6 @@ static void base_set_mapview_origin(float gui_x0, float gui_y0) old_gui_x0 = gui_x0 - dx; old_gui_y0 = gui_y0 - dy; - mapview.gui_x0 = gui_x0; - mapview.gui_y0 = gui_y0; - /* Find the overlapping area of the new and old mapview. This is * done in GUI coordinates. Note that if the GUI coordinates wrap * no overlap will be found. */ @@ -886,6 +882,7 @@ static void base_set_mapview_origin(float gui_x0, float gui_y0) /* Do a partial redraw only. This means the area of overlap (a * rectangle) is copied. Then the remaining areas (two rectangles) * are updated through update_map_canvas(). */ + int update_x0, update_x1, update_y0, update_y1; struct canvas *target = mapview.tmp_store; if (old_gui_x0 < gui_x0) { @@ -912,6 +909,13 @@ static void base_set_mapview_origin(float gui_x0, float gui_y0) mapview.tmp_store = mapview.store; mapview.store = target; + /* FIXME: partial update_map_canvas() would break completely + * if these are not updated before the call, but + * it sometimes causes screen to recenter to wrong + * place when they *are* updated. */ + mapview.gui_x0 = gui_x0; + mapview.gui_y0 = gui_y0; + if (update_y1 > update_y0) { update_map_canvas(0, update_y0 - gui_y0, width, update_y1 - update_y0); @@ -923,6 +927,11 @@ static void base_set_mapview_origin(float gui_x0, float gui_y0) } else { dirty_all(); update_map_canvas(0, 0, mapview.store_width, mapview.store_height); + + /* Set them correctly after update_map_canvas() has done its + * updates based on old values. */ + mapview.gui_x0 = gui_x0; + mapview.gui_y0 = gui_y0; } center_tile_overviewcanvas(); @@ -3216,9 +3225,18 @@ void get_city_mapview_name_and_growth(struct city *pcity, ****************************************************************************/ static bool can_do_cached_drawing(void) { - const int W = tileset_tile_width(tileset) * map_zoom; - const int H = tileset_tile_height(tileset) * map_zoom; - int w = mapview.store_width, h = mapview.store_height; + int tw, th; + int w, h; + + if (!allow_cached_drawing()) { + /* gui does not allow it. */ + return FALSE; + } + + tw = tileset_tile_width(tileset) * map_zoom; + th = tileset_tile_height(tileset) * map_zoom; + w = mapview.store_width; + h = mapview.store_height; /* If the mapview window is too large, cached drawing is not possible. * @@ -3264,8 +3282,8 @@ static bool can_do_cached_drawing(void) * of the (width+height). The second division by two is because for * an iso-map, NATURAL_XXX has a scale of 2, whereas for iso-view * NORMAL_TILE_XXX has a scale of 2. */ - return (w <= (NATURAL_WIDTH + NATURAL_HEIGHT) * W / 4 - && h <= (NATURAL_WIDTH + NATURAL_HEIGHT) * H / 4); + return (w <= (NATURAL_WIDTH + NATURAL_HEIGHT) * tw / 4 + && h <= (NATURAL_WIDTH + NATURAL_HEIGHT) * th / 4); } else { /* Matching. */ const int isofactor = (tileset_is_isometric(tileset) ? 2 : 1); @@ -3274,13 +3292,14 @@ static bool can_do_cached_drawing(void) /* Now we can use the full width and height, with the exception of a small * area on each side. */ if (current_wrap_has_flag(WRAP_X) - && w > (NATURAL_WIDTH - isodiff) * W / isofactor) { + && w > (NATURAL_WIDTH - isodiff) * tw / isofactor) { return FALSE; } if (current_wrap_has_flag(WRAP_Y) - && h > (NATURAL_HEIGHT - isodiff) * H / isofactor) { + && h > (NATURAL_HEIGHT - isodiff) * th / isofactor) { return FALSE; } + return TRUE; } } -- 2.39.2