Fix handling of frame position values

* src/frame.c (tty_child_pos_param): Handle additional position
values.  New SIZE argument.
(tty_child_frame_rect): Process size before position.
(Fmake_terminal_frame): Do not store calculated size/position
values in parameters to avoid that a negative absolute position
is later interpreted as position relative to bottom/right edge
of parent.
(Fmodify_frame_parameters): For tty child frames process size
before position values so the latter can take a new size into
account.
* src/frame.h: Adjust declaration of tty_child_pos_param.
* src/gtkutil.c (xg_set_geometry): Handle negative frame
position specifications.
* src/msdos.c (IT_set_frame_parameters): For tty child frames
process size before position parameters.
* src/xfns.c (x_window): In the non-GTK toolkit variant leave
negative position values unchanged - the toolkit should know how
to handle them.  Process child frame position parameters
separately.  In the non-toolkit variant process child frame
parameters separately.
This commit is contained in:
Martin Rudalics 2025-03-10 09:33:17 +01:00
parent 94ba1b097e
commit cbad6215cf
5 changed files with 104 additions and 55 deletions

View file

@ -1489,17 +1489,43 @@ get_future_frame_param (Lisp_Object parameter,
#endif
int
tty_child_pos_param (struct frame *child, Lisp_Object key,
Lisp_Object params, int dflt)
tty_child_pos_param (struct frame *f, Lisp_Object key,
Lisp_Object params, int pos, int size)
{
struct frame *p = XFRAME (f->parent_frame);
Lisp_Object val = Fassq (key, params);
if (CONSP (val))
{
val = XCDR (val);
if (FIXNUMP (val))
return XFIXNUM (val);
if (EQ (val, Qminus))
pos = (EQ (key, Qtop)
? p->pixel_height - size
: p->pixel_width - size);
else if (TYPE_RANGED_FIXNUMP (int, val))
{
pos = XFIXNUM (val);
if (pos < 0)
/* Handle negative value. */
pos = (EQ (key, Qtop)
? p->pixel_height - size + pos
: p->pixel_width - size + pos);
}
else if (CONSP (val) && EQ (XCAR (val), Qplus)
&& CONSP (XCDR (val))
&& TYPE_RANGED_FIXNUMP (int, XCAR (XCDR (val))))
pos = XFIXNUM (XCAR (XCDR (val)));
else if (CONSP (val) && EQ (XCAR (val), Qminus)
&& CONSP (XCDR (val))
&& RANGED_FIXNUMP (-INT_MAX, XCAR (XCDR (val)), INT_MAX))
pos = (EQ (key, Qtop)
? p->pixel_height - size - XFIXNUM (XCAR (XCDR (val)))
: p->pixel_width - size - XFIXNUM (XCAR (XCDR (val))));
}
return dflt;
return pos;
}
int
@ -1546,10 +1572,10 @@ static void
tty_child_frame_rect (struct frame *f, Lisp_Object params,
int *x, int *y, int *w, int *h)
{
*x = tty_child_pos_param (f, Qleft, params, 0);
*y = tty_child_pos_param (f, Qtop, params, 0);
*w = tty_child_size_param (f, Qwidth, params, FRAME_TOTAL_COLS (f));
*h = tty_child_size_param (f, Qheight, params, FRAME_TOTAL_LINES (f));
*x = tty_child_pos_param (f, Qleft, params, 0, *w);
*y = tty_child_pos_param (f, Qtop, params, 0, *h);
}
#endif /* !HAVE_ANDROID */
@ -1688,10 +1714,6 @@ affects all frames on the same terminal device. */)
f->left_pos = x;
f->top_pos = y;
store_in_alist (&parms, Qleft, make_fixnum (x));
store_in_alist (&parms, Qtop, make_fixnum (y));
store_in_alist (&parms, Qwidth, make_fixnum (width));
store_in_alist (&parms, Qheight, make_fixnum (height));
store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
store_in_alist (&parms, Qtty,
@ -3951,8 +3973,11 @@ list, but are otherwise ignored. */)
if (is_tty_child_frame (f))
{
int x = tty_child_pos_param (f, Qleft, params, f->left_pos);
int y = tty_child_pos_param (f, Qtop, params, f->top_pos);
int w = tty_child_size_param (f, Qwidth, params, f->total_cols);
int h = tty_child_size_param (f, Qheight, params, f->total_lines);
int x = tty_child_pos_param (f, Qleft, params, f->left_pos, w);
int y = tty_child_pos_param (f, Qtop, params, f->top_pos, h);
if (x != f->left_pos || y != f->top_pos)
{
f->left_pos = x;
@ -3960,8 +3985,6 @@ list, but are otherwise ignored. */)
SET_FRAME_GARBAGED (root_frame (f));
}
int w = tty_child_size_param (f, Qwidth, params, f->total_cols);
int h = tty_child_size_param (f, Qheight, params, f->total_lines);
if (w != f->total_cols || h != f->total_lines)
change_frame_size (f, w, h, false, false, false);

