* alloc.c: Do not define struct catchtag.
[bpt/emacs.git] / src / xterm.c
index 7590d2e..c77136e 100644 (file)
@@ -1,6 +1,6 @@
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -28,6 +28,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <signal.h>
 
 #include <stdio.h>
+#include <setjmp.h>
 
 #ifdef HAVE_X_WINDOWS
 
@@ -84,6 +85,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "atimer.h"
 #include "keymap.h"
 #include "font.h"
+#include "fontset.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
@@ -108,8 +110,6 @@ extern void xlwmenu_redisplay P_ ((Widget));
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 
 extern void free_frame_menubar P_ ((struct frame *));
-extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
-                                                   int));
 #endif
 
 #ifdef USE_X_TOOLKIT
@@ -142,11 +142,6 @@ extern void _XEditResCheckMessages ();
 
 #endif /* USE_X_TOOLKIT */
 
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
-#define x_any_window_to_frame x_window_to_frame
-#define x_top_window_to_frame x_window_to_frame
-#endif
-
 #ifdef USE_X_TOOLKIT
 #include "widget.h"
 #ifndef XtNinitialState
@@ -319,6 +314,14 @@ static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
 static Lisp_Object Qvendor_specific_keysyms;
 static Lisp_Object Qlatin_1;
 
+#ifdef USE_GTK
+/* The name of the Emacs icon file.  */
+static Lisp_Object xg_default_icon_file;
+
+/* Used in gtkutil.c.  */
+Lisp_Object Qx_gtk_map_stock;
+#endif
+
 /* Used in x_flush.  */
 
 extern Lisp_Object Vinhibit_redisplay;
@@ -362,6 +365,7 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            enum scroll_bar_part *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
+static void x_handle_net_wm_state P_ ((struct frame *, XPropertyEvent *));
 static void x_check_fullscreen P_ ((struct frame *));
 static void x_check_expected_move P_ ((struct frame *, int, int));
 static void x_sync_with_move P_ ((struct frame *, int, int, int));
@@ -457,6 +461,89 @@ x_display_info_for_display (dpy)
   return 0;
 }
 
+#define OPAQUE  0xffffffff
+#define OPACITY "_NET_WM_WINDOW_OPACITY"
+
+void
+x_set_frame_alpha (f)
+     struct frame *f;
+{
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  Display *dpy = FRAME_X_DISPLAY (f);
+  Window win = FRAME_OUTER_WINDOW (f);
+  double alpha = 1.0;
+  double alpha_min = 1.0;
+  unsigned long opac;
+
+  if (FRAME_X_DISPLAY_INFO (f)->root_window != FRAME_X_OUTPUT (f)->parent_desc)
+    /* Since the WM decoration lies under the FRAME_OUTER_WINDOW,
+       we must treat the former instead of the latter. */
+    win = FRAME_X_OUTPUT(f)->parent_desc;
+
+  if (dpyinfo->x_highlight_frame == f)
+    alpha = f->alpha[0];
+  else
+    alpha = f->alpha[1];
+
+  if (FLOATP (Vframe_alpha_lower_limit))
+    alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
+  else if (INTEGERP (Vframe_alpha_lower_limit))
+    alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
+
+  if (alpha < 0.0)
+    return;
+  else if (alpha > 1.0)
+    alpha = 1.0;
+  else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
+    alpha = alpha_min;
+
+  opac = alpha * OPAQUE;
+
+  /* return unless necessary */
+  {
+    unsigned char *data;
+    Atom actual;
+    int rc, format;
+    unsigned long n, left;
+
+    x_catch_errors (dpy);
+    rc = XGetWindowProperty(dpy, win, XInternAtom(dpy, OPACITY, False),
+                           0L, 1L, False, XA_CARDINAL,
+                           &actual, &format, &n, &left,
+                           &data);
+
+    if (rc == Success && actual != None)
+      if (*(unsigned long *)data == opac)
+       {
+         XFree ((void *) data);
+         x_uncatch_errors ();
+         return;
+       }
+      else
+       XFree ((void *) data);
+    x_uncatch_errors ();
+  }
+
+  x_catch_errors (dpy);
+  XChangeProperty (dpy, win, XInternAtom (dpy, OPACITY, False),
+                  XA_CARDINAL, 32, PropModeReplace,
+                  (unsigned char *) &opac, 1L);
+  x_uncatch_errors ();
+}
+
+int
+x_display_pixel_height (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  return HeightOfScreen (dpyinfo->screen);
+}
+
+int
+x_display_pixel_width (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  return WidthOfScreen (dpyinfo->screen);
+}
 
 \f
 /***********************************************************************
@@ -502,32 +589,6 @@ x_update_window_begin (w)
         highlighting.  */
       if (FRAME_GARBAGED_P (f))
        display_info->mouse_face_window = Qnil;
-
-#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
-        their mouse_face_p flag set, which means that they are always
-        unequal to rows in a desired matrix which never have that
-        flag set.  So, rows containing mouse-face glyphs are never
-        scrolled, and we don't have to switch the mouse highlight off
-        here to prevent it from being scrolled.  */
-
-      /* Can we tell that this update does not affect the window
-        where the mouse highlight is?  If so, no need to turn off.
-        Likewise, don't do anything if the frame is garbaged;
-        in that case, the frame's current matrix that we would use
-        is all wrong, and we will redisplay that line anyway.  */
-      if (!NILP (display_info->mouse_face_window)
-         && w == XWINDOW (display_info->mouse_face_window))
-       {
-         int i;
-
-         for (i = 0; i < w->desired_matrix->nrows; ++i)
-           if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
-             break;
-
-         if (i < w->desired_matrix->nrows)
-           clear_mouse_face (display_info);
-       }
-#endif /* 0 */
     }
 
   UNBLOCK_INPUT;
@@ -1109,16 +1170,27 @@ x_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
   if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
+      && (s->first_glyph->type == CHAR_GLYPH
+         || s->first_glyph->type == COMPOSITE_GLYPH))
     {
-      unsigned *code = alloca (sizeof (unsigned) * s->nchars);
-      struct font *font = s->font;
       struct font_metrics metrics;
-      int i;
 
-      for (i = 0; i < s->nchars; i++)
-       code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
-      font->driver->text_extents (font, code, s->nchars, &metrics);
+      if (s->first_glyph->type == CHAR_GLYPH)
+       {
+         unsigned *code = alloca (sizeof (unsigned) * s->nchars);
+         struct font *font = s->font;
+         int i;
+
+         for (i = 0; i < s->nchars; i++)
+           code[i] = (s->char2b[i].byte1 << 8) | s->char2b[i].byte2;
+         font->driver->text_extents (font, code, s->nchars, &metrics);
+       }
+      else
+       {
+         Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
+
+         composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics);
+       }
       s->right_overhang = (metrics.rbearing > metrics.width
                           ? metrics.rbearing - metrics.width : 0);
       s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0;
@@ -1244,6 +1316,7 @@ x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, j, x;
+  struct font *font = s->font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -1253,73 +1326,66 @@ x_draw_composite_glyph_string_foreground (s)
   else
     x = s->x;
 
-  /* S is a glyph string for a composition.  S->gidx is the index of
-     the first character drawn for glyphs of this composition.
-     S->gidx == 0 means we are drawing the very first character of
+  /* S is a glyph string for a composition.  S->cmp_from is the index
+     of the first character drawn for glyphs of this composition.
+     S->cmp_from == 0 means we are drawing the very first character of
      this composition.  */
 
   /* Draw a rectangle for the composition if the font for the very
      first character of the composition could not be loaded.  */
   if (s->font_not_found_p)
     {
-      if (s->gidx == 0)
+      if (s->cmp_from == 0)
        XDrawRectangle (s->display, s->window, s->gc, x, s->y,
                        s->width - 1, s->height - 1);
     }
+  else if (! s->first_glyph->u.cmp.automatic)
+    {
+      int y = s->ybase;
+
+      for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
+       if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
+         {
+           int xx = x + s->cmp->offsets[j * 2];
+           int yy = y - s->cmp->offsets[j * 2 + 1];
+
+           font->driver->draw (s, j, j + 1, xx, yy, 0);
+           if (s->face->overstrike)
+             font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+         }
+    }
   else
     {
-      struct font *font = s->font;
+      Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
+      Lisp_Object glyph;
       int y = s->ybase;
       int width = 0;
 
-      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
+      for (i = j = s->cmp_from; i < s->cmp_to; i++)
        {
-         Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
-                                     ->key_and_value,
-                                     s->cmp->hash_index * 2);
-         int from;
-
-         for (i = from = 0; i < s->nchars; i++)
+         glyph = LGSTRING_GLYPH (gstring, i);
+         if (NILP (LGLYPH_ADJUSTMENT (glyph)))
+           width += LGLYPH_WIDTH (glyph);
+         else
            {
-             Lisp_Object g = LGSTRING_GLYPH (gstring, i);
-             Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
              int xoff, yoff, wadjust;
 
-             if (! VECTORP (adjustment))
-               {
-                 width += LGLYPH_WIDTH (g);
-                 continue;
-               }
-             if (from < i)
+             if (j < i)
                {
-                 font->driver->draw (s, from, i, x, y, 0);
+                 font->driver->draw (s, j, i, x, y, 0);
                  x += width;
                }
-             xoff = XINT (AREF (adjustment, 0));
-             yoff = XINT (AREF (adjustment, 1));
-             wadjust = XINT (AREF (adjustment, 2));
-
+             xoff = LGLYPH_XOFF (glyph);
+             yoff = LGLYPH_YOFF (glyph);
+             wadjust = LGLYPH_WADJUST (glyph);
              font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
              x += wadjust;
-             from = i + 1;
+             j = i + 1;
              width = 0;
            }
-         if (from < i)
-           font->driver->draw (s, from, i, x, y, 0);
-       }
-      else
-       {
-         for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
-           if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
-             {
-               int xx = x + s->cmp->offsets[j * 2];
-               int yy = y - s->cmp->offsets[j * 2 + 1];
-
-               font->driver->draw (s, j, j + 1, xx, yy, 0);
-               if (s->face->overstrike)
-                 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
-             }
        }
+      if (j < i)
+       font->driver->draw (s, j, i, x, y, 0);
     }
 }
 
@@ -2575,13 +2641,17 @@ x_draw_glyph_string (s)
       int width;
       struct glyph_string *next;
 
-      for (width = 0, next = s->next; next;
+      for (width = 0, next = s->next;
+          next && width < s->right_overhang;
           width += next->width, next = next->next)
        if (next->first_glyph->type != IMAGE_GLYPH)
          {
            x_set_glyph_string_gc (next);
            x_set_glyph_string_clipping (next);
-           x_draw_glyph_string_background (next, 1);
+           if (next->first_glyph->type == STRETCH_GLYPH)
+             x_draw_stretch_glyph_string (next);
+           else
+             x_draw_glyph_string_background (next, 1);
            next->num_clips = 0;
          }
     }
@@ -2603,8 +2673,10 @@ x_draw_glyph_string (s)
       x_set_glyph_string_clipping (s);
       relief_drawn_p = 1;
     }
-  else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
-          || (s->next && s->next->hl != s->hl && s->right_overhang))
+  else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
+          && !s->clip_tail
+          && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+              || (s->next && s->next->hl != s->hl && s->right_overhang)))
     /* We must clip just this glyph.  left_overhang part has already
        drawn when s->prev was drawn, and right_overhang part will be
        drawn later when s->next is drawn. */
@@ -2631,7 +2703,8 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps || s->gidx > 0)
+      if (s->for_overlaps || (s->cmp_from > 0
+                             && ! s->first_glyph->u.cmp.automatic))
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -2664,7 +2737,7 @@ x_draw_glyph_string (s)
              else
                thickness = 1;
              if (x_underline_at_descent_line)
-               position = (s->height - thickness) - s->ybase;
+               position = (s->height - thickness) - (s->ybase - s->y);
              else
                {
                  /* Get the underline position.  This is the recommended
@@ -2680,21 +2753,30 @@ x_draw_glyph_string (s)
                    position = s->font->underline_position;
                  else if (s->font)
                    position = (s->font->descent + 1) / 2;
+                 else
+                   position = underline_minimum_offset;
                }
-             s->underline_thickness = thickness;
-             s->underline_position = position;
+             position = max (position, underline_minimum_offset);
            }
+         /* Check the sanity of thickness and position.  We should
+            avoid drawing underline out of the current line area.  */
+         if (s->y + s->height <= s->ybase + position)
+           position = (s->height - 1) - (s->ybase - s->y);
+         if (s->y + s->height < s->ybase + position + thickness)
+           thickness = (s->y + s->height) - (s->ybase + position);
+         s->underline_thickness = thickness;
+         s->underline_position = position;
          y = s->ybase + position;
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
-                           s->x, y, s->background_width, thickness);
+                           s->x, y, s->width, thickness);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->underline_color);
              XFillRectangle (s->display, s->window, s->gc,
-                             s->x, y, s->background_width, thickness);
+                             s->x, y, s->width, thickness);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -2706,14 +2788,14 @@ x_draw_glyph_string (s)
 
          if (s->face->overline_color_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                           s->background_width, h);
+                           s->width, h);
          else
            {
              XGCValues xgcv;
              XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
              XSetForeground (s->display, s->gc, s->face->overline_color);
              XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
-                             s->background_width, h);
+                             s->width, h);
              XSetForeground (s->display, s->gc, xgcv.foreground);
            }
        }
@@ -3043,6 +3125,26 @@ XTflash (f)
 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
 
 
+static void
+XTtoggle_invisible_pointer (f, invisible)
+     FRAME_PTR f;
+     int invisible;
+{
+  BLOCK_INPUT;
+  if (invisible) 
+    {
+      if (FRAME_X_DISPLAY_INFO (f)->invisible_cursor != 0)
+        XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                       FRAME_X_DISPLAY_INFO (f)->invisible_cursor);
+    }
+  else
+    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                   f->output_data.x->current_cursor);
+  f->pointer_invisible = invisible;
+  UNBLOCK_INPUT;
+}
+
+
 /* Make audible bell.  */
 
 void
@@ -3171,6 +3273,7 @@ frame_highlight (f)
                    f->output_data.x->border_pixel);
   UNBLOCK_INPUT;
   x_update_cursor (f, 1);
+  x_set_frame_alpha (f);
 }
 
 static void
@@ -3186,6 +3289,7 @@ frame_unhighlight (f)
                          f->output_data.x->border_tile);
   UNBLOCK_INPUT;
   x_update_cursor (f, 1);
+  x_set_frame_alpha (f);
 }
 
 /* The focus has changed.  Update the frames as necessary to reflect
@@ -3210,14 +3314,6 @@ x_new_focus_frame (dpyinfo, frame)
       if (old_focus && old_focus->auto_lower)
        x_lower_frame (old_focus);
 
-#if 0
-      selected_frame = frame;
-      XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
-                selected_frame);
-      Fselect_window (selected_frame->selected_window, Qnil);
-      choose_minibuf_frame ();
-#endif /* ! 0 */
-
       if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
        pending_autoraise_frame = dpyinfo->x_focus_frame;
       else
@@ -3278,6 +3374,8 @@ x_focus_changed (type, state, dpyinfo, frame, bufp)
       if (FRAME_XIC (frame))
         XUnsetICFocus (FRAME_XIC (frame));
 #endif
+      if (frame->pointer_invisible)
+        XTtoggle_invisible_pointer (frame, 0);
     }
 }
 
@@ -3807,7 +3905,14 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
                if (child == None || child == win)
                  break;
-
+#ifdef USE_GTK
+               /* We don't wan't to know the innermost window.  We
+                  want the edit window.  For non-Gtk+ the innermost
+                  window is the edit window.  For Gtk+ it might not
+                  be.  It might be the tool bar for example.  */
+               if (x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win))
+                 break;
+#endif
                win = child;
                parent_x = win_x;
                parent_y = win_y;
@@ -3824,8 +3929,14 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
               parent_{x,y} are invalid, but that's okay, because we'll
               never use them in that case.)  */
 
+#ifdef USE_GTK
+           /* We don't wan't to know the innermost window.  We
+              want the edit window.  */
+           f1 = x_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
+#else
            /* Is win one of our frames?  */
            f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
+#endif
 
 #ifdef USE_X_TOOLKIT
            /* If we end up with the menu bar window, say it's not
@@ -3921,7 +4032,7 @@ x_window_to_scroll_bar (display, window_id)
 
       if (! FRAME_X_P (XFRAME (frame)))
         continue;
-      
+
       /* Scan this frame's scroll bar list for a scroll bar with the
          right window ID.  */
       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
@@ -4489,7 +4600,7 @@ x_create_toolkit_scroll_bar (f, bar)
   /* Set the cursor to an arrow.  I didn't find a resource to do that.
      And I'm wondering why it hasn't an arrow cursor by default.  */
   XDefineCursor (XtDisplay (widget), XtWindow (widget),
-                f->output_data.x->nontext_cursor);
+                 f->output_data.x->nontext_cursor);
 
 #else /* !USE_MOTIF i.e. use Xaw */
 
@@ -5380,11 +5491,6 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
   emacs_event->arg = Qnil;
   emacs_event->timestamp = event->xbutton.time;
   {
-#if 0
-    FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-    int internal_height
-      = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
-#endif
     int top_range
       = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
     int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
@@ -5399,17 +5505,6 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
     else
       emacs_event->part = scroll_bar_below_handle;
 
-    /* Just because the user has clicked on the handle doesn't mean
-       they want to drag it.  Lisp code needs to be able to decide
-       whether or not we're dragging.  */
-#if 0
-    /* If the user has just clicked on the handle, record where they're
-       holding it.  */
-    if (event->type == ButtonPress
-       && emacs_event->part == scroll_bar_handle)
-      XSETINT (bar->dragging, y - bar->start);
-#endif
-
 #ifndef USE_TOOLKIT_SCROLL_BARS
     /* If the user has released the handle, set it to its final position.  */
     if (event->type == ButtonRelease
@@ -5423,18 +5518,7 @@ x_scroll_bar_handle_click (bar, event, emacs_event)
       }
 #endif
 
-    /* Same deal here as the other #if 0.  */
-#if 0
-    /* Clicks on the handle are always reported as occurring at the top of
-       the handle.  */
-    if (emacs_event->part == scroll_bar_handle)
-      emacs_event->x = bar->start;
-    else
-      XSETINT (emacs_event->x, y);
-#else
     XSETINT (emacs_event->x, y);
-#endif
-
     XSETINT (emacs_event->y, top_range);
   }
 }
@@ -5512,10 +5596,6 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
     ;
   else
     {
-#if 0
-      int inside_height
-       = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
-#endif
       int top_range
        = VERTICAL_SCROLL_BAR_TOP_RANGE     (f, bar->height);
 
@@ -5581,14 +5661,6 @@ x_scroll_bar_clear (f)
 \f
 /* The main X event-reading loop - XTread_socket.  */
 
-#if 0
-/* Time stamp of enter window event.  This is only used by XTread_socket,
-   but we have to put it out here, since static variables within functions
-   sometimes don't work.  */
-
-static Time enter_timestamp;
-#endif
-
 /* This holds the state XLookupString needs to implement dead keys
    and other tricks known as "compose processing".  _X Window System_
    says that a portable program can't use this, but Stephen Gildea assures
@@ -5992,14 +6064,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
     case PropertyNotify:
       last_user_time = event.xproperty.time;
-#if 0 /* This is plain wrong.  In the case that we are waiting for a
-        PropertyNotify used as an ACK in incremental selection
-        transfer, the property will be on the receiver's window.  */
-#if defined USE_X_TOOLKIT
-      if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
-        goto OTHER;
-#endif
-#endif
+      f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
+      if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
+        x_handle_net_wm_state (f, &event.xproperty);
+
       x_handle_property_notify (&event.xproperty);
       goto OTHER;
 
@@ -6023,8 +6091,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       f = x_window_to_frame (dpyinfo, event.xexpose.window);
       if (f)
         {
-          x_check_fullscreen (f);
-
 #ifdef USE_GTK
           /* This seems to be needed for GTK 2.6.  */
           x_clear_area (event.xexpose.display,
@@ -6154,6 +6220,11 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
           if (! f->async_iconified)
             SET_FRAME_GARBAGED (f);
 
+          /* Check if fullscreen was specified before we where mapped the
+             first time, i.e. from the command line. */
+          if (!f->output_data.x->has_been_visible)
+            x_check_fullscreen (f);
+
           f->async_visible = 1;
           f->async_iconified = 0;
           f->output_data.x->has_been_visible = 1;
@@ -6169,6 +6240,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                to update the frame titles
                in case this is the second frame.  */
             record_asynch_buffer_change ();
+
+#ifdef USE_GTK
+          xg_frame_resized (f, -1, -1);
+#endif
         }
       goto OTHER;
 
@@ -6282,27 +6357,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                                             &status_return);
                 }
               /* Xutf8LookupString is a new but already deprecated interface.  -stef  */
