int gray_bitmap_width = gray_width;
int gray_bitmap_height = gray_height;
-unsigned char *gray_bitmap_bits = gray_bits;
+char *gray_bitmap_bits = gray_bits;
/* The name we're using in resource queries. Most often "emacs". */
Lisp_Object Vx_sensitive_text_pointer_shape;
+/* If non-nil, the pointer shape to indicate that windows can be
+ dragged horizontally. */
+
+Lisp_Object Vx_window_horizontal_drag_shape;
+
/* Color of chars displayed in cursor box. */
Lisp_Object Vx_cursor_fore_pixel;
Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
Lisp_Object Qscreen_gamma, Qline_spacing, Qcenter;
Lisp_Object Qcompound_text;
-extern Lisp_Object Qbackground_tile;
/* The below are defined in frame.c. */
Lisp_Object Qface_set_after_frame_default;
+#if GLYPH_DEBUG
+int image_cache_refcount, dpyinfo_refcount;
+#endif
+
+
\f
/* Error if we are not connected to X. */
fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
if (fd < 0)
return -1;
- /* XReadBitmapFile won't handle magic file names. */
- if (fd == 0)
- return -1;
emacs_close (fd);
filename = (char *) XSTRING (found)->data;
void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
};
+static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
+static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
static void x_change_window_heights P_ ((Lisp_Object, int));
static void x_disable_image P_ ((struct frame *, struct image *));
static void x_create_im P_ ((struct frame *));
void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_background_tile P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
"auto-raise", x_set_autoraise,
"auto-lower", x_set_autolower,
"background-color", x_set_background_color,
- "background-tile", x_set_background_tile,
"border-color", x_set_border_color,
"border-width", x_set_border_width,
"cursor-color", x_set_cursor_color,
}
}
-void
-x_set_background_tile (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- int tile_id = lookup_image (f, arg, 0);
- struct image *tile_image = IMAGE_FROM_ID (f, tile_id);
- Pixmap tile_pixmap = tile_image ? tile_image->pixmap : 0;
-
- f->output_data.x->background_tile = tile_pixmap;
-
- if (FRAME_X_WINDOW (f) != 0 && tile_pixmap)
- {
- BLOCK_INPUT;
- /* The main frame area. */
- XSetTile (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
- f->output_data.x->background_tile);
- XSetWindowBackgroundPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->background_tile);
- {
- Lisp_Object bar;
- for (bar = FRAME_SCROLL_BARS (f); !NILP (bar);
- bar = XSCROLL_BAR (bar)->next)
- XSetWindowBackgroundPixmap (FRAME_X_DISPLAY (f),
- SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
- f->output_data.x->background_tile);
- }
- UNBLOCK_INPUT;
-
- update_face_from_frame_parameter (f, Qbackground_tile, arg);
-
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
void
x_set_mouse_color (f, arg, oldval)
struct frame *f;
Lisp_Object arg, oldval;
{
Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
- Cursor busy_cursor;
+ Cursor busy_cursor, horizontal_drag_cursor;
int count;
unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
unsigned long mask_color = f->output_data.x->background_pixel;
else
cross_cursor = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_crosshair);
+ if (!NILP (Vx_window_horizontal_drag_shape))
+ {
+ CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
+ horizontal_drag_cursor
+ = XCreateFontCursor (FRAME_X_DISPLAY (f),
+ XINT (Vx_window_horizontal_drag_shape));
+ }
+ else
+ horizontal_drag_cursor
+ = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
+
/* Check and report errors with the above calls. */
x_check_errors (FRAME_X_DISPLAY (f), "can't set cursor shape: %s");
x_uncatch_errors (FRAME_X_DISPLAY (f), count);
XColor fore_color, back_color;
fore_color.pixel = f->output_data.x->mouse_pixel;
+ x_query_color (f, &fore_color);
back_color.pixel = mask_color;
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- &fore_color);
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- &back_color);
+ x_query_color (f, &back_color);
+
XRecolorCursor (FRAME_X_DISPLAY (f), cursor,
&fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), nontext_cursor,
XRecolorCursor (FRAME_X_DISPLAY (f), mode_cursor,
&fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), cross_cursor,
- &fore_color, &back_color);
+ &fore_color, &back_color);
XRecolorCursor (FRAME_X_DISPLAY (f), busy_cursor,
&fore_color, &back_color);
+ XRecolorCursor (FRAME_X_DISPLAY (f), horizontal_drag_cursor,
+ &fore_color, &back_color);
}
if (FRAME_X_WINDOW (f) != 0)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
- if (cursor != f->output_data.x->text_cursor && f->output_data.x->text_cursor != 0)
+ if (cursor != f->output_data.x->text_cursor
+ && f->output_data.x->text_cursor != 0)
XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->text_cursor);
f->output_data.x->text_cursor = cursor;
XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->cross_cursor);
f->output_data.x->cross_cursor = cross_cursor;
+ if (horizontal_drag_cursor != f->output_data.x->horizontal_drag_cursor
+ && f->output_data.x->horizontal_drag_cursor != 0)
+ XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
+ f->output_data.x->horizontal_drag_cursor = horizontal_drag_cursor;
+
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
{
updating_frame = f;
clear_frame ();
+ clear_current_matrices (f);
updating_frame = NULL;
}
+
+ /* If the tool bar gets smaller, the internal border below it
+ has to be cleared. It was formerly part of the display
+ of the larger tool bar, and updating windows won't clear it. */
+ if (delta < 0)
+ {
+ int height = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = PIXEL_WIDTH (f);
+ int y = nlines * CANON_Y_UNIT (f);
+
+ BLOCK_INPUT;
+ XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height, False);
+ UNBLOCK_INPUT;
+ }
}
coding.mode |= CODING_MODE_LAST_BLOCK;
if (coding.type == coding_type_iso2022)
coding.flags |= CODING_FLAG_ISO_SAFE;
+ /* We suppress producing escape sequences for composition. */
+ coding.composing = COMPOSITION_DISABLED;
bufsize = encoding_buffer_size (&coding, bytes);
buf = (unsigned char *) xmalloc (bufsize);
encode_coding (&coding, str, buf, bytes, bufsize);
gc_values.foreground = f->output_data.x->foreground_pixel;
gc_values.background = f->output_data.x->background_pixel;
gc_values.line_width = 0; /* Means 1 using fast algorithm. */
- f->output_data.x->normal_gc = XCreateGC (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- GCLineWidth | GCFont
- | GCForeground | GCBackground,
- &gc_values);
+ f->output_data.x->normal_gc
+ = XCreateGC (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ GCLineWidth | GCFont | GCForeground | GCBackground,
+ &gc_values);
/* Reverse video style. */
gc_values.foreground = f->output_data.x->background_pixel;
gc_values.background = f->output_data.x->foreground_pixel;
- f->output_data.x->reverse_gc = XCreateGC (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
- GCFont | GCForeground | GCBackground
- | GCLineWidth,
- &gc_values);
+ f->output_data.x->reverse_gc
+ = XCreateGC (FRAME_X_DISPLAY (f),
+ FRAME_X_WINDOW (f),
+ GCFont | GCForeground | GCBackground | GCLineWidth,
+ &gc_values);
/* Cursor has cursor-color background, background-color foreground. */
gc_values.foreground = f->output_data.x->background_pixel;
UNBLOCK_INPUT;
}
+
+/* Free what was was allocated in x_make_gc. */
+
+void
+x_free_gcs (f)
+ struct frame *f;
+{
+ Display *dpy = FRAME_X_DISPLAY (f);
+
+ BLOCK_INPUT;
+
+ if (f->output_data.x->normal_gc)
+ {
+ XFreeGC (dpy, f->output_data.x->normal_gc);
+ f->output_data.x->normal_gc = 0;
+ }
+
+ if (f->output_data.x->reverse_gc)
+ {
+ XFreeGC (dpy, f->output_data.x->reverse_gc);
+ f->output_data.x->reverse_gc = 0;
+ }
+
+ if (f->output_data.x->cursor_gc)
+ {
+ XFreeGC (dpy, f->output_data.x->cursor_gc);
+ f->output_data.x->cursor_gc = 0;
+ }
+
+ if (f->output_data.x->border_tile)
+ {
+ XFreePixmap (dpy, f->output_data.x->border_tile);
+ f->output_data.x->border_tile = 0;
+ }
+
+ UNBLOCK_INPUT;
+}
+
+
+/* Handler for signals raised during x_create_frame and
+ x_create_top_frame. FRAME is the frame which is partially
+ constructed. */
+
+static Lisp_Object
+unwind_create_frame (frame)
+ Lisp_Object frame;
+{
+ struct frame *f = XFRAME (frame);
+
+ /* If frame is ``official'', nothing to do. */
+ if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
+ {
+#if GLYPH_DEBUG
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+#endif
+
+ x_free_frame_resources (f);
+
+ /* Check that reference counts are indeed correct. */
+ xassert (dpyinfo->reference_count == dpyinfo_refcount);
+ xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
+ return Qt;
+ }
+
+ return Qnil;
+}
+
+
DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1, 1, 0,
"Make a new X window, which is called a \"frame\" in Emacs terms.\n\
int minibuffer_only = 0;
long window_prompting = 0;
int width, height;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object display;
struct x_display_info *dpyinfo = NULL;
f->output_data.x->fontset = -1;
f->output_data.x->scroll_bar_foreground_pixel = -1;
f->output_data.x->scroll_bar_background_pixel = -1;
+ record_unwind_protect (unwind_create_frame, frame);
f->icon_name
= x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
f->icon_name = Qnil;
FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+ image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+ dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
#ifdef MULTI_KBOARD
FRAME_KBOARD (f) = kb;
#endif
SET_FRAME_WIDTH (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);
+
#ifdef USE_X_TOOLKIT
/* Create the menu bar. */
if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
return unbind_to (count, frame);
}
+
/* FRAME is used only to get a handle on the X display. We don't pass the
display info directly because we're called from frame.c, which doesn't
know about that structure. */
validate_x_resource_name ();
- dpyinfo = x_term_init (name, (unsigned char *)0,
+ dpyinfo = x_term_init (name, (char *)0,
(char *) XSTRING (Vx_resource_name)->data);
if (dpyinfo == 0)
if (valid_image_p (spec))
{
struct frame *f = check_x_frame (frame);
- int id = lookup_image (f, spec, 0);
+ int id = lookup_image (f, spec);
struct image *img = IMAGE_FROM_ID (f, id);
int width = img->width + 2 * img->margin;
int height = img->height + 2 * img->margin;
if (valid_image_p (spec))
{
struct frame *f = check_x_frame (frame);
- int id = lookup_image (f, spec, 0);
+ int id = lookup_image (f, spec);
struct image *img = IMAGE_FROM_ID (f, id);
if (img->mask)
mask = Qt;
{
struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
- if (c && (c->refcount <= 1) && INTEGERP (Vimage_cache_eviction_delay))
+ if (c && INTEGERP (Vimage_cache_eviction_delay))
{
EMACS_TIME t;
unsigned long old;
struct frame *f = XFRAME (frame);
if (FRAME_X_P (f)
&& FRAME_X_IMAGE_CACHE (f) == c)
- {
- clear_current_matrices (f);
- free_all_realized_faces (frame);
- }
+ clear_current_matrices (f);
}
++windows_or_buffers_changed;
/* Return the id of image with Lisp specification SPEC on frame F.
- SPEC must be a valid Lisp image specification (see valid_image_p).
- If DELAY_LOAD is true, then the image isn't actually loaded yet (it
- will be loaded when prepare_image_for_display is called). */
+ SPEC must be a valid Lisp image specification (see valid_image_p). */
int
-lookup_image (f, spec, delay_load)
+lookup_image (f, spec)
struct frame *f;
Lisp_Object spec;
- int delay_load;
{
struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
struct image *img;
BLOCK_INPUT;
img = make_image (spec, hash);
cache_image (f, img);
- if (! delay_load)
- img->load_failed_p = img->type->load (f, img) == 0;
- xassert (!interrupt_input_blocked);
+ img->load_failed_p = img->type->load (f, img) == 0;
/* If we can't load the image, and we don't have a width and
height, use some arbitrary width and height so that we can
draw a rectangle for it. */
- if (img->pixmap == 0)
+ if (img->load_failed_p)
{
Lisp_Object value;
/* Handle image type independent image attributes
`:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */
Lisp_Object ascent, margin, relief;
- Lisp_Object file;
ascent = image_spec_value (spec, QCascent, NULL);
if (INTEGERP (ascent))
/* Try to find FILE in data-directory, then x-bitmap-file-path. */
fd = openp (search_path, file, "", &file_found, 0);
- if (fd < 0)
+ if (fd == -1)
file_found = Qnil;
else
close (fd);
{
struct image_keyword fmt[XBM_LAST];
Lisp_Object data;
- unsigned char *bitmap_data;
int depth;
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
unsigned long background = FRAME_BACKGROUND_PIXEL (f);
char *bits;
- int parsed_p, height, width;
+ int parsed_p;
int in_memory_file_p = 0;
/* See if data looks like an in-memory XBM file. */
char *color_name;
XColor *color;
{
- char *s;
struct xpm_cached_color *p;
- unsigned h = xpm_color_bucket (color_name);
-
- for (s = color_name; *s; ++s)
- h = (h << 2) ^ *s;
- h %= XPM_COLOR_CACHE_BUCKETS;
+ int h = xpm_color_bucket (color_name);
for (p = xpm_color_cache[h]; p; p = p->next)
if (strcmp (p->name, color_name) == 0)
struct frame *f;
struct image *img;
{
- int rc, i;
+ int rc;
XpmAttributes attrs;
Lisp_Object specified_file, color_symbols;
cmap = FRAME_X_COLORMAP (f);
color.pixel = pixel;
- XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
+ x_query_color (f, &color);
rc = x_alloc_nearest_color (f, cmap, &color);
if (rc)
p->pixel = XGetPixel (ximg, x, y);
if (rgb_p)
- XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
- row, img->width);
+ x_query_colors (f, row, img->width);
}
XDestroyImage (ximg);
PBM_ALGORITHM,
PBM_HEURISTIC_MASK,
PBM_MASK,
+ PBM_FOREGROUND,
+ PBM_BACKGROUND,
PBM_LAST
};
{":relief", IMAGE_INTEGER_VALUE, 0},
{":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":foreground", IMAGE_STRING_VALUE, 0},
+ {":background", IMAGE_STRING_VALUE, 0}
};
/* Structure describing the image type `pbm'. */
if (type == PBM_MONO)
{
int c = 0, g;
+ struct image_keyword fmt[PBM_LAST];
+ unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
+ unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
+
+ /* Parse the image specification. */
+ bcopy (pbm_format, fmt, sizeof fmt);
+ parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
+
+ /* Get foreground and background colors, maybe allocate colors. */
+ if (fmt[PBM_FOREGROUND].count)
+ fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
+ if (fmt[PBM_BACKGROUND].count)
+ bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
else
g = pbm_scan_number (&p, end);
- XPutPixel (ximg, x, y, (g
- ? FRAME_FOREGROUND_PIXEL (f)
- : FRAME_BACKGROUND_PIXEL (f)));
+ XPutPixel (ximg, x, y, g ? fg : bg);
}
}
else
cmap = FRAME_X_COLORMAP (f);
color.pixel = FRAME_BACKGROUND_PIXEL (f);
- XQueryColor (FRAME_X_DISPLAY (f), cmap, &color);
+ x_query_color (f, &color);
bzero (&frame_background, sizeof frame_background);
frame_background.red = color.red;
{
static int interlace_start[] = {0, 4, 2, 1};
static int interlace_increment[] = {8, 8, 4, 2};
- int pass, inc;
+ int pass;
int row = interlace_start[0];
pass = 0;
BLOCK_INPUT;
FOR_EACH_FRAME (rest, frame)
- if (FRAME_X_P (XFRAME (frame)))
- {
- struct frame *f = XFRAME (frame);
-
- f->output_data.x->busy_p = 1;
+ {
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_LIVE_P (f) && FRAME_X_P (f) && FRAME_X_DISPLAY (f))
+ {
+ Display *dpy = FRAME_X_DISPLAY (f);
+
+#ifdef USE_X_TOOLKIT
+ if (f->output_data.x->widget)
+#else
+ if (FRAME_OUTER_WINDOW (f))
+#endif
+ {
+ f->output_data.x->busy_p = 1;
- if (!f->output_data.x->busy_window)
- {
- unsigned long mask = CWCursor;
- XSetWindowAttributes attrs;
+ if (!f->output_data.x->busy_window)
+ {
+ unsigned long mask = CWCursor;
+ XSetWindowAttributes attrs;
- attrs.cursor = f->output_data.x->busy_cursor;
+ attrs.cursor = f->output_data.x->busy_cursor;
- f->output_data.x->busy_window
- = XCreateWindow (FRAME_X_DISPLAY (f),
- FRAME_OUTER_WINDOW (f),
- 0, 0, 32000, 32000, 0, 0,
- InputOnly,
- CopyFromParent,
- mask, &attrs);
- }
+ f->output_data.x->busy_window
+ = XCreateWindow (dpy, FRAME_OUTER_WINDOW (f),
+ 0, 0, 32000, 32000, 0, 0,
+ InputOnly,
+ CopyFromParent,
+ mask, &attrs);
+ }
- XMapRaised (FRAME_X_DISPLAY (f), f->output_data.x->busy_window);
- XFlush (FRAME_X_DISPLAY (f));
- }
+ XMapRaised (dpy, f->output_data.x->busy_window);
+ XFlush (dpy);
+ }
+ }
+ }
busy_cursor_shown_p = 1;
UNBLOCK_INPUT;
static Lisp_Object x_create_tip_frame P_ ((struct x_display_info *,
Lisp_Object));
-/* The frame of a currently visible tooltip, or null. */
+/* The frame of a currently visible tooltip. */
-struct frame *tip_frame;
+Lisp_Object tip_frame;
/* If non-nil, a timer started that hides the last tooltip when it
fires. */
Lisp_Object tip_timer;
Window tip_window;
+
+static Lisp_Object
+unwind_create_tip_frame (frame)
+ Lisp_Object frame;
+{
+ Lisp_Object deleted;
+
+ deleted = unwind_create_frame (frame);
+ if (EQ (deleted, Qt))
+ {
+ tip_window = None;
+ tip_frame = Qnil;
+ }
+
+ return deleted;
+}
+
+
/* Create a frame for a tooltip on the display described by DPYINFO.
- PARMS is a list of frame parameters. Value is the frame. */
+ PARMS is a list of frame parameters. Value is the frame.
+
+ Note that functions called here, esp. x_default_parameter can
+ signal errors, for instance when a specified color name is
+ undefined. We have to make sure that we're in a consistent state
+ when this happens. */
static Lisp_Object
x_create_tip_frame (dpyinfo, parms)
Lisp_Object name;
long window_prompting = 0;
int width, height;
- int count = specpdl_ptr - specpdl;
+ int count = BINDING_STACK_SIZE ();
struct gcpro gcpro1, gcpro2, gcpro3;
struct kboard *kb;
frame = Qnil;
GCPRO3 (parms, name, frame);
- tip_frame = f = make_frame (1);
+ f = make_frame (1);
XSETFRAME (frame, f);
FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+ record_unwind_protect (unwind_create_tip_frame, frame);
+ /* 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
+ counts etc. */
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));
f->output_data.x->scroll_bar_background_pixel = -1;
f->icon_name = Qnil;
FRAME_X_DISPLAY_INFO (f) = dpyinfo;
+#if GLYPH_DEBUG
+ image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+ dpyinfo_refcount = dpyinfo->reference_count;
+#endif /* GLYPH_DEBUG */
#ifdef MULTI_KBOARD
FRAME_KBOARD (f) = kb;
#endif
specbind (Qx_resource_name, name);
}
- /* Extract the window parameters from the supplied values
- that are needed to determine window geometry. */
+ /* Extract the window parameters from the supplied values that are
+ needed to determine window geometry. */
{
Lisp_Object font;
unsigned long mask;
BLOCK_INPUT;
- mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
+ mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
+ if (DoesSaveUnders (dpyinfo->screen))
+ mask |= CWSaveUnder;
+
/* Window managers look at the override-redirect flag to determine
whether or net to give windows a decoration (Xlib spec, chapter
3.2.8). */
SET_FRAME_WIDTH (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);
+
f->no_split = 1;
UNGCPRO;
below. And the frame needs to be on Vframe_list or making it
visible won't work. */
Vframe_list = Fcons (frame, Vframe_list);
+ tip_frame = frame;
/* Now that the frame is official, it counts as a reference to
its display. */
FRAME_X_DISPLAY_INFO (f)->reference_count++;
+ /* Discard the unwind_protect. */
return unbind_to (count, frame);
}
DX isn't specified). Likewise for the y-position; if a `top' frame\n\
parameter is specified, it determines the y-position of the tooltip\n\
window, otherwise it is displayed at the mouse position, with offset\n\
-DY added (default is -5).")
+DY added (default is -10).")
(string, frame, parms, timeout, dx, dy)
Lisp_Object string, frame, parms, timeout, dx, dy;
{
CHECK_NUMBER (dx, 5);
if (NILP (dy))
- dy = make_number (-5);
+ dy = make_number (-10);
else
CHECK_NUMBER (dy, 6);
/* Create a frame for the tooltip, and record it in the global
variable tip_frame. */
frame = x_create_tip_frame (FRAME_X_DISPLAY_INFO (f), parms);
- tip_frame = f = XFRAME (frame);
+ f = XFRAME (frame);
/* Set up the frame's root window. Currently we use a size of 80
columns x 40 lines. If someone wants to show a larger tip, he
Value is t is tooltip was open, nil otherwise.")
()
{
- int count = specpdl_ptr - specpdl;
- int deleted_p = 0;
+ int count;
+ Lisp_Object deleted, frame, timer;
+ struct gcpro gcpro1, gcpro2;
+
+ /* Return quickly if nothing to do. */
+ if (NILP (tip_timer) && NILP (tip_frame))
+ return Qnil;
+ frame = tip_frame;
+ timer = tip_timer;
+ GCPRO2 (frame, timer);
+ tip_frame = tip_timer = deleted = Qnil;
+
+ count = BINDING_STACK_SIZE ();
specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
- if (!NILP (tip_timer))
- {
- call1 (intern ("cancel-timer"), tip_timer);
- tip_timer = Qnil;
- }
+ if (!NILP (timer))
+ call1 (intern ("cancel-timer"), timer);
- if (tip_frame)
+ if (FRAMEP (frame))
{
- Lisp_Object frame;
-
- XSETFRAME (frame, tip_frame);
- Fdelete_frame (frame, Qt);
- tip_frame = NULL;
- deleted_p = 1;
+ Fdelete_frame (frame, Qnil);
+ deleted = Qt;
+
+#ifdef USE_LUCID
+ /* Bloodcurdling hack alert: The Lucid menu bar widget's
+ redisplay procedure is not called when a tip frame over menu
+ items is unmapped. Redisplay the menu manually... */
+ {
+ struct frame *f = SELECTED_FRAME ();
+ Widget w = f->output_data.x->menubar_widget;
+ extern void xlwmenu_redisplay P_ ((Widget));
+
+ if (!DoesSaveUnders (FRAME_X_DISPLAY_INFO (f)->screen)
+ && w != None)
+ {
+ BLOCK_INPUT;
+ xlwmenu_redisplay (w);
+ UNBLOCK_INPUT;
+ }
+ }
+#endif /* USE_LUCID */
}
- return unbind_to (count, deleted_p ? Qt : Qnil);
+ UNGCPRO;
+ return unbind_to (count, deleted);
}
\f
+/***********************************************************************
+ Keyboard
+ ***********************************************************************/
+
+#ifdef HAVE_XKBGETKEYBOARD
+#include <X11/XKBlib.h>
+#include <X11/keysym.h>
+#endif
+
+DEFUN ("x-backspace-delete-keys-p", Fx_backspace_delete_keys_p,
+ Sx_backspace_delete_keys_p, 0, 1, 0,
+ "Check if both Backspace and Delete keys are on the keyboard of FRAME.\n\
+FRAME nil means use the selected frame.\n\
+Value is t if we know that both keys are present, and are mapped to the\n\
+usual X keysyms.")
+ (frame)
+ Lisp_Object frame;
+{
+#ifdef HAVE_XKBGETKEYBOARD
+ XkbDescPtr kb;
+ struct frame *f = check_x_frame (frame);
+ Display *dpy = FRAME_X_DISPLAY (f);
+ Lisp_Object have_keys;
+ int major, minor, op, event, error;
+
+ BLOCK_INPUT;
+
+ /* Check library version in case we're dynamically linked. */
+ major = XkbMajorVersion;
+ minor = XkbMinorVersion;
+ if (!XkbLibraryVersion (&major, &minor))
+ return Qnil;
+
+ /* Check that the server supports XKB. */
+ major = XkbMajorVersion;
+ minor = XkbMinorVersion;
+ if (!XkbQueryExtension (dpy, &op, &event, &error, &major, &minor))
+ return Qnil;
+
+ have_keys = Qnil;
+ kb = XkbGetKeyboard (dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+ if (kb)
+ {
+ int delete_keycode = 0, backspace_keycode = 0, i;
+
+ for (i = kb->min_key_code;
+ (i < kb->max_key_code
+ && (delete_keycode == 0 || backspace_keycode == 0));
+ ++i)
+ {
+ /* The XKB symbolic key names can be seen most easily
+ in the PS file generated by `xkbprint -label name $DISPLAY'. */
+ if (bcmp ("DELE", kb->names->keys[i].name, 4) == 0)
+ delete_keycode = i;
+ else if (bcmp ("BKSP", kb->names->keys[i].name, 4) == 0)
+ backspace_keycode = i;
+ }
+
+ XkbFreeKeyboard (kb, 0, True);
+
+ if (delete_keycode
+ && backspace_keycode
+ && XKeysymToKeycode (dpy, XK_Delete) == delete_keycode
+ && XKeysymToKeycode (dpy, XK_BackSpace) == backspace_keycode)
+ have_keys = Qt;
+ }
+ UNBLOCK_INPUT;
+ return have_keys;
+#else /* not HAVE_XKBGETKEYBOARD */
+ return Qnil;
+#endif /* not HAVE_XKBGETKEYBOARD */
+}
+
+
+\f
/***********************************************************************
Initialization
***********************************************************************/
or when you set the mouse color.");
Vx_sensitive_text_pointer_shape = Qnil;
+ DEFVAR_LISP ("x-window-horizontal-drag-cursor",
+ &Vx_window_horizontal_drag_shape,
+ "Pointer shape to use for indicating a window can be dragged horizontally.\n\
+This variable takes effect when you create a new frame\n\
+or when you set the mouse color.");
+ Vx_window_horizontal_drag_shape = Qnil;
+
DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
"A string indicating the foreground color of the cursor box.");
Vx_cursor_fore_pixel = Qnil;
defsubr (&Sx_display_list);
defsubr (&Sx_synchronize);
defsubr (&Sx_focus_frame);
-
+ defsubr (&Sx_backspace_delete_keys_p);
+
/* Setting callback functions for fontset handler. */
get_font_info_func = x_get_font_info;
defsubr (&Sx_show_tip);
defsubr (&Sx_hide_tip);
- staticpro (&tip_timer);
tip_timer = Qnil;
+ staticpro (&tip_timer);
+ tip_frame = Qnil;
+ staticpro (&tip_frame);
#ifdef USE_MOTIF
defsubr (&Sx_file_dialog);