View file

@ -1461,7 +1461,7 @@ extern struct frame *make_initial_frame (void);
extern struct frame *make_frame (bool);
extern bool frame_redisplay_p (struct frame *);
extern int tty_child_pos_param (struct frame *, Lisp_Object,
Lisp_Object, int);
Lisp_Object, int, int);
extern int tty_child_size_param (struct frame *, Lisp_Object,
Lisp_Object, int);
#ifdef HAVE_WINDOW_SYSTEM

View file

@ -1070,19 +1070,27 @@ xg_set_geometry (struct frame *f)
be off by scrollbar width + window manager decorations. */
#ifndef HAVE_PGTK
if (f->size_hint_flags & XNegative)
f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
f->left_pos = ((FRAME_PARENT_FRAME (f)
? FRAME_PIXEL_WIDTH (FRAME_PARENT_FRAME (f))
: x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
- FRAME_PIXEL_WIDTH (f) + f->left_pos);
if (f->size_hint_flags & YNegative)
f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
f->top_pos = ((FRAME_PARENT_FRAME (f)
? FRAME_PIXEL_HEIGHT (FRAME_PARENT_FRAME (f))
: x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
- FRAME_PIXEL_HEIGHT (f) + f->top_pos);
#else
if (f->size_hint_flags & XNegative)
f->left_pos = (pgtk_display_pixel_width (FRAME_DISPLAY_INFO (f))
f->left_pos = ((FRAME_PARENT_FRAME (f)
? FRAME_PIXEL_WIDTH (FRAME_PARENT_FRAME (f))
: pgtk_display_pixel_width (FRAME_DISPLAY_INFO (f)))
- FRAME_PIXEL_WIDTH (f) + f->left_pos);
if (f->size_hint_flags & YNegative)
f->top_pos = (pgtk_display_pixel_height (FRAME_DISPLAY_INFO (f))
f->top_pos = ((FRAME_PARENT_FRAME (f)
? FRAME_PIXEL_HEIGHT (FRAME_PARENT_FRAME (f))
: pgtk_display_pixel_height (FRAME_DISPLAY_INFO (f)))
- FRAME_PIXEL_HEIGHT (f) + f->top_pos);
#endif

View file

@ -1715,8 +1715,13 @@ IT_set_frame_parameters (struct frame *f, Lisp_Object alist)
a nuumber of other flags. */
if (is_tty_child_frame (f))
{
int x = tty_child_pos_param (f, Qleft, alist, f->left_pos);
int y = tty_child_pos_param (f, Qtop, alist, f->top_pos);
int w = tty_child_size_param (f, Qwidth, alist, f->total_cols);
int h = tty_child_size_param (f, Qheight, alist, f->total_lines);
if (w != f->total_cols || h != f->total_lines)
change_frame_size (f, w, h, false, false, false);
int x = tty_child_pos_param (f, Qleft, alist, f->left_pos, w);
int y = tty_child_pos_param (f, Qtop, alist, f->top_pos, h);
if (x != f->left_pos || y != f->top_pos)
{
f->left_pos = x;
@ -1724,11 +1729,6 @@ IT_set_frame_parameters (struct frame *f, Lisp_Object alist)
SET_FRAME_GARBAGED (root_frame (f));
}
int w = tty_child_size_param (f, Qwidth, alist, f->total_cols);
int h = tty_child_size_param (f, Qheight, alist, f->total_lines);
if (w != f->total_cols || h != f->total_lines)
change_frame_size (f, w, h, false, false, false);
Lisp_Object visible = Fassq (Qvisibility, alist);
if (CONSP (visible))
SET_FRAME_VISIBLE (f, !NILP (Fcdr (visible)));

View file

@ -4251,37 +4251,42 @@ x_window (struct frame *f, long window_prompting)
Note that we do not specify here whether the position
is a user-specified or program-specified one.
We pass that information later, in x_wm_set_size_hint. */
{
int left = f->left_pos;
bool xneg = (window_prompting & XNegative) != 0;
int top = f->top_pos;
bool yneg = (window_prompting & YNegative) != 0;
if (xneg)
left = -left;
if (yneg)
top = -top;
bool xneg = (window_prompting & XNegative) != 0;
bool yneg = (window_prompting & YNegative) != 0;
if (window_prompting & USPosition)
sprintf (f->shell_position, "=%dx%d%c%d%c%d",
if (FRAME_PARENT_FRAME (f))
{
if (window_prompting & XNegative)
f->left_pos = (FRAME_PIXEL_WIDTH (FRAME_PARENT_FRAME (f))
- FRAME_PIXEL_WIDTH (f) + f->left_pos);
if (window_prompting & YNegative)
f->top_pos = (FRAME_PIXEL_HEIGHT (FRAME_PARENT_FRAME (f))
- FRAME_PIXEL_HEIGHT (f) + f->top_pos);
window_prompting &= ~ (XNegative | YNegative);
}
if (window_prompting & USPosition)
sprintf (f->shell_position, "=%dx%d%c%d%c%d",
FRAME_PIXEL_WIDTH (f) + extra_borders,
FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
(xneg ? '-' : '+'), f->left_pos,
(yneg ? '-' : '+'), f->top_pos);
else
{
sprintf (f->shell_position, "=%dx%d",
FRAME_PIXEL_WIDTH (f) + extra_borders,
FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders,
(xneg ? '-' : '+'), left,
(yneg ? '-' : '+'), top);
else
{
sprintf (f->shell_position, "=%dx%d",
FRAME_PIXEL_WIDTH (f) + extra_borders,
FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
/* Setting x and y when the position is not specified in
the geometry string will set program position in the WM hints.
If Emacs had just one program position, we could set it in
fallback resources, but since each make-frame call can specify
different program positions, this is easier. */
XtSetArg (gal[gac], XtNx, left); gac++;
XtSetArg (gal[gac], XtNy, top); gac++;
}
}
/* Setting x and y when the position is not specified in
the geometry string will set program position in the WM hints.
If Emacs had just one program position, we could set it in
fallback resources, but since each make-frame call can specify
different program positions, this is easier. */
XtSetArg (gal[gac], XtNx, f->left_pos); gac++;
XtSetArg (gal[gac], XtNy, f->top_pos); gac++;
}
XtSetArg (gal[gac], XtNgeometry, f->shell_position); gac++;
XtSetValues (shell_widget, gal, gac);
@ -4460,6 +4465,19 @@ x_window (struct frame *f)
attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
| CWOverrideRedirect | CWColormap);
if (FRAME_PARENT_FRAME (f))
{
if (f->size_hint_flags & XNegative)
f->left_pos = (FRAME_PIXEL_WIDTH (FRAME_PARENT_FRAME (f))
- FRAME_PIXEL_WIDTH (f) + f->left_pos);
if (f->size_hint_flags & YNegative)
f->top_pos = (FRAME_PIXEL_HEIGHT (FRAME_PARENT_FRAME (f))
- FRAME_PIXEL_HEIGHT (f) + f->top_pos);
f->size_hint_flags &= ~ (XNegative | YNegative);
}
block_input ();
FRAME_X_WINDOW (f)
= XCreateWindow (FRAME_X_DISPLAY (f),