/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* Xt features made by Fred Pierresteguy. */
#ifdef USE_X_TOOLKIT
extern void free_frame_menubar ();
-extern void _XEditResCheckMessages ();
extern FRAME_PTR x_menubar_window_to_frame ();
+#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
+#define HACK_EDITRES
+extern void _XEditResCheckMessages ();
+#endif /* not NO_EDITRES */
#endif /* USE_X_TOOLKIT */
#ifndef USE_X_TOOLKIT
#include <locale.h>
#endif
+#ifdef SOLARIS2
+#define X_CONNECTION_LOCK_FLAG XlibDisplayWriting
+#endif
+
+#ifndef min
#define min(a,b) ((a)<(b) ? (a) : (b))
+#endif
+#ifndef max
#define max(a,b) ((a)>(b) ? (a) : (b))
+#endif
\f
/* This is a chain of structures for all the X displays currently in use. */
struct x_display_info *x_display_list;
XTframe_up_to_date (f)
FRAME_PTR f;
{
+ BLOCK_INPUT;
if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc
|| f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
{
FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
}
+ UNBLOCK_INPUT;
}
\f
/* External interface to control of standout mode.
{
/* If char is out of range, try the font's default char instead. */
c = font->default_char;
- row = c >> (INTBITS - 8);
+ row = c >> (BITS_PER_INT - 8);
within = c & 0177;
}
if (!(within >= font->min_char_or_byte2
{
/* If char is out of range, try the font's default char instead. */
c = font->default_char;
- row = c >> (INTBITS - 8);
+ row = c >> (BITS_PER_INT - 8);
within = c & 0177;
}
if (!(within >= font->min_char_or_byte2
#ifdef HAVE_X11R4
XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
#else
- min_code = display->min_keycode;
- max_code = display->max_keycode;
+ min_code = dpyinfo->display->min_keycode;
+ max_code = dpyinfo->display->max_keycode;
#endif
syms = XGetKeyboardMapping (dpyinfo->display,
/* If the cursor's in the text we are about to rewrite,
turn the cursor off. */
if (i == curs_y
- && curs_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col - 1
- && curs_x <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col)
+ && curs_x >= column - 1
+ && curs_x <= endcolumn)
{
x_display_cursor (f, 0);
cursor_off = 1;
/* Child of win. */
&child);
- if (child == None)
+ if (child == None || child == win)
break;
win = child;
XTcondemn_scroll_bars (frame)
FRAME_PTR frame;
{
- /* The condemned list should be empty at this point; if it's not,
- then the rest of Emacs isn't using the condemn/redeem/judge
- protocol correctly. */
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- abort ();
-
- /* Move them all to the "condemned" list. */
- FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
- FRAME_SCROLL_BARS (frame) = Qnil;
+ /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
+ while (! NILP (FRAME_SCROLL_BARS (frame)))
+ {
+ Lisp_Object bar;
+ bar = FRAME_SCROLL_BARS (frame);
+ FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
+ XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
+ XSCROLL_BAR (bar)->prev = Qnil;
+ if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
+ XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
+ FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
+ }
}
/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
int prefix;
Lisp_Object part;
struct x_display_info *dpyinfo;
+#ifdef HAVE_X_I18N
+ Status status_return;
+#endif
if (interrupt_input_blocked)
{
#ifdef FIOSNBIO
/* If available, Xlib uses FIOSNBIO to make the socket
non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
- FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
+ FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
a read returns 0, which Xlib interprets as equivalent to EPIPE. */
fcntl (dpyinfo->connection, F_SETFL, 0);
#endif /* ! defined (FIOSNBIO) */
/* Since we set WM_TAKE_FOCUS, we must call
XSetInputFocus explicitly. But not if f is null,
since that might be an event for a deleted frame. */
+#ifdef HAVE_X_I18N
+ /* Not quite sure this is needed -pd */
+ if (f)
+ XSetICFocus (FRAME_XIC (f));
+#endif
if (f)
XSetInputFocus (event.xclient.display,
event.xclient.window,
f->output_data.x->top_pos = new_y;
}
}
-#if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
+#ifdef HACK_EDITRES
else if (event.xclient.message_type
== dpyinfo->Xatom_editres)
{
_XEditResCheckMessages (f->output_data.x->widget, NULL,
&event, NULL);
}
-#endif /* USE_X_TOOLKIT and HAVE_X11R5 */
+#endif /* HACK_EDITRES */
}
break;
SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
SELECTION_EVENT_TIME (bufp) = eventp->time;
+ bufp->frame_or_window = Qnil;
bufp++;
count += 1;
SELECTION_EVENT_TARGET (bufp) = eventp->target;
SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
SELECTION_EVENT_TIME (bufp) = eventp->time;
+ bufp->frame_or_window = Qnil;
bufp++;
count += 1;
break;
case UnmapNotify:
- f = x_any_window_to_frame (dpyinfo, event.xunmap.window);
+ f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
if (f) /* F may no longer exist if
the frame was deleted. */
{
count++;
numchars--;
}
-#ifdef USE_X_TOOLKIT
goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
case MapNotify:
/* We use x_top_window_to_frame because map events can come
in case this is the second frame. */
record_asynch_buffer_change ();
}
-#ifdef USE_X_TOOLKIT
goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
/* Turn off processing if we become fully obscured. */
case VisibilityNotify:
| dpyinfo->hyper_mod_mask
| dpyinfo->alt_mod_mask);
+#ifdef HAVE_X_I18N
+ if (FRAME_XIC (f))
+ {
+ /* The necessity of the following line took me
+ a full work-day to decipher from the docs!! */
+ if (XFilterEvent (&event, None))
+ break;
+ nbytes = XmbLookupString (FRAME_XIC (f),
+ &event.xkey, copy_buffer,
+ 80, &keysym,
+ &status_return);
+ }
+ else
+ nbytes = XLookupString (&event.xkey, copy_buffer,
+ 80, &keysym, &compose_status);
+#else
nbytes = XLookupString (&event.xkey, copy_buffer,
80, &keysym, &compose_status);
+#endif
orig_keysym = keysym;
else
abort ();
}
- break;
+ goto OTHER;
/* Here's a possible interpretation of the whole
FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
so update things that depend on mouse position. */
if (f)
note_mouse_movement (f, &event.xmotion);
-#ifdef USE_X_TOOLKIT
goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
case FocusIn:
f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
dpyinfo->x_focus_event_frame = f;
if (f)
x_new_focus_frame (dpyinfo, f);
-#ifdef USE_X_TOOLKIT
- goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
+#ifdef HAVE_X_I18N
+ if (f && FRAME_XIC (f))
+ XSetICFocus (FRAME_XIC (f));
+#endif
+
+ goto OTHER;
case LeaveNotify:
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
x_new_focus_frame (dpyinfo, 0);
}
}
-#ifdef USE_X_TOOLKIT
goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
case FocusOut:
f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
dpyinfo->x_focus_event_frame = 0;
if (f && f == dpyinfo->x_focus_frame)
x_new_focus_frame (dpyinfo, 0);
-#ifdef USE_X_TOOLKIT
+
+#ifdef HAVE_X_I18N
+ if (f && FRAME_XIC (f))
+ XUnsetICFocus (FRAME_XIC (f));
+#endif
+
goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
case MotionNotify:
{
clear_mouse_face (dpyinfo);
}
}
-#ifdef USE_X_TOOLKIT
goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
case ConfigureNotify:
f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
/* #endif */
}
}
-#ifdef USE_X_TOOLKIT
goto OTHER;
-#else
- break;
-#endif
case ButtonPress:
case ButtonRelease:
Instead, save it away
and we will pass it to Xt from kbd_buffer_get_event.
That way, we can run some Lisp code first. */
- if (f && event.type == ButtonPress)
+ if (f && event.type == ButtonPress
+ /* Verify the event is really within the menu bar
+ and not just sent to it due to grabbing. */
+ && event.xbutton.x >= 0
+ && event.xbutton.x < f->output_data.x->pixel_width
+ && event.xbutton.y >= 0
+ && event.xbutton.y < f->output_data.x->menubar_height
+ && event.xbutton.same_screen)
{
if (f->output_data.x->saved_button_event == 0)
f->output_data.x->saved_button_event
case MappingKeyboard:
XRefreshKeyboardMapping (&event.xmapping);
}
-#ifdef USE_X_TOOLKIT
goto OTHER;
-#endif /* USE_X_TOOLKIT */
- break;
default:
-#ifdef USE_X_TOOLKIT
OTHER:
+#ifdef USE_X_TOOLKIT
BLOCK_INPUT;
XtDispatchEvent (&event);
UNBLOCK_INPUT;
struct frame *f;
int on;
{
+ /* If we don't have any previous cursor position to use,
+ leave the cursor off. */
+ if (f->phys_cursor_x < 0)
+ return;
+
BLOCK_INPUT;
if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
struct x_display_info *dpyinfo = x_display_info_for_display (display);
Lisp_Object frame, tail;
- /* Whatever we were in the middle of, we are going to throw out of it,
- so reassure various things that have error checks about being
- called with input blocked. */
- TOTALLY_UNBLOCK_INPUT;
-
if (_Xdebug)
abort ();
+ /* Indicate that this display is dead. */
+
+ dpyinfo->display = 0;
+
/* First delete frames whose minibuffers are on frames
that are on the dead display. */
FOR_EACH_FRAME (tail, frame)
Fdelete_frame (frame, Qt);
}
- x_delete_display (dpyinfo);
+ if (dpyinfo)
+ x_delete_display (dpyinfo);
if (x_display_list == 0)
{
error ("%s", error_message);
}
-static SIGTYPE
-x_connection_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
-{
- /* We really ought to close the connection to the display
- that actually failed.
- But do we actually get this signal ever with X11? */
- fprintf (stderr, "X connection closed");
- shut_down_emacs (0, 0, Qnil);
- exit (70);
-}
-
/* This is the usual handler for X protocol errors.
It kills all frames on the display that we got the error for.
If that was the only one, it prints an error message and kills Emacs. */
original error handler. */
XGetErrorText (display, error->error_code, buf, sizeof (buf));
- sprintf (buf1, "X protocol error: %s on protocol request %d",
+ sprintf (buf1, "X protocol error: %s on protocol request %d\n",
buf, error->request_code);
x_connection_closed (display, buf1);
}
x_connection_closed (display, buf);
}
\f
+/* Handle SIGPIPE, which can happen when the connection to a server
+ simply goes away. SIGPIPE is handled by x_connection_signal.
+ It works by sending a no-op command to each X server connection.
+ When we try a connection that has closed, we get SIGPIPE again.
+ But this time, it is handled by x_connection_signal_1.
+ That function knows which connection we were testing,
+ so it closes that one.
+
+ x_connection_closed never returns,
+ so if more than one connection was lost at once,
+ we only find one. But XTread_socket keeps trying them all,
+ so it will notice the other closed one sooner or later. */
+
+
+static struct x_display_info *x_connection_signal_dpyinfo;
+
+static SIGTYPE x_connection_signal ();
+
+static SIGTYPE
+x_connection_signal_1 (signalnum) /* If we don't have an argument, */
+ int signalnum; /* some compilers complain in signal calls. */
+{
+ signal (SIGPIPE, x_connection_signal);
+ x_connection_closed (x_connection_signal_dpyinfo,
+ "connection was lost");
+}
+
+static SIGTYPE
+x_connection_signal (signalnum) /* If we don't have an argument, */
+ int signalnum; /* some compilers complain in signal calls. */
+{
+ x_connection_signal_dpyinfo = x_display_list;
+
+ sigunblock (SIGPIPE);
+
+ while (x_connection_signal_dpyinfo)
+ {
+ signal (SIGPIPE, x_connection_signal_1);
+
+ x_connection_close_if_hung (x_connection_signal_dpyinfo);
+
+ XNoOp (x_connection_signal_dpyinfo->display);
+
+ XSync (x_connection_signal_dpyinfo->display, False);
+
+ /* Each time we get here, cycle through the displays now open. */
+ x_connection_signal_dpyinfo = x_connection_signal_dpyinfo->next;
+ }
+
+ /* We should have found some closed connection. */
+ abort ();
+}
+\f
/* A buffer for storing X error messages. */
static char *x_caught_error_message;
#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
}
}
\f
+/* Calculate the absolute position in frame F
+ from its current recorded position values and gravity. */
+
x_calc_absolute_position (f)
struct frame *f;
{
position that fits on the screen. */
if (flags & XNegative)
f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
- - 2 * f->output_data.x->border_width - win_x
- - PIXEL_WIDTH (f)
- + f->output_data.x->left_pos);
+ - 2 * f->output_data.x->border_width - win_x
+ - PIXEL_WIDTH (f)
+ + f->output_data.x->left_pos);
if (flags & YNegative)
+ /* We used to subtract f->output_data.x->menubar_height here
+ in the toolkit case, but PIXEL_HEIGHT already includes that. */
f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
- - 2 * f->output_data.x->border_width - win_y
- - PIXEL_HEIGHT (f)
- - (FRAME_EXTERNAL_MENU_BAR (f)
- ? f->output_data.x->menubar_height : 0)
- + f->output_data.x->top_pos);
+ - 2 * f->output_data.x->border_width - win_y
+ - PIXEL_HEIGHT (f)
+ + f->output_data.x->top_pos);
+
/* The left_pos and top_pos
are now relative to the top and left screen edges,
so the flags should correspond. */
{
int pixelwidth, pixelheight;
int mask;
+ Lisp_Object window;
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-#ifdef USE_X_TOOLKIT
BLOCK_INPUT;
+
+#ifdef USE_X_TOOLKIT
{
/* The x and y position of the widget is clobbered by the
call to XtSetValues within EmacsFrameSetCharSize.
f->output_data.x->widget->core.x = xpos;
f->output_data.x->widget->core.y = ypos;
}
- UNBLOCK_INPUT;
#else /* not USE_X_TOOLKIT */
- BLOCK_INPUT;
-
check_frame_size (f, &rows, &cols);
f->output_data.x->vertical_scroll_bar_extra
= (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
PIXEL_WIDTH (f) = pixelwidth;
PIXEL_HEIGHT (f) = pixelheight;
+ /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
+ receive in the ConfigureNotify event; if we get what we asked
+ for, then the event won't cause the screen to become garbaged, so
+ we have to make sure to do it here. */
+ SET_FRAME_GARBAGED (f);
+
+ XFlush (FRAME_X_DISPLAY (f));
+
+#endif /* not USE_X_TOOLKIT */
+
/* If cursor was outside the new size, mark it as off. */
if (f->phys_cursor_y >= rows
|| f->phys_cursor_x >= cols)
f->phys_cursor_y = -1;
}
- /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
- receive in the ConfigureNotify event; if we get what we asked
- for, then the event won't cause the screen to become garbaged, so
- we have to make sure to do it here. */
- SET_FRAME_GARBAGED (f);
+ /* Clear out any recollection of where the mouse highlighting was,
+ since it might be in a place that's outside the new frame size.
+ Actually checking whether it is outside is a pain in the neck,
+ so don't try--just let the highlighting be done afresh with new size. */
+ window = dpyinfo->mouse_face_window;
+ if (! NILP (window) && XFRAME (window) == f)
+ {
+ dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_window = Qnil;
+ }
- XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
-#endif /* not USE_X_TOOLKIT */
}
\f
/* Mouse warping. */
}
static void
-XTframe_raise_lower (f, raise)
+XTframe_raise_lower (f, raise_flag)
FRAME_PTR f;
- int raise;
+ int raise_flag;
{
- if (raise)
+ if (raise_flag)
x_raise_frame (f);
else
x_lower_frame (f);
BLOCK_INPUT;
+ FRAME_SAMPLE_VISIBILITY (f);
+
type = x_icon_type (f);
if (!NILP (type))
x_bitmap_icon (f, type);
BLOCK_INPUT;
- if (f->output_data.x->icon_desc != 0)
- XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
- XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
+ /* If a display connection is dead, don't try sending more
+ commands to the X server. */
+ if (dpyinfo->display != 0)
+ {
+ if (f->output_data.x->icon_desc != 0)
+ XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
+#ifdef HAVE_X_I18N
+ if (FRAME_XIM (f))
+ {
+ XDestroyIC (FRAME_XIC (f));
+ XCloseIM (FRAME_XIM (f));
+ }
+#endif
+ XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
#ifdef USE_X_TOOLKIT
- XtDestroyWidget (f->output_data.x->widget);
- free_frame_menubar (f);
+ XtDestroyWidget (f->output_data.x->widget);
+ free_frame_menubar (f);
#endif /* USE_X_TOOLKIT */
- free_frame_faces (f);
- XFlush (FRAME_X_DISPLAY (f));
+ free_frame_faces (f);
+ XFlush (FRAME_X_DISPLAY (f));
+ }
xfree (f->output_data.x);
f->output_data.x = 0;
f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
}
else
- f->output_data.x->wm_hints.icon_pixmap = None;
+ {
+ /* It seems there is no way to turn off use of an icon pixmap.
+ The following line does it, only if no icon has yet been created,
+ for some window managers. But with mwm it crashes.
+ Some people say it should clear the IconPixmapHint bit in this case,
+ but that doesn't work, and the X consortium said it isn't the
+ right thing at all. Since there is no way to win,
+ best to explicitly give up. */
+#if 0
+ f->output_data.x->wm_hints.icon_pixmap = None;
+#else
+ return;
+#endif
+ }
f->output_data.x->wm_hints.flags |= IconPixmapHint;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
x_initialized = 1;
}
+#ifdef HAVE_X_I18N
+ setlocale (LC_ALL, "");
+#endif
+
#ifdef USE_X_TOOLKIT
/* weiner@footloose.sps.mot.com reports that this causes
errors with X11R5:
tail->next = tail->next->next;
}
-#ifndef USE_X_TOOLKIT
- /* I'm told Xt does this itself. */
+#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
+#ifndef AIX /* On AIX, XCloseDisplay calls this. */
XrmDestroyDatabase (dpyinfo->xrdb);
#endif
+#endif
#ifdef MULTI_KBOARD
if (--dpyinfo->kboard->reference_count == 0)
delete_kboard (dpyinfo->kboard);
staticpro (&Qvendor_specific_keysyms);
Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
}
-#endif /* ! defined (HAVE_X_WINDOWS) */
+\f
+/* Avoid warnings or errors from including Xlibint.h.
+ We don't need these functions for the rest of this file. */
+#undef bzero
+#undef bcopy
+#undef bcmp
+#undef min
+#undef max
+
+#ifdef X_CONNECTION_LOCK_FLAG
+#define free loserfree
+#define malloc losermalloc
+#define exit loserexit
+#define abort loserabort
+/* For XlibDisplayWriting */
+#include <X11/Xlibint.h>
+#endif
+
+/* Check whether display connection DPYINFO is hung
+ because its thread-interlock is locked.
+ If it is, close the connection.
+ Do nothing if this system does not have a thread interlock. */
+
+x_connection_close_if_hung (dpyinfo)
+ struct x_display_info *dpyinfo;
+{
+ /* This tests (1) whether X_CONNECTION_LOCK_FLAG is defined at all,
+ and (2) whether the name it is defined as is itself defined.
+ (It ought to have been defined by Xlibint.h. */
+#if X_CONNECTION_LOCK_FLAG
+
+ if (dpyinfo->display->flags & X_CONNECTION_LOCK_FLAG)
+ {
+ /* If the thread-interlock is locked, assume this connection is dead.
+ This assumes that the library does not make other threads
+ that can be locking the display legitimately. */
+
+ dpyinfo->display->flags &= ~X_CONNECTION_LOCK_FLAG;
+ x_connection_closed (dpyinfo->display, "connection was lost");
+ }
+#endif /* X_CONNECTION_LOCK_FLAG */
+}
+
+/* Don't put any additional functions here! */
+
+#endif /* not HAVE_X_WINDOWS */