Commit 5c646d5a authored by Jan Djärv's avatar Jan Djärv

Fix resize due to font change on a maximized/xmonad-controlled frame.

* xterm.h (x_wait_for_event): Declare it.

* xterm.c (pending_event_wait): New variable.
(handle_one_xevent): Set pending_event_wait.eventtype to 0 if we
see pending_event_wait.eventtype.
(handle_one_xevent): Don't change gravity when parent changes.
(x_new_font): Call change_frame_size with new rows/columns before we try
to resize the frame.
(x_wait_for_event): New function.
(x_set_window_size_1): Don't change gravity unless change_gravity is set.
Call XResizeWindow with FRAME_OUTER_WINDOW.  If we are visible,
don't change frame size, instead wait for the ConfigureNotify.
(x_set_window_size): Call x_set_window_size_1 for USE_X_TOOLKIT also.
(x_wm_set_size_hint): Remove ifdefs for USE_X_TOOLKIT.
(x_initialize): Initialize pending_event_wait.

* xmenu.c (set_frame_menubar): Add internal border width to menu bar
size.

* widget.c (EmacsFrameSetValues): Add comment.
(EmacsFrameSetCharSize): Just call x_set_window_size.

* gtkutil.c (xg_frame_set_char_size): Flush events and call
x_wait_for_event.
(flush_and_sync): Removed again.
(xg_get_font_name): Suggest monospace if no previous font is known.
parent 8d106ea0
2009-10-21 Jan Djärv <jan.h.d@swipnet.se>
* xterm.h (x_wait_for_event): Declare it.
* xterm.c (pending_event_wait): New variable.
(handle_one_xevent): Set pending_event_wait.eventtype to 0 if we
see pending_event_wait.eventtype.
(handle_one_xevent): Don't change gravity when parent changes.
(x_new_font): Call change_frame_size with new rows/columns before we try
to resize the frame.
(x_wait_for_event): New function.
(x_set_window_size_1): Don't change gravity unless change_gravity is set.
Call XResizeWindow with FRAME_OUTER_WINDOW. If we are visible,
don't change frame size, instead wait for the ConfigureNotify.
(x_set_window_size): Call x_set_window_size_1 for USE_X_TOOLKIT also.
(x_wm_set_size_hint): Remove ifdefs for USE_X_TOOLKIT.
(x_initialize): Initialize pending_event_wait.
* xmenu.c (set_frame_menubar): Add internal border width to menu bar
size.
* widget.c (EmacsFrameSetValues): Add comment.
(EmacsFrameSetCharSize): Just call x_set_window_size.
* gtkutil.c (xg_frame_set_char_size): Flush events and call
x_wait_for_event.
(flush_and_sync): Removed again.
(xg_get_font_name): Suggest monospace if no previous font is known.
2009-10-20 Stefan Monnier <monnier@iro.umontreal.ca>
* character.c (char_resolve_modifier_mask): Don't resolve meta to the
......
......@@ -665,20 +665,6 @@ xg_frame_resized (f, pixelwidth, pixelheight)
}
}
static void
flush_and_sync (f)
FRAME_PTR f;
{
gdk_window_process_all_updates ();
x_sync (f);
while (gtk_events_pending ())
{
gtk_main_iteration ();
gdk_window_process_all_updates ();
x_sync (f);
}
}
/* Resize the outer window of frame F after chainging the height.
COLUMNS/ROWS is the size the edit area shall have after the resize. */
......@@ -715,6 +701,9 @@ xg_frame_set_char_size (f, cols, rows)
pixelwidth, pixelheight);
x_wm_set_size_hint (f, 0, 0);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
/* 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.
......@@ -723,14 +712,17 @@ xg_frame_set_char_size (f, cols, rows)
For unmapped windows, we can set rows/cols. When
the frame is mapped again we will (hopefully) get the correct size. */
if (f->async_visible)
flush_and_sync (f);
{
/* Must call this to flush out events */
(void)gtk_events_pending ();
gdk_flush ();
x_wait_for_event (f, ConfigureNotify);
}
else
{
change_frame_size (f, rows, cols, 0, 1, 0);
FRAME_PIXEL_WIDTH (f) = pixelwidth;
FRAME_PIXEL_HEIGHT (f) = pixelheight;
change_frame_size (f, rows, cols, 0, 1, 0);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
}
......@@ -1640,9 +1632,10 @@ xg_get_font_name (f, default_name)
#endif /* HAVE_GTK_AND_PTHREAD */
w = gtk_font_selection_dialog_new ("Pick a font");
if (default_name)
gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (w),
default_name);
if (!default_name)
default_name = "Monospace 10";
gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (w),
default_name);
xg_set_screen (w, f);
gtk_widget_set_name (w, "emacs-fontdialog");
......
......@@ -775,6 +775,7 @@ EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
Dimension pixel_width;
Dimension pixel_height;
/* AFAIK, this function is never called. -- Jan D, Oct 2009. */
has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
|| (cur->emacs_frame.foreground_pixel
!= new->emacs_frame.foreground_pixel)
......@@ -872,112 +873,9 @@ EmacsFrameSetCharSize (widget, columns, rows)
int rows;
{
EmacsFrame ew = (EmacsFrame) widget;
Dimension pixel_width, pixel_height;
struct frame *f = ew->emacs_frame.frame;
if (columns < 3) columns = 3; /* no way buddy */
check_frame_size (f, &rows, &columns);
f->scroll_bar_actual_width
= FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
compute_fringe_widths (f, 0);
char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
#if 0 /* This doesn't seem to be right. The frame gets too wide. --gerd. */
/* Something is really strange here wrt to the border width:
Apparently, XtNwidth and XtNheight include the border, so we have
to add it here. But the XtNborderWidth set for the widgets has
no similarity to what f->border_width is set to. */
XtVaGetValues (widget, XtNborderWidth, &border_width, NULL);
pixel_height += 2 * border_width;
pixel_width += 2 * border_width;
#endif
/* Manually change the height and width of all our widgets,
adjusting each widget by the same increments. */
if (ew->core.width != pixel_width
|| ew->core.height != pixel_height)
{
int hdelta = pixel_height - ew->core.height;
int wdelta = pixel_width - ew->core.width;
int column_widget_height = f->output_data.x->column_widget->core.height;
int column_widget_width = f->output_data.x->column_widget->core.width;
int outer_widget_height = f->output_data.x->widget->core.height;
int outer_widget_width = f->output_data.x->widget->core.width;
int old_left = f->output_data.x->widget->core.x;
int old_top = f->output_data.x->widget->core.y;
/* Input is blocked here, and Xt waits for some event to
occur. */
lw_refigure_widget (f->output_data.x->column_widget, False);
update_hints_inhibit = 1;
/* Xt waits for a ConfigureNotify event from the window manager
in EmacsFrameSetCharSize when the shell widget is resized.
For some window managers like fvwm2 2.2.5 and KDE 2.1 this
event doesn't arrive for an unknown reason and Emacs hangs in
Xt when the default font is changed. Tell Xt not to wait,
depending on the value of the frame parameter
`wait-for-wm'. */
x_catch_errors (FRAME_X_DISPLAY (f));
XtVaSetValues (f->output_data.x->widget,
XtNwaitForWm, (XtArgVal) f->output_data.x->wait_for_wm,
NULL);
x_uncatch_errors ();
/* Workaround: When a SIGIO or SIGALRM occurs while Xt is
waiting for a ConfigureNotify event (see above), this leads
to Xt waiting indefinitely instead of using its default
timeout (5 seconds). */
turn_on_atimers (0);
#ifdef SIGIO
sigblock (sigmask (SIGIO));
#endif
/* Do parents first, otherwise LessTif's geometry management
enters an infinite loop (as of 2000-01-15). This is fixed in
later versions of LessTif (as of 2001-03-13); I'll leave it
as is because I think it can't do any harm. */
/* In April 2002, simon.marshall@misys.com reports the problem
seems not to occur any longer. */
x_catch_errors (FRAME_X_DISPLAY (f));
XtVaSetValues (f->output_data.x->widget,
XtNheight, (XtArgVal) (outer_widget_height + hdelta),
XtNwidth, (XtArgVal) (outer_widget_width + wdelta),
NULL);
XtVaSetValues (f->output_data.x->column_widget,
XtNheight, (XtArgVal) (column_widget_height + hdelta),
XtNwidth, (XtArgVal) column_widget_width + wdelta,
NULL);
XtVaSetValues ((Widget) ew,
XtNheight, (XtArgVal) pixel_height,
XtNwidth, (XtArgVal) pixel_width,
NULL);
x_uncatch_errors ();
#ifdef SIGIO
sigunblock (sigmask (SIGIO));
#endif
turn_on_atimers (1);
lw_refigure_widget (f->output_data.x->column_widget, True);
update_hints_inhibit = 0;
update_wm_hints (ew);
/* These seem to get clobbered. I don't know why. - rms. */
f->output_data.x->widget->core.x = old_left;
f->output_data.x->widget->core.y = old_top;
}
/* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
receive in the ConfigureNotify event; if we get what we asked
for, then the event won't cause the screen to become garbaged, so
we have to make sure to do it here. */
SET_FRAME_GARBAGED (f);
x_set_window_size (f, 0, columns, rows);
}
......
......@@ -1555,8 +1555,10 @@ set_frame_menubar (f, first_time, deep_p)
+ f->output_data.x->menubar_widget->core.border_width)
: 0);
#if 0 /* Experimentally, we now get the right results
for -geometry -0-0 without this. 24 Aug 96, rms. */
#if 1 /* Experimentally, we now get the right results
for -geometry -0-0 without this. 24 Aug 96, rms.
Maybe so, but the menu bar size is missing the pixels so the
WM size hints are off by theses pixel. Jan D, oct 2009. */
#ifdef USE_LUCID
if (FRAME_EXTERNAL_MENU_BAR (f))
{
......@@ -1566,7 +1568,7 @@ set_frame_menubar (f, first_time, deep_p)
menubar_size += ibw;
}
#endif /* USE_LUCID */
#endif /* 0 */
#endif /* 1 */
f->output_data.x->menubar_height = menubar_size;
}
......
......@@ -86,6 +86,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keymap.h"
#include "font.h"
#include "fontset.h"
#include "sysselect.h"
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
......@@ -199,7 +200,14 @@ extern struct frame *updating_frame;
/* This is a frame waiting to be auto-raised, within XTread_socket. */
struct frame *pending_autoraise_frame;
static struct frame *pending_autoraise_frame;
/* This is a frame waiting for an event matching mask, within XTread_socket. */
static struct {
struct frame *f;
int eventtype;
} pending_event_wait;
#ifdef USE_X_TOOLKIT
/* The application context for Xt use. */
......@@ -5833,7 +5841,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
EVENT_INIT (inev.ie);
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
if (pending_event_wait.eventtype == event.type)
pending_event_wait.eventtype = 0; /* Indicates we got it. */
switch (event.type)
{
case ClientMessage:
......@@ -6779,7 +6790,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
#ifdef USE_GTK
/* GTK creates windows but doesn't map them.
Only get real positions and check fullscreen when mapped. */
Only get real positions when mapped. */
if (FRAME_GTK_OUTER_WIDGET (f)
&& GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
#endif
......@@ -6792,15 +6803,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
xic_set_statusarea (f);
#endif
#ifndef USE_GTK
if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
{
/* Since the WM decorations come below top_pos now,
we must put them below top_pos in the future. */
f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
}
#endif
}
goto OTHER;
......@@ -8043,9 +8045,15 @@ x_new_font (f, font_object, fontset)
turns out to not be a no-op (there is no way to know).
The size will be adjusted again if the frame gets a
ConfigureNotify event as a result of x_set_window_size. */
int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f,
FRAME_PIXEL_HEIGHT (f));
int pixelh = FRAME_PIXEL_HEIGHT (f);
#ifdef USE_X_TOOLKIT
/* The menu bar is not part of text lines. The tool bar
is however. */
pixelh -= FRAME_MENUBAR_HEIGHT (f);
#endif
int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
int cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
change_frame_size (f, rows, cols, 0, 1, 0);
x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
}
......@@ -8810,6 +8818,49 @@ x_sync_with_move (f, left, top, fuzzy)
}
/* Wait for an event on frame F matching EVENTTYPE. */
void
x_wait_for_event (f, eventtype)
struct frame *f;
int eventtype;
{
int level = interrupt_input_blocked;
SELECT_TYPE fds;
EMACS_TIME tmo, tmo_at, time_now;
int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
pending_event_wait.f = f;
pending_event_wait.eventtype = eventtype;
/* Set timeout to 0.1 second. Hopefully not noticable.
Maybe it should be configurable. */
EMACS_SET_SECS_USECS (tmo, 0, 100000);
EMACS_GET_TIME (tmo_at);
EMACS_ADD_TIME (tmo_at, tmo_at, tmo);
while (pending_event_wait.eventtype)
{
interrupt_input_pending = 1;
TOTALLY_UNBLOCK_INPUT;
/* XTread_socket is called after unblock. */
BLOCK_INPUT;
interrupt_input_blocked = level;
FD_ZERO (&fds);
FD_SET (fd, &fds);
EMACS_GET_TIME (time_now);
EMACS_SUB_TIME (tmo, tmo_at, time_now);
if (EMACS_TIME_NEG_P (tmo) || select (fd+1, &fds, NULL, NULL, &tmo) == 0)
break; /* Timeout */
}
pending_event_wait.f = 0;
pending_event_wait.eventtype = 0;
}
/* Change the size of frame F's X window to COLS/ROWS in the case F
doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
top-left-corner window gravity for this size change and subsequent
......@@ -8833,16 +8884,24 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
compute_fringe_widths (f, 0);
pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
+ 2*f->border_width;
pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
+ FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)
+ 2*f->border_width;
f->win_gravity = NorthWestGravity;
if (change_gravity) f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
XSync (FRAME_X_DISPLAY (f), False);
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
pixelwidth, pixelheight);
/* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
receive in the ConfigureNotify event; if we get what we asked
for, then the event won't cause the screen to become garbaged, so
we have to make sure to do it here. */
SET_FRAME_GARBAGED (f);
/* Now, strictly speaking, we can't be sure that this is accurate,
but the window manager will get around to dealing with the size
change request eventually, and we'll hear how it went when the
......@@ -8856,17 +8915,19 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
We pass 1 for DELAY since we can't run Lisp code inside of
a BLOCK_INPUT. */
change_frame_size (f, rows, cols, 0, 1, 0);
FRAME_PIXEL_WIDTH (f) = pixelwidth;
FRAME_PIXEL_HEIGHT (f) = pixelheight;
/* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
receive in the ConfigureNotify event; if we get what we asked
for, then the event won't cause the screen to become garbaged, so
we have to make sure to do it here. */
SET_FRAME_GARBAGED (f);
XFlush (FRAME_X_DISPLAY (f));
/* But the ConfigureNotify may in fact never arrive, and then this is
not right if the frame is visible. Instead wait (with timeout)
for the ConfigureNotify. */
if (f->async_visible)
x_wait_for_event (f, ConfigureNotify);
else
{
change_frame_size (f, rows, cols, 0, 1, 0);
FRAME_PIXEL_WIDTH (f) = pixelwidth;
FRAME_PIXEL_HEIGHT (f) = pixelheight;
x_sync (f);
}
}
......@@ -8888,28 +8949,11 @@ x_set_window_size (f, change_gravity, cols, rows)
xg_frame_set_char_size (f, cols, rows);
else
x_set_window_size_1 (f, change_gravity, cols, rows);
#elif USE_X_TOOLKIT
if (f->output_data.x->widget != NULL)
{
/* The x and y position of the widget is clobbered by the
call to XtSetValues within EmacsFrameSetCharSize.
This is a real kludge, but I don't understand Xt so I can't
figure out a correct fix. Can anyone else tell me? -- rms. */
int xpos = f->output_data.x->widget->core.x;
int ypos = f->output_data.x->widget->core.y;
EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
f->output_data.x->widget->core.x = xpos;
f->output_data.x->widget->core.y = ypos;
}
else
x_set_window_size_1 (f, change_gravity, cols, rows);
#else /* not USE_X_TOOLKIT */
#else /* not USE_GTK */
x_set_window_size_1 (f, change_gravity, cols, rows);
#endif /* not USE_X_TOOLKIT */
#endif /* not USE_GTK */
/* If cursor was outside the new size, mark it as off. */
mark_window_cursors_off (XWINDOW (f->root_window));
......@@ -9611,13 +9655,6 @@ x_wm_set_size_hint (f, flags, user_position)
int user_position;
{
XSizeHints size_hints;
#ifdef USE_X_TOOLKIT
Arg al[2];
int ac = 0;
Dimension widget_width, widget_height;
#endif
Window window = FRAME_OUTER_WINDOW (f);
/* Setting PMaxSize caused various problems. */
......@@ -9626,16 +9663,8 @@ x_wm_set_size_hint (f, flags, user_position)
size_hints.x = f->left_pos;
size_hints.y = f->top_pos;
#ifdef USE_X_TOOLKIT
XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
XtSetArg (al[ac], XtNheight, &widget_height); ac++;
XtGetValues (f->output_data.x->widget, al, ac);
size_hints.height = widget_height;
size_hints.width = widget_width;
#else /* not USE_X_TOOLKIT */
size_hints.height = FRAME_PIXEL_HEIGHT (f);
size_hints.width = FRAME_PIXEL_WIDTH (f);
#endif /* not USE_X_TOOLKIT */
size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
size_hints.height_inc = FRAME_LINE_HEIGHT (f);
......@@ -9644,11 +9673,7 @@ x_wm_set_size_hint (f, flags, user_position)
size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
/* Calculate the base and minimum sizes.
(When we use the X toolkit, we don't do it here.
Instead we copy the values that the widgets are using, below.) */
#ifndef USE_X_TOOLKIT
/* Calculate the base and minimum sizes. */
{
int base_width, base_height;
int min_rows = 0, min_cols = 0;
......@@ -9670,7 +9695,7 @@ x_wm_set_size_hint (f, flags, user_position)
size_hints.flags |= PBaseSize;
size_hints.base_width = base_width;
size_hints.base_height = base_height;
size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
size_hints.min_width = base_width + min_cols * size_hints.width_inc;
size_hints.min_height = base_height + min_rows * size_hints.height_inc;
}
......@@ -9681,7 +9706,6 @@ x_wm_set_size_hint (f, flags, user_position)
size_hints.flags |= flags;
goto no_read;
}
#endif /* not USE_X_TOOLKIT */
{
XSizeHints hints; /* Sometimes I hate X Windows... */
......@@ -9691,13 +9715,6 @@ x_wm_set_size_hint (f, flags, user_position)
value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
&supplied_return);
#ifdef USE_X_TOOLKIT
size_hints.base_height = hints.base_height;
size_hints.base_width = hints.base_width;
size_hints.min_height = hints.min_height;
size_hints.min_width = hints.min_width;
#endif
if (flags)
size_hints.flags |= flags;
else
......@@ -9715,9 +9732,7 @@ x_wm_set_size_hint (f, flags, user_position)
}
}
#ifndef USE_X_TOOLKIT
no_read:
#endif
#ifdef PWinGravity
size_hints.win_gravity = f->win_gravity;
......@@ -10791,6 +10806,10 @@ x_initialize ()
#endif
#endif
pending_autoraise_frame = 0;
pending_event_wait.f = 0;
pending_event_wait.eventtype = 0;
/* Note that there is no real way portable across R3/R4 to get the
original error handler. */
XSetErrorHandler (x_error_handler);
......
......@@ -973,6 +973,7 @@ extern int x_display_pixel_height P_ ((struct x_display_info *));
extern int x_display_pixel_width P_ ((struct x_display_info *));
extern void x_set_sticky P_ ((struct frame *, Lisp_Object, Lisp_Object));
extern void x_wait_for_event P_ ((struct frame *, int));
/* Defined in xselect.c */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment