#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
#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;
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
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
#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;
{
/* 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
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;
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);
{
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);
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);
}
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;
{
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,
UNBLOCK_INPUT;
if (!result)
{
- XDestroyImage(ximg);
+ XDestroyImage (ximg);
return -1;
}
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;
}
#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 */
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;
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);
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);
XFree (needed);
attr = XVaCreateNestedList (0, XNArea, &area, NULL);
- XSetICValues(xic, XNStatusAttributes, attr, NULL);
+ XSetICValues (xic, XNStatusAttributes, attr, NULL);
XFree (attr);
}
{
int len;
char *tem, shell_position[32];
- Arg al[2];
+ Arg al[10];
int ac = 0;
int extra_borders = 0;
int menubar_size
(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;
{
/* 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 */
{
/* 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)
{
{
/* 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),
;
}
+ /* 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
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);
}
}
\f
+/***********************************************************************
+ General X functions exposed to Elisp.
+ ***********************************************************************/
+
+DEFUN ("x-send-client-message", Fx_send_client_event,
+ Sx_send_client_message, 6, 6, 0,
+ doc: /* Send a client message of MESSAGE-TYPE to window DEST on DISPLAY.
+
+For DISPLAY, specify either a frame or a display name (a string).
+If DISPLAY is nil, that stands for the selected frame's display.
+DEST may be an integer, in which case it is a Window id. The value 0 may
+be used to send to the root window of the DISPLAY.
+If DEST is a frame the event is sent to the outer window of that frame.
+Nil means the currently selected frame.
+If DEST is the string "PointerWindow" the event is sent to the window that
+contains the pointer. If DEST is the string "InputFocus" the event is
+sent to the window that has the input focus.
+FROM is the frame sending the event. Use nil for currently selected frame.
+MESSAGE-TYPE is the name of an Atom as a string.
+FORMAT must be one of 8, 16 or 32 and determines the size of the values in
+bits. VALUES is a list of integer and/or strings containing the values to
+send. If a value is a string, it is converted to an Atom and the value of
+the Atom is sent. If more values than fits into the event is given,
+the excessive values are ignored. */)
+ (display, dest, from, message_type, format, values)
+ Lisp_Object display, dest, from, message_type, format, values;
+{
+ struct x_display_info *dpyinfo = check_x_display_info (display);
+ Window wdest;
+ XEvent event;
+ Lisp_Object cons;
+ int i;
+ int max_nr_values = (int) sizeof (event.xclient.data.b);
+ struct frame *f = check_x_frame (from);
+
+ CHECK_STRING (message_type);
+ CHECK_NUMBER (format);
+ CHECK_CONS (values);
+
+ for (cons = values; CONSP (cons); cons = XCDR (cons))
+ {
+ Lisp_Object o = XCAR (cons);
+
+ if (! INTEGERP (o) && ! STRINGP (o))
+ error ("Bad data in VALUES, must be integer or string");
+ }
+
+ event.xclient.type = ClientMessage;
+ event.xclient.format = XFASTINT (format);
+
+ if (event.xclient.format != 8 && event.xclient.format != 16
+ && event.xclient.format != 32)
+ error ("FORMAT must be one of 8, 16 or 32");
+ if (event.xclient.format == 16) max_nr_values /= 2;
+ if (event.xclient.format == 32) max_nr_values /= 4;
+
+ if (FRAMEP (dest) || NILP (dest))
+ {
+ struct frame *fdest = check_x_frame (dest);
+ wdest = FRAME_OUTER_WINDOW (fdest);
+ }
+ else if (STRINGP (dest))
+ {
+ if (strcmp (SDATA (dest), "PointerWindow") == 0)
+ wdest = PointerWindow;
+ else if (strcmp (SDATA (dest), "InputFocus") == 0)
+ wdest = InputFocus;
+ else
+ error ("DEST as a string must be one of PointerWindow or InputFocus");
+ }
+ else
+ {
+ CHECK_NUMBER (dest);
+ wdest = (Window) XFASTINT (dest);
+ if (wdest == 0) wdest = dpyinfo->root_window;
+ }
+
+ BLOCK_INPUT;
+ for (cons = values, i = 0;
+ CONSP (cons) && i < max_nr_values;
+ cons = XCDR (cons), ++i)
+ {
+ Lisp_Object o = XCAR (cons);
+ long val;
+
+ if (INTEGERP (o))
+ val = XINT (o);
+ else if (STRINGP (o))
+ val = XInternAtom (dpyinfo->display, SDATA (o), False);
+
+ if (event.xclient.format == 8)
+ event.xclient.data.b[i] = (char) val;
+ else if (event.xclient.format == 16)
+ event.xclient.data.s[i] = (short) val;
+ else
+ event.xclient.data.l[i] = val;
+ }
+
+ for ( ; i < max_nr_values; ++i)
+ if (event.xclient.format == 8)
+ event.xclient.data.b[i] = 0;
+ else if (event.xclient.format == 16)
+ event.xclient.data.s[i] = 0;
+ else
+ event.xclient.data.l[i] = 0;
+
+ event.xclient.message_type
+ = XInternAtom (dpyinfo->display, SDATA (message_type), False);
+ event.xclient.display = dpyinfo->display;
+ event.xclient.window = FRAME_OUTER_WINDOW (f);
+
+ XSendEvent (dpyinfo->display, wdest, False, 0xffff, &event);
+
+ XFlush (dpyinfo->display);
+ UNBLOCK_INPUT;
+
+ return Qnil;
+}
+\f
/***********************************************************************
Image types
***********************************************************************/
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;
#if HAVE_PNG
-#include <libpng/png.h>
+#if defined HAVE_LIBPNG_PNG_H
+# include <libpng/png.h>
+#else
+# include <png.h>
+#endif
/* Function prototypes. */
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);
#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);
defsubr (&Sx_close_connection);
defsubr (&Sx_display_list);
defsubr (&Sx_synchronize);
+ defsubr (&Sx_send_client_message);
defsubr (&Sx_focus_frame);
defsubr (&Sx_backspace_delete_keys_p);
}
#endif /* HAVE_X_WINDOWS */
+
+/* arch-tag: 55040d02-5485-4d58-8b22-95a7a05f3288
+ (do not change this comment) */