Article View: gnu.emacs.bug
Article #87399emacs-19.27 - interpretation of X geometry
From: Gary Barnes
Date: Thu, 22 Sep 1994 18:01
Date: Thu, 22 Sep 1994 18:01
536 lines
20682 bytes
20682 bytes
Emacs 19.27, unmodified, no .emacs in use
SPARCstation 2, SunOS 4.1.3
./configure sparc-sun-sunos4.1.3 --with-gcc --with-x-toolkit=athena
Emacs doesn't always respond correctly to a geometry specification.
In particular, it doesn't seem possible to specify a window location
that is slightly off-screen.
As an example, let's suppose that the window manager being used will
always place a 4 pixel border around every window on the screen.
Since it seems silly to "waste" 4 pixels on all borders of every
window, it is nice to be able to place a "large" window, such as
Emacs, into a corner and also to place it just 4 pixels off the
screen. With that placement, we don't lose any of the useful text
area of Emacs, and we avoid using up screen real estate for
unnecessary window borders.
With xterm or other applications, this could be done with "-geometry --4--4".
However, Emacs treats this as if it were specified as "-4-4" instead.
Looking at the code in src/xterm.c and src/xfns.c, the problem is that
Emacs thinks that the XNegative and YNegative flags returned by
XParseGeometry mean that the X and Y coordinates are negative.
Unfortunately, this is not the correct interpretation.
(Short tutorial on -geometry and the XNegative and YNegative flags:
To place a window at any of the 4 corners of a screen, use these
geometries:
+0+0 top left corner ~XNegative ~YNegative X = 0 Y = 0
+0-0 bottom left corner ~XNegative YNegative X = 0 Y = 0
-0+0 top right corner XNegative ~YNegative X = 0 Y = 0
-0-0 bottom right corner XNegative YNegative X = 0 Y = 0
To place a window at any of the 4 corners of a screen, but doing so
at a position 4 pixels inward (towards the center of the screen), use
these geometries:
+4+4 top left corner ~XNegative ~YNegative X > 0 Y > 0
+4-4 bottom left corner ~XNegative YNegative X > 0 Y < 0
-4+4 top right corner XNegative ~YNegative X < 0 Y > 0
-4-4 bottom right corner XNegative YNegative X < 0 Y < 0
And, for the more advanced player (this is what Emacs is missing),
To place a window at any of the 4 corners of a screen, but doing so
at a position 4 pixels outward (away from the center of the screen),
use these geometries:
+-4+-4 top left corner ~XNegative ~YNegative X < 0 Y < 0
+-4--4 bottom left corner ~XNegative YNegative X < 0 Y > 0
--4+-4 top right corner XNegative ~YNegative X > 0 Y < 0
--4--4 bottom right corner XNegative YNegative X > 0 Y > 0
X and Y have positive or negative values which are *independent* of
the XNegative and YNegative flags.
XNegative means that placement of the window is to be relative to the
right hand edge of the screen. That placement is then positive
(inward) or negative (outward) independent of the XNegative flag.
YNegative means that placement of the window is to be relative to the
bottom edge of the screen. That placement is then positive (inward)
or negative (outward) independent of the YNegative flag.
)
The fix for this requires two things:
a) The code that calculates geometry must change the way it treats the
X/YNegative flags.
b) On the Lisp side, there needs to be a way to represent X/YNegative
other than by erroneously changing the sign of the x/y values taken
from the geometry.
(a) is fairly straight forward. (b) requires the introduction of two
new frame attributes. I've called them 'top-negative and 'left-negative
since the other attributes are called 'top and 'left.
Here is a context diff of my changes to src/xterm.c and src/xfns.c.
My changes are all guarded by #ifdef GEB_GEOMETRY.
*** xterm.c.orig Thu Sep 22 10:25:01 1994
--- xterm.c Wed Sep 21 19:41:23 1994
***************
*** 5324,5331 ****
--- 5324,5376 ----
Window win, child;
int win_x = 0, win_y = 0;
int flags = f->display.x->size_hint_flags;
+ #ifdef GEB_GEOMETRY
+ Window root_return;
+ int x_return, y_return;
+ unsigned int width_return, height_return;
+ unsigned int border_width_return;
+ unsigned int depth_return;
+
+ /* Find the position of the outside upper-left corner of
+ the inner window, with respect to the outer window. */
+ if (flags & (XNegative | YNegative)) {
+ {
+ if (((f->display.x->parent_desc != ROOT_WINDOW)
+ ? f->display.x->parent_desc
+ : f->display.x->window_desc) == None) {
+ win_x = PIXEL_WIDTH (f);
+ win_y = PIXEL_HEIGHT (f);
+ } else {
+ BLOCK_INPUT;
+ XGetGeometry (x_current_display,
+ (f->display.x->parent_desc != ROOT_WINDOW)
+ ? f->display.x->parent_desc
+ : f->display.x->window_desc,
+ &root_return, &x_return, &y_return,
+ &width_return, &height_return,
+ &border_width_return, &depth_return);
+ UNBLOCK_INPUT;
+ win_x = width_return + 2 * border_width_return;
+ win_y = height_return + 2 * border_width_return;
+ }
+ }
+
+ /* Treat negative positions as relative to the leftmost bottommost
+ position that fits on the screen. */
+ if (flags & XNegative)
+ f->display.x->left_pos = (x_screen_width
+ - win_x
+ + f->display.x->left_pos);
+
+ if (flags & YNegative)
+ f->display.x->top_pos = (x_screen_height
+ - win_y
+ + f->display.x->top_pos);
+
+ }
+ #else /* ! GEB_GEOMETRY */
/* Find the position of the outside upper-left corner of
the inner window, with respect to the outer window. */
if (f->display.x->parent_desc != ROOT_WINDOW)
***************
*** 5357,5364 ****
--- 5402,5410 ----
f->display.x->top_pos = (x_screen_height
- 2 * f->display.x->border_width - win_y
- PIXEL_HEIGHT (f)
+ f->display.x->top_pos);
+ #endif /* ! GEB_GEOMETRY */
/* The left_pos and top_pos
are now relative to the top and left screen edges,
so the flags should correspond. */
*** xfns.c.orig Thu Sep 22 10:26:43 1994
--- xfns.c Wed Sep 21 19:29:33 1994
***************
*** 232,239 ****
--- 232,243 ----
Lisp_Object Qnone;
Lisp_Object Qparent_id;
Lisp_Object Qsuppress_icon;
Lisp_Object Qtop;
+ #ifdef GEB_GEOMETRY
+ Lisp_Object Qtop_negative;
+ Lisp_Object Qleft_negative;
+ #endif
Lisp_Object Qundefined_color;
Lisp_Object Qvertical_scroll_bars;
Lisp_Object Qvisibility;
Lisp_Object Qwindow_id;
***************
*** 468,475 ****
--- 472,482 ----
Lisp_Object width, height;
/* Same here. */
Lisp_Object left, top;
+ #ifdef GEB_GEOMETRY
+ Lisp_Object left_negative, top_negative;
+ #endif
/* Record in these vectors all the parms specified. */
Lisp_Object *parms;
Lisp_Object *values;
***************
*** 495,502 ****
--- 502,512 ----
i++;
}
width = height = top = left = Qunbound;
+ #ifdef GEB_GEOMETRY
+ left_negative = top_negative = Qunbound;
+ #endif
/* Now process them in reverse of specified order. */
for (i--; i >= 0; i--)
{
***************
*** 512,519 ****
--- 522,535 ----
else if (EQ (prop, Qtop))
top = val;
else if (EQ (prop, Qleft))
left = val;
+ #ifdef GEB_GEOMETRY
+ else if (EQ (prop, Qleft_negative))
+ left_negative = val;
+ else if (EQ (prop, Qtop_negative))
+ top_negative = val;
+ #endif
else
{
register Lisp_Object param_index, old_value;
***************
*** 528,539 ****
--- 544,570 ----
}
}
/* Don't die if just one of these was set. */
+ #ifdef GEB_GEOMETRY
+ if (EQ (left_negative, Qunbound))
+ left_negative = Qnil;
+ if (EQ (top_negative, Qunbound))
+ top_negative = Qnil;
+ if (EQ (left, Qunbound)) {
+ XSET (left, Lisp_Int, f->display.x->left_pos);
+ left_negative = Qnil;
+ }
+ if (EQ (top, Qunbound)) {
+ XSET (top, Lisp_Int, f->display.x->top_pos);
+ top_negative = Qnil;
+ }
+ #else
if (EQ (left, Qunbound))
XSET (left, Lisp_Int, f->display.x->left_pos);
if (EQ (top, Qunbound))
XSET (top, Lisp_Int, f->display.x->top_pos);
+ #endif
/* Don't die if just one of these was set. */
if (EQ (width, Qunbound))
XSET (width, Lisp_Int, FRAME_WIDTH (f));
***************
*** 557,564 ****
--- 588,639 ----
if ((NUMBERP (width) && XINT (width) != FRAME_WIDTH (f))
|| (NUMBERP (height) && XINT (height) != FRAME_HEIGHT (f)))
Fset_frame_size (frame, width, height);
+ #ifdef GEB_GEOMETRY
+ /*--Take care of any X/YNegative flags that may wish to affect the
+ * geometry of this window. */
+
+ if (! EQ (left_negative, Qnil) || ! EQ (top_negative, Qnil)) {
+ int win_x, win_y;
+ Window root_return;
+ int x_return, y_return;
+ unsigned int width_return, height_return;
+ unsigned int border_width_return;
+ unsigned int depth_return;
+
+ /* Find the position of the outside upper-left corner of
+ the inner window, with respect to the outer window. */
+ {
+ BLOCK_INPUT;
+ XGetGeometry (x_current_display,
+ (f->display.x->parent_desc != ROOT_WINDOW)
+ ? f->display.x->parent_desc
+ : f->display.x->window_desc,
+ &root_return, &x_return, &y_return,
+ &width_return, &height_return,
+ &border_width_return, &depth_return);
+ UNBLOCK_INPUT;
+ win_x = width_return + 2 * border_width_return;
+ win_y = height_return + 2 * border_width_return;
+ }
+
+ if (! EQ (left_negative, Qnil) && NUMBERP (left)) {
+ XSET (left, Lisp_Int, (x_screen_width
+ - win_x
+ + XINT (left)));
+ }
+ if (! EQ (top_negative, Qnil) && NUMBERP (top)) {
+ XSET (top, Lisp_Int, (x_screen_height
+ - win_y
+ + XINT (top)));
+ }
+ }
+ /* The left_pos and top_pos
+ are now relative to the top and left screen edges,
+ so the flags should correspond. */
+ f->display.x->size_hint_flags &= ~ (XNegative | YNegative);
+ #endif /* GEB_GEOMETRY */
if ((!NILP (left) || !NILP (top))
&& ! (NUMBERP (left) && XINT (left) == f->display.x->left_pos
&& NUMBERP (top) && XINT (top) == f->display.x->top_pos))
***************
*** 1700,1707 ****
--- 1775,1811 ----
element = Fcons (Qleft, Qminus);
else
element = Fcons (Qleft, make_number (x));
result = Fcons (element, result);
+ #ifdef GEB_GEOMETRY
+ /*--XNegative does not mean (at all) that the X value is negative.
+ * That is not the intent of XNegative. Rather, XNegative means that
+ * the x position started with a minus sign. This means that the
+ * x position is specified relative to the *right* side of the screen
+ * rather than to the normal *left* side of the screen. The x position,
+ * *independent* of the XNegative flag may be positive or negative.
+ * For example,
+ * =+4+4 means 4 pixels in from the top left hand corner
+ * =+4-4 menas 4 pixels in from the bottom left hand corner
+ * =-4-4 means 4 pixels in from the bottom right hand corner
+ * =-4+4 means 4 pixels in from the top right hand corner
+ * and then we have these specifications:
+ * =+-4+-4 means 4 pixels out from the top left hand corner
+ * =+-4--4 menas 4 pixels out from the bottom left hand corner
+ * =--4--4 means 4 pixels out from the bottom right hand corner
+ * =--4+-4 means 4 pixels out from the top right hand corner
+ * So, XNegative means do thing relative to the right instead of the
+ * left. The sign of the x value is independent of this and may specify
+ * either a positive or a negative offset from the left or the right.
+ * This requires us to record XNegative *separately* from x. This
+ * is why there is a left-negative as well as a left. It is also why
+ * there is a top-negative as well as a top.
+ */
+ if ((geometry & XNegative) != 0) {
+ element = Fcons (Qleft_negative, Qt);
+ result = Fcons (element, result);
+ }
+ #endif
}
if (geometry & YValue)
{
***************
*** 1711,1718 ****
--- 1815,1830 ----
element = Fcons (Qtop, Qminus);
else
element = Fcons (Qtop, make_number (y));
result = Fcons (element, result);
+ #ifdef GEB_GEOMETRY
+ /*--See comments above about XNegative. The ditto applies to YNegative.
+ */
+ if ((geometry & YNegative) != 0) {
+ element = Fcons (Qtop_negative, Qt);
+ result = Fcons (element, result);
+ }
+ #endif
}
if (geometry & WidthValue)
result = Fcons (Fcons (Qwidth, make_number (width)), result);
***************
*** 1736,1743 ****
--- 1848,1858 ----
struct frame *f;
Lisp_Object parms;
{
register Lisp_Object tem0, tem1, tem2;
+ #ifdef GEB_GEOMETRY
+ Lisp_Object tem3, tem4;
+ #endif
int height, width, left, top;
register int geometry;
long window_prompting = 0;
***************
*** 1781,1788 ****
--- 1896,1907 ----
tem0 = x_get_arg (parms, Qtop, 0, 0, number);
tem1 = x_get_arg (parms, Qleft, 0, 0, number);
tem2 = x_get_arg (parms, Quser_position, 0, 0, number);
+ #ifdef GEB_GEOMETRY
+ tem3 = x_get_arg (parms, Qleft_negative, 0, 0, symbol);
+ tem4 = x_get_arg (parms, Qtop_negative, 0, 0, symbol);
+ #endif
if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
{
if (EQ (tem0, Qminus))
***************
*** 1795,1804 ****
--- 1914,1928 ----
else
{
CHECK_NUMBER (tem0, 0);
f->display.x->top_pos = XINT (tem0);
+ #ifdef GEB_GEOMETRY
+ if (! EQ (tem3, Qunbound) && ! EQ (tem3, Qnil))
+ window_prompting |= XNegative;
+ #else
if (f->display.x->top_pos < 0)
window_prompting |= YNegative;
+ #endif
}
if (EQ (tem1, Qminus))
{
***************
*** 1810,1819 ****
--- 1934,1948 ----
else
{
CHECK_NUMBER (tem1, 0);
f->display.x->left_pos = XINT (tem1);
+ #ifdef GEB_GEOMETRY
+ if (! EQ (tem4, Qunbound) && ! EQ (tem4, Qnil))
+ window_prompting |= YNegative;
+ #else
if (f->display.x->left_pos < 0)
window_prompting |= XNegative;
+ #endif
}
if (!NILP (tem2))
window_prompting |= USPosition;
***************
*** 1983,2002 ****
int left = f->display.x->left_pos;
int xneg = window_prompting & XNegative;
int top = f->display.x->top_pos;
int yneg = window_prompting & YNegative;
if (left < 0)
left = -left;
if (top < 0)
top = -top;
sprintf (shell_position, "=%dx%d%c%d%c%d", PIXEL_WIDTH (f),
! PIXEL_HEIGHT (f) + menubar_size,
(xneg ? '-' : '+'), left,
(yneg ? '-' : '+'), top);
}
else
sprintf (shell_position, "=%dx%d", PIXEL_WIDTH (f),
! PIXEL_HEIGHT (f) + menubar_size);
len = strlen (shell_position) + 1;
tem = (char *) xmalloc (len);
strncpy (tem, shell_position, len);
XtSetArg (al[ac], XtNgeometry, tem); ac++;
--- 2112,2154 ----
int left = f->display.x->left_pos;
int xneg = window_prompting & XNegative;
int top = f->display.x->top_pos;
int yneg = window_prompting & YNegative;
+ #ifdef GEB_GEOMETRY
+ /*--Preserve the possiblities of: +4+4,-4-4,+-4+-4,--4--4, etc. */
+ if (xneg) left = -left;
+ if (yneg) top = -top;
+ #else
if (left < 0)
left = -left;
if (top < 0)
top = -top;
+ #endif
sprintf (shell_position, "=%dx%d%c%d%c%d", PIXEL_WIDTH (f),
! PIXEL_HEIGHT (f)
! #ifdef GEB_GEOMETRY
! /*--The geometry of the shell was specified by the user.
! * We should not gratuitously change the size that he
! * specified. If he said 80x50 then that's what he gets.
! * If there is a menubar then the text area will be less
! * than 80x50 but the *window* size will be 80x50. That is
! * what -geometry is for, to specify total window geometry.*/
! #else
! + menubar_size
! #endif
! ,
(xneg ? '-' : '+'), left,
(yneg ? '-' : '+'), top);
}
else
sprintf (shell_position, "=%dx%d", PIXEL_WIDTH (f),
! PIXEL_HEIGHT (f)
! #ifdef GEB_GEOMETRY
! /*--Ditto to just above about -geometry. */
! #else
! + menubar_size
! #endif
! );
len = strlen (shell_position) + 1;
tem = (char *) xmalloc (len);
strncpy (tem, shell_position, len);
XtSetArg (al[ac], XtNgeometry, tem); ac++;
***************
*** 2084,2091 ****
--- 2236,2262 ----
#endif
| CWEventMask);
+ #ifdef GEB_GEOMETRY
+ /*--Make sure that all possible geometry options are handled. Merge the
+ * X/YNegative flag values with the current left/top positions. */
+
+ if (f->display.x->size_hint_flags & XNegative) {
+ f->display.x->left_pos = (x_screen_width
+ - PIXEL_WIDTH (f)
+ - 2 * f->display.x->border_width
+ + f->display.x->left_pos);
+ }
+ if (f->display.x->size_hint_flags & YNegative) {
+ f->display.x->top_pos = (x_screen_height
+ - PIXEL_HEIGHT (f)
+ - 2 * f->display.x->border_width
+ + f->display.x->top_pos);
+ }
+ f->display.x->size_hint_flags &= ~( XNegative | YNegative );
+ #endif
+
BLOCK_INPUT;
FRAME_X_WINDOW (f)
= XCreateWindow (x_current_display, ROOT_WINDOW,
f->display.x->left_pos,
***************
*** 4400,4407 ****
--- 4571,4584 ----
Qsuppress_icon = intern ("suppress-icon");
staticpro (&Qsuppress_icon);
Qtop = intern ("top");
staticpro (&Qtop);
+ #ifdef GEB_GEOMETRY
+ Qtop_negative = intern ("top-negative");
+ staticpro (&Qtop_negative);
+ Qleft_negative = intern ("left-negative");
+ staticpro (&Qleft_negative);
+ #endif
Qundefined_color = intern ("undefined-color");
staticpro (&Qundefined_color);
Qvertical_scroll_bars = intern ("vertical-scroll-bars");
staticpro (&Qvertical_scroll_bars);
Technical Details
Message-ID:
<9409221759.AA03122@igor.Rational.COM>Path:
arc1-ca.pugleaf.net!bga.com!news.sprintlink.net!howland.reston.ans.net!math.ohio-state.edu!cis.ohio-state.edu!rational.COM!gebShow Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: fb2f1,7e8ea43a4db0e99,start X-Google-Attributes: gidfb2f1,public X-Google-ArrivalTime: 1994-09-22 12:18:07 PST Path: arc1-ca.pugleaf.net!bga.com!news.sprintlink.net!howland.reston.ans.net!math.ohio-state.edu!cis.ohio-state.edu!rational.COM!geb From: geb@rational.COM (Gary Barnes) Newsgroups: gnu.emacs.bug Subject: emacs-19.27 - interpretation of X geometry Date: 22 Sep 1994 14:01:53 -0400 Organization: GNUs Not Usenet Lines: 536 Sender: daemon@cis.ohio-state.edu Approved: bug-gnu-emacs@prep.ai.mit.edu Distribution: gnu Message-ID: <9409221759.AA03122@igor.Rational.COM> Reply-To: geb@rational.com