-#if 0 && defined X_HAVE_UTF8_STRING
-              else if (status_return == XLookupKeySym)
-                {  /* Try again but with utf-8.  */
-                  coding_system = Qutf_8;
-                  nbytes = Xutf8LookupString (FRAME_XIC (f),
-                                              &event.xkey, copy_bufptr,
-                                              copy_bufsiz, &keysym,
-                                              &status_return);
-                  if (status_return == XBufferOverflow)
-                    {
-                      copy_bufsiz = nbytes + 1;
-                      copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
-                      nbytes = Xutf8LookupString (FRAME_XIC (f),
-                                                  &event.xkey,
-                                                  copy_bufptr,
-                                                  copy_bufsiz, &keysym,
-                                                  &status_return);
-                    }
-                }
-#endif
-
               if (status_return == XLookupNone)
                 break;
               else if (status_return == XLookupChars)
@@ -6371,7 +6425,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
              inev.ie.code = XFASTINT (c);
              goto done_keysym;
            }
+
          /* Random non-modifier sorts of keysyms.  */
          if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                         || keysym == XK_Delete
@@ -6548,22 +6602,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
       if (f && x_mouse_click_focus_ignore_position)
        ignore_next_mouse_click_timeout = event.xmotion.time + 200;
 
-#if 0
-      if (event.xcrossing.focus)
-       {
-         /* Avoid nasty pop/raise loops.  */
-         if (f && (!(f->auto_raise)
-                   || !(f->auto_lower)
-                   || (event.xcrossing.time - enter_timestamp) > 500))
-           {
-             x_new_focus_frame (dpyinfo, f);
-             enter_timestamp = event.xcrossing.time;
-           }
-       }
-      else if (f == dpyinfo->x_focus_frame)
-       x_new_focus_frame (dpyinfo, 0);
-#endif
-
       /* EnterNotify counts as mouse movement,
         so update things that depend on mouse position.  */
       if (f && !f->output_data.x->hourglass_p)
@@ -6634,8 +6672,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         if (f)
           {
 
-            /* Generate SELECT_WINDOW_EVENTs when needed.  */
-            if (!NILP (Vmouse_autoselect_window))
+            /* Generate SELECT_WINDOW_EVENTs when needed.
+               Don't let popup menus influence things (bug#1261).  */
+            if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
               {
                 Lisp_Object window;
 
@@ -6705,19 +6744,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         {
 #ifndef USE_X_TOOLKIT
 #ifndef USE_GTK
-          /* If there is a pending resize for fullscreen, don't
-             do this one, the right one will come later.
-             The toolkit version doesn't seem to need this, but we
-             need to reset it below.  */
-          int dont_resize
-           = ((f->want_fullscreen & FULLSCREEN_WAIT)
-              && f->new_text_cols != 0);
           int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
           int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
 
-          if (dont_resize)
-            goto OTHER;
-
           /* In the toolkit version, change_frame_size
              is called by the code that handles resizing
              of the EmacsFrame widget.  */
@@ -6748,9 +6777,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 #endif
             {
              x_real_positions (f, &f->left_pos, &f->top_pos);
-
-             if (f->want_fullscreen & FULLSCREEN_WAIT)
-               f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
             }
 
 #ifdef HAVE_X_I18N
@@ -6758,6 +6784,7 @@ 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,
@@ -6765,6 +6792,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
               f->win_gravity = NorthWestGravity;
               x_wm_set_size_hint (f, (long) 0, 0);
             }
+#endif
         }
       goto OTHER;
 
@@ -7034,17 +7062,20 @@ XTread_socket (terminal, expected, hold_quit)
   int count = 0;
   XEvent event;
   int event_found = 0;
-#if 0
-  struct x_display_info *dpyinfo;
-#endif
 
   if (interrupt_input_blocked)
     {
       interrupt_input_pending = 1;
+#ifdef SYNC_INPUT
+      pending_signals = 1;
+#endif
       return -1;
     }
 
   interrupt_input_pending = 0;
+#ifdef SYNC_INPUT
+  pending_signals = pending_atimers;
+#endif
   BLOCK_INPUT;
 
   /* So people can tell when we have read the available input.  */
@@ -7075,40 +7106,6 @@ XTread_socket (terminal, expected, hold_quit)
       XTread_socket_fake_io_error = 0;
       x_io_error_quitter (terminal->display_info.x->display);
     }
-  
-#if 0 /* This loop is a noop now.  */
-  /* Find the display we are supposed to read input for.
-     It's the one communicating on descriptor SD.  */
-  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
-    {
-#if 0 /* This ought to be unnecessary; let's verify it.  */
-#ifdef FIOSNBIO
-      /* If available, Xlib uses FIOSNBIO to make the socket
-        non-blocking, and then looks for EWOULDBLOCK.  If O_NDELAY is set,
-        FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
-        a read returns 0, which Xlib interprets as equivalent to EPIPE.  */
-      fcntl (dpyinfo->connection, F_SETFL, 0);
-#endif /* ! defined (FIOSNBIO) */
-#endif
-
-#if 0 /* This code can't be made to work, with multiple displays,
-        and appears not to be used on any system any more.
-        Also keyboard.c doesn't turn O_NDELAY on and off
-        for X connections.  */
-#ifndef SIGIO
-#ifndef HAVE_SELECT
-      if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
-       {
-         extern int read_alarm_should_throw;
-         read_alarm_should_throw = 1;
-         XPeekEvent (dpyinfo->display, &event);
-         read_alarm_should_throw = 0;
-       }
-#endif /* HAVE_SELECT */
-#endif /* SIGIO */
-#endif
-    }
-#endif
 
 #ifndef USE_GTK
   while (XPending (terminal->display_info.x->display))
@@ -7318,7 +7315,7 @@ x_draw_bar_cursor (w, row, width, kind)
       XGCValues xgcv;
 
       /* If the glyph's background equals the color we normally draw
-        the bar cursor in, the bar cursor in its normal color is
+        the bars cursor in, the bar cursor in its normal color is
         invisible.  Use the glyph's foreground color instead in this
         case, on the assumption that the glyph's colors are chosen so
         that the glyph is legible.  */
@@ -7336,25 +7333,39 @@ x_draw_bar_cursor (w, row, width, kind)
          FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
        }
 
-      if (width < 0)
-       width = FRAME_CURSOR_WIDTH (f);
-      width = min (cursor_glyph->pixel_width, width);
-
-      w->phys_cursor_width = width;
       x_clip_to_row (w, row, TEXT_AREA, gc);
 
       if (kind == BAR_CURSOR)
+       {
+         if (width < 0)
+           width = FRAME_CURSOR_WIDTH (f);
+         width = min (cursor_glyph->pixel_width, width);
+
+         w->phys_cursor_width = width;
+
          XFillRectangle (dpy, window, gc,
                          WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
                          WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
                          width, row->height);
+       }
       else
+       {
+         int dummy_x, dummy_y, dummy_h;
+
+         if (width < 0)
+           width = row->height;
+
+         width = min (row->height, width);
+
+         get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x,
+                                   &dummy_y, &dummy_h);
+
          XFillRectangle (dpy, window, gc,
                          WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
                          WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
                                                   row->height - width),
