# HG changeset patch # User Jan Dj¸«£rv # Date 1256149786 0 # Node ID 964ff7cbc8a680807e0629d0677c844163c4602f # Parent 15b4b661ceb1754d2a745a3307220df2c35ddcc1 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. diff -r 15b4b661ceb1 -r 964ff7cbc8a6 src/ChangeLog --- a/src/ChangeLog Wed Oct 21 14:04:00 2009 +0000 +++ b/src/ChangeLog Wed Oct 21 18:29:46 2009 +0000 @@ -1,3 +1,32 @@ +2009-10-21 Jan DjƤrv + + * 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 * character.c (char_resolve_modifier_mask): Don't resolve meta to the diff -r 15b4b661ceb1 -r 964ff7cbc8a6 src/gtkutil.c --- a/src/gtkutil.c Wed Oct 21 14:04:00 2009 +0000 +++ b/src/gtkutil.c Wed Oct 21 18:29:46 2009 +0000 @@ -665,20 +665,6 @@ } } -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 @@ 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 @@ 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 @@ #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"); diff -r 15b4b661ceb1 -r 964ff7cbc8a6 src/widget.c --- a/src/widget.c Wed Oct 21 14:04:00 2009 +0000 +++ b/src/widget.c Wed Oct 21 18:29:46 2009 +0000 @@ -775,6 +775,7 @@ 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 @@ 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); } diff -r 15b4b661ceb1 -r 964ff7cbc8a6 src/xmenu.c --- a/src/xmenu.c Wed Oct 21 14:04:00 2009 +0000 +++ b/src/xmenu.c Wed Oct 21 18:29:46 2009 +0000 @@ -1555,8 +1555,10 @@ + 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 @@ menubar_size += ibw; } #endif /* USE_LUCID */ -#endif /* 0 */ +#endif /* 1 */ f->output_data.x->menubar_height = menubar_size; } diff -r 15b4b661ceb1 -r 964ff7cbc8a6 src/xterm.c --- a/src/xterm.c Wed Oct 21 14:04:00 2009 +0000 +++ b/src/xterm.c Wed Oct 21 18:29:46 2009 +0000 @@ -86,6 +86,7 @@ #include "keymap.h" #include "font.h" #include "fontset.h" +#include "sysselect.h" #ifdef USE_X_TOOLKIT #include @@ -199,7 +200,14 @@ /* 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ } +/* 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 @@ compute_fringe_widths (f, 0); - pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols); - pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); - - f->win_gravity = NorthWestGravity; + 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; + + 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ size_hints.flags |= flags; goto no_read; } -#endif /* not USE_X_TOOLKIT */ { XSizeHints hints; /* Sometimes I hate X Windows... */ @@ -9691,13 +9715,6 @@ 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 @@ } } -#ifndef USE_X_TOOLKIT no_read: -#endif #ifdef PWinGravity size_hints.win_gravity = f->win_gravity; @@ -10791,6 +10806,10 @@ #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); diff -r 15b4b661ceb1 -r 964ff7cbc8a6 src/xterm.h --- a/src/xterm.h Wed Oct 21 14:04:00 2009 +0000 +++ b/src/xterm.h Wed Oct 21 18:29:46 2009 +0000 @@ -973,6 +973,7 @@ 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 */