]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
*** empty log message ***
[gnu-emacs] / src / xterm.c
index 9e34d988b91161f9c34439baad948d935204cf4a..0dafcfb0101a45589e1760b8f9669f7eb963a4d0 100644 (file)
@@ -1,5 +1,5 @@
 /* X Communication module for terminals which understand the X protocol.
-   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 02, 2003
+   Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000,01,02,03,04
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -217,6 +217,17 @@ static String Xt_default_resources[] = {0};
 
 static int toolkit_scroll_bar_interaction;
 
+/* Non-zero means to not move point as a result of clicking on a
+   frame to focus it (when focus-follows-mouse is nil).  */
+
+int x_mouse_click_focus_ignore_position;
+
+/* Non-zero timeout value means ignore next mouse click if it arrives
+   before that timeout elapses (i.e. as part of the same sequence of
+   events resulting from clicking on a frame to select it).  */
+
+static unsigned long ignore_next_mouse_click_timeout;
+
 /* Mouse movement.
 
    Formerly, we used PointerMotionHintMask (in standard_event_mask)
@@ -346,7 +357,7 @@ static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
                                   enum text_cursor_kinds));
 
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
 static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
@@ -560,9 +571,8 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
-      x_draw_vertical_border (w);
-
-      draw_window_fringes (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
 
       UNBLOCK_INPUT;
     }
@@ -699,12 +709,12 @@ x_draw_fringe_bitmap (w, row, p)
       int oldVH = row->visible_height;
       row->visible_height = p->h;
       row->y -= rowY - p->y;
-      x_clip_to_row (w, row, gc);
+      x_clip_to_row (w, row, -1, gc);
       row->y = oldY;
       row->visible_height = oldVH;
     }
   else
-    x_clip_to_row (w, row, gc);
+    x_clip_to_row (w, row, -1, gc);
 
   if (p->bx >= 0 && !p->overlay_p)
     {
@@ -747,13 +757,13 @@ x_draw_fringe_bitmap (w, row, p)
 
       if (p->overlay_p)
        {
-         clipmask = XCreatePixmapFromBitmapData (display, 
+         clipmask = XCreatePixmapFromBitmapData (display,
                                                  FRAME_X_DISPLAY_INFO (f)->root_window,
-                                                 bits, p->wd, p->h, 
+                                                 bits, p->wd, p->h,
                                                  1, 0, 1);
          gcv.clip_mask = clipmask;
          gcv.clip_x_origin = p->x;
-         gcv.clip_y_origin = p->y; 
+         gcv.clip_y_origin = p->y;
          XChangeGC (display, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
        }
 
@@ -970,7 +980,8 @@ static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
                                           int, int, int));
 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
-                                   int, int, int, int, XRectangle *));
+                                   int, int, int, int, int, int,
+                                   XRectangle *));
 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, XRectangle *));
 
@@ -2008,9 +2019,10 @@ x_setup_relief_colors (s)
 
 static void
 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
-                   raised_p, left_p, right_p, clip_rect)
+                   raised_p, top_p, bot_p, left_p, right_p, clip_rect)
      struct frame *f;
-     int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p;
+     int left_x, top_y, right_x, bottom_y, width;
+     int top_p, bot_p, left_p, right_p, raised_p;
      XRectangle *clip_rect;
 {
   Display *dpy = FRAME_X_DISPLAY (f);
@@ -2025,10 +2037,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Top.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, top_y + i,
-              right_x + 1 - i * right_p, top_y + i);
+  if (top_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, top_y + i,
+                right_x + 1 - i * right_p, top_y + i);
 
   /* Left.  */
   if (left_p)
@@ -2044,10 +2057,11 @@ x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
   /* Bottom.  */
-  for (i = 0; i < width; ++i)
-    XDrawLine (dpy, window, gc,
-              left_x + i * left_p, bottom_y - i,
-              right_x + 1 - i * right_p, bottom_y - i);
+  if (bot_p)
+    for (i = 0; i < width; ++i)
+      XDrawLine (dpy, window, gc,
+                left_x + i * left_p, bottom_y - i,
+                right_x + 1 - i * right_p, bottom_y - i);
 
   /* Right.  */
   if (right_p)
