/* X Communication module for terminals which understand the X protocol.
- Copyright (C) 1989, 93, 94, 95, 96, 97, 98, 1999, 2000,01,02,03,04
- Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2005 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>
static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
enum text_cursor_kinds));
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
static void x_flush P_ ((struct frame *f));
static void x_update_begin P_ ((struct frame *));
static void x_update_window_begin P_ ((struct window *));
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);
output_cursor.vpos,
output_cursor.x, output_cursor.y);
- x_draw_vertical_border (w);
-
- draw_window_fringes (w);
+ if (draw_window_fringes (w, 1))
+ x_draw_vertical_border (w);
UNBLOCK_INPUT;
}
int oldVH = row->visible_height;
row->visible_height = p->h;
row->y -= rowY - p->y;
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, -1, gc);
row->y = oldY;
row->visible_height = oldVH;
}
else
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, -1, gc);
if (p->bx >= 0 && !p->overlay_p)
{
/* 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;
struct glyph *last_glyph;
XRectangle clip_rect;
- last_x = window_box_right (s->w, s->area);
- if (s->row->full_width_p
- && !s->w->pseudo_window_p)
- {
- last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
- if (s->area != RIGHT_MARGIN_AREA
- || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
- last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
- }
+ last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
+ ? WINDOW_RIGHT_EDGE_X (s->w)
+ : window_box_right (s->w, s->area));
/* The glyph that may have a right box line. */
last_glyph = (s->cmp || s->img
XFlush (FRAME_X_DISPLAY (f));
-#ifdef USE_GTK
- xg_frame_cleared (f);
-#endif
-
UNBLOCK_INPUT;
}
Alt keysyms are on. */
{
int row, col; /* The row and column in the modifier table. */
+ int found_alt_or_meta;
for (row = 3; row < 8; row++)
+ {
+ found_alt_or_meta = 0;
for (col = 0; col < mods->max_keypermod; col++)
{
- KeyCode code
- = mods->modifiermap[(row * mods->max_keypermod) + col];
+ KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col];
/* Zeroes are used for filler. Skip them. */
if (code == 0)
{
case XK_Meta_L:
case XK_Meta_R:
+ found_alt_or_meta = 1;
dpyinfo->meta_mod_mask |= (1 << row);
break;
case XK_Alt_L:
case XK_Alt_R:
+ found_alt_or_meta = 1;
dpyinfo->alt_mod_mask |= (1 << row);
break;
case XK_Hyper_L:
case XK_Hyper_R:
- dpyinfo->hyper_mod_mask |= (1 << row);
+ if (!found_alt_or_meta)
+ dpyinfo->hyper_mod_mask |= (1 << row);
+ code_col = syms_per_code;
+ col = mods->max_keypermod;
break;
case XK_Super_L:
case XK_Super_R:
- dpyinfo->super_mod_mask |= (1 << row);
+ if (!found_alt_or_meta)
+ dpyinfo->super_mod_mask |= (1 << row);
+ code_col = syms_per_code;
+ col = mods->max_keypermod;
break;
case XK_Shift_Lock:
/* Ignore this if it's not on the lock modifier. */
- if ((1 << row) == LockMask)
+ if (!found_alt_or_meta && ((1 << row) == LockMask))
dpyinfo->shift_lock_mask = LockMask;
+ code_col = syms_per_code;
+ col = mods->max_keypermod;
break;
}
}
}
}
+ }
}
/* If we couldn't find any meta keys, accept any alt keys as meta keys. */
{
Lisp_Object tail;
-#ifdef USE_GTK
+#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
-#endif /* USE_GTK */
+#endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */
for (tail = Vframe_list;
XGCTYPE (tail) == Lisp_Cons;
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
int part = -1, whole = 0, portion = 0;
GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (widget));
- if (xg_ignore_gtk_scrollbar) return;
-
position = gtk_adjustment_get_value (adj);
p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
previous = *p;
*p = position;
+ if (xg_ignore_gtk_scrollbar) return;
+
diff = (int) (position - previous);
if (diff == (int) adj->step_increment)
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
}
}
}
top,
left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- max (height, 1),
- left,
- width);
+ max (height, 1));
xg_show_scroll_bar (SCROLL_BAR_X_WINDOW (bar));
#else /* not USE_GTK */
Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
/* Compute the left edge of the scroll bar. */
#ifdef USE_TOOLKIT_SCROLL_BARS
if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
- sb_left = left + width - sb_width - (width - sb_width) / 2;
+ sb_left = (left +
+ (WINDOW_RIGHTMOST_P (w)
+ ? width - sb_width - (width - sb_width) / 2
+ : 0));
else
- sb_left = left + (width - sb_width) / 2;
+ sb_left = (left +
+ (WINDOW_LEFTMOST_P (w)
+ ? (width - sb_width) / 2
+ : width - sb_width));
#else
if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
sb_left = left + width - sb_width;
#ifdef USE_TOOLKIT_SCROLL_BARS
-#ifdef USE_GTK
- if (mask)
- xg_update_scrollbar_pos (f,
- SCROLL_BAR_X_WINDOW (bar),
- top,
- sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
- sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- max (height, 1),
- left,
- width);
-#else /* not USE_GTK */
-
- /* Since toolkit scroll bars are smaller than the space reserved
- for them on the frame, we have to clear "under" them. */
- if (width > 0 && height > 0)
- x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- left, top, width, height, False);
/* Move/size the scroll bar widget. */
if (mask)
+ {
+ /* Since toolkit scroll bars are smaller than the space reserved
+ for them on the frame, we have to clear "under" them. */
+ if (width > 0 && height > 0)
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ left, top, width, height, False);
+#ifdef USE_GTK
+ xg_update_scrollbar_pos (f,
+ SCROLL_BAR_X_WINDOW (bar),
+ top,
+ sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
+ sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM *2,
+ max (height, 1));
+#else /* not USE_GTK */
XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top,
sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
max (height, 1), 0);
-
#endif /* not USE_GTK */
+ }
#else /* not USE_TOOLKIT_SCROLL_BARS */
/* Clear areas not covered by the scroll bar because of
}
\f
-/* Define a queue to save up SelectionRequest events for later handling. */
-
-struct selection_event_queue
- {
- XEvent event;
- struct selection_event_queue *next;
- };
-
-static struct selection_event_queue *queue;
-
-/* Nonzero means queue up certain events--don't process them yet. */
-
-static int x_queue_selection_requests;
-
-/* Queue up an X event *EVENT, to be processed later. */
-
-static void
-x_queue_event (f, event)
- FRAME_PTR f;
- XEvent *event;
-{
- struct selection_event_queue *queue_tmp
- = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
-
- if (queue_tmp != NULL)
- {
- queue_tmp->event = *event;
- queue_tmp->next = queue;
- queue = queue_tmp;
- }
-}
-
-/* Take all the queued events and put them back
- so that they get processed afresh. */
-
-static void
-x_unqueue_events (display)
- Display *display;
-{
- while (queue != NULL)
- {
- struct selection_event_queue *queue_tmp = queue;
- XPutBackEvent (display, &queue_tmp->event);
- queue = queue_tmp->next;
- xfree ((char *)queue_tmp);
- }
-}
-
-/* Start queuing SelectionRequest events. */
-
-void
-x_start_queuing_selection_requests (display)
- Display *display;
-{
- x_queue_selection_requests++;
-}
-
-/* Stop queuing SelectionRequest events. */
-
-void
-x_stop_queuing_selection_requests (display)
- Display *display;
-{
- x_queue_selection_requests--;
- x_unqueue_events (display);
-}
-\f
/* The main X event-reading loop - XTread_socket. */
#if 0
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)
{
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;
if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
goto OTHER;
#endif /* USE_X_TOOLKIT */
- if (x_queue_selection_requests)
- x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
- &event);
- else
- {
+ {
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;
case PropertyNotify:
{
x_check_fullscreen (f);
+#ifdef USE_GTK
+ /* This seems to be needed for GTK 2.6. */
+ x_clear_area (event.xexpose.display,
+ event.xexpose.window,
+ event.xexpose.x, event.xexpose.y,
+ event.xexpose.width, event.xexpose.height,
+ FALSE);
+#endif
if (f->async_visible == 0)
{
f->async_visible = 1;
{
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)))
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;
}
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);
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)
goto OTHER;
case FocusOut:
- x_detect_focus_change (dpyinfo, &event, &inev);
+ x_detect_focus_change (dpyinfo, &event, &inev.ie);
goto OTHER;
case MotionNotify:
&& !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;
&& (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++;
}
mode lines must be clipped to the whole window. */
static void
-x_clip_to_row (w, row, gc)
+x_clip_to_row (w, row, area, gc)
struct window *w;
struct glyph_row *row;
+ int area;
GC gc;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
XRectangle clip_rect;
- int window_y, window_width;
+ int window_x, window_y, window_width;
- window_box (w, -1, 0, &window_y, &window_width, 0);
+ window_box (w, area, &window_x, &window_y, &window_width, 0);
- clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
- clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+ clip_rect.x = window_x;
+ clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
clip_rect.y = max (clip_rect.y, window_y);
clip_rect.width = window_width;
clip_rect.height = row->visible_height;
if (cursor_glyph == NULL)
return;
- /* Compute the width of the rectangle to draw. If on a stretch
- glyph, and `x-stretch-block-cursor' is nil, don't draw a
- rectangle as wide as the glyph, but use a canonical character
- width instead. */
- wd = cursor_glyph->pixel_width - 1;
- if (cursor_glyph->type == STRETCH_GLYPH
- && !x_stretch_cursor_p)
- wd = min (FRAME_COLUMN_WIDTH (f), wd);
- w->phys_cursor_width = wd;
-
- /* Compute frame-relative coordinates from window-relative
- coordinates. */
+ /* Compute frame-relative coordinates for phys cursor. */
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
-
- /* Compute the proper height and ascent of the rectangle, based
- on the actual glyph. Using the full height of the row looks
- bad when there are tall images on that row. */
- h = max (min (FRAME_LINE_HEIGHT (f), row->height),
- cursor_glyph->ascent + cursor_glyph->descent);
- if (h < row->height)
- y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
- h--;
+ y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+ wd = w->phys_cursor_width;
/* The foreground of cursor_gc is typically the same as the normal
background color, which can cause the cursor box to be invisible. */
gc = dpyinfo->scratch_cursor_gc;
/* Set clipping, draw the rectangle, and reset clipping again. */
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc);
XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
XSetClipMask (dpy, gc, None);
}
width = min (cursor_glyph->pixel_width, width);
w->phys_cursor_width = width;
- x_clip_to_row (w, row, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc);
if (kind == BAR_CURSOR)
XFillRectangle (dpy, window, gc,
/* 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)
- XSync (dpy, False);
+ {
+ BLOCK_INPUT;
+ XSync (dpy, False);
+ UNBLOCK_INPUT;
+ }
x_error_message_string = XCDR (old_val);
return Qnil;
error ("%s", error_msg);
}
+/* We specifically use it before defining it, so that gcc doesn't inline it,
+ otherwise gdb doesn't know how to properly put a breakpoint on it. */
+static void x_error_quitter (Display *display, XErrorEvent *error);
+
+/* This is the first-level handler for X protocol errors.
+ It calls x_error_quitter or x_error_catcher. */
+
+static int
+x_error_handler (display, error)
+ Display *display;
+ XErrorEvent *error;
+{
+ if (! NILP (x_error_message_string))
+ x_error_catcher (display, error);
+ else
+ x_error_quitter (display, error);
+ return 0;
+}
/* 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. */
-static void
+/* .gdbinit puts a breakpoint here, so make sure it is not inlined. */
+
+#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;
}
-/* This is the first-level handler for X protocol errors.
- It calls x_error_quitter or x_error_catcher. */
-
-static int
-x_error_handler (display, error)
- Display *display;
- XErrorEvent *error;
-{
- if (! NILP (x_error_message_string))
- x_error_catcher (display, error);
- else
- x_error_quitter (display, error);
- return 0;
-}
-
/* This is the handler for X IO errors, always.
It kills all frames on the display that we lost touch with.
If that was the only one, it prints an error message and kills Emacs. */
FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
FRAME_FONTSET (f) = -1;
- FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+ FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+ FRAME_SPACE_WIDTH (f) = fontp->space_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
compute_fringe_widths (f, 1);
if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
{
FRAME_XIC (f) = NULL;
- if (FRAME_XIC_FONTSET (f))
- {
- XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
- FRAME_XIC_FONTSET (f) = NULL;
- }
+ xic_free_xfontset (f);
}
}
if (! ((flags & XNegative) || (flags & YNegative)))
return;
- /* Find the offsets of the outside upper-left corner of
- the inner window, with respect to the outer window.
- But do this only if we will need the results. */
- if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
- /* This is to get *_pixels_outer_diff. */
- x_real_positions (f, &win_x, &win_y);
-
/* Treat negative positions as relative to the leftmost bottommost
position that fits on the screen. */
if (flags & XNegative)
f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
- - 2 * FRAME_X_OUTPUT (f)->x_pixels_outer_diff
- - FRAME_PIXEL_WIDTH (f)
- + f->left_pos);
+ - FRAME_PIXEL_WIDTH (f) + f->left_pos);
{
int height = FRAME_PIXEL_HEIGHT (f);
#endif
if (flags & YNegative)
- f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
- - FRAME_X_OUTPUT (f)->y_pixels_outer_diff
-
- /* Assume the window manager decorations are the same size on
- three sides, i.e. left, right and bottom. This is to
- compensate for the bottom part. */
- - FRAME_X_OUTPUT (f)->x_pixels_outer_diff
- - height
- + f->top_pos);
+ f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
}
/* The left_pos and top_pos
FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
- x_set_offset (f, expect_left, expect_top, 1);
+ f->left_pos = expect_left;
+ f->top_pos = expect_top;
+ x_set_offset (f, expect_left, expect_top, 0);
}
else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
#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
fontp->name = (char *) xmalloc (strlen (fontname) + 1);
bcopy (fontname, fontp->name, strlen (fontname) + 1);
+ if (font->min_bounds.width == font->max_bounds.width)
+ {
+ /* Fixed width font. */
+ fontp->average_width = fontp->space_width = font->min_bounds.width;
+ }
+ else
+ {
+ XChar2b char2b;
+ XCharStruct *pcm;
+
+ char2b.byte1 = 0x00, char2b.byte2 = 0x20;
+ pcm = x_per_char_metric (font, &char2b, 0);
+ if (pcm)
+ fontp->space_width = pcm->width;
+ else
+ fontp->space_width = FONT_WIDTH (font);
+
+ fontp->average_width
+ = (XGetFontProperty (font, dpyinfo->Xatom_AVERAGE_WIDTH, &value)
+ ? (long) value / 10 : 0);
+ if (fontp->average_width < 0)
+ fontp->average_width = - fontp->average_width;
+ if (fontp->average_width == 0)
+ {
+ if (pcm)
+ {
+ int width = pcm->width;
+ for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
+ if ((pcm = x_per_char_metric (font, &char2b, 0)) != NULL)
+ width += pcm->width;
+ fontp->average_width = width / 95;
+ }
+ else
+ fontp->average_width = FONT_WIDTH (font);
+ }
+ }
+
/* Try to get the full name of FONT. Put it in FULL_NAME. */
full_name = 0;
if (XGetFontProperty (font, XA_FONT, &value))
int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
double pixels = DisplayHeight (dpyinfo->display, screen_number);
double mm = DisplayHeightMM (dpyinfo->display, screen_number);
- dpyinfo->resy = pixels * 25.4 / mm;
+ /* 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);
- dpyinfo->resx = pixels * 25.4 / mm;
+ dpyinfo->resx = (mm < 1) ? 100 : pixels * 25.4 / mm;
}
dpyinfo->Xatom_wm_protocols
/* For properties of font. */
dpyinfo->Xatom_PIXEL_SIZE
= XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
+ dpyinfo->Xatom_AVERAGE_WIDTH
+ = XInternAtom (dpyinfo->display, "AVERAGE_WIDTH", False);
dpyinfo->Xatom_MULE_BASELINE_OFFSET
= XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
x_update_window_end,
x_cursor_to,
x_flush,
-#ifndef XFlush
+#ifdef XFlush
x_flush,
#else
0, /* flush_display_optional */