Subject: bug#21317: 25.0.50; frame-resize-pixelwise has no effect (GTK, no window manager)

From: martin rudalics <[email-masked]>
Date: Sun, 23 Aug 2015 13:12:29 +0200

> Sorry about that. You're right, I've only seen the problem when I make
 > a fullscreen frame. That wasn't perfectly clear to me at the time, but
 > I should have tested better. Thank you for your patience.

It's not immediately clear that the problem happens only with attempts
to make a fullscreen frame which, to be clear again, could mean any of
maximized, fullheight, fullwidth and fullboth.

So when you try to increase the height of a normal frame by one pixel,
which is the resize operation you send?  I suppose it's the last one
from x_set_window_size_1 so Emacs correctly passes the size hint with
frame_resize_pixelwise 1.  Right?

If this is the case, then Emacs should, for you, also handle fullwidth
and fullheight requests correctly via the first and second of the
requests in x_set_window_size_1.  Right?

So the two remaining cases Emacs can't handle for you are fullscreen and
maximized requests.  Right?

 >> I faintly remember that bug now.

Rereading the corresponding thread I wonder how my memory could fail
so miserably.

 > What I don't understand is the remedy.
 >> When we do
 >>
 >>    fs_state = Fframe_parameter (frame, Qfullscreen);
 >>    if (EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth))
 >>
 >> the parameter has been already set but the frame is not yet fullscreen.
 >> Does this shrinking occur when the frame is already fullscreen or does
 >> it occur when a user wants to switch to fullscreen?
 >
 > I'm not a hundred percent certain; from reading the thread, I think
 > it's the former: the window is in full-screen mode and starts
 > shrinking. I've installed KWin but have been unable to produce buggy
 > behavior, so far, without the workaround in gtkutil.c.

I attach a patch that should handle the case where we want to switch
from a non-fullscreen to a fullscreen frame.  Please try it.
FRAME_OUTER_WINDOW (f) should probably be replaced by some GTK-specific
window but I don't yet know which one.

 >> When worse comes to worse we could condition that somehow: Invent an
 >> option which is off by default and call x_wm_set_size_hint when it's on.
 >
 > I do wonder how useful it is to support the case without a window
 > manager; unfortunately, I think it is useful, much as I'd enjoy all
 > that code going away and leaving things to the window manager.

I miss you here: Which "case" do you mean?

 > Anyway, if x_check_fullscreen is supposed to work the way it currently
 > does, bypassing xg_frame_set_char_size, there's a third issue to add
 > to my list:
 >
 > (3) x_check_fullscreen does not call store_frame_param, unlike
 > x_set_window_size_1, so the frame has its 'fullscreen parameter
 > cleared to nil by x_net_wm_state; the next `set-frame-font' call then
 > results in an integral frame size rather than the full screen.

Correct me if I'm wrong: We run x_check_fullscreen only when the window
manager doesn't support fullscreen natively.  WOW when we run
x_check_fullscreen, we emulate the behavior of a window manager by
calculating the respective sizes ourselves.

Now when Emacs sets the fullscreen frame parameter itself, this action
basically covers only what we get from the window manager.  A user who
wanted a fullscreen frame would have set the according frame parameter
already.  What am I missing?

 > If my understanding is correct, the best way forward is this:
 >
 >   - skip the hints in maximized/fullscreen state if
 > wm_supports(net_wm_state) || wm_supports(net_wm_state_fullscreen), it
 > might be KWin
 >   - otherwise, set the hints

OK.  These can be done easily, maybe in combination with my patch.

 >   - call x_wm_set_size_hint from x_check_fullscreen

OK.  Funnily we call a function x_wm_set_size_hint to handle a scenario
where there's no window manager.

 >   - call store_frame_param from x_check_fullscreen

It might not harm but, as mentioned above, this should not be
necessary.  Or, if it is necessary because the parameters are not in
place yet, the bug seems to be elsewhere,

 >> I see.  If in frame.c you initialize frame_resize_pixelwise to 1 then
 >> everything works OK?
 >
 > ...Almost. Sorry. If I set frame_resize_pixelwise to 1 and run
 > `set-frame-font' afterwards,

Hmm..  so you insist.  Can you tell me why `set-frame-font' can change a
fullscreen frame's size?

 > the frame loses its full-screen
 > resolution and changes to a similar resolution that's a multiple of
 > the character size, as far as I can tell. This is due to issue (3), I
 > believe. Similarly, we don't adjust for the tool bar size, which I
 > also believe is due to issue (3) (I keep forgetting about that one
 > since I don't usually use the tool bar).

Let's look into the toolbar issue later.  What we have to check first
is:

(1) You have a "correctly" maximized frame and `frame-resize-pixelwise'
     is non-nil.  What is the frame's fullscreen parameter's value?

(2) If that value is non-nil, how comes `set-frame-font' can change the
     frame size?

 > I have attached the minimal patch (as far as I know) that works:
 > initialize frame_resize_pixelwise to 1,

We can't do that.  I mentioned that only so you can check whether it
would work in principle.

 > and fix issue (3). That works
 > both with a tool bar and with `set-frame-font' (I'm not in the habit
 > of running `set-frame-font', but it's run by the gconf code when
 > gnome-settings-daemon is active and specifies a system font).

OK.

 >> We could invent a function `set-frame-resize-pixelwise' which sends the
 >> size hints (maybe iff when a frame is not fullscreen, or so to avoid the
 >> KWin bug).
 >
 > How would that be different from x_wm_set_size_hints with FLAGS=0?

It would modify the increments accordingly.  That is
`set-frame-resize-pixelwise' with a non-nil ARG would set the increments
to 1 and with a nil ARG it would set them to the frame's column and line
heights.

 > I
 > suppose we could modify only the increments and leave the rest of the
 > size hints alone, but is that enough to prevent bad KWin behavior?

You mean calling `set-frame-resize-pixelwise' in a fullscreen state on
KWin would produce the bug again.  You're probably right.  So this won't
help much.

 > It seems like the code in x_check_fullscreen was intended to work
 > without a window manager (and without calling xg_frame_set_char_size),

... that's my impression too ...

 > but never did. It didn't call x_wm_set_size_hints and it didn't clean
 > up after x_net_wm_state by setting the 'fullscreen property again.

Do I understand finally?  x_net_wm_state resets the fullscreen state to
nil via its store_frame_param?  That would be the missing link then.
But then there's no use to set the fullscreen parameter earlier.
x_net_wm_state would annihilate that anyway.

martin
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -135,6 +135,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 static void update_theme_scrollbar_width (void);
 static void update_theme_scrollbar_height (void);

+bool get_current_wm_state (struct frame *, Window, int *, bool *);
+
 #define TB_INFO_KEY "xg_frame_tb_info"
 struct xg_frame_tb_info
 {
@@ -1364,7 +1366,8 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
   int base_width, base_height;
   int min_rows = 0, min_cols = 0;
   int win_gravity = f->win_gravity;
-  Lisp_Object fs_state, frame;
+  int state = FULLSCREEN_NONE;
+  bool sticky = false;
   int scale = xg_get_gdk_scale ();

   /* Don't set size hints during initialization; that apparently leads
@@ -1373,13 +1376,12 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
   if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f))
     return;

-  XSETFRAME (frame, f);
-  fs_state = Fframe_parameter (frame, Qfullscreen);
-  if (EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth))
+  get_current_wm_state (f, FRAME_OUTER_WINDOW (f), &state, &sticky);
+  if (state != FULLSCREEN_NONE)
     {
-      /* Don't set hints when maximized or fullscreen.  Apparently KWin and
-         Gtk3 don't get along and the frame shrinks (!).
-      */
+      /* Don't set hints when the frame currently is maximized or
+         fullscreen.  Apparently KWin and Gtk3 don't get along and the
+         frame shrinks (!).  */
       return;
     }

diff --git a/src/xterm.c b/src/xterm.c
index b7aacfa..2e1c0b5 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -247,7 +247,7 @@ static void x_wm_set_window_state (struct frame *, int);
 static void x_wm_set_icon_pixmap (struct frame *, ptrdiff_t);
 static void x_initialize (void);

-static bool get_current_wm_state (struct frame *, Window, int *, bool *);
+bool get_current_wm_state (struct frame *, Window, int *, bool *);

 /* Flush display of frame F.  */

@@ -9904,7 +9904,7 @@ x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)

    Return true iff we are not hidden.  */

-static bool
+bool
 get_current_wm_state (struct frame *f,
                       Window window,
                       int *size_state,