@@ -2155,7 +2169,7 @@ x_draw_glyph_string_box (s)
     {
       x_setup_relief_colors (s);
       x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-                         width, raised_p, left_p, right_p, &clip_rect);
+                         width, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
 
@@ -2166,21 +2180,22 @@ static void
 x_draw_image_foreground (s)
      struct glyph_string *s;
 {
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -2205,11 +2220,12 @@ x_draw_image_foreground (s)
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
+         image_rect.width = s->slice.width;
+         image_rect.height = s->slice.height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+                      s->slice.x + r.x - x, s->slice.y + r.y - y,
+                      r.width, r.height, r.x, r.y);
        }
       else
        {
@@ -2218,11 +2234,12 @@ x_draw_image_foreground (s)
          get_glyph_string_clip_rect (s, &clip_rect);
          image_rect.x = x;
          image_rect.y = y;
-         image_rect.width = s->img->width;
-         image_rect.height = s->img->height;
+         image_rect.width = s->slice.width;
+         image_rect.height = s->slice.height;
          if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
-                      r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+                      s->slice.x + r.x - x, s->slice.y + r.y - y,
+                      r.width, r.height, r.x, r.y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2234,15 +2251,17 @@ x_draw_image_foreground (s)
            {
              int r = s->img->relief;
              if (r < 0) r = -r;
-             XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
-                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+             XDrawRectangle (s->display, s->window, s->gc,
+                             x - r, y - r,
+                             s->slice.width + r*2 - 1,
+                             s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, s->window, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
@@ -2254,21 +2273,22 @@ x_draw_image_relief (s)
 {
   int x0, y0, x1, y1, thick, raised_p;
   XRectangle r;
-  int x;
-  int y = s->ybase - image_ascent (s->img, s->face);
+  int x = s->x;
+  int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
-  else
-    x = s->x;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -2284,12 +2304,17 @@ x_draw_image_relief (s)
 
   x0 = x - thick;
   y0 = y - thick;
-  x1 = x + s->img->width + thick - 1;
-  y1 = y + s->img->height + thick - 1;
+  x1 = x + s->slice.width + thick - 1;
+  y1 = y + s->slice.height + thick - 1;
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+  x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
+                     s->slice.y == 0,
+                     s->slice.y + s->slice.height == s->img->height,
+                     s->slice.x == 0,
+                     s->slice.x + s->slice.width == s->img->width,
+                     &r);
 }
 
 
@@ -2300,21 +2325,22 @@ x_draw_image_foreground_1 (s, pixmap)
      struct glyph_string *s;
      Pixmap pixmap;
 {
-  int x;
-  int y = s->ybase - s->y - image_ascent (s->img, s->face);
+  int x = 0;
+  int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
-      && s->first_glyph->left_box_line_p)
-    x = abs (s->face->box_line_width);
-  else
-    x = 0;
+      && s->first_glyph->left_box_line_p
+      && s->slice.x == 0)
+    x += abs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  x += s->img->hmargin;
-  y += s->img->vmargin;
+  if (s->slice.x == 0)
+    x += s->img->hmargin;
+  if (s->slice.y == 0)
+    y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
@@ -2330,19 +2356,21 @@ x_draw_image_foreground_1 (s, pixmap)
          XGCValues xgcv;
 
          xgcv.clip_mask = s->img->mask;
-         xgcv.clip_x_origin = x;
-         xgcv.clip_y_origin = y;
+         xgcv.clip_x_origin = x - s->slice.x;
+         xgcv.clip_y_origin = y - s->slice.y;
          xgcv.function = GXcopy;
          XChangeGC (s->display, s->gc, mask, &xgcv);
 
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+                    s->slice.x, s->slice.y,
+                    s->slice.width, s->slice.height, x, y);
          XSetClipMask (s->display, s->gc, None);
        }
       else
        {
          XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
-                    0, 0, s->img->width, s->img->height, x, y);
+                    s->slice.x, s->slice.y,
+                    s->slice.width, s->slice.height, x, y);
 
          /* When the image has a mask, we can expect that at
             least part of a mouse highlight or a block cursor will
@@ -2355,14 +2383,15 @@ x_draw_image_foreground_1 (s, pixmap)
              int r = s->img->relief;
              if (r < 0) r = -r;
              XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
-                             s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+                             s->slice.width + r*2 - 1,
+                             s->slice.height + r*2 - 1);
            }
        }
     }
   else
     /* Draw a rectangle if image could not be loaded.  */
     XDrawRectangle (s->display, pixmap, s->gc, x, y,
-                   s->img->width - 1, s->img->height - 1);
+                   s->slice.width - 1, s->slice.height - 1);
 }
 
 
