]> git.eshelyaron.com Git - emacs.git/commitdiff
Try to improve handling of fullwidth/-height frames.
authorMartin Rudalics <rudalics@gmx.at>
Sat, 7 Feb 2015 10:51:03 +0000 (11:51 +0100)
committerMartin Rudalics <rudalics@gmx.at>
Sat, 7 Feb 2015 10:51:03 +0000 (11:51 +0100)
* frame.el (frame-notice-user-settings): Update
`frame-size-history'.
(make-frame): Update `frame-size-history'.  Call
`frame-after-make-frame'.
* faces.el (face-set-after-frame-default): Remove call to
frame-can-run-window-configuration-change-hook.
* frame.c (frame_size_history_add): New function.
(frame_inhibit_resize): Consider frame_inhibit_implied_resize
only after frame's after_make_frame slot is true.  Inhibit
resizing fullwidth-/height frames in one direction only.  Update
frame_size_history.
(adjust_frame_size): Call frame_size_history_add.
(make_frame): Initalize after_make_frame slot.
(Fmake_terminal_frame): Adjust adjust_frame_size call.
(Fcan_run_window_configuration_change_hook): Rename to
Fframe_after_make_frame.  Set after_make_frame slot.  Return
second argument.
(x_set_frame_parameters): Postpone handling fullscreen parameter
until after width and height parameters have been set.  Apply
width and height changes only if can_x_set_window_size is true.
Update frame_size_history.
(Qadjust_frame_size_1, Qadjust_frame_size_2)
(Qadjust_frame_size_3, QEmacsFrameResize, Qframe_inhibit_resize)
(Qx_set_fullscreen, Qx_check_fullscreen, Qx_set_window_size_1)
(Qxg_frame_resized, Qxg_frame_set_char_size_1)
(Qxg_frame_set_char_size_2, Qxg_frame_set_char_size_3)
(Qxg_change_toolbar_position, Qx_net_wm_state)
(Qx_handle_net_wm_state, Qtb_size_cb, Qupdate_frame_tool_bar)
(Qfree_frame_tool_bar): New symbol for updating
frame_size_history.
(Qtip_frame, Qterminal_frame): New symbols.
(Vframe_adjust_size_history): Rename to frame_size_history.
* frame.h (struct frame): Rename
can_run_window_configuration_change_hook slot to
after_make_frame.
(frame_size_history_add): Extern.
* gtkutil.c (xg_frame_resized): Call frame_size_history_add.
Don't set FRAME_PIXEL_WIDTH and FRAME_PIXEL_HEIGHT here.
(xg_frame_set_char_size): Try to preserve the status of
fullwidth/-height frames.  Call frame_size_history_add.
(tb_size_cb, update_frame_tool_bar, free_frame_tool_bar)
(xg_change_toolbar_position): Call frame_size_history_add.
* w32fns.c (x_change_tool_bar_height): Handle frame's fullscreen
status.
(Fx_create_frame): Process fullscreen parameter after frame has
been resized.
(x_create_tip_frame): Pass Qtip_frame to adjust_frame_size.
(Fx_frame_geometry): Don't pollute pure storage.
* w32term.c (w32_read_socket): For WM_WINDOWPOSCHANGED,
WM_ACTIVATE and WM_ACTIVATEAPP set frame's visibility before
calling w32fullscreen_hook.  For WM_DISPLAYCHANGE call
w32fullscreen_hook immediately.
(x_fullscreen_adjust, x_check_fullscreen): Remove.
(w32fullscreen_hook): Call change_frame_size just as with a
"normal" frame resize operation.  Call do_pending_window_change.
(x_set_window_size): Try to handle fullwidth and fullheight more
accurately.  Don't rely on w32_enable_frame_resize_hack.
(w32_enable_frame_resize_hack): Remove variable.
* widget.c (EmacsFrameResize): Remove dead code.  Call
frame_size_history_add
* window.c (run_window_configuration_change_hook): Check
f->after_make_frame instead of
f->can_run_window_configuration_change_hook.
* xfns.c (x_change_tool_bar_height): Handle frame's fullscreen status.
(Fx_create_frame): Process fullscreen parameter after frame has
been resized.
(Fx_frame_geometry): Don't pollute pure storage.
* xterm.c (x_net_wm_state, x_handle_net_wm_state): Call
frame_size_history_add.
(do_ewmh_fullscreen): Handle x_frame_normalize_before_maximize.
(x_check_fullscreen): Count in menubar when calling
XResizeWindow.  Wait for ConfigureNotify event.  Call
frame_size_history_add.
(x_set_window_size_1): Remove PIXELWISE argument.  Try to handle
changing a fullheight frame's width or a fullwidth frame's
height.  Call frame_size_history_add.
(x_set_window_size): Simplify xg_frame_set_char_size and
x_set_window_size_1 calls.
(x_frame_normalize_before_maximize): New variable.

13 files changed:
lisp/ChangeLog
lisp/faces.el
lisp/frame.el
src/ChangeLog
src/frame.c
src/frame.h
src/gtkutil.c
src/w32fns.c
src/w32term.c
src/widget.c
src/window.c
src/xfns.c
src/xterm.c

index c67113f2a61fe66f45f589f2a5da9160e1023930..a3abb1a4f1f673851a3100c9288d9fc0ca4ba59e 100644 (file)
@@ -1,3 +1,12 @@
+2015-02-07  Martin Rudalics  <rudalics@gmx.at>
+
+       * frame.el (frame-notice-user-settings): Update
+       `frame-size-history'.
+       (make-frame): Update `frame-size-history'.  Call
+       `frame-after-make-frame'.
+       * faces.el (face-set-after-frame-default): Remove call to
+       frame-can-run-window-configuration-change-hook.
+
 2015-02-06  Dmitry Gutov  <dgutov@yandex.ru>
 
        * vc/vc-cvs.el (vc-cvs-dir-status-files): Don't pass DIR to
index 22bf26267222da7a47e38d42c3910264eb4dd628..ce74c728474d229d30640561963191a57f950cf8 100644 (file)
@@ -2092,8 +2092,7 @@ frame parameters in PARAMETERS."
             (value (cdr (assq param-name parameters))))
        (if value
            (set-face-attribute (nth 1 param) frame
-                               (nth 2 param) value))))
-    (frame-can-run-window-configuration-change-hook frame t)))
+                               (nth 2 param) value))))))
 
 (defun tty-handle-reverse-video (frame parameters)
   "Handle the reverse-video frame parameter for terminal frames."
index 1d5bbf2317e24a4b1c294deaf8c13eb4bea3e93f..ecb433e8335e2ff6a462fe9dfd124a18aa2b66d5 100644 (file)
@@ -465,6 +465,16 @@ there (in decreasing order of priority)."
                (frame-set-background-mode frame-initial-frame))
              (face-set-after-frame-default frame-initial-frame)
              (setq newparms (delq new-bg newparms)))
+
+           (when (numberp (car frame-size-history))
+             (setq frame-size-history
+                   (cons (1- (car frame-size-history))
+                         (cons
+                          (list frame-initial-frame
+                                "frame-notice-user-settings"
+                                nil newparms)
+                          (cdr frame-size-history)))))
+
            (modify-frame-parameters frame-initial-frame newparms)))))
 
     ;; Restore the original buffer.
