diff --git a/etc/NEWS b/etc/NEWS index 6777d6c3b5e..f1b2225100d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -465,6 +465,13 @@ either resize the frame and change the fullscreen status accordingly or keep the frame size unchanged. The value t means to first reset the fullscreen status and then resize the frame. +*** New commands to set frame size and position in one compound step. +'set-frame-size-and-position' sets the new size and position of a frame +in one compound step. Both, size and position, can be specified as with +the corresponding frame parameters 'width', 'height', 'left' and 'top'. +'set-frame-size-and-position-pixelwise' is similar but has a more +restricted set of values for specifying size and position. + *** New commands 'split-frame' and 'merge-frames'. 'split-frame' moves a specified number of windows from an existing frame to a newly-created frame. 'merge-frames' merges all windows from two diff --git a/lisp/frame.el b/lisp/frame.el index 307312ef71a..d521d49c175 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1534,6 +1534,200 @@ Functions on this hook are called with the theme name as a symbol: `light' or `dark'. By the time the hook is called, `toolkit-theme' will already be set to one of these values as well.") + +(defun set-frame-size-and-position (&optional frame width height left top) + "Set size and position of specified FRAME in one compound step. +WIDTH and HEIGHT stand for the new width and height of FRAME. They can +be specified as follows where \"display area\" stands for the entire +display area of FRAME's dominating monitor, \"work area\" stands for the +work area (the usable space) of FRAME's display area and \"parent area\" +stands for the area occupied by the native rectangle of FRAME's parent +provided FRAME is a child frame. + +- An integer specifies the size of FRAME's text area in characters. + +- A cons cell with the symbol `text-pixels' in its car specifies in its + cdr the size of FRAME's text area in pixels. + +- A floating-point number between 0.0 and 1.0 specifies the ratio of + FRAME's outer size to the size of its work or parent area. + +Unless you use a plain integer value, you may have to set +`frame-resize-pixelwise' to a non-nil value in order to get the exact +size in pixels. A value of nil means to leave the width or height +unaltered. Any other value will signal an error. + +LEFT and TOP stand for FRAME's outer position relative to coordinates of +its display, work or parent area. They can be specified as follows: + +- An integer where a positive value relates the left or top edge of + FRAME to the origin of its display or parent area. A negative value + relates the right or bottom edge of FRAME to the right or bottom edge + of its display or parent area. + +- The symbol `-' means to place the right or bottom edge of FRAME at the + right or bottom edge of its display or parent area. + +- A list with `+' as its first and an integer as its second element + specifies the position of the left or top edge of FRAME relative to + the left or top edge of its display or parent area. If the second + element is negative, this means a position outside FRAME's display or + parent area. + +- A list with `-' as its first and an integer as its second element + specifies the position of the right or bottom edge of FRAME relative + to the right or bottom edge of its display or parent area. If the + second element is negative, this means a position outside the area of + its display or parent area. + +- A floating-point number between 0.0 and 1.0 specifies the ratio of + FRAME's outer position to the size of its work or parent area. Thus, + a value of 0.0 flushes FRAME to the left or top, a value of 0.5 + centers it and a ratio of 1.0 flushes it to the right or bottom of its + work or parent area. + +Calculating a position relative to the right or bottom edge of FRAME's +display, work or parent area proceeds by calculating the new size of +FRAME first and then relate the new prospective outer edges of FRAME to +the respective edges of its display, work or parent area. + +A value of nil means to leave the position in this direction unchanged. +Any other value will signal an error. + +This function calls `set-frame-size-and-position-pixelwise' to actually +resize and move FRAME." + (let* ((frame (window-normalize-frame frame)) + (parent (frame-parent frame)) + (monitor-attributes + (unless parent + (frame-monitor-attributes frame))) + (geometry + (unless parent + (cdr (assq 'geometry monitor-attributes)))) + (parent-or-display-width + (if parent + (frame-native-width parent) + (nth 2 geometry))) + (parent-or-display-height + (if parent + (frame-native-height parent) + (nth 3 geometry))) + (parent-or-workarea + (if parent + `(0 0 ,parent-or-display-width ,parent-or-display-height) + (cdr (assq 'workarea monitor-attributes)))) + (outer-edges (frame-edges frame 'outer-edges)) + (outer-left (nth 0 outer-edges)) + (outer-top (nth 1 outer-edges)) + (outer-width (if outer-edges + (- (nth 2 outer-edges) outer-left) + (frame-pixel-width frame))) + (outer-minus-text-width + (- outer-width (frame-text-width frame))) + (outer-height (if outer-edges + (- (nth 3 outer-edges) outer-top) + (frame-pixel-height frame))) + (outer-minus-text-height + (- outer-height (frame-text-height frame))) + (old-text-width (frame-text-width frame)) + (old-text-height (frame-text-height frame)) + (text-width old-text-width) + (text-height old-text-height) + (char-width (frame-char-width frame)) + (char-height (frame-char-height frame)) + (gravity 1) + negative) + + (cond + ((and (integerp width) (> width 0)) + (setq text-width (* width char-width))) + ((and (consp width) (eq (car width) 'text-pixels) + (integerp (cdr width)) (> (cdr width) 0)) + (setq text-width (cdr width))) + ((and (floatp width) (> width 0.0) (<= width 1.0)) + (setq text-width + (- (round (* width (- (nth 2 parent-or-workarea) + (nth 0 parent-or-workarea)))) + outer-minus-text-width))) + (width + (user-error "Invalid width specification"))) + + (cond + ((and (integerp height) (> height 0)) + (setq text-height (* height char-height))) + ((and (consp height) (eq (car height) 'text-pixels) + (integerp (cdr height)) (> (cdr height) 0)) + (setq text-height (cdr height))) + ((and (floatp height) (> height 0.0) (<= height 1.0)) + (setq text-height + (- (round (* height (- (nth 3 parent-or-workarea) + (nth 1 parent-or-workarea)))) + outer-minus-text-height))) + (width + (user-error "Invalid height specification"))) + + (cond + ((eq left '-) + (setq left 0) + (setq negative t)) + ((integerp left) + (setq negative (< left 0))) + ((consp left) + (cond + ((and (eq (car left) '-) (integerp (cadr left))) + (setq left (- (cadr left))) + (setq negative t)) + ((and (eq (car left) '+) (integerp (cadr left))) + (setq left (cadr left))) + (t + (user-error "Invalid position specification")))) + ((floatp left) + (setq left + (round (* left (- (nth 2 parent-or-workarea) + (nth 0 parent-or-workarea)))))) + (t (setq left outer-left))) + + (when negative + (setq gravity 3) + (setq left (- parent-or-display-width (- left) + (+ text-width + (frame-scroll-bar-width frame) + (frame-fringe-width frame) + (* 2 (frame-internal-border-width frame)) + outer-minus-text-width)))) + + (setq negative nil) + (cond + ((eq top '-) + (setq top 0) + (setq negative t)) + ((integerp top) + (setq negative (< top 0))) + ((consp top) + (cond + ((and (eq (car top) '-) (integerp (cadr top))) + (setq top (- (cadr top))) + (setq negative t)) + ((and (eq (car top) '+) (integerp (cadr top))) + (setq top (cadr top))) + (t + (user-error "Invalid position specification")))) + ((floatp top) + (setq top + (round (* top (- (nth 3 parent-or-workarea) + (nth 1 parent-or-workarea)))))) + (t (setq top outer-top))) + + (when negative + ;; This should get us 7 or 9. + (setq gravity (+ gravity 6)) + (setq top (- parent-or-display-height (- top) + (+ text-height + (* 2 (frame-internal-border-width frame))) + outer-minus-text-height))) + + (set-frame-size-and-position-pixelwise + frame text-width text-height left top gravity))) ;;;; Frame configurations diff --git a/src/frame.c b/src/frame.c index 49317379354..c226852bc09 100644 --- a/src/frame.c +++ b/src/frame.c @@ -777,6 +777,7 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, int old_text_width = FRAME_TEXT_WIDTH (f); int old_text_height = FRAME_TEXT_HEIGHT (f); bool inhibit_horizontal, inhibit_vertical; + bool size_and_position = EQ (parameter, Qsize_and_position); Lisp_Object frame; XSETFRAME (frame, f); @@ -855,7 +856,8 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, /* For inhibit == 1 call the window_size_hook only if a native size changes. For inhibit == 0 or inhibit == 2 always call it. */ - && ((!inhibit_horizontal + && (size_and_position + || (!inhibit_horizontal && (new_native_width != old_native_width || inhibit == 0 || inhibit == 2)) || (!inhibit_vertical @@ -907,7 +909,13 @@ adjust_frame_size (struct frame *f, int new_text_width, int new_text_height, f->new_size_p = false; } - if (FRAME_TERMINAL (f)->set_window_size_hook) + if (size_and_position) + /* The caller must have set the new position and gravity and + made sure that set_window_size_and_position_hook has been + defined. */ + FRAME_TERMINAL (f)->set_window_size_and_position_hook + (f, new_native_width, new_native_height); + else if (FRAME_TERMINAL (f)->set_window_size_hook) FRAME_TERMINAL (f)->set_window_size_hook (f, 0, new_native_width, new_native_height); f->resized_p = true; @@ -4545,6 +4553,69 @@ bottom edge of FRAME's display. */) return Qt; } +DEFUN ("set-frame-size-and-position-pixelwise", Fset_frame_size_and_position_pixelwise, + Sset_frame_size_and_position_pixelwise, 5, 6, 0, + doc: /* Set FRAME's size to WIDTH and HEIGHT and its position to (X, Y). +FRAME must be a live frame and defaults to the selected one. + +WIDTH and HEIGHT must be positive integers and specify the new pixel +width and height of FRAME's text area in pixels. If WIDTH or HEIGHT do +not secify a value that is a multiple of FRAME's character sizes, you +may have to set `frame-resize-pixelwise' to a non-nil value in order to +get the exact size in pixels. + +X and Y specify the coordinates of the left and top edge of FRAME's +outer frame in pixels relative to an origin (0, 0) of FRAME's display or +parent frame. Negative values mean the top or left edge may be outside +the display or parent frame. + +GRAVITY specifies the new gravity of FRAME and must be a value in the +range 0..10. It defaults to 1. + +This function uses any existing backend of the toolkit to resize and +move FRAME in one compound step. If the backend does not provide such a +function, it calls `set-frame-size' followed by `set-frame-position' +instead. See 'set-frame-size-and-position'. */) + (Lisp_Object frame, Lisp_Object width, Lisp_Object height, + Lisp_Object x, Lisp_Object y, Lisp_Object gravity) +{ + struct frame *f = decode_live_frame (frame); + + if (NILP (gravity)) + f->win_gravity = 1; + else + f->win_gravity = check_integer_range (gravity, 0, 10); + + if (FRAME_WINDOW_P (f) + && FRAME_TERMINAL (f)->set_window_size_and_position_hook) + { + int text_width = check_integer_range (width, 1, INT_MAX); + int text_height = check_integer_range (height, 1, INT_MAX); + + f->left_pos = check_integer_range (x, INT_MIN, INT_MAX); + f->top_pos = check_integer_range (y, INT_MIN, INT_MAX); + + adjust_frame_size (f, text_width, text_height, 1, false, + Qsize_and_position); + } + else + { + Fset_frame_size (frame, width, height, Qt); + + int left_pos = check_integer_range (x, INT_MIN, INT_MAX); + int top_pos = check_integer_range (y, INT_MIN, INT_MAX); + + Lisp_Object left + = Fcons (Qleft, left_pos < 0 ? list2 (Qplus, x) : x); + Lisp_Object top + = Fcons (Qtop, top_pos < 0 ? list2 (Qplus, y) : y); + + Fmodify_frame_parameters (frame, list2 (left, top)); + } + + return Qnil; +} + DEFUN ("frame-window-state-change", Fframe_window_state_change, Sframe_window_state_change, 0, 1, 0, doc: /* Return t if FRAME's window state change flag is set, nil otherwise. @@ -7113,6 +7184,7 @@ syms_of_frame (void) DEFSYM (Qmin_height, "min-height"); DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame"); DEFSYM (Qkeep_ratio, "keep-ratio"); + DEFSYM (Qsize_and_position, "size-and-position"); DEFSYM (Qwidth_only, "width-only"); DEFSYM (Qheight_only, "height-only"); DEFSYM (Qleft_only, "left-only"); @@ -7593,6 +7665,7 @@ The default is \\+`inhibit' in NS builds and nil everywhere else. */); defsubr (&Sset_frame_size); defsubr (&Sframe_position); defsubr (&Sset_frame_position); + defsubr (&Sset_frame_size_and_position_pixelwise); defsubr (&Sframe_pointer_visible_p); defsubr (&Smouse_position_in_root_frame); defsubr (&Sframe__set_was_invisible); diff --git a/src/gtkutil.c b/src/gtkutil.c index 7ad6c7ce8c4..9eaf4723bb0 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1384,6 +1384,67 @@ xg_height_or_width_changed (struct frame *f) } #endif +/** Move and resize the outer window of frame F. WIDTH and HEIGHT are + the new native pixel sizes of F. */ +void +xg_frame_set_size_and_position (struct frame *f, int width, int height) +{ + int outer_height + = height + FRAME_TOOLBAR_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f); + int outer_width = width + FRAME_TOOLBAR_WIDTH (f); + int scale = xg_get_scale (f); + int x = f->left_pos; + int y = f->top_pos; + GdkWindow *gwin = NULL; + int flags = 0; + + if (FRAME_GTK_OUTER_WIDGET (f)) + gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)); + else + gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); + + outer_height /= scale; + outer_width /= scale; + + /* Full force ahead. For top-level frames the gravity will get reset + to NorthWestGravity anyway. */ + flags |= USSize; + if (f->win_gravity == 3 || f->win_gravity == 9) + flags |= XNegative; + if (f->win_gravity == 6 || f->win_gravity == 9) + flags |= YNegative; + flags |= USPosition; + + xg_wm_set_size_hint (f, flags, true); + +#ifndef HAVE_PGTK + gdk_window_move_resize (gwin, x, y, outer_width, outer_height); +#else + if (FRAME_GTK_OUTER_WIDGET (f)) + gdk_window_move_resize (gwin, x, y, outer_width, outer_height); + else + gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), + outer_width, outer_height); +#endif + + SET_FRAME_GARBAGED (f); + cancel_mouse_face (f); + + if (FRAME_VISIBLE_P (f)) + { + /* Must call this to flush out events */ + (void)gtk_events_pending (); + gdk_flush (); +#ifndef HAVE_PGTK + x_wait_for_event (f, ConfigureNotify); +#endif + } + else + adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), + 5, 0, Qxg_frame_set_char_size); +} + #ifndef HAVE_PGTK /* Convert an X Window WSESC on display DPY to its corresponding GtkWidget. Must be done like this, because GtkWidget:s can have "hidden" @@ -2041,28 +2102,33 @@ xg_wm_set_size_hint (struct frame *f, long int flags, bool user_position) /* These currently have a one to one mapping with the X values, but I don't think we should rely on that. */ - hint_flags |= GDK_HINT_WIN_GRAVITY; - size_hints.win_gravity = 0; - if (win_gravity == NorthWestGravity) + if (FRAME_PARENT_FRAME (f)) + { + hint_flags |= GDK_HINT_WIN_GRAVITY; + size_hints.win_gravity = 0; + if (win_gravity == NorthWestGravity) + size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST; + else if (win_gravity == NorthGravity) + size_hints.win_gravity = GDK_GRAVITY_NORTH; + else if (win_gravity == NorthEastGravity) + size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST; + else if (win_gravity == WestGravity) + size_hints.win_gravity = GDK_GRAVITY_WEST; + else if (win_gravity == CenterGravity) + size_hints.win_gravity = GDK_GRAVITY_CENTER; + else if (win_gravity == EastGravity) + size_hints.win_gravity = GDK_GRAVITY_EAST; + else if (win_gravity == SouthWestGravity) + size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST; + else if (win_gravity == SouthGravity) + size_hints.win_gravity = GDK_GRAVITY_SOUTH; + else if (win_gravity == SouthEastGravity) + size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST; + else if (win_gravity == StaticGravity) + size_hints.win_gravity = GDK_GRAVITY_STATIC; + } + else size_hints.win_gravity = GDK_GRAVITY_NORTH_WEST; - else if (win_gravity == NorthGravity) - size_hints.win_gravity = GDK_GRAVITY_NORTH; - else if (win_gravity == NorthEastGravity) - size_hints.win_gravity = GDK_GRAVITY_NORTH_EAST; - else if (win_gravity == WestGravity) - size_hints.win_gravity = GDK_GRAVITY_WEST; - else if (win_gravity == CenterGravity) - size_hints.win_gravity = GDK_GRAVITY_CENTER; - else if (win_gravity == EastGravity) - size_hints.win_gravity = GDK_GRAVITY_EAST; - else if (win_gravity == SouthWestGravity) - size_hints.win_gravity = GDK_GRAVITY_SOUTH_WEST; - else if (win_gravity == SouthGravity) - size_hints.win_gravity = GDK_GRAVITY_SOUTH; - else if (win_gravity == SouthEastGravity) - size_hints.win_gravity = GDK_GRAVITY_SOUTH_EAST; - else if (win_gravity == StaticGravity) - size_hints.win_gravity = GDK_GRAVITY_STATIC; if (flags & PPosition) hint_flags |= GDK_HINT_POS; diff --git a/src/gtkutil.h b/src/gtkutil.h index e6c1e19c765..849315a826a 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -163,6 +163,8 @@ extern void xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight); extern void xg_frame_set_char_size (struct frame *f, int width, int height); +extern void xg_frame_set_size_and_position (struct frame *f, int width, + int height); extern GtkWidget * xg_win_to_widget (Display *dpy, Window wdesc); extern int xg_get_scale (struct frame *f); diff --git a/src/termhooks.h b/src/termhooks.h index e688ed40c0f..5e861051498 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -684,6 +684,11 @@ struct terminal void (*set_window_size_hook) (struct frame *f, bool change_gravity, int width, int height); + /* This hook is called to change the size and position of frame F's + native (underlying) window. */ + void (*set_window_size_and_position_hook) (struct frame *f, int width, + int height); + /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, to really change the position, and 0 when calling from *_make_frame_visible (in that case, XOFF and YOFF are the current diff --git a/src/w32term.c b/src/w32term.c index 9387cc3e7b7..80b072d6b5d 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -7237,6 +7237,85 @@ w32_set_window_size (struct frame *f, bool change_gravity, do_pending_window_change (false); } + +/* Change the size of frame F's Windows window to WIDTH and HEIGHT + pixels and its position to those stored in f->left_pos and + f->top_pos. */ +static void +w32_set_window_size_and_position (struct frame *f, int width, int height) +{ + RECT rect; + MENUBARINFO info; + int menu_bar_height; + + block_input (); + + /* Get the height of the menu bar here. It's used below to detect + whether the menu bar is wrapped. It's also used to specify the + third argument for AdjustWindowRect. See bug#22105. */ + info.cbSize = sizeof (info); + info.rcBar.top = info.rcBar.bottom = 0; + GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info); + menu_bar_height = info.rcBar.bottom - info.rcBar.top; + + if (w32_add_wrapped_menu_bar_lines) + { + /* When the menu bar wraps sending a SetWindowPos shrinks the + 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. */ + int default_menu_bar_height; + + /* Why is (apparently) SM_CYMENUSIZE needed here instead of + SM_CYMENU ?? */ + default_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE); + + if ((default_menu_bar_height > 0) + && (menu_bar_height > default_menu_bar_height) + && ((menu_bar_height % default_menu_bar_height) == 0)) + height = height + menu_bar_height - default_menu_bar_height; + } + + f->win_gravity = NorthWestGravity; + w32_wm_set_size_hint (f, (long) 0, false); + + rect.left = f->left_pos; + rect.top = f->top_pos; + rect.right = rect.left + width; + rect.bottom = rect.top + height; + + AdjustWindowRect (&rect, f->output_data.w32->dwStyle, menu_bar_height > 0); + + if (!FRAME_PARENT_FRAME (f)) + my_set_window_pos (FRAME_W32_WINDOW (f), NULL, + f->left_pos, f->top_pos, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOZORDER | SWP_NOACTIVATE); + else + my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP, + f->left_pos, f->top_pos, + rect.right - rect.left, + rect.bottom - rect.top, + SWP_NOACTIVATE); + + change_frame_size (f, width, height, false, true, false); + SET_FRAME_GARBAGED (f); + + /* If cursor was outside the new size, mark it as off. */ + mark_window_cursors_off (XWINDOW (f->root_window)); + + /* Clear out any recollection of where the mouse highlighting was, + since it might be in a place that's outside the new frame size. + Actually checking whether it is outside is a pain in the neck, + so don't try--just let the highlighting be done afresh with new + size. */ + cancel_mouse_face (f); + + unblock_input (); + + do_pending_window_change (false); +} /* Mouse warping. */ @@ -7891,6 +7970,7 @@ w32_create_terminal (struct w32_display_info *dpyinfo) terminal->fullscreen_hook = w32fullscreen_hook; terminal->iconify_frame_hook = w32_iconify_frame; terminal->set_window_size_hook = w32_set_window_size; + terminal->set_window_size_and_position_hook = w32_set_window_size_and_position; terminal->set_frame_offset_hook = w32_set_offset; terminal->set_frame_alpha_hook = w32_set_frame_alpha; terminal->set_new_font_hook = w32_new_font; diff --git a/src/xterm.c b/src/xterm.c index 9a6131ebb7d..088eaee83c9 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -28563,6 +28563,59 @@ x_set_window_size (struct frame *f, bool change_gravity, do_pending_window_change (false); } +static void +x_set_window_size_and_position_1 (struct frame *f, int width, int height) +{ + int x = f->left_pos; + int y = f->top_pos; + + x_wm_set_size_hint (f, 0, false); + + XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + x, y, width, height + FRAME_MENUBAR_HEIGHT (f)); + + SET_FRAME_GARBAGED (f); + + if (FRAME_VISIBLE_P (f)) + x_wait_for_event (f, ConfigureNotify); + else + /* Call adjust_frame_size right away as with GTK. It might be + tempting to clear out f->new_width and f->new_height here. */ + adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), + 5, 0, Qx_set_window_size_1); +} + +void +x_set_window_size_and_position (struct frame *f, int width, int height) +{ + block_input (); + +#ifdef USE_GTK + if (FRAME_GTK_WIDGET (f)) + xg_frame_set_size_and_position (f, width, height); + else + x_set_window_size_and_position_1 (f, width, height); +#else /* not USE_GTK */ + x_set_window_size_and_position_1 (f, width, height); +#endif /* USE_GTK */ + + x_clear_under_internal_border (f); + + /* If cursor was outside the new size, mark it as off. */ + mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); + + /* Clear out any recollection of where the mouse highlighting was, + since it might be in a place that's outside the new frame size. + Actually checking whether it is outside is a pain in the neck, + so don't try--just let the highlighting be done afresh with new size. */ + cancel_mouse_face (f); + + unblock_input (); + + do_pending_window_change (false); +} + /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */ void @@ -32148,6 +32201,7 @@ x_create_terminal (struct x_display_info *dpyinfo) terminal->fullscreen_hook = XTfullscreen_hook; terminal->iconify_frame_hook = x_iconify_frame; terminal->set_window_size_hook = x_set_window_size; + terminal->set_window_size_and_position_hook = x_set_window_size_and_position; terminal->set_frame_offset_hook = x_set_offset; terminal->set_frame_alpha_hook = x_set_frame_alpha; terminal->set_new_font_hook = x_new_font; diff --git a/src/xterm.h b/src/xterm.h index 661f6ae78b7..199fcd2edf0 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1766,6 +1766,7 @@ extern void x_ignore_errors_for_next_request (struct x_display_info *, extern void x_stop_ignoring_errors (struct x_display_info *); extern void x_clear_errors (Display *); extern void x_set_window_size (struct frame *, bool, int, int); +extern void x_set_window_size_and_position (struct frame *, int, int); extern void x_set_last_user_time_from_lisp (struct x_display_info *, Time); extern void x_make_frame_visible (struct frame *); extern void x_make_frame_invisible (struct frame *);