@@ -2404,33 +2433,28 @@ static void
 x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
-  int x, y;
   int box_line_hwidth = abs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   Pixmap pixmap = None;
 
-  height = s->height - 2 * box_line_vwidth;
-
+  height = s->height;
+  if (s->slice.y == 0)
+    height -= box_line_vwidth;
+  if (s->slice.y + s->slice.height >= s->img->height)
+    height -= box_line_vwidth;
 
   /* Fill background with face under the image.  Do it only if row is
      taller than image or if image has a clip mask to reduce
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
-  if (height > s->img->height
+  if (height > s->slice.height
       || s->img->hmargin
       || s->img->vmargin
       || s->img->mask
       || s->img->pixmap == 0
       || s->width != s->background_width)
     {
-      if (box_line_hwidth && s->first_glyph->left_box_line_p)
-       x = s->x + box_line_hwidth;
-      else
-       x = s->x;
-
-      y = s->y + box_line_vwidth;
-
       if (s->img->mask)
        {
          /* Create a pixmap as large as the glyph string.  Fill it
@@ -2469,7 +2493,19 @@ x_draw_image_glyph_string (s)
            }
        }
       else
-       x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+       {
+         int x = s->x;
+         int y = s->y;
+
+         if (s->first_glyph->left_box_line_p
+             && s->slice.x == 0)
+           x += box_line_hwidth;
+
+         if (s->slice.y == 0)
+           y += box_line_vwidth;
+
+         x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+       }
 
       s->background_filled_p = 1;
     }
@@ -2787,10 +2823,6 @@ x_clear_frame ()
 
   XFlush (FRAME_X_DISPLAY (f));
 
-#ifdef USE_GTK
-  xg_frame_cleared (f);
-#endif
-
   UNBLOCK_INPUT;
 }
 
@@ -3222,7 +3254,6 @@ x_detect_focus_change (dpyinfo, event, bufp)
      struct input_event *bufp;
 {
   struct frame *frame;
-  int nr_events = 0;
 
   frame = x_any_window_to_frame (dpyinfo, event->xany.window);
   if (! frame)
@@ -3347,12 +3378,14 @@ x_find_modifier_meanings (dpyinfo)
      Alt keysyms are on.  */
   {
     int row, col;      /* The row and column in the modifier table.  */
+    int found_alt_or_meta;
 
     for (row = 3; row < 8; row++)
+    {
+      found_alt_or_meta = 0;
       for (col = 0; col < mods->max_keypermod; col++)
        {
-         KeyCode code
-           = mods->modifiermap[(row * mods->max_keypermod) + col];
+         KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
 
          /* Zeroes are used for filler.  Skip them.  */
          if (code == 0)
@@ -3370,33 +3403,44 @@ x_find_modifier_meanings (dpyinfo)
                  {
                  case XK_Meta_L:
                  case XK_Meta_R:
+                   found_alt_or_meta = 1;
                    dpyinfo->meta_mod_mask |= (1 << row);
                    break;
 
                  case XK_Alt_L:
                  case XK_Alt_R:
+                   found_alt_or_meta = 1;
                    dpyinfo->alt_mod_mask |= (1 << row);
                    break;
 
                  case XK_Hyper_L:
                  case XK_Hyper_R:
-                   dpyinfo->hyper_mod_mask |= (1 << row);
+                   if (!found_alt_or_meta)
+                     dpyinfo->hyper_mod_mask |= (1 << row);
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
 
                  case XK_Super_L:
                  case XK_Super_R:
-                   dpyinfo->super_mod_mask |= (1 << row);
+                   if (!found_alt_or_meta)
+                     dpyinfo->super_mod_mask |= (1 << row);
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
 
                  case XK_Shift_Lock:
                    /* Ignore this if it's not on the lock modifier.  */
-                   if ((1 << row) == LockMask)
+                   if (!found_alt_or_meta && ((1 << row) == LockMask))
                      dpyinfo->shift_lock_mask = LockMask;
+                   code_col = syms_per_code;
+                   col = mods->max_keypermod;
                    break;
                  }
              }
          }
        }
