diff src/xterm.c @ 105693:964ff7cbc8a6

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.
author Jan Djärv <jan.h.d@swipnet.se>
date Wed, 21 Oct 2009 18:29:46 +0000
parents 061e00486e48
children 56d1856a3ea9
line wrap: on
line diff
--- 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 <X11/Shell.h>
@@ -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);