-                         cursor_glyph->pixel_width,
-                         width);
+                         w->phys_cursor_width, width);
+       }
 
       XSetClipMask (dpy, gc, None);
     }
@@ -7368,7 +7379,10 @@ x_define_frame_cursor (f, cursor)
      struct frame *f;
      Cursor cursor;
 {
-  XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
+  if (!f->pointer_invisible
+      && f->output_data.x->current_cursor != cursor)
+    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
+  f->output_data.x->current_cursor = cursor;
 }
 
 
@@ -7484,16 +7498,19 @@ x_bitmap_icon (f, file)
        {
          int rc = -1;
 
-#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
 #ifdef USE_GTK
-         if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
+
+         if (xg_set_icon (f, xg_default_icon_file)
+             || xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
            return 0;
-#else
+
+#elif defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+
          rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
          if (rc != -1)
            FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
-#endif /* USE_GTK */
-#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
+#endif
 
          /* If all else fails, use the (black and white) xbm image. */
          if (rc == -1)
@@ -7774,7 +7791,7 @@ x_connection_closed (dpy, error_message)
       dpyinfo->reference_count++;
       dpyinfo->terminal->reference_count++;
     }
-  
+
   /* First delete frames whose mini-buffers are on frames
      that are on the dead display.  */
   FOR_EACH_FRAME (tail, frame)
@@ -7786,7 +7803,7 @@ x_connection_closed (dpy, error_message)
          && FRAME_X_P (XFRAME (minibuf_frame))
          && ! EQ (frame, minibuf_frame)
          && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
-       Fdelete_frame (frame, Qnoelisp);
+       delete_frame (frame, Qnoelisp);
     }
 
   /* Now delete all remaining frames on the dead display.
@@ -7796,10 +7813,10 @@ x_connection_closed (dpy, error_message)
     if (FRAME_X_P (XFRAME (frame))
        && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
       {
-       /* Set this to t so that Fdelete_frame won't get confused
+       /* Set this to t so that delete_frame won't get confused
           trying to find a replacement.  */
        FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
-       Fdelete_frame (frame, Qnoelisp);
+       delete_frame (frame, Qnoelisp);
       }
 
   /* We have to close the display to inform Xt that it doesn't
@@ -8010,7 +8027,20 @@ x_new_font (f, font_object, fontset)
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+        {
+          /* When the frame is maximized/fullscreen or running under for
+             example Xmonad, x_set_window_size will be a no-op.
+             In that case, the right thing to do is extend rows/cols to
+             the current frame size.  We do that first if x_set_window_size
+             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 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));
+        }
     }
 
 #ifdef HAVE_X_I18N
@@ -8087,6 +8117,8 @@ xim_open_dpy (dpyinfo, resource_name)
 #ifdef HAVE_XIM
   if (use_xim)
     {
+      if (dpyinfo->xim)
+       XCloseIM (dpyinfo->xim);
       xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
                     EMACS_CLASS);
       dpyinfo->xim = xim;
@@ -8116,12 +8148,6 @@ xim_open_dpy (dpyinfo, resource_name)
 
 #ifdef HAVE_X11R6_XIM
 
-struct xim_inst_t
-{
-  struct x_display_info *dpyinfo;
-  char *resource_name;
-};
-
 /* XIM instantiate callback function, which is called whenever an XIM
    server is available.  DISPLAY is the display of the XIM.
    CLIENT_DATA contains a pointer to an xim_inst_t structure created
@@ -8185,6 +8211,7 @@ xim_initialize (dpyinfo, resource_name)
      struct x_display_info *dpyinfo;
      char *resource_name;
 {
+  dpyinfo->xim = NULL;
 #ifdef HAVE_XIM
   if (use_xim)
     {
@@ -8192,8 +8219,8 @@ xim_initialize (dpyinfo, resource_name)
       struct xim_inst_t *xim_inst;
       int len;
 
-      dpyinfo->xim = NULL;
       xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
+      dpyinfo->xim_callback_data = xim_inst;
       xim_inst->dpyinfo = dpyinfo;
       len = strlen (resource_name);
       xim_inst->resource_name = (char *) xmalloc (len + 1);
@@ -8206,14 +8233,10 @@ xim_initialize (dpyinfo, resource_name)
                                         least, hence the configure test.  */
                                      (XRegisterIMInstantiateCallback_arg6) xim_inst);
 #else /* not HAVE_X11R6_XIM */
-      dpyinfo->xim = NULL;
       xim_open_dpy (dpyinfo, resource_name);
 #endif /* not HAVE_X11R6_XIM */
-
     }
-  else
 #endif /* HAVE_XIM */
-    dpyinfo->xim = NULL;
 }
 
 
@@ -8231,7 +8254,9 @@ xim_close_dpy (dpyinfo)
        XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
                                          NULL, EMACS_CLASS,
                                          xim_instantiate_callback, NULL);
-#endif /* not HAVE_X11R6_XIM */
+      xfree (dpyinfo->xim_callback_data->resource_name);
+      xfree (dpyinfo->xim_callback_data);
+#endif /* HAVE_X11R6_XIM */
       if (dpyinfo->display)
        XCloseIM (dpyinfo->xim);
       dpyinfo->xim = NULL;
@@ -8261,8 +8286,8 @@ x_calc_absolute_position (f)
   /* 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
-                   - FRAME_PIXEL_WIDTH (f) + f->left_pos);
+    f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+      - FRAME_PIXEL_WIDTH (f) + f->left_pos;
 
   {
     int height = FRAME_PIXEL_HEIGHT (f);
@@ -8283,8 +8308,9 @@ x_calc_absolute_position (f)
     XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
 #endif
 
-  if (flags & YNegative)
-    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
+    if (flags & YNegative)
+      f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
+       - height + f->top_pos;
   }
 
   /* The left_pos and top_pos
@@ -8462,6 +8488,40 @@ wm_supports (f, atomname)
   return rc;
 }
 
+static void
+set_wm_state (frame, add, what, what2)
+     Lisp_Object frame;
+     int add;
+     const char *what;
+     const char *what2;
+{
+  const char *atom = "_NET_WM_STATE";
+  Fx_send_client_event (frame, make_number (0), frame,
+                        make_unibyte_string (atom, strlen (atom)),
+                        make_number (32),
+                        /* 1 = add, 0 = remove */
+                        Fcons
+                        (make_number (add ? 1 : 0),
+                         Fcons
+                         (make_unibyte_string (what, strlen (what)),
+                          what2 != 0
+                          ? Fcons (make_unibyte_string (what2, strlen (what2)),
+                                   Qnil)
+                          : Qnil)));
+}
+
+void
+x_set_sticky (f, new_value, old_value)
+     struct frame *f;
+     Lisp_Object new_value, old_value;
+{
+  Lisp_Object frame;
+
+  XSETFRAME (frame, f);
+  set_wm_state (frame, NILP (new_value) ? 0 : 1,
+                "_NET_WM_STATE_STICKY", NULL);
+}
+
 /* Do fullscreen as specified in extended window manager hints */
 
 static int
@@ -8478,66 +8538,36 @@ do_ewmh_fullscreen (f)
   if (have_net_atom)
     {
       Lisp_Object frame;
-      const char *atom = "_NET_WM_STATE";
       const char *fs = "_NET_WM_STATE_FULLSCREEN";
       const char *fw = "_NET_WM_STATE_MAXIMIZED_HORZ";
       const char *fh = "_NET_WM_STATE_MAXIMIZED_VERT";
-      const char *what = NULL;
 
       XSETFRAME (frame, f);
 
+      set_wm_state (frame, 0, fs, NULL);
+      set_wm_state (frame, 0, fh, NULL);
+      set_wm_state (frame, 0, fw, NULL);
+      
       /* If there are _NET_ atoms we assume we have extended window manager
          hints.  */
       switch (f->want_fullscreen)
         {
         case FULLSCREEN_BOTH:
-          what = fs;
+          set_wm_state (frame, 1, fs, NULL);
           break;
         case FULLSCREEN_WIDTH:
-          what = fw;
+          set_wm_state (frame, 1, fw, NULL);
           break;
         case FULLSCREEN_HEIGHT:
-          what = fh;
+          set_wm_state (frame, 1, fh, NULL);
+          break;
+        case FULLSCREEN_MAXIMIZED:
+          set_wm_state (frame, 1, fw, fh);
           break;
         }
 
-      if (what != NULL && !wm_supports (f, what)) return 0;
-
-
-      Fx_send_client_event (frame, make_number (0), frame,
-                            make_unibyte_string (atom, strlen (atom)),
-                            make_number (32),
-                            Fcons (make_number (0), /* Remove */
-                                   Fcons
-                                   (make_unibyte_string (fs,
-                                                         strlen (fs)),
-                                    Qnil)));
-      Fx_send_client_event (frame, make_number (0), frame,
-                            make_unibyte_string (atom, strlen (atom)),
-                            make_number (32),
-                            Fcons (make_number (0), /* Remove */
-                                   Fcons
-                                   (make_unibyte_string (fh,
-                                                         strlen (fh)),
-                                    Qnil)));
-      Fx_send_client_event (frame, make_number (0), frame,
-                            make_unibyte_string (atom, strlen (atom)),
-                            make_number (32),
-                            Fcons (make_number (0), /* Remove */
-                                   Fcons
-                                   (make_unibyte_string (fw,
-                                                         strlen (fw)),
-                                    Qnil)));
       f->want_fullscreen = FULLSCREEN_NONE;
-      if (what != NULL)
-        Fx_send_client_event (frame, make_number (0), frame,
-                              make_unibyte_string (atom, strlen (atom)),
-                              make_number (32),
-                              Fcons (make_number (1), /* Add */
-                                     Fcons
-                                     (make_unibyte_string (what,
-                                                           strlen (what)),
-                                      Qnil)));
+
     }
 
   return have_net_atom;
@@ -8550,42 +8580,130 @@ XTfullscreen_hook (f)
   if (f->async_visible)
     {
       BLOCK_INPUT;
-      do_ewmh_fullscreen (f);
+      x_check_fullscreen (f);
       x_sync (f);
       UNBLOCK_INPUT;
     }
 }
 
 
+static void
+x_handle_net_wm_state (f, event)
+     struct frame *f;
+     XPropertyEvent *event;
+{
+  Atom actual_type;
+  unsigned long actual_size, bytes_remaining;
+  int i, rc, actual_format, value = FULLSCREEN_NONE;
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  long max_len = 65536;
+  Display *dpy = FRAME_X_DISPLAY (f);
+  unsigned char *tmp_data = NULL;
+  Atom target_type = XA_ATOM;
+  Lisp_Object lval;
+  int sticky = 0;
+
+  BLOCK_INPUT;
+  x_catch_errors (dpy);
+  rc = XGetWindowProperty (dpy, event->window,
+                           event->atom, 0, max_len, False, target_type,
+                           &actual_type, &actual_format, &actual_size,
+                           &bytes_remaining, &tmp_data);
+
+  if (rc != Success || actual_type != target_type || x_had_errors_p (dpy))
+    {
+      if (tmp_data) XFree (tmp_data);
+      x_uncatch_errors ();
+      UNBLOCK_INPUT;
+      return;
+    }
+
+  x_uncatch_errors ();
+
+  for (i = 0; i < actual_size; ++i)
+    {
+      Atom a = ((Atom*)tmp_data)[i];
+      if (a == dpyinfo->Xatom_net_wm_state_maximized_horz) 
+        {
+          if (value == FULLSCREEN_HEIGHT)
+            value = FULLSCREEN_MAXIMIZED;
+          else
+            value = FULLSCREEN_WIDTH;
+        }
+      else if (a == dpyinfo->Xatom_net_wm_state_maximized_vert)
+        {
+          if (value == FULLSCREEN_WIDTH)
+            value = FULLSCREEN_MAXIMIZED;
+          else
+            value = FULLSCREEN_HEIGHT;
+        }
+      else if (a == dpyinfo->Xatom_net_wm_state_fullscreen_atom)
+        value = FULLSCREEN_BOTH;
+      else if (a == dpyinfo->Xatom_net_wm_state_sticky)
+        sticky = 1;
+    }
+
+  lval = Qnil;
+  switch (value) 
+    {
+    case FULLSCREEN_WIDTH:
+      lval = Qfullwidth;
+      break;
+    case FULLSCREEN_HEIGHT:
+      lval = Qfullheight;
+      break;
+    case FULLSCREEN_BOTH:
+      lval = Qfullboth;
+      break;
+    case FULLSCREEN_MAXIMIZED:
+      lval = Qmaximized;
+      break;
+    }
+      
+  store_frame_param (f, Qfullscreen, lval);
+  store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
+
+  if (tmp_data) XFree (tmp_data);
+  UNBLOCK_INPUT;
+}
+
 /* Check if we need to resize the frame due to a fullscreen request.
    If so needed, resize the frame. */
 static void
 x_check_fullscreen (f)
      struct frame *f;
 {
-  if (f->want_fullscreen & FULLSCREEN_BOTH)
-    {
-      int width, height, ign;
-
-      if (do_ewmh_fullscreen (f))
-        return;
+  if (do_ewmh_fullscreen (f))
+    return;
 
-      x_real_positions (f, &f->left_pos, &f->top_pos);
+  if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
+    return; /* Only fullscreen without WM or with EWM hints (above). */
 
-      x_fullscreen_adjust (f, &width, &height, &ign, &ign);
+  if (f->want_fullscreen != FULLSCREEN_NONE)
+    {
+      int width = FRAME_COLS (f), height = FRAME_LINES (f);
+      struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
-      /* We do not need to move the window, it shall be taken care of
-         when setting WM manager hints.
-         If the frame is visible already, the position is checked by
-         x_check_expected_move. */
+      switch (f->want_fullscreen)
+        {
+          /* No difference between these two when there is no WM */
+        case FULLSCREEN_BOTH:
+        case FULLSCREEN_MAXIMIZED:
+          width = x_display_pixel_width (dpyinfo);
+          height = x_display_pixel_height (dpyinfo);
+          break;
+        case FULLSCREEN_WIDTH:
+          width = x_display_pixel_width (dpyinfo);
+          break;
+        case FULLSCREEN_HEIGHT:
+          height = x_display_pixel_height (dpyinfo);
+        }
+      
       if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
         {
           change_frame_size (f, height, width, 0, 1, 0);
           SET_FRAME_GARBAGED (f);
           cancel_mouse_face (f);
-
-          /* Wait for the change of frame size to occur */
-          f->want_fullscreen |= FULLSCREEN_WAIT;
         }
     }
 }
@@ -8612,7 +8730,7 @@ x_check_expected_move (f, expected_left, expected_top)
   x_real_positions (f, &current_left, &current_top);
 
   if (current_left != expected_left || current_top != expected_top)
-      {
+    {
       /* It's a "Type A" window manager. */
 
       int adjusted_left;
@@ -8631,7 +8749,7 @@ x_check_expected_move (f, expected_left, expected_top)
                    adjusted_left, adjusted_top);
 
       x_sync_with_move (f, expected_left, expected_top, 0);
-      }
+    }
   else
     /* It's a "Type B" window manager.  We don't have to adjust the
        frame's position. */
