Add 2010 to copyright years.
[bpt/emacs.git] / src / xterm.c
index 32ee159..22d9f67 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, 2009
+                 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
                  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
 
@@ -85,6 +86,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "keymap.h"
 #include "font.h"
 #include "fontset.h"
+#include "xsettings.h"
+#include "xgselect.h"
+#include "sysselect.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
@@ -109,12 +113,10 @@ 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
-#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
+#if !defined(NO_EDITRES)
 #define HACK_EDITRES
 extern void _XEditResCheckMessages ();
 #endif /* not NO_EDITRES */
@@ -143,11 +145,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
@@ -205,7 +202,14 @@ extern struct frame *updating_frame;
 
 /* This is a frame waiting to be auto-raised, within XTread_socket.  */
 
-struct frame *pending_autoraise_frame;
+static struct frame *pending_autoraise_frame;
+
+/* This is a frame waiting for an event matching mask, within XTread_socket.  */
+
+static struct {
+  struct frame *f;
+  int eventtype;
+} pending_event_wait;
 
 #ifdef USE_X_TOOLKIT
 /* The application context for Xt use.  */
@@ -323,6 +327,9 @@ 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.  */
@@ -746,11 +753,6 @@ x_after_update_window_line (desired_row)
     {
       int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
 
-      /* Internal border is drawn below the tool bar.  */
-      if (WINDOWP (f->tool_bar_window)
-         && w == XWINDOW (f->tool_bar_window))
-       y -= width;
-
       BLOCK_INPUT;
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    0, y, width, height, False);
@@ -1376,19 +1378,27 @@ x_draw_composite_glyph_string_foreground (s)
              if (j < i)
                {
                  font->driver->draw (s, j, i, x, y, 0);
+                 if (s->face->overstrike)
+                   font->driver->draw (s, j, i, x + 1, y, 0);
                  x += width;
                }
              xoff = LGLYPH_XOFF (glyph);
              yoff = LGLYPH_YOFF (glyph);
              wadjust = LGLYPH_WADJUST (glyph);
              font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+             if (s->face->overstrike)
+               font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 0);
              x += wadjust;
              j = i + 1;
              width = 0;
            }
        }
       if (j < i)
-       font->driver->draw (s, j, i, x, y, 0);
+       {
+         font->driver->draw (s, j, i, x, y, 0);
+         if (s->face->overstrike)
+           font->driver->draw (s, j, i, x + 1, y, 0);
+       }
     }
 }
 
@@ -2944,6 +2954,12 @@ x_clear_frame (struct frame *f)
      colors or something like that, then they should be notified.  */
   x_scroll_bar_clear (f);
 
+#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
+  /* Make sure scroll bars are redrawn.  As they aren't redrawn by
+     redisplay, do it here.  */
+  gtk_widget_queue_draw (FRAME_GTK_WIDGET (f));
+#endif
+  
   XFlush (FRAME_X_DISPLAY (f));
 
   UNBLOCK_INPUT;
@@ -3049,7 +3065,7 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                          + FRAME_TOP_MARGIN_HEIGHT (f)),
                          width, flash_height);
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
@@ -3103,7 +3119,7 @@ XTflash (f)
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
                          (FRAME_INTERNAL_BORDER_WIDTH (f)
-                          + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
+                          + FRAME_TOP_MARGIN_HEIGHT (f)),
                          width, flash_height);
          XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
                          flash_left,
@@ -3128,6 +3144,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
@@ -3357,6 +3393,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);
     }
 }
 
@@ -3886,7 +3924,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;
@@ -3903,8 +3948,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
@@ -4332,63 +4383,51 @@ xm_scroll_callback (widget, client_data, call_data)
 /* Scroll bar callback for GTK scroll bars.  WIDGET is the scroll
    bar widget.  DATA is a pointer to the scroll_bar structure. */
 
-static void
-xg_scroll_callback (widget, data)
-     GtkRange *widget;
-     gpointer data;
+static gboolean
+xg_scroll_callback (GtkRange     *range,
+                    GtkScrollType scroll,
+                    gdouble       value,
+                    gpointer      user_data)
 {
-  struct scroll_bar *bar = (struct scroll_bar *) data;
-  gdouble previous;
+  struct scroll_bar *bar = (struct scroll_bar *) user_data;
   gdouble position;
-  gdouble *p;
-  int diff;
-
   int part = -1, whole = 0, portion = 0;
-  GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
+  GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range));
+  FRAME_PTR f = (FRAME_PTR) g_object_get_data (G_OBJECT (range), XG_FRAME_DATA);
 
+  if (xg_ignore_gtk_scrollbar) return FALSE;
   position = gtk_adjustment_get_value (adj);
 
-  p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
-  if (! p)
-    {
-      p = (gdouble*) xmalloc (sizeof (gdouble));
-      *p = XG_SB_MIN;
-      g_object_set_data (G_OBJECT (widget), XG_LAST_SB_DATA, p);
-    }
-
-  previous = *p;
-  *p = position;
-
-  if (xg_ignore_gtk_scrollbar) return;
-
-  diff = (int) (position - previous);
 
-  if (diff == (int) adj->step_increment)
-    {
-      part = scroll_bar_down_arrow;
-      bar->dragging = Qnil;
-    }
-  else if (-diff == (int) adj->step_increment)
+  switch (scroll)
     {
+    case GTK_SCROLL_JUMP:
+      /* Buttons 1 2 or 3 must be grabbed.  */
+      if (FRAME_X_DISPLAY_INFO (f)->grabbed != 0
+          && FRAME_X_DISPLAY_INFO (f)->grabbed < (1 << 4))
+        {
+          part = scroll_bar_handle;
+          whole = adj->upper - adj->page_size;
+          portion = min ((int)position, whole);
+          bar->dragging = make_number ((int)portion);
+        }
+      break;
+    case GTK_SCROLL_STEP_BACKWARD:
       part = scroll_bar_up_arrow;
       bar->dragging = Qnil;
-    }
-  else if (diff == (int) adj->page_increment)
-    {
-      part = scroll_bar_below_handle;
+      break;
+    case GTK_SCROLL_STEP_FORWARD:
+      part = scroll_bar_down_arrow;
       bar->dragging = Qnil;
-    }
-  else if (-diff == (int) adj->page_increment)
-    {
+      break;
+    case GTK_SCROLL_PAGE_BACKWARD:
       part = scroll_bar_above_handle;
       bar->dragging = Qnil;
-    }
-  else
-    {
-      part = scroll_bar_handle;
-      whole = adj->upper - adj->page_size;
-      portion = min ((int)position, whole);
-      bar->dragging = make_number ((int)portion);
+      break;
+    case GTK_SCROLL_PAGE_FORWARD:
+      part = scroll_bar_below_handle;
+      bar->dragging = Qnil;
+      break;
     }
 
   if (part >= 0)
@@ -4397,8 +4436,30 @@ xg_scroll_callback (widget, data)
       last_scroll_bar_part = part;
       x_send_scroll_bar_event (bar->window, part, portion, whole);
     }
+
+  return FALSE;
+}
+
+/* Callback for button release. Sets dragging to Qnil when dragging is done.  */
+
+static gboolean
+xg_end_scroll_callback (GtkWidget *widget,
+                        GdkEventButton *event,
+                        gpointer user_data)
+{
+  struct scroll_bar *bar = (struct scroll_bar *) user_data;
+  bar->dragging = Qnil;
+  if (WINDOWP (window_being_scrolled))
+    {
+      x_send_scroll_bar_event (window_being_scrolled,
+                               scroll_bar_end_scroll, 0, 0);
+      window_being_scrolled = Qnil;
+    }
+
+  return FALSE;
 }
 
+
 #else /* not USE_GTK and not USE_MOTIF */
 
 /* Xaw scroll bar callback.  Invoked when the thumb is dragged.
@@ -4499,6 +4560,7 @@ x_create_toolkit_scroll_bar (f, bar)
 
   BLOCK_INPUT;
   xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback),
+                        G_CALLBACK (xg_end_scroll_callback),
                         scroll_bar_name);
   UNBLOCK_INPUT;
 }
@@ -4568,7 +4630,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 */
 
@@ -4601,18 +4663,26 @@ x_create_toolkit_scroll_bar (f, bar)
   if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
     {
       pixel = f->output_data.x->scroll_bar_background_pixel;
-      if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
-                                 &pixel, 1.2, 0x8000))
-       pixel = -1;
-      f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
+      if (pixel != -1) 
+        {
+          if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
+                                      FRAME_X_COLORMAP (f),
+                                      &pixel, 1.2, 0x8000))
+            pixel = -1;
+          f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
+        }
     }
   if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
     {
       pixel = f->output_data.x->scroll_bar_background_pixel;
-      if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
-                                 &pixel, 0.6, 0x4000))
-       pixel = -1;
-      f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
+      if (pixel != -1) 
+        {
+          if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f),
+                                      FRAME_X_COLORMAP (f),
+                                      &pixel, 0.6, 0x4000))
+            pixel = -1;
+          f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
+        }
     }
 
 #ifdef XtNbeNiceToColormap
@@ -5793,7 +5863,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
   EVENT_INIT (inev.ie);
   inev.ie.kind = NO_EVENT;
   inev.ie.arg = Qnil;
-
+  
+  if (pending_event_wait.eventtype == event.type)
+    pending_event_wait.eventtype = 0; /* Indicates we got it.  */
+  
   switch (event.type)
     {
     case ClientMessage:
@@ -5975,6 +6048,8 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
             goto done;
           }
 
+        xft_settings_event (dpyinfo, &event);
+
        f = x_any_window_to_frame (dpyinfo, event.xclient.window);
        if (!f)
          goto OTHER;
@@ -6037,6 +6112,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         x_handle_net_wm_state (f, &event.xproperty);
 
       x_handle_property_notify (&event.xproperty);
+      xft_settings_event (dpyinfo, &event);
       goto OTHER;
 
     case ReparentNotify:
@@ -6188,6 +6264,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;
@@ -6204,8 +6285,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                in case this is the second frame.  */
             record_asynch_buffer_change ();
 
-          /* Check if fullscreen was specified before we where mapped. */
-          x_check_fullscreen (f);
+#ifdef USE_GTK
+          xg_frame_resized (f, -1, -1);
+#endif
         }
       goto OTHER;
 
@@ -6517,8 +6599,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
                if (nchars == nbytes)
                  c = copy_bufptr[i], len = 1;
                else
-                 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
-                                             nbytes - i, len);
+                 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i, len);
                inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
                                ? ASCII_KEYSTROKE_EVENT
                                : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
@@ -6631,6 +6712,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
             clear_mouse_face (dpyinfo);
           }
 
+#ifdef USE_GTK
+        if (f && xg_event_is_for_scrollbar (f, &event))
+          f = 0;
+#endif
         if (f)
           {
 
@@ -6733,7 +6818,7 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
 
 #ifdef USE_GTK
           /* GTK creates windows but doesn't map them.
-             Only get real positions and check fullscreen when mapped. */
+             Only get real positions when mapped. */
           if (FRAME_GTK_OUTER_WIDGET (f)
               && GTK_WIDGET_MAPPED (FRAME_GTK_OUTER_WIDGET (f)))
 #endif
@@ -6746,15 +6831,6 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
             xic_set_statusarea (f);
 #endif
 
-#ifndef USE_GTK
-          if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-            {
-              /* Since the WM decorations come below top_pos now,
-                 we must put them below top_pos in the future.  */
-              f->win_gravity = NorthWestGravity;
-              x_wm_set_size_hint (f, (long) 0, 0);
-            }
-#endif
         }
       goto OTHER;
 
@@ -6776,6 +6852,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         else
           f = x_window_to_frame (dpyinfo, event.xbutton.window);
 
+#ifdef USE_GTK
+        if (f && xg_event_is_for_scrollbar (f, &event))
+          f = 0;
+#endif
         if (f)
           {
             /* Is this in the tool-bar?  */
@@ -6935,6 +7015,10 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         }
       goto OTHER;
 
+    case DestroyNotify:
+      xft_settings_event (dpyinfo, &event);
+      break;
+
     default:
     OTHER:
 #ifdef USE_X_TOOLKIT
@@ -7079,7 +7163,7 @@ XTread_socket (terminal, expected, hold_quit)
 #ifdef HAVE_X_I18N
       /* Filter events for the current X input method.  */
       if (x_filter_event (terminal->display_info.x, &event))
-        break;
+        continue;
 #endif
       event_found = 1;
 
@@ -7341,7 +7425,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;
 }
 
 
@@ -7986,7 +8073,7 @@ 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));
+        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
     }
 
 #ifdef HAVE_X_I18N
@@ -8456,6 +8543,18 @@ set_wm_state (frame, add, what, what2)
                           : 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
@@ -8535,6 +8634,7 @@ x_handle_net_wm_state (f, event)
   unsigned char *tmp_data = NULL;
   Atom target_type = XA_ATOM;
   Lisp_Object lval;
+  int sticky = 0;
 
   BLOCK_INPUT;
   x_catch_errors (dpy);
@@ -8572,6 +8672,8 @@ x_handle_net_wm_state (f, event)
         }
       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;
@@ -8592,7 +8694,8 @@ x_handle_net_wm_state (f, event)
     }
       
   store_frame_param (f, Qfullscreen, lval);
-  
+  store_frame_param (f, Qsticky, sticky ? Qt : Qnil);
+
   if (tmp_data) XFree (tmp_data);
   UNBLOCK_INPUT;
 }
@@ -8607,7 +8710,7 @@ x_check_fullscreen (f)
     return;
 
   if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
-    return; // Only fullscreen without WM or with EWM hints (above).
+    return; /* Only fullscreen without WM or with EWM hints (above). */
 
   if (f->want_fullscreen != FULLSCREEN_NONE)
     {
@@ -8732,6 +8835,49 @@ x_sync_with_move (f, left, top, fuzzy)
 }
 
 
+/* Wait for an event on frame F matching EVENTTYPE.  */
+void
+x_wait_for_event (f, eventtype)
+     struct frame *f;
+     int eventtype;
+{
+  int level = interrupt_input_blocked;
+
+  SELECT_TYPE fds;
+  EMACS_TIME tmo, tmo_at, time_now;
+  int fd = ConnectionNumber (FRAME_X_DISPLAY (f));
+
+  pending_event_wait.f = f;
+  pending_event_wait.eventtype = eventtype;
+
+  /* Set timeout to 0.1 second.  Hopefully not noticable.
+     Maybe it should be configurable.  */
+  EMACS_SET_SECS_USECS (tmo, 0, 100000);
+  EMACS_GET_TIME (tmo_at);
+  EMACS_ADD_TIME (tmo_at, tmo_at, tmo);
+
+  while (pending_event_wait.eventtype)
+    {
+      interrupt_input_pending = 1;
+      TOTALLY_UNBLOCK_INPUT;
+      /* XTread_socket is called after unblock.  */
+      BLOCK_INPUT;
+      interrupt_input_blocked = level;
+
+      FD_ZERO (&fds);
+      FD_SET (fd, &fds);
+      
+      EMACS_GET_TIME (time_now);
+      EMACS_SUB_TIME (tmo, tmo_at, time_now);
+
+      if (EMACS_TIME_NEG_P (tmo) || select (fd+1, &fds, NULL, NULL, &tmo) == 0)
+        break; /* Timeout */
+    }
+  pending_event_wait.f = 0;
+  pending_event_wait.eventtype = 0;
+}
+
+
 /* Change the size of frame F's X window to COLS/ROWS in the case F
    doesn't have a widget.  If CHANGE_GRAVITY is 1, we change to
    top-left-corner window gravity for this size change and subsequent
@@ -8755,16 +8901,24 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
-  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
+    + 2*f->border_width;
+  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
+    + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f)
+    + 2*f->border_width;
 
-  f->win_gravity = NorthWestGravity;
+  if (change_gravity) f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
-
-  XSync (FRAME_X_DISPLAY (f), False);
-  XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+  XResizeWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
                 pixelwidth, pixelheight);
 
+
+  /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
+     receive in the ConfigureNotify event; if we get what we asked
+     for, then the event won't cause the screen to become garbaged, so
+     we have to make sure to do it here.  */
+  SET_FRAME_GARBAGED (f);
+
   /* Now, strictly speaking, we can't be sure that this is accurate,
      but the window manager will get around to dealing with the size
      change request eventually, and we'll hear how it went when the
@@ -8778,17 +8932,19 @@ x_set_window_size_1 (f, change_gravity, cols, rows)
 
      We pass 1 for DELAY since we can't run Lisp code inside of
      a BLOCK_INPUT.  */
-  change_frame_size (f, rows, cols, 0, 1, 0);
-  FRAME_PIXEL_WIDTH (f) = pixelwidth;
-  FRAME_PIXEL_HEIGHT (f) = pixelheight;
-
-  /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
-     receive in the ConfigureNotify event; if we get what we asked
-     for, then the event won't cause the screen to become garbaged, so
-     we have to make sure to do it here.  */
-  SET_FRAME_GARBAGED (f);
 
-  XFlush (FRAME_X_DISPLAY (f));
+  /* But the ConfigureNotify may in fact never arrive, and then this is
+     not right if the frame is visible.  Instead wait (with timeout)
+     for the ConfigureNotify.  */
+  if (f->async_visible)
+    x_wait_for_event (f, ConfigureNotify);
+  else
+    {
+      change_frame_size (f, rows, cols, 0, 1, 0);
+      FRAME_PIXEL_WIDTH (f) = pixelwidth;
+      FRAME_PIXEL_HEIGHT (f) = pixelheight;
+      x_sync (f);
+    }
 }
 
 
@@ -8805,33 +8961,42 @@ x_set_window_size (f, change_gravity, cols, rows)
 {
   BLOCK_INPUT;
 
+  if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+    {
+      int r, c;
+         
+      /* When the frame is maximized/fullscreen or running under for
+         example Xmonad, x_set_window_size_1 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_1
+         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 pixelh = FRAME_PIXEL_HEIGHT (f);
+#ifdef USE_X_TOOLKIT
+      /* The menu bar is not part of text lines.  The tool bar
+         is however.  */
+      pixelh -= FRAME_MENUBAR_HEIGHT (f);
+#endif
+      r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
+      /* Update f->scroll_bar_actual_width because it is used in
+         FRAME_PIXEL_WIDTH_TO_TEXT_COLS.  */
+      f->scroll_bar_actual_width
+        = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
+      c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
+      change_frame_size (f, r, c, 0, 1, 0);
+    }
+
 #ifdef USE_GTK
   if (FRAME_GTK_WIDGET (f))
     xg_frame_set_char_size (f, cols, rows);
   else
     x_set_window_size_1 (f, change_gravity, cols, rows);
-#elif USE_X_TOOLKIT
-
-  if (f->output_data.x->widget != NULL)
-    {
-      /* The x and y position of the widget is clobbered by the
-        call to XtSetValues within EmacsFrameSetCharSize.
-        This is a real kludge, but I don't understand Xt so I can't
-        figure out a correct fix.  Can anyone else tell me? -- rms.  */
-      int xpos = f->output_data.x->widget->core.x;
-      int ypos = f->output_data.x->widget->core.y;
-      EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
-      f->output_data.x->widget->core.x = xpos;
-      f->output_data.x->widget->core.y = ypos;
-    }
-  else
-    x_set_window_size_1 (f, change_gravity, cols, rows);
-
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_GTK */
 
   x_set_window_size_1 (f, change_gravity, cols, rows);
 
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_GTK */
 
   /* If cursor was outside the new size, mark it as off.  */
   mark_window_cursors_off (XWINDOW (f->root_window));
@@ -9533,13 +9698,6 @@ x_wm_set_size_hint (f, flags, user_position)
      int user_position;
 {
   XSizeHints size_hints;
-
-#ifdef USE_X_TOOLKIT
-  Arg al[2];
-  int ac = 0;
-  Dimension widget_width, widget_height;
-#endif
-
   Window window = FRAME_OUTER_WINDOW (f);
 
   /* Setting PMaxSize caused various problems.  */
@@ -9548,16 +9706,8 @@ x_wm_set_size_hint (f, flags, user_position)
   size_hints.x = f->left_pos;
   size_hints.y = f->top_pos;
 
-#ifdef USE_X_TOOLKIT
-  XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
-  XtSetArg (al[ac], XtNheight, &widget_height); ac++;
-  XtGetValues (f->output_data.x->widget, al, ac);
-  size_hints.height = widget_height;
-  size_hints.width = widget_width;
-#else /* not USE_X_TOOLKIT */
   size_hints.height = FRAME_PIXEL_HEIGHT (f);
   size_hints.width = FRAME_PIXEL_WIDTH (f);
-#endif /* not USE_X_TOOLKIT */
 
   size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
   size_hints.height_inc = FRAME_LINE_HEIGHT (f);
@@ -9566,11 +9716,7 @@ x_wm_set_size_hint (f, flags, user_position)
   size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
     - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
-  /* Calculate the base and minimum sizes.
-
-     (When we use the X toolkit, we don't do it here.
-     Instead we copy the values that the widgets are using, below.)  */
-#ifndef USE_X_TOOLKIT
+  /* Calculate the base and minimum sizes.  */
   {
     int base_width, base_height;
     int min_rows = 0, min_cols = 0;
@@ -9592,7 +9738,7 @@ x_wm_set_size_hint (f, flags, user_position)
 
     size_hints.flags |= PBaseSize;
     size_hints.base_width = base_width;
-    size_hints.base_height = base_height;
+    size_hints.base_height = base_height + FRAME_MENUBAR_HEIGHT (f);
     size_hints.min_width  = base_width + min_cols * size_hints.width_inc;
     size_hints.min_height = base_height + min_rows * size_hints.height_inc;
   }
@@ -9603,7 +9749,6 @@ x_wm_set_size_hint (f, flags, user_position)
       size_hints.flags |= flags;
       goto no_read;
     }
-#endif /* not USE_X_TOOLKIT */
 
   {
     XSizeHints hints;          /* Sometimes I hate X Windows... */
@@ -9613,13 +9758,6 @@ x_wm_set_size_hint (f, flags, user_position)
     value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
                               &supplied_return);
 
-#ifdef USE_X_TOOLKIT
-    size_hints.base_height = hints.base_height;
-    size_hints.base_width = hints.base_width;
-    size_hints.min_height = hints.min_height;
-    size_hints.min_width = hints.min_width;
-#endif
-
     if (flags)
       size_hints.flags |= flags;
     else
@@ -9637,9 +9775,7 @@ x_wm_set_size_hint (f, flags, user_position)
       }
   }
 
-#ifndef USE_X_TOOLKIT
  no_read:
-#endif
 
 #ifdef PWinGravity
   size_hints.win_gravity = f->win_gravity;
@@ -9894,6 +10030,19 @@ x_display_ok (display)
     return dpy_ok;
 }
 
+#ifdef USE_GTK
+static void
+my_log_handler (log_domain, log_level, message, user_data)
+     const gchar *log_domain;
+     GLogLevelFlags log_level;
+     const gchar *message;
+     gpointer user_data;
+{
+  if (!strstr (message, "g_set_prgname"))
+      fprintf (stderr, "%s-WARNING **: %s\n", log_domain, message);
+}
+#endif
+  
 /* Open a connection to X display DISPLAY_NAME, and return
    the structure that describes the open display.
    If we cannot contact the display, return null.  */
@@ -9928,9 +10077,9 @@ x_term_init (display_name, xrm_option, resource_name)
     char *argv[NUM_ARGV];
     char **argv2 = argv;
     GdkAtom atom;
-
+    guint id;
 #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
 
@@ -9963,7 +10112,12 @@ x_term_init (display_name, xrm_option, resource_name)
 
         XSetLocaleModifiers ("");
 
+        /* Work around GLib bug that outputs a faulty warning. See
+           https://bugzilla.gnome.org/show_bug.cgi?id=563627.  */
+        id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL
+                                  | G_LOG_FLAG_RECURSION, my_log_handler, NULL);
         gtk_init (&argc, &argv2);
+        g_log_remove_handler ("GLib", id);
 
         /* gtk_init does set_locale.  We must fix locale after calling it.  */
         fixup_locale ();
@@ -10060,7 +10214,7 @@ 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);
@@ -10199,17 +10353,33 @@ x_term_init (display_name, xrm_option, resource_name)
     dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
                                     dpyinfo->visual, AllocNone);
 
+#ifdef HAVE_XFT
   {
-    int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
-    double pixels = DisplayHeight (dpyinfo->display, screen_number);
-    double mm = DisplayHeightMM (dpyinfo->display, screen_number);
-    /* 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);
-    mm = DisplayWidthMM (dpyinfo->display, screen_number);
-    /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
-    dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
+    /* If we are using Xft, check dpi value in X resources.
+       It is better we use it as well, since Xft will use it, as will all
+       Gnome applications.  If our real DPI is smaller or larger than the
+       one Xft uses, our font will look smaller or larger than other
+       for other applications, even if it is the same font name (monospace-10
+       for example).  */
+    char *v = XGetDefault (dpyinfo->display, "Xft", "dpi");
+    double d;
+    if (v != NULL && sscanf (v, "%lf", &d) == 1)
+      dpyinfo->resy = dpyinfo->resx = d;
   }
+#endif
+
+  if (dpyinfo->resy < 1)
+    {
+      int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
+      double pixels = DisplayHeight (dpyinfo->display, screen_number);
+      double mm = DisplayHeightMM (dpyinfo->display, screen_number);
+      /* 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);
+      mm = DisplayWidthMM (dpyinfo->display, screen_number);
+      /* Mac OS X 10.3's Xserver sometimes reports 0.0mm.  */
+      dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
+    }
 
   dpyinfo->Xatom_wm_protocols
     = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
@@ -10283,7 +10453,13 @@ x_term_init (display_name, xrm_option, resource_name)
     = 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->Xatom_net_window_type
+    = XInternAtom (dpyinfo->display, "_NET_WM_WINDOW_TYPE", False);
+  dpyinfo->Xatom_net_window_type_tooltip
+    = XInternAtom (dpyinfo->display, "_NET_WM_WINDOW_TYPE_TOOLTIP", False);
+  
   dpyinfo->cut_buffers_initialized = 0;
 
   dpyinfo->x_dnd_atoms_size = 8;
@@ -10312,6 +10488,8 @@ x_term_init (display_name, xrm_option, resource_name)
   xim_initialize (dpyinfo, resource_name);
 #endif
 
+  xsettings_initialize (dpyinfo);
+
 #ifdef subprocesses
   /* This is only needed for distinguishing keyboard and process input.  */
   if (connection != 0)
@@ -10612,6 +10790,8 @@ x_delete_terminal (struct terminal *terminal)
 #endif /* ! USE_GTK */
     }
 
+  /* Mark as dead. */
+  dpyinfo->display = NULL;
   x_delete_display (dpyinfo);
   UNBLOCK_INPUT;
 }
@@ -10636,6 +10816,7 @@ x_create_terminal (struct x_display_info *dpyinfo)
   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;
@@ -10709,12 +10890,18 @@ x_initialize ()
 #endif
 #endif
 
+  pending_autoraise_frame = 0;
+  pending_event_wait.f = 0;
+  pending_event_wait.eventtype = 0;
+
   /* Note that there is no real way portable across R3/R4 to get the
      original error handler.  */
   XSetErrorHandler (x_error_handler);
   XSetIOErrorHandler (x_io_error_quitter);
 
   signal (SIGPIPE, x_connection_signal);
+
+  xgselect_initialize ();
 }
 
 
@@ -10730,17 +10917,20 @@ syms_of_xterm ()
   last_mouse_scroll_bar = Qnil;
 
   staticpro (&Qvendor_specific_keysyms);
-  Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+  Qvendor_specific_keysyms = intern_c_string ("vendor-specific-keysyms");
 
   staticpro (&Qlatin_1);
-  Qlatin_1 = intern ("latin-1");
+  Qlatin_1 = intern_c_string ("latin-1");
 
   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");
+  xg_default_icon_file = make_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
   staticpro (&xg_default_icon_file);
+
+  Qx_gtk_map_stock = intern_c_string ("x-gtk-map-stock");
+  staticpro (&Qx_gtk_map_stock);
 #endif
 
   DEFVAR_BOOL ("x-use-underline-position-properties",
@@ -10777,13 +10967,13 @@ A value of nil means Emacs doesn't use X toolkit scroll bars.
 Otherwise, value is a symbol describing the X toolkit.  */);
 #ifdef USE_TOOLKIT_SCROLL_BARS
 #ifdef USE_MOTIF
-  Vx_toolkit_scroll_bars = intern ("motif");
+  Vx_toolkit_scroll_bars = intern_c_string ("motif");
 #elif defined HAVE_XAW3D
-  Vx_toolkit_scroll_bars = intern ("xaw3d");
+  Vx_toolkit_scroll_bars = intern_c_string ("xaw3d");
 #elif USE_GTK
-  Vx_toolkit_scroll_bars = intern ("gtk");
+  Vx_toolkit_scroll_bars = intern_c_string ("gtk");
 #else
-  Vx_toolkit_scroll_bars = intern ("xaw");
+  Vx_toolkit_scroll_bars = intern_c_string ("xaw");
 #endif
 #else
   Vx_toolkit_scroll_bars = Qnil;
@@ -10792,14 +10982,14 @@ Otherwise, value is a symbol describing the X toolkit.  */);
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 
-  Qmodifier_value = intern ("modifier-value");
-  Qalt = intern ("alt");
+  Qmodifier_value = intern_c_string ("modifier-value");
+  Qalt = intern_c_string ("alt");
   Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
-  Qhyper = intern ("hyper");
+  Qhyper = intern_c_string ("hyper");
   Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
-  Qmeta = intern ("meta");
+  Qmeta = intern_c_string ("meta");
   Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
-  Qsuper = intern ("super");
+  Qsuper = intern_c_string ("super");
   Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
 
   DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,