/* 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 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006 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, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* New display code by Gerd Moellmann <gerd@gnu.org>. */
/* Xt features made by Fred Pierresteguy. */
#ifdef HAVE_XAW3D
#include <X11/Xaw3d/Simple.h>
#include <X11/Xaw3d/Scrollbar.h>
-#define ARROW_SCROLLBAR
-#define XAW_ARROW_SCROLLBARS
-#include <X11/Xaw3d/ScrollbarP.h>
+#include <X11/Xaw3d/ThreeD.h>
#else /* !HAVE_XAW3D */
#include <X11/Xaw/Simple.h>
#include <X11/Xaw/Scrollbar.h>
/* Where the mouse was last time we reported a mouse event. */
static XRectangle last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
static Lisp_Object last_mouse_press_frame;
/* The scroll bar in which the last X motion event occurred.
static const XColor *x_color_cells P_ ((Display *, int *));
static void x_update_window_end P_ ((struct window *, int, int));
void x_delete_display P_ ((struct x_display_info *));
-static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
- unsigned));
+
static int x_io_error_quitter P_ ((Display *));
-int x_catch_errors P_ ((Display *));
-void x_uncatch_errors P_ ((Display *, int));
+void x_catch_errors P_ ((Display *));
+void x_uncatch_errors P_ ((void));
void x_lower_frame P_ ((struct frame *));
void x_scroll_bar_clear P_ ((struct frame *));
int x_had_errors_p P_ ((Display *));
int x, y0, y1;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct face *face;
+
+ face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+ if (face)
+ XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+ face->foreground);
XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->normal_gc, x, y0, x, y1);
/* It's a program. */
struct ccl_program *ccl = font_info->font_encoder;
+ check_ccl_update (ccl);
if (CHARSET_DIMENSION (charset) == 1)
{
ccl->reg[0] = charset;
XDrawImageString is usually faster than XDrawString.) Always
use XDrawImageString when drawing the cursor so that there is
no chance that characters under a box cursor are invisible. */
- if (s->for_overlaps_p
+ if (s->for_overlaps
|| (s->background_filled_p && s->hl != DRAW_CURSOR))
{
/* Draw characters with 16-bit or 8-bit functions. */
/* If S draws into the background of its successor, draw the
background of the successor first so that S can draw into it.
This makes S->next use XDrawString instead of XDrawImageString. */
- if (s->next && s->right_overhang && !s->for_overlaps_p)
+ if (s->next && s->right_overhang && !s->for_overlaps)
{
xassert (s->next->img == NULL);
x_set_glyph_string_gc (s->next);
/* Draw relief (if any) in advance for char/composition so that the
glyph string can be drawn over it. */
- if (!s->for_overlaps_p
+ if (!s->for_overlaps
&& s->face->box != FACE_NO_BOX
&& (s->first_glyph->type == CHAR_GLYPH
|| s->first_glyph->type == COMPOSITE_GLYPH))
break;
case CHAR_GLYPH:
- if (s->for_overlaps_p)
+ if (s->for_overlaps)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 0);
break;
case COMPOSITE_GLYPH:
- if (s->for_overlaps_p || s->gidx > 0)
+ if (s->for_overlaps || s->gidx > 0)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 1);
abort ();
}
- if (!s->for_overlaps_p)
+ if (!s->for_overlaps)
{
/* Draw underline. */
if (s->face->underline_p)
/* Convert between the modifier bits X uses and the modifier bits
Emacs uses. */
-static unsigned int
+unsigned int
x_x_to_emacs_modifiers (dpyinfo, state)
struct x_display_info *dpyinfo;
unsigned int state;
static XMotionEvent last_mouse_motion_event;
static Lisp_Object last_mouse_motion_frame;
-static void
+static int
note_mouse_movement (frame, event)
FRAME_PTR frame;
XMotionEvent *event;
last_mouse_motion_event = *event;
XSETFRAME (last_mouse_motion_frame, frame);
+ if (!FRAME_X_OUTPUT (frame))
+ return 0;
+
if (event->window != FRAME_X_WINDOW (frame))
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, -1, -1);
+ last_mouse_glyph_frame = 0;
+ return 1;
}
+
/* Has the mouse moved off the glyph it was on at the last sighting? */
- else if (event->x < last_mouse_glyph.x
- || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
- || event->y < last_mouse_glyph.y
- || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+ if (frame != last_mouse_glyph_frame
+ || event->x < last_mouse_glyph.x
+ || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
+ || event->y < last_mouse_glyph.y
+ || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, event->x, event->y);
+ /* Remember which glyph we're now on. */
+ remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
+ last_mouse_glyph_frame = frame;
+ return 1;
}
+
+ return 0;
}
\f
}
-static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
-
-
-/* Try to determine frame pixel position and size of the glyph under
- frame pixel coordinates X/Y on frame F . Return the position and
- size in *RECT. Value is non-zero if we could compute these
- values. */
-
-static int
-glyph_rect (f, x, y, rect)
- struct frame *f;
- int x, y;
- XRectangle *rect;
-{
- Lisp_Object window;
- struct window *w;
- struct glyph_row *r, *end_row;
-
- window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
- if (NILP (window))
- return 0;
-
- w = XWINDOW (window);
- r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
- end_row = r + w->current_matrix->nrows - 1;
-
- for (; r < end_row && r->enabled_p; ++r)
- {
- if (r->y >= y)
- {
- struct glyph *g = r->glyphs[TEXT_AREA];
- struct glyph *end = g + r->used[TEXT_AREA];
- int gx = r->x;
- while (g < end && gx < x)
- gx += g->pixel_width, ++g;
- if (g < end)
- {
- rect->width = g->pixel_width;
- rect->height = r->height;
- rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
- rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
- return 1;
- }
- break;
- }
- }
-
- return 0;
-}
-
/* Return the current position of the mouse.
*FP should be a frame which indicates which display to ask about.
Window win, child;
int win_x, win_y;
int parent_x = 0, parent_y = 0;
- int count;
win = root;
structure is changing at the same time this function
is running. So at least we must not crash from them. */
- count = x_catch_errors (FRAME_X_DISPLAY (*fp));
+ x_catch_errors (FRAME_X_DISPLAY (*fp));
if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
f1 = 0;
- x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
+ x_uncatch_errors ();
/* If not, is it one of our scroll bars? */
if (! f1)
on it, i.e. into the same rectangles that matrices on
the frame are divided into. */
- int width, height, gx, gy;
- XRectangle rect;
-
- if (glyph_rect (f1, win_x, win_y, &rect))
- last_mouse_glyph = rect;
- else
- {
- width = FRAME_SMALLEST_CHAR_WIDTH (f1);
- height = FRAME_SMALLEST_FONT_HEIGHT (f1);
- gx = win_x;
- gy = win_y;
-
- /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
- round down even for negative values. */
- if (gx < 0)
- gx -= width - 1;
- if (gy < 0)
- gy -= height - 1;
- gx = (gx + width - 1) / width * width;
- gy = (gy + height - 1) / height * height;
-
- last_mouse_glyph.width = width;
- last_mouse_glyph.height = height;
- last_mouse_glyph.x = gx;
- last_mouse_glyph.y = gy;
- }
+ remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
+ last_mouse_glyph_frame = f1;
*bar_window = Qnil;
*part = 0;
static Boolean xaw3d_pick_top;
-extern void set_vertical_scroll_bar P_ ((struct window *));
-
/* Action hook installed via XtAppAddActionHook when toolkit scroll
bars are used.. The hook is responsible for detecting when
the user ends an interaction with the scroll bar, and generates
f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
}
+#ifdef XtNbeNiceToColormap
/* Tell the toolkit about them. */
if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
|| f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
if (pixel != -1)
{
- XtSetArg (av[ac], "topShadowPixel", pixel);
+ XtSetArg (av[ac], XtNtopShadowPixel, pixel);
++ac;
}
pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
if (pixel != -1)
{
- XtSetArg (av[ac], "bottomShadowPixel", pixel);
+ XtSetArg (av[ac], XtNbottomShadowPixel, pixel);
++ac;
}
}
+#endif
widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
f->output_data.x->edit_widget, av, ac);
char *initial = "";
char *val = initial;
XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
+#ifdef XtNarrowScrollbars
+ XtNarrowScrollbars, (XtPointer) &xaw3d_arrow_scroll,
+#endif
XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
- if (val == initial)
+ if (xaw3d_arrow_scroll || val == initial)
{ /* ARROW_SCROLL */
xaw3d_arrow_scroll = True;
- /* Isn't that just a personal preference ? -sm */
+ /* Isn't that just a personal preference ? --Stef */
XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
}
}
XawScrollbarSetThumb (widget, top, shown);
else
{
-#ifdef HAVE_XAW3D
- ScrollbarWidget sb = (ScrollbarWidget) widget;
- int scroll_mode = 0;
-
- /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
- if (xaw3d_arrow_scroll)
- {
- /* Xaw3d stupidly ignores resize requests while dragging
- so we have to make it believe it's not in dragging mode. */
- scroll_mode = sb->scrollbar.scroll_mode;
- if (scroll_mode == 2)
- sb->scrollbar.scroll_mode = 0;
- }
-#endif
/* Try to make the scrolling a tad smoother. */
if (!xaw3d_pick_top)
shown = min (shown, old_shown);
XawScrollbarSetThumb (widget, top, shown);
-
-#ifdef HAVE_XAW3D
- if (xaw3d_arrow_scroll && scroll_mode == 2)
- sb->scrollbar.scroll_mode = scroll_mode;
-#endif
}
}
}
f->output_data.x->saved_menu_event \
= (XEvent *) xmalloc (sizeof (XEvent)); \
bcopy (&event, f->output_data.x->saved_menu_event, size); \
- inev.kind = MENU_BAR_ACTIVATE_EVENT; \
- XSETFRAME (inev.frame_or_window, f); \
+ inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
+ XSETFRAME (inev.ie.frame_or_window, f); \
} \
while (0)
int *finish;
struct input_event *hold_quit;
{
- struct input_event inev;
+ union {
+ struct input_event ie;
+ struct selection_input_event sie;
+ } inev;
int count = 0;
int do_help = 0;
int nbytes = 0;
*finish = X_EVENT_NORMAL;
- EVENT_INIT (inev);
- inev.kind = NO_EVENT;
- inev.arg = Qnil;
+ EVENT_INIT (inev.ie);
+ inev.ie.kind = NO_EVENT;
+ inev.ie.arg = Qnil;
switch (event.type)
{
Display *d = event.xclient.display;
/* Catch and ignore errors, in case window has been
iconified by a window manager such as GWM. */
- int count = x_catch_errors (d);
+ x_catch_errors (d);
XSetInputFocus (d, event.xclient.window,
/* The ICCCM says this is
the only valid choice. */
/* This is needed to detect the error
if there is an error. */
XSync (d, False);
- x_uncatch_errors (d, count);
+ x_uncatch_errors ();
}
/* Not certain about handling scroll bars here */
#endif /* 0 */
if (!f)
goto OTHER; /* May be a dialog that is to be removed */
- inev.kind = DELETE_WINDOW_EVENT;
- XSETFRAME (inev.frame_or_window, f);
+ inev.ie.kind = DELETE_WINDOW_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
goto done;
}
if (event.xclient.message_type
== dpyinfo->Xatom_Scrollbar)
{
- x_scroll_bar_to_input_event (&event, &inev);
+ x_scroll_bar_to_input_event (&event, &inev.ie);
*finish = X_EVENT_GOTO_OUT;
goto done;
}
if (!f)
goto OTHER;
- if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev))
+ if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
*finish = X_EVENT_DROP;
}
break;
{
XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
- inev.kind = SELECTION_CLEAR_EVENT;
- SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
- SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
- SELECTION_EVENT_TIME (&inev) = eventp->time;
- inev.frame_or_window = Qnil;
+ inev.ie.kind = SELECTION_CLEAR_EVENT;
+ SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+ SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+ SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+ inev.ie.frame_or_window = Qnil;
}
break;
XSelectionRequestEvent *eventp
= (XSelectionRequestEvent *) &event;
- inev.kind = SELECTION_REQUEST_EVENT;
- SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
- SELECTION_EVENT_REQUESTOR (&inev) = eventp->requestor;
- SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
- SELECTION_EVENT_TARGET (&inev) = eventp->target;
- SELECTION_EVENT_PROPERTY (&inev) = eventp->property;
- SELECTION_EVENT_TIME (&inev) = eventp->time;
- inev.frame_or_window = Qnil;
+ inev.ie.kind = SELECTION_REQUEST_EVENT;
+ SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+ SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
+ SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+ SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
+ SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
+ SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+ inev.ie.frame_or_window = Qnil;
}
break;
{
f->async_iconified = 1;
- inev.kind = ICONIFY_EVENT;
- XSETFRAME (inev.frame_or_window, f);
+ inev.ie.kind = ICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
}
}
goto OTHER;
if (f->iconified)
{
- inev.kind = DEICONIFY_EVENT;
- XSETFRAME (inev.frame_or_window, f);
+ inev.ie.kind = DEICONIFY_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
}
else if (! NILP (Vframe_list)
&& ! NILP (XCDR (Vframe_list)))
f = x_any_window_to_frame (dpyinfo, event.xkey.window);
- if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+ if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+ && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_hidden = 1;
if (status_return == XBufferOverflow)
{
copy_bufsiz = nbytes + 1;
- copy_bufptr = (char *) alloca (copy_bufsiz);
+ copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
nbytes = XmbLookupString (FRAME_XIC (f),
&event.xkey, copy_bufptr,
copy_bufsiz, &keysym,
if (status_return == XBufferOverflow)
{
copy_bufsiz = nbytes + 1;
- copy_bufptr = (char *) alloca (copy_bufsiz);
+ copy_bufptr = (unsigned char *) alloca (copy_bufsiz);
nbytes = Xutf8LookupString (FRAME_XIC (f),
&event.xkey,
copy_bufptr,
if (compose_status.chars_matched > 0 && nbytes == 0)
break;
+ bzero (&compose_status, sizeof (compose_status));
orig_keysym = keysym;
/* Common for all keysym input events. */
- XSETFRAME (inev.frame_or_window, f);
- inev.modifiers
+ XSETFRAME (inev.ie.frame_or_window, f);
+ inev.ie.modifiers
= x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
- inev.timestamp = event.xkey.time;
+ 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.kind = ASCII_KEYSTROKE_EVENT;
- inev.code = keysym;
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
+ goto done_keysym;
+ }
+
+ /* Keysyms directly mapped to supported Unicode characters. */
+ if ((keysym >= 0x01000000 && keysym <= 0x010033ff)
+ || (keysym >= 0x0100e000 && keysym <= 0x0100ffff))
+ {
+ int code = keysym & 0xFFFF, charset_id, c1, c2;
+
+ if (code < 0x80)
+ {
+ inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = code;
+ }
+ else if (code < 0x100)
+ {
+ if (code < 0xA0)
+ charset_id = CHARSET_8_BIT_CONTROL;
+ else
+ charset_id = charset_latin_iso8859_1;
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.code = MAKE_CHAR (charset_id, code, 0);
+ }
+ else
+ {
+ if (code < 0x2500)
+ charset_id = charset_mule_unicode_0100_24ff,
+ code -= 0x100;
+ else if (code < 0xE000)
+ charset_id = charset_mule_unicode_2500_33ff,
+ code -= 0x2500;
+ else
+ charset_id = charset_mule_unicode_e000_ffff,
+ code -= 0xE000;
+ c1 = (code / 96) + 32, c2 = (code % 96) + 32;
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.code = MAKE_CHAR (charset_id, c1, c2);
+ }
goto done_keysym;
}
Vx_keysym_table,
Qnil))))
{
- inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.code = XFASTINT (c);
+ inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+ ? ASCII_KEYSTROKE_EVENT
+ : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ inev.ie.code = XFASTINT (c);
goto done_keysym;
}
STORE_KEYSYM_FOR_DEBUG (keysym);
/* make_lispy_event will convert this to a symbolic
key. */
- inev.kind = NON_ASCII_KEYSTROKE_EVENT;
- inev.code = keysym;
+ inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
+ inev.ie.code = keysym;
goto done_keysym;
}
else
c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
nbytes - i, len);
- inev.kind = (SINGLE_BYTE_CHAR_P (c)
+ inev.ie.kind = (SINGLE_BYTE_CHAR_P (c)
? ASCII_KEYSTROKE_EVENT
: MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.code = c;
- kbd_buffer_store_event_hold (&inev, hold_quit);
+ 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;
- inev.kind = NO_EVENT; /* Already stored above. */
+ inev.ie.kind = NO_EVENT; /* Already stored above. */
if (keysym == NoSymbol)
break;
#endif
case EnterNotify:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
so update things that depend on mouse position. */
if (f && !f->output_data.x->hourglass_p)
note_mouse_movement (f, &event.xmotion);
+#ifdef USE_GTK
+ /* 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);
+#endif
goto OTHER;
case FocusIn:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
goto OTHER;
case LeaveNotify:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
if (f)
if (any_help_event_p)
do_help = -1;
}
+#ifdef USE_GTK
+ /* See comment in EnterNotify above */
+ else if (last_mouse_glyph_frame)
+ note_mouse_movement (last_mouse_glyph_frame, &event);
+#endif
goto OTHER;
case FocusOut:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
goto OTHER;
case MotionNotify:
{
previous_help_echo_string = help_echo_string;
- help_echo_string = help_echo_object = help_echo_window = Qnil;
- help_echo_pos = -1;
+ help_echo_string = Qnil;
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
&& !EQ (window, last_window)
&& !EQ (window, selected_window))
{
- inev.kind = SELECT_WINDOW_EVENT;
- inev.frame_or_window = window;
+ inev.ie.kind = SELECT_WINDOW_EVENT;
+ inev.ie.frame_or_window = window;
}
last_window=window;
}
- note_mouse_movement (f, &event.xmotion);
+ if (!note_mouse_movement (f, &event.xmotion))
+ help_echo_string = previous_help_echo_string;
}
else
{
int tool_bar_p = 0;
bzero (&compose_status, sizeof (compose_status));
+ last_mouse_glyph_frame = 0;
if (dpyinfo->grabbed
&& last_mouse_frame
&& (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
{
ignore_next_mouse_click_timeout = 0;
- construct_mouse_click (&inev, &event, f);
+ construct_mouse_click (&inev.ie, &event.xbutton, f);
}
if (event.type == ButtonRelease)
ignore_next_mouse_click_timeout = 0;
}
else
- construct_mouse_click (&inev, &event, f);
+ construct_mouse_click (&inev.ie, &event.xbutton, f);
}
}
}
scroll bars. */
if (bar && event.xbutton.state & ControlMask)
{
- x_scroll_bar_handle_click (bar, &event, &inev);
+ x_scroll_bar_handle_click (bar, &event, &inev.ie);
*finish = X_EVENT_DROP;
}
#else /* not USE_TOOLKIT_SCROLL_BARS */
if (bar)
- x_scroll_bar_handle_click (bar, &event, &inev);
+ x_scroll_bar_handle_click (bar, &event, &inev.ie);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
{
dpyinfo->grabbed |= (1 << event.xbutton.button);
last_mouse_frame = f;
- /* Ignore any mouse motion that happened
- before this event; any subsequent mouse-movement
- Emacs events should reflect only motion after
- the ButtonPress. */
- if (f != 0)
- f->mouse_moved = 0;
if (!tool_bar_p)
last_tool_bar_item = -1;
else
dpyinfo->grabbed &= ~(1 << event.xbutton.button);
+ /* Ignore any mouse motion that happened before this event;
+ any subsequent mouse-movement Emacs events should reflect
+ only motion after the ButtonPress/Release. */
+ if (f != 0)
+ f->mouse_moved = 0;
+
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
/* For a down-event in the menu bar,
}
done:
- if (inev.kind != NO_EVENT)
+ if (inev.ie.kind != NO_EVENT)
{
- kbd_buffer_store_event_hold (&inev, hold_quit);
+ kbd_buffer_store_event_hold (&inev.ie, hold_quit);
count++;
}
/* Set clipping, draw the rectangle, and reset clipping again. */
x_clip_to_row (w, row, TEXT_AREA, gc);
- XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
+ XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1);
XSetClipMask (dpy, gc, None);
}
/* Create the GNU bitmap and mask if necessary. */
if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
{
- FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
- = x_create_bitmap_from_data (f, gnu_bits,
- gnu_width, gnu_height);
- x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+ int rc = -1;
+
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+#ifdef USE_GTK
+ if (xg_set_icon_from_xpm_data (f, gnu_xpm_bits))
+ return 0;
+#else
+ rc = x_create_bitmap_from_xpm_data (f, gnu_xpm_bits);
+ if (rc != -1)
+ FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+#endif /* USE_GTK */
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
+ /* If all else fails, use the (black and white) xbm image. */
+ if (rc == -1)
+ {
+ rc = x_create_bitmap_from_data (f, gnu_xbm_bits,
+ gnu_xbm_width, gnu_xbm_height);
+ if (rc == -1)
+ return 1;
+
+ FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id = rc;
+ x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+ }
}
/* The first time we create the GNU bitmap and mask,
#define X_ERROR_MESSAGE_SIZE 200
/* If non-nil, this should be a string.
- It means catch X errors and store the error message in this string. */
+ It means catch X errors and store the error message in this string.
-static Lisp_Object x_error_message_string;
+ The reason we use a stack is that x_catch_error/x_uncatch_error can
+ be called from a signal handler.
+*/
+
+struct x_error_message_stack {
+ char string[X_ERROR_MESSAGE_SIZE];
+ Display *dpy;
+ struct x_error_message_stack *prev;
+};
+static struct x_error_message_stack *x_error_message;
/* An X error handler which stores the error message in
x_error_message_string. This is called from x_error_handler if
XErrorEvent *error;
{
XGetErrorText (display, error->error_code,
- SDATA (x_error_message_string),
+ x_error_message->string,
X_ERROR_MESSAGE_SIZE);
}
Calling x_uncatch_errors resumes the normal error handling. */
void x_check_errors ();
-static Lisp_Object x_catch_errors_unwind ();
-int
+void
x_catch_errors (dpy)
Display *dpy;
{
- int count = SPECPDL_INDEX ();
+ struct x_error_message_stack *data = xmalloc (sizeof (*data));
/* Make sure any errors from previous requests have been dealt with. */
XSync (dpy, False);
- record_unwind_protect (x_catch_errors_unwind,
- Fcons (make_save_value (dpy, 0),
- x_error_message_string));
-
- x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
- SSET (x_error_message_string, 0, 0);
-
- return count;
+ data->dpy = dpy;
+ data->string[0] = 0;
+ data->prev = x_error_message;
+ x_error_message = data;
}
-/* Unbind the binding that we made to check for X errors. */
+/* Undo the last x_catch_errors call.
+ DPY should be the display that was passed to x_catch_errors. */
-static Lisp_Object
-x_catch_errors_unwind (old_val)
- Lisp_Object old_val;
+void
+x_uncatch_errors ()
{
- Lisp_Object first = XCAR (old_val);
- Display *dpy = XSAVE_VALUE (first)->pointer;
+ struct x_error_message_stack *tmp;
+
+ BLOCK_INPUT;
/* The display may have been closed before this function is called.
Check if it is still open before calling XSync. */
- if (x_display_info_for_display (dpy) != 0)
- {
- BLOCK_INPUT;
- XSync (dpy, False);
- UNBLOCK_INPUT;
- }
+ if (x_display_info_for_display (x_error_message->dpy) != 0)
+ XSync (x_error_message->dpy, False);
- x_error_message_string = XCDR (old_val);
- return Qnil;
+ tmp = x_error_message;
+ x_error_message = x_error_message->prev;
+ xfree (tmp);
+ UNBLOCK_INPUT;
}
/* If any X protocol errors have arrived since the last call to
/* Make sure to catch any errors incurred so far. */
XSync (dpy, False);
- if (SREF (x_error_message_string, 0))
- error (format, SDATA (x_error_message_string));
+ if (x_error_message->string[0])
+ {
+ char string[X_ERROR_MESSAGE_SIZE];
+ bcopy (x_error_message->string, string, X_ERROR_MESSAGE_SIZE);
+ x_uncatch_errors ();
+ error (format, string);
+ }
}
/* Nonzero if we had any X protocol errors
/* Make sure to catch any errors incurred so far. */
XSync (dpy, False);
- return SREF (x_error_message_string, 0) != 0;
+ return x_error_message->string[0] != 0;
}
/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
x_clear_errors (dpy)
Display *dpy;
{
- SSET (x_error_message_string, 0, 0);
+ x_error_message->string[0] = 0;
}
-/* Stop catching X protocol errors and let them make Emacs die.
- DPY should be the display that was passed to x_catch_errors.
- COUNT should be the value that was returned by
- the corresponding call to x_catch_errors. */
+/* Close off all unclosed x_catch_errors calls. */
void
-x_uncatch_errors (dpy, count)
- Display *dpy;
- int count;
+x_fully_uncatch_errors ()
+{
+ while (x_error_message)
+ x_uncatch_errors ();
+}
+
+/* Nonzero if x_catch_errors has been done and not yet canceled. */
+
+int
+x_catching_errors ()
{
- unbind_to (count, Qnil);
+ return x_error_message != 0;
}
#if 0
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
Lisp_Object frame, tail;
- int count;
error_msg = (char *) alloca (strlen (error_message) + 1);
strcpy (error_msg, error_message);
below. Otherwise, we might end up with printing ``can't find per
display information'' in the recursive call instead of printing
the original message here. */
- count = x_catch_errors (dpy);
+ 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
if (dpyinfo)
x_delete_display (dpyinfo);
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
if (x_display_list == 0)
{
Display *display;
XErrorEvent *error;
{
- if (! NILP (x_error_message_string))
+ if (x_error_message)
x_error_catcher (display, error);
else
x_error_quitter (display, error);
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. */
-/* It is after x_error_handler so that it won't get inlined in
- x_error_handler. */
+/* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
-static void
+#if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
+#define NO_INLINE __attribute__((noinline))
+#else
+#define NO_INLINE
+#endif
+
+/* Some versions of GNU/Linux define noinline in their headers. */
+
+#ifdef noinline
+#undef noinline
+#endif
+
+/* On older GCC versions, just putting x_error_quitter
+ after x_error_handler prevents inlining into the former. */
+
+static void NO_INLINE
x_error_quitter (display, error)
Display *display;
XErrorEvent *error;
x_calc_absolute_position (f)
struct frame *f;
{
- int win_x = 0, win_y = 0;
int flags = f->size_hint_flags;
/* We have nothing to do if the current position
#endif
}
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
+
+#ifdef USE_GTK
+ {
+ xg_set_frame_icon (f, icon_pixmap, icon_mask);
+ return;
+ }
+
+#elif defined (USE_X_TOOLKIT) /* same as in x_wm_set_window_state. */
{
Arg al[1];
XtSetValues (f->output_data.x->widget, al, 1);
}
-#else /* not USE_X_TOOLKIT */
+#else /* not USE_X_TOOLKIT && not USE_GTK */
f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint);
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-#endif /* not USE_X_TOOLKIT */
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
}
void
= f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
Display *dpy = dpyinfo->display;
int try_XLoadQueryFont = 0;
- int count;
int allow_auto_scaled_font = 0;
if (size < 0)
/* At first, put PATTERN in the cache. */
BLOCK_INPUT;
- count = x_catch_errors (dpy);
+ x_catch_errors (dpy);
if (try_XLoadQueryFont)
{
}
}
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
UNBLOCK_INPUT;
if (names)
XFontStruct *thisinfo;
BLOCK_INPUT;
- count = x_catch_errors (dpy);
+ x_catch_errors (dpy);
thisinfo = XLoadQueryFont (dpy,
SDATA (XCAR (tem)));
if (x_had_errors_p (dpy))
thisinfo = NULL;
x_clear_errors (dpy);
}
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
UNBLOCK_INPUT;
if (thisinfo)
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Lisp_Object font_names;
- int count;
/* Get a list of all the fonts that match this name. Once we
have a list of matching fonts, we compare them against the fonts
fontname = (char *) SDATA (XCAR (font_names));
BLOCK_INPUT;
- count = x_catch_errors (FRAME_X_DISPLAY (f));
+ x_catch_errors (FRAME_X_DISPLAY (f));
font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
if (x_had_errors_p (FRAME_X_DISPLAY (f)))
{
font = NULL;
x_clear_errors (FRAME_X_DISPLAY (f));
}
- x_uncatch_errors (FRAME_X_DISPLAY (f), count);
+ x_uncatch_errors ();
UNBLOCK_INPUT;
if (!font)
return NULL;
static int x_initialized;
+#ifdef HAVE_X_SM
+static int x_session_initialized;
+#endif
+
#ifdef MULTI_KBOARD
/* Test whether two display-name strings agree up to the dot that separates
the screen number from the server number. */
*bits = nr;
}
+int
+x_display_ok (display)
+ const char * display;
+{
+ int dpy_ok = 1;
+ Display *dpy;
+
+ dpy = XOpenDisplay (display);
+ if (dpy)
+ XCloseDisplay (dpy);
+ else
+ dpy_ok = 0;
+ return dpy_ok;
+}
+
struct x_display_info *
x_term_init (display_name, xrm_option, resource_name)
Lisp_Object display_name;
/* Load our own gtkrc if it exists. */
{
- struct gcpro gcpro1, gcpro2;
char *file = "~/.emacs.d/gtkrc";
Lisp_Object s, abs_file;
- GCPRO2 (s, abs_file);
s = make_string (file, strlen (file));
abs_file = Fexpand_file_name (s, Qnil);
if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
gtk_rc_parse (SDATA (abs_file));
-
- UNGCPRO;
}
XSetErrorHandler (x_error_handler);
Display *dpy = dpyinfo->display;
XrmValue d, fr, to;
Font font;
- int count;
d.addr = (XPointer)&dpy;
d.size = sizeof (Display *);
fr.size = sizeof (XtDefaultFont);
to.size = sizeof (Font *);
to.addr = (XPointer)&font;
- count = x_catch_errors (dpy);
+ x_catch_errors (dpy);
if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
abort ();
if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
- x_uncatch_errors (dpy, count);
+ x_uncatch_errors ();
}
#endif
#endif
#ifdef HAVE_X_SM
/* Only do this for the first display. */
- if (x_initialized == 1)
+ if (!x_session_initialized++)
x_session_initialize (dpyinfo);
#endif
last_tool_bar_item = -1;
any_help_event_p = 0;
ignore_next_mouse_click_timeout = 0;
+#ifdef HAVE_X_SM
+ x_session_initialized = 0;
+#endif
#ifdef USE_GTK
current_count = -1;
void
syms_of_xterm ()
{
- staticpro (&x_error_message_string);
- x_error_message_string = Qnil;
+ x_error_message = NULL;
staticpro (&x_display_name_list);
x_display_name_list = Qnil;