void
pgtk_iconify_frame (struct frame *f)
-/* --------------------------------------------------------------------------
- External: Iconify window
- -------------------------------------------------------------------------- */
{
+ GtkWindow *window;
+
/* Don't keep the highlight on an invisible frame. */
+
if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
- FRAME_DISPLAY_INFO (f)->highlight_frame = 0;
+ FRAME_DISPLAY_INFO (f)->highlight_frame = NULL;
+
+ /* If the frame is already iconified, return. */
if (FRAME_ICONIFIED_P (f))
return;
- block_input ();
+ /* Child frames on PGTK have no outer widgets. In that case, simply
+ refuse to iconify the frame. */
if (FRAME_GTK_OUTER_WIDGET (f))
{
if (!FRAME_VISIBLE_P (f))
gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
- gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
- SET_FRAME_VISIBLE (f, 0);
- SET_FRAME_ICONIFIED (f, true);
- unblock_input ();
- return;
- }
+ window = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
- /* Make sure the X server knows where the window should be positioned,
- in case the user deiconifies with the window manager. */
- if (!FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
- pgtk_set_offset (f, f->left_pos, f->top_pos, 0);
+ gtk_window_iconify (window);
- SET_FRAME_ICONIFIED (f, true);
- SET_FRAME_VISIBLE (f, 0);
+ /* Don't make the frame iconified here. Doing so will cause it
+ to be skipped by redisplay, until GDK says it is deiconified
+ (see window_state_event for more details). However, if the
+ window server rejects the iconification request, GDK will
+ never tell Emacs about the iconification not happening,
+ leading to the frame not being redisplayed until the next
+ window state change. */
- unblock_input ();
+ /* SET_FRAME_VISIBLE (f, 0);
+ SET_FRAME_ICONIFIED (f, true); */
+ }
}
static gboolean
/* Check if fullscreen was specified before we where mapped the
first time, i.e. from the command line. */
if (!FRAME_X_OUTPUT (f)->has_been_visible)
- {
- set_fullscreen_state (f);
- }
+ set_fullscreen_state (f);
if (!iconified)
{
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
- if (f)
- {
- if (new_state & GDK_WINDOW_STATE_FOCUSED)
- {
- if (FRAME_ICONIFIED_P (f))
- {
- /* Gnome shell does not iconify us when C-z is pressed.
- It hides the frame. So if our state says we aren't
- hidden anymore, treat it as deiconified. */
- SET_FRAME_VISIBLE (f, 1);
- SET_FRAME_ICONIFIED (f, false);
- FRAME_X_OUTPUT (f)->has_been_visible = true;
- inev.ie.kind = DEICONIFY_EVENT;
- XSETFRAME (inev.ie.frame_or_window, f);
- }
- }
- }
-
if (new_state & GDK_WINDOW_STATE_FULLSCREEN)
store_frame_param (f, Qfullscreen, Qfullboth);
else if (new_state & GDK_WINDOW_STATE_MAXIMIZED)
else
store_frame_param (f, Qfullscreen, Qnil);
+ /* The Wayland protocol provides no way for the client to know
+ whether or not one of its toplevels has actually been
+ deiconified. It only provides a request for clients to iconify a
+ toplevel, without even the ability to determine whether or not
+ the iconification request was rejected by the display server.
+
+ GDK computes the iconified state by sending a window state event
+ containing only GDK_WINDOW_STATE_ICONIFIED immediately after
+ gtk_window_iconify is called. That is error-prone if the request
+ to iconify the frame was rejected by the display server, but is
+ not the main problem here, as Wayland compositors only rarely
+ reject such requests. GDK also assumes that it can clear the
+ iconified state upon receiving the next toplevel configure event
+ from the display server. Unfortunately, such events can be sent
+ by Wayland compositors while the frame is iconified, and may also
+ not be sent upon deiconification. So, no matter what Emacs does,
+ the iconification state of a frame is likely to be wrong under
+ one situation or another. */
+
if (new_state & GDK_WINDOW_STATE_ICONIFIED)
- SET_FRAME_ICONIFIED (f, true);
+ {
+ SET_FRAME_ICONIFIED (f, true);
+ SET_FRAME_VISIBLE (f, false);
+ }
else
{
FRAME_X_OUTPUT (f)->has_been_visible = true;
inev.ie.kind = DEICONIFY_EVENT;
XSETFRAME (inev.ie.frame_or_window, f);
SET_FRAME_ICONIFIED (f, false);
+ SET_FRAME_VISIBLE (f, true);
}
if (new_state & GDK_WINDOW_STATE_STICKY)