@@ -8842,9 +8960,6 @@ void
 x_focus_on_frame (f)
      struct frame *f;
 {
-#if 0  /* This proves to be unpleasant.  */
-  x_raise_frame (f);
-#endif
 #if 0
   /* I don't think that the ICCCM allows programs to do things like this
      without the interaction of the window manager.  Whatever you end up
@@ -9033,12 +9148,6 @@ x_make_frame_visible (f)
        XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
 #endif /* not USE_GTK */
 #endif /* not USE_X_TOOLKIT */
-#if 0 /* This seems to bring back scroll bars in the wrong places
-        if the window configuration has changed.  They seem
-        to come back ok without this.  */
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-       XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-#endif
     }
 
   XFlush (FRAME_X_DISPLAY (f));
@@ -9166,11 +9275,6 @@ x_make_frame_invisible (f)
   if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
     FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
-#if 0/* This might add unreliability; I don't trust it -- rms.  */
-  if (! f->async_visible && ! f->async_iconified)
-    return;
-#endif
-
   BLOCK_INPUT;
 
   /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
@@ -9435,16 +9539,11 @@ x_free_frame_resources (f)
       if (f->output_data.x->black_relief.allocated_p)
        unload_color (f, f->output_data.x->black_relief.pixel);
 
-      if (FRAME_FACE_CACHE (f))
-       free_frame_faces (f);
-
       x_free_gcs (f);
       XFlush (FRAME_X_DISPLAY (f));
     }
 
-  if (f->output_data.x->saved_menu_event)
-    xfree (f->output_data.x->saved_menu_event);
-
+  xfree (f->output_data.x->saved_menu_event);
   xfree (f->output_data.x);
   f->output_data.x = NULL;
 
@@ -9532,10 +9631,10 @@ x_wm_set_size_hint (f, flags, user_position)
 
   size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
   size_hints.height_inc = FRAME_LINE_HEIGHT (f);
-  size_hints.max_width
-    = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
-  size_hints.max_height
-    = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
+  size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+    - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
+  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.
 
@@ -9669,19 +9768,9 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     }
   else
     {
-      /* It seems there is no way to turn off use of an icon pixmap.
-        The following line does it, only if no icon has yet been created,
-        for some window managers.  But with mwm it crashes.
-        Some people say it should clear the IconPixmapHint bit in this case,
-        but that doesn't work, and the X consortium said it isn't the
-        right thing at all.  Since there is no way to win,
-        best to explicitly give up.  */
-#if 0
-      f->output_data.x->wm_hints.icon_pixmap = None;
-      f->output_data.x->wm_hints.icon_mask = None;
-#else
+      /* It seems there is no way to turn off use of an icon
+        pixmap.  */
       return;
-#endif
     }
 
 
@@ -9782,7 +9871,6 @@ static int x_initialized;
 static int x_session_initialized;
 #endif
 
-#ifdef MULTI_KBOARD
 /* Test whether two display-name strings agree up to the dot that separates
    the screen number from the server number.  */
 static int
@@ -9829,7 +9917,6 @@ same_x_server (name1, name2)
          && (*name1 == '.' || *name1 == '\0')
          && (*name2 == '.' || *name2 == '\0'));
 }
-#endif
 
 /* Count number of set bits in mask and number of bits to shift to
    get to the first bit.  With MASK 0x7e0, *BITS is set to 6, and *OFFSET
@@ -9913,7 +10000,7 @@ x_term_init (display_name, xrm_option, resource_name)
     GdkAtom atom;
 
 #ifndef HAVE_GTK_MULTIDISPLAY
-    if (!EQ (Vinitial_window_system, intern ("x")))
+    if (!EQ (Vinitial_window_system, Qx))
       error ("Sorry, you cannot connect to X servers with the GTK toolkit");
 #endif
 
@@ -10028,7 +10115,6 @@ x_term_init (display_name, xrm_option, resource_name)
 
   terminal = x_create_terminal (dpyinfo);
 
-#ifdef MULTI_KBOARD
   {
     struct x_display_info *share;
     Lisp_Object tail;
@@ -10044,15 +10130,19 @@ x_term_init (display_name, xrm_option, resource_name)
       {
        terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
        init_kboard (terminal->kboard);
-       terminal->kboard->Vwindow_system = intern ("x");
+       terminal->kboard->Vwindow_system = Qx;
        if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
          {
            char *vendor = ServerVendor (dpy);
+           /* Temporarily hide the partially initialized terminal */
+           terminal_list = terminal->next_terminal;
            UNBLOCK_INPUT;
            terminal->kboard->Vsystem_key_alist
              = call1 (Qvendor_specific_keysyms,
                       vendor ? build_string (vendor) : empty_unibyte_string);
            BLOCK_INPUT;
+           terminal->next_terminal = terminal_list;
+           terminal_list = terminal;
          }
 
        terminal->kboard->next_kboard = all_kboards;
@@ -10065,7 +10155,6 @@ x_term_init (display_name, xrm_option, resource_name)
       }
     terminal->kboard->reference_count++;
   }
-#endif
 
   /* Put this display on the chain.  */
   dpyinfo->next = x_display_list;
@@ -10082,7 +10171,7 @@ x_term_init (display_name, xrm_option, resource_name)
   terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
   strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
   terminal->name[SBYTES (display_name)] = 0;
-  
+
 #if 0
   XSetAfterFunction (x_current_display, x_trace_wire);
 #endif /* ! 0 */
@@ -10121,8 +10210,6 @@ x_term_init (display_name, xrm_option, resource_name)
                                     DefaultScreen (dpyinfo->display));
   select_visual (dpyinfo);
   dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
-  dpyinfo->height = HeightOfScreen (dpyinfo->screen);
-  dpyinfo->width = WidthOfScreen (dpyinfo->screen);
   dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
   dpyinfo->client_leader_window = 0;
   dpyinfo->grabbed = 0;
@@ -10146,7 +10233,6 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->x_focus_frame = 0;
   dpyinfo->x_focus_event_frame = 0;
   dpyinfo->x_highlight_frame = 0;
-  dpyinfo->terminal->image_cache = make_image_cache ();
   dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
 
   /* See if we can construct pixel values from RGB values.  */
