X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/8972820c930609390ad70db7e20adfbf2a447b7f..b15aa9f9e878c384909910b247da7dc2b3bcc65b:/src/xfns.c diff --git a/src/xfns.c b/src/xfns.c index 4e66e6ef78..cecffb1c22 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -125,6 +125,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 +308,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 +352,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 +404,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 +448,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 +494,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 @@ -550,6 +558,14 @@ x_bitmap_pixmap (f, id) return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; } +int +x_bitmap_mask (f, id) + FRAME_PTR f; + int id; +{ + return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask; +} + /* Allocate a new bitmap record. Returns index of new record. */ @@ -615,6 +631,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; @@ -666,6 +683,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); @@ -693,6 +711,8 @@ x_destroy_bitmap (f, id) { BLOCK_INPUT; XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap); + 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); @@ -714,6 +734,8 @@ x_destroy_all_bitmaps (dpyinfo) if (dpyinfo->bitmaps[i].refcount > 0) { XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap); + if (dpyinfo->bitmaps[i].have_mask) + XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].mask); if (dpyinfo->bitmaps[i].file) xfree (dpyinfo->bitmaps[i].file); } @@ -721,6 +743,105 @@ x_destroy_all_bitmaps (dpyinfo) } + + +/* Useful functions defined in the section + `Image type independent image structures' below. */ + +static unsigned long four_corners_best P_ ((XImage *ximg, unsigned long width, + unsigned long height)); + +static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height, + int depth, XImage **ximg, + Pixmap *pixmap)); + +static void x_destroy_x_image P_ ((XImage *ximg)); + + +/* Create a mask of a bitmap. Note is this not a perfect mask. + It's nicer with some borders in this context */ + +int +x_create_bitmap_mask (f, id) + struct frame *f; + int id; +{ + Pixmap pixmap, mask; + XImage *ximg, *mask_img; + unsigned long width, height; + int result; + unsigned long bg; + unsigned long x, y, xp, xm, yp, ym; + GC gc; + + 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); + + BLOCK_INPUT; + ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height, + ~0, ZPixmap); + + if (!ximg) + { + UNBLOCK_INPUT; + return -1; + } + + result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask); + + UNBLOCK_INPUT; + if (!result) + { + XDestroyImage (ximg); + return -1; + } + + bg = four_corners_best (ximg, width, height); + + for (y = 0; y < ximg->height; ++y) + { + for (x = 0; x < ximg->width; ++x) + { + xp = x != ximg->width - 1 ? x + 1 : 0; + xm = x != 0 ? x - 1 : ximg->width - 1; + yp = y != ximg->height - 1 ? y + 1 : 0; + ym = y != 0 ? y - 1 : ximg->height - 1; + if (XGetPixel (ximg, x, y) == bg + && XGetPixel (ximg, x, yp) == bg + && XGetPixel (ximg, x, ym) == bg + && XGetPixel (ximg, xp, y) == bg + && XGetPixel (ximg, xp, yp) == bg + && XGetPixel (ximg, xp, ym) == bg + && XGetPixel (ximg, xm, y) == bg + && XGetPixel (ximg, xm, yp) == bg + && XGetPixel (ximg, xm, ym) == bg) + XPutPixel (mask_img, x, y, 0); + else + XPutPixel (mask_img, x, y, 1); + } + } + + xassert (interrupt_input_blocked); + gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL); + XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0, + 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); + + return 0; +} + static Lisp_Object unwind_create_frame P_ ((Lisp_Object)); static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object)); static void x_disable_image P_ ((struct frame *, struct image *)); @@ -976,6 +1097,56 @@ x_set_wait_for_wm (f, new_value, old_value) f->output_data.x->wait_for_wm = !NILP (new_value); } +#ifdef USE_GTK + +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) + FRAME_PTR f; + Lisp_Object file; +{ + struct gcpro gcpro1; + int result = 0; + Lisp_Object found; + + GCPRO1 (found); + + 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 */ + /* Functions called only from `x_set_frame_param' to set individual parameters. @@ -1128,7 +1299,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); @@ -1425,7 +1595,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 @@ -1791,11 +1961,11 @@ x_set_name (f, name, explicit) managers which don't support that encoding. So, if NAME contains only ASCII and 8859-1 characters, encode it by iso-latin-1, and use "STRING" in text.encoding hoping that - such window manager at least analize this format correctly, + such window managers at least analyze this format correctly, i.e. treat 8-bit bytes as 8859-1 characters. We may also be able to use "UTF8_STRING" in text.encoding - in the feature which can encode all Unicode characters. + in the future which can encode all Unicode characters. But, for the moment, there's no way to know that the current window manager supports it or not. */ coding_system = Qcompound_text; @@ -2286,8 +2456,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); @@ -2331,7 +2501,7 @@ xic_set_preeditarea (w, x, y) XVaNestedList attr; XPoint spot; - spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x); + spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w); spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f)); attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL); XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL); @@ -2378,7 +2548,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); } @@ -2498,7 +2668,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 @@ -2550,9 +2720,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; @@ -2611,7 +2791,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 */ @@ -2665,7 +2845,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) { @@ -2729,7 +2909,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), @@ -3316,13 +3496,6 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_LINES (f) = 0; change_frame_size (f, height, width, 1, 0, 0); - /* Set up faces after all frame parameters are known. This call - also merges in face attributes specified for new frames. If we - don't do this, the `menu' face for instance won't have the right - colors, and the menu bar won't appear in the specified colors for - new frames. */ - call1 (Qface_set_after_frame_default, frame); - #if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Create the menu bar. */ if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) @@ -3369,6 +3542,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 @@ -4034,9 +4220,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); } @@ -4112,11 +4295,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; @@ -4196,7 +4374,7 @@ valid_image_p (object) { int valid_p = 0; - if (CONSP (object) && EQ (XCAR (object), Qimage)) + if (IMAGEP (object)) { Lisp_Object tem; @@ -4298,7 +4476,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); @@ -6577,7 +6755,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; @@ -7428,7 +7636,11 @@ pbm_load (f, img) #if HAVE_PNG -#include +#if defined HAVE_LIBPNG_PNG_H +# include +#else +# include +#endif /* Function prototypes. */ @@ -8828,7 +9040,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); @@ -9261,24 +9473,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)); @@ -9312,13 +9585,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; @@ -9326,14 +9606,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) @@ -9343,19 +9652,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; } @@ -10407,7 +10726,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); @@ -10725,6 +11043,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); @@ -10879,3 +11210,6 @@ init_xfns () } #endif /* HAVE_X_WINDOWS */ + +/* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288 + (do not change this comment) */