+    }
   }
 
   /* If we couldn't find any meta keys, accept any alt keys as meta keys.  */
@@ -3880,9 +3924,9 @@ x_window_to_scroll_bar (display, window_id)
 {
   Lisp_Object tail;
 
-#ifdef USE_GTK
+#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
   window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
-#endif /* USE_GTK */
+#endif /* USE_GTK  && USE_TOOLKIT_SCROLL_BARS */
 
   for (tail = Vframe_list;
        XGCTYPE (tail) == Lisp_Cons;
@@ -4239,8 +4283,6 @@ xg_scroll_callback (widget, data)
   int part = -1, whole = 0, portion = 0;
   GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
 
-  if (xg_ignore_gtk_scrollbar) return;
-
   position = gtk_adjustment_get_value (adj);
 
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
@@ -4254,6 +4296,8 @@ xg_scroll_callback (widget, data)
   previous = *p;
   *p = position;
 
+  if (xg_ignore_gtk_scrollbar) return;
+
   diff = (int) (position - previous);
 
   if (diff == (int) adj->step_increment)
@@ -4285,7 +4329,7 @@ xg_scroll_callback (widget, data)
     }
 
   if (part >= 0)
-    {
+    { 
       window_being_scrolled = bar->window;
       last_scroll_bar_part = part;
       x_send_scroll_bar_event (bar->window, part, portion, whole);
@@ -4813,9 +4857,7 @@ x_scroll_bar_create (w, top, left, width, height)
                              top,
                              left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                             max (height, 1),
-                             left,
-                             width);
+                             max (height, 1));
     xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
 #else /* not USE_GTK */
     Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
@@ -5010,9 +5052,15 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
   /* Compute the left edge of the scroll bar.  */
 #ifdef USE_TOOLKIT_SCROLL_BARS
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + width - sb_width - (width - sb_width) / 2;
+    sb_left = (left +
+              (WINDOW_RIGHTMOST_P (w)
+               ? width - sb_width - (width - sb_width) / 2
+               : 0));
   else
-    sb_left = left + (width - sb_width) / 2;
+    sb_left = (left +
+              (WINDOW_LEFTMOST_P (w)
+               ? (width - sb_width) / 2
+               : width - sb_width));
 #else
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     sb_left = left + width - sb_width;
@@ -5053,32 +5101,29 @@ XTset_vertical_scroll_bar (w, portion, whole, position)
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
 
-#ifdef USE_GTK
-      if (mask)
-        xg_update_scrollbar_pos (f,
-                                 SCROLL_BAR_X_WINDOW (bar),
-                                 top,
-                                 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
-                                 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
-                                 max (height, 1),
-                                 left,
-                                 width);
-#else /* not USE_GTK */
-
-      /* Since toolkit scroll bars are smaller than the space reserved
-         for them on the frame, we have to clear "under" them.  */
-      if (width > 0 && height > 0)
-        x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                          left, top, width, height, False);
       /* Move/size the scroll bar widget.  */
       if (mask)
+       {
+         /* Since toolkit scroll bars are smaller than the space reserved
+            for them on the frame, we have to clear "under" them.  */
+         if (width > 0 && height > 0)
+           x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                          left, top, width, height, False);
+#ifdef USE_GTK
+          xg_update_scrollbar_pos (f,
+                                   SCROLL_BAR_X_WINDOW (bar),
+                                   top,
+                                   sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+                                   sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
+                                   max (height, 1));
+#else /* not USE_GTK */
           XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
                              sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                              top,
                              sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                              max (height, 1), 0);
-
 #endif /* not USE_GTK */
+       }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
 
       /* Clear areas not covered by the scroll bar because of
@@ -5529,73 +5574,6 @@ x_scroll_bar_clear (f)
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
 }
 
-\f
-/* Define a queue to save up SelectionRequest events for later handling.  */
-
-struct selection_event_queue
-  {
-    XEvent event;
-    struct selection_event_queue *next;
-  };
-
-static struct selection_event_queue *queue;
-
-/* Nonzero means queue up certain events--don't process them yet.  */
-
-static int x_queue_selection_requests;
-
-/* Queue up an X event *EVENT, to be processed later.  */
-
-static void
-x_queue_event (f, event)
-     FRAME_PTR f;
-     XEvent *event;
-{
-  struct selection_event_queue *queue_tmp
-    = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
-
-  if (queue_tmp != NULL)
-    {
-      queue_tmp->event = *event;
-      queue_tmp->next = queue;
-      queue = queue_tmp;
-    }
-}
-
-/* Take all the queued events and put them back
-   so that they get processed afresh.  */
-
-static void
-x_unqueue_events (display)
-     Display *display;
-{
-  while (queue != NULL)
-    {
-      struct selection_event_queue *queue_tmp = queue;
-      XPutBackEvent (display, &queue_tmp->event);
-      queue = queue_tmp->next;
-      xfree ((char *)queue_tmp);
-    }
-}
-
-/* Start queuing SelectionRequest events.  */
-
-void
-x_start_queuing_selection_requests (display)
-     Display *display;
-{
-  x_queue_selection_requests++;
-}
-
-/* Stop queuing SelectionRequest events.  */
-
-void
-x_stop_queuing_selection_requests (display)
-     Display *display;
-{
-  x_queue_selection_requests--;
-  x_unqueue_events (display);
-}
 \f
 /* The main X event-reading loop - XTread_socket.  */
 
@@ -5725,7 +5703,7 @@ event_handler_gdk (gxev, ev, data)
       else
        {
          current_count +=
-           handle_one_xevent (dpyinfo, xev, &current_finish, 
+           handle_one_xevent (dpyinfo, xev, &current_finish,
                               current_hold_quit);
        }
     }
@@ -5974,11 +5952,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
         goto OTHER;
 #endif /* USE_X_TOOLKIT */
-      if (x_queue_selection_requests)
-        x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
-                       &event);
-      else
-        {
+      {
           XSelectionRequestEvent *eventp
             = (XSelectionRequestEvent *) &event;
 
@@ -5990,7 +5964,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           SELECTION_EVENT_PROPERTY (&inev) = eventp->property;
           SELECTION_EVENT_TIME (&inev) = eventp->time;
           inev.frame_or_window = Qnil;
-        }
+      }
       break;
 
     case PropertyNotify:
@@ -6026,6 +6000,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         {
           x_check_fullscreen (f);
 
+#ifdef USE_GTK
+          /* This seems to be needed for GTK 2.6.  */
+          x_clear_area (event.xexpose.display,
+                        event.xexpose.window,
+                        event.xexpose.x, event.xexpose.y,
+                        event.xexpose.width, event.xexpose.height,
+                        FALSE);
+#endif
           if (f->async_visible == 0)
             {
               f->async_visible = 1;
@@ -6138,7 +6120,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       f = x_top_window_to_frame (dpyinfo, event.xmap.window);
       if (f)
         {
-          /* wait_reading_process_input will notice this and update
+          /* wait_reading_process_output will notice this and update
              the frame's display structures.
              If we where iconified, we should not set garbaged,
              because that stops redrawing on Expose events.  This looks
@@ -6167,6 +6149,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
     case KeyPress:
 
+      ignore_next_mouse_click_timeout = 0;
+
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
       /* Dispatch KeyPress events when in menu.  */
       if (popup_activated ())
@@ -6177,8 +6161,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
       if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
         {
-          dpyinfo->mouse_face_hidden = 1;
           clear_mouse_face (dpyinfo);
+          dpyinfo->mouse_face_hidden = 1;
         }
 
 #if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
@@ -6217,6 +6201,14 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           Lisp_Object coding_system = Qlatin_1;
          Lisp_Object c;
 
+#ifdef USE_GTK
+          /* Don't pass keys to GTK.  A Tab will shift focus to the
+             tool bar in GTK 2.4.  Keys will still go to menus and
+             dialogs because in that case popup_activated is TRUE
+             (see above).  */
+          *finish = X_EVENT_DROP;
+#endif
+
           event.xkey.state
             |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
                                        extra_keyboard_modifiers);
@@ -6518,6 +6510,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
       f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
+      if (f && x_mouse_click_focus_ignore_position)
+       ignore_next_mouse_click_timeout = event.xmotion.time + 200;
+
 #if 0
       if (event.xcrossing.focus)
        {
@@ -6761,7 +6756,21 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
                   if (! popup_activated ())
 #endif
-                    construct_mouse_click (&inev, &event, f);
+                   {
+                     if (ignore_next_mouse_click_timeout)
+                       {
+                         if (event.type == ButtonPress
+                             && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
+                           {
+                             ignore_next_mouse_click_timeout = 0;
+                             construct_mouse_click (&inev, &event, f);
+                           }
+                         if (event.type == ButtonRelease)
+                           ignore_next_mouse_click_timeout = 0;
+                       }
+                     else
+                       construct_mouse_click (&inev, &event, f);
+                   }
                 }
           }
         else
@@ -6909,7 +6918,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
          any_help_event_p = 1;
          gen_help_event (help_echo_string, frame, help_echo_window,
                          help_echo_object, help_echo_pos);
-       } 
+       }
       else
        {
          help_echo_string = Qnil;
@@ -7134,18 +7143,19 @@ XTread_socket (sd, expected, hold_quit)
    mode lines must be clipped to the whole window.  */
 
 static void
-x_clip_to_row (w, row, gc)
+x_clip_to_row (w, row, area, gc)
      struct window *w;
      struct glyph_row *row;
+     int area;
      GC gc;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   XRectangle clip_rect;
-  int window_y, window_width;
+  int window_x, window_y, window_width;
 
-  window_box (w, -1, 0, &window_y, &window_width, 0);
+  window_box (w, area, &window_x, &window_y, &window_width, 0);
 
-  clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
+  clip_rect.x = window_x;
   clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
   clip_rect.y = max (clip_rect.y, window_y);
   clip_rect.width = window_width;
@@ -7194,7 +7204,8 @@ x_draw_hollow_cursor (w, row)
   /* Compute the proper height and ascent of the rectangle, based
      on the actual glyph.  Using the full height of the row looks
      bad when there are tall images on that row.  */
-  h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent);
+  h = max (min (FRAME_LINE_HEIGHT (f), row->height),
+          cursor_glyph->ascent + cursor_glyph->descent);
   if (h < row->height)
     y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
   h--;
@@ -7210,7 +7221,7 @@ x_draw_hollow_cursor (w, row)
   gc = dpyinfo->scratch_cursor_gc;
 
   /* Set clipping, draw the rectangle, and reset clipping again.  */
-  x_clip_to_row (w, row, gc);
+  x_clip_to_row (w, row, TEXT_AREA, gc);
   XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
   XSetClipMask (dpy, gc, None);
 }
@@ -7282,7 +7293,7 @@ x_draw_bar_cursor (w, row, width, kind)
       width = min (cursor_glyph->pixel_width, width);
 
       w->phys_cursor_width = width;
-      x_clip_to_row (w, row, gc);
+      x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
          XFillRectangle (dpy, window, gc,
@@ -7540,11 +7551,17 @@ static Lisp_Object
 x_catch_errors_unwind (old_val)
      Lisp_Object old_val;
 {
-  Lisp_Object first;
-
-  first = XCAR (old_val);
+  Lisp_Object first = XCAR (old_val);
+  Display *dpy = XSAVE_VALUE (first)->pointer;
 
-  XSync (XSAVE_VALUE (first)->pointer, False);
+  /* The display may have been closed before this function is called.
+     Check if it is still open before calling XSync.  */
+  if (x_display_info_for_display (dpy) != 0)
+    {
+      BLOCK_INPUT;
+      XSync (dpy, False);
+      UNBLOCK_INPUT;
+    }
 
   x_error_message_string = XCDR (old_val);
   return Qnil;
@@ -7829,7 +7846,8 @@ x_new_font (f, fontname)
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
 
-  FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+  FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+  FRAME_SPACE_WIDTH (f) = fontp->space_width;
   FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
 
   compute_fringe_widths (f, 1);
@@ -7937,11 +7955,7 @@ xim_destroy_callback (xim, client_data, call_data)
       if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
-         if (FRAME_XIC_FONTSET (f))
-           {
-             XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
-             FRAME_XIC_FONTSET (f) = NULL;
-           }
+          xic_free_xfontset (f);
        }
     }
 
@@ -8134,7 +8148,6 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Window child;
   int win_x = 0, win_y = 0;
   int flags = f->size_hint_flags;
 
@@ -8143,20 +8156,11 @@ x_calc_absolute_position (f)
   if (! ((flags & XNegative) || (flags & YNegative)))
     return;
 
-  /* Find the offsets of the outside upper-left corner of
-     the inner window, with respect to the outer window.
-     But do this only if we will need the results.  */
-  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-    /* This is to get *_pixels_outer_diff.  */
-    x_real_positions (f, &win_x, &win_y);
-
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                   - 2 * FRAME_X_OUTPUT (f)->x_pixels_outer_diff
-                  - FRAME_PIXEL_WIDTH (f)
-                  + f->left_pos);
+                   - FRAME_PIXEL_WIDTH (f) + f->left_pos);
 
   {
     int height = FRAME_PIXEL_HEIGHT (f);
@@ -8178,15 +8182,7 @@ x_calc_absolute_position (f)
 #endif
 
   if (flags & YNegative)
-    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
-                  - FRAME_X_OUTPUT (f)->y_pixels_outer_diff
-
-                  /* Assume the window manager decorations are the same size on
-                     three sides, i.e. left, right and bottom.  This is to
-                     compensate for the bottom part.  */
-                  - FRAME_X_OUTPUT (f)->x_pixels_outer_diff
-                 - height
-                 + f->top_pos);
+    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
   }
 
   /* The left_pos and top_pos
@@ -8221,7 +8217,7 @@ x_set_offset (f, xoff, yoff, change_gravity)
       f->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
+
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
@@ -8302,7 +8298,9 @@ x_check_expected_move (f)
         FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
         FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
 
-        x_set_offset (f, expect_left, expect_top, 1);
+        f->left_pos = expect_left;
+        f->top_pos = expect_top;
+        x_set_offset (f, expect_left, expect_top, 0);
       }
     else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
       FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
@@ -9793,6 +9791,43 @@ x_load_font (f, fontname, size)
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
+    if (font->min_bounds.width == font->max_bounds.width)
+      {
+       /* Fixed width font.  */
+       fontp->average_width = fontp->space_width = font->min_bounds.width;
+      }
+    else
+      {
+       XChar2b char2b;
+       XCharStruct *pcm;
+
+       char2b.byte1 = 0x00, char2b.byte2 = 0x20;
+       pcm = x_per_char_metric (font, &char2b, 0);
+       if (pcm)
+         fontp->space_width = pcm->width;
+       else
+         fontp->space_width = FONT_WIDTH (font);
+
+       fontp->average_width
+         = (XGetFontProperty (font, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
+            ? (long) value / 10 : 0);
+       if (fontp->average_width < 0)
+         fontp->average_width = - fontp->average_width;
+       if (fontp->average_width == 0)
+         {
+           if (pcm)
+             {
+               int width = pcm->width;
+               for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
+                 if ((pcm = x_per_char_metric (font, &char2b, 0)) != NULL)
+                   width += pcm->width;
+               fontp->average_width = width / 95;
+             }
+           else
+             fontp->average_width = FONT_WIDTH (font);
+         }
+      }
+
     /* Try to get the full name of FONT.  Put it in FULL_NAME.  */
     full_name = 0;
     if (XGetFontProperty (font, XA_FONT, &value))
@@ -10342,7 +10377,7 @@ x_term_init (display_name, xrm_option, resource_name)
       get_bits_and_offset (dpyinfo->visual->green_mask,
                            &dpyinfo->green_bits, &dpyinfo->green_offset);
     }
-      
+
   /* See if a private colormap is requested.  */
   if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
     {
@@ -10367,10 +10402,12 @@ x_term_init (display_name, xrm_option, resource_name)
     int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
     double pixels = DisplayHeight (dpyinfo->display, screen_number);
     double mm = DisplayHeightMM (dpyinfo->display, screen_number);
-    dpyinfo->resy = pixels * 25.4 / mm;
+    /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
+    dpyinfo->resy = (mm < 1) ? 100 : pixels * 25.4 / mm;
     pixels = DisplayWidth (dpyinfo->display, screen_number);
+    /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
     mm = DisplayWidthMM (dpyinfo->display, screen_number);
-    dpyinfo->resx = pixels * 25.4 / mm;
+    dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
   }
 
   dpyinfo->Xatom_wm_protocols
@@ -10418,6 +10455,8 @@ x_term_init (display_name, xrm_option, resource_name)
   /* For properties of font.  */
   dpyinfo->Xatom_PIXEL_SIZE
     = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
+  dpyinfo->Xatom_AVERAGE_WIDTH
+    = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False);
   dpyinfo->Xatom_MULE_BASELINE_OFFSET
     = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
   dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
@@ -10672,7 +10711,7 @@ static struct redisplay_interface x_redisplay_interface =
   x_update_window_end,
   x_cursor_to,
   x_flush,
-#ifndef XFlush
+#ifdef XFlush
   x_flush,
 #else
   0,  /* flush_display_optional */
@@ -10729,6 +10768,7 @@ x_initialize ()
   x_noop_count = 0;
   last_tool_bar_item = -1;
   any_help_event_p = 0;
+  ignore_next_mouse_click_timeout = 0;
 
 #ifdef USE_GTK
   current_count = -1;
@@ -10816,6 +10856,16 @@ UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 to 4.1, set this to nil.  */);
   x_use_underline_position_properties = 1;
 
+  DEFVAR_BOOL ("x-mouse-click-focus-ignore-position",
+              &x_mouse_click_focus_ignore_position,
+    doc: /* Non-nil means that a mouse click to focus a frame does not move point.
+This variable is only used when the window manager requires that you
+click on a frame to select it (give it focus).  In that case, a value
+of nil, means that the selected window and cursor position changes to
+reflect the mouse click position, while a non-nil value means that the
+selected window or cursor position is preserved.  */);
+  x_mouse_click_focus_ignore_position = 0;
+
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
     doc: /* What X toolkit scroll bars Emacs uses.
 A value of nil means Emacs doesn't use X toolkit scroll bars.