@@ -10259,6 +10345,17 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->Xatom_XEMBED = XInternAtom (dpyinfo->display, "_XEMBED",
                                       False);
 
+  dpyinfo->Xatom_net_wm_state
+    = XInternAtom (dpyinfo->display, "_NET_WM_STATE", False);
+  dpyinfo->Xatom_net_wm_state_fullscreen_atom
+    = XInternAtom (dpyinfo->display, "_NET_WM_STATE_FULLSCREEN", False);
+  dpyinfo->Xatom_net_wm_state_maximized_horz
+    = XInternAtom (dpyinfo->display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+  dpyinfo->Xatom_net_wm_state_maximized_vert
+    = XInternAtom (dpyinfo->display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+  dpyinfo->Xatom_net_wm_state_sticky
+    = XInternAtom (dpyinfo->display, "_NET_WM_STATE_STICKY", False);
+
   dpyinfo->cut_buffers_initialized = 0;
 
   dpyinfo->x_dnd_atoms_size = 8;
@@ -10273,17 +10370,6 @@ x_term_init (display_name, xrm_option, resource_name)
   connection = ConnectionNumber (dpyinfo->display);
   dpyinfo->connection = connection;
 
-  {
-    char null_bits[1];
-
-    null_bits[0] = 0x00;
-
-    dpyinfo->null_pixel
-      = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
-                                    null_bits, 1, 1, (long) 0, (long) 0,
-                                    1);
-  }
-
   {
     extern int gray_bitmap_width, gray_bitmap_height;
     extern char *gray_bitmap_bits;
@@ -10441,20 +10527,9 @@ x_delete_display (dpyinfo)
          tail->next = tail->next->next;
     }
 
-#ifndef USE_X_TOOLKIT   /* I'm told Xt does this itself.  */
-#ifndef AIX            /* On AIX, XCloseDisplay calls this.  */
-  XrmDestroyDatabase (dpyinfo->xrdb);
-#endif
-#endif
-#ifdef HAVE_X_I18N
-  if (dpyinfo->xim)
-    xim_close_dpy (dpyinfo);
-#endif
-
-  if (dpyinfo->x_id_name)
-    xfree (dpyinfo->x_id_name);
-  if (dpyinfo->color_cells)
-    xfree (dpyinfo->color_cells);
+  xfree (dpyinfo->x_id_name);
+  xfree (dpyinfo->x_dnd_atoms);
+  xfree (dpyinfo->color_cells);
   xfree (dpyinfo);
 }
 
@@ -10552,12 +10627,19 @@ x_delete_terminal (struct terminal *terminal)
   struct x_display_info *dpyinfo = terminal->display_info.x;
   int i;
 
-  /* Protect against recursive calls.  Fdelete_frame in
+  /* Protect against recursive calls.  delete_frame in
      delete_terminal calls us back when it deletes our last frame.  */
   if (!terminal->name)
     return;
 
   BLOCK_INPUT;
+#ifdef HAVE_X_I18N
+  /* We must close our connection to the XIM server before closing the
+     X display.  */
+  if (dpyinfo->xim)
+    xim_close_dpy (dpyinfo);
+#endif
+
   /* If called from x_connection_closed, the display may already be closed
      and dpyinfo->display was set to 0 to indicate that.  */
   if (dpyinfo->display)
@@ -10565,6 +10647,32 @@ x_delete_terminal (struct terminal *terminal)
       x_destroy_all_bitmaps (dpyinfo);
       XSetCloseDownMode (dpyinfo->display, DestroyAll);
 
+      /* Whether or not XCloseDisplay destroys the associated resource
+        database depends on the version of libX11.  To avoid both
+        crash and memory leak, we dissociate the database from the
+        display and then destroy dpyinfo->xrdb ourselves.
+
+        Unfortunately, the above strategy does not work in some
+        situations due to a bug in newer versions of libX11: because
+        XrmSetDatabase doesn't clear the flag XlibDisplayDfltRMDB if
+        dpy->db is NULL, XCloseDisplay destroys the associated
+        database whereas it has not been created by XGetDefault
+        (Bug#21974 in freedesktop.org Bugzilla).  As a workaround, we
+        don't destroy the database here in order to avoid the crash
+        in the above situations for now, though that may cause memory
+        leaks in other situations.  */
+#if 0
+#ifdef HAVE_XRMSETDATABASE
+      XrmSetDatabase (dpyinfo->display, NULL);
+#else
+      dpyinfo->display->db = NULL;
+#endif
+      /* We used to call XrmDestroyDatabase from x_delete_display, but
+        some older versions of libX11 crash if we call it after
+        closing all the displays.  */
+      XrmDestroyDatabase (dpyinfo->xrdb);
+#endif
+
 #ifdef USE_GTK
       xg_display_close (dpyinfo->display);
 #else
@@ -10587,7 +10695,7 @@ static struct terminal *
 x_create_terminal (struct x_display_info *dpyinfo)
 {
   struct terminal *terminal;
-  
+
   terminal = create_terminal ();
 
   terminal->type = output_x_window;
@@ -10595,11 +10703,12 @@ x_create_terminal (struct x_display_info *dpyinfo)
   dpyinfo->terminal = terminal;
 
   /* kboard is initialized in x_term_init. */
-  
+
   terminal->clear_frame_hook = x_clear_frame;
   terminal->ins_del_lines_hook = x_ins_del_lines;
   terminal->delete_glyphs_hook = x_delete_glyphs;
   terminal->ring_bell_hook = XTring_bell;
+  terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer;
   terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
   terminal->set_terminal_modes_hook = XTset_terminal_modes;
   terminal->update_begin_hook = x_update_begin;
@@ -10618,7 +10727,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
 
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
-  
+
   terminal->rif = &x_redisplay_interface;
   terminal->scroll_region_ok = 1;    /* We'll scroll partial frames. */
   terminal->char_ins_del_ok = 1;
@@ -10678,13 +10787,6 @@ x_initialize ()
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_io_error_quitter);
 
-  /* Disable Window Change signals;  they are handled by X events.  */
-#if 0              /* Don't.  We may want to open tty frames later. */
-#ifdef SIGWINCH
-  signal (SIGWINCH, SIG_DFL);
-#endif /* SIGWINCH */
-#endif
-
   signal (SIGPIPE, x_connection_signal);
 }
 
@@ -10709,12 +10811,22 @@ syms_of_xterm ()
   staticpro (&last_mouse_press_frame);
   last_mouse_press_frame = Qnil;
 
+#ifdef USE_GTK
+  xg_default_icon_file = build_string ("icons/hicolor/scalable/apps/emacs.svg");
+  staticpro (&xg_default_icon_file);
+
+  Qx_gtk_map_stock = intern ("x-gtk-map-stock");
+  staticpro (&Qx_gtk_map_stock);
+#endif
+
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
 A value of nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil.  */);
+to 4.1, set this to nil.  You can also use `underline-minimum-offset'
+to override the font's UNDERLINE_POSITION for small font display
+sizes.  */);
   x_use_underline_position_properties = 1;
 
   DEFVAR_BOOL ("x-underline-at-descent-line",