Merged in changes from CVS HEAD
[bpt/emacs.git] / src / xfns.c
index 4ce7dec..a649ddd 100644 (file)
@@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA.  */
 #include "systime.h"
 #include "termhooks.h"
 #include "atimer.h"
+#include "termchar.h"
 
 #ifdef HAVE_X_WINDOWS
 
@@ -125,6 +126,14 @@ static Lisp_Object Vmotif_version_string;
 
 #endif /* USE_X_TOOLKIT */
 
+#ifdef USE_GTK
+
+/* GTK+ version info */
+
+static Lisp_Object Vgtk_version_string;
+
+#endif /* USE_GTK */
+
 #ifdef HAVE_X11R4
 #define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
 #else
@@ -300,7 +309,7 @@ x_window_to_frame (dpyinfo, wdesc)
 #ifdef USE_GTK
       if (f->output_data.x->edit_widget)
       {
-        GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+        GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
         struct x_output *x = f->output_data.x;
         if (gwdesc != 0 && gwdesc == x->edit_widget)
           return f;
@@ -344,7 +353,7 @@ x_any_window_to_frame (dpyinfo, wdesc)
          else if (x->widget)
            {
 #ifdef USE_GTK
-              GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+              GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
               if (gwdesc != 0
                   && (gwdesc == x->widget
                       || gwdesc == x->edit_widget
@@ -396,7 +405,7 @@ x_non_menubar_window_to_frame (dpyinfo, wdesc)
       else if (x->widget)
        {
 #ifdef USE_GTK
-          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+          GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
           if (gwdesc != 0
               && (gwdesc == x->widget
                   || gwdesc == x->edit_widget
@@ -440,7 +449,7 @@ x_menubar_window_to_frame (dpyinfo, wdesc)
 #ifdef USE_GTK
       if (x->menubar_widget)
         {
-          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+          GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
           int found = 0;
 
           BLOCK_INPUT;
@@ -486,7 +495,7 @@ x_top_window_to_frame (dpyinfo, wdesc)
        {
          /* This frame matches if the window is its topmost widget.  */
 #ifdef USE_GTK
-          GtkWidget *gwdesc = xg_win_to_widget (wdesc);
+          GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
           if (gwdesc == x->widget)
             return f;
 #else
@@ -623,6 +632,7 @@ x_create_bitmap_from_data (f, bits, width, height)
 
   id = x_allocate_bitmap_record (f);
   dpyinfo->bitmaps[id - 1].pixmap = bitmap;
+  dpyinfo->bitmaps[id - 1].have_mask = 0;
   dpyinfo->bitmaps[id - 1].file = NULL;
   dpyinfo->bitmaps[id - 1].refcount = 1;
   dpyinfo->bitmaps[id - 1].depth = 1;
@@ -674,6 +684,7 @@ x_create_bitmap_from_file (f, file)
 
   id = x_allocate_bitmap_record (f);
   dpyinfo->bitmaps[id - 1].pixmap = bitmap;
+  dpyinfo->bitmaps[id - 1].have_mask = 0;
   dpyinfo->bitmaps[id - 1].refcount = 1;
   dpyinfo->bitmaps[id - 1].file
     = (char *) xmalloc (SBYTES (file) + 1);
@@ -701,7 +712,8 @@ x_destroy_bitmap (f, id)
        {
          BLOCK_INPUT;
          XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap);
-         XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].mask);
+         if (dpyinfo->bitmaps[id - 1].have_mask)
+           XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].mask);
          if (dpyinfo->bitmaps[id - 1].file)
            {
              xfree (dpyinfo->bitmaps[id - 1].file);
@@ -723,7 +735,8 @@ x_destroy_all_bitmaps (dpyinfo)
     if (dpyinfo->bitmaps[i].refcount > 0)
       {
        XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap);
-       XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].mask);
+       if (dpyinfo->bitmaps[i].have_mask)
+         XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].mask);
        if (dpyinfo->bitmaps[i].file)
          xfree (dpyinfo->bitmaps[i].file);
       }
@@ -750,7 +763,7 @@ static void x_destroy_x_image P_ ((XImage *ximg));
    It's nicer with some borders in this context */
 
 int
-x_create_bitmap_mask(f, id)
+x_create_bitmap_mask (f, id)
      struct frame *f;
      int id;
 {
@@ -762,15 +775,14 @@ x_create_bitmap_mask(f, id)
   unsigned long x, y, xp, xm, yp, ym;
   GC gc;
 
-  int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
   if (!(id > 0))
     return -1;
 
-  pixmap = x_bitmap_pixmap(f, id);
-  width = x_bitmap_width(f, id);
-  height = x_bitmap_height(f, id);
+  pixmap = x_bitmap_pixmap (f, id);
+  width = x_bitmap_width (f, id);
+  height = x_bitmap_height (f, id);
 
   BLOCK_INPUT;
   ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
@@ -787,7 +799,7 @@ x_create_bitmap_mask(f, id)
   UNBLOCK_INPUT;
   if (!result)
     {
-      XDestroyImage(ximg);
+      XDestroyImage (ximg);
       return -1;
     }
 
@@ -822,10 +834,11 @@ x_create_bitmap_mask(f, id)
             width, height);
   XFreeGC (FRAME_X_DISPLAY (f), gc);
 
+  dpyinfo->bitmaps[id - 1].have_mask = 1;
   dpyinfo->bitmaps[id - 1].mask = mask;
 
   XDestroyImage (ximg);
-  x_destroy_x_image(mask_img);
+  x_destroy_x_image (mask_img);
 
   return 0;
 }
@@ -1087,36 +1100,51 @@ x_set_wait_for_wm (f, new_value, old_value)
 
 #ifdef USE_GTK
 
-/* Wrapper for gtk_window_icon_from_file() */
+static Lisp_Object x_find_image_file P_ ((Lisp_Object file));
+
+/* Set icon from FILE for frame F.  By using GTK functions the icon
+   may be any format that GdkPixbuf knows about, i.e. not just bitmaps.  */
 
 int
-xg_set_icon(f, file)
-    struct frame *f;
+xg_set_icon (f, file)
+    FRAME_PTR f;
     Lisp_Object file;
 {
-    struct gcpro gcpro1, gcpro2, gcpro3;
-    int fd;
-    int result = 1;
-    Lisp_Object found, search_path;
-    char *filename;
+  struct gcpro gcpro1;
+  int result = 0;
+  Lisp_Object found;
 
-    search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
+  GCPRO1 (found);
 
-    GCPRO3 (found, search_path, file);
-    fd = openp (search_path, file, Qnil, &found, Qnil);
-    if (fd > 0)
-      {
-       filename = (char *) SDATA (found);
-       BLOCK_INPUT;
-       result =
-         gtk_window_set_icon_from_file (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
-                                        filename,
-                                        NULL);
-       UNBLOCK_INPUT;
-      }
-    emacs_close (fd);
-    UNGCPRO;
-    return result;
+  found = x_find_image_file (file);
+
+  if (! NILP (found))
+    {
+      GdkPixbuf *pixbuf;
+      GError *err = NULL;
+      char *filename;
+
+      filename = SDATA (found);
+      BLOCK_INPUT;
+
+      pixbuf = gdk_pixbuf_new_from_file (filename, &err);
+
+      if (pixbuf)
+       {
+         gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
+                              pixbuf);
+         g_object_unref (pixbuf);
+
+         result = 1;
+       }
+      else
+       g_error_free (err);
+
+      UNBLOCK_INPUT;
+    }
+
+  UNGCPRO;
+  return result;
 }
 #endif /* USE_GTK */
 
@@ -1272,7 +1300,6 @@ x_set_mouse_color (f, arg, oldval)
     hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
   x_check_errors (dpy, "bad hourglass pointer cursor: %s");
 
-  x_check_errors (dpy, "bad nontext pointer cursor: %s");
   if (!NILP (Vx_mode_pointer_shape))
     {
       CHECK_NUMBER (Vx_mode_pointer_shape);
@@ -1569,7 +1596,7 @@ x_set_menu_bar_lines (f, value, oldval)
      Lisp_Object value, oldval;
 {
   int nlines;
-#ifndef USE_X_TOOLKIT
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   int olines = FRAME_MENU_BAR_LINES (f);
 #endif
 
@@ -1733,10 +1760,10 @@ x_set_scroll_bar_foreground (f, value, oldval)
   if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
     {
       /* Remove all scroll bars because they have wrong colors.  */
-      if (condemn_scroll_bars_hook)
-       (*condemn_scroll_bars_hook) (f);
-      if (judge_scroll_bars_hook)
-       (*judge_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
+       (*FRAME_DISPLAY (f)->condemn_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
+       (*FRAME_DISPLAY (f)->judge_scroll_bars_hook) (f);
 
       update_face_from_frame_parameter (f, Qscroll_bar_foreground, value);
       redraw_frame (f);
@@ -1782,10 +1809,10 @@ x_set_scroll_bar_background (f, value, oldval)
   if (FRAME_X_WINDOW (f) && FRAME_VISIBLE_P (f))
     {
       /* Remove all scroll bars because they have wrong colors.  */
-      if (condemn_scroll_bars_hook)
-       (*condemn_scroll_bars_hook) (f);
-      if (judge_scroll_bars_hook)
-       (*judge_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->condemn_scroll_bars_hook)
+       (*FRAME_DISPLAY (f)->condemn_scroll_bars_hook) (f);
+      if (FRAME_DISPLAY (f)->judge_scroll_bars_hook)
+       (*FRAME_DISPLAY (f)->judge_scroll_bars_hook) (f);
 
       update_face_from_frame_parameter (f, Qscroll_bar_background, value);
       redraw_frame (f);
@@ -2430,8 +2457,8 @@ create_frame_xic (f)
 
       xic = XCreateIC (xim,
                       XNInputStyle, xic_style,
-                      XNClientWindow, FRAME_X_WINDOW(f),
-                      XNFocusWindow, FRAME_X_WINDOW(f),
+                      XNClientWindow, FRAME_X_WINDOW (f),
+                      XNFocusWindow, FRAME_X_WINDOW (f),
                       XNStatusAttributes, status_attr,
                       XNPreeditAttributes, preedit_attr,
                       NULL);
@@ -2522,7 +2549,7 @@ xic_set_statusarea (f)
   XFree (needed);
 
   attr = XVaCreateNestedList (0, XNArea, &area, NULL);
-  XSetICValues(xic, XNStatusAttributes, attr, NULL);
+  XSetICValues (xic, XNStatusAttributes, attr, NULL);
   XFree (attr);
 }
 
@@ -2642,7 +2669,7 @@ x_window (f, window_prompting, minibuffer_only)
   {
     int len;
     char *tem, shell_position[32];
-    Arg al[2];
+    Arg al[10];
     int ac = 0;
     int extra_borders = 0;
     int menubar_size
@@ -2694,9 +2721,19 @@ x_window (f, window_prompting, minibuffer_only)
                 (xneg ? '-' : '+'), left,
                 (yneg ? '-' : '+'), top);
       else
-       sprintf (shell_position, "=%dx%d",
-                FRAME_PIXEL_WIDTH (f) + extra_borders,
-                FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
+        {
+          sprintf (shell_position, "=%dx%d",
+                   FRAME_PIXEL_WIDTH (f) + extra_borders,
+                   FRAME_PIXEL_HEIGHT (f) + menubar_size + extra_borders);
+
+          /* Setting x and y when the position is not specified in
+             the geometry string will set program position in the WM hints.
+             If Emacs had just one program position, we could set it in
+             fallback resources, but since each make-frame call can specify
+             different program positions, this is easier.  */
+          XtSetArg (al[ac], XtNx, left); ac++;
+          XtSetArg (al[ac], XtNy, top); ac++;
+        }
     }
 
     len = strlen (shell_position) + 1;
@@ -2755,7 +2792,7 @@ x_window (f, window_prompting, minibuffer_only)
     {
       /* XIM server might require some X events. */
       unsigned long fevent = NoEventMask;
-      XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+      XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
       attributes.event_mask |= fevent;
     }
 #endif /* HAVE_X_I18N */
@@ -2809,7 +2846,7 @@ if (use_xim)
       {
        /* XIM server might require some X events. */
        unsigned long fevent = NoEventMask;
-       XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+       XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
 
        if (fevent != NoEventMask)
          {
@@ -2873,7 +2910,7 @@ x_window (f)
        {
          /* XIM server might require some X events. */
          unsigned long fevent = NoEventMask;
-         XGetICValues(FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
+         XGetICValues (FRAME_XIC (f), XNFilterEvents, &fevent, NULL);
          attributes.event_mask |= fevent;
          attribute_mask = CWEventMask;
          XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -3150,8 +3187,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
   Lisp_Object parent;
   struct kboard *kb;
 
-  check_x ();
-
   /* Use this general default value to start with
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
@@ -3206,6 +3241,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Note that X Windows does support scroll bars.  */
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
 
+  f->display = dpyinfo->frame_display;
+  f->display->reference_count++;
+
   f->output_method = output_x_window;
   f->output_data.x = (struct x_output *) xmalloc (sizeof (struct x_output));
   bzero (f->output_data.x, sizeof (struct x_output));
@@ -3295,6 +3333,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
       specbind (Qx_resource_name, name);
     }
 
+  Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
+
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
   {
@@ -3506,6 +3546,19 @@ This function is an internal primitive--use `make-frame' instead.  */)
        ;
     }
 
+  /* Set the WM leader property.  GTK does this itself, so this is not
+     needed when using GTK.  */
+  if (dpyinfo->client_leader_window != 0)
+    {
+      BLOCK_INPUT;
+      XChangeProperty (FRAME_X_DISPLAY (f),
+                       FRAME_OUTER_WINDOW (f),
+                       dpyinfo->Xatom_wm_client_leader,
+                       XA_WINDOW, 32, PropModeReplace,
+                       (char *) &dpyinfo->client_leader_window, 1);
+      UNBLOCK_INPUT;
+    }
+
   UNGCPRO;
 
   /* Make sure windows on this frame appear in calls to next-window
@@ -4070,8 +4123,10 @@ x_display_info_for_name (name)
 
   CHECK_STRING (name);
 
-  if (! EQ (Vwindow_system, intern ("x")))
-    error ("Not using X Windows");
+#if 0
+  if (! EQ (Vinitial_window_system, intern ("x")))
+    error ("Not using X Windows"); /* That doesn't stop us anymore. */
+#endif
 
   for (dpyinfo = x_display_list, names = x_display_name_list;
        dpyinfo;
@@ -4118,8 +4173,10 @@ terminate Emacs if we can't open the connection.  */)
   if (! NILP (xrm_string))
     CHECK_STRING (xrm_string);
 
-  if (! EQ (Vwindow_system, intern ("x")))
-    error ("Not using X Windows");
+#if 0
+  if (! EQ (Vinitial_window_system, intern ("x")))
+    error ("Not using X Windows"); /* That doesn't stop us anymore. */
+#endif
 
   if (! NILP (xrm_string))
     xrm_option = (unsigned char *) SDATA (xrm_string);
@@ -4171,9 +4228,6 @@ If DISPLAY is nil, that stands for the selected frame's display.  */)
   for (i = 0; i < dpyinfo->n_fonts; i++)
     if (dpyinfo->font_table[i].name)
       {
-       if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
-         xfree (dpyinfo->font_table[i].full_name);
-       xfree (dpyinfo->font_table[i].name);
        XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
       }
 
@@ -4249,11 +4303,6 @@ x_sync (f)
 
 static struct image_type *image_types;
 
-/* The symbol `image' which is the car of the lists used to represent
-   images in Lisp.  */
-
-extern Lisp_Object Qimage;
-
 /* The symbol `xbm' which is used as the type symbol for XBM images.  */
 
 Lisp_Object Qxbm;
@@ -4333,7 +4382,7 @@ valid_image_p (object)
 {
   int valid_p = 0;
 
-  if (CONSP (object) && EQ (XCAR (object), Qimage))
+  if (IMAGEP (object))
     {
       Lisp_Object tem;
 
@@ -4435,7 +4484,7 @@ parse_image_spec (spec, keywords, nkeywords, type)
   int i;
   Lisp_Object plist;
 
-  if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
+  if (!IMAGEP (spec))
     return 0;
 
   plist = XCDR (spec);
@@ -6714,7 +6763,37 @@ lookup_rgb_color (f, r, g, b)
   unsigned hash = CT_HASH_RGB (r, g, b);
   int i = hash % CT_SIZE;
   struct ct_color *p;
+  struct x_display_info *dpyinfo;
+
+  /* Handle TrueColor visuals specially, which improves performance by
+     two orders of magnitude.  Freeing colors on TrueColor visuals is
+     a nop, and pixel colors specify RGB values directly.  See also
+     the Xlib spec, chapter 3.1.  */
+  dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  if (dpyinfo->red_bits > 0)
+    {
+      unsigned long pr, pg, pb;
 
+      /* Apply gamma-correction like normal color allocation does.  */
+      if (f->gamma)
+       {
+         XColor color;
+         color.red = r, color.green = g, color.blue = b;
+         gamma_correct (f, &color);
+         r = color.red, g = color.green, b = color.blue;
+       }
+
+      /* Scale down RGB values to the visual's bits per RGB, and shift
+        them to the right position in the pixel color.  Note that the
+        original RGB values are 16-bit values, as usual in X.  */
+      pr = (r >> (16 - dpyinfo->red_bits))   << dpyinfo->red_offset;
+      pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
+      pb = (b >> (16 - dpyinfo->blue_bits))  << dpyinfo->blue_offset;
+
+      /* Assemble the pixel color.  */
+      return pr | pg | pb;
+    }
+  
   for (p = ct_table[i]; p; p = p->next)
     if (p->r == r && p->g == g && p->b == b)
       break;
@@ -8969,7 +9048,7 @@ gif_load (f, img)
       memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
-      gif = DGifOpen(&memsrc, gif_read_from_memory);
+      gif = DGifOpen (&memsrc, gif_read_from_memory);
       if (!gif)
        {
          image_error ("Cannot open memory source `%s'", img->spec, Qnil);
@@ -9402,24 +9481,85 @@ x_kill_gs_process (pixmap, f)
  ***********************************************************************/
 
 DEFUN ("x-change-window-property", Fx_change_window_property,
-       Sx_change_window_property, 2, 3, 0,
+       Sx_change_window_property, 2, 6, 0,
        doc: /* Change window property PROP to VALUE on the X window of FRAME.
-PROP and VALUE must be strings.  FRAME nil or omitted means use the
-selected frame.  Value is VALUE.  */)
-     (prop, value, frame)
-     Lisp_Object frame, prop, value;
+PROP must be a string.
+VALUE may be a string or a list of conses, numbers and/or strings.
+If an element in the list is a string, it is converted to
+an Atom and the value of the Atom is used.  If an element is a cons,
+it is converted to a 32 bit number where the car is the 16 top bits and the
+cdr is the lower 16 bits.
+FRAME nil or omitted means use the selected frame.
+If TYPE is given and non-nil, it is the name of the type of VALUE.
+If TYPE is not given or nil, the type is STRING.
+FORMAT gives the size in bits of each element if VALUE is a list.
+It must be one of 8, 16 or 32.
+If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
+If OUTER_P is non-nil, the property is changed for the outer X window of
+FRAME.  Default is to change on the edit X window.
+
+Value is VALUE.  */)
+     (prop, value, frame, type, format, outer_p)
+     Lisp_Object prop, value, frame, type, format, outer_p;
 {
   struct frame *f = check_x_frame (frame);
   Atom prop_atom;
+  Atom target_type = XA_STRING;
+  int element_format = 8;
+  unsigned char *data;
+  int nelements;
+  Window w;
 
   CHECK_STRING (prop);
-  CHECK_STRING (value);
+
+  if (! NILP (format))
+    {
+      CHECK_NUMBER (format);
+      element_format = XFASTINT (format);
+
+      if (element_format != 8 && element_format != 16
+          && element_format != 32)
+        error ("FORMAT must be one of 8, 16 or 32");
+    }
+
+  if (CONSP (value))
+    {
+      nelements = x_check_property_data (value);
+      if (nelements == -1)
+        error ("Bad data in VALUE, must be number, string or cons");
+
+      if (element_format == 8)
+        data = (unsigned char *) xmalloc (nelements);
+      else if (element_format == 16)
+        data = (unsigned char *) xmalloc (nelements*2);
+      else
+        data = (unsigned char *) xmalloc (nelements*4);
+
+      x_fill_property_data (FRAME_X_DISPLAY (f), value, data, element_format);
+    }
+  else
+    {
+      CHECK_STRING (value);
+      data = SDATA (value);
+      nelements = SCHARS (value);
+    }
 
   BLOCK_INPUT;
   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
-  XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                  prop_atom, XA_STRING, 8, PropModeReplace,
-                  SDATA (value), SCHARS (value));
+  if (! NILP (type))
+    {
+      CHECK_STRING (type);
+      target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
+    }
+
+  if (! NILP (outer_p)) w = FRAME_OUTER_WINDOW (f);
+  else w = FRAME_X_WINDOW (f);
+  XChangeProperty (FRAME_X_DISPLAY (f), w,
+                  prop_atom, target_type, element_format, PropModeReplace,
+                  data, nelements);
+
+  if (CONSP (value)) xfree (data);
 
   /* Make sure the property is set when we return.  */
   XFlush (FRAME_X_DISPLAY (f));
@@ -9453,13 +9593,20 @@ FRAME nil or omitted means use the selected frame.  Value is PROP.  */)
 
 
 DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
-       1, 2, 0,
+       1, 6, 0,
        doc: /* Value is the value of window property PROP on FRAME.
-If FRAME is nil or omitted, use the selected frame.  Value is nil
-if FRAME hasn't a property with name PROP or if PROP has no string
-value.  */)
-     (prop, frame)
-     Lisp_Object prop, frame;
+If FRAME is nil or omitted, use the selected frame.
+If TYPE is nil or omitted, get the property as a string.  Otherwise TYPE
+is the name of the Atom that denotes the type expected.
+If SOURCE is non-nil, get the property on that window instead of from
+FRAME.  The number 0 denotes the root window.
+If DELETE_P is non-nil, delete the property after retreiving it.
+If VECTOR_RET_P is non-nil, don't return a string but a vector of values.
+
+Value is nil if FRAME hasn't a property with name PROP or if PROP has
+no value of TYPE.  */)
+     (prop, frame, type, source, delete_p, vector_ret_p)
+     Lisp_Object prop, frame, type, source, delete_p, vector_ret_p;
 {
   struct frame *f = check_x_frame (frame);
   Atom prop_atom;
@@ -9467,14 +9614,43 @@ value.  */)
   Lisp_Object prop_value = Qnil;
   char *tmp_data = NULL;
   Atom actual_type;
+  Atom target_type = XA_STRING;
   int actual_format;
   unsigned long actual_size, bytes_remaining;
+  Window target_window = FRAME_X_WINDOW (f);
+  struct gcpro gcpro1;
 
+  GCPRO1 (prop_value);
   CHECK_STRING (prop);
+
+  if (! NILP (source))
+    {
+      if (NUMBERP (source))
+        {
+          if (FLOATP (source))
+            target_window = (Window) XFLOAT (source);
+          else
+            target_window = XFASTINT (source);
+
+          if (target_window == 0)
+            target_window = FRAME_X_DISPLAY_INFO (f)->root_window;
+        }
+      else if (CONSP (source))
+        target_window = cons_to_long (source);
+    }
+
   BLOCK_INPUT;
+  if (STRINGP (type))
+    {
+      if (strcmp ("AnyPropertyType", SDATA (type)) == 0)
+        target_type = AnyPropertyType;
+      else
+        target_type = XInternAtom (FRAME_X_DISPLAY (f), SDATA (type), False);
+    }
+
   prop_atom = XInternAtom (FRAME_X_DISPLAY (f), SDATA (prop), False);
-  rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                          prop_atom, 0, 0, False, XA_STRING,
+  rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
+                          prop_atom, 0, 0, False, target_type,
                           &actual_type, &actual_format, &actual_size,
                           &bytes_remaining, (unsigned char **) &tmp_data);
   if (rc == Success)
@@ -9484,19 +9660,29 @@ value.  */)
       XFree (tmp_data);
       tmp_data = NULL;
 
-      rc = XGetWindowProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+      rc = XGetWindowProperty (FRAME_X_DISPLAY (f), target_window,
                               prop_atom, 0, bytes_remaining,
-                              False, XA_STRING,
+                              ! NILP (delete_p), target_type,
                               &actual_type, &actual_format,
                               &actual_size, &bytes_remaining,
                               (unsigned char **) &tmp_data);
       if (rc == Success && tmp_data)
-       prop_value = make_string (tmp_data, size);
+        {
+          if (NILP (vector_ret_p))
+            prop_value = make_string (tmp_data, size);
+          else
+            prop_value = x_property_data_to_lisp (f,
+                                                  (unsigned char *) tmp_data,
+                                                  actual_type,
+                                                  actual_format,
+                                                  actual_size);
+        }
 
-      XFree (tmp_data);
+      if (tmp_data) XFree (tmp_data);
     }
 
   UNBLOCK_INPUT;
+  UNGCPRO;
   return prop_value;
 }
 
@@ -9787,6 +9973,9 @@ x_create_tip_frame (dpyinfo, parms, text)
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   record_unwind_protect (unwind_create_tip_frame, frame);
 
+  f->display = dpyinfo->frame_display;
+  f->display->reference_count++;
+
   /* By setting the output method, we're essentially saying that
      the frame is live, as per FRAME_LIVE_P.  If we get a signal
      from this point on, x_destroy_window might screw up reference
@@ -10010,6 +10199,8 @@ x_create_tip_frame (dpyinfo, parms, text)
                                              Qnil));
   }
 
+  Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qx), Qnil));
+
   f->no_split = 1;
 
   UNGCPRO;
@@ -10548,7 +10739,6 @@ selection dialog's entry field, if MUSTMATCH is non-nil.")
   int count = specpdl_ptr - specpdl;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   char *cdef_file;
-  char *cprompt;
 
   GCPRO5 (prompt, dir, default_filename, mustmatch, file);
   CHECK_STRING (prompt);
@@ -10866,6 +11056,19 @@ meaning don't clear the cache.  */);
 #endif /* USE_MOTIF */
 #endif /* USE_X_TOOLKIT */
 
+#ifdef USE_GTK
+  Fprovide (intern ("gtk"), Qnil);
+
+  DEFVAR_LISP ("gtk-version-string", &Vgtk_version_string,
+               doc: /* Version info for GTK+.  */);
+  {
+    char gtk_version[40];
+    g_snprintf (gtk_version, sizeof (gtk_version), "%u.%u.%u",
+                GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
+    Vgtk_version_string = build_string (gtk_version);
+  }
+#endif /* USE_GTK */
+
   /* X window properties.  */
   defsubr (&Sx_change_window_property);
   defsubr (&Sx_delete_window_property);
@@ -11020,3 +11223,6 @@ init_xfns ()
 }
 
 #endif /* HAVE_X_WINDOWS */
+
+/* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
+   (do not change this comment) */