@@ -686,7 +696,7 @@ the new frame according to its own rules."
     ;; Now make the frame.
     (run-hooks 'before-make-frame-hook)
 
-;;     (setq frame-adjust-size-history '(t))
+;;     (setq frame-size-history '(1000))
 
     (setq frame
           (funcall (gui-method frame-creation-function w) params))
@@ -697,11 +707,14 @@ the new frame according to its own rules."
         (let ((val (frame-parameter oldframe param)))
           (when val (set-frame-parameter frame param val)))))
 
-    (when (eq (car frame-adjust-size-history) t)
-      (setq frame-adjust-size-history
-           (cons t (cons (list "Frame made")
-                         (cdr frame-adjust-size-history)))))
+    (when (numberp (car frame-size-history))
+      (setq frame-size-history
+           (cons (1- (car frame-size-history))
+                 (cons (list frame "make-frame")
+                       (cdr frame-size-history)))))
 
+    ;; We can run `window-configuration-change-hook' for this frame now.
+    (frame-after-make-frame frame t)
     (run-hook-with-args 'after-make-frame-functions frame)
     frame))
 
index cd72f98c1161624c05d2df67c40a3f54fae3176a..ec70cdb93a94ea1dfcc8a5a1c8306bc9ec0e7012 100644 (file)
@@ -1,3 +1,79 @@
+2015-02-07  Martin Rudalics  <rudalics@gmx.at>
+
+       * frame.c (frame_size_history_add): New function.
+       (frame_inhibit_resize): Consider frame_inhibit_implied_resize
+       only after frame's after_make_frame slot is true.  Inhibit
+       resizing fullwidth-/height frames in one direction only.  Update
+       frame_size_history.
+       (adjust_frame_size): Call frame_size_history_add.
+       (make_frame): Initalize after_make_frame slot.
+       (Fmake_terminal_frame): Adjust adjust_frame_size call.
+       (Fcan_run_window_configuration_change_hook): Rename to
+       Fframe_after_make_frame.  Set after_make_frame slot.  Return
+       second argument.
+       (x_set_frame_parameters): Postpone handling fullscreen parameter
+       until after width and height parameters have been set.  Apply
+       width and height changes only if can_x_set_window_size is true.
+       Update frame_size_history.
+       (Qadjust_frame_size_1, Qadjust_frame_size_2)
+       (Qadjust_frame_size_3, QEmacsFrameResize, Qframe_inhibit_resize)
+       (Qx_set_fullscreen, Qx_check_fullscreen, Qx_set_window_size_1)
+       (Qxg_frame_resized, Qxg_frame_set_char_size_1)
+       (Qxg_frame_set_char_size_2, Qxg_frame_set_char_size_3)
+       (Qxg_change_toolbar_position, Qx_net_wm_state)
+       (Qx_handle_net_wm_state, Qtb_size_cb, Qupdate_frame_tool_bar)
+       (Qfree_frame_tool_bar): New symbol for updating
+       frame_size_history.
+       (Qtip_frame, Qterminal_frame): New symbols.
+       (Vframe_adjust_size_history): Rename to frame_size_history.
+       * frame.h (struct frame): Rename
+       can_run_window_configuration_change_hook slot to
+       after_make_frame.
+       (frame_size_history_add): Extern.
+       * gtkutil.c (xg_frame_resized): Call frame_size_history_add.
+       Don't set FRAME_PIXEL_WIDTH and FRAME_PIXEL_HEIGHT here.
+       (xg_frame_set_char_size): Try to preserve the status of
+       fullwidth/-height frames.  Call frame_size_history_add.
+       (tb_size_cb, update_frame_tool_bar, free_frame_tool_bar)
+       (xg_change_toolbar_position): Call frame_size_history_add.
+       * w32fns.c (x_change_tool_bar_height): Handle frame's fullscreen
+       status.
+       (Fx_create_frame): Process fullscreen parameter after frame has
+       been resized.
+       (x_create_tip_frame): Pass Qtip_frame to adjust_frame_size.
+       (Fx_frame_geometry): Don't pollute pure storage.
+       * w32term.c (w32_read_socket): For WM_WINDOWPOSCHANGED,
+       WM_ACTIVATE and WM_ACTIVATEAPP set frame's visibility before
+       calling w32fullscreen_hook.  For WM_DISPLAYCHANGE call
+       w32fullscreen_hook immediately.
+       (x_fullscreen_adjust, x_check_fullscreen): Remove.
+       (w32fullscreen_hook): Call change_frame_size just as with a
+       "normal" frame resize operation.  Call do_pending_window_change.
+       (x_set_window_size): Try to handle fullwidth and fullheight more
+       accurately.  Don't rely on w32_enable_frame_resize_hack.
+       (w32_enable_frame_resize_hack): Remove variable.
+       * widget.c (EmacsFrameResize): Remove dead code.  Call
+       frame_size_history_add
+       * window.c (run_window_configuration_change_hook): Check
+       f->after_make_frame instead of
+       f->can_run_window_configuration_change_hook.
+       * xfns.c (x_change_tool_bar_height): Handle frame's fullscreen status.
+       (Fx_create_frame): Process fullscreen parameter after frame has
+       been resized.
+       (Fx_frame_geometry): Don't pollute pure storage.
+       * xterm.c (x_net_wm_state, x_handle_net_wm_state): Call
+       frame_size_history_add.
+       (do_ewmh_fullscreen): Handle x_frame_normalize_before_maximize.
+       (x_check_fullscreen): Count in menubar when calling
+       XResizeWindow.  Wait for ConfigureNotify event.  Call
+       frame_size_history_add.
+       (x_set_window_size_1): Remove PIXELWISE argument.  Try to handle
+       changing a fullheight frame's width or a fullwidth frame's
+       height.  Call frame_size_history_add.
+       (x_set_window_size): Simplify xg_frame_set_char_size and
+       x_set_window_size_1 calls.
+       (x_frame_normalize_before_maximize): New variable.
+
 2015-02-07  Paul Eggert  <eggert@cs.ucla.edu>
 
        Remove no-longer-used cursor_in_echo_area code
index 890e8972617069b00ac6b09c8c5274496a7b4bf1..96fe3778dbce0149d56461ec7dd86ceafa564849 100644 (file)
@@ -149,6 +149,33 @@ get_frame_param (register struct frame *frame, Lisp_Object prop)
   return Fcdr (tem);
 }
 
+
+void
+frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
+                       int width, int height, Lisp_Object rest)
+{
+  Lisp_Object frame;
+  int number;
+
+  XSETFRAME (frame, f);
+  if (CONSP (frame_size_history)
+      && NUMBERP (Fcar (frame_size_history))
+      && ((number = XINT (Fcar (frame_size_history))) > 0))
+    frame_size_history =
+      Fcons (make_number (number - 1),
+            Fcons (list4
+                   (frame, fun_symbol,
+                    ((width > 0)
+                     ? list4 (make_number (FRAME_TEXT_WIDTH (f)),
+                              make_number (FRAME_TEXT_HEIGHT (f)),
+                              make_number (width),
+                              make_number (height))
+                     : Qnil),
+                    rest),
+                   Fcdr (frame_size_history)));
+}
+
+
 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
    state of frame F would be affected by a vertical (horizontal if
    HORIZONTAL is true) resize.  PARAMETER is the symbol of the frame
@@ -156,11 +183,27 @@ get_frame_param (register struct frame *frame, Lisp_Object prop)
 bool
 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
 {
-  return (EQ (frame_inhibit_implied_resize, Qt)
-         || (CONSP (frame_inhibit_implied_resize)
-             && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
-         || !NILP (get_frame_param (f, Qfullscreen))
-         || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
+  Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+  bool inhibit
+    = ((f->after_make_frame
+       && (EQ (frame_inhibit_implied_resize, Qt)
+           || (CONSP (frame_inhibit_implied_resize)
+               && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))))
+       || (horizontal
+          && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullheight))
+       || (!horizontal
+          && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullwidth))
+       || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
+
+  if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
+    frame_size_history_add
+      (f, Qframe_inhibit_resize, 0, 0,
+       list5 (horizontal ? Qt : Qnil, parameter,
+             f->after_make_frame ? Qt : Qnil,
+             frame_inhibit_implied_resize,
+             fullscreen));
+
+  return inhibit;
 }
 
 static void
@@ -369,18 +412,9 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
 
   XSETFRAME (frame, f);
 
-  /* `make-frame' initializes Vframe_adjust_size_history to (Qt) and
-     strips its car when exiting.  Just in case make sure its size never
-     exceeds 100.  */
-  if (!NILP (Fconsp (Vframe_adjust_size_history))
-      && EQ (Fcar (Vframe_adjust_size_history), Qt)
-      && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
-    Vframe_adjust_size_history =
-      Fcons (Qt, Fcons (list5 (make_number (0),
-                              make_number (new_text_width),
-                              make_number (new_text_height),
-                              make_number (inhibit), parameter),
-                       Fcdr (Vframe_adjust_size_history)));
+  frame_size_history_add
+    (f, Qadjust_frame_size_1, new_text_width, new_text_height,
+     list2 (parameter, make_number (inhibit)));
 
   /* The following two values are calculated from the old window body
      sizes and any "new" settings for scroll bars, dividers, fringes and
@@ -391,7 +425,7 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
     = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
 
   if (inhibit >= 2 && inhibit <= 4)
-    /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay
+    /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
        within the limits and either frame_inhibit_resize tells us to do
        so or INHIBIT equals 4.  */
     {
@@ -449,16 +483,10 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
       else if (inhibit_vertical)
        new_text_height = old_text_height;
 
-      if (!NILP (Fconsp (Vframe_adjust_size_history))
-         && EQ (Fcar (Vframe_adjust_size_history), Qt)
-         && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
-       Vframe_adjust_size_history =
-         Fcons (Qt, Fcons (list5 (make_number (1),
-                                  make_number (new_text_width),
-                                  make_number (new_text_height),
-                                  make_number (new_cols),
-                                  make_number (new_lines)),
-                           Fcdr (Vframe_adjust_size_history)));
+      frame_size_history_add
+       (f, Qadjust_frame_size_2, new_text_width, new_text_height,
+        list2 (inhibit_horizontal ? Qt : Qnil,
+               inhibit_vertical ? Qt : Qnil));
 
       x_set_window_size (f, 0, new_text_width, new_text_height, 1);
       f->resized_p = true;
@@ -525,6 +553,11 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
        FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
     }
 
+  frame_size_history_add
+    (f, Qadjust_frame_size_3, new_text_width, new_text_height,
+     list4 (make_number (old_pixel_width), make_number (old_pixel_height),
+           make_number (new_pixel_width), make_number (new_pixel_height)));
+
   /* Assign new sizes.  */
   FRAME_TEXT_WIDTH (f) = new_text_width;
   FRAME_TEXT_HEIGHT (f) = new_text_height;
@@ -533,17 +566,6 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
   SET_FRAME_COLS (f, new_cols);
   SET_FRAME_LINES (f, new_lines);
 
-  if (!NILP (Fconsp (Vframe_adjust_size_history))
-      && EQ (Fcar (Vframe_adjust_size_history), Qt)
-      && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
-    Vframe_adjust_size_history =
-      Fcons (Qt, Fcons (list5 (make_number (2),
-                              make_number (new_text_width),
-                              make_number (new_text_height),
-                              make_number (new_cols),
-                              make_number (new_lines)),
-                       Fcdr (Vframe_adjust_size_history)));
-
   {
     struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
     int text_area_x, text_area_y, text_area_width, text_area_height;
@@ -608,7 +630,7 @@ make_frame (bool mini_p)
   f->redisplay = true;
   f->garbaged = true;
   f->can_x_set_window_size = false;
-  f->can_run_window_configuration_change_hook = false;
+  f->after_make_frame = false;
   f->tool_bar_redisplayed_once = false;
   f->column_width = 1;  /* !FRAME_WINDOW_P value.  */
   f->line_height = 1;  /* !FRAME_WINDOW_P value.  */
@@ -1020,7 +1042,8 @@ affects all frames on the same terminal device.  */)
   {
     int width, height;
     get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
-    adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil);
+    adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
+                      5, 0, Qterminal_frame);
   }
 
   adjust_frame_glyphs (f);
@@ -2260,24 +2283,25 @@ If there is no window system support, this function does nothing.  */)
   return Qnil;
 }
 
