/* 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 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <sys/ioctl.h>
#endif /* ! defined (BSD_SYSTEM) */
-#include "systty.h"
#include "systime.h"
#ifndef INCLUDED_FCNTL
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
-#include "gnu.h"
+#include "emacs-icon.h"
#include "disptab.h"
#include "buffer.h"
#include "window.h"
#endif
#endif
-#define abs(x) ((x) < 0 ? -(x) : (x))
-
/* Default to using XIM if available. */
#ifdef USE_XIM
int use_xim = 1;
static Lisp_Object Qvendor_specific_keysyms;
static Lisp_Object Qlatin_1;
+/* Used in x_flush. */
+
+extern Lisp_Object Vinhibit_redisplay;
+
extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
extern int x_bitmap_mask P_ ((FRAME_PTR, int));
static void x_update_window_end P_ ((struct window *, int, int));
static int x_io_error_quitter P_ ((Display *));
+static struct terminal *x_create_terminal P_ ((struct x_display_info *));
+void x_delete_terminal P_ ((struct terminal *));
static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
static int x_compute_min_glyph_bounds P_ ((struct frame *));
static void x_update_end P_ ((struct frame *));
static void XTframe_up_to_date P_ ((struct frame *));
-static void XTset_terminal_modes P_ ((void));
-static void XTreset_terminal_modes P_ ((void));
-static void x_clear_frame P_ ((void));
+static void XTset_terminal_modes P_ ((struct terminal *));
+static void XTreset_terminal_modes P_ ((struct terminal *));
+static void x_clear_frame P_ ((struct frame *));
static void frame_highlight P_ ((struct frame *));
static void frame_unhighlight P_ ((struct frame *));
static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
x_flush (f)
struct frame *f;
{
+ /* Don't call XFlush when it is not safe to redisplay; the X
+ connection may be broken. */
+ if (!NILP (Vinhibit_redisplay))
+ return;
+
BLOCK_INPUT;
if (f == NULL)
{
Lisp_Object rest, frame;
FOR_EACH_FRAME (rest, frame)
- x_flush (XFRAME (frame));
+ if (FRAME_X_P (XFRAME (frame)))
+ x_flush (XFRAME (frame));
}
else if (FRAME_X_P (f))
XFlush (FRAME_X_DISPLAY (f));
rarely happens). */
static void
-XTset_terminal_modes ()
+XTset_terminal_modes (struct terminal *terminal)
{
}
the X-windows go away, and suspending requires no action. */
static void
-XTreset_terminal_modes ()
+XTreset_terminal_modes (struct terminal *terminal)
{
}
}
IF_DEBUG (x_check_font (s->f, s->font));
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ xgcv.font = FRAME_X_DISPLAY_INFO (s->f)->font->fid;
+ else
+#endif
xgcv.font = s->font->fid;
xgcv.graphics_exposures = False;
mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
xgcv.background = s->face->background;
xgcv.foreground = s->face->foreground;
IF_DEBUG (x_check_font (s->f, s->font));
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ xgcv.font = FRAME_X_DISPLAY_INFO (s->f)->font->fid;
+ else
+#endif
xgcv.font = s->font->fid;
xgcv.graphics_exposures = False;
mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
of S to the right of that box line. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
- x = s->x + abs (s->face->box_line_width);
+ x = s->x + eabs (s->face->box_line_width);
else
x = s->x;
of S to the right of that box line. */
if (s->face && s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
- x = s->x + abs (s->face->box_line_width);
+ x = s->x + eabs (s->face->box_line_width);
else
x = s->x;
if (! VECTORP (adjustment))
{
- width += XINT (LGLYPH_WIDTH (g));
+ width += LGLYPH_WIDTH (g);
continue;
}
if (from < i)
wadjust = XINT (AREF (adjustment, 2));
font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
- x += XINT (LGLYPH_WIDTH (g)) + wadjust;
+ x += wadjust;
from = i + 1;
width = 0;
}
for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
if (FRAMEP (XCAR (tail))
&& (f = XFRAME (XCAR (tail)),
- (f->output_data.nothing != 1
+ (FRAME_X_P (f)
+ && f->output_data.nothing != 1
&& FRAME_X_DISPLAY_INFO (f) == dpyinfo))
&& f->output_data.x->widget == widget)
return f;
? s->first_glyph
: s->first_glyph + s->nchars - 1);
- width = abs (s->face->box_line_width);
+ width = eabs (s->face->box_line_width);
raised_p = s->face->box == FACE_RAISED_BOX;
left_x = s->x;
right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
- x += abs (s->face->box_line_width);
+ x += eabs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
- x += abs (s->face->box_line_width);
+ x += eabs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
}
else
{
- thick = abs (s->img->relief);
+ thick = eabs (s->img->relief);
raised_p = s->img->relief > 0;
}
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
- x += abs (s->face->box_line_width);
+ x += eabs (s->face->box_line_width);
/* If there is a margin around the image, adjust x- and y-position
by that margin. */
x_draw_image_glyph_string (s)
struct glyph_string *s;
{
- int box_line_hwidth = abs (s->face->box_line_width);
+ int box_line_hwidth = eabs (s->face->box_line_width);
int box_line_vwidth = max (s->face->box_line_width, 0);
int height;
Pixmap pixmap = None;
struct glyph_string *s;
{
xassert (s->first_glyph->type == STRETCH_GLYPH);
- s->stippled_p = s->face->stipple != 0;
if (s->hl == DRAW_CURSOR
&& !x_stretch_cursor_p)
for X frames. */
static void
-x_delete_glyphs (n)
+x_delete_glyphs (f, n)
+ struct frame *f;
register int n;
{
abort ();
}
-/* Clear entire frame. If updating_frame is non-null, clear that
- frame. Otherwise clear the selected frame. */
+/* Clear an entire frame. */
static void
-x_clear_frame ()
+x_clear_frame (struct frame *f)
{
- struct frame *f;
-
- if (updating_frame)
- f = updating_frame;
- else
- f = SELECTED_FRAME ();
-
/* Clearing the frame will erase any cursor, so mark them all as no
longer visible. */
mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
XGCValues values;
values.function = GXxor;
- values.foreground = (f->output_data.x->foreground_pixel
- ^ f->output_data.x->background_pixel);
+ values.foreground = (FRAME_FOREGROUND_PIXEL (f)
+ ^ FRAME_BACKGROUND_PIXEL (f));
gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
GCFunction | GCForeground, &values);
lines or deleting -N lines at vertical position VPOS. */
static void
-x_ins_del_lines (vpos, n)
+x_ins_del_lines (f, vpos, n)
+ struct frame *f;
int vpos, n;
{
abort ();
FOCUS_IMPLICIT : FOCUS_EXPLICIT),
dpyinfo, frame, bufp);
break;
+
+ case ClientMessage:
+ if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
+ {
+ enum xembed_message msg = event->xclient.data.l[1];
+ x_focus_changed ((msg == XEMBED_FOCUS_IN ? FocusIn : FocusOut),
+ FOCUS_EXPLICIT, dpyinfo, frame, bufp);
+ }
+ break;
}
}
dpyinfo->super_mod_mask = 0;
dpyinfo->hyper_mod_mask = 0;
-#ifdef HAVE_X11R4
XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-#else
- min_code = dpyinfo->display->min_keycode;
- max_code = dpyinfo->display->max_keycode;
-#endif
syms = XGetKeyboardMapping (dpyinfo->display,
min_code, max_code - min_code + 1,
/* Clear the mouse-moved flag for every frame on this display. */
FOR_EACH_FRAME (tail, frame)
- if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
+ if (FRAME_X_P (XFRAME (frame))
+ && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
XFRAME (frame)->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
if (! FRAMEP (frame))
abort ();
+ if (! FRAME_X_P (XFRAME (frame)))
+ continue;
+
/* Scan this frame's scroll bar list for a scroll bar with the
right window ID. */
condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
condemned = Qnil,
! NILP (bar));
bar = XSCROLL_BAR (bar)->next)
- if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id &&
+ if (XSCROLL_BAR (bar)->x_window == window_id &&
FRAME_X_DISPLAY (XFRAME (frame)) == display)
return XSCROLL_BAR (bar);
}
for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
{
- Lisp_Object frame = XCAR (tail);
- Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+ if (FRAME_X_P (XFRAME (XCAR (tail))))
+ {
+ Lisp_Object frame = XCAR (tail);
+ Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
- if (menu_bar && xlwmenu_window_p (menu_bar, window))
- return menu_bar;
+ if (menu_bar && xlwmenu_window_p (menu_bar, window))
+ return menu_bar;
+ }
}
return NULL;
}
}
+#elif defined USE_GTK
-#else /* !USE_MOTIF, i.e. Xaw or GTK */
-#ifdef USE_GTK
/* Scroll bar callback for GTK scroll bars. WIDGET is the scroll
bar widget. DATA is a pointer to the scroll_bar structure. */
}
}
-#else /* not USE_GTK */
+#else /* not USE_GTK and not USE_MOTIF */
/* Xaw scroll bar callback. Invoked when the thumb is dragged.
WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
whole = 10000000;
portion = shown < 1 ? top * whole : 0;
- if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
+ if (shown < 1 && (eabs (top + shown - 1) < 1.0/height))
/* Some derivatives of Xaw refuse to shrink the thumb when you reach
the bottom, so we force the scrolling whenever we see that we're
too close to the bottom (in x_set_toolkit_scroll_bar_thumb
XtVaGetValues (widget, XtNheight, &height, NULL);
UNBLOCK_INPUT;
- if (abs (position) >= height)
+ if (eabs (position) >= height)
part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
/* If Xaw3d was compiled with ARROW_SCROLLBAR,
it maps line-movement to call_data = max(5, height/20). */
- else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
+ else if (xaw3d_arrow_scroll && eabs (position) <= max (5, height / 20))
part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
else
part = scroll_bar_move_ratio;
x_send_scroll_bar_event (bar->window, part, position, height);
}
-#endif /* not USE_GTK */
-#endif /* not USE_MOTIF */
+#endif /* not USE_GTK and not USE_MOTIF */
#define SCROLL_BAR_NAME "verticalScrollBar"
/* Remember X window and widget in the scroll bar vector. */
SET_SCROLL_BAR_X_WIDGET (bar, widget);
xwindow = XtWindow (widget);
- SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
+ bar->x_window = xwindow;
UNBLOCK_INPUT;
}
{
struct frame *f = XFRAME (w->frame);
struct scroll_bar *bar
- = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
+ = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, x_window, PVEC_OTHER);
BLOCK_INPUT;
a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
if (a.background_pixel == -1)
- a.background_pixel = f->output_data.x->background_pixel;
+ a.background_pixel = FRAME_BACKGROUND_PIXEL (f);
a.event_mask = (ButtonPressMask | ButtonReleaseMask
| ButtonMotionMask | PointerMotionHintMask
CopyFromParent,
/* Attributes. */
mask, &a);
- SET_SCROLL_BAR_X_WINDOW (bar, window);
+ bar->x_window = window;
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
XSETWINDOW (bar->window, w);
- XSETINT (bar->top, top);
- XSETINT (bar->left, left);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
- XSETINT (bar->start, 0);
- XSETINT (bar->end, 0);
+ bar->top = top;
+ bar->left = left;
+ bar->width = width;
+ bar->height = height;
+ bar->start = 0;
+ bar->end = 0;
bar->dragging = Qnil;
-#ifdef USE_TOOLKIT_SCROLL_BARS
- bar->fringe_extended_p = Qnil;
-#endif
+ bar->fringe_extended_p = 0;
/* Add bar to its frame's list of scroll bars. */
bar->next = FRAME_SCROLL_BARS (f);
{
#ifdef USE_GTK
xg_update_scrollbar_pos (f,
- SCROLL_BAR_X_WINDOW (bar),
+ bar->x_window,
top,
left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
max (height, 1));
- xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
+ xg_show_scroll_bar (bar->x_window);
#else /* not USE_GTK */
Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
XtConfigureWidget (scroll_bar,
#endif /* not USE_GTK */
}
#else /* not USE_TOOLKIT_SCROLL_BARS */
- XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
+ XMapRaised (FRAME_X_DISPLAY (f), bar->x_window);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
UNBLOCK_INPUT;
}
+#ifndef USE_TOOLKIT_SCROLL_BARS
+
/* Draw BAR's handle in the proper position.
If the handle is already drawn from START to END, don't bother
the bar's top is as far down as it goes; otherwise, there's no way
to move to the very end of the buffer. */
-#ifndef USE_TOOLKIT_SCROLL_BARS
-
static void
x_scroll_bar_set_handle (bar, start, end, rebuild)
struct scroll_bar *bar;
int rebuild;
{
int dragging = ! NILP (bar->dragging);
- Window w = SCROLL_BAR_X_WINDOW (bar);
+ Window w = bar->x_window;
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
GC gc = f->output_data.x->normal_gc;
/* If the display is already accurate, do nothing. */
if (! rebuild
- && start == XINT (bar->start)
- && end == XINT (bar->end))
+ && start == bar->start
+ && end == bar->end)
return;
BLOCK_INPUT;
{
- int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
- int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+ int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, bar->width);
+ int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
+ int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
/* Make sure the values are reasonable, and try to preserve
the distance between start and end. */
}
/* Store the adjusted setting in the scroll bar. */
- XSETINT (bar->start, start);
- XSETINT (bar->end, end);
+ bar->start = start;
+ bar->end = end;
/* Clip the end position, just for display. */
if (end > top_range)
/* Restore the foreground color of the GC if we changed it above. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
XSetForeground (FRAME_X_DISPLAY (f), gc,
- f->output_data.x->foreground_pixel);
+ FRAME_FOREGROUND_PIXEL (f));
/* Draw the empty space below the handle. Note that we can't
clear zero-height areas; that means "clear to end of window." */
#ifdef USE_TOOLKIT_SCROLL_BARS
#ifdef USE_GTK
- xg_remove_scroll_bar (f, SCROLL_BAR_X_WINDOW (bar));
+ xg_remove_scroll_bar (f, bar->x_window);
#else /* not USE_GTK */
XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
#endif /* not USE_GTK */
#else
- XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
+ XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window);
#endif
/* Disassociate this scroll bar from its window. */
BLOCK_INPUT;
- if (sb_left != XINT (bar->left))
+ if (sb_left != bar->left)
mask |= CWX;
- if (top != XINT (bar->top))
+ if (top != bar->top)
mask |= CWY;
- if (sb_width != XINT (bar->width))
+ if (sb_width != bar->width)
mask |= CWWidth;
- if (height != XINT (bar->height))
+ if (height != bar->height)
mask |= CWHeight;
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Move/size the scroll bar widget. */
- if (mask || !NILP (bar->fringe_extended_p) != fringe_extended_p)
+ if (mask || bar->fringe_extended_p != fringe_extended_p)
{
/* Since toolkit scroll bars are smaller than the space reserved
for them on the frame, we have to clear "under" them. */
}
#ifdef USE_GTK
xg_update_scrollbar_pos (f,
- SCROLL_BAR_X_WINDOW (bar),
+ bar->x_window,
top,
sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
wc.y = top;
wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
wc.height = height;
- XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
+ XConfigureWindow (FRAME_X_DISPLAY (f), bar->x_window,
mask, &wc);
}
#endif /* not USE_TOOLKIT_SCROLL_BARS */
/* Remember new settings. */
- XSETINT (bar->left, sb_left);
- XSETINT (bar->top, top);
- XSETINT (bar->width, sb_width);
- XSETINT (bar->height, height);
+ bar->left = sb_left;
+ bar->top = top;
+ bar->width = sb_width;
+ bar->height = height;
UNBLOCK_INPUT;
}
#ifdef USE_TOOLKIT_SCROLL_BARS
- bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
+ bar->fringe_extended_p = fringe_extended_p;
x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
#else /* not USE_TOOLKIT_SCROLL_BARS */
struct scroll_bar *bar;
XEvent *event;
{
- Window w = SCROLL_BAR_X_WINDOW (bar);
+ Window w = bar->x_window;
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
GC gc = f->output_data.x->normal_gc;
int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
BLOCK_INPUT;
- x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
+ x_scroll_bar_set_handle (bar, bar->start, bar->end, 1);
/* Switch to scroll bar foreground color. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
/* x, y, width, height */
0, 0,
- XINT (bar->width) - 1 - width_trim - width_trim,
- XINT (bar->height) - 1);
+ bar->width - 1 - width_trim - width_trim,
+ bar->height - 1);
/* Restore the foreground color of the GC if we changed it above. */
if (f->output_data.x->scroll_bar_foreground_pixel != -1)
XSetForeground (FRAME_X_DISPLAY (f), gc,
- f->output_data.x->foreground_pixel);
+ FRAME_FOREGROUND_PIXEL (f));
UNBLOCK_INPUT;
#if 0
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int internal_height
- = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
+ = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
#endif
int top_range
- = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+ = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
if (y < 0) y = 0;
if (y > top_range) y = top_range;
- if (y < XINT (bar->start))
+ if (y < bar->start)
emacs_event->part = scroll_bar_above_handle;
- else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
+ else if (y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
emacs_event->part = scroll_bar_handle;
else
emacs_event->part = scroll_bar_below_handle;
holding it. */
if (event->type == ButtonPress
&& emacs_event->part == scroll_bar_handle)
- XSETINT (bar->dragging, y - XINT (bar->start));
+ XSETINT (bar->dragging, y - bar->start);
#endif
#ifndef USE_TOOLKIT_SCROLL_BARS
&& ! NILP (bar->dragging))
{
int new_start = y - XINT (bar->dragging);
- int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
+ int new_end = new_start + bar->end - bar->start;
x_scroll_bar_set_handle (bar, new_start, new_end, 0);
bar->dragging = Qnil;
/* Where should the handle be now? */
int new_start = event->xmotion.y - XINT (bar->dragging);
- if (new_start != XINT (bar->start))
+ if (new_start != bar->start)
{
- int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
+ int new_end = new_start + bar->end - bar->start;
x_scroll_bar_set_handle (bar, new_start, new_end, 0);
}
unsigned long *time;
{
struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
- Window w = SCROLL_BAR_X_WINDOW (bar);
+ Window w = bar->x_window;
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int win_x, win_y;
Window dummy_window;
{
#if 0
int inside_height
- = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
+ = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, bar->height);
#endif
int top_range
- = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+ = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
if (! NILP (bar->dragging))
*part = scroll_bar_handle;
- else if (win_y < XINT (bar->start))
+ else if (win_y < bar->start)
*part = scroll_bar_above_handle;
- else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
+ else if (win_y < bar->end + VERTICAL_SCROLL_BAR_MIN_HANDLE)
*part = scroll_bar_handle;
else
*part = scroll_bar_below_handle;
for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
bar = XSCROLL_BAR (bar)->next)
XClearArea (FRAME_X_DISPLAY (f),
- SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
+ XSCROLL_BAR (bar)->x_window,
0, 0, 0, 0, True);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
int count = 0;
int do_help = 0;
int nbytes = 0;
- struct frame *f;
+ struct frame *f = NULL;
struct coding_system coding;
XEvent event = *eventp;
}
#endif /* USE_TOOLKIT_SCROLL_BARS */
+ /* XEmbed messages from the embedder (if any). */
+ if (event.xclient.message_type
+ == dpyinfo->Xatom_XEMBED)
+ {
+ enum xembed_message msg = event.xclient.data.l[1];
+ if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
+
+ *finish = X_EVENT_GOTO_OUT;
+ goto done;
+ }
+
f = x_any_window_to_frame (dpyinfo, event.xclient.window);
if (!f)
goto OTHER;
bzero (&compose_status, sizeof (compose_status));
orig_keysym = keysym;
- /* Common for all keysym input events. */
- XSETFRAME (inev.ie.frame_or_window, f);
- inev.ie.modifiers
- = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
- inev.ie.timestamp = event.xkey.time;
-
- /* First deal with keysyms which have defined
- translations to characters. */
- if (keysym >= 32 && keysym < 128)
- /* Avoid explicitly decoding each ASCII character. */
- {
- inev.ie.kind = ASCII_KEYSTROKE_EVENT;
- inev.ie.code = keysym;
+ /* Common for all keysym input events. */
+ XSETFRAME (inev.ie.frame_or_window, f);
+ inev.ie.modifiers
+ = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
+ inev.ie.timestamp = event.xkey.time;
+
+ /* First deal with keysyms which have defined
+ translations to characters. */
+ if (keysym >= 32 && keysym < 128)
+ /* Avoid explicitly decoding each ASCII character. */
+ {
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
goto done_keysym;
}
/* Now non-ASCII. */
if (HASH_TABLE_P (Vx_keysym_table)
&& (NATNUMP (c = Fgethash (make_number (keysym),
- Vx_keysym_table,
- Qnil))))
- {
- inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.ie.code = XFASTINT (c);
- goto done_keysym;
- }
-
- /* Random non-modifier sorts of keysyms. */
- if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+ Vx_keysym_table,
+ Qnil))))
+ {
+ inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ inev.ie.code = XFASTINT (c);
+ goto done_keysym;
+ }
+
+ /* Random non-modifier sorts of keysyms. */
+ if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
|| keysym == XK_Delete
#ifdef XK_ISO_Left_Tab
|| (keysym >= XK_ISO_Left_Tab
|| (orig_keysym & (1 << 28))
|| (keysym != NoSymbol && nbytes == 0))
&& ! (IsModifierKey (orig_keysym)
-#ifndef HAVE_X11R5
-#ifdef XK_Mode_switch
- || ((unsigned)(orig_keysym) == XK_Mode_switch)
-#endif
-#ifdef XK_Num_Lock
- || ((unsigned)(orig_keysym) == XK_Num_Lock)
-#endif
-#endif /* not HAVE_X11R5 */
/* The symbols from XK_ISO_Lock
to XK_ISO_Last_Group_Lock
don't have real modifiers but
c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
nbytes - i, len);
inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
inev.ie.code = c;
kbd_buffer_store_event_hold (&inev.ie, hold_quit);
}
- /* Previous code updated count by nchars rather than nbytes,
- but that seems bogus to me. ++kfs */
- count += nbytes;
+ count += nchars;
inev.ie.kind = NO_EVENT; /* Already stored above. */
/* We may get an EnterNotify on the buttons in the toolbar. In that
case we moved out of any highlighted area and need to note this. */
if (!f && last_mouse_glyph_frame)
- note_mouse_movement (last_mouse_glyph_frame, &event);
+ note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
#endif
goto OTHER;
#ifdef USE_GTK
/* See comment in EnterNotify above */
else if (last_mouse_glyph_frame)
- note_mouse_movement (last_mouse_glyph_frame, &event);
+ note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
#endif
goto OTHER;
will be selected only when it is active. */
if (WINDOWP (window)
&& !EQ (window, last_window)
- && !EQ (window, selected_window))
+ && !EQ (window, selected_window)
+ /* For click-to-focus window managers
+ create event iff we don't leave the
+ selected frame. */
+ && (focus_follows_mouse
+ || (EQ (XWINDOW (window)->frame,
+ XWINDOW (selected_window)->frame))))
{
inev.ie.kind = SELECT_WINDOW_EVENT;
inev.ie.frame_or_window = window;
case ConfigureNotify:
f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
+#ifdef USE_GTK
+ if (!f
+ && (f = x_any_window_to_frame (dpyinfo, event.xconfigure.window))
+ && event.xconfigure.window == FRAME_X_WINDOW (f))
+ {
+ xg_frame_resized (f, event.xconfigure.width,
+ event.xconfigure.height);
+ f = 0;
+ }
+#endif
if (f)
{
#ifndef USE_X_TOOLKIT
-#ifdef USE_GTK
- xg_resize_widgets (f, event.xconfigure.width,
- event.xconfigure.height);
-#else /* not USE_GTK */
+#ifndef USE_GTK
/* If there is a pending resize for fullscreen, don't
do this one, the right one will come later.
The toolkit version doesn't seem to need this, but we
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
-#endif /* not USE_GTK */
-#endif
FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
+#endif /* not USE_GTK */
+#endif
#ifdef USE_GTK
/* GTK creates windows but doesn't map them.
if (tool_bar_p && event.xbutton.button < 4)
{
- if (event.xbutton.type == ButtonPress)
- handle_tool_bar_click (f, x, y, 1, 0);
- else
- handle_tool_bar_click (f, x, y, 0,
- x_x_to_emacs_modifiers (dpyinfo,
- event.xbutton.state));
+ handle_tool_bar_click (f, x, y,
+ event.xbutton.type == ButtonPress,
+ x_x_to_emacs_modifiers (dpyinfo,
+ event.xbutton.state));
}
}
else
construct_mouse_click (&inev.ie, &event.xbutton, f);
}
+ if (FRAME_X_EMBEDDED_P (f))
+ xembed_send_message (f, event.xbutton.time,
+ XEMBED_REQUEST_FOCUS, 0, 0, 0);
}
else
{
We return as soon as there are no more events to be read.
We return the number of characters stored into the buffer,
- thus pretending to be `read'.
+ thus pretending to be `read' (except the characters we store
+ in the keyboard buffer can be multibyte, so are not necessarily
+ C chars).
EXPECTED is nonzero if the caller knows input is available. */
static int
-XTread_socket (sd, expected, hold_quit)
- register int sd;
+XTread_socket (terminal, expected, hold_quit)
+ struct terminal *terminal;
int expected;
struct input_event *hold_quit;
{
int count = 0;
XEvent event;
int event_found = 0;
+#if 0
struct x_display_info *dpyinfo;
+#endif
if (interrupt_input_blocked)
{
++handling_signal;
+#ifdef HAVE_X_SM
+ /* Only check session manager input for the primary display. */
+ if (terminal->id == 1 && x_session_have_connection ())
+ {
+ struct input_event inev;
+ BLOCK_INPUT;
+ /* We don't need to EVENT_INIT (inev) here, as
+ x_session_check_input copies an entire input_event. */
+ if (x_session_check_input (&inev))
+ {
+ kbd_buffer_store_event_hold (&inev, hold_quit);
+ count++;
+ }
+ UNBLOCK_INPUT;
+ }
+#endif
+
+ /* For debugging, this gives a way to fake an I/O error. */
+ if (terminal->display_info.x == XTread_socket_fake_io_error)
+ {
+ XTread_socket_fake_io_error = 0;
+ x_io_error_quitter (terminal->display_info.x->display);
+ }
+
+#if 0 /* This loop is a noop now. */
/* Find the display we are supposed to read input for.
It's the one communicating on descriptor SD. */
for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
#endif /* HAVE_SELECT */
#endif /* SIGIO */
#endif
-
- /* For debugging, this gives a way to fake an I/O error. */
- if (dpyinfo == XTread_socket_fake_io_error)
- {
- XTread_socket_fake_io_error = 0;
- x_io_error_quitter (dpyinfo->display);
- }
-
-#ifdef HAVE_X_SM
- {
- struct input_event inev;
- BLOCK_INPUT;
- /* We don't need to EVENT_INIT (inev) here, as
- x_session_check_input copies an entire input_event. */
- if (x_session_check_input (&inev))
- {
- kbd_buffer_store_event_hold (&inev, hold_quit);
- count++;
- }
- UNBLOCK_INPUT;
- }
+ }
#endif
#ifndef USE_GTK
- while (XPending (dpyinfo->display))
- {
- int finish;
+ while (XPending (terminal->display_info.x->display))
+ {
+ int finish;
- XNextEvent (dpyinfo->display, &event);
+ XNextEvent (terminal->display_info.x->display, &event);
#ifdef HAVE_X_I18N
- /* Filter events for the current X input method. */
- if (x_filter_event (dpyinfo, &event))
- break;
+ /* Filter events for the current X input method. */
+ if (x_filter_event (terminal->display_info.x, &event))
+ break;
#endif
- event_found = 1;
+ event_found = 1;
- count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
+ count += handle_one_xevent (terminal->display_info.x,
+ &event, &finish, hold_quit);
- if (finish == X_EVENT_GOTO_OUT)
- goto out;
- }
-#endif /* not USE_GTK */
+ if (finish == X_EVENT_GOTO_OUT)
+ goto out;
}
-#ifdef USE_GTK
+#else /* USE_GTK */
/* For GTK we must use the GTK event loop. But XEvents gets passed
to our filter function above, and then to the big event switch.
}
#ifndef XFlush
- if (updating_frame != f)
- XFlush (FRAME_X_DISPLAY (f));
+ XFlush (FRAME_X_DISPLAY (f));
#endif
}
if (FRAME_X_WINDOW (f) == 0)
return 1;
-#ifdef HAVE_X11R4
{
XTextProperty text;
text.value = (unsigned char *) icon_name;
text.nitems = strlen (icon_name);
XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &text);
}
-#else /* not HAVE_X11R4 */
- XSetIconName (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), icon_name);
-#endif /* not HAVE_X11R4 */
if (f->output_data.x->icon_bitmap > 0)
x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
x_error_message->string[0] = 0;
}
+#if 0 /* See comment in unwind_to_catch why calling this is a bad
+ * idea. --lorentey */
/* Close off all unclosed x_catch_errors calls. */
void
while (x_error_message)
x_uncatch_errors ();
}
+#endif
/* Nonzero if x_catch_errors has been done and not yet canceled. */
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
Lisp_Object frame, tail;
+ int index = SPECPDL_INDEX ();
error_msg = (char *) alloca (strlen (error_message) + 1);
strcpy (error_msg, error_message);
the original message here. */
x_catch_errors (dpy);
- /* We have to close the display to inform Xt that it doesn't
- exist anymore. If we don't, Xt will continue to wait for
- events from the display. As a consequence, a sequence of
+ /* Inhibit redisplay while frames are being deleted. */
+ specbind (Qinhibit_redisplay, Qt);
- M-x make-frame-on-display RET :1 RET
- ...kill the new frame, so that we get an IO error...
- M-x make-frame-on-display RET :1 RET
-
- will indefinitely wait in Xt for events for display `:1', opened
- in the first class to make-frame-on-display.
-
- Closing the display is reported to lead to a bus error on
- OpenWindows in certain situations. I suspect that is a bug
- in OpenWindows. I don't know how to cicumvent it here. */
-
-#ifdef USE_X_TOOLKIT
- /* If DPYINFO is null, this means we didn't open the display
- in the first place, so don't try to close it. */
if (dpyinfo)
{
- extern void (*fatal_error_signal_hook) P_ ((void));
- fatal_error_signal_hook = x_fatal_error_signal;
- XtCloseDisplay (dpy);
- fatal_error_signal_hook = NULL;
+ /* Protect display from being closed when we delete the last
+ frame on it. */
+ dpyinfo->reference_count++;
+ dpyinfo->terminal->reference_count++;
}
-#endif
-
-#ifdef USE_GTK
- if (dpyinfo)
- xg_display_close (dpyinfo->display);
-#endif
-
- /* Indicate that this display is dead. */
- if (dpyinfo)
- dpyinfo->display = 0;
-
+
/* First delete frames whose mini-buffers are on frames
that are on the dead display. */
FOR_EACH_FRAME (tail, frame)
&& FRAME_X_P (XFRAME (minibuf_frame))
&& ! EQ (frame, minibuf_frame)
&& FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
- Fdelete_frame (frame, Qt);
+ Fdelete_frame (frame, Qnoelisp);
}
/* Now delete all remaining frames on the dead display.
/* Set this to t so that Fdelete_frame won't get confused
trying to find a replacement. */
FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
- Fdelete_frame (frame, Qt);
+ Fdelete_frame (frame, Qnoelisp);
}
+ /* We have to close the display to inform Xt that it doesn't
+ exist anymore. If we don't, Xt will continue to wait for
+ events from the display. As a consequence, a sequence of
+
+ M-x make-frame-on-display RET :1 RET
+ ...kill the new frame, so that we get an IO error...
+ M-x make-frame-on-display RET :1 RET
+
+ will indefinitely wait in Xt for events for display `:1', opened
+ in the first call to make-frame-on-display.
+
+ Closing the display is reported to lead to a bus error on
+ OpenWindows in certain situations. I suspect that is a bug
+ in OpenWindows. I don't know how to circumvent it here. */
+
if (dpyinfo)
- x_delete_display (dpyinfo);
+ {
+#ifdef USE_X_TOOLKIT
+ /* If DPYINFO is null, this means we didn't open the display
+ in the first place, so don't try to close it. */
+ {
+ extern void (*fatal_error_signal_hook) P_ ((void));
+ fatal_error_signal_hook = x_fatal_error_signal;
+ XtCloseDisplay (dpy);
+ fatal_error_signal_hook = NULL;
+ }
+#endif
+
+#ifdef USE_GTK
+ /* Due to bugs in some Gtk+ versions, just exit here if this
+ is the last display/terminal. */
+ if (terminal_list->next_terminal == NULL)
+ {
+ fprintf (stderr, "%s\n", error_msg);
+ shut_down_emacs (0, 0, Qnil);
+ exit (70);
+ }
+ xg_display_close (dpyinfo->display);
+#endif
+
+ /* Indicate that this display is dead. */
+ dpyinfo->display = 0;
+
+ dpyinfo->reference_count--;
+ dpyinfo->terminal->reference_count--;
+ if (dpyinfo->reference_count != 0)
+ /* We have just closed all frames on this display. */
+ abort ();
+
+ {
+ Lisp_Object tmp;
+ XSETTERMINAL (tmp, dpyinfo->terminal);
+ Fdelete_terminal (tmp, Qnoelisp);
+ }
+ }
x_uncatch_errors ();
- if (x_display_list == 0)
+ if (terminal_list == 0)
{
fprintf (stderr, "%s\n", error_msg);
shut_down_emacs (0, 0, Qnil);
sigunblock (sigmask (SIGALRM));
TOTALLY_UNBLOCK_INPUT;
+ unbind_to (index, Qnil);
clear_waiting_for_input ();
+ /* Here, we absolutely have to use a non-local exit (e.g. signal, throw,
+ longjmp), because returning from this function would get us back into
+ Xlib's code which will directly call `exit'. */
error ("%s", error_msg);
}
/* Now make the frame display the given font. */
if (FRAME_X_WINDOW (f) != 0)
{
- XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
- FRAME_FONT (f)->fid);
- XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
- FRAME_FONT (f)->fid);
- XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
- FRAME_FONT (f)->fid);
+ Font fid;
+
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ fid = FRAME_X_DISPLAY_INFO (f)->font->fid;
+ else
+#endif
+ fid = FRAME_FONT (f)->fid;
+ XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc, fid);
+ XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc, fid);
+ XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc, fid);
/* Don't change the size of a tip frame; there's no point in
doing it because it's done in Fx_show_tip, and it leads to
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
- if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+ if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
{
FRAME_XIC (f) = NULL;
xic_free_xfontset (f);
{
struct frame *f = XFRAME (frame);
- if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+ if (FRAME_X_P (f)
+ && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
if (FRAME_XIC (f) == NULL)
{
create_frame_xic (f);
{
int modified_top, modified_left;
- if (change_gravity != 0)
+ if (change_gravity > 0)
{
FRAME_X_OUTPUT (f)->left_before_move = f->left_pos;
FRAME_X_OUTPUT (f)->top_before_move = f->top_pos;
on the root window for frame F contains ATOMNAME.
This is how a WM check shall be done according to the Window Manager
Specification/Extended Window Manager Hints at
- http://freedesktop.org/wiki/Standards_2fwm_2dspec. */
+ http://freedesktop.org/wiki/Specifications/wm-spec. */
static int
wm_supports (f, atomname)
/* The left fuzz-factor is 10 pixels. The top fuzz-factor is 40
pixels. */
- if (abs (current_left - left) <= 10 && abs (current_top - top) <= 40)
+ if (eabs (current_left - left) <= 10
+ && eabs (current_top - top) <= 40)
return;
}
else if (current_left == left && current_top == top)
FRAME_PTR f;
{
/* See Window Manager Specification/Extended Window Manager Hints at
- http://freedesktop.org/wiki/Standards_2fwm_2dspec */
+ http://freedesktop.org/wiki/Specifications/wm-spec */
const char *atom = "_NET_ACTIVE_WINDOW";
if (f->async_visible && wm_supports (f, atom))
x_lower_frame (f);
}
\f
+/* XEmbed implementation. */
+
+void
+xembed_set_info (f, flags)
+ struct frame *f;
+ enum xembed_info flags;
+{
+ Atom atom;
+ unsigned long data[2];
+
+ atom = XInternAtom (FRAME_X_DISPLAY (f), "_XEMBED_INFO", False);
+
+ data[0] = XEMBED_VERSION;
+ data[1] = flags;
+
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), atom, atom,
+ 32, PropModeReplace, (unsigned char *) data, 2);
+}
+
+void
+xembed_send_message (f, time, message, detail, data1, data2)
+ struct frame *f;
+ Time time;
+ enum xembed_message message;
+ long detail;
+ long data1;
+ long data2;
+{
+ XEvent event;
+
+ event.xclient.type = ClientMessage;
+ event.xclient.window = FRAME_X_OUTPUT (f)->parent_desc;
+ event.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_XEMBED;
+ event.xclient.format = 32;
+ event.xclient.data.l[0] = time;
+ event.xclient.data.l[1] = message;
+ event.xclient.data.l[2] = detail;
+ event.xclient.data.l[3] = data1;
+ event.xclient.data.l[4] = data2;
+
+ XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
+ False, NoEventMask, &event);
+ XSync (FRAME_X_DISPLAY (f), False);
+}
+\f
/* Change of visibility. */
/* This tries to wait until the frame is really visible.
if we get to x_make_frame_visible a second time
before the window gets really visible. */
if (! FRAME_ICONIFIED_P (f)
+ && ! FRAME_X_EMBEDDED_P (f)
&& ! f->output_data.x->asked_for_visible)
x_set_offset (f, f->left_pos, f->top_pos, 0);
if (! EQ (Vx_no_window_manager, Qt))
x_wm_set_window_state (f, NormalState);
#ifdef USE_X_TOOLKIT
- /* This was XtPopup, but that did nothing for an iconified frame. */
- XtMapWidget (f->output_data.x->widget);
+ if (FRAME_X_EMBEDDED_P (f))
+ xembed_set_info (f, XEMBED_MAPPED);
+ else
+ {
+ /* This was XtPopup, but that did nothing for an iconified frame. */
+ XtMapWidget (f->output_data.x->widget);
+ }
#else /* not USE_X_TOOLKIT */
#ifdef USE_GTK
gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
gtk_window_deiconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
#else
- XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ if (FRAME_X_EMBEDDED_P (f))
+ xembed_set_info (f, XEMBED_MAPPED);
+ else
+ XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif /* not USE_GTK */
#endif /* not USE_X_TOOLKIT */
#if 0 /* This seems to bring back scroll bars in the wrong places
because the window manager may choose the position
and we don't want to override it. */
- if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
+ if (! FRAME_VISIBLE_P (f)
+ && ! FRAME_ICONIFIED_P (f)
+ && ! FRAME_X_EMBEDDED_P (f)
&& f->win_gravity == NorthWestGravity
&& previously_visible)
{
if (FRAME_GTK_OUTER_WIDGET (f))
gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f));
else
+#else
+ if (FRAME_X_EMBEDDED_P (f))
+ xembed_set_info (f, 0);
+ else
#endif
{
-#ifdef HAVE_X11R4
if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
DefaultScreen (FRAME_X_DISPLAY (f))))
UNBLOCK_INPUT_RESIGNAL;
error ("Can't notify window manager of window withdrawal");
}
-#else /* ! defined (HAVE_X11R4) */
-
- /* Tell the window manager what we're going to do. */
- if (! EQ (Vx_no_window_manager, Qt))
- {
- XEvent unmap;
-
- unmap.xunmap.type = UnmapNotify;
- unmap.xunmap.window = window;
- unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
- unmap.xunmap.from_configure = False;
- if (! XSendEvent (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
- False,
- SubstructureRedirectMaskSubstructureNotifyMask,
- &unmap))
- {
- UNBLOCK_INPUT_RESIGNAL;
- error ("Can't notify window manager of withdrawal");
- }
- }
-
- /* Unmap the window ourselves. Cheeky! */
- XUnmapWindow (FRAME_X_DISPLAY (f), window);
-#endif /* ! defined (HAVE_X11R4) */
}
/* We can't distinguish this from iconification
/* Make sure the X server knows where the window should be positioned,
in case the user deiconifies with the window manager. */
- if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
+ if (! FRAME_VISIBLE_P (f)
+ && ! FRAME_ICONIFIED_P (f)
+ && ! FRAME_X_EMBEDDED_P (f))
x_set_offset (f, f->left_pos, f->top_pos, 0);
/* Since we don't know which revision of X we're running, we'll use both
XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
#endif /* !USE_X_TOOLKIT */
- unload_color (f, f->output_data.x->foreground_pixel);
- unload_color (f, f->output_data.x->background_pixel);
+ unload_color (f, FRAME_FOREGROUND_PIXEL (f));
+ unload_color (f, FRAME_BACKGROUND_PIXEL (f));
unload_color (f, f->output_data.x->cursor_pixel);
unload_color (f, f->output_data.x->cursor_foreground_pixel);
unload_color (f, f->output_data.x->border_pixel);
them; otherwise, we set the min_width and min_height members
to the size for a zero x zero frame. */
-#ifdef HAVE_X11R4
size_hints.flags |= PBaseSize;
size_hints.base_width = base_width;
size_hints.base_height = base_height;
size_hints.min_width = base_width + min_cols * size_hints.width_inc;
size_hints.min_height = base_height + min_rows * size_hints.height_inc;
-#else
- size_hints.min_width = base_width;
- size_hints.min_height = base_height;
-#endif
}
/* If we don't need the old flags, we don't need the old hint at all. */
long supplied_return;
int value;
-#ifdef HAVE_X11R4
value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
&supplied_return);
-#else
- value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
-#endif
#ifdef USE_X_TOOLKIT
size_hints.base_height = hints.base_height;
}
#endif /* PWinGravity */
-#ifdef HAVE_X11R4
XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#else
- XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#endif
}
#endif /* not USE_GTK */
xassert (font != NULL);
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ /* Fixme: Perhaps we should check all cached fonts. */
+ return;
+#endif
for (i = 0; i < dpyinfo->n_fonts; i++)
if (dpyinfo->font_table[i].name
&& font == dpyinfo->font_table[i].font)
*bits = nr;
}
+/* Return 1 if display DISPLAY is available for use, 0 otherwise.
+ But don't permanently open it, just test its availability. */
+
int
x_display_ok (display)
- const char * display;
+ const char *display;
{
int dpy_ok = 1;
Display *dpy;
return dpy_ok;
}
+/* 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. */
+
struct x_display_info *
x_term_init (display_name, xrm_option, resource_name)
Lisp_Object display_name;
{
int connection;
Display *dpy;
+ struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
++x_initialized;
}
+ if (! x_display_ok (SDATA (display_name)))
+ error ("Display %s can't be opened", SDATA (display_name));
+
#ifdef USE_GTK
{
#define NUM_ARGV 10
char **argv2 = argv;
GdkAtom atom;
+#ifndef HAVE_GTK_MULTIDISPLAY
+ if (!EQ (Vinitial_window_system, intern ("x")))
+ error ("Sorry, you cannot connect to X servers with the GTK toolkit");
+#endif
+
if (x_initialized++ > 1)
{
+#ifdef HAVE_GTK_MULTIDISPLAY
/* Opening another display. If xg_display_open returns less
than zero, we are probably on GTK 2.0, which can only handle
one display. GTK 2.2 or later can handle more than one. */
if (xg_display_open (SDATA (display_name), &dpy) < 0)
+#endif
error ("Sorry, this version of GTK can only handle one display");
- }
+ }
else
{
for (argc = 0; argc < NUM_ARGV; ++argc)
argv[argc++] = "--name";
argv[argc++] = resource_name;
-#ifdef HAVE_X11R5
XSetLocaleModifiers ("");
-#endif
gtk_init (&argc, &argv2);
}
#else /* not USE_X_TOOLKIT */
-#ifdef HAVE_X11R5
XSetLocaleModifiers ("");
-#endif
dpy = XOpenDisplay (SDATA (display_name));
#endif /* not USE_X_TOOLKIT */
#endif /* not USE_GTK*/
dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
bzero (dpyinfo, sizeof *dpyinfo);
+ terminal = x_create_terminal (dpyinfo);
+
#ifdef MULTI_KBOARD
{
struct x_display_info *share;
SDATA (display_name)))
break;
if (share)
- dpyinfo->kboard = share->kboard;
+ terminal->kboard = share->terminal->kboard;
else
{
- dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
- init_kboard (dpyinfo->kboard);
+ terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+ init_kboard (terminal->kboard);
+ terminal->kboard->Vwindow_system = intern ("x");
if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
{
char *vendor = ServerVendor (dpy);
UNBLOCK_INPUT;
- dpyinfo->kboard->Vsystem_key_alist
+ terminal->kboard->Vsystem_key_alist
= call1 (Qvendor_specific_keysyms,
vendor ? build_string (vendor) : empty_unibyte_string);
BLOCK_INPUT;
}
- dpyinfo->kboard->next_kboard = all_kboards;
- all_kboards = dpyinfo->kboard;
+ terminal->kboard->next_kboard = all_kboards;
+ all_kboards = terminal->kboard;
/* Don't let the initial kboard remain current longer than necessary.
That would cause problems if a file loaded on startup tries to
prompt in the mini-buffer. */
if (current_kboard == initial_kboard)
- current_kboard = dpyinfo->kboard;
+ current_kboard = terminal->kboard;
}
- dpyinfo->kboard->reference_count++;
+ terminal->kboard->reference_count++;
}
#endif
dpyinfo->display = dpy;
+ /* Set the name of the terminal. */
+ terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
+ strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
+ terminal->name[SBYTES (display_name)] = 0;
+
#if 0
XSetAfterFunction (x_current_display, x_trace_wire);
#endif /* ! 0 */
dpyinfo->font_table = NULL;
dpyinfo->n_fonts = 0;
dpyinfo->font_table_size = 0;
+#ifdef USE_FONT_BACKEND
+ dpyinfo->font = XLoadQueryFont (dpyinfo->display, "fixed");
+ if (! dpyinfo->font)
+ dpyinfo->font = XLoadQueryFont (dpyinfo->display, "*");
+ if (! dpyinfo->font)
+ abort ();
+#endif /* USE_FONT_BACKEND */
dpyinfo->bitmaps = 0;
dpyinfo->bitmaps_size = 0;
dpyinfo->bitmaps_last = 0;
dpyinfo->x_focus_frame = 0;
dpyinfo->x_focus_event_frame = 0;
dpyinfo->x_highlight_frame = 0;
- dpyinfo->image_cache = make_image_cache ();
+ dpyinfo->terminal->image_cache = make_image_cache ();
dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
/* See if we can construct pixel values from RGB values. */
/* 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);
- /* Mac OS X 10.3's Xserver sometimes reports 0.0mm. */
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_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
False);
+ dpyinfo->Xatom_XEMBED = XInternAtom (dpyinfo->display, "_XEMBED",
+ False);
+
dpyinfo->cut_buffers_initialized = 0;
dpyinfo->x_dnd_atoms_size = 8;
add_keyboard_wait_descriptor (connection);
#endif
-#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
-#ifdef F_SETOWN_SOCK_NEG
- /* stdin is a socket here */
- fcntl (connection, F_SETOWN, -getpid ());
-#else /* ! defined (F_SETOWN_SOCK_NEG) */
fcntl (connection, F_SETOWN, getpid ());
-#endif /* ! defined (F_SETOWN_SOCK_NEG) */
#endif /* ! defined (F_SETOWN) */
-#endif /* F_SETOWN_BUG */
#ifdef SIGIO
if (interrupt_input)
#endif /* ! defined (SIGIO) */
#ifdef USE_LUCID
-#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
- /* Make sure that we have a valid font for dialog boxes
- so that Xt does not crash. */
{
Display *dpy = dpyinfo->display;
XrmValue d, fr, to;
XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
x_uncatch_errors ();
}
-#endif
#endif
/* See if we should run in synchronous mode. This is useful
Qnil, Qnil);
#ifdef USE_XIM
if (STRINGP (value)
- && (!strcmp (XSTRING (value)->data, "false")
- || !strcmp (XSTRING (value)->data, "off")))
+ && (!strcmp (SDATA (value), "false")
+ || !strcmp (SDATA (value), "off")))
use_xim = 0;
#else
if (STRINGP (value)
- && (!strcmp (XSTRING (value)->data, "true")
- || !strcmp (XSTRING (value)->data, "on")))
+ && (!strcmp (SDATA (value), "true")
+ || !strcmp (SDATA (value), "on")))
use_xim = 1;
#endif
}
#ifdef HAVE_X_SM
- /* Only do this for the first display. */
- if (!x_session_initialized++)
+ /* Only do this for the very first display in the Emacs session.
+ Ignore X session management when Emacs was first started on a
+ tty. */
+ if (terminal->id == 1)
x_session_initialize (dpyinfo);
#endif
return dpyinfo;
}
\f
-/* Get rid of display DPYINFO, assuming all frames are already gone,
+/* Get rid of display DPYINFO, deleting all frames on it,
and without sending any more commands to the X server. */
void
struct x_display_info *dpyinfo;
{
int i;
+ struct terminal *t;
+
+ /* Close all frames and delete the generic struct terminal for this
+ X display. */
+ for (t = terminal_list; t; t = t->next_terminal)
+ if (t->type == output_x_window && t->display_info.x == dpyinfo)
+ {
+#ifdef HAVE_X_SM
+ /* Close X session management when we close its display. */
+ if (t->id == 1 && x_session_have_connection ())
+ x_session_close();
+#endif
+ delete_terminal (t);
+ break;
+ }
delete_keyboard_wait_descriptor (dpyinfo->connection);
XrmDestroyDatabase (dpyinfo->xrdb);
#endif
#endif
-#ifdef MULTI_KBOARD
- if (--dpyinfo->kboard->reference_count == 0)
- delete_kboard (dpyinfo->kboard);
-#endif
#ifdef HAVE_X_I18N
if (dpyinfo->xim)
xim_close_dpy (dpyinfo);
#endif
+#ifdef USE_FONT_BACKEND
+ if (! enable_font_backend)
+ {
+#endif
/* Free the font names in the font table. */
for (i = 0; i < dpyinfo->n_fonts; i++)
if (dpyinfo->font_table[i].name)
xfree (dpyinfo->font_table->font_encoder);
xfree (dpyinfo->font_table);
}
+#ifdef USE_FONT_BACKEND
+ }
+#endif
+
if (dpyinfo->x_id_name)
xfree (dpyinfo->x_id_name);
if (dpyinfo->color_cells)
extern frame_parm_handler x_frame_parm_handlers[];
static struct redisplay_interface x_redisplay_interface =
-{
- x_frame_parm_handlers,
- x_produce_glyphs,
- x_write_glyphs,
- x_insert_glyphs,
- x_clear_end_of_line,
- x_scroll_run,
- x_after_update_window_line,
- x_update_window_begin,
- x_update_window_end,
- x_cursor_to,
- x_flush,
+ {
+ x_frame_parm_handlers,
+ x_produce_glyphs,
+ x_write_glyphs,
+ x_insert_glyphs,
+ x_clear_end_of_line,
+ x_scroll_run,
+ x_after_update_window_line,
+ x_update_window_begin,
+ x_update_window_end,
+ x_cursor_to,
+ x_flush,
#ifdef XFlush
- x_flush,
+ x_flush,
#else
- 0, /* flush_display_optional */
-#endif
- x_clear_window_mouse_face,
- x_get_glyph_overhangs,
- x_fix_overlapping_area,
- x_draw_fringe_bitmap,
- 0, /* define_fringe_bitmap */
- 0, /* destroy_fringe_bitmap */
- x_per_char_metric,
- x_encode_char,
- x_compute_glyph_string_overhangs,
- x_draw_glyph_string,
- x_define_frame_cursor,
- x_clear_frame_area,
- x_draw_window_cursor,
- x_draw_vertical_window_border,
- x_shift_glyphs_for_insert
-};
+ 0, /* flush_display_optional */
+#endif
+ x_clear_window_mouse_face,
+ x_get_glyph_overhangs,
+ x_fix_overlapping_area,
+ x_draw_fringe_bitmap,
+ 0, /* define_fringe_bitmap */
+ 0, /* destroy_fringe_bitmap */
+ x_per_char_metric,
+ x_encode_char,
+ x_compute_glyph_string_overhangs,
+ x_draw_glyph_string,
+ x_define_frame_cursor,
+ x_clear_frame_area,
+ x_draw_window_cursor,
+ x_draw_vertical_window_border,
+ x_shift_glyphs_for_insert
+ };
+
+
+/* This function is called when the last frame on a display is deleted. */
+void
+x_delete_terminal (struct terminal *terminal)
+{
+ struct x_display_info *dpyinfo = terminal->display_info.x;
+ int i;
+
+ /* Protect against recursive calls. Fdelete_frame in
+ delete_terminal calls us back when it deletes our last frame. */
+ if (!terminal->name)
+ return;
+
+ BLOCK_INPUT;
+ /* If called from x_connection_closed, the display may already be closed
+ and dpyinfo->display was set to 0 to indicate that. */
+ if (dpyinfo->display)
+ {
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ XFreeFont (dpyinfo->display, dpyinfo->font);
+ else
+#endif
+ /* Free the fonts in the font table. */
+ for (i = 0; i < dpyinfo->n_fonts; i++)
+ if (dpyinfo->font_table[i].name)
+ {
+ XFreeFont (dpyinfo->display, dpyinfo->font_table[i].font);
+ }
+
+ x_destroy_all_bitmaps (dpyinfo);
+ XSetCloseDownMode (dpyinfo->display, DestroyAll);
+
+#ifdef USE_GTK
+ xg_display_close (dpyinfo->display);
+#else
+#ifdef USE_X_TOOLKIT
+ XtCloseDisplay (dpyinfo->display);
+#else
+ XCloseDisplay (dpyinfo->display);
+#endif
+#endif /* ! USE_GTK */
+ }
+
+ x_delete_display (dpyinfo);
+ UNBLOCK_INPUT;
+}
+
+/* Create a struct terminal, initialize it with the X11 specific
+ functions and make DISPLAY->TERMINAL point to it. */
+
+static struct terminal *
+x_create_terminal (struct x_display_info *dpyinfo)
+{
+ struct terminal *terminal;
+
+ terminal = create_terminal ();
+
+ terminal->type = output_x_window;
+ terminal->display_info.x = dpyinfo;
+ dpyinfo->terminal = terminal;
+
+ /* kboard is initialized in x_term_init. */
+
+ terminal->clear_frame_hook = x_clear_frame;
+ terminal->ins_del_lines_hook = x_ins_del_lines;
+ terminal->delete_glyphs_hook = x_delete_glyphs;
+ terminal->ring_bell_hook = XTring_bell;
+ terminal->reset_terminal_modes_hook = XTreset_terminal_modes;
+ terminal->set_terminal_modes_hook = XTset_terminal_modes;
+ terminal->update_begin_hook = x_update_begin;
+ terminal->update_end_hook = x_update_end;
+ terminal->set_terminal_window_hook = XTset_terminal_window;
+ terminal->read_socket_hook = XTread_socket;
+ terminal->frame_up_to_date_hook = XTframe_up_to_date;
+ terminal->mouse_position_hook = XTmouse_position;
+ terminal->frame_rehighlight_hook = XTframe_rehighlight;
+ terminal->frame_raise_lower_hook = XTframe_raise_lower;
+ terminal->fullscreen_hook = XTfullscreen_hook;
+ terminal->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
+ terminal->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
+ terminal->redeem_scroll_bar_hook = XTredeem_scroll_bar;
+ terminal->judge_scroll_bars_hook = XTjudge_scroll_bars;
+
+ terminal->delete_frame_hook = x_destroy_window;
+ terminal->delete_terminal_hook = x_delete_terminal;
+
+ terminal->rif = &x_redisplay_interface;
+ terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
+ terminal->char_ins_del_ok = 1;
+ terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
+ terminal->fast_clear_end_of_line = 1; /* X does this well. */
+ terminal->memory_below_frame = 0; /* We don't remember what scrolls
+ off the bottom. */
+
+ return terminal;
+}
void
x_initialize ()
{
- rif = &x_redisplay_interface;
-
- clear_frame_hook = x_clear_frame;
- ins_del_lines_hook = x_ins_del_lines;
- delete_glyphs_hook = x_delete_glyphs;
- ring_bell_hook = XTring_bell;
- reset_terminal_modes_hook = XTreset_terminal_modes;
- set_terminal_modes_hook = XTset_terminal_modes;
- update_begin_hook = x_update_begin;
- update_end_hook = x_update_end;
- set_terminal_window_hook = XTset_terminal_window;
- read_socket_hook = XTread_socket;
- frame_up_to_date_hook = XTframe_up_to_date;
- mouse_position_hook = XTmouse_position;
- frame_rehighlight_hook = XTframe_rehighlight;
- frame_raise_lower_hook = XTframe_raise_lower;
- set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
- condemn_scroll_bars_hook = XTcondemn_scroll_bars;
- redeem_scroll_bar_hook = XTredeem_scroll_bar;
- judge_scroll_bars_hook = XTjudge_scroll_bars;
- fullscreen_hook = XTfullscreen_hook;
-
- scroll_region_ok = 1; /* we'll scroll partial frames */
- char_ins_del_ok = 1;
- line_ins_del_ok = 1; /* we'll just blt 'em */
- fast_clear_end_of_line = 1; /* X does this well */
- memory_below_frame = 0; /* we don't remember what scrolls
- off the bottom */
baud_rate = 19200;
x_noop_count = 0;
#endif
/* Try to use interrupt input; if we can't, then start polling. */
- Fset_input_mode (Qt, Qnil, Qt, Qnil);
+ Fset_input_interrupt_mode (Qt);
#ifdef USE_X_TOOLKIT
XtToolkitInitialize ();
XSetIOErrorHandler (x_io_error_quitter);
/* Disable Window Change signals; they are handled by X events. */
+#if 0 /* Don't. We may want to open tty frames later. */
#ifdef SIGWINCH
signal (SIGWINCH, SIG_DFL);
#endif /* SIGWINCH */
+#endif
signal (SIGPIPE, x_connection_signal);
}