From d1655783194f7b84ccac7114a2c341f10bc438b0 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Sat, 7 Feb 2015 11:51:03 +0100 Subject: [PATCH] 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. --- lisp/ChangeLog | 9 ++ lisp/faces.el | 3 +- lisp/frame.el | 23 ++++-- src/ChangeLog | 76 +++++++++++++++++ src/frame.c | 202 +++++++++++++++++++++++++++++++-------------- src/frame.h | 13 +-- src/gtkutil.c | 113 ++++++++++++++++++++----- src/w32fns.c | 18 ++-- src/w32term.c | 217 ++++++++++++++++++++----------------------------- src/widget.c | 39 +++------ src/window.c | 2 +- src/xfns.c | 18 ++-- src/xterm.c | 214 ++++++++++++++++++++++++++++++++++++++---------- 13 files changed, 641 insertions(+), 306 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index c67113f2a61..a3abb1a4f1f 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,12 @@ +2015-02-07 Martin Rudalics + + * 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 * vc/vc-cvs.el (vc-cvs-dir-status-files): Don't pass DIR to diff --git a/lisp/faces.el b/lisp/faces.el index 22bf2626722..ce74c728474 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -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." diff --git a/lisp/frame.el b/lisp/frame.el index 1d5bbf2317e..ecb433e8335 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -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)) diff --git a/src/ChangeLog b/src/ChangeLog index cd72f98c116..ec70cdb93a9 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,79 @@ +2015-02-07 Martin Rudalics + + * 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 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) 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; } @@ -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); 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 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; 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) 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 (); } 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) 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))), 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 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); } 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) 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 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) 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. */ 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) 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, 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 }; 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; } -- 2.39.2