-DEFUN ("frame-can-run-window-configuration-change-hook",
-       Fcan_run_window_configuration_change_hook,
-       Scan_run_window_configuration_change_hook, 2, 2, 0,
-       doc: /* Whether `window-configuration-change-hook' is run for frame FRAME.
-FRAME nil means use the selected frame.  Second argument ALLOW non-nil
+DEFUN ("frame-after-make-frame",
+       Fframe_after_make_frame,
+       Sframe_after_make_frame, 2, 2, 0,
+       doc: /* Mark FRAME as made.
+FRAME nil means use the selected frame.  Second argument MADE non-nil
 means functions on `window-configuration-change-hook' are called
-whenever the window configuration of FRAME changes.  ALLOW nil means
+whenever the window configuration of FRAME changes.  MADE nil means
 these functions are not called.
 
-This function is currently called by `face-set-after-frame-default' only
-and should be otherwise used with utter care to avoid that running
-functions on `window-configuration-change-hook' is impeded forever.  */)
-  (Lisp_Object frame, Lisp_Object allow)
+This function is currently called by `make-frame' only and should be
+otherwise used with utter care to avoid that running functions on
+`window-configuration-change-hook' is impeded forever.  */)
+  (Lisp_Object frame, Lisp_Object made)
 {
   struct frame *f = decode_live_frame (frame);
 
-  f->can_run_window_configuration_change_hook = NILP (allow) ? false : true;
-  return Qnil;
+  f->after_make_frame = NILP (made) ? false : true;
+
+  return made;
 }
 
 \f
@@ -3037,7 +3061,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
      set them both at once.  So we wait until we've looked at the
      entire list before we set them.  */
   int width IF_LINT (= 0), height IF_LINT (= 0);
-  bool width_change = 0, height_change = 0;
+  bool width_change = false, height_change = false;
 
   /* Same here.  */
   Lisp_Object left, top;
@@ -3045,6 +3069,10 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
   /* Same with these.  */
   Lisp_Object icon_left, icon_top;
 
+  /* And with this.  */
+  Lisp_Object fullscreen;
+  bool fullscreen_change = false;
+
   /* Record in these vectors all the parms specified.  */
   Lisp_Object *parms;
   Lisp_Object *values;
@@ -3138,6 +3166,11 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
        icon_top = val;
       else if (EQ (prop, Qicon_left))
        icon_left = val;
+      else if (EQ (prop, Qfullscreen))
+       {
+         fullscreen = val;
+         fullscreen_change = true;
+       }
       else if (EQ (prop, Qforeground_color)
               || EQ (prop, Qbackground_color)
               || EQ (prop, Qfont))
@@ -3218,14 +3251,14 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
           that here since otherwise a size change implied by an
           intermittent font change may get lost as in Bug#17142.  */
        if (!width_change)
-         width = (f->new_width
+         width = ((f->can_x_set_window_size && f->new_width)
                   ? (f->new_pixelwise
                      ? f->new_width
                      : (f->new_width * FRAME_COLUMN_WIDTH (f)))
                   : FRAME_TEXT_WIDTH (f));
 
        if (!height_change)
-         height = (f->new_height
+         height = ((f->can_x_set_window_size && f->new_height)
                    ? (f->new_pixelwise
                       ? f->new_height
                       : (f->new_height * FRAME_LINE_HEIGHT (f)))
@@ -3298,6 +3331,20 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
        /* Actually set that position, and convert to absolute.  */
        x_set_offset (f, leftpos, toppos, -1);
       }
+
+    if (fullscreen_change)
+      {
+       Lisp_Object old_value = get_frame_param (f, Qfullscreen);
+
+       frame_size_history_add
+         (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
+
+       store_frame_param (f, Qfullscreen, fullscreen);
+       if (!EQ (fullscreen, old_value))
+         x_set_fullscreen (f, fullscreen, old_value);
+      }
+
+
 #ifdef HAVE_X_WINDOWS
     if ((!NILP (icon_left) || !NILP (icon_top))
        && ! (icon_left_no_change && icon_top_no_change))
@@ -4834,11 +4881,33 @@ syms_of_frame (void)
   DEFSYM (Qtool_bar_external, "tool-bar-external");
   DEFSYM (Qtool_bar_size, "tool-bar-size");
   DEFSYM (Qframe_inner_size, "frame-inner-size");
+  /* The following are used for frame_size_history.  */
+  DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
+  DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
+  DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
+  DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
+  DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
+  DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
+  DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
+  DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
+  DEFSYM (Qxg_frame_resized, "xg-frame-resized");
+  DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
+  DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
+  DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
+  DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
+  DEFSYM (Qx_net_wm_state, "x-net-wm-state");
+  DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
+  DEFSYM (Qtb_size_cb, "tb-size-cb");
+  DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
+  DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
+
   DEFSYM (Qchange_frame_size, "change-frame-size");
   DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
   DEFSYM (Qset_window_configuration, "set-window-configuration");
   DEFSYM (Qx_create_frame_1, "x-create-frame-1");
   DEFSYM (Qx_create_frame_2, "x-create-frame-2");
+  DEFSYM (Qtip_frame, "tip-frame");
+  DEFSYM (Qterminal_frame, "terminal-frame");
 
 #ifdef HAVE_NS
   DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
@@ -5106,9 +5175,22 @@ even if this option is non-nil.  */);
   frame_inhibit_implied_resize = Qt;
 #endif
 
-  DEFVAR_LISP ("frame-adjust-size-history", Vframe_adjust_size_history,
-               doc: /* History of frame size adjustments.  */);
-  Vframe_adjust_size_history = Qnil;
+  DEFVAR_LISP ("frame-size-history", frame_size_history,
+               doc: /* History of frame size adjustments.
+If non-nil, list recording frame size adjustment.  Adjustments are
+recorded only if the first element of this list is a positive number.
+Adding an adjustment decrements that number by one.
+
+The remaining elements are the adjustments.  Each adjustment is a list
+of four elements `frame', `function', `sizes' and `more'.  `frame' is
+the affected frame and `function' the invoking function.  `sizes' is
+usually a list of four elements `old-width', `old-height', `new-width'
+and `new-height' representing the old and new sizes recorded/requested
+by `function'.  `more' is a list with additional information.
+
+The function `frame--size-history' displays the value of this variable
+in a more readable form.  */);
+    frame_size_history = Qnil;
 
   staticpro (&Vframe_list);
 
@@ -5141,7 +5223,7 @@ even if this option is non-nil.  */);
   defsubr (&Sraise_frame);
   defsubr (&Slower_frame);
   defsubr (&Sx_focus_frame);
-  defsubr (&Scan_run_window_configuration_change_hook);
+  defsubr (&Sframe_after_make_frame);
   defsubr (&Sredirect_frame_focus);
   defsubr (&Sframe_focus);
   defsubr (&Sframe_parameters);
index 0c08d12c92eedc555b85f3fd5167cedb402bfc0c..6f5de3f5689ffe9c7939cf4515db00a70d73c0ac 100644 (file)
@@ -332,9 +332,8 @@ struct frame
      frame.  */
   bool_bf can_x_set_window_size : 1;
 
-  /* True means run_window_configuration_change_hook can be processed
-     for this frame.  */
-  bool_bf can_run_window_configuration_change_hook : 1;
+  /* Set to true after this frame was made by `make-frame'.  */
+  bool_bf after_make_frame : 1;
 
   /* True means tool bar has been redisplayed at least once in current
      session.  */
@@ -392,9 +391,9 @@ struct frame
   int left_pos, top_pos;
 
   /* Total width of this frame (including fringes, vertical scroll bar
-     and internal border widths) and total height (including menu bar,
-     tool bar, horizontal scroll bar and internal border widths) in
-     pixels.  */
+     and internal border widths) and total height (including internal
+     menu and tool bars, horizontal scroll bar and internal border
+     widths) in pixels.  */
   int pixel_width, pixel_height;
 
   /* These many pixels are the difference between the outer window (i.e. the
@@ -1124,6 +1123,8 @@ extern void frame_make_pointer_visible (struct frame *);
 extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object);
 extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object);
 extern void adjust_frame_size (struct frame *, int, int, int, bool, Lisp_Object);
+extern void frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
+                                   int width, int height, Lisp_Object rest);
 
 extern Lisp_Object Vframe_list;
 
index 21f3cb15e66eb298ecace15b9d45ed0603a34217..063e88262d97ecec78730e0bcb97a7159717e6fe 100644 (file)
@@ -886,23 +886,25 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
   if (pixelwidth == -1 && pixelheight == -1)
     {
       if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f)))
-          gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
-                                   0, 0,
-                                   &pixelwidth, &pixelheight);
-      else return;
+       gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
+                                0, 0, &pixelwidth, &pixelheight);
+      else
+       return;
     }
 
-
   width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth);
   height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight);
 
+  frame_size_history_add
+    (f, Qxg_frame_resized, width, height, Qnil);
+
   if (width != FRAME_TEXT_WIDTH (f)
       || height != FRAME_TEXT_HEIGHT (f)
       || pixelwidth != FRAME_PIXEL_WIDTH (f)
       || pixelheight != FRAME_PIXEL_HEIGHT (f))
     {
-      FRAME_PIXEL_WIDTH (f) = pixelwidth;
-      FRAME_PIXEL_HEIGHT (f) = pixelheight;
+/**       FRAME_PIXEL_WIDTH (f) = pixelwidth; **/
+/**       FRAME_PIXEL_HEIGHT (f) = pixelheight; **/
 
       xg_clear_under_internal_border (f);
       change_frame_size (f, width, height, 0, 1, 0, 1);
@@ -921,24 +923,71 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
 {
   int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
   int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
+  Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+  gint gwidth, gheight;
 
   if (FRAME_PIXEL_HEIGHT (f) == 0)
     return;
 
+  gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                      &gwidth, &gheight);
+
   /* Do this before resize, as we don't know yet if we will be resized.  */
   xg_clear_under_internal_border (f);
 
-  /* Must resize our top level widget.  Font size may have changed,
-     but not rows/cols.  */
-  gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                     pixelwidth + FRAME_TOOLBAR_WIDTH (f),
-                    pixelheight + FRAME_TOOLBAR_HEIGHT (f)
-                    + FRAME_MENUBAR_HEIGHT (f));
-  x_wm_set_size_hint (f, 0, 0);
+  /* Resize the top level widget so rows and columns remain constant.
+
+     When the frame is fullheight and we only want to change the width
+     or it is fullwidth and we only want to change the height we should
+     be able to preserve the fullscreen property.  However, due to the
+     fact that we have to send a resize request anyway, the window
+     manager will abolish it.  At least the respective size should
+     remain unchanged but giving the frame back its normal size will
+     be broken ... */
+  if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
+    {
+      frame_size_history_add
+       (f, Qxg_frame_set_char_size_1, width, height,
+        list2 (make_number (gheight),
+               make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
+                            + FRAME_MENUBAR_HEIGHT (f))));
+
+      gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                        gwidth,
+                        pixelheight + FRAME_TOOLBAR_HEIGHT (f)
+                        + FRAME_MENUBAR_HEIGHT (f));
+    }
+  else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
+    {
+      frame_size_history_add
+       (f, Qxg_frame_set_char_size_2, width, height,
+        list2 (make_number (gwidth),
+               make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f))));
+
+      gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                        pixelwidth + FRAME_TOOLBAR_WIDTH (f),
+                        gheight);
+    }
+
+  else
+    {
+      frame_size_history_add
+       (f, Qxg_frame_set_char_size_3, width, height,
+        list2 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
+               make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
+                            + FRAME_MENUBAR_HEIGHT (f))));
+
+      gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                        pixelwidth + FRAME_TOOLBAR_WIDTH (f),
+                        pixelheight + FRAME_TOOLBAR_HEIGHT (f)
+                        + FRAME_MENUBAR_HEIGHT (f));
+      fullscreen = Qnil;
+    }
 
   SET_FRAME_GARBAGED (f);
   cancel_mouse_face (f);
 
+  x_wm_set_size_hint (f, 0, 0);
   /* We can not call change_frame_size for a mapped frame,
      we can not set pixel width/height either.  The window manager may
      override our resize request, XMonad does this all the time.
@@ -952,9 +1001,17 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
       (void)gtk_events_pending ();
       gdk_flush ();
       x_wait_for_event (f, ConfigureNotify);
+
+      if (!NILP (fullscreen))
+       /* Try to restore fullscreen state.  */
+       {
+         store_frame_param (f, Qfullscreen, fullscreen);
+         x_set_fullscreen (f, fullscreen, fullscreen);
+       }
     }
   else
-    adjust_frame_size (f, -1, -1, 5, 0, Qxg_frame_set_char_size);
+    adjust_frame_size (f, width, height, 5, 0, Qxg_frame_set_char_size);
+
 }
 
 /* Handle height/width changes (i.e. add/remove/move menu/toolbar).
@@ -4214,8 +4271,12 @@ tb_size_cb (GtkWidget    *widget,
      allocated between widgets, it may get another.  So we must update
      size hints if tool bar size changes.  Seen on Fedora 18 at least.  */
   struct frame *f = user_data;
+
   if (xg_update_tool_bar_sizes (f))
-    adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
+    {
+      frame_size_history_add (f, Qtb_size_cb, 0, 0, Qnil);
+      adjust_frame_size (f, -1, -1, 5, 0, Qtool_bar_lines);
+    }
 }
 
 /* Create a tool bar for frame F.  */
@@ -4489,10 +4550,11 @@ xg_update_tool_bar_sizes (struct frame *f)
       FRAME_TOOLBAR_RIGHT_WIDTH (f) = nr;
       FRAME_TOOLBAR_TOP_HEIGHT (f) = nt;
       FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = nb;
-      return 1;
-    }
 
-  return 0;
+      return true;
+    }
+  else
+    return false;
 }
 
 static char *
@@ -4815,7 +4877,10 @@ update_frame_tool_bar (struct frame *f)
         xg_pack_tool_bar (f, FRAME_TOOL_BAR_POSITION (f));
       gtk_widget_show_all (x->toolbar_widget);
       if (xg_update_tool_bar_sizes (f))
-       adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
+       {
+         frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
+         adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
+       }
     }
 
   unblock_input ();
@@ -4863,6 +4928,7 @@ free_frame_tool_bar (struct frame *f)
                              NULL);
         }
 
+      frame_size_history_add (f, Qfree_frame_tool_bar, 0, 0, Qnil);
       adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
 
       unblock_input ();
@@ -4892,8 +4958,13 @@ xg_change_toolbar_position (struct frame *f, Lisp_Object pos)
 
   xg_pack_tool_bar (f, pos);
   g_object_unref (top_widget);
+
   if (xg_update_tool_bar_sizes (f))
-    adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
+    {
+      frame_size_history_add (f, Qxg_change_toolbar_position, 0, 0, Qnil);
+      adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
+    }
+
 
   unblock_input ();
 }
index 8435270438d233b14af80e987eaac8c9068d5a60..08000d87d381471fa70631ea049144e975d2f906 100644 (file)
@@ -1722,6 +1722,7 @@ x_change_tool_bar_height (struct frame *f, int height)
   int old_height = FRAME_TOOL_BAR_HEIGHT (f);
   int lines = (height + unit - 1) / unit;
   int old_text_height = FRAME_TEXT_HEIGHT (f);
+  Lisp_Object fullscreen;
 
   /* Make sure we redisplay all windows in this frame.  */
   windows_or_buffers_changed = 23;
@@ -1746,7 +1747,10 @@ x_change_tool_bar_height (struct frame *f, int height)
   f->n_tool_bar_rows = 0;
 
   adjust_frame_size (f, -1, -1,
-                    (!f->tool_bar_redisplayed_once ? 1
+                    ((!f->tool_bar_redisplayed_once
+                      && (NILP (fullscreen =
+                                get_frame_param (f, Qfullscreen))
+                          || EQ (fullscreen, Qfullwidth))) ? 1
                      : (old_height == 0 || height == 0) ? 2
                      : 4),
                     false, Qtool_bar_lines);
@@ -4668,8 +4672,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
                       "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
   x_default_parameter (f, parameters, Qtitle, Qnil,
                       "title", "Title", RES_TYPE_STRING);
-  x_default_parameter (f, parameters, Qfullscreen, Qnil,
-                      "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
 
   f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
   f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
@@ -4728,6 +4730,12 @@ This function is an internal primitive--use `make-frame' instead.  */)
   x_wm_set_size_hint (f, window_prompting, false);
   unblock_input ();
 
+  /* Process fullscreen parameter here in the hope that normalizing a
+     fullheight/fullwidth frame will produce the size set by the last
+     adjust_frame_size call.  */
+  x_default_parameter (f, parameters, Qfullscreen, Qnil,
+                      "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
+
   /* Make the window appear on the frame and enable display, unless
      the caller says not to.  However, with explicit parent, Emacs
      cannot control visibility, so don't try.  */
@@ -5832,7 +5840,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
   SET_FRAME_COLS (f, 0);
   SET_FRAME_LINES (f, 0);
   adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
-                    height * FRAME_LINE_HEIGHT (f), 0, true, Qnil);
+                    height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7558,7 +7566,7 @@ elements (all size values are in pixels).
     menu_bar_height = single_bar_height;
 
   return
-    listn (CONSTYPE_PURE, 10,
+    listn (CONSTYPE_HEAP, 10,
           Fcons (Qframe_position,
                  Fcons (make_number (frame_outer_edges.left),
                         make_number (frame_outer_edges.top))),
index 251c46c73cf2c864603c8a37607900c1897398a3..fb9d2388d6b730135f311ce3c2cd585b49016498 100644 (file)
@@ -3344,8 +3344,6 @@ static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object
                                                   enum scroll_bar_part *,
                                                   Lisp_Object *, Lisp_Object *,
                                                   Time *);
-static void x_check_fullscreen (struct frame *);
-
 static void
 w32_define_cursor (Window window, Cursor cursor)
 {
@@ -4989,8 +4987,12 @@ w32_read_socket (struct terminal *terminal,
                 sets the WAIT flag.  */
              if ((msg.msg.message == WM_WINDOWPOSCHANGED || msg.msg.wParam)
                  && (f->want_fullscreen & FULLSCREEN_WAIT))
-               w32fullscreen_hook (f);
-             x_check_fullscreen (f);
+               {
+                 /* Must set visibility right here since otherwise
+                    w32fullscreen_hook returns immediately.  */
+                 SET_FRAME_VISIBLE (f, 1);
+                 w32fullscreen_hook (f);
+               }
            }
          check_visibility = 1;
          break;
@@ -5269,11 +5271,18 @@ w32_read_socket (struct terminal *terminal,
 
          if (f)
            {
+             Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+
              dpyinfo->n_cbits = msg.msg.wParam;
              /* The new display could have a different resolution, in
-                which case we must reconsider what fullscreen
-                means.  */
-             x_check_fullscreen (f);
+                which case we must reconsider what fullscreen means.
+                The following code is untested yet.  */
+             if (!NILP (fullscreen))
+               {
+                 x_set_fullscreen (f, fullscreen, fullscreen);
+                 w32fullscreen_hook (f);
+               }
+
              DebPrint (("display change: %d %d\n",
                         (short) LOWORD (msg.msg.lParam),
                         (short) HIWORD (msg.msg.lParam)));
@@ -5959,75 +5968,6 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
   unblock_input ();
 }
 
-/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
-   wanted positions of the WM window (not Emacs window).
-   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
-   window (FRAME_X_WINDOW).
- */
-
-static void
-x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos)
-{
-  int newwidth = FRAME_COLS (f);
-  int newheight = FRAME_LINES (f);
-  Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
-
-  *top_pos = f->top_pos;
-  *left_pos = f->left_pos;
-
-  if (f->want_fullscreen & FULLSCREEN_HEIGHT)
-    {
-      int ph;
-
-      ph = x_display_pixel_height (dpyinfo);
-      newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
-      ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
-      newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
-      *top_pos = 0;
-    }
-
-  if (f->want_fullscreen & FULLSCREEN_WIDTH)
-    {
-      int pw;
-
-      pw = x_display_pixel_width (dpyinfo);
-      newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
-      pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
-      newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
-      *left_pos = 0;
-    }
-
-  *width = newwidth;
-  *height = newheight;
-}
-
-/* Check if we need to resize the frame due to a fullscreen request.
-   If so needed, resize the frame.  */
-static void
-x_check_fullscreen (struct frame *f)
-{
-  if (f->want_fullscreen & FULLSCREEN_BOTH)
-    {
-      int width, height, ign;
-
-      x_real_positions (f, &f->left_pos, &f->top_pos);
-
-      x_fullscreen_adjust (f, &width, &height, &ign, &ign);
-
-      /* We do not need to move the window, it shall be taken care of
-         when setting WM manager hints.  */
-      if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
-        {
-          change_frame_size (f, width, height, 0, 1, 0, 0);
-          SET_FRAME_GARBAGED (f);
-          cancel_mouse_face (f);
-
-          /* Wait for the change of frame size to occur.  */
-          f->want_fullscreen |= FULLSCREEN_WAIT;
-        }
-    }
-}
-
 static void
 w32fullscreen_hook (struct frame *f)
 {
@@ -6074,6 +6014,10 @@ w32fullscreen_hook (struct frame *f)
           SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
                         rect.right - rect.left, rect.bottom - rect.top,
                         SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
+         change_frame_size
+           (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, rect.right - rect.left),
+            FRAME_PIXEL_TO_TEXT_HEIGHT (f, rect.bottom - rect.top),
+            0, 1, 0, 1);
         }
       else
         {
@@ -6082,10 +6026,39 @@ w32fullscreen_hook (struct frame *f)
                               FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
           SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
                         rect.right - rect.left, rect.bottom - rect.top, 0);
+
+         if (f->want_fullscreen == FULLSCREEN_WIDTH)
+           {
+             int border_width = GetSystemMetrics (SM_CXFRAME);
+
+             change_frame_size
+               (f, (FRAME_PIXEL_TO_TEXT_WIDTH
+                    (f, rect.right - rect.left - 2 * border_width)),
+                0, 0, 1, 0, 1);
+           }
+         else
+           {
+             int border_height = GetSystemMetrics (SM_CYFRAME);
+             /* Won't work for wrapped menu bar.  */
+             int menu_bar_height = GetSystemMetrics (SM_CYMENU);
+             int title_height = GetSystemMetrics (SM_CYCAPTION);
+
+             change_frame_size
+               (f, 0, (FRAME_PIXEL_TO_TEXT_HEIGHT
+                       (f, rect.bottom - rect.top - 2 * border_height
+                        - title_height - menu_bar_height)),
+                0, 1, 0, 1);
+           }
         }
 
       f->want_fullscreen = FULLSCREEN_NONE;
       unblock_input ();
+
+      if (f->want_fullscreen == FULLSCREEN_BOTH
+         || f->want_fullscreen == FULLSCREEN_WIDTH
+         || f->want_fullscreen == FULLSCREEN_HEIGHT)
+       do_pending_window_change (0);
+
     }
   else
     f->want_fullscreen |= FULLSCREEN_WAIT;
@@ -6101,6 +6074,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
                   int width, int height, bool pixelwise)
 {
   int pixelwidth, pixelheight;
+  Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
   RECT rect;
 
   block_input ();
@@ -6119,7 +6093,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
   if (w32_add_wrapped_menu_bar_lines)
     {
       /* When the menu bar wraps sending a SetWindowPos shrinks the
-        height of the frame when the wrapped menu bar lines are not
+        height of the frame then the wrapped menu bar lines are not
         accounted for (Bug#15174 and Bug#18720).  Here we add these
         extra lines to the frame height.  */
       MENUBARINFO info;
@@ -6143,9 +6117,6 @@ x_set_window_size (struct frame *f, bool change_gravity,
   f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, false);
 
-  f->want_fullscreen = FULLSCREEN_NONE;
-  w32fullscreen_hook (f);
-
   rect.left = rect.top = 0;
   rect.right = pixelwidth;
   rect.bottom = pixelheight;
@@ -6153,45 +6124,45 @@ x_set_window_size (struct frame *f, bool change_gravity,
   AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
                    FRAME_EXTERNAL_MENU_BAR (f));
 
-  my_set_window_pos (FRAME_W32_WINDOW (f),
-                    NULL,
-                    0, 0,
-                    rect.right - rect.left,
-                    rect.bottom - rect.top,
-                    SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
-
-  /* If w32_enable_frame_resize_hack is non-nil, immediately apply the
-     new pixel sizes to the frame and its subwindows.
-
-     Jason Rumney earlier refused to call change_frame_size right here
-     with the following argument:
-
-     The following mirrors what is done in xterm.c. It appears to be for
-     informing lisp of the new size immediately, while the actual resize
-     will happen asynchronously. But on Windows, the menu bar
-     automatically wraps when the frame is too narrow to contain it, and
-     that causes any calculations made here to come out wrong.  The end
-     is some nasty buggy behavior, including the potential loss of the
-     minibuffer.
-
-     Disabling this code is either not sufficient to fix the problems
-     completely, or it causes fresh problems, but at least it removes
-     the most problematic symptom of the minibuffer becoming unusable.
-
-     However, as the discussion about how to handle frame size
-     parameters on Windows (Bug#1348, Bug#16028) shows, that cure seems
-     worse than the disease.  In particular, menu bar wrapping looks
-     like a non-issue - maybe so because Windows eventually gets back to
-     us with the correct client rectangle anyway.  But we have to avoid
-     calling change_frame_size with a delta of less than one canoncial
-     character size when frame_resize_pixelwise is nil, as explained in
-     the comment above.  */
-
-  if (w32_enable_frame_resize_hack)
+  if (!(f->after_make_frame)
+      && !(f->want_fullscreen & FULLSCREEN_WAIT)
+      && FRAME_VISIBLE_P (f))
+    {
+      RECT window_rect;
+
+      GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
 
+      if (EQ (fullscreen, Qmaximized)
+         || EQ (fullscreen, Qfullboth)
+         || EQ (fullscreen, Qfullwidth))
+       {
+         rect.left = window_rect.left;
+         rect.right = window_rect.right;
+         pixelwidth = 0;
+       }
+      if (EQ (fullscreen, Qmaximized)
+         || EQ (fullscreen, Qfullboth)
+         || EQ (fullscreen, Qfullheight))
+       {
+         rect.top = window_rect.top;
+         rect.bottom = window_rect.bottom;
+         pixelheight = 0;
+       }
+    }
+
+  if (pixelwidth > 0 || pixelheight > 0)
     {
-      change_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth),
-                        FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight),
+      my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
+                        0, 0,
+                        rect.right - rect.left,
+                        rect.bottom - rect.top,
+                        SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+
+      change_frame_size (f,
+                        ((pixelwidth == 0)
+                            ? 0 : FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth)),
+                        ((pixelheight == 0)
+                         ? 0 : FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)),
                         0, 1, 0, 1);
       SET_FRAME_GARBAGED (f);
 
@@ -7102,7 +7073,7 @@ Windows 8.  It is set to nil on Windows 9X.  */);
   w32_unicode_filenames = 0;
 
 
-  /* FIXME: The following two variables will be (hopefully) removed
+  /* FIXME: The following variable will be (hopefully) removed
      before Emacs 25.1 gets released.  */
 
   DEFVAR_BOOL ("w32-add-wrapped-menu-bar-lines",
@@ -7116,16 +7087,6 @@ wrapped menu bar lines when sending frame resize requests to the Windows
 API.  */);
   w32_add_wrapped_menu_bar_lines = 1;
 
-  DEFVAR_BOOL ("w32-enable-frame-resize-hack",
-              w32_enable_frame_resize_hack,
-     doc: /* Non-nil means enable hack for frame resizing on Windows.
-A value of nil means to resize frames by sending a corresponding request
-to the Windows API and changing the pixel sizes of the frame and its
-windows after the latter calls back.  If this is non-nil, Emacs changes
-the pixel sizes of the frame and its windows at the time it sends the
-resize request to the API.  */);
-  w32_enable_frame_resize_hack = 1;
-
   /* Tell Emacs about this window system.  */
   Fprovide (Qw32, Qnil);
 }
index c4d69407176355c4d76c8534527e0a5a62b9c439..acf559f313b981a2644af69975956968d45ac3bd 100644 (file)
@@ -460,7 +460,7 @@ update_wm_hints (EmacsFrame ew)
   base_width = (wmshell->core.width - ew->core.width
                + (rounded_width - (char_width * cw)));
   base_height = (wmshell->core.height - ew->core.height
-               + (rounded_height - (char_height * ch)));
+                + (rounded_height - (char_height * ch)));
 
   /* This is kind of sleazy, but I can't see how else to tell it to
      make it mark the WM_SIZE_HINTS size as user specified.
@@ -573,39 +573,20 @@ EmacsFrameResize (Widget widget)
 {
   EmacsFrame ew = (EmacsFrame)widget;
   struct frame *f = ew->emacs_frame.frame;
+  int width, height;
 
-  /* Always process resize requests pixelwise.  Frame maximizing
-     should work even when frame_resize_pixelwise is nil.  */
-  if (true || frame_resize_pixelwise)
-    {
-      int width, height;
-
-      pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height);
-      change_frame_size (f, width, height, 0, 1, 0, 1);
+  pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height);
 
-      update_wm_hints (ew);
-      update_various_frame_slots (ew);
+  frame_size_history_add
+    (f, QEmacsFrameResize, width, height,
+     list2 (make_number (ew->core.width), make_number (ew->core.height)));
 
-      cancel_mouse_face (f);
-    }
-  else
-    {
-      struct x_output *x = f->output_data.x;
-      int columns, rows;
+  change_frame_size (f, width, height, 0, 1, 0, 1);
 
-      pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
-      if (columns != FRAME_COLS (f)
-         || rows != FRAME_LINES (f)
-         || ew->core.width != FRAME_PIXEL_WIDTH (f)
-         || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
-       {
-         change_frame_size (f, columns, rows, 0, 1, 0, 0);
-         update_wm_hints (ew);
-         update_various_frame_slots (ew);
+  update_wm_hints (ew);
+  update_various_frame_slots (ew);
 
-         cancel_mouse_face (f);
-       }
-    }
+  cancel_mouse_face (f);
 }
 
 static XtGeometryResult
index 2f44bf78304b5da98cf7f0dad1bf2021ea425ce9..293140041a9e9fa081ce4d141bceb9ca0e70d189 100644 (file)
@@ -3329,7 +3329,7 @@ run_window_configuration_change_hook (struct frame *f)
 
   if (NILP (Vrun_hooks)
       || !(f->can_x_set_window_size)
-      || !(f->can_run_window_configuration_change_hook))
+      || !(f->after_make_frame))
     return;
 
   /* Use the right buffer.  Matters when running the local hooks.  */
index 65eb6b497f2aab0557e6835240d757b28d5aa40d..e667e71b56328375d6bc9f01a541514715140f70 100644 (file)
@@ -1095,6 +1095,7 @@ x_change_tool_bar_height (struct frame *f, int height)
   int unit = FRAME_LINE_HEIGHT (f);
   int old_height = FRAME_TOOL_BAR_HEIGHT (f);
   int lines = (height + unit - 1) / unit;
+  Lisp_Object fullscreen;
 
   /* Make sure we redisplay all windows in this frame.  */
   windows_or_buffers_changed = 60;
@@ -1126,7 +1127,10 @@ x_change_tool_bar_height (struct frame *f, int height)
   f->n_tool_bar_rows = 0;
 
   adjust_frame_size (f, -1, -1,
-                    (!f->tool_bar_redisplayed_once ? 1
+                    ((!f->tool_bar_redisplayed_once
+                      && (NILP (fullscreen =
+                                get_frame_param (f, Qfullscreen))
+                          || EQ (fullscreen, Qfullwidth))) ? 1
                      : (old_height == 0 || height == 0) ? 2
                      : 4),
                     false, Qtool_bar_lines);
@@ -3180,9 +3184,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
                       "title", "Title", RES_TYPE_STRING);
   x_default_parameter (f, parms, Qwait_for_wm, Qt,
                       "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
-  x_default_parameter (f, parms, Qfullscreen, Qnil,
-                      "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
-  x_default_parameter (f, parms, Qtool_bar_position,
+ x_default_parameter (f, parms, Qtool_bar_position,
                        FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
 
   /* Compute the size of the X window.  */
@@ -3259,6 +3261,12 @@ This function is an internal primitive--use `make-frame' instead.  */)
   x_wm_set_size_hint (f, window_prompting, false);
   unblock_input ();
 
+  /* Process fullscreen parameter here in the hope that normalizing a
+     fullheight/fullwidth frame will produce the size set by the last
+     adjust_frame_size call.  */
+  x_default_parameter (f, parms, Qfullscreen, Qnil,
+                      "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
+
   /* Make the window appear on the frame and enable display, unless
      the caller says not to.  However, with explicit parent, Emacs
      cannot control visibility, so don't try.  */
@@ -4318,7 +4326,7 @@ elements (all size values are in pixels).
     inner_height -= tool_bar_height;
 
   return
-    listn (CONSTYPE_PURE, 10,
+    listn (CONSTYPE_HEAP, 10,
           Fcons (Qframe_position,
                  Fcons (make_number (f->left_pos), make_number (f->top_pos))),
           Fcons (Qframe_outer_size,
index 3955d027a528c832ab8375659ce47452c7248dcb..6a63a454baca99b52c2b94d08ecde04a25c9b575 100644 (file)
@@ -212,7 +212,7 @@ enum xembed_message
   };
 
 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
-static void x_set_window_size_1 (struct frame *, bool, int, int, bool);
+static void x_set_window_size_1 (struct frame *, bool, int, int);
 static void x_raise_frame (struct frame *);
 static void x_lower_frame (struct frame *);
 static const XColor *x_color_cells (Display *, int *);
@@ -6575,6 +6575,10 @@ x_net_wm_state (struct frame *f, Window window)
       break;
     }
 
+  frame_size_history_add
+    (f, Qx_net_wm_state, 0, 0,
+     list2 (get_frame_param (f, Qfullscreen), lval));
+
   store_frame_param (f, Qfullscreen, lval);
 /**   store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
 }
@@ -9227,30 +9231,78 @@ do_ewmh_fullscreen (struct frame *f)
                           None);
           break;
         case FULLSCREEN_WIDTH:
-          if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
-              || cur == FULLSCREEN_MAXIMIZED)
-            set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
-                          dpyinfo->Xatom_net_wm_state_maximized_vert);
-          if (cur != FULLSCREEN_MAXIMIZED)
-            set_wm_state (frame, true,
-                         dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+         if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
+           {
+             set_wm_state (frame, false,
+                           dpyinfo->Xatom_net_wm_state_maximized_horz,
+                           dpyinfo->Xatom_net_wm_state_maximized_vert);
+             set_wm_state (frame, true,
+                           dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+           }
+         else
+           {
+             if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
+                 || cur == FULLSCREEN_MAXIMIZED)
+               set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+                             dpyinfo->Xatom_net_wm_state_maximized_vert);
+             if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
+               set_wm_state (frame, true,
+                             dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+           }
           break;
         case FULLSCREEN_HEIGHT:
-          if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
-              || cur == FULLSCREEN_MAXIMIZED)
-            set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
-                          dpyinfo->Xatom_net_wm_state_maximized_horz);
-          if (cur != FULLSCREEN_MAXIMIZED)
-            set_wm_state (frame, true,
-                         dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+         if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
+           {
+             set_wm_state (frame, false,
+                           dpyinfo->Xatom_net_wm_state_maximized_horz,
+                           dpyinfo->Xatom_net_wm_state_maximized_vert);
+             set_wm_state (frame, true,
+                           dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+           }
+         else
+           {
+             if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
+                 || cur == FULLSCREEN_MAXIMIZED)
+               set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+                             dpyinfo->Xatom_net_wm_state_maximized_horz);
+             if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
+               set_wm_state (frame, true,
+                             dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+           }
           break;
         case FULLSCREEN_MAXIMIZED:
-          if (cur == FULLSCREEN_BOTH)
-            set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
-                         None);
-          set_wm_state (frame, true,
-                       dpyinfo->Xatom_net_wm_state_maximized_horz,
-                        dpyinfo->Xatom_net_wm_state_maximized_vert);
+         if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
+           {
+             set_wm_state (frame, false,
+                           dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+             set_wm_state (frame, true,
+                           dpyinfo->Xatom_net_wm_state_maximized_horz,
+                           dpyinfo->Xatom_net_wm_state_maximized_vert);
+           }
+         else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
+           {
+             set_wm_state (frame, false,
+                           dpyinfo->Xatom_net_wm_state_maximized_vert, None);
+             set_wm_state (frame, true,
+                           dpyinfo->Xatom_net_wm_state_maximized_horz,
+                           dpyinfo->Xatom_net_wm_state_maximized_vert);
+           }
+         else
+           {
+             if (cur == FULLSCREEN_BOTH)
+               set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
+                             None);
+             else if (cur == FULLSCREEN_HEIGHT)
+               set_wm_state (frame, true,
+                             dpyinfo->Xatom_net_wm_state_maximized_horz, None);
+             else if (cur == FULLSCREEN_WIDTH)
+               set_wm_state (frame, true, None,
+                             dpyinfo->Xatom_net_wm_state_maximized_vert);
+             else
+               set_wm_state (frame, true,
+                             dpyinfo->Xatom_net_wm_state_maximized_horz,
+                             dpyinfo->Xatom_net_wm_state_maximized_vert);
+           }
           break;
         case FULLSCREEN_NONE:
           if (cur == FULLSCREEN_BOTH)
@@ -9307,6 +9359,10 @@ x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
       break;
     }
 
+  frame_size_history_add
+    (f, Qx_handle_net_wm_state, 0, 0,
+     list2 (get_frame_param (f, Qfullscreen), lval));
+
   store_frame_param (f, Qfullscreen, lval);
   store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
 
@@ -9343,13 +9399,26 @@ x_check_fullscreen (struct frame *f)
           break;
         case FULLSCREEN_WIDTH:
           width = x_display_pixel_width (dpyinfo);
-          break;
+         height = height + FRAME_MENUBAR_HEIGHT (f);
+         break;
         case FULLSCREEN_HEIGHT:
           height = x_display_pixel_height (dpyinfo);
         }
 
+      frame_size_history_add
+       (f, Qx_check_fullscreen, width, height, Qnil);
+
       XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
-                     width, height);
+                    width, height);
+
+      if (FRAME_VISIBLE_P (f))
+       x_wait_for_event (f, ConfigureNotify);
+      else
+       {
+         change_frame_size (f, width, height - FRAME_MENUBAR_HEIGHT (f),
+                            false, true, false, true);
+         x_sync (f);
+       }
     }
 }
 
@@ -9490,21 +9559,57 @@ x_wait_for_event (struct frame *f, int eventtype)
 
 static void
 x_set_window_size_1 (struct frame *f, bool change_gravity,
-                    int width, int height, bool pixelwise)
+                    int width, int height)
 {
-  int pixelwidth, pixelheight;
-
-  pixelwidth = (pixelwise
-               ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width)
-               : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width));
-  pixelheight = ((pixelwise
-                 ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
-                 : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height)));
+  int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
+  int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
+  int old_width = FRAME_PIXEL_WIDTH (f);
+  int old_height = FRAME_PIXEL_HEIGHT (f);
+  Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
 
   if (change_gravity) f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, 0, false);
-  XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
-                pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
+
+  /* When the frame is fullheight and we only want to change the width
+     or it is fullwidth and we only want to change the height we should
+     be able to preserve the fullscreen property.  However, due to the
+     fact that we have to send a resize request anyway, the window
+     manager will abolish it.  At least the respective size should
+     remain unchanged but giving the frame back its normal size will
+     be broken ... */
+  if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
+    {
+      frame_size_history_add
+       (f, Qxg_frame_set_char_size_1, width, height,
+        list2 (make_number (old_height),
+               make_number (pixelheight + FRAME_MENUBAR_HEIGHT (f))));
+
+      XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                    old_width, pixelheight + FRAME_MENUBAR_HEIGHT (f));
+    }
+  else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
+    {
+      frame_size_history_add
+       (f, Qxg_frame_set_char_size_2, width, height,
+        list2 (make_number (old_width), make_number (pixelwidth)));
+
+      XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                    pixelwidth, old_height);
+    }
+
+  else
+    {
+      frame_size_history_add
+       (f, Qxg_frame_set_char_size_3, width, height,
+        list2 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
+               make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
+                            + FRAME_MENUBAR_HEIGHT (f))));
+
+      XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
+                    pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
+      fullscreen = Qnil;
+    }
+
 
 
   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
@@ -9531,7 +9636,16 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
      not right if the frame is visible.  Instead wait (with timeout)
      for the ConfigureNotify.  */
   if (FRAME_VISIBLE_P (f))
-    x_wait_for_event (f, ConfigureNotify);
+    {
+      x_wait_for_event (f, ConfigureNotify);
+
+      if (!NILP (fullscreen))
+       /* Try to restore fullscreen state.  */
+       {
+         store_frame_param (f, Qfullscreen, fullscreen);
+         x_set_fullscreen (f, fullscreen, fullscreen);
+       }
+    }
   else
     {
       change_frame_size (f, width, height, false, true, false, true);
@@ -9578,20 +9692,21 @@ x_set_window_size (struct frame *f, bool change_gravity,
     }
 #endif
 
+  /* Pixelize width and height, if necessary.  */
+  if (! pixelwise)
+    {
+      width = width * FRAME_COLUMN_WIDTH (f);
+      height = height * FRAME_LINE_HEIGHT (f);
+    }
+
 #ifdef USE_GTK
   if (FRAME_GTK_WIDGET (f))
-    if (! pixelwise)
-      xg_frame_set_char_size (f, width * FRAME_COLUMN_WIDTH (f),
-                             height * FRAME_LINE_HEIGHT (f));
-    else
-      xg_frame_set_char_size (f, width, height);
+    xg_frame_set_char_size (f, width, height);
   else
-    x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
+    x_set_window_size_1 (f, change_gravity, width, height);
 #else /* not USE_GTK */
-
-  x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
+  x_set_window_size_1 (f, change_gravity, width, height);
   x_clear_under_internal_border (f);
-
 #endif /* not USE_GTK */
 
   /* If cursor was outside the new size, mark it as off.  */
@@ -11602,4 +11717,15 @@ default is nil, which is the same as `super'.  */);
                                     make_float (DEFAULT_REHASH_SIZE),
                                     make_float (DEFAULT_REHASH_THRESHOLD),
                                     Qnil);
+
+  DEFVAR_BOOL ("x-frame-normalize-before-maximize",
+              x_frame_normalize_before_maximize,
+    doc: /* Non-nil means normalize frame before maximizing.
+If this variable is t, Emacs asks the window manager to give the frame
+intermediately its normal size whenever changing from a full-height or
+full-width state to the fully maximized one and vice versa.
+
+Set this variable only if your window manager cannot handle the
+transition between the various maximization states.  */);
+  x_frame_normalize_before_maximize = false;
 }