aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2015-02-07 11:51:03 +0100
committerMartin Rudalics2015-02-07 11:51:03 +0100
commitd1655783194f7b84ccac7114a2c341f10bc438b0 (patch)
tree1ee78b1870dfbe7baa45d8e0c4cebae582e13423 /src
parentcf498e5b9a73329edea0bdbf1bd8dfe06fdd75e2 (diff)
downloademacs-d1655783194f7b84ccac7114a2c341f10bc438b0.tar.gz
emacs-d1655783194f7b84ccac7114a2c341f10bc438b0.zip
Try to improve handling of fullwidth/-height frames.
* 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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog76
-rw-r--r--src/frame.c202
-rw-r--r--src/frame.h13
-rw-r--r--src/gtkutil.c113
-rw-r--r--src/w32fns.c18
-rw-r--r--src/w32term.c217
-rw-r--r--src/widget.c39
-rw-r--r--src/window.c2
-rw-r--r--src/xfns.c18
-rw-r--r--src/xterm.c214
10 files changed, 613 insertions, 299 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index cd72f98c116..ec70cdb93a9 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,79 @@
12015-02-07 Martin Rudalics <rudalics@gmx.at>
2
3 * frame.c (frame_size_history_add): New function.
4 (frame_inhibit_resize): Consider frame_inhibit_implied_resize
5 only after frame's after_make_frame slot is true. Inhibit
6 resizing fullwidth-/height frames in one direction only. Update
7 frame_size_history.
8 (adjust_frame_size): Call frame_size_history_add.
9 (make_frame): Initalize after_make_frame slot.
10 (Fmake_terminal_frame): Adjust adjust_frame_size call.
11 (Fcan_run_window_configuration_change_hook): Rename to
12 Fframe_after_make_frame. Set after_make_frame slot. Return
13 second argument.
14 (x_set_frame_parameters): Postpone handling fullscreen parameter
15 until after width and height parameters have been set. Apply
16 width and height changes only if can_x_set_window_size is true.
17 Update frame_size_history.
18 (Qadjust_frame_size_1, Qadjust_frame_size_2)
19 (Qadjust_frame_size_3, QEmacsFrameResize, Qframe_inhibit_resize)
20 (Qx_set_fullscreen, Qx_check_fullscreen, Qx_set_window_size_1)
21 (Qxg_frame_resized, Qxg_frame_set_char_size_1)
22 (Qxg_frame_set_char_size_2, Qxg_frame_set_char_size_3)
23 (Qxg_change_toolbar_position, Qx_net_wm_state)
24 (Qx_handle_net_wm_state, Qtb_size_cb, Qupdate_frame_tool_bar)
25 (Qfree_frame_tool_bar): New symbol for updating
26 frame_size_history.
27 (Qtip_frame, Qterminal_frame): New symbols.
28 (Vframe_adjust_size_history): Rename to frame_size_history.
29 * frame.h (struct frame): Rename
30 can_run_window_configuration_change_hook slot to
31 after_make_frame.
32 (frame_size_history_add): Extern.
33 * gtkutil.c (xg_frame_resized): Call frame_size_history_add.
34 Don't set FRAME_PIXEL_WIDTH and FRAME_PIXEL_HEIGHT here.
35 (xg_frame_set_char_size): Try to preserve the status of
36 fullwidth/-height frames. Call frame_size_history_add.
37 (tb_size_cb, update_frame_tool_bar, free_frame_tool_bar)
38 (xg_change_toolbar_position): Call frame_size_history_add.
39 * w32fns.c (x_change_tool_bar_height): Handle frame's fullscreen
40 status.
41 (Fx_create_frame): Process fullscreen parameter after frame has
42 been resized.
43 (x_create_tip_frame): Pass Qtip_frame to adjust_frame_size.
44 (Fx_frame_geometry): Don't pollute pure storage.
45 * w32term.c (w32_read_socket): For WM_WINDOWPOSCHANGED,
46 WM_ACTIVATE and WM_ACTIVATEAPP set frame's visibility before
47 calling w32fullscreen_hook. For WM_DISPLAYCHANGE call
48 w32fullscreen_hook immediately.
49 (x_fullscreen_adjust, x_check_fullscreen): Remove.
50 (w32fullscreen_hook): Call change_frame_size just as with a
51 "normal" frame resize operation. Call do_pending_window_change.
52 (x_set_window_size): Try to handle fullwidth and fullheight more
53 accurately. Don't rely on w32_enable_frame_resize_hack.
54 (w32_enable_frame_resize_hack): Remove variable.
55 * widget.c (EmacsFrameResize): Remove dead code. Call
56 frame_size_history_add
57 * window.c (run_window_configuration_change_hook): Check
58 f->after_make_frame instead of
59 f->can_run_window_configuration_change_hook.
60 * xfns.c (x_change_tool_bar_height): Handle frame's fullscreen status.
61 (Fx_create_frame): Process fullscreen parameter after frame has
62 been resized.
63 (Fx_frame_geometry): Don't pollute pure storage.
64 * xterm.c (x_net_wm_state, x_handle_net_wm_state): Call
65 frame_size_history_add.
66 (do_ewmh_fullscreen): Handle x_frame_normalize_before_maximize.
67 (x_check_fullscreen): Count in menubar when calling
68 XResizeWindow. Wait for ConfigureNotify event. Call
69 frame_size_history_add.
70 (x_set_window_size_1): Remove PIXELWISE argument. Try to handle
71 changing a fullheight frame's width or a fullwidth frame's
72 height. Call frame_size_history_add.
73 (x_set_window_size): Simplify xg_frame_set_char_size and
74 x_set_window_size_1 calls.
75 (x_frame_normalize_before_maximize): New variable.
76
12015-02-07 Paul Eggert <eggert@cs.ucla.edu> 772015-02-07 Paul Eggert <eggert@cs.ucla.edu>
2 78
3 Remove no-longer-used cursor_in_echo_area code 79 Remove no-longer-used cursor_in_echo_area code
diff --git a/src/frame.c b/src/frame.c
index 890e8972617..96fe3778dbc 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -149,6 +149,33 @@ get_frame_param (register struct frame *frame, Lisp_Object prop)
149 return Fcdr (tem); 149 return Fcdr (tem);
150} 150}
151 151
152
153void
154frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
155 int width, int height, Lisp_Object rest)
156{
157 Lisp_Object frame;
158 int number;
159
160 XSETFRAME (frame, f);
161 if (CONSP (frame_size_history)
162 && NUMBERP (Fcar (frame_size_history))
163 && ((number = XINT (Fcar (frame_size_history))) > 0))
164 frame_size_history =
165 Fcons (make_number (number - 1),
166 Fcons (list4
167 (frame, fun_symbol,
168 ((width > 0)
169 ? list4 (make_number (FRAME_TEXT_WIDTH (f)),
170 make_number (FRAME_TEXT_HEIGHT (f)),
171 make_number (width),
172 make_number (height))
173 : Qnil),
174 rest),
175 Fcdr (frame_size_history)));
176}
177
178
152/* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen 179/* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
153 state of frame F would be affected by a vertical (horizontal if 180 state of frame F would be affected by a vertical (horizontal if
154 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame 181 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)
156bool 183bool
157frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter) 184frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
158{ 185{
159 return (EQ (frame_inhibit_implied_resize, Qt) 186 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
160 || (CONSP (frame_inhibit_implied_resize) 187 bool inhibit
161 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize))) 188 = ((f->after_make_frame
162 || !NILP (get_frame_param (f, Qfullscreen)) 189 && (EQ (frame_inhibit_implied_resize, Qt)
163 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)); 190 || (CONSP (frame_inhibit_implied_resize)
191 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))))
192 || (horizontal
193 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullheight))
194 || (!horizontal
195 && !EQ (fullscreen, Qnil) && !EQ (fullscreen, Qfullwidth))
196 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
197
198 if (inhibit && !FRAME_TERMCAP_P (f) && !FRAME_MSDOS_P (f))
199 frame_size_history_add
200 (f, Qframe_inhibit_resize, 0, 0,
201 list5 (horizontal ? Qt : Qnil, parameter,
202 f->after_make_frame ? Qt : Qnil,
203 frame_inhibit_implied_resize,
204 fullscreen));
205
206 return inhibit;
164} 207}
165 208
166static void 209static void
@@ -369,18 +412,9 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
369 412
370 XSETFRAME (frame, f); 413 XSETFRAME (frame, f);
371 414
372 /* `make-frame' initializes Vframe_adjust_size_history to (Qt) and 415 frame_size_history_add
373 strips its car when exiting. Just in case make sure its size never 416 (f, Qadjust_frame_size_1, new_text_width, new_text_height,
374 exceeds 100. */ 417 list2 (parameter, make_number (inhibit)));
375 if (!NILP (Fconsp (Vframe_adjust_size_history))
376 && EQ (Fcar (Vframe_adjust_size_history), Qt)
377 && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
378 Vframe_adjust_size_history =
379 Fcons (Qt, Fcons (list5 (make_number (0),
380 make_number (new_text_width),
381 make_number (new_text_height),
382 make_number (inhibit), parameter),
383 Fcdr (Vframe_adjust_size_history)));
384 418
385 /* The following two values are calculated from the old window body 419 /* The following two values are calculated from the old window body
386 sizes and any "new" settings for scroll bars, dividers, fringes and 420 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,
391 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt); 425 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
392 426
393 if (inhibit >= 2 && inhibit <= 4) 427 if (inhibit >= 2 && inhibit <= 4)
394 /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay 428 /* When INHIBIT is in [2..4] inhibit if the "old" window sizes stay
395 within the limits and either frame_inhibit_resize tells us to do 429 within the limits and either frame_inhibit_resize tells us to do
396 so or INHIBIT equals 4. */ 430 so or INHIBIT equals 4. */
397 { 431 {
@@ -449,16 +483,10 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
449 else if (inhibit_vertical) 483 else if (inhibit_vertical)
450 new_text_height = old_text_height; 484 new_text_height = old_text_height;
451 485
452 if (!NILP (Fconsp (Vframe_adjust_size_history)) 486 frame_size_history_add
453 && EQ (Fcar (Vframe_adjust_size_history), Qt) 487 (f, Qadjust_frame_size_2, new_text_width, new_text_height,
454 && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100) 488 list2 (inhibit_horizontal ? Qt : Qnil,
455 Vframe_adjust_size_history = 489 inhibit_vertical ? Qt : Qnil));
456 Fcons (Qt, Fcons (list5 (make_number (1),
457 make_number (new_text_width),
458 make_number (new_text_height),
459 make_number (new_cols),
460 make_number (new_lines)),
461 Fcdr (Vframe_adjust_size_history)));
462 490
463 x_set_window_size (f, 0, new_text_width, new_text_height, 1); 491 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
464 f->resized_p = true; 492 f->resized_p = true;
@@ -525,6 +553,11 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
525 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f); 553 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
526 } 554 }
527 555
556 frame_size_history_add
557 (f, Qadjust_frame_size_3, new_text_width, new_text_height,
558 list4 (make_number (old_pixel_width), make_number (old_pixel_height),
559 make_number (new_pixel_width), make_number (new_pixel_height)));
560
528 /* Assign new sizes. */ 561 /* Assign new sizes. */
529 FRAME_TEXT_WIDTH (f) = new_text_width; 562 FRAME_TEXT_WIDTH (f) = new_text_width;
530 FRAME_TEXT_HEIGHT (f) = new_text_height; 563 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,
533 SET_FRAME_COLS (f, new_cols); 566 SET_FRAME_COLS (f, new_cols);
534 SET_FRAME_LINES (f, new_lines); 567 SET_FRAME_LINES (f, new_lines);
535 568
536 if (!NILP (Fconsp (Vframe_adjust_size_history))
537 && EQ (Fcar (Vframe_adjust_size_history), Qt)
538 && XFASTINT (Fsafe_length (Vframe_adjust_size_history)) <= 100)
539 Vframe_adjust_size_history =
540 Fcons (Qt, Fcons (list5 (make_number (2),
541 make_number (new_text_width),
542 make_number (new_text_height),
543 make_number (new_cols),
544 make_number (new_lines)),
545 Fcdr (Vframe_adjust_size_history)));
546
547 { 569 {
548 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); 570 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
549 int text_area_x, text_area_y, text_area_width, text_area_height; 571 int text_area_x, text_area_y, text_area_width, text_area_height;
@@ -608,7 +630,7 @@ make_frame (bool mini_p)
608 f->redisplay = true; 630 f->redisplay = true;
609 f->garbaged = true; 631 f->garbaged = true;
610 f->can_x_set_window_size = false; 632 f->can_x_set_window_size = false;
611 f->can_run_window_configuration_change_hook = false; 633 f->after_make_frame = false;
612 f->tool_bar_redisplayed_once = false; 634 f->tool_bar_redisplayed_once = false;
613 f->column_width = 1; /* !FRAME_WINDOW_P value. */ 635 f->column_width = 1; /* !FRAME_WINDOW_P value. */
614 f->line_height = 1; /* !FRAME_WINDOW_P value. */ 636 f->line_height = 1; /* !FRAME_WINDOW_P value. */
@@ -1020,7 +1042,8 @@ affects all frames on the same terminal device. */)
1020 { 1042 {
1021 int width, height; 1043 int width, height;
1022 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height); 1044 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
1023 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil); 1045 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f),
1046 5, 0, Qterminal_frame);
1024 } 1047 }
1025 1048
1026 adjust_frame_glyphs (f); 1049 adjust_frame_glyphs (f);
@@ -2260,24 +2283,25 @@ If there is no window system support, this function does nothing. */)
2260 return Qnil; 2283 return Qnil;
2261} 2284}
2262 2285
2263DEFUN ("frame-can-run-window-configuration-change-hook", 2286DEFUN ("frame-after-make-frame",
2264 Fcan_run_window_configuration_change_hook, 2287 Fframe_after_make_frame,
2265 Scan_run_window_configuration_change_hook, 2, 2, 0, 2288 Sframe_after_make_frame, 2, 2, 0,
2266 doc: /* Whether `window-configuration-change-hook' is run for frame FRAME. 2289 doc: /* Mark FRAME as made.
2267FRAME nil means use the selected frame. Second argument ALLOW non-nil 2290FRAME nil means use the selected frame. Second argument MADE non-nil
2268means functions on `window-configuration-change-hook' are called 2291means functions on `window-configuration-change-hook' are called
2269whenever the window configuration of FRAME changes. ALLOW nil means 2292whenever the window configuration of FRAME changes. MADE nil means
2270these functions are not called. 2293these functions are not called.
2271 2294
2272This function is currently called by `face-set-after-frame-default' only 2295This function is currently called by `make-frame' only and should be
2273and should be otherwise used with utter care to avoid that running 2296otherwise used with utter care to avoid that running functions on
2274functions on `window-configuration-change-hook' is impeded forever. */) 2297`window-configuration-change-hook' is impeded forever. */)
2275 (Lisp_Object frame, Lisp_Object allow) 2298 (Lisp_Object frame, Lisp_Object made)
2276{ 2299{
2277 struct frame *f = decode_live_frame (frame); 2300 struct frame *f = decode_live_frame (frame);
2278 2301
2279 f->can_run_window_configuration_change_hook = NILP (allow) ? false : true; 2302 f->after_make_frame = NILP (made) ? false : true;
2280 return Qnil; 2303
2304 return made;
2281} 2305}
2282 2306
2283 2307
@@ -3037,7 +3061,7 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3037 set them both at once. So we wait until we've looked at the 3061 set them both at once. So we wait until we've looked at the
3038 entire list before we set them. */ 3062 entire list before we set them. */
3039 int width IF_LINT (= 0), height IF_LINT (= 0); 3063 int width IF_LINT (= 0), height IF_LINT (= 0);
3040 bool width_change = 0, height_change = 0; 3064 bool width_change = false, height_change = false;
3041 3065
3042 /* Same here. */ 3066 /* Same here. */
3043 Lisp_Object left, top; 3067 Lisp_Object left, top;
@@ -3045,6 +3069,10 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3045 /* Same with these. */ 3069 /* Same with these. */
3046 Lisp_Object icon_left, icon_top; 3070 Lisp_Object icon_left, icon_top;
3047 3071
3072 /* And with this. */
3073 Lisp_Object fullscreen;
3074 bool fullscreen_change = false;
3075
3048 /* Record in these vectors all the parms specified. */ 3076 /* Record in these vectors all the parms specified. */
3049 Lisp_Object *parms; 3077 Lisp_Object *parms;
3050 Lisp_Object *values; 3078 Lisp_Object *values;
@@ -3138,6 +3166,11 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3138 icon_top = val; 3166 icon_top = val;
3139 else if (EQ (prop, Qicon_left)) 3167 else if (EQ (prop, Qicon_left))
3140 icon_left = val; 3168 icon_left = val;
3169 else if (EQ (prop, Qfullscreen))
3170 {
3171 fullscreen = val;
3172 fullscreen_change = true;
3173 }
3141 else if (EQ (prop, Qforeground_color) 3174 else if (EQ (prop, Qforeground_color)
3142 || EQ (prop, Qbackground_color) 3175 || EQ (prop, Qbackground_color)
3143 || EQ (prop, Qfont)) 3176 || EQ (prop, Qfont))
@@ -3218,14 +3251,14 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3218 that here since otherwise a size change implied by an 3251 that here since otherwise a size change implied by an
3219 intermittent font change may get lost as in Bug#17142. */ 3252 intermittent font change may get lost as in Bug#17142. */
3220 if (!width_change) 3253 if (!width_change)
3221 width = (f->new_width 3254 width = ((f->can_x_set_window_size && f->new_width)
3222 ? (f->new_pixelwise 3255 ? (f->new_pixelwise
3223 ? f->new_width 3256 ? f->new_width
3224 : (f->new_width * FRAME_COLUMN_WIDTH (f))) 3257 : (f->new_width * FRAME_COLUMN_WIDTH (f)))
3225 : FRAME_TEXT_WIDTH (f)); 3258 : FRAME_TEXT_WIDTH (f));
3226 3259
3227 if (!height_change) 3260 if (!height_change)
3228 height = (f->new_height 3261 height = ((f->can_x_set_window_size && f->new_height)
3229 ? (f->new_pixelwise 3262 ? (f->new_pixelwise
3230 ? f->new_height 3263 ? f->new_height
3231 : (f->new_height * FRAME_LINE_HEIGHT (f))) 3264 : (f->new_height * FRAME_LINE_HEIGHT (f)))
@@ -3298,6 +3331,20 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3298 /* Actually set that position, and convert to absolute. */ 3331 /* Actually set that position, and convert to absolute. */
3299 x_set_offset (f, leftpos, toppos, -1); 3332 x_set_offset (f, leftpos, toppos, -1);
3300 } 3333 }
3334
3335 if (fullscreen_change)
3336 {
3337 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
3338
3339 frame_size_history_add
3340 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
3341
3342 store_frame_param (f, Qfullscreen, fullscreen);
3343 if (!EQ (fullscreen, old_value))
3344 x_set_fullscreen (f, fullscreen, old_value);
3345 }
3346
3347
3301#ifdef HAVE_X_WINDOWS 3348#ifdef HAVE_X_WINDOWS
3302 if ((!NILP (icon_left) || !NILP (icon_top)) 3349 if ((!NILP (icon_left) || !NILP (icon_top))
3303 && ! (icon_left_no_change && icon_top_no_change)) 3350 && ! (icon_left_no_change && icon_top_no_change))
@@ -4834,11 +4881,33 @@ syms_of_frame (void)
4834 DEFSYM (Qtool_bar_external, "tool-bar-external"); 4881 DEFSYM (Qtool_bar_external, "tool-bar-external");
4835 DEFSYM (Qtool_bar_size, "tool-bar-size"); 4882 DEFSYM (Qtool_bar_size, "tool-bar-size");
4836 DEFSYM (Qframe_inner_size, "frame-inner-size"); 4883 DEFSYM (Qframe_inner_size, "frame-inner-size");
4884 /* The following are used for frame_size_history. */
4885 DEFSYM (Qadjust_frame_size_1, "adjust-frame-size-1");
4886 DEFSYM (Qadjust_frame_size_2, "adjust-frame-size-2");
4887 DEFSYM (Qadjust_frame_size_3, "adjust-frame-size-3");
4888 DEFSYM (QEmacsFrameResize, "EmacsFrameResize");
4889 DEFSYM (Qframe_inhibit_resize, "frame-inhibit-resize");
4890 DEFSYM (Qx_set_fullscreen, "x-set-fullscreen");
4891 DEFSYM (Qx_check_fullscreen, "x-check-fullscreen");
4892 DEFSYM (Qx_set_window_size_1, "x-set-window-size-1");
4893 DEFSYM (Qxg_frame_resized, "xg-frame-resized");
4894 DEFSYM (Qxg_frame_set_char_size_1, "xg-frame-set-char-size-1");
4895 DEFSYM (Qxg_frame_set_char_size_2, "xg-frame-set-char-size-2");
4896 DEFSYM (Qxg_frame_set_char_size_3, "xg-frame-set-char-size-3");
4897 DEFSYM (Qxg_change_toolbar_position, "xg-change-toolbar-position");
4898 DEFSYM (Qx_net_wm_state, "x-net-wm-state");
4899 DEFSYM (Qx_handle_net_wm_state, "x-handle-net-wm-state");
4900 DEFSYM (Qtb_size_cb, "tb-size-cb");
4901 DEFSYM (Qupdate_frame_tool_bar, "update-frame-tool-bar");
4902 DEFSYM (Qfree_frame_tool_bar, "free-frame-tool-bar");
4903
4837 DEFSYM (Qchange_frame_size, "change-frame-size"); 4904 DEFSYM (Qchange_frame_size, "change-frame-size");
4838 DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size"); 4905 DEFSYM (Qxg_frame_set_char_size, "xg-frame-set-char-size");
4839 DEFSYM (Qset_window_configuration, "set-window-configuration"); 4906 DEFSYM (Qset_window_configuration, "set-window-configuration");
4840 DEFSYM (Qx_create_frame_1, "x-create-frame-1"); 4907 DEFSYM (Qx_create_frame_1, "x-create-frame-1");
4841 DEFSYM (Qx_create_frame_2, "x-create-frame-2"); 4908 DEFSYM (Qx_create_frame_2, "x-create-frame-2");
4909 DEFSYM (Qtip_frame, "tip-frame");
4910 DEFSYM (Qterminal_frame, "terminal-frame");
4842 4911
4843#ifdef HAVE_NS 4912#ifdef HAVE_NS
4844 DEFSYM (Qns_parse_geometry, "ns-parse-geometry"); 4913 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
@@ -5106,9 +5175,22 @@ even if this option is non-nil. */);
5106 frame_inhibit_implied_resize = Qt; 5175 frame_inhibit_implied_resize = Qt;
5107#endif 5176#endif
5108 5177
5109 DEFVAR_LISP ("frame-adjust-size-history", Vframe_adjust_size_history, 5178 DEFVAR_LISP ("frame-size-history", frame_size_history,
5110 doc: /* History of frame size adjustments. */); 5179 doc: /* History of frame size adjustments.
5111 Vframe_adjust_size_history = Qnil; 5180If non-nil, list recording frame size adjustment. Adjustments are
5181recorded only if the first element of this list is a positive number.
5182Adding an adjustment decrements that number by one.
5183
5184The remaining elements are the adjustments. Each adjustment is a list
5185of four elements `frame', `function', `sizes' and `more'. `frame' is
5186the affected frame and `function' the invoking function. `sizes' is
5187usually a list of four elements `old-width', `old-height', `new-width'
5188and `new-height' representing the old and new sizes recorded/requested
5189by `function'. `more' is a list with additional information.
5190
5191The function `frame--size-history' displays the value of this variable
5192in a more readable form. */);
5193 frame_size_history = Qnil;
5112 5194
5113 staticpro (&Vframe_list); 5195 staticpro (&Vframe_list);
5114 5196
@@ -5141,7 +5223,7 @@ even if this option is non-nil. */);
5141 defsubr (&Sraise_frame); 5223 defsubr (&Sraise_frame);
5142 defsubr (&Slower_frame); 5224 defsubr (&Slower_frame);
5143 defsubr (&Sx_focus_frame); 5225 defsubr (&Sx_focus_frame);
5144 defsubr (&Scan_run_window_configuration_change_hook); 5226 defsubr (&Sframe_after_make_frame);
5145 defsubr (&Sredirect_frame_focus); 5227 defsubr (&Sredirect_frame_focus);
5146 defsubr (&Sframe_focus); 5228 defsubr (&Sframe_focus);
5147 defsubr (&Sframe_parameters); 5229 defsubr (&Sframe_parameters);
diff --git a/src/frame.h b/src/frame.h
index 0c08d12c92e..6f5de3f5689 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -332,9 +332,8 @@ struct frame
332 frame. */ 332 frame. */
333 bool_bf can_x_set_window_size : 1; 333 bool_bf can_x_set_window_size : 1;
334 334
335 /* True means run_window_configuration_change_hook can be processed 335 /* Set to true after this frame was made by `make-frame'. */
336 for this frame. */ 336 bool_bf after_make_frame : 1;
337 bool_bf can_run_window_configuration_change_hook : 1;
338 337
339 /* True means tool bar has been redisplayed at least once in current 338 /* True means tool bar has been redisplayed at least once in current
340 session. */ 339 session. */
@@ -392,9 +391,9 @@ struct frame
392 int left_pos, top_pos; 391 int left_pos, top_pos;
393 392
394 /* Total width of this frame (including fringes, vertical scroll bar 393 /* Total width of this frame (including fringes, vertical scroll bar
395 and internal border widths) and total height (including menu bar, 394 and internal border widths) and total height (including internal
396 tool bar, horizontal scroll bar and internal border widths) in 395 menu and tool bars, horizontal scroll bar and internal border
397 pixels. */ 396 widths) in pixels. */
398 int pixel_width, pixel_height; 397 int pixel_width, pixel_height;
399 398
400 /* These many pixels are the difference between the outer window (i.e. the 399 /* 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 *);
1124extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object); 1123extern Lisp_Object delete_frame (Lisp_Object, Lisp_Object);
1125extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object); 1124extern bool frame_inhibit_resize (struct frame *, bool, Lisp_Object);
1126extern void adjust_frame_size (struct frame *, int, int, int, bool, Lisp_Object); 1125extern void adjust_frame_size (struct frame *, int, int, int, bool, Lisp_Object);
1126extern void frame_size_history_add (struct frame *f, Lisp_Object fun_symbol,
1127 int width, int height, Lisp_Object rest);
1127 1128
1128extern Lisp_Object Vframe_list; 1129extern Lisp_Object Vframe_list;
1129 1130
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 21f3cb15e66..063e88262d9 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -886,23 +886,25 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
886 if (pixelwidth == -1 && pixelheight == -1) 886 if (pixelwidth == -1 && pixelheight == -1)
887 { 887 {
888 if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f))) 888 if (FRAME_GTK_WIDGET (f) && gtk_widget_get_mapped (FRAME_GTK_WIDGET (f)))
889 gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)), 889 gdk_window_get_geometry (gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
890 0, 0, 890 0, 0, &pixelwidth, &pixelheight);
891 &pixelwidth, &pixelheight); 891 else
892 else return; 892 return;
893 } 893 }
894 894
895
896 width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth); 895 width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth);
897 height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight); 896 height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight);
898 897
898 frame_size_history_add
899 (f, Qxg_frame_resized, width, height, Qnil);
900
899 if (width != FRAME_TEXT_WIDTH (f) 901 if (width != FRAME_TEXT_WIDTH (f)
900 || height != FRAME_TEXT_HEIGHT (f) 902 || height != FRAME_TEXT_HEIGHT (f)
901 || pixelwidth != FRAME_PIXEL_WIDTH (f) 903 || pixelwidth != FRAME_PIXEL_WIDTH (f)
902 || pixelheight != FRAME_PIXEL_HEIGHT (f)) 904 || pixelheight != FRAME_PIXEL_HEIGHT (f))
903 { 905 {
904 FRAME_PIXEL_WIDTH (f) = pixelwidth; 906/** FRAME_PIXEL_WIDTH (f) = pixelwidth; **/
905 FRAME_PIXEL_HEIGHT (f) = pixelheight; 907/** FRAME_PIXEL_HEIGHT (f) = pixelheight; **/
906 908
907 xg_clear_under_internal_border (f); 909 xg_clear_under_internal_border (f);
908 change_frame_size (f, width, height, 0, 1, 0, 1); 910 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)
921{ 923{
922 int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); 924 int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
923 int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); 925 int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
926 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
927 gint gwidth, gheight;
924 928
925 if (FRAME_PIXEL_HEIGHT (f) == 0) 929 if (FRAME_PIXEL_HEIGHT (f) == 0)
926 return; 930 return;
927 931
932 gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
933 &gwidth, &gheight);
934
928 /* Do this before resize, as we don't know yet if we will be resized. */ 935 /* Do this before resize, as we don't know yet if we will be resized. */
929 xg_clear_under_internal_border (f); 936 xg_clear_under_internal_border (f);
930 937
931 /* Must resize our top level widget. Font size may have changed, 938 /* Resize the top level widget so rows and columns remain constant.
932 but not rows/cols. */ 939
933 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), 940 When the frame is fullheight and we only want to change the width
934 pixelwidth + FRAME_TOOLBAR_WIDTH (f), 941 or it is fullwidth and we only want to change the height we should
935 pixelheight + FRAME_TOOLBAR_HEIGHT (f) 942 be able to preserve the fullscreen property. However, due to the
936 + FRAME_MENUBAR_HEIGHT (f)); 943 fact that we have to send a resize request anyway, the window
937 x_wm_set_size_hint (f, 0, 0); 944 manager will abolish it. At least the respective size should
945 remain unchanged but giving the frame back its normal size will
946 be broken ... */
947 if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
948 {
949 frame_size_history_add
950 (f, Qxg_frame_set_char_size_1, width, height,
951 list2 (make_number (gheight),
952 make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
953 + FRAME_MENUBAR_HEIGHT (f))));
954
955 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
956 gwidth,
957 pixelheight + FRAME_TOOLBAR_HEIGHT (f)
958 + FRAME_MENUBAR_HEIGHT (f));
959 }
960 else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
961 {
962 frame_size_history_add
963 (f, Qxg_frame_set_char_size_2, width, height,
964 list2 (make_number (gwidth),
965 make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f))));
966
967 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
968 pixelwidth + FRAME_TOOLBAR_WIDTH (f),
969 gheight);
970 }
971
972 else
973 {
974 frame_size_history_add
975 (f, Qxg_frame_set_char_size_3, width, height,
976 list2 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
977 make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
978 + FRAME_MENUBAR_HEIGHT (f))));
979
980 gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
981 pixelwidth + FRAME_TOOLBAR_WIDTH (f),
982 pixelheight + FRAME_TOOLBAR_HEIGHT (f)
983 + FRAME_MENUBAR_HEIGHT (f));
984 fullscreen = Qnil;
985 }
938 986
939 SET_FRAME_GARBAGED (f); 987 SET_FRAME_GARBAGED (f);
940 cancel_mouse_face (f); 988 cancel_mouse_face (f);
941 989
990 x_wm_set_size_hint (f, 0, 0);
942 /* We can not call change_frame_size for a mapped frame, 991 /* We can not call change_frame_size for a mapped frame,
943 we can not set pixel width/height either. The window manager may 992 we can not set pixel width/height either. The window manager may
944 override our resize request, XMonad does this all the time. 993 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)
952 (void)gtk_events_pending (); 1001 (void)gtk_events_pending ();
953 gdk_flush (); 1002 gdk_flush ();
954 x_wait_for_event (f, ConfigureNotify); 1003 x_wait_for_event (f, ConfigureNotify);
1004
1005 if (!NILP (fullscreen))
1006 /* Try to restore fullscreen state. */
1007 {
1008 store_frame_param (f, Qfullscreen, fullscreen);
1009 x_set_fullscreen (f, fullscreen, fullscreen);
1010 }
955 } 1011 }
956 else 1012 else
957 adjust_frame_size (f, -1, -1, 5, 0, Qxg_frame_set_char_size); 1013 adjust_frame_size (f, width, height, 5, 0, Qxg_frame_set_char_size);
1014
958} 1015}
959 1016
960/* Handle height/width changes (i.e. add/remove/move menu/toolbar). 1017/* Handle height/width changes (i.e. add/remove/move menu/toolbar).
@@ -4214,8 +4271,12 @@ tb_size_cb (GtkWidget *widget,
4214 allocated between widgets, it may get another. So we must update 4271 allocated between widgets, it may get another. So we must update
4215 size hints if tool bar size changes. Seen on Fedora 18 at least. */ 4272 size hints if tool bar size changes. Seen on Fedora 18 at least. */
4216 struct frame *f = user_data; 4273 struct frame *f = user_data;
4274
4217 if (xg_update_tool_bar_sizes (f)) 4275 if (xg_update_tool_bar_sizes (f))
4218 adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); 4276 {
4277 frame_size_history_add (f, Qtb_size_cb, 0, 0, Qnil);
4278 adjust_frame_size (f, -1, -1, 5, 0, Qtool_bar_lines);
4279 }
4219} 4280}
4220 4281
4221/* Create a tool bar for frame F. */ 4282/* Create a tool bar for frame F. */
@@ -4489,10 +4550,11 @@ xg_update_tool_bar_sizes (struct frame *f)
4489 FRAME_TOOLBAR_RIGHT_WIDTH (f) = nr; 4550 FRAME_TOOLBAR_RIGHT_WIDTH (f) = nr;
4490 FRAME_TOOLBAR_TOP_HEIGHT (f) = nt; 4551 FRAME_TOOLBAR_TOP_HEIGHT (f) = nt;
4491 FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = nb; 4552 FRAME_TOOLBAR_BOTTOM_HEIGHT (f) = nb;
4492 return 1;
4493 }
4494 4553
4495 return 0; 4554 return true;
4555 }
4556 else
4557 return false;
4496} 4558}
4497 4559
4498static char * 4560static char *
@@ -4815,7 +4877,10 @@ update_frame_tool_bar (struct frame *f)
4815 xg_pack_tool_bar (f, FRAME_TOOL_BAR_POSITION (f)); 4877 xg_pack_tool_bar (f, FRAME_TOOL_BAR_POSITION (f));
4816 gtk_widget_show_all (x->toolbar_widget); 4878 gtk_widget_show_all (x->toolbar_widget);
4817 if (xg_update_tool_bar_sizes (f)) 4879 if (xg_update_tool_bar_sizes (f))
4818 adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); 4880 {
4881 frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
4882 adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
4883 }
4819 } 4884 }
4820 4885
4821 unblock_input (); 4886 unblock_input ();
@@ -4863,6 +4928,7 @@ free_frame_tool_bar (struct frame *f)
4863 NULL); 4928 NULL);
4864 } 4929 }
4865 4930
4931 frame_size_history_add (f, Qfree_frame_tool_bar, 0, 0, Qnil);
4866 adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); 4932 adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
4867 4933
4868 unblock_input (); 4934 unblock_input ();
@@ -4892,8 +4958,13 @@ xg_change_toolbar_position (struct frame *f, Lisp_Object pos)
4892 4958
4893 xg_pack_tool_bar (f, pos); 4959 xg_pack_tool_bar (f, pos);
4894 g_object_unref (top_widget); 4960 g_object_unref (top_widget);
4961
4895 if (xg_update_tool_bar_sizes (f)) 4962 if (xg_update_tool_bar_sizes (f))
4896 adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines); 4963 {
4964 frame_size_history_add (f, Qxg_change_toolbar_position, 0, 0, Qnil);
4965 adjust_frame_size (f, -1, -1, 2, 0, Qtool_bar_lines);
4966 }
4967
4897 4968
4898 unblock_input (); 4969 unblock_input ();
4899} 4970}
diff --git a/src/w32fns.c b/src/w32fns.c
index 8435270438d..08000d87d38 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -1722,6 +1722,7 @@ x_change_tool_bar_height (struct frame *f, int height)
1722 int old_height = FRAME_TOOL_BAR_HEIGHT (f); 1722 int old_height = FRAME_TOOL_BAR_HEIGHT (f);
1723 int lines = (height + unit - 1) / unit; 1723 int lines = (height + unit - 1) / unit;
1724 int old_text_height = FRAME_TEXT_HEIGHT (f); 1724 int old_text_height = FRAME_TEXT_HEIGHT (f);
1725 Lisp_Object fullscreen;
1725 1726
1726 /* Make sure we redisplay all windows in this frame. */ 1727 /* Make sure we redisplay all windows in this frame. */
1727 windows_or_buffers_changed = 23; 1728 windows_or_buffers_changed = 23;
@@ -1746,7 +1747,10 @@ x_change_tool_bar_height (struct frame *f, int height)
1746 f->n_tool_bar_rows = 0; 1747 f->n_tool_bar_rows = 0;
1747 1748
1748 adjust_frame_size (f, -1, -1, 1749 adjust_frame_size (f, -1, -1,
1749 (!f->tool_bar_redisplayed_once ? 1 1750 ((!f->tool_bar_redisplayed_once
1751 && (NILP (fullscreen =
1752 get_frame_param (f, Qfullscreen))
1753 || EQ (fullscreen, Qfullwidth))) ? 1
1750 : (old_height == 0 || height == 0) ? 2 1754 : (old_height == 0 || height == 0) ? 2
1751 : 4), 1755 : 4),
1752 false, Qtool_bar_lines); 1756 false, Qtool_bar_lines);
@@ -4668,8 +4672,6 @@ This function is an internal primitive--use `make-frame' instead. */)
4668 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL); 4672 "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
4669 x_default_parameter (f, parameters, Qtitle, Qnil, 4673 x_default_parameter (f, parameters, Qtitle, Qnil,
4670 "title", "Title", RES_TYPE_STRING); 4674 "title", "Title", RES_TYPE_STRING);
4671 x_default_parameter (f, parameters, Qfullscreen, Qnil,
4672 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4673 4675
4674 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW; 4676 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
4675 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; 4677 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. */)
4728 x_wm_set_size_hint (f, window_prompting, false); 4730 x_wm_set_size_hint (f, window_prompting, false);
4729 unblock_input (); 4731 unblock_input ();
4730 4732
4733 /* Process fullscreen parameter here in the hope that normalizing a
4734 fullheight/fullwidth frame will produce the size set by the last
4735 adjust_frame_size call. */
4736 x_default_parameter (f, parameters, Qfullscreen, Qnil,
4737 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4738
4731 /* Make the window appear on the frame and enable display, unless 4739 /* Make the window appear on the frame and enable display, unless
4732 the caller says not to. However, with explicit parent, Emacs 4740 the caller says not to. However, with explicit parent, Emacs
4733 cannot control visibility, so don't try. */ 4741 cannot control visibility, so don't try. */
@@ -5832,7 +5840,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
5832 SET_FRAME_COLS (f, 0); 5840 SET_FRAME_COLS (f, 0);
5833 SET_FRAME_LINES (f, 0); 5841 SET_FRAME_LINES (f, 0);
5834 adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f), 5842 adjust_frame_size (f, width * FRAME_COLUMN_WIDTH (f),
5835 height * FRAME_LINE_HEIGHT (f), 0, true, Qnil); 5843 height * FRAME_LINE_HEIGHT (f), 0, true, Qtip_frame);
5836 5844
5837 /* Add `tooltip' frame parameter's default value. */ 5845 /* Add `tooltip' frame parameter's default value. */
5838 if (NILP (Fframe_parameter (frame, Qtooltip))) 5846 if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -7558,7 +7566,7 @@ elements (all size values are in pixels).
7558 menu_bar_height = single_bar_height; 7566 menu_bar_height = single_bar_height;
7559 7567
7560 return 7568 return
7561 listn (CONSTYPE_PURE, 10, 7569 listn (CONSTYPE_HEAP, 10,
7562 Fcons (Qframe_position, 7570 Fcons (Qframe_position,
7563 Fcons (make_number (frame_outer_edges.left), 7571 Fcons (make_number (frame_outer_edges.left),
7564 make_number (frame_outer_edges.top))), 7572 make_number (frame_outer_edges.top))),
diff --git a/src/w32term.c b/src/w32term.c
index 251c46c73cf..fb9d2388d6b 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -3344,8 +3344,6 @@ static void x_horizontal_scroll_bar_report_motion (struct frame **, Lisp_Object
3344 enum scroll_bar_part *, 3344 enum scroll_bar_part *,
3345 Lisp_Object *, Lisp_Object *, 3345 Lisp_Object *, Lisp_Object *,
3346 Time *); 3346 Time *);
3347static void x_check_fullscreen (struct frame *);
3348
3349static void 3347static void
3350w32_define_cursor (Window window, Cursor cursor) 3348w32_define_cursor (Window window, Cursor cursor)
3351{ 3349{
@@ -4989,8 +4987,12 @@ w32_read_socket (struct terminal *terminal,
4989 sets the WAIT flag. */ 4987 sets the WAIT flag. */
4990 if ((msg.msg.message == WM_WINDOWPOSCHANGED || msg.msg.wParam) 4988 if ((msg.msg.message == WM_WINDOWPOSCHANGED || msg.msg.wParam)
4991 && (f->want_fullscreen & FULLSCREEN_WAIT)) 4989 && (f->want_fullscreen & FULLSCREEN_WAIT))
4992 w32fullscreen_hook (f); 4990 {
4993 x_check_fullscreen (f); 4991 /* Must set visibility right here since otherwise
4992 w32fullscreen_hook returns immediately. */
4993 SET_FRAME_VISIBLE (f, 1);
4994 w32fullscreen_hook (f);
4995 }
4994 } 4996 }
4995 check_visibility = 1; 4997 check_visibility = 1;
4996 break; 4998 break;
@@ -5269,11 +5271,18 @@ w32_read_socket (struct terminal *terminal,
5269 5271
5270 if (f) 5272 if (f)
5271 { 5273 {
5274 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
5275
5272 dpyinfo->n_cbits = msg.msg.wParam; 5276 dpyinfo->n_cbits = msg.msg.wParam;
5273 /* The new display could have a different resolution, in 5277 /* The new display could have a different resolution, in
5274 which case we must reconsider what fullscreen 5278 which case we must reconsider what fullscreen means.
5275 means. */ 5279 The following code is untested yet. */
5276 x_check_fullscreen (f); 5280 if (!NILP (fullscreen))
5281 {
5282 x_set_fullscreen (f, fullscreen, fullscreen);
5283 w32fullscreen_hook (f);
5284 }
5285
5277 DebPrint (("display change: %d %d\n", 5286 DebPrint (("display change: %d %d\n",
5278 (short) LOWORD (msg.msg.lParam), 5287 (short) LOWORD (msg.msg.lParam),
5279 (short) HIWORD (msg.msg.lParam))); 5288 (short) HIWORD (msg.msg.lParam)));
@@ -5959,75 +5968,6 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
5959 unblock_input (); 5968 unblock_input ();
5960} 5969}
5961 5970
5962/* Calculate fullscreen size. Return in *TOP_POS and *LEFT_POS the
5963 wanted positions of the WM window (not Emacs window).
5964 Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
5965 window (FRAME_X_WINDOW).
5966 */
5967
5968static void
5969x_fullscreen_adjust (struct frame *f, int *width, int *height, int *top_pos, int *left_pos)
5970{
5971 int newwidth = FRAME_COLS (f);
5972 int newheight = FRAME_LINES (f);
5973 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
5974
5975 *top_pos = f->top_pos;
5976 *left_pos = f->left_pos;
5977
5978 if (f->want_fullscreen & FULLSCREEN_HEIGHT)
5979 {
5980 int ph;
5981
5982 ph = x_display_pixel_height (dpyinfo);
5983 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
5984 ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, newheight) - f->y_pixels_diff;
5985 newheight = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, ph);
5986 *top_pos = 0;
5987 }
5988
5989 if (f->want_fullscreen & FULLSCREEN_WIDTH)
5990 {
5991 int pw;
5992
5993 pw = x_display_pixel_width (dpyinfo);
5994 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
5995 pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, newwidth) - f->x_pixels_diff;
5996 newwidth = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pw);
5997 *left_pos = 0;
5998 }
5999
6000 *width = newwidth;
6001 *height = newheight;
6002}
6003
6004/* Check if we need to resize the frame due to a fullscreen request.
6005 If so needed, resize the frame. */
6006static void
6007x_check_fullscreen (struct frame *f)
6008{
6009 if (f->want_fullscreen & FULLSCREEN_BOTH)
6010 {
6011 int width, height, ign;
6012
6013 x_real_positions (f, &f->left_pos, &f->top_pos);
6014
6015 x_fullscreen_adjust (f, &width, &height, &ign, &ign);
6016
6017 /* We do not need to move the window, it shall be taken care of
6018 when setting WM manager hints. */
6019 if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
6020 {
6021 change_frame_size (f, width, height, 0, 1, 0, 0);
6022 SET_FRAME_GARBAGED (f);
6023 cancel_mouse_face (f);
6024
6025 /* Wait for the change of frame size to occur. */
6026 f->want_fullscreen |= FULLSCREEN_WAIT;
6027 }
6028 }
6029}
6030
6031static void 5971static void
6032w32fullscreen_hook (struct frame *f) 5972w32fullscreen_hook (struct frame *f)
6033{ 5973{
@@ -6074,6 +6014,10 @@ w32fullscreen_hook (struct frame *f)
6074 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top, 6014 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
6075 rect.right - rect.left, rect.bottom - rect.top, 6015 rect.right - rect.left, rect.bottom - rect.top,
6076 SWP_NOOWNERZORDER | SWP_FRAMECHANGED); 6016 SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
6017 change_frame_size
6018 (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, rect.right - rect.left),
6019 FRAME_PIXEL_TO_TEXT_HEIGHT (f, rect.bottom - rect.top),
6020 0, 1, 0, 1);
6077 } 6021 }
6078 else 6022 else
6079 { 6023 {
@@ -6082,10 +6026,39 @@ w32fullscreen_hook (struct frame *f)
6082 FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect); 6026 FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
6083 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top, 6027 SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
6084 rect.right - rect.left, rect.bottom - rect.top, 0); 6028 rect.right - rect.left, rect.bottom - rect.top, 0);
6029
6030 if (f->want_fullscreen == FULLSCREEN_WIDTH)
6031 {
6032 int border_width = GetSystemMetrics (SM_CXFRAME);
6033
6034 change_frame_size
6035 (f, (FRAME_PIXEL_TO_TEXT_WIDTH
6036 (f, rect.right - rect.left - 2 * border_width)),
6037 0, 0, 1, 0, 1);
6038 }
6039 else
6040 {
6041 int border_height = GetSystemMetrics (SM_CYFRAME);
6042 /* Won't work for wrapped menu bar. */
6043 int menu_bar_height = GetSystemMetrics (SM_CYMENU);
6044 int title_height = GetSystemMetrics (SM_CYCAPTION);
6045
6046 change_frame_size
6047 (f, 0, (FRAME_PIXEL_TO_TEXT_HEIGHT
6048 (f, rect.bottom - rect.top - 2 * border_height
6049 - title_height - menu_bar_height)),
6050 0, 1, 0, 1);
6051 }
6085 } 6052 }
6086 6053
6087 f->want_fullscreen = FULLSCREEN_NONE; 6054 f->want_fullscreen = FULLSCREEN_NONE;
6088 unblock_input (); 6055 unblock_input ();
6056
6057 if (f->want_fullscreen == FULLSCREEN_BOTH
6058 || f->want_fullscreen == FULLSCREEN_WIDTH
6059 || f->want_fullscreen == FULLSCREEN_HEIGHT)
6060 do_pending_window_change (0);
6061
6089 } 6062 }
6090 else 6063 else
6091 f->want_fullscreen |= FULLSCREEN_WAIT; 6064 f->want_fullscreen |= FULLSCREEN_WAIT;
@@ -6101,6 +6074,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
6101 int width, int height, bool pixelwise) 6074 int width, int height, bool pixelwise)
6102{ 6075{
6103 int pixelwidth, pixelheight; 6076 int pixelwidth, pixelheight;
6077 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
6104 RECT rect; 6078 RECT rect;
6105 6079
6106 block_input (); 6080 block_input ();
@@ -6119,7 +6093,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
6119 if (w32_add_wrapped_menu_bar_lines) 6093 if (w32_add_wrapped_menu_bar_lines)
6120 { 6094 {
6121 /* When the menu bar wraps sending a SetWindowPos shrinks the 6095 /* When the menu bar wraps sending a SetWindowPos shrinks the
6122 height of the frame when the wrapped menu bar lines are not 6096 height of the frame then the wrapped menu bar lines are not
6123 accounted for (Bug#15174 and Bug#18720). Here we add these 6097 accounted for (Bug#15174 and Bug#18720). Here we add these
6124 extra lines to the frame height. */ 6098 extra lines to the frame height. */
6125 MENUBARINFO info; 6099 MENUBARINFO info;
@@ -6143,9 +6117,6 @@ x_set_window_size (struct frame *f, bool change_gravity,
6143 f->win_gravity = NorthWestGravity; 6117 f->win_gravity = NorthWestGravity;
6144 x_wm_set_size_hint (f, (long) 0, false); 6118 x_wm_set_size_hint (f, (long) 0, false);
6145 6119
6146 f->want_fullscreen = FULLSCREEN_NONE;
6147 w32fullscreen_hook (f);
6148
6149 rect.left = rect.top = 0; 6120 rect.left = rect.top = 0;
6150 rect.right = pixelwidth; 6121 rect.right = pixelwidth;
6151 rect.bottom = pixelheight; 6122 rect.bottom = pixelheight;
@@ -6153,45 +6124,45 @@ x_set_window_size (struct frame *f, bool change_gravity,
6153 AdjustWindowRect (&rect, f->output_data.w32->dwStyle, 6124 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
6154 FRAME_EXTERNAL_MENU_BAR (f)); 6125 FRAME_EXTERNAL_MENU_BAR (f));
6155 6126
6156 my_set_window_pos (FRAME_W32_WINDOW (f), 6127 if (!(f->after_make_frame)
6157 NULL, 6128 && !(f->want_fullscreen & FULLSCREEN_WAIT)
6158 0, 0, 6129 && FRAME_VISIBLE_P (f))
6159 rect.right - rect.left, 6130 {
6160 rect.bottom - rect.top, 6131 RECT window_rect;
6161 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); 6132
6162 6133 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
6163 /* If w32_enable_frame_resize_hack is non-nil, immediately apply the
6164 new pixel sizes to the frame and its subwindows.
6165
6166 Jason Rumney earlier refused to call change_frame_size right here
6167 with the following argument:
6168
6169 The following mirrors what is done in xterm.c. It appears to be for
6170 informing lisp of the new size immediately, while the actual resize
6171 will happen asynchronously. But on Windows, the menu bar
6172 automatically wraps when the frame is too narrow to contain it, and
6173 that causes any calculations made here to come out wrong. The end
6174 is some nasty buggy behavior, including the potential loss of the
6175 minibuffer.
6176
6177 Disabling this code is either not sufficient to fix the problems
6178 completely, or it causes fresh problems, but at least it removes
6179 the most problematic symptom of the minibuffer becoming unusable.
6180
6181 However, as the discussion about how to handle frame size
6182 parameters on Windows (Bug#1348, Bug#16028) shows, that cure seems
6183 worse than the disease. In particular, menu bar wrapping looks
6184 like a non-issue - maybe so because Windows eventually gets back to
6185 us with the correct client rectangle anyway. But we have to avoid
6186 calling change_frame_size with a delta of less than one canoncial
6187 character size when frame_resize_pixelwise is nil, as explained in
6188 the comment above. */
6189
6190 if (w32_enable_frame_resize_hack)
6191 6134
6135 if (EQ (fullscreen, Qmaximized)
6136 || EQ (fullscreen, Qfullboth)
6137 || EQ (fullscreen, Qfullwidth))
6138 {
6139 rect.left = window_rect.left;
6140 rect.right = window_rect.right;
6141 pixelwidth = 0;
6142 }
6143 if (EQ (fullscreen, Qmaximized)
6144 || EQ (fullscreen, Qfullboth)
6145 || EQ (fullscreen, Qfullheight))
6146 {
6147 rect.top = window_rect.top;
6148 rect.bottom = window_rect.bottom;
6149 pixelheight = 0;
6150 }
6151 }
6152
6153 if (pixelwidth > 0 || pixelheight > 0)
6192 { 6154 {
6193 change_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth), 6155 my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
6194 FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight), 6156 0, 0,
6157 rect.right - rect.left,
6158 rect.bottom - rect.top,
6159 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
6160
6161 change_frame_size (f,
6162 ((pixelwidth == 0)
6163 ? 0 : FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth)),
6164 ((pixelheight == 0)
6165 ? 0 : FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)),
6195 0, 1, 0, 1); 6166 0, 1, 0, 1);
6196 SET_FRAME_GARBAGED (f); 6167 SET_FRAME_GARBAGED (f);
6197 6168
@@ -7102,7 +7073,7 @@ Windows 8. It is set to nil on Windows 9X. */);
7102 w32_unicode_filenames = 0; 7073 w32_unicode_filenames = 0;
7103 7074
7104 7075
7105 /* FIXME: The following two variables will be (hopefully) removed 7076 /* FIXME: The following variable will be (hopefully) removed
7106 before Emacs 25.1 gets released. */ 7077 before Emacs 25.1 gets released. */
7107 7078
7108 DEFVAR_BOOL ("w32-add-wrapped-menu-bar-lines", 7079 DEFVAR_BOOL ("w32-add-wrapped-menu-bar-lines",
@@ -7116,16 +7087,6 @@ wrapped menu bar lines when sending frame resize requests to the Windows
7116API. */); 7087API. */);
7117 w32_add_wrapped_menu_bar_lines = 1; 7088 w32_add_wrapped_menu_bar_lines = 1;
7118 7089
7119 DEFVAR_BOOL ("w32-enable-frame-resize-hack",
7120 w32_enable_frame_resize_hack,
7121 doc: /* Non-nil means enable hack for frame resizing on Windows.
7122A value of nil means to resize frames by sending a corresponding request
7123to the Windows API and changing the pixel sizes of the frame and its
7124windows after the latter calls back. If this is non-nil, Emacs changes
7125the pixel sizes of the frame and its windows at the time it sends the
7126resize request to the API. */);
7127 w32_enable_frame_resize_hack = 1;
7128
7129 /* Tell Emacs about this window system. */ 7090 /* Tell Emacs about this window system. */
7130 Fprovide (Qw32, Qnil); 7091 Fprovide (Qw32, Qnil);
7131} 7092}
diff --git a/src/widget.c b/src/widget.c
index c4d69407176..acf559f313b 100644
--- a/src/widget.c
+++ b/src/widget.c
@@ -460,7 +460,7 @@ update_wm_hints (EmacsFrame ew)
460 base_width = (wmshell->core.width - ew->core.width 460 base_width = (wmshell->core.width - ew->core.width
461 + (rounded_width - (char_width * cw))); 461 + (rounded_width - (char_width * cw)));
462 base_height = (wmshell->core.height - ew->core.height 462 base_height = (wmshell->core.height - ew->core.height
463 + (rounded_height - (char_height * ch))); 463 + (rounded_height - (char_height * ch)));
464 464
465 /* This is kind of sleazy, but I can't see how else to tell it to 465 /* This is kind of sleazy, but I can't see how else to tell it to
466 make it mark the WM_SIZE_HINTS size as user specified. 466 make it mark the WM_SIZE_HINTS size as user specified.
@@ -573,39 +573,20 @@ EmacsFrameResize (Widget widget)
573{ 573{
574 EmacsFrame ew = (EmacsFrame)widget; 574 EmacsFrame ew = (EmacsFrame)widget;
575 struct frame *f = ew->emacs_frame.frame; 575 struct frame *f = ew->emacs_frame.frame;
576 int width, height;
576 577
577 /* Always process resize requests pixelwise. Frame maximizing 578 pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height);
578 should work even when frame_resize_pixelwise is nil. */
579 if (true || frame_resize_pixelwise)
580 {
581 int width, height;
582
583 pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height);
584 change_frame_size (f, width, height, 0, 1, 0, 1);
585 579
586 update_wm_hints (ew); 580 frame_size_history_add
587 update_various_frame_slots (ew); 581 (f, QEmacsFrameResize, width, height,
582 list2 (make_number (ew->core.width), make_number (ew->core.height)));
588 583
589 cancel_mouse_face (f); 584 change_frame_size (f, width, height, 0, 1, 0, 1);
590 }
591 else
592 {
593 struct x_output *x = f->output_data.x;
594 int columns, rows;
595 585
596 pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows); 586 update_wm_hints (ew);
597 if (columns != FRAME_COLS (f) 587 update_various_frame_slots (ew);
598 || rows != FRAME_LINES (f)
599 || ew->core.width != FRAME_PIXEL_WIDTH (f)
600 || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
601 {
602 change_frame_size (f, columns, rows, 0, 1, 0, 0);
603 update_wm_hints (ew);
604 update_various_frame_slots (ew);
605 588
606 cancel_mouse_face (f); 589 cancel_mouse_face (f);
607 }
608 }
609} 590}
610 591
611static XtGeometryResult 592static XtGeometryResult
diff --git a/src/window.c b/src/window.c
index 2f44bf78304..293140041a9 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3329,7 +3329,7 @@ run_window_configuration_change_hook (struct frame *f)
3329 3329
3330 if (NILP (Vrun_hooks) 3330 if (NILP (Vrun_hooks)
3331 || !(f->can_x_set_window_size) 3331 || !(f->can_x_set_window_size)
3332 || !(f->can_run_window_configuration_change_hook)) 3332 || !(f->after_make_frame))
3333 return; 3333 return;
3334 3334
3335 /* Use the right buffer. Matters when running the local hooks. */ 3335 /* Use the right buffer. Matters when running the local hooks. */
diff --git a/src/xfns.c b/src/xfns.c
index 65eb6b497f2..e667e71b563 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1095,6 +1095,7 @@ x_change_tool_bar_height (struct frame *f, int height)
1095 int unit = FRAME_LINE_HEIGHT (f); 1095 int unit = FRAME_LINE_HEIGHT (f);
1096 int old_height = FRAME_TOOL_BAR_HEIGHT (f); 1096 int old_height = FRAME_TOOL_BAR_HEIGHT (f);
1097 int lines = (height + unit - 1) / unit; 1097 int lines = (height + unit - 1) / unit;
1098 Lisp_Object fullscreen;
1098 1099
1099 /* Make sure we redisplay all windows in this frame. */ 1100 /* Make sure we redisplay all windows in this frame. */
1100 windows_or_buffers_changed = 60; 1101 windows_or_buffers_changed = 60;
@@ -1126,7 +1127,10 @@ x_change_tool_bar_height (struct frame *f, int height)
1126 f->n_tool_bar_rows = 0; 1127 f->n_tool_bar_rows = 0;
1127 1128
1128 adjust_frame_size (f, -1, -1, 1129 adjust_frame_size (f, -1, -1,
1129 (!f->tool_bar_redisplayed_once ? 1 1130 ((!f->tool_bar_redisplayed_once
1131 && (NILP (fullscreen =
1132 get_frame_param (f, Qfullscreen))
1133 || EQ (fullscreen, Qfullwidth))) ? 1
1130 : (old_height == 0 || height == 0) ? 2 1134 : (old_height == 0 || height == 0) ? 2
1131 : 4), 1135 : 4),
1132 false, Qtool_bar_lines); 1136 false, Qtool_bar_lines);
@@ -3180,9 +3184,7 @@ This function is an internal primitive--use `make-frame' instead. */)
3180 "title", "Title", RES_TYPE_STRING); 3184 "title", "Title", RES_TYPE_STRING);
3181 x_default_parameter (f, parms, Qwait_for_wm, Qt, 3185 x_default_parameter (f, parms, Qwait_for_wm, Qt,
3182 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); 3186 "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
3183 x_default_parameter (f, parms, Qfullscreen, Qnil, 3187 x_default_parameter (f, parms, Qtool_bar_position,
3184 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3185 x_default_parameter (f, parms, Qtool_bar_position,
3186 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); 3188 FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
3187 3189
3188 /* Compute the size of the X window. */ 3190 /* Compute the size of the X window. */
@@ -3259,6 +3261,12 @@ This function is an internal primitive--use `make-frame' instead. */)
3259 x_wm_set_size_hint (f, window_prompting, false); 3261 x_wm_set_size_hint (f, window_prompting, false);
3260 unblock_input (); 3262 unblock_input ();
3261 3263
3264 /* Process fullscreen parameter here in the hope that normalizing a
3265 fullheight/fullwidth frame will produce the size set by the last
3266 adjust_frame_size call. */
3267 x_default_parameter (f, parms, Qfullscreen, Qnil,
3268 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
3269
3262 /* Make the window appear on the frame and enable display, unless 3270 /* Make the window appear on the frame and enable display, unless
3263 the caller says not to. However, with explicit parent, Emacs 3271 the caller says not to. However, with explicit parent, Emacs
3264 cannot control visibility, so don't try. */ 3272 cannot control visibility, so don't try. */
@@ -4318,7 +4326,7 @@ elements (all size values are in pixels).
4318 inner_height -= tool_bar_height; 4326 inner_height -= tool_bar_height;
4319 4327
4320 return 4328 return
4321 listn (CONSTYPE_PURE, 10, 4329 listn (CONSTYPE_HEAP, 10,
4322 Fcons (Qframe_position, 4330 Fcons (Qframe_position,
4323 Fcons (make_number (f->left_pos), make_number (f->top_pos))), 4331 Fcons (make_number (f->left_pos), make_number (f->top_pos))),
4324 Fcons (Qframe_outer_size, 4332 Fcons (Qframe_outer_size,
diff --git a/src/xterm.c b/src/xterm.c
index 3955d027a52..6a63a454bac 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -212,7 +212,7 @@ enum xembed_message
212 }; 212 };
213 213
214static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *); 214static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
215static void x_set_window_size_1 (struct frame *, bool, int, int, bool); 215static void x_set_window_size_1 (struct frame *, bool, int, int);
216static void x_raise_frame (struct frame *); 216static void x_raise_frame (struct frame *);
217static void x_lower_frame (struct frame *); 217static void x_lower_frame (struct frame *);
218static const XColor *x_color_cells (Display *, int *); 218static const XColor *x_color_cells (Display *, int *);
@@ -6575,6 +6575,10 @@ x_net_wm_state (struct frame *f, Window window)
6575 break; 6575 break;
6576 } 6576 }
6577 6577
6578 frame_size_history_add
6579 (f, Qx_net_wm_state, 0, 0,
6580 list2 (get_frame_param (f, Qfullscreen), lval));
6581
6578 store_frame_param (f, Qfullscreen, lval); 6582 store_frame_param (f, Qfullscreen, lval);
6579/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/ 6583/** store_frame_param (f, Qsticky, sticky ? Qt : Qnil); **/
6580} 6584}
@@ -9227,30 +9231,78 @@ do_ewmh_fullscreen (struct frame *f)
9227 None); 9231 None);
9228 break; 9232 break;
9229 case FULLSCREEN_WIDTH: 9233 case FULLSCREEN_WIDTH:
9230 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT 9234 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
9231 || cur == FULLSCREEN_MAXIMIZED) 9235 {
9232 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen, 9236 set_wm_state (frame, false,
9233 dpyinfo->Xatom_net_wm_state_maximized_vert); 9237 dpyinfo->Xatom_net_wm_state_maximized_horz,
9234 if (cur != FULLSCREEN_MAXIMIZED) 9238 dpyinfo->Xatom_net_wm_state_maximized_vert);
9235 set_wm_state (frame, true, 9239 set_wm_state (frame, true,
9236 dpyinfo->Xatom_net_wm_state_maximized_horz, None); 9240 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
9241 }
9242 else
9243 {
9244 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_HEIGHT
9245 || cur == FULLSCREEN_MAXIMIZED)
9246 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
9247 dpyinfo->Xatom_net_wm_state_maximized_vert);
9248 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
9249 set_wm_state (frame, true,
9250 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
9251 }
9237 break; 9252 break;
9238 case FULLSCREEN_HEIGHT: 9253 case FULLSCREEN_HEIGHT:
9239 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH 9254 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_MAXIMIZED)
9240 || cur == FULLSCREEN_MAXIMIZED) 9255 {
9241 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen, 9256 set_wm_state (frame, false,
9242 dpyinfo->Xatom_net_wm_state_maximized_horz); 9257 dpyinfo->Xatom_net_wm_state_maximized_horz,
9243 if (cur != FULLSCREEN_MAXIMIZED) 9258 dpyinfo->Xatom_net_wm_state_maximized_vert);
9244 set_wm_state (frame, true, 9259 set_wm_state (frame, true,
9245 dpyinfo->Xatom_net_wm_state_maximized_vert, None); 9260 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
9261 }
9262 else
9263 {
9264 if (cur == FULLSCREEN_BOTH || cur == FULLSCREEN_WIDTH
9265 || cur == FULLSCREEN_MAXIMIZED)
9266 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
9267 dpyinfo->Xatom_net_wm_state_maximized_horz);
9268 if (cur != FULLSCREEN_MAXIMIZED || x_frame_normalize_before_maximize)
9269 set_wm_state (frame, true,
9270 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
9271 }
9246 break; 9272 break;
9247 case FULLSCREEN_MAXIMIZED: 9273 case FULLSCREEN_MAXIMIZED:
9248 if (cur == FULLSCREEN_BOTH) 9274 if (x_frame_normalize_before_maximize && cur == FULLSCREEN_WIDTH)
9249 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen, 9275 {
9250 None); 9276 set_wm_state (frame, false,
9251 set_wm_state (frame, true, 9277 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
9252 dpyinfo->Xatom_net_wm_state_maximized_horz, 9278 set_wm_state (frame, true,
9253 dpyinfo->Xatom_net_wm_state_maximized_vert); 9279 dpyinfo->Xatom_net_wm_state_maximized_horz,
9280 dpyinfo->Xatom_net_wm_state_maximized_vert);
9281 }
9282 else if (x_frame_normalize_before_maximize && cur == FULLSCREEN_HEIGHT)
9283 {
9284 set_wm_state (frame, false,
9285 dpyinfo->Xatom_net_wm_state_maximized_vert, None);
9286 set_wm_state (frame, true,
9287 dpyinfo->Xatom_net_wm_state_maximized_horz,
9288 dpyinfo->Xatom_net_wm_state_maximized_vert);
9289 }
9290 else
9291 {
9292 if (cur == FULLSCREEN_BOTH)
9293 set_wm_state (frame, false, dpyinfo->Xatom_net_wm_state_fullscreen,
9294 None);
9295 else if (cur == FULLSCREEN_HEIGHT)
9296 set_wm_state (frame, true,
9297 dpyinfo->Xatom_net_wm_state_maximized_horz, None);
9298 else if (cur == FULLSCREEN_WIDTH)
9299 set_wm_state (frame, true, None,
9300 dpyinfo->Xatom_net_wm_state_maximized_vert);
9301 else
9302 set_wm_state (frame, true,
9303 dpyinfo->Xatom_net_wm_state_maximized_horz,
9304 dpyinfo->Xatom_net_wm_state_maximized_vert);
9305 }
9254 break; 9306 break;
9255 case FULLSCREEN_NONE: 9307 case FULLSCREEN_NONE:
9256 if (cur == FULLSCREEN_BOTH) 9308 if (cur == FULLSCREEN_BOTH)
@@ -9307,6 +9359,10 @@ x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
9307 break; 9359 break;
9308 } 9360 }
9309 9361
9362 frame_size_history_add
9363 (f, Qx_handle_net_wm_state, 0, 0,
9364 list2 (get_frame_param (f, Qfullscreen), lval));
9365
9310 store_frame_param (f, Qfullscreen, lval); 9366 store_frame_param (f, Qfullscreen, lval);
9311 store_frame_param (f, Qsticky, sticky ? Qt : Qnil); 9367 store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
9312 9368
@@ -9343,13 +9399,26 @@ x_check_fullscreen (struct frame *f)
9343 break; 9399 break;
9344 case FULLSCREEN_WIDTH: 9400 case FULLSCREEN_WIDTH:
9345 width = x_display_pixel_width (dpyinfo); 9401 width = x_display_pixel_width (dpyinfo);
9346 break; 9402 height = height + FRAME_MENUBAR_HEIGHT (f);
9403 break;
9347 case FULLSCREEN_HEIGHT: 9404 case FULLSCREEN_HEIGHT:
9348 height = x_display_pixel_height (dpyinfo); 9405 height = x_display_pixel_height (dpyinfo);
9349 } 9406 }
9350 9407
9408 frame_size_history_add
9409 (f, Qx_check_fullscreen, width, height, Qnil);
9410
9351 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 9411 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9352 width, height); 9412 width, height);
9413
9414 if (FRAME_VISIBLE_P (f))
9415 x_wait_for_event (f, ConfigureNotify);
9416 else
9417 {
9418 change_frame_size (f, width, height - FRAME_MENUBAR_HEIGHT (f),
9419 false, true, false, true);
9420 x_sync (f);
9421 }
9353 } 9422 }
9354} 9423}
9355 9424
@@ -9490,21 +9559,57 @@ x_wait_for_event (struct frame *f, int eventtype)
9490 9559
9491static void 9560static void
9492x_set_window_size_1 (struct frame *f, bool change_gravity, 9561x_set_window_size_1 (struct frame *f, bool change_gravity,
9493 int width, int height, bool pixelwise) 9562 int width, int height)
9494{ 9563{
9495 int pixelwidth, pixelheight; 9564 int pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
9496 9565 int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
9497 pixelwidth = (pixelwise 9566 int old_width = FRAME_PIXEL_WIDTH (f);
9498 ? FRAME_TEXT_TO_PIXEL_WIDTH (f, width) 9567 int old_height = FRAME_PIXEL_HEIGHT (f);
9499 : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width)); 9568 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
9500 pixelheight = ((pixelwise
9501 ? FRAME_TEXT_TO_PIXEL_HEIGHT (f, height)
9502 : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height)));
9503 9569
9504 if (change_gravity) f->win_gravity = NorthWestGravity; 9570 if (change_gravity) f->win_gravity = NorthWestGravity;
9505 x_wm_set_size_hint (f, 0, false); 9571 x_wm_set_size_hint (f, 0, false);
9506 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 9572
9507 pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f)); 9573 /* When the frame is fullheight and we only want to change the width
9574 or it is fullwidth and we only want to change the height we should
9575 be able to preserve the fullscreen property. However, due to the
9576 fact that we have to send a resize request anyway, the window
9577 manager will abolish it. At least the respective size should
9578 remain unchanged but giving the frame back its normal size will
9579 be broken ... */
9580 if (EQ (fullscreen, Qfullwidth) && width == FRAME_TEXT_WIDTH (f))
9581 {
9582 frame_size_history_add
9583 (f, Qxg_frame_set_char_size_1, width, height,
9584 list2 (make_number (old_height),
9585 make_number (pixelheight + FRAME_MENUBAR_HEIGHT (f))));
9586
9587 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9588 old_width, pixelheight + FRAME_MENUBAR_HEIGHT (f));
9589 }
9590 else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f))
9591 {
9592 frame_size_history_add
9593 (f, Qxg_frame_set_char_size_2, width, height,
9594 list2 (make_number (old_width), make_number (pixelwidth)));
9595
9596 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9597 pixelwidth, old_height);
9598 }
9599
9600 else
9601 {
9602 frame_size_history_add
9603 (f, Qxg_frame_set_char_size_3, width, height,
9604 list2 (make_number (pixelwidth + FRAME_TOOLBAR_WIDTH (f)),
9605 make_number (pixelheight + FRAME_TOOLBAR_HEIGHT (f)
9606 + FRAME_MENUBAR_HEIGHT (f))));
9607
9608 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
9609 pixelwidth, pixelheight + FRAME_MENUBAR_HEIGHT (f));
9610 fullscreen = Qnil;
9611 }
9612
9508 9613
9509 9614
9510 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to 9615 /* 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,
9531 not right if the frame is visible. Instead wait (with timeout) 9636 not right if the frame is visible. Instead wait (with timeout)
9532 for the ConfigureNotify. */ 9637 for the ConfigureNotify. */
9533 if (FRAME_VISIBLE_P (f)) 9638 if (FRAME_VISIBLE_P (f))
9534 x_wait_for_event (f, ConfigureNotify); 9639 {
9640 x_wait_for_event (f, ConfigureNotify);
9641
9642 if (!NILP (fullscreen))
9643 /* Try to restore fullscreen state. */
9644 {
9645 store_frame_param (f, Qfullscreen, fullscreen);
9646 x_set_fullscreen (f, fullscreen, fullscreen);
9647 }
9648 }
9535 else 9649 else
9536 { 9650 {
9537 change_frame_size (f, width, height, false, true, false, true); 9651 change_frame_size (f, width, height, false, true, false, true);
@@ -9578,20 +9692,21 @@ x_set_window_size (struct frame *f, bool change_gravity,
9578 } 9692 }
9579#endif 9693#endif
9580 9694
9695 /* Pixelize width and height, if necessary. */
9696 if (! pixelwise)
9697 {
9698 width = width * FRAME_COLUMN_WIDTH (f);
9699 height = height * FRAME_LINE_HEIGHT (f);
9700 }
9701
9581#ifdef USE_GTK 9702#ifdef USE_GTK
9582 if (FRAME_GTK_WIDGET (f)) 9703 if (FRAME_GTK_WIDGET (f))
9583 if (! pixelwise) 9704 xg_frame_set_char_size (f, width, height);
9584 xg_frame_set_char_size (f, width * FRAME_COLUMN_WIDTH (f),
9585 height * FRAME_LINE_HEIGHT (f));
9586 else
9587 xg_frame_set_char_size (f, width, height);
9588 else 9705 else
9589 x_set_window_size_1 (f, change_gravity, width, height, pixelwise); 9706 x_set_window_size_1 (f, change_gravity, width, height);
9590#else /* not USE_GTK */ 9707#else /* not USE_GTK */
9591 9708 x_set_window_size_1 (f, change_gravity, width, height);
9592 x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
9593 x_clear_under_internal_border (f); 9709 x_clear_under_internal_border (f);
9594
9595#endif /* not USE_GTK */ 9710#endif /* not USE_GTK */
9596 9711
9597 /* If cursor was outside the new size, mark it as off. */ 9712 /* If cursor was outside the new size, mark it as off. */
@@ -11602,4 +11717,15 @@ default is nil, which is the same as `super'. */);
11602 make_float (DEFAULT_REHASH_SIZE), 11717 make_float (DEFAULT_REHASH_SIZE),
11603 make_float (DEFAULT_REHASH_THRESHOLD), 11718 make_float (DEFAULT_REHASH_THRESHOLD),
11604 Qnil); 11719 Qnil);
11720
11721 DEFVAR_BOOL ("x-frame-normalize-before-maximize",
11722 x_frame_normalize_before_maximize,
11723 doc: /* Non-nil means normalize frame before maximizing.
11724If this variable is t, Emacs asks the window manager to give the frame
11725intermediately its normal size whenever changing from a full-height or
11726full-width state to the fully maximized one and vice versa.
11727
11728Set this variable only if your window manager cannot handle the
11729transition between the various maximization states. */);
11730 x_frame_normalize_before_maximize = false;
11605} 11731}