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

From: Pip Cet <[email-masked]>
Date: Sun, 23 Aug 2015 12:20:27 +0000

Let me answer that email bottom-to-top, I think it makes most sense that way:

On Sun, Aug 23, 2015 at 11:12 AM, martin rudalics <[email-masked]> wrote:
>> 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.

Indeed.

(Minor point of confusion here: there are two functions called
`x_net_wm_state' and `x_handle_net_wm_state' which appear to do the
same thing...)

> But then there's no use to set the fullscreen parameter earlier.
> x_net_wm_state would annihilate that anyway.

I think you're right for X, but other toolkits might need the generic
code that sets it earlier.

>> 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.

The problem appears with all 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?

set_frame_height calls adjust_frame_size which calls x_set_window_size
which calls xg_frame_set_char_size.
x_set_window_size_1 is NOT being called in this case.

>  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?

No, x_set_window_size_1 never is called here.

It's the last case in xg_frame_set_char_size, which calls
gtk_window_resize FIRST, then calls x_wm_set_size_hints. I do not
understand why that works, but it appears to. (Is this another bug?
I'm seriously confused at this point).

> 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?

No. x_set_window_size_1 isn't called at all. xg_frame_set_char_size
isn't called for fullscreen requests at all.

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

No, it's all four fullscreen settings.

>> 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.

Th

> 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?

I was considering whether it might be best to remove the
no-window-manager code entirely, but I don't think we should.

>> 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.

Right. x_check_fullscreen exits very early unless the window manager
fails to support fullscreen.

> WOW when we run
> x_check_fullscreen, we emulate the behavior of a window manager by
> calculating the respective sizes ourselves.

Correct.

> 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?

I think it's that x_net_wm_state clears the fullscreen flag in the
middle of our operation.

>> 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.

I think your patch actually solves that problem: if there's no WM,
get_current_wm_state will always return FULLSCREEN_NONE, so we set the
size hints appropriately.

>>   - 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,

Again, I think it makes sense once you take into account x_net_wm_state.

>>> 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?

Missing link :-)

>> 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.

Oh, I agree, but I was sufficiently confused I thought it important to
be sure what needed changing before actually working out how to do it
cleanly.

>>> 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.

> martin