From: Yuuki Harano Date: Sat, 4 Dec 2021 06:54:37 +0000 (+0900) Subject: Keep track of scale factor by atimer and recreate cairo_surface_t X-Git-Tag: emacs-29.0.90~3620 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=729311c22b230faab9f8714ca2b6cb8f73ac0737;p=emacs.git Keep track of scale factor by atimer and recreate cairo_surface_t Otherwise texts become blurry when a frame moved from 1x monitor to 2x monitor. I need GTK's such signal, but there isn't. Instead I watch frame's monitor's scale factor periodically. We can see blurriness for a short time, but it is gone soon. * src/pgtkfns.c (update_watched_scale_factor): New function to check scale factor and recreate cairo_surface_t if changed. * src/pgtkfns.c (Fx_create_frame): Initialize atimer. (Fx_show_tip): Add an argument. * src/pgtkterm.c (FRAME_CR_SURFACE_DESIRED_WIDTH): Move macros to pgtkterm.h (x_free_frame_resources): Free atimer. (size_allocate): Add an argument. (pgtk_cr_update_surface_desired_size): Add an argument. Recreate if it is true. * src/pgtkterm.h (struct pgtk_output): New members. (FRAME_CR_SURFACE_DESIRED_HEIGHT): Move macros from pgtkterm.c --- diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 4f1f9faa2cb..febc90ad4e1 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -36,6 +36,7 @@ along with GNU Emacs. If not, see . */ #include "fontset.h" #include "font.h" #include "xsettings.h" +#include "atimer.h" #ifdef HAVE_PGTK @@ -1179,6 +1180,21 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) RES_TYPE_STRING); } +static void update_watched_scale_factor(struct atimer *timer) +{ + struct frame *f = timer->client_data; + + double scale_factor = FRAME_SCALE_FACTOR (f); + if (scale_factor != FRAME_X_OUTPUT (f)->watched_scale_factor) + { + FRAME_X_OUTPUT (f)->watched_scale_factor = scale_factor; + pgtk_cr_update_surface_desired_size (f, + FRAME_CR_SURFACE_DESIRED_WIDTH (f), + FRAME_CR_SURFACE_DESIRED_HEIGHT (f), + true); + } +} + /* ========================================================================== Lisp definitions @@ -1773,6 +1789,12 @@ This function is an internal primitive--use `make-frame' instead. */ ) FRAME_X_OUTPUT (f)->cr_surface_visible_bell = NULL; FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL; + FRAME_X_OUTPUT (f)->watched_scale_factor = 1.0; + struct timespec ts = make_timespec (1, 0); + FRAME_X_OUTPUT (f)->scale_factor_atimer = start_atimer(ATIMER_CONTINUOUS, + ts, + update_watched_scale_factor, + f); /* Make sure windows on this frame appear in calls to next-window and similar functions. */ @@ -3481,7 +3503,7 @@ Text larger than the specified size is clipped. */) gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (tip_f)), root_x, root_y); unblock_input (); - pgtk_cr_update_surface_desired_size (tip_f, width, height); + pgtk_cr_update_surface_desired_size (tip_f, width, height, false); w->must_be_updated_p = true; update_single_window (w); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 1fc8fa98a46..4c953fa92b2 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -72,10 +72,6 @@ along with GNU Emacs. If not, see . */ #define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) #define FRAME_CR_ACTIVE_CONTEXT(f) ((f)->output_data.pgtk->cr_active) #define FRAME_CR_SURFACE(f) (cairo_get_target (FRAME_CR_CONTEXT (f))) -#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \ - ((f)->output_data.pgtk->cr_surface_desired_width) -#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ - ((f)->output_data.pgtk->cr_surface_desired_height) /* Non-zero means that a HELP_EVENT has been generated since Emacs start. */ @@ -215,6 +211,12 @@ x_free_frame_resources (struct frame *f) free_frame_faces (f); + if (FRAME_X_OUTPUT (f)->scale_factor_atimer != NULL) + { + cancel_atimer (FRAME_X_OUTPUT (f)->scale_factor_atimer); + FRAME_X_OUTPUT (f)->scale_factor_atimer = NULL; + } + #define CLEAR_IF_EQ(FIELD) \ do { if (f == dpyinfo->FIELD) dpyinfo->FIELD = 0; } while (false) @@ -4845,7 +4847,7 @@ size_allocate (GtkWidget * widget, GtkAllocation * alloc, if (f) { xg_frame_resized (f, alloc->width, alloc->height); - pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height); + pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height, false); } } @@ -6820,10 +6822,11 @@ If set to a non-float value, there will be no wait at all. */); * until a redrawn frame is completed. */ void -pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height) +pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height, bool force) { if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width - || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height) + || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height + || force) { pgtk_cr_destroy_frame_context (f); FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index c16221da832..e76411cf021 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -398,6 +398,13 @@ struct pgtk_output frame, or IMPLICIT if we received an EnterNotify. FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */ int focus_state; + + /* Keep track of scale factor. If monitor's scale factor is changed, or + monitor is switched and scale factor is changed, then recreate cairo_t + and cairo_surface_t. I need GTK's such signal, but there isn't, so + I watch it periodically with atimer. */ + double watched_scale_factor; + struct atimer *scale_factor_atimer; }; /* this dummy decl needed to support TTYs */ @@ -521,6 +528,10 @@ enum (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \ : FRAME_SCROLL_BAR_COLS (f)) +#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \ + ((f)->output_data.pgtk->cr_surface_desired_width) +#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ + ((f)->output_data.pgtk->cr_surface_desired_height) /* Display init/shutdown functions implemented in pgtkterm.c */ extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name, @@ -575,7 +586,7 @@ extern void x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); /* Cairo related functions implemented in pgtkterm.c */ -extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int); +extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int, bool); extern cairo_t *pgtk_begin_cr_clip (struct frame *f); extern void pgtk_end_cr_clip (struct frame *f); extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f,