diff options
| author | Jim Blandy | 1993-01-14 15:34:14 +0000 |
|---|---|---|
| committer | Jim Blandy | 1993-01-14 15:34:14 +0000 |
| commit | 12ba150f2f80f87cf02a6f1ac21bd51a4abf3c8d (patch) | |
| tree | 21aa57098d5266cada9c2bd9957881920e5356e5 /src | |
| parent | cf177271a6a7fc36a9a320484d2561b798fa693a (diff) | |
| download | emacs-12ba150f2f80f87cf02a6f1ac21bd51a4abf3c8d.tar.gz emacs-12ba150f2f80f87cf02a6f1ac21bd51a4abf3c8d.zip | |
Make scrollbar structures into lisp objects, so that they can be
GC'd; this allows windows and scrollbars can refer to each other
without worrying about dangling pointers.
* xterm.h (struct x_display): vertical_scrollbars and
judge_timestamp members deleted.
(struct scrollbar): Redesigned to be a template for a Lisp_Vector.
(SCROLLBAR_VEC_SIZE, XSCROLLBAR, SCROLLBAR_PACK, SCROLLBAR_UNPACK,
SCROLLBAR_X_WINDOW, SET_SCROLLBAR_X_WINDOW,
VERTICAL_SCROLLBAR_INSIDE_WIDTH, VERTICAL_SCROLLBAR_TOP_RANGE,
VERTICAL_SCROLLBAR_INSIDE_HEIGHT, VERTICAL_SCROLLBAR_MIN_HANDLE):
New macros, to help deal with the lispy structures, and deal with
the graphics.
* frame.h (WINDOW_VERTICAL_SCROLLBAR): Macro deleted.
(struct frame): New fields `scrollbars' and
`condemned_scrollbars', for use by the scrollbar implementation.
[MULTI_FRAME and not MULTI_FRAME] (FRAME_SCROLLBARS,
FRAME_CONDEMNED_SCROLLBARS): Accessors for the new field.
* window.h (struct window): Doc fix for vertical_scrollbar field.
* frame.c (make_frame): Initialize the `scrollbars' and
`condemned_scrollbars' fields of the new frame.
* alloc.c (mark_object): Mark the `scrollbars' and
`condemned_scrollbars' slots of frames.
* xterm.c (x_window_to_scrollbar): Scrollbars are chained on
frames' scrollbar field, not their x.display->vertical_scrollbars
field.
(x_scrollbar_create, x_scrollbar_set_handle, x_scrollbar_move,
x_scrollbar_remove, XTset_vertical_scrollbar,
XTcondemn_scrollbars, XTredeem_scrollbar, XTjudge_scrollbars,
x_scrollbar_expose, x_scrollbar_handle_click,
x_scrollbar_handle_motion): Substantially rewritten to correct
typos and brainos, and to accomodate the lispy structures.
* xterm.c (x_scrollbar_background_expose): Function deleted; we
don't want anything in the background there after all.
(XTread_socket): Don't call x_scrollbar_background_expose. We
don't care.
* xterm.h (CHAR_TO_PIXEL_WIDTH, CHAR_TO_PIXEL_HEIGHT,
PIXEL_TO_CHAR_WIDTH, PIXEL_TO_CHAR_HEIGHT): Rewritten, using:
(CHAR_TO_PIXEL_ROW, CHAR_TO_PIXEL_COL, PIXEL_TO_CHAR_ROW,
PIXEL_TO_CHAR_COL): New macros.
* xfns.c [not HAVE_X11] (Fx_create_frame): Use the
PIXEL_TO_CHAR_{HEIGHT,WIDTH} macros to figure the frame's
character size, and the CHAR_TO_PIXEL* macros for vice versa.
* xterm.c (XTwrite_glyphs, XTclear_end_of_line, stufflines,
scraplines, dumprectangle, pixel_to_glyph_coords, x_draw_box,
clear_cursor, x_display_bar_cursor, x_draw_single_glyph,
x_set_mouse_position): Use the CHAR_TO_PIXEL_* macros.
* xterm.c (x_wm_set_size_hint): The max_width and max_height
members of the size_hints are expressed in pixels, not columns.
* xterm.c (x_set_window_size): Remove ibw var; it's not used.
Set FRAME_WIDTH (f) to cols instead of rows. Duh.
* xterm.c (pixel_to_glyph_coords): Properly set *bounds to the
character cell bounding the position, even when the position is
off the frame.
* termhooks.h (mouse_position_hook): Doc fix.
(set_vertical_scrollbar_hook): This doesn't return anything any
more, and doesn't take a struct scrollbar * argument any more.
(condemn_scrollbars_hook, redeem_scrollbar_hook,
judge_scrollbars_hook): Doc fixes.
* term.c (mouse_position_hook): Doc fix.
(set_vertical_scrollbar_hook): This doesn't return
anything any more. Doc fixes.
* keyboard.c (kbd_buffer_get_event): Receive the scrollbar's
window from *mouse_position_hook and pass it to
make_lispy_movement, instead of working with a pointer to a struct
scrollbar.
(make_lispy_event): We don't need a window_from_scrollbar function
anymore; we are given the window directly in *EVENT.
Unify the code which generates
text-area mouse clicks and scrollbar clicks; use the same code to
distinguish clicks from drags on the scrollbar as in the text area.
Distinguish clicks from drags by storing a copy of the lispy
position list returned as part of the event.
(button_down_location): Make this a lisp vector, rather than an
array of random structures.
(struct mouse_position): Remove this; it's been replaced by a lisp
list.
(make_lispy_movement): Accept the scrollbar's window as a
parameter, rather than the scrollbar itself.
If FRAME is zero, assume that the other arguments are garbage.
(syms_of_keyboard): No need to staticpro each window of
button_down_location now; just initialize and staticpro it.
* window.c (window_from_scrollbar): Function deleted; no longer
needed.
* xdisp.c (redisplay_window): Just pass the window to
set_vertical_scrollbar hook; don't pass the scrollbar object too.
* xterm.c (XTmouse_position): Don't return a pointer to the
scrollbar for scrollbar motion; instead, return the scrollbar's
window.
* xterm.c (XTmouse_position): Entirely rewritten, using
XTranslateCoordinates. Call x_scrollbar_report_motion to handle
scrollbar movement events.
(x_scrollbar_report_motion): New function, to help out
XTmouse_position.
* termhooks.h (struct input_event): Replace the frame member with
a Lisp_Object member by the name of frame_or_window. Doc fixes.
Remove the scrollbar member; instead, use frame_or_window to hold the
window whose scrollbar was clicked.
* keyboard.c (kbd_buffer_store_event, kbd_buffer_get_event,
make_lispy_event): Adjust references to frame member of struct
input_event to use frame_or_window now.
* xterm.c (construct_mouse_click, XTread_socket): Same.
* xterm.c (last_mouse_bar, last_mouse_bar_frame, last_mouse_part,
last_mouse_scroll_range_start, last_mouse_scroll_range_end):
Replaced with...
(last_mouse_scrollbar): New variable.
(note_mouse_movement): Clear last_mouse_scrollbar when we have
receieved a new motion.
(syms_of_xterm): Staticpro last_mouse_scrollbar.
* xterm.c (note_mouse_position): Renamed to note_mouse_movement,
because that's what it really does.
(x_scrollbar_handle_motion): Renamed to x_scrollbar_note_movement,
for consistency.
(XTread_socket): Adjusted.
* xterm.c (XTset_scrollbar): Renamed to XTset_vertical_scrollbar.
(x_term_init): Adjusted.
* emacs.c (shut_down_emacs): New function.
(fatal_error_signal, Fkill_emacs): Call it, instead of writing it out.
* xterm.c (x_connection_closed): Call shut_down_emacs instead of
Fkill_emacs; the latter will try to perform operations on the X
server and die a horrible death.
* lisp.h (shut_down_emacs): Add extern declaration for it.
* xterm.c (x_error_quitter): Move the abort call to after we print
the error message. No harm in that.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 1097 |
1 files changed, 621 insertions, 476 deletions
diff --git a/src/xterm.c b/src/xterm.c index d840ff08816..ef74a4a3ac8 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* X Communication module for terminals which understand the X protocol. | 1 | /* X Communication module for terminals which understand the X protocol. |
| 2 | Copyright (C) 1989, 1992 Free Software Foundation, Inc. | 2 | Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| @@ -571,11 +571,9 @@ XTwrite_glyphs (start, len) | |||
| 571 | } | 571 | } |
| 572 | 572 | ||
| 573 | dumpglyphs (f, | 573 | dumpglyphs (f, |
| 574 | (curs_x * FONT_WIDTH (f->display.x->font) | 574 | CHAR_TO_PIXEL_COL (f, curs_x), |
| 575 | + f->display.x->internal_border_width), | 575 | CHAR_TO_PIXEL_ROW (f, curs_y), |
| 576 | (curs_y * FONT_HEIGHT (f->display.x->font) | 576 | start, len, highlight, f->display.x->font); |
| 577 | + f->display.x->internal_border_width), | ||
| 578 | start, len, highlight, f->display.x->font); | ||
| 579 | 577 | ||
| 580 | /* If we drew on top of the cursor, note that it is turned off. */ | 578 | /* If we drew on top of the cursor, note that it is turned off. */ |
| 581 | if (curs_y == f->phys_cursor_y | 579 | if (curs_y == f->phys_cursor_y |
| @@ -628,17 +626,15 @@ XTclear_end_of_line (first_unused) | |||
| 628 | 626 | ||
| 629 | #ifdef HAVE_X11 | 627 | #ifdef HAVE_X11 |
| 630 | XClearArea (x_current_display, FRAME_X_WINDOW (f), | 628 | XClearArea (x_current_display, FRAME_X_WINDOW (f), |
| 631 | curs_x * FONT_WIDTH (f->display.x->font) | 629 | CHAR_TO_PIXEL_COL (f, curs_x), |
| 632 | + f->display.x->internal_border_width, | 630 | CHAR_TO_PIXEL_ROW (f, curs_y), |
| 633 | curs_y * FONT_HEIGHT (f->display.x->font) | ||
| 634 | + f->display.x->internal_border_width, | ||
| 635 | FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), | 631 | FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), |
| 636 | FONT_HEIGHT (f->display.x->font), False); | 632 | FONT_HEIGHT (f->display.x->font), False); |
| 637 | 633 | ||
| 638 | #else /* ! defined (HAVE_X11) */ | 634 | #else /* ! defined (HAVE_X11) */ |
| 639 | XPixSet (FRAME_X_WINDOW (f), | 635 | XPixSet (FRAME_X_WINDOW (f), |
| 640 | curs_x * FONT_WIDTH (f->display.x->font) + f->display.x->internal_border_width, | 636 | CHAR_TO_PIXEL_COL (f, curs_x), |
| 641 | curs_y * FONT_HEIGHT (f->display.x->font) + f->display.x->internal_border_width, | 637 | CHAR_TO_PIXEL_ROW (f, curs_y), |
| 642 | FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), | 638 | FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), |
| 643 | FONT_HEIGHT (f->display.x->font), | 639 | FONT_HEIGHT (f->display.x->font), |
| 644 | f->display.x->background_pixel); | 640 | f->display.x->background_pixel); |
| @@ -843,14 +839,14 @@ stufflines (n) | |||
| 843 | #ifdef HAVE_X11 | 839 | #ifdef HAVE_X11 |
| 844 | XCopyArea (x_current_display, FRAME_X_WINDOW (f), | 840 | XCopyArea (x_current_display, FRAME_X_WINDOW (f), |
| 845 | FRAME_X_WINDOW (f), f->display.x->normal_gc, | 841 | FRAME_X_WINDOW (f), f->display.x->normal_gc, |
| 846 | intborder, topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 842 | intborder, CHAR_TO_PIXEL_ROW (f, topregion), |
| 847 | f->width * FONT_WIDTH (f->display.x->font), | 843 | f->width * FONT_WIDTH (f->display.x->font), |
| 848 | length * FONT_HEIGHT (f->display.x->font), intborder, | 844 | length * FONT_HEIGHT (f->display.x->font), intborder, |
| 849 | newtop * FONT_HEIGHT (f->display.x->font) + intborder); | 845 | CHAR_TO_PIXEL_ROW (f, newtop)); |
| 850 | #else /* ! defined (HAVE_X11) */ | 846 | #else /* ! defined (HAVE_X11) */ |
| 851 | XMoveArea (FRAME_X_WINDOW (f), | 847 | XMoveArea (FRAME_X_WINDOW (f), |
| 852 | intborder, topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 848 | intborder, CHAR_TO_PIXEL_ROW (f, topregion), |
| 853 | intborder, newtop * FONT_HEIGHT (f->display.x->font) + intborder, | 849 | intborder, CHAR_TO_PIXEL_ROW (f, newtop), |
| 854 | f->width * FONT_WIDTH (f->display.x->font), | 850 | f->width * FONT_WIDTH (f->display.x->font), |
| 855 | length * FONT_HEIGHT (f->display.x->font)); | 851 | length * FONT_HEIGHT (f->display.x->font)); |
| 856 | /* Now we must process any ExposeRegion events that occur | 852 | /* Now we must process any ExposeRegion events that occur |
| @@ -867,13 +863,13 @@ stufflines (n) | |||
| 867 | { | 863 | { |
| 868 | #ifdef HAVE_X11 | 864 | #ifdef HAVE_X11 |
| 869 | XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, | 865 | XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, |
| 870 | topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 866 | CHAR_TO_PIXEL_ROW (f, topregion), |
| 871 | f->width * FONT_WIDTH (f->display.x->font), | 867 | f->width * FONT_WIDTH (f->display.x->font), |
| 872 | n * FONT_HEIGHT (f->display.x->font), False); | 868 | n * FONT_HEIGHT (f->display.x->font), False); |
| 873 | #else /* ! defined (HAVE_X11) */ | 869 | #else /* ! defined (HAVE_X11) */ |
| 874 | XPixSet (FRAME_X_WINDOW (f), | 870 | XPixSet (FRAME_X_WINDOW (f), |
| 875 | intborder, | 871 | intborder, |
| 876 | topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 872 | CHAR_TO_PIXEL_ROW (f, topregion), |
| 877 | f->width * FONT_WIDTH (f->display.x->font), | 873 | f->width * FONT_WIDTH (f->display.x->font), |
| 878 | n * FONT_HEIGHT (f->display.x->font), | 874 | n * FONT_HEIGHT (f->display.x->font), |
| 879 | f->display.x->background_pixel); | 875 | f->display.x->background_pixel); |
| @@ -905,12 +901,12 @@ scraplines (n) | |||
| 905 | { | 901 | { |
| 906 | #ifdef HAVE_X11 | 902 | #ifdef HAVE_X11 |
| 907 | XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, | 903 | XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, |
| 908 | curs_y * FONT_HEIGHT (f->display.x->font) + intborder, | 904 | CHAR_TO_PIXEL_ROW (f, curs_y), |
| 909 | f->width * FONT_WIDTH (f->display.x->font), | 905 | f->width * FONT_WIDTH (f->display.x->font), |
| 910 | (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False); | 906 | (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False); |
| 911 | #else /* ! defined (HAVE_X11) */ | 907 | #else /* ! defined (HAVE_X11) */ |
| 912 | XPixSet (FRAME_X_WINDOW (f), | 908 | XPixSet (FRAME_X_WINDOW (f), |
| 913 | intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder, | 909 | intborder, CHAR_TO_PIXEL_ROW (f, curs_y), |
| 914 | f->width * FONT_WIDTH (f->display.x->font), | 910 | f->width * FONT_WIDTH (f->display.x->font), |
| 915 | (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), | 911 | (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), |
| 916 | f->display.x->background_pixel); | 912 | f->display.x->background_pixel); |
| @@ -923,20 +919,20 @@ scraplines (n) | |||
| 923 | XCopyArea (x_current_display, FRAME_X_WINDOW (f), | 919 | XCopyArea (x_current_display, FRAME_X_WINDOW (f), |
| 924 | FRAME_X_WINDOW (f), f->display.x->normal_gc, | 920 | FRAME_X_WINDOW (f), f->display.x->normal_gc, |
| 925 | intborder, | 921 | intborder, |
| 926 | (curs_y + n) * FONT_HEIGHT (f->display.x->font) + intborder, | 922 | CHAR_TO_PIXEL_ROW (f, curs_y + n), |
| 927 | f->width * FONT_WIDTH (f->display.x->font), | 923 | f->width * FONT_WIDTH (f->display.x->font), |
| 928 | (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font), | 924 | (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font), |
| 929 | intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder); | 925 | intborder, CHAR_TO_PIXEL_ROW (f, curs_y)); |
| 930 | XClearArea (x_current_display, FRAME_X_WINDOW (f), | 926 | XClearArea (x_current_display, FRAME_X_WINDOW (f), |
| 931 | intborder, | 927 | intborder, |
| 932 | (flexlines - n) * FONT_HEIGHT (f->display.x->font) + intborder, | 928 | CHAR_TO_PIXEL_ROW (f, flexlines - n), |
| 933 | f->width * FONT_WIDTH (f->display.x->font), | 929 | f->width * FONT_WIDTH (f->display.x->font), |
| 934 | n * FONT_HEIGHT (f->display.x->font), False); | 930 | n * FONT_HEIGHT (f->display.x->font), False); |
| 935 | #else /* ! defined (HAVE_X11) */ | 931 | #else /* ! defined (HAVE_X11) */ |
| 936 | XMoveArea (FRAME_X_WINDOW (f), | 932 | XMoveArea (FRAME_X_WINDOW (f), |
| 937 | intborder, | 933 | intborder, |
| 938 | (curs_y + n) * FONT_HEIGHT (f->display.x->font) + intborder, | 934 | CHAR_TO_PIXEL_ROW (f, curs_y + n), |
| 939 | intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder, | 935 | intborder, CHAR_TO_PIXEL_ROW (f, curs_y), |
| 940 | f->width * FONT_WIDTH (f->display.x->font), | 936 | f->width * FONT_WIDTH (f->display.x->font), |
| 941 | (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font)); | 937 | (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font)); |
| 942 | /* Now we must process any ExposeRegion events that occur | 938 | /* Now we must process any ExposeRegion events that occur |
| @@ -945,7 +941,7 @@ scraplines (n) | |||
| 945 | may want to copy this area to another area. */ | 941 | may want to copy this area to another area. */ |
| 946 | x_read_exposes (); | 942 | x_read_exposes (); |
| 947 | XPixSet (FRAME_X_WINDOW (f), intborder, | 943 | XPixSet (FRAME_X_WINDOW (f), intborder, |
| 948 | (flexlines - n) * FONT_HEIGHT (f->display.x->font) + intborder, | 944 | CHAR_TO_PIXEL_ROW (f, flexlines - n), |
| 949 | f->width * FONT_WIDTH (f->display.x->font), | 945 | f->width * FONT_WIDTH (f->display.x->font), |
| 950 | n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel); | 946 | n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel); |
| 951 | #endif /* ! defined (HAVE_X11) */ | 947 | #endif /* ! defined (HAVE_X11) */ |
| @@ -996,30 +992,31 @@ dumprectangle (f, left, top, cols, rows) | |||
| 996 | if (FRAME_GARBAGED_P (f)) | 992 | if (FRAME_GARBAGED_P (f)) |
| 997 | return; | 993 | return; |
| 998 | 994 | ||
| 999 | top -= f->display.x->internal_border_width; | ||
| 1000 | left -= f->display.x->internal_border_width; | ||
| 1001 | |||
| 1002 | /* Express rectangle as four edges, instead of position-and-size. */ | 995 | /* Express rectangle as four edges, instead of position-and-size. */ |
| 1003 | bottom = top + rows; | 996 | bottom = top + rows; |
| 1004 | right = left + cols; | 997 | right = left + cols; |
| 1005 | 998 | ||
| 1006 | #ifndef HAVE_X11 /* Window manger does this for X11. */ | 999 | #ifndef HAVE_X11 /* Window manger does this for X11. */ |
| 1007 | /* If the rectangle includes any of the internal border area, | 1000 | { |
| 1008 | redisplay the border emphasis. */ | 1001 | int intborder = f->display.x->internal_border_width; |
| 1009 | if (top < 0 || left < 0 | 1002 | |
| 1010 | || bottom > f->height * FONT_HEIGHT (f->display.x->font) | 1003 | /* If the rectangle includes any of the internal border area, |
| 1011 | || right > f->width * FONT_WIDTH (f->display.x->font)) | 1004 | redisplay the border emphasis. */ |
| 1012 | dumpborder (f, 0); | 1005 | if (top < intborder || left < intborder |
| 1006 | || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font) | ||
| 1007 | || right > intborder + f->width * FONT_WIDTH (f->display.x->font)) | ||
| 1008 | dumpborder (f, 0); | ||
| 1009 | } | ||
| 1013 | #endif /* HAVE_X11 /* Window manger does this for X11. */ */ | 1010 | #endif /* HAVE_X11 /* Window manger does this for X11. */ */ |
| 1014 | 1011 | ||
| 1015 | /* Convert rectangle edges in pixels to edges in chars. | 1012 | /* Convert rectangle edges in pixels to edges in chars. |
| 1016 | Round down for left and top, up for right and bottom. */ | 1013 | Round down for left and top, up for right and bottom. */ |
| 1017 | top /= FONT_HEIGHT (f->display.x->font); | 1014 | top = PIXEL_TO_CHAR_ROW (f, top); |
| 1018 | left /= FONT_WIDTH (f->display.x->font); | 1015 | left = PIXEL_TO_CHAR_COL (f, left); |
| 1019 | bottom += (FONT_HEIGHT (f->display.x->font) - 1); | 1016 | bottom += (FONT_HEIGHT (f->display.x->font) - 1); |
| 1020 | right += (FONT_WIDTH (f->display.x->font) - 1); | 1017 | right += (FONT_WIDTH (f->display.x->font) - 1); |
| 1021 | bottom /= FONT_HEIGHT (f->display.x->font); | 1018 | bottom = PIXEL_TO_CHAR_ROW (f, bottom); |
| 1022 | right /= FONT_WIDTH (f->display.x->font); | 1019 | right = PIXEL_TO_CHAR_COL (f, right); |
| 1023 | 1020 | ||
| 1024 | /* Clip the rectangle to what can be visible. */ | 1021 | /* Clip the rectangle to what can be visible. */ |
| 1025 | if (left < 0) | 1022 | if (left < 0) |
| @@ -1058,12 +1055,10 @@ dumprectangle (f, left, top, cols, rows) | |||
| 1058 | continue; | 1055 | continue; |
| 1059 | 1056 | ||
| 1060 | dumpglyphs (f, | 1057 | dumpglyphs (f, |
| 1061 | (left * FONT_WIDTH (f->display.x->font) | 1058 | CHAR_TO_PIXEL_COL (f, left), |
| 1062 | + f->display.x->internal_border_width), | 1059 | CHAR_TO_PIXEL_ROW (f, y), |
| 1063 | (y * FONT_HEIGHT (f->display.x->font) | 1060 | line, min (cols, active_frame->used[y] - left), |
| 1064 | + f->display.x->internal_border_width), | 1061 | active_frame->highlight[y], f->display.x->font); |
| 1065 | line, min (cols, active_frame->used[y] - left), | ||
| 1066 | active_frame->highlight[y], f->display.x->font); | ||
| 1067 | } | 1062 | } |
| 1068 | 1063 | ||
| 1069 | /* Turn the cursor on if we turned it off. */ | 1064 | /* Turn the cursor on if we turned it off. */ |
| @@ -1313,36 +1308,25 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds) | |||
| 1313 | register int *x, *y; | 1308 | register int *x, *y; |
| 1314 | XRectangle *bounds; | 1309 | XRectangle *bounds; |
| 1315 | { | 1310 | { |
| 1316 | int ibw = f->display.x->internal_border_width; | 1311 | pix_x = PIXEL_TO_CHAR_COL (f, pix_x); |
| 1317 | int width, height; | 1312 | pix_y = PIXEL_TO_CHAR_ROW (f, pix_y); |
| 1318 | FONT_TYPE *font = f->display.x->font; | ||
| 1319 | |||
| 1320 | width = FONT_WIDTH (font); | ||
| 1321 | height = FONT_HEIGHT (font); | ||
| 1322 | |||
| 1323 | /* What line is it on? */ | ||
| 1324 | if (pix_y < ibw) | ||
| 1325 | *y = 0; | ||
| 1326 | else if (pix_y > f->display.x->pixel_height - ibw) | ||
| 1327 | *y = FRAME_HEIGHT (f) - 1; | ||
| 1328 | else | ||
| 1329 | *y = (pix_y - ibw) / height; | ||
| 1330 | |||
| 1331 | /* And what column? */ | ||
| 1332 | if (pix_x < ibw) | ||
| 1333 | *x = 0; | ||
| 1334 | else if (pix_x > f->display.x->pixel_width - ibw) | ||
| 1335 | *x = FRAME_WIDTH (f) - 1; | ||
| 1336 | else | ||
| 1337 | *x = (pix_x - ibw) / width; | ||
| 1338 | 1313 | ||
| 1339 | if (bounds) | 1314 | if (bounds) |
| 1340 | { | 1315 | { |
| 1341 | bounds->width = width; | 1316 | bounds->width = FONT_WIDTH (f->display.x->font); |
| 1342 | bounds->height = height; | 1317 | bounds->height = FONT_HEIGHT (f->display.x->font); |
| 1343 | bounds->x = ibw + (*x * width); | 1318 | bounds->x = CHAR_TO_PIXEL_COL (f, pix_x); |
| 1344 | bounds->y = ibw + (*y * height); | 1319 | bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y); |
| 1345 | } | 1320 | } |
| 1321 | |||
| 1322 | if (pix_x < 0) pix_x = 0; | ||
| 1323 | else if (pix_x > f->width) pix_x = f->width; | ||
| 1324 | |||
| 1325 | if (pix_y < 0) pix_y = 0; | ||
| 1326 | else if (pix_y > f->height) pix_y = f->height; | ||
| 1327 | |||
| 1328 | *x = pix_x; | ||
| 1329 | *y = pix_y; | ||
| 1346 | } | 1330 | } |
| 1347 | 1331 | ||
| 1348 | /* Any buttons grabbed. */ | 1332 | /* Any buttons grabbed. */ |
| @@ -1492,7 +1476,7 @@ construct_mouse_click (result, event, f) | |||
| 1492 | pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); | 1476 | pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); |
| 1493 | XFASTINT (result->x) = column; | 1477 | XFASTINT (result->x) = column; |
| 1494 | XFASTINT (result->y) = row; | 1478 | XFASTINT (result->y) = row; |
| 1495 | result->frame = f; | 1479 | XSET (result->frame_or_window, Lisp_Frame, f); |
| 1496 | } | 1480 | } |
| 1497 | } | 1481 | } |
| 1498 | 1482 | ||
| @@ -1520,14 +1504,15 @@ construct_mouse_click (result, event, f) | |||
| 1520 | static FRAME_PTR last_mouse_frame; | 1504 | static FRAME_PTR last_mouse_frame; |
| 1521 | static XRectangle last_mouse_glyph; | 1505 | static XRectangle last_mouse_glyph; |
| 1522 | 1506 | ||
| 1523 | /* If the last-checked mouse motion was in a scrollbar, this is that | 1507 | /* The scrollbar in which the last X motion event occurred. |
| 1524 | scrollbar, the part being dragged, and the limits it is moving in. | 1508 | |
| 1525 | Otherwise, this is zero. */ | 1509 | If the last X motion event occured in a scrollbar, we set this |
| 1526 | static struct scrollbar *last_mouse_bar; | 1510 | so XTmouse_position can know whether to report a scrollbar motion or |
| 1527 | static FRAME_PTR last_mouse_bar_frame; | 1511 | an ordinary motion. |
| 1528 | static enum scrollbar_part last_mouse_part; | 1512 | |
| 1529 | static int last_mouse_scroll_range_start; | 1513 | If the last X motion event didn't occur in a scrollbar, we set this |
| 1530 | static int last_mouse_scroll_range_end; | 1514 | to Qnil, to tell XTmouse_position to return an ordinary motion event. */ |
| 1515 | static Lisp_Object last_mouse_scrollbar; | ||
| 1531 | 1516 | ||
| 1532 | /* This is a hack. We would really prefer that XTmouse_position would | 1517 | /* This is a hack. We would really prefer that XTmouse_position would |
| 1533 | return the time associated with the position it returns, but there | 1518 | return the time associated with the position it returns, but there |
| @@ -1545,7 +1530,7 @@ static Time last_mouse_movement_time; | |||
| 1545 | the mainstream emacs code by setting mouse_moved. If not, ask for | 1530 | the mainstream emacs code by setting mouse_moved. If not, ask for |
| 1546 | another motion event, so we can check again the next time it moves. */ | 1531 | another motion event, so we can check again the next time it moves. */ |
| 1547 | static void | 1532 | static void |
| 1548 | note_mouse_position (frame, event) | 1533 | note_mouse_movement (frame, event) |
| 1549 | FRAME_PTR frame; | 1534 | FRAME_PTR frame; |
| 1550 | XMotionEvent *event; | 1535 | XMotionEvent *event; |
| 1551 | 1536 | ||
| @@ -1557,7 +1542,10 @@ note_mouse_position (frame, event) | |||
| 1557 | || event->x >= last_mouse_glyph.x + last_mouse_glyph.width | 1542 | || event->x >= last_mouse_glyph.x + last_mouse_glyph.width |
| 1558 | || event->y < last_mouse_glyph.y | 1543 | || event->y < last_mouse_glyph.y |
| 1559 | || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) | 1544 | || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) |
| 1560 | mouse_moved = 1; | 1545 | { |
| 1546 | mouse_moved = 1; | ||
| 1547 | last_mouse_scrollbar = Qnil; | ||
| 1548 | } | ||
| 1561 | else | 1549 | else |
| 1562 | { | 1550 | { |
| 1563 | /* It's on the same glyph. Call XQueryPointer so we'll get an | 1551 | /* It's on the same glyph. Call XQueryPointer so we'll get an |
| @@ -1572,97 +1560,141 @@ note_mouse_position (frame, event) | |||
| 1572 | } | 1560 | } |
| 1573 | } | 1561 | } |
| 1574 | 1562 | ||
| 1563 | static struct scrollbar *x_window_to_scrollbar (); | ||
| 1564 | static void x_scrollbar_report_motion (); | ||
| 1565 | |||
| 1575 | /* Return the current position of the mouse. | 1566 | /* Return the current position of the mouse. |
| 1576 | 1567 | ||
| 1568 | If the mouse movement started in a scrollbar, set *f, *bar_window, | ||
| 1569 | and *part to the frame, window, and scrollbar part that the mouse | ||
| 1570 | is over. Set *x and *y to the portion and whole of the mouse's | ||
| 1571 | position on the scrollbar. | ||
| 1572 | |||
| 1573 | If the mouse movement started elsewhere, set *f to the frame the | ||
| 1574 | mouse is on, *bar_window to nil, and *x and *y to the character cell | ||
| 1575 | the mouse is over. | ||
| 1576 | |||
| 1577 | Set *time to the server timestamp for the time at which the mouse | ||
| 1578 | was at this position. | ||
| 1579 | |||
| 1577 | This clears the mouse_moved flag, so we can wait for the next mouse | 1580 | This clears the mouse_moved flag, so we can wait for the next mouse |
| 1578 | position. This also calls XQueryPointer, which will cause the | 1581 | movement. This also calls XQueryPointer, which will cause the |
| 1579 | server to give us another MotionNotify when the mouse moves again. | 1582 | server to give us another MotionNotify when the mouse moves |
| 1580 | */ | 1583 | again. */ |
| 1581 | 1584 | ||
| 1582 | static void | 1585 | static void |
| 1583 | XTmouse_position (f, bar, part, x, y, time) | 1586 | XTmouse_position (f, bar_window, part, x, y, time) |
| 1584 | FRAME_PTR *f; | 1587 | FRAME_PTR *f; |
| 1585 | struct scrollbar **bar; | 1588 | Lisp_Object *bar_window; |
| 1586 | enum scrollbar_part *part; | 1589 | enum scrollbar_part *part; |
| 1587 | Lisp_Object *x, *y; | 1590 | Lisp_Object *x, *y; |
| 1588 | unsigned long *time; | 1591 | unsigned long *time; |
| 1589 | { | 1592 | { |
| 1590 | int ix, iy, dummy; | ||
| 1591 | Display *d = x_current_display; | ||
| 1592 | Window guess, root, child; | ||
| 1593 | |||
| 1594 | BLOCK_INPUT; | 1593 | BLOCK_INPUT; |
| 1595 | 1594 | ||
| 1596 | /* I would like to have an X function that just told me the | 1595 | if (! NILP (last_mouse_scrollbar)) |
| 1597 | innermost window containing the mouse. | 1596 | x_scrollbar_report_motion (f, bar_window, part, x, y, time); |
| 1598 | |||
| 1599 | /* There doesn't seem to be any way to just get the innermost window | ||
| 1600 | containing the pointer, no matter what X frame it's on; you have | ||
| 1601 | to guess a window, and then X will tell you which one of that | ||
| 1602 | window's children it's in. If the pointer isn't in any of that | ||
| 1603 | window's children, it gives you a root window that contains it. | ||
| 1604 | |||
| 1605 | So we start with the selected frame's window and chase down | ||
| 1606 | branches under the guidance of XQueryPointer until we hit a leaf | ||
| 1607 | (all of the Emacs windows we care about are leaf windows). If at | ||
| 1608 | any time XQueryPointer returns false, that means that the current | ||
| 1609 | window does not contain the pointer any more (perhaps it moved), | ||
| 1610 | so we start with the root window XQueryPointer has given us and | ||
| 1611 | start again. */ | ||
| 1612 | |||
| 1613 | guess = FRAME_X_WINDOW (selected_frame); | ||
| 1614 | for (;;) | ||
| 1615 | if (XQueryPointer (d, guess, &root, &child, | ||
| 1616 | &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy)) | ||
| 1617 | { | ||
| 1618 | if (child == None) | ||
| 1619 | /* Guess is a leaf window, and it contains the pointer. */ | ||
| 1620 | break; | ||
| 1621 | else | ||
| 1622 | guess = child; | ||
| 1623 | } | ||
| 1624 | else | ||
| 1625 | /* When XQueryPointer returns False, the pointer isn't in guess | ||
| 1626 | anymore, but root is the root window of the frame we should | ||
| 1627 | try instead. */ | ||
| 1628 | guess = root; | ||
| 1629 | |||
| 1630 | if (last_mouse_bar) | ||
| 1631 | { | ||
| 1632 | *f = last_mouse_bar_frame; | ||
| 1633 | *bar = last_mouse_bar; | ||
| 1634 | *part = last_mouse_part; | ||
| 1635 | |||
| 1636 | if (iy < last_mouse_scroll_range_start) | ||
| 1637 | iy = last_mouse_scroll_range_start; | ||
| 1638 | if (iy > last_mouse_scroll_range_end) | ||
| 1639 | iy = last_mouse_scroll_range_end; | ||
| 1640 | XSETINT (*x, iy - last_mouse_scroll_range_start); | ||
| 1641 | XSETINT (*y, (last_mouse_scroll_range_end | ||
| 1642 | - last_mouse_scroll_range_start)); | ||
| 1643 | } | ||
| 1644 | else | 1597 | else |
| 1645 | { | 1598 | { |
| 1646 | *f = last_mouse_frame = x_window_to_frame (guess); | 1599 | Window root; |
| 1647 | if (! *f) | 1600 | int root_x, root_y; |
| 1648 | *x = *y = Qnil; | ||
| 1649 | else | ||
| 1650 | { | ||
| 1651 | pixel_to_glyph_coords (*f, ix, iy, &ix, &iy, &last_mouse_glyph); | ||
| 1652 | XSET (*x, Lisp_Int, ix); | ||
| 1653 | XSET (*y, Lisp_Int, iy); | ||
| 1654 | } | ||
| 1655 | } | ||
| 1656 | 1601 | ||
| 1657 | mouse_moved = 0; | 1602 | Window dummy_window; |
| 1658 | last_mouse_bar = 0; | 1603 | int dummy; |
| 1604 | |||
| 1605 | mouse_moved = 0; | ||
| 1606 | last_mouse_scrollbar = Qnil; | ||
| 1607 | |||
| 1608 | /* Figure out which root window we're on. */ | ||
| 1609 | XQueryPointer (x_current_display, | ||
| 1610 | DefaultRootWindow (x_current_display), | ||
| 1611 | |||
| 1612 | /* The root window which contains the pointer. */ | ||
| 1613 | &root, | ||
| 1614 | |||
| 1615 | /* Trash which we can't trust if the pointer is on | ||
| 1616 | a different screen. */ | ||
| 1617 | &dummy_window, | ||
| 1618 | |||
| 1619 | /* The position on that root window. */ | ||
| 1620 | &root_x, &root_y, | ||
| 1621 | |||
| 1622 | /* More trash we can't trust. */ | ||
| 1623 | &dummy, &dummy, | ||
| 1624 | |||
| 1625 | /* Modifier keys and pointer buttons, about which | ||
| 1626 | we don't care. */ | ||
| 1627 | (unsigned int *) &dummy); | ||
| 1628 | |||
| 1629 | /* Now we have a position on the root; find the innermost window | ||
| 1630 | containing the pointer. */ | ||
| 1631 | { | ||
| 1632 | Window win, child; | ||
| 1633 | int win_x, win_y; | ||
| 1634 | int parent_x, parent_y; | ||
| 1635 | |||
| 1636 | win = root; | ||
| 1637 | for (;;) | ||
| 1638 | { | ||
| 1639 | XTranslateCoordinates (x_current_display, | ||
| 1640 | |||
| 1641 | /* From-window, to-window. */ | ||
| 1642 | root, win, | ||
| 1643 | |||
| 1644 | /* From-position, to-position. */ | ||
| 1645 | root_x, root_y, &win_x, &win_y, | ||
| 1646 | |||
| 1647 | /* Child of win. */ | ||
| 1648 | &child); | ||
| 1649 | |||
| 1650 | if (child == None) | ||
| 1651 | break; | ||
| 1652 | |||
| 1653 | win = child; | ||
| 1654 | parent_x = win_x; | ||
| 1655 | parent_y = win_y; | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | /* Now we know that: | ||
| 1659 | win is the innermost window containing the pointer | ||
| 1660 | (XTC says it has no child containing the pointer), | ||
| 1661 | win_x and win_y are the pointer's position in it | ||
| 1662 | (XTC did this the last time through), and | ||
| 1663 | parent_x and parent_y are the pointer's position in win's parent. | ||
| 1664 | (They are what win_x and win_y were when win was child. | ||
| 1665 | If win is the root window, it has no parent, and | ||
| 1666 | parent_{x,y} are invalid, but that's okay, because we'll | ||
| 1667 | never use them in that case.) */ | ||
| 1668 | |||
| 1669 | /* Is win one of our frames? */ | ||
| 1670 | *f = x_window_to_frame (win); | ||
| 1671 | |||
| 1672 | /* If not, is it one of our scrollbars? */ | ||
| 1673 | if (! *f) | ||
| 1674 | { | ||
| 1675 | struct scrollbar *bar = x_window_to_scrollbar (win); | ||
| 1676 | |||
| 1677 | if (bar) | ||
| 1678 | { | ||
| 1679 | *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | ||
| 1680 | win_x = parent_x; | ||
| 1681 | win_y = parent_y; | ||
| 1682 | } | ||
| 1683 | } | ||
| 1659 | 1684 | ||
| 1660 | /* I don't know how to find the time for the last movement; it seems | 1685 | if (*f) |
| 1661 | like XQueryPointer ought to return it, but it doesn't. So, we'll | 1686 | { |
| 1662 | return the time of the last MotionNotify event we received. Note | 1687 | pixel_to_glyph_coords (*f, win_x, win_y, &win_x, &win_y, |
| 1663 | that the use of motion hints means that this isn't guaranteed to | 1688 | &last_mouse_glyph); |
| 1664 | be accurate at all. */ | 1689 | |
| 1665 | *time = last_mouse_movement_time; | 1690 | *bar_window = Qnil; |
| 1691 | *part = 0; | ||
| 1692 | XSET (*x, Lisp_Int, win_x); | ||
| 1693 | XSET (*y, Lisp_Int, win_y); | ||
| 1694 | *time = last_mouse_movement_time; | ||
| 1695 | } | ||
| 1696 | } | ||
| 1697 | } | ||
| 1666 | 1698 | ||
| 1667 | UNBLOCK_INPUT; | 1699 | UNBLOCK_INPUT; |
| 1668 | } | 1700 | } |
| @@ -1673,19 +1705,17 @@ XTmouse_position (f, bar, part, x, y, time) | |||
| 1673 | 1705 | ||
| 1674 | /* Scrollbar support. */ | 1706 | /* Scrollbar support. */ |
| 1675 | 1707 | ||
| 1676 | /* Map an X window that implements a scroll bar to the struct | 1708 | /* Given an X window ID, find the struct scrollbar which manages it. */ |
| 1677 | scrollbar representing it. */ | ||
| 1678 | static struct scrollbar * | 1709 | static struct scrollbar * |
| 1679 | x_window_to_scrollbar (window_id) | 1710 | x_window_to_scrollbar (window_id) |
| 1680 | Window window_id; | 1711 | Window window_id; |
| 1681 | { | 1712 | { |
| 1682 | Lisp_Object tail, frame; | 1713 | Lisp_Object tail, frame; |
| 1683 | struct frame *f; | ||
| 1684 | 1714 | ||
| 1685 | for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) | 1715 | for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) |
| 1686 | { | 1716 | { |
| 1687 | struct scrollbar *bar; | ||
| 1688 | Lisp_Object frame = XCONS (tail)->car; | 1717 | Lisp_Object frame = XCONS (tail)->car; |
| 1718 | Lisp_Object bar; | ||
| 1689 | 1719 | ||
| 1690 | /* All elements of Vframe_list should be frames. */ | 1720 | /* All elements of Vframe_list should be frames. */ |
| 1691 | if (XTYPE (frame) != Lisp_Frame) | 1721 | if (XTYPE (frame) != Lisp_Frame) |
| @@ -1693,32 +1723,26 @@ x_window_to_scrollbar (window_id) | |||
| 1693 | 1723 | ||
| 1694 | /* Scan this frame's scrollbar list for a scrollbar with the | 1724 | /* Scan this frame's scrollbar list for a scrollbar with the |
| 1695 | right window ID. */ | 1725 | right window ID. */ |
| 1696 | for (bar = XFRAME (frame)->display.x->vertical_scrollbars; | 1726 | for (bar = FRAME_SCROLLBARS (XFRAME (frame)); |
| 1697 | bar; | 1727 | ! NILP (bar); |
| 1698 | bar = bar->next) | 1728 | bar = XSCROLLBAR(bar)->next) |
| 1699 | if (bar->window == window_id) | 1729 | if (SCROLLBAR_X_WINDOW (XSCROLLBAR (bar)) == window_id) |
| 1700 | return bar; | 1730 | return XSCROLLBAR (bar); |
| 1701 | } | 1731 | } |
| 1702 | 1732 | ||
| 1703 | return 0; | 1733 | return 0; |
| 1704 | } | 1734 | } |
| 1705 | 1735 | ||
| 1706 | 1736 | /* Open a new X window to serve as a scrollbar, and return the | |
| 1707 | /* Open a new X window to serve as a scrollbar. */ | 1737 | scrollbar vector for it. */ |
| 1708 | static struct scrollbar * | 1738 | static struct scrollbar * |
| 1709 | x_scrollbar_create (frame, top, left, width, height) | 1739 | x_scrollbar_create (window, top, left, width, height) |
| 1710 | FRAME_PTR frame; | 1740 | struct window *window; |
| 1711 | int top, left, width, height; | 1741 | int top, left, width, height; |
| 1712 | { | 1742 | { |
| 1713 | struct x_display *d = frame->display.x; | 1743 | FRAME_PTR frame = XFRAME (WINDOW_FRAME (window)); |
| 1714 | |||
| 1715 | /* We can't signal a malloc error from within redisplay, so call | ||
| 1716 | malloc instead of xmalloc. */ | ||
| 1717 | struct scrollbar *bar = | 1744 | struct scrollbar *bar = |
| 1718 | (struct scrollbar *) malloc (sizeof (struct scrollbar)); | 1745 | XSCROLLBAR (Fmake_vector (make_number (SCROLLBAR_VEC_SIZE), Qnil)); |
| 1719 | |||
| 1720 | if (! bar) | ||
| 1721 | return 0; | ||
| 1722 | 1746 | ||
| 1723 | BLOCK_INPUT; | 1747 | BLOCK_INPUT; |
| 1724 | 1748 | ||
| @@ -1726,144 +1750,153 @@ x_scrollbar_create (frame, top, left, width, height) | |||
| 1726 | XSetWindowAttributes a; | 1750 | XSetWindowAttributes a; |
| 1727 | unsigned long mask; | 1751 | unsigned long mask; |
| 1728 | 1752 | ||
| 1729 | a.background_pixel = d->background_pixel; | 1753 | a.background_pixel = frame->display.x->background_pixel; |
| 1730 | a.border_pixel = d->foreground_pixel; | 1754 | a.event_mask = (ButtonPressMask | ButtonReleaseMask |
| 1731 | a.event_mask = (KeyPressMask | 1755 | | ButtonMotionMask |
| 1732 | | ButtonPressMask | ButtonReleaseMask | 1756 | | ExposureMask); |
| 1733 | | ButtonMotionMask); | ||
| 1734 | a.cursor = x_vertical_scrollbar_cursor; | 1757 | a.cursor = x_vertical_scrollbar_cursor; |
| 1735 | 1758 | ||
| 1736 | mask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor); | 1759 | mask = (CWBackPixel | CWEventMask | CWCursor); |
| 1737 | 1760 | ||
| 1738 | bar->window = | 1761 | SET_SCROLLBAR_X_WINDOW |
| 1739 | XCreateWindow (x_current_display, FRAME_X_WINDOW (frame), | 1762 | (bar, |
| 1763 | XCreateWindow (x_current_display, FRAME_X_WINDOW (frame), | ||
| 1740 | 1764 | ||
| 1741 | /* Position and size of scrollbar. */ | 1765 | /* Position and size of scrollbar. */ |
| 1742 | top, left, width, height, | 1766 | left, top, width, height, |
| 1743 | 1767 | ||
| 1744 | /* Border width, depth, class, and visual. */ | 1768 | /* Border width, depth, class, and visual. */ |
| 1745 | 1, CopyFromParent, CopyFromParent, CopyFromParent, | 1769 | 0, CopyFromParent, CopyFromParent, CopyFromParent, |
| 1746 | 1770 | ||
| 1747 | /* Attributes. */ | 1771 | /* Attributes. */ |
| 1748 | mask, &a); | 1772 | mask, &a)); |
| 1749 | } | 1773 | } |
| 1750 | 1774 | ||
| 1751 | bar->frame = frame; | 1775 | XSET (bar->window, Lisp_Window, window); |
| 1752 | bar->top = top; | 1776 | XSET (bar->top, Lisp_Int, top); |
| 1753 | bar->left = left; | 1777 | XSET (bar->left, Lisp_Int, left); |
| 1754 | bar->width = width; | 1778 | XSET (bar->width, Lisp_Int, width); |
| 1755 | bar->height = height; | 1779 | XSET (bar->height, Lisp_Int, height); |
| 1756 | bar->start = bar->end = 0; | 1780 | XSET (bar->start, Lisp_Int, 0); |
| 1757 | bar->judge_timestamp = d->judge_timestamp; | 1781 | XSET (bar->end, Lisp_Int, 0); |
| 1758 | bar->dragging = -1; | 1782 | bar->dragging = Qnil; |
| 1759 | 1783 | ||
| 1760 | /* Add bar to its frame's list of scroll bars. */ | 1784 | /* Add bar to its frame's list of scroll bars. */ |
| 1761 | bar->next = d->vertical_scrollbars; | 1785 | bar->next = FRAME_SCROLLBARS (frame); |
| 1762 | d->vertical_scrollbars = bar; | 1786 | bar->prev = Qnil; |
| 1787 | XSET (FRAME_SCROLLBARS (frame), Lisp_Vector, bar); | ||
| 1788 | if (! NILP (bar->next)) | ||
| 1789 | XSET (XSCROLLBAR (bar->next)->prev, Lisp_Vector, bar); | ||
| 1763 | 1790 | ||
| 1764 | XMapWindow (x_current_display, bar->window); | 1791 | XMapWindow (x_current_display, SCROLLBAR_X_WINDOW (bar)); |
| 1765 | 1792 | ||
| 1766 | UNBLOCK_INPUT; | 1793 | UNBLOCK_INPUT; |
| 1794 | |||
| 1795 | return bar; | ||
| 1767 | } | 1796 | } |
| 1768 | 1797 | ||
| 1769 | /* Draw BAR's handle in the proper position. */ | 1798 | /* Draw BAR's handle in the proper position. |
| 1799 | If the handle is already drawn from START to END, don't bother | ||
| 1800 | redrawing it, unless REBUILD is non-zero; in that case, always | ||
| 1801 | redraw it. (REBUILD is handy for drawing the handle after expose | ||
| 1802 | events.) | ||
| 1803 | |||
| 1804 | Normally, we want to constrain the start and end of the handle to | ||
| 1805 | fit inside its rectangle, but if the user is dragging the scrollbar | ||
| 1806 | handle, we want to let them drag it down all the way, so that the | ||
| 1807 | bar's top is as far down as it goes; otherwise, there's no way to | ||
| 1808 | move to the very end of the buffer. */ | ||
| 1770 | static void | 1809 | static void |
| 1771 | x_scrollbar_set_handle (bar, start, end) | 1810 | x_scrollbar_set_handle (bar, start, end, rebuild) |
| 1772 | struct scrollbar *bar; | 1811 | struct scrollbar *bar; |
| 1773 | int start, end; | 1812 | int start, end; |
| 1813 | int rebuild; | ||
| 1774 | { | 1814 | { |
| 1815 | int dragging = ! NILP (bar->dragging); | ||
| 1816 | Window w = SCROLLBAR_X_WINDOW (bar); | ||
| 1817 | GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc; | ||
| 1818 | |||
| 1819 | /* If the display is already accurate, do nothing. */ | ||
| 1820 | if (! rebuild | ||
| 1821 | && start == XINT (bar->start) | ||
| 1822 | && end == XINT (bar->end)) | ||
| 1823 | return; | ||
| 1824 | |||
| 1775 | BLOCK_INPUT; | 1825 | BLOCK_INPUT; |
| 1776 | 1826 | ||
| 1777 | { | 1827 | { |
| 1778 | int inside_width = (bar->width | 1828 | int inside_width = VERTICAL_SCROLLBAR_INSIDE_WIDTH (XINT (bar->width)); |
| 1779 | - VERTICAL_SCROLLBAR_LEFT_BORDER | 1829 | int inside_height = VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar->height)); |
| 1780 | - VERTICAL_SCROLLBAR_RIGHT_BORDER); | 1830 | int top_range = VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar->height)); |
| 1781 | int inside_height = (bar->height | ||
| 1782 | - VERTICAL_SCROLLBAR_TOP_BORDER | ||
| 1783 | - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | ||
| 1784 | 1831 | ||
| 1785 | /* Make sure the values are reasonable, and try to preserve | 1832 | /* Make sure the values are reasonable, and try to preserve |
| 1786 | the distance between start and end. */ | 1833 | the distance between start and end. */ |
| 1787 | if (end < start) | 1834 | { |
| 1788 | end = start; | 1835 | int length = end - start; |
| 1789 | if (start < VERTICAL_SCROLLBAR_TOP_BORDER) | 1836 | |
| 1790 | { | 1837 | if (start < 0) |
| 1791 | end = VERTICAL_SCROLLBAR_TOP_BORDER + (end - start); | 1838 | start = 0; |
| 1792 | start = VERTICAL_SCROLLBAR_TOP_BORDER; | 1839 | else if (start > top_range) |
| 1793 | } | 1840 | start = top_range; |
| 1794 | if (end > bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | 1841 | end = start + length; |
| 1795 | { | 1842 | |
| 1796 | start = ((bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | 1843 | if (end < start) |
| 1797 | - (end - start)); | 1844 | end = start; |
| 1798 | end = bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER; | 1845 | else if (end > top_range && ! dragging) |
| 1799 | } | 1846 | end = top_range; |
| 1800 | if (start < VERTICAL_SCROLLBAR_TOP_BORDER) | 1847 | } |
| 1801 | start = VERTICAL_SCROLLBAR_TOP_BORDER; | ||
| 1802 | |||
| 1803 | /* Draw the empty space above the handle. */ | ||
| 1804 | XClearArea (x_current_display, bar->window, | ||
| 1805 | 1848 | ||
| 1806 | /* x, y, width, height, and exposures. */ | 1849 | /* Store the adjusted setting in the scrollbar. */ |
| 1807 | VERTICAL_SCROLLBAR_LEFT_BORDER, | 1850 | XSET (bar->start, Lisp_Int, start); |
| 1808 | VERTICAL_SCROLLBAR_TOP_BORDER, | 1851 | XSET (bar->end, Lisp_Int, end); |
| 1809 | inside_width + 1, start + 1, | ||
| 1810 | False); | ||
| 1811 | 1852 | ||
| 1812 | /* Draw the handle itself. */ | 1853 | /* Clip the end position, just for display. */ |
| 1813 | XFillRectangle (x_current_display, bar->window, | 1854 | if (end > top_range) |
| 1814 | bar->frame->display.x->normal_gc, | 1855 | end = top_range; |
| 1815 | 1856 | ||
| 1816 | /* x, y, width, height */ | 1857 | /* Draw bottom positions VERTICAL_SCROLLBAR_MIN_HANDLE pixels |
| 1817 | VERTICAL_SCROLLBAR_LEFT_BORDER, start, | 1858 | below top positions, to make sure the handle is always at least |
| 1818 | inside_width, (end - start) + 1); | 1859 | that many pixels tall. */ |
| 1860 | end += VERTICAL_SCROLLBAR_MIN_HANDLE; | ||
| 1819 | 1861 | ||
| 1862 | /* Draw the empty space above the handle. Note that we can't clear | ||
| 1863 | zero-height areas; that means "clear to end of window." */ | ||
| 1864 | if (0 < start) | ||
| 1865 | XClearArea (x_current_display, w, | ||
| 1820 | 1866 | ||
| 1821 | /* Draw the empty space below the handle. */ | 1867 | /* x, y, width, height, and exposures. */ |
| 1822 | XClearArea (x_current_display, bar->window, | 1868 | VERTICAL_SCROLLBAR_LEFT_BORDER, |
| 1869 | VERTICAL_SCROLLBAR_TOP_BORDER, | ||
| 1870 | inside_width, start, | ||
| 1871 | False); | ||
| 1823 | 1872 | ||
| 1824 | /* x, y, width, height, and exposures. */ | 1873 | /* Draw the handle itself. */ |
| 1825 | VERTICAL_SCROLLBAR_LEFT_BORDER, | 1874 | XFillRectangle (x_current_display, w, gc, |
| 1826 | VERTICAL_SCROLLBAR_TOP_BORDER + end, | ||
| 1827 | inside_width + 1, (inside_height - end) + 1, | ||
| 1828 | False); | ||
| 1829 | 1875 | ||
| 1830 | bar->start = start; | 1876 | /* x, y, width, height */ |
| 1831 | bar->end = end; | 1877 | VERTICAL_SCROLLBAR_LEFT_BORDER, |
| 1832 | } | 1878 | VERTICAL_SCROLLBAR_TOP_BORDER + start, |
| 1879 | inside_width, end - start); | ||
| 1833 | 1880 | ||
| 1834 | UNBLOCK_INPUT; | ||
| 1835 | } | ||
| 1836 | 1881 | ||
| 1837 | /* Remove the scrollbar BAR. */ | 1882 | /* Draw the empty space below the handle. Note that we can't |
| 1838 | static void | 1883 | clear zero-height areas; that means "clear to end of window." */ |
| 1839 | x_scrollbar_remove (bar) | 1884 | if (end < inside_height) |
| 1840 | struct scrollbar *bar; | 1885 | XClearArea (x_current_display, w, |
| 1841 | { | ||
| 1842 | BLOCK_INPUT; | ||
| 1843 | 1886 | ||
| 1844 | /* Remove bar from the frame's list. */ | 1887 | /* x, y, width, height, and exposures. */ |
| 1845 | { | 1888 | VERTICAL_SCROLLBAR_LEFT_BORDER, |
| 1846 | struct scrollbar **ptr; | 1889 | VERTICAL_SCROLLBAR_TOP_BORDER + end, |
| 1890 | inside_width, inside_height - end, | ||
| 1891 | False); | ||
| 1847 | 1892 | ||
| 1848 | for (ptr = &bar->frame->display.x->vertical_scrollbars; | ||
| 1849 | *ptr; | ||
| 1850 | ptr = &(*ptr)->next) | ||
| 1851 | if (*ptr == bar) | ||
| 1852 | { | ||
| 1853 | *ptr = bar->next; | ||
| 1854 | break; | ||
| 1855 | } | ||
| 1856 | } | 1893 | } |
| 1857 | 1894 | ||
| 1858 | /* Destroy the window. */ | ||
| 1859 | XDestroyWindow (x_current_display, bar->window); | ||
| 1860 | |||
| 1861 | /* Free the storage. */ | ||
| 1862 | free (bar); | ||
| 1863 | |||
| 1864 | UNBLOCK_INPUT; | 1895 | UNBLOCK_INPUT; |
| 1865 | } | 1896 | } |
| 1866 | 1897 | ||
| 1898 | /* Move a scrollbar around on the screen, to accomodate changing | ||
| 1899 | window configurations. */ | ||
| 1867 | static void | 1900 | static void |
| 1868 | x_scrollbar_move (bar, top, left, width, height) | 1901 | x_scrollbar_move (bar, top, left, width, height) |
| 1869 | struct scrollbar *bar; | 1902 | struct scrollbar *bar; |
| @@ -1880,107 +1913,196 @@ x_scrollbar_move (bar, top, left, width, height) | |||
| 1880 | wc.width = width; | 1913 | wc.width = width; |
| 1881 | wc.height = height; | 1914 | wc.height = height; |
| 1882 | 1915 | ||
| 1883 | if (left != bar->left) mask |= CWX; | 1916 | if (left != XINT (bar->left)) mask |= CWX; |
| 1884 | if (top != bar->top) mask |= CWY; | 1917 | if (top != XINT (bar->top)) mask |= CWY; |
| 1885 | if (width != bar->width) mask |= CWWidth; | 1918 | if (width != XINT (bar->width)) mask |= CWWidth; |
| 1886 | if (height != bar->height) mask |= CWHeight; | 1919 | if (height != XINT (bar->height)) mask |= CWHeight; |
| 1887 | 1920 | ||
| 1888 | XConfigureWindow (x_current_display, bar->window, mask, &wc); | 1921 | if (mask) |
| 1922 | XConfigureWindow (x_current_display, SCROLLBAR_X_WINDOW (bar), | ||
| 1923 | mask, &wc); | ||
| 1889 | } | 1924 | } |
| 1890 | 1925 | ||
| 1926 | XSET (bar->left, Lisp_Int, left); | ||
| 1927 | XSET (bar->top, Lisp_Int, top); | ||
| 1928 | XSET (bar->width, Lisp_Int, width); | ||
| 1929 | XSET (bar->height, Lisp_Int, height); | ||
| 1930 | |||
| 1891 | UNBLOCK_INPUT; | 1931 | UNBLOCK_INPUT; |
| 1892 | } | 1932 | } |
| 1893 | 1933 | ||
| 1894 | /* Set BAR to be the vertical scroll bar for WINDOW. Set its handle | 1934 | /* Destroy the X window for BAR, and set its Emacs window's scrollbar |
| 1895 | to indicate that we are displaying PORTION characters out of a | 1935 | to nil. */ |
| 1896 | total of WHOLE characters, starting at POSITION. Return BAR. If | 1936 | static void |
| 1897 | BAR is zero, create a new scrollbar and return a pointer to it. */ | 1937 | x_scrollbar_remove (bar) |
| 1898 | static struct scrollbar * | ||
| 1899 | XTset_scrollbar (bar, window, portion, whole, position) | ||
| 1900 | struct scrollbar *bar; | 1938 | struct scrollbar *bar; |
| 1939 | { | ||
| 1940 | FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | ||
| 1941 | |||
| 1942 | BLOCK_INPUT; | ||
| 1943 | |||
| 1944 | /* Destroy the window. */ | ||
| 1945 | XDestroyWindow (x_current_display, SCROLLBAR_X_WINDOW (bar)); | ||
| 1946 | |||
| 1947 | /* Disassociate this scrollbar from its window. */ | ||
| 1948 | XWINDOW (bar->window)->vertical_scrollbar = Qnil; | ||
| 1949 | |||
| 1950 | UNBLOCK_INPUT; | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | /* Set the handle of the vertical scroll bar for WINDOW to indicate | ||
| 1954 | that we are displaying PORTION characters out of a total of WHOLE | ||
| 1955 | characters, starting at POSITION. If WINDOW has no scrollbar, | ||
| 1956 | create one. */ | ||
| 1957 | static void | ||
| 1958 | XTset_vertical_scrollbar (window, portion, whole, position) | ||
| 1901 | struct window *window; | 1959 | struct window *window; |
| 1902 | int portion, whole, position; | 1960 | int portion, whole, position; |
| 1903 | { | 1961 | { |
| 1904 | FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); | 1962 | FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); |
| 1905 | struct x_display *d = f->display.x; | ||
| 1906 | int top = XINT (window->top); | 1963 | int top = XINT (window->top); |
| 1907 | int left = WINDOW_VERTICAL_SCROLLBAR_COLUMN (window); | 1964 | int left = WINDOW_VERTICAL_SCROLLBAR_COLUMN (window); |
| 1908 | int height = WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window); | 1965 | int height = WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window); |
| 1909 | 1966 | ||
| 1910 | /* Where should this scrollbar be, pixelwise? */ | 1967 | /* Where should this scrollbar be, pixelwise? */ |
| 1911 | int pixel_top = (d->internal_border_width + top * FONT_HEIGHT (d->font)); | 1968 | int pixel_top = CHAR_TO_PIXEL_ROW (f, top); |
| 1912 | int pixel_left = (d->internal_border_width + left * FONT_WIDTH (d->font)); | 1969 | int pixel_left = CHAR_TO_PIXEL_COL (f, left); |
| 1913 | int pixel_width = VERTICAL_SCROLLBAR_PIXEL_WIDTH (f); | 1970 | int pixel_width = VERTICAL_SCROLLBAR_PIXEL_WIDTH (f); |
| 1914 | int pixel_height = VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f, height); | 1971 | int pixel_height = VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f, height); |
| 1915 | 1972 | ||
| 1973 | struct scrollbar *bar; | ||
| 1974 | |||
| 1916 | /* Does the scrollbar exist yet? */ | 1975 | /* Does the scrollbar exist yet? */ |
| 1917 | if (! bar) | 1976 | if (NILP (window->vertical_scrollbar)) |
| 1918 | bar = x_scrollbar_create (f, | 1977 | bar = x_scrollbar_create (window, |
| 1919 | pixel_top, pixel_left, | 1978 | pixel_top, pixel_left, |
| 1920 | pixel_width, pixel_height); | 1979 | pixel_width, pixel_height); |
| 1921 | else | 1980 | else |
| 1922 | /* It may just need to be moved and resized. */ | 1981 | { |
| 1923 | x_scrollbar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); | 1982 | /* It may just need to be moved and resized. */ |
| 1983 | bar = XSCROLLBAR (window->vertical_scrollbar); | ||
| 1984 | x_scrollbar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); | ||
| 1985 | } | ||
| 1924 | 1986 | ||
| 1925 | /* Set the scrollbar's current state, unless we're currently being | 1987 | /* Set the scrollbar's current state, unless we're currently being |
| 1926 | dragged. */ | 1988 | dragged. */ |
| 1927 | 1989 | if (NILP (bar->dragging)) | |
| 1928 | if (bar && bar->dragging == -1) | ||
| 1929 | { | 1990 | { |
| 1930 | int inside_height = (pixel_height | 1991 | int top_range = |
| 1931 | - VERTICAL_SCROLLBAR_TOP_BORDER | 1992 | VERTICAL_SCROLLBAR_TOP_RANGE (pixel_height); |
| 1932 | - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | ||
| 1933 | int start = (position * inside_height) / whole; | ||
| 1934 | int end = ((position + portion) * inside_height) / whole; | ||
| 1935 | 1993 | ||
| 1936 | x_scrollbar_set_handle (bar, start, end); | 1994 | if (whole == 0) |
| 1995 | x_scrollbar_set_handle (bar, 0, top_range, 0); | ||
| 1996 | else | ||
| 1997 | { | ||
| 1998 | int start = (position * top_range) / whole; | ||
| 1999 | int end = ((position + portion) * top_range) / whole; | ||
| 2000 | |||
| 2001 | x_scrollbar_set_handle (bar, start, end, 0); | ||
| 2002 | } | ||
| 1937 | } | 2003 | } |
| 1938 | 2004 | ||
| 1939 | return bar; | 2005 | XSET (window->vertical_scrollbar, Lisp_Vector, bar); |
| 1940 | } | 2006 | } |
| 1941 | 2007 | ||
| 2008 | |||
| 1942 | /* The following three hooks are used when we're doing a thorough | 2009 | /* The following three hooks are used when we're doing a thorough |
| 1943 | redisplay of the frame. We don't explicitly know which scrollbars | 2010 | redisplay of the frame. We don't explicitly know which scrollbars |
| 1944 | are going to be deleted, because keeping track of when windows go | 2011 | are going to be deleted, because keeping track of when windows go |
| 1945 | away is a real pain - can you say set-window-configuration? | 2012 | away is a real pain - "Can you say set-window-configuration, boys |
| 1946 | Instead, we just assert at the beginning of redisplay that *all* | 2013 | and girls?" Instead, we just assert at the beginning of redisplay |
| 1947 | scrollbars are to be removed, and then save scrollbars from the | 2014 | that *all* scrollbars are to be removed, and then save a scrollbar |
| 1948 | firey pit when we actually redisplay their window. */ | 2015 | from the fiery pit when we actually redisplay its window. */ |
| 1949 | 2016 | ||
| 1950 | /* Arrange for all scrollbars on FRAME to be removed at the next call | 2017 | /* Arrange for all scrollbars on FRAME to be removed at the next call |
| 1951 | to `*judge_scrollbars_hook'. A scrollbar may be spared if | 2018 | to `*judge_scrollbars_hook'. A scrollbar may be spared if |
| 1952 | `*redeem_scrollbar_hook' is applied to it before the judgement. */ | 2019 | `*redeem_scrollbar_hook' is applied to its window before the judgement. */ |
| 1953 | static void | 2020 | static void |
| 1954 | XTcondemn_scrollbars (frame) | 2021 | XTcondemn_scrollbars (frame) |
| 1955 | FRAME_PTR frame; | 2022 | FRAME_PTR frame; |
| 1956 | { | 2023 | { |
| 1957 | /* Any scrollbars which don't get caught up to this will be deleted. */ | 2024 | /* The condemned list should be empty at this point; if it's not, |
| 1958 | frame->display.x->judge_timestamp++; | 2025 | then the rest of Emacs isn't using the condemn/redeem/judge |
| 2026 | protocol correctly. */ | ||
| 2027 | if (! NILP (FRAME_CONDEMNED_SCROLLBARS (frame))) | ||
| 2028 | abort (); | ||
| 2029 | |||
| 2030 | /* Move them all to the "condemned" list. */ | ||
| 2031 | FRAME_CONDEMNED_SCROLLBARS (frame) = FRAME_SCROLLBARS (frame); | ||
| 2032 | FRAME_SCROLLBARS (frame) = Qnil; | ||
| 1959 | } | 2033 | } |
| 1960 | 2034 | ||
| 1961 | /* Unmark BAR for deletion in this judgement cycle. */ | 2035 | /* Unmark WINDOW's scrollbar for deletion in this judgement cycle. |
| 2036 | Note that WINDOW isn't necessarily condemned at all. */ | ||
| 1962 | static void | 2037 | static void |
| 1963 | XTredeem_scrollbar (bar) | 2038 | XTredeem_scrollbar (window) |
| 1964 | struct scrollbar *bar; | 2039 | struct window *window; |
| 1965 | { | 2040 | { |
| 1966 | bar->judge_timestamp = bar->frame->display.x->judge_timestamp; | 2041 | struct scrollbar *bar; |
| 2042 | |||
| 2043 | /* We can't redeem this window's scrollbar if it doesn't have one. */ | ||
| 2044 | if (NILP (window->vertical_scrollbar)) | ||
| 2045 | abort (); | ||
| 2046 | |||
| 2047 | bar = XSCROLLBAR (window->vertical_scrollbar); | ||
| 2048 | |||
| 2049 | /* Unlink it from the condemned list. */ | ||
| 2050 | { | ||
| 2051 | FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); | ||
| 2052 | |||
| 2053 | if (NILP (bar->prev)) | ||
| 2054 | { | ||
| 2055 | /* If the prev pointer is nil, it must be the first in one of | ||
| 2056 | the lists. */ | ||
| 2057 | if (EQ (FRAME_SCROLLBARS (f), window->vertical_scrollbar)) | ||
| 2058 | /* It's not condemned. Everything's fine. */ | ||
| 2059 | return; | ||
| 2060 | else if (EQ (FRAME_CONDEMNED_SCROLLBARS (f), | ||
| 2061 | window->vertical_scrollbar)) | ||
| 2062 | FRAME_CONDEMNED_SCROLLBARS (f) = bar->next; | ||
| 2063 | else | ||
| 2064 | /* If its prev pointer is nil, it must be at the front of | ||
| 2065 | one or the other! */ | ||
| 2066 | abort (); | ||
| 2067 | } | ||
| 2068 | else | ||
| 2069 | XSCROLLBAR (bar->prev)->next = bar->next; | ||
| 2070 | |||
| 2071 | if (! NILP (bar->next)) | ||
| 2072 | XSCROLLBAR (bar->next)->prev = bar->prev; | ||
| 2073 | |||
| 2074 | bar->next = FRAME_SCROLLBARS (f); | ||
| 2075 | bar->prev = Qnil; | ||
| 2076 | XSET (FRAME_SCROLLBARS (f), Lisp_Vector, bar); | ||
| 2077 | if (! NILP (bar->next)) | ||
| 2078 | XSET (XSCROLLBAR (bar->next)->prev, Lisp_Vector, bar); | ||
| 2079 | } | ||
| 1967 | } | 2080 | } |
| 1968 | 2081 | ||
| 1969 | /* Remove all scrollbars on FRAME that haven't been saved since the | 2082 | /* Remove all scrollbars on FRAME that haven't been saved since the |
| 1970 | last call to `*condemn_scrollbars_hook'. */ | 2083 | last call to `*condemn_scrollbars_hook'. */ |
| 1971 | static void | 2084 | static void |
| 1972 | XTjudge_scrollbars(frame) | 2085 | XTjudge_scrollbars (f) |
| 1973 | FRAME_PTR frame; | 2086 | FRAME_PTR f; |
| 1974 | { | 2087 | { |
| 1975 | int judge_timestamp = frame->display.x->judge_timestamp; | 2088 | Lisp_Object bar, next; |
| 1976 | struct scrollbar *bar, *next; | ||
| 1977 | 2089 | ||
| 1978 | for (bar = frame->display.x->vertical_scrollbars; bar; bar = next) | 2090 | for (bar = FRAME_CONDEMNED_SCROLLBARS (f); |
| 2091 | ! NILP (bar); | ||
| 2092 | bar = next) | ||
| 1979 | { | 2093 | { |
| 1980 | next = bar->next; | 2094 | struct scrollbar *b = XSCROLLBAR (bar); |
| 1981 | if (bar->judge_timestamp < judge_timestamp) | 2095 | |
| 1982 | x_scrollbar_remove (bar); | 2096 | x_scrollbar_remove (b); |
| 2097 | |||
| 2098 | next = b->next; | ||
| 2099 | b->next = b->prev = Qnil; | ||
| 1983 | } | 2100 | } |
| 2101 | |||
| 2102 | FRAME_CONDEMNED_SCROLLBARS (f) = Qnil; | ||
| 2103 | |||
| 2104 | /* Now there should be no references to the condemned scrollbars, | ||
| 2105 | and they should get garbage-collected. */ | ||
| 1984 | } | 2106 | } |
| 1985 | 2107 | ||
| 1986 | 2108 | ||
| @@ -1990,51 +2112,24 @@ x_scrollbar_expose (bar, event) | |||
| 1990 | struct scrollbar *bar; | 2112 | struct scrollbar *bar; |
| 1991 | XEvent *event; | 2113 | XEvent *event; |
| 1992 | { | 2114 | { |
| 2115 | Window w = SCROLLBAR_X_WINDOW (bar); | ||
| 2116 | GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc; | ||
| 2117 | |||
| 1993 | BLOCK_INPUT; | 2118 | BLOCK_INPUT; |
| 1994 | 2119 | ||
| 1995 | x_scrollbar_set_handle (bar, bar->start, bar->end); | 2120 | x_scrollbar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1); |
| 1996 | 2121 | ||
| 1997 | /* Draw the extra-thick border on the right. */ | 2122 | /* Draw a one-pixel border just inside the edges of the scrollbar. */ |
| 1998 | XFillRectangle (x_current_display, bar->window, | 2123 | XDrawRectangle (x_current_display, w, gc, |
| 1999 | bar->frame->display.x->normal_gc, | ||
| 2000 | 2124 | ||
| 2001 | /* x, y, width, height */ | 2125 | /* x, y, width, height */ |
| 2002 | bar->width - VERTICAL_SCROLLBAR_RIGHT_BORDER, 0, | 2126 | 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1); |
| 2003 | VERTICAL_SCROLLBAR_RIGHT_BORDER, bar->height + 1); | ||
| 2004 | 2127 | ||
| 2005 | UNBLOCK_INPUT; | 2128 | /* Draw another line to make the extra-thick border on the right. */ |
| 2006 | } | 2129 | XFillRectangle (x_current_display, w, gc, |
| 2007 | |||
| 2008 | /* Handle an exposure event which might be over the extra scrollbar space. */ | ||
| 2009 | static void | ||
| 2010 | x_scrollbar_background_expose (frame, event) | ||
| 2011 | FRAME_PTR frame; | ||
| 2012 | XEvent *event; | ||
| 2013 | { | ||
| 2014 | /* Where is the extra scrollbar space, anyway? */ | ||
| 2015 | int width = VERTICAL_SCROLLBAR_PIXEL_WIDTH (frame); | ||
| 2016 | int height = PIXEL_HEIGHT (frame); | ||
| 2017 | int x = PIXEL_WIDTH (frame) - width; | ||
| 2018 | int y = 0; | ||
| 2019 | |||
| 2020 | BLOCK_INPUT; | ||
| 2021 | 2130 | ||
| 2022 | /* Clear it out. */ | 2131 | /* x, y, width, height */ |
| 2023 | XClearArea (x_current_display, FRAME_X_WINDOW (frame), | 2132 | XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2); |
| 2024 | |||
| 2025 | /* x, y, width, height, expose */ | ||
| 2026 | x, y, width+1, height+1, False); | ||
| 2027 | |||
| 2028 | /* Draw the border. */ | ||
| 2029 | XDrawRectangle (x_current_display, FRAME_X_WINDOW (frame), | ||
| 2030 | frame->display.x->normal_gc, | ||
| 2031 | x, y, width, height); | ||
| 2032 | |||
| 2033 | /* Draw the extra-thick border on the right edge. */ | ||
| 2034 | XFillRectangle (x_current_display, FRAME_X_WINDOW (frame), | ||
| 2035 | frame->display.x->normal_gc, | ||
| 2036 | x + width - VERTICAL_SCROLLBAR_RIGHT_BORDER, 0, | ||
| 2037 | VERTICAL_SCROLLBAR_RIGHT_BORDER, height + 1); | ||
| 2038 | 2133 | ||
| 2039 | UNBLOCK_INPUT; | 2134 | UNBLOCK_INPUT; |
| 2040 | } | 2135 | } |
| @@ -2047,78 +2142,85 @@ x_scrollbar_handle_click (bar, event, emacs_event) | |||
| 2047 | XEvent *event; | 2142 | XEvent *event; |
| 2048 | struct input_event *emacs_event; | 2143 | struct input_event *emacs_event; |
| 2049 | { | 2144 | { |
| 2145 | if (XTYPE (bar->window) != Lisp_Window) | ||
| 2146 | abort (); | ||
| 2147 | |||
| 2050 | emacs_event->kind = scrollbar_click; | 2148 | emacs_event->kind = scrollbar_click; |
| 2051 | XSETINT (emacs_event->code, event->xbutton.button - Button1); | 2149 | XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1); |
| 2052 | emacs_event->modifiers = | 2150 | emacs_event->modifiers = |
| 2053 | (x_convert_modifiers (event->xbutton.state) | 2151 | (x_convert_modifiers (event->xbutton.state) |
| 2054 | | (event->type == ButtonRelease | 2152 | | (event->type == ButtonRelease |
| 2055 | ? up_modifier | 2153 | ? up_modifier |
| 2056 | : down_modifier)); | 2154 | : down_modifier)); |
| 2057 | emacs_event->part = | 2155 | emacs_event->frame_or_window = bar->window; |
| 2058 | ((event->xbutton.x < bar->start) ? scrollbar_above_handle | ||
| 2059 | : (event->xbutton.x < bar->end) ? scrollbar_handle | ||
| 2060 | : scrollbar_below_handle); | ||
| 2061 | emacs_event->scrollbar = bar; | ||
| 2062 | |||
| 2063 | if (event->xbutton.y < VERTICAL_SCROLLBAR_TOP_BORDER) | ||
| 2064 | event->xbutton.y = VERTICAL_SCROLLBAR_TOP_BORDER; | ||
| 2065 | if (event->xbutton.y > bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | ||
| 2066 | event->xbutton.y = bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER; | ||
| 2067 | XSETINT (emacs_event->x, | ||
| 2068 | event->xbutton.y - VERTICAL_SCROLLBAR_TOP_BORDER); | ||
| 2069 | XSETINT (emacs_event->y, | ||
| 2070 | (bar->height | ||
| 2071 | - VERTICAL_SCROLLBAR_TOP_BORDER | ||
| 2072 | - VERTICAL_SCROLLBAR_BOTTOM_BORDER)); | ||
| 2073 | |||
| 2074 | emacs_event->frame = bar->frame; | ||
| 2075 | emacs_event->timestamp = event->xbutton.time; | 2156 | emacs_event->timestamp = event->xbutton.time; |
| 2157 | { | ||
| 2158 | int internal_height = | ||
| 2159 | VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar->height)); | ||
| 2160 | int top_range = | ||
| 2161 | VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar->height)); | ||
| 2162 | int y = event->xbutton.y - VERTICAL_SCROLLBAR_TOP_BORDER; | ||
| 2163 | |||
| 2164 | if (y < 0) y = 0; | ||
| 2165 | if (y > top_range) y = top_range; | ||
| 2166 | |||
| 2167 | if (y < XINT (bar->start)) | ||
| 2168 | emacs_event->part = scrollbar_above_handle; | ||
| 2169 | else if (y < XINT (bar->end) + VERTICAL_SCROLLBAR_MIN_HANDLE) | ||
| 2170 | emacs_event->part = scrollbar_handle; | ||
| 2171 | else | ||
| 2172 | emacs_event->part = scrollbar_below_handle; | ||
| 2173 | |||
| 2174 | /* If the user has just clicked on the handle, record where they're | ||
| 2175 | holding it. */ | ||
| 2176 | if (event->type == ButtonPress | ||
| 2177 | && emacs_event->part == scrollbar_handle) | ||
| 2178 | XSET (bar->dragging, Lisp_Int, y - XINT (bar->start)); | ||
| 2179 | |||
| 2180 | /* If the user has released the handle, set it to its final position. */ | ||
| 2181 | if (event->type == ButtonRelease | ||
| 2182 | && ! NILP (bar->dragging)) | ||
| 2183 | { | ||
| 2184 | int new_start = y - XINT (bar->dragging); | ||
| 2185 | int new_end = new_start + (XINT (bar->end) - XINT (bar->start)); | ||
| 2076 | 2186 | ||
| 2077 | if (event->type == ButtonPress | 2187 | x_scrollbar_set_handle (bar, new_start, new_end, 0); |
| 2078 | && emacs_event->part == scrollbar_handle) | 2188 | bar->dragging = Qnil; |
| 2079 | bar->dragging = event->xbutton.x - bar->start; | 2189 | } |
| 2080 | else | ||
| 2081 | { | ||
| 2082 | int new_start = event->xbutton.x - bar->dragging; | ||
| 2083 | int new_end = new_start + (bar->end - bar->start); | ||
| 2084 | 2190 | ||
| 2085 | x_scrollbar_set_handle (bar, new_start, new_end); | 2191 | /* Clicks on the handle are always reported as occuring at the top of |
| 2086 | bar->dragging = -1; | 2192 | the handle. */ |
| 2087 | } | 2193 | if (emacs_event->part == scrollbar_handle) |
| 2088 | } | 2194 | emacs_event->x = bar->start; |
| 2195 | else | ||
| 2196 | XSET (emacs_event->x, Lisp_Int, y); | ||
| 2089 | 2197 | ||
| 2198 | XSET (emacs_event->y, Lisp_Int, top_range); | ||
| 2199 | } | ||
| 2200 | } | ||
| 2090 | 2201 | ||
| 2091 | /* Handle some mouse motion while someone is dragging the scrollbar. */ | 2202 | /* Handle some mouse motion while someone is dragging the scrollbar. */ |
| 2092 | static void | 2203 | static void |
| 2093 | x_scrollbar_handle_motion (bar, event) | 2204 | x_scrollbar_note_movement (bar, event) |
| 2094 | struct scrollbar *bar; | 2205 | struct scrollbar *bar; |
| 2095 | XEvent *event; | 2206 | XEvent *event; |
| 2096 | { | 2207 | { |
| 2097 | last_mouse_movement_time = event->xmotion.time; | 2208 | last_mouse_movement_time = event->xmotion.time; |
| 2098 | 2209 | ||
| 2099 | mouse_moved = 1; | 2210 | mouse_moved = 1; |
| 2100 | last_mouse_bar = bar; | 2211 | XSET (last_mouse_scrollbar, Lisp_Vector, bar); |
| 2101 | last_mouse_bar_frame = bar->frame; | ||
| 2102 | last_mouse_part = (bar->dragging == -1 ? scrollbar_handle | ||
| 2103 | : (event->xbutton.x < bar->start) ? scrollbar_above_handle | ||
| 2104 | : (event->xbutton.x < bar->end) ? scrollbar_handle | ||
| 2105 | : scrollbar_below_handle); | ||
| 2106 | last_mouse_scroll_range_start = bar->top + VERTICAL_SCROLLBAR_TOP_BORDER; | ||
| 2107 | last_mouse_scroll_range_end = (bar->top | ||
| 2108 | + bar->height | ||
| 2109 | - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | ||
| 2110 | 2212 | ||
| 2111 | /* If we're dragging the bar, display it. */ | 2213 | /* If we're dragging the bar, display it. */ |
| 2112 | if (bar->dragging != -1) | 2214 | if (! NILP (bar->dragging)) |
| 2113 | { | 2215 | { |
| 2114 | /* Where should the handle be now? */ | 2216 | /* Where should the handle be now? */ |
| 2115 | int new_start = event->xmotion.x - bar->dragging; | 2217 | int new_start = event->xmotion.y - XINT (bar->dragging); |
| 2116 | 2218 | ||
| 2117 | if (new_start != bar->start) | 2219 | if (new_start != XINT (bar->start)) |
| 2118 | { | 2220 | { |
| 2119 | int new_end = new_start + (bar->end - bar->start); | 2221 | int new_end = new_start + (XINT (bar->end) - XINT (bar->start)); |
| 2120 | 2222 | ||
| 2121 | x_scrollbar_set_handle (bar, new_start, new_end); | 2223 | x_scrollbar_set_handle (bar, new_start, new_end, 0); |
| 2122 | } | 2224 | } |
| 2123 | } | 2225 | } |
| 2124 | 2226 | ||
| @@ -2134,6 +2236,79 @@ x_scrollbar_handle_motion (bar, event) | |||
| 2134 | } | 2236 | } |
| 2135 | } | 2237 | } |
| 2136 | 2238 | ||
| 2239 | /* Return information to the user about the current position of the mouse | ||
| 2240 | on the scrollbar. */ | ||
| 2241 | static void | ||
| 2242 | x_scrollbar_report_motion (f, bar_window, part, x, y, time) | ||
| 2243 | FRAME_PTR *f; | ||
| 2244 | Lisp_Object *bar_window; | ||
| 2245 | enum scrollbar_part *part; | ||
| 2246 | Lisp_Object *x, *y; | ||
| 2247 | unsigned long *time; | ||
| 2248 | { | ||
| 2249 | struct scrollbar *bar = XSCROLLBAR (last_mouse_scrollbar); | ||
| 2250 | int win_x, win_y; | ||
| 2251 | |||
| 2252 | /* Get the mouse's position relative to the scrollbar window, and | ||
| 2253 | report that. */ | ||
| 2254 | { | ||
| 2255 | Window dummy_window; | ||
| 2256 | int dummy_coord; | ||
| 2257 | unsigned int dummy_mask; | ||
| 2258 | |||
| 2259 | if (! XQueryPointer (x_current_display, | ||
| 2260 | SCROLLBAR_X_WINDOW (bar), | ||
| 2261 | |||
| 2262 | /* Root, child, root x and root y. */ | ||
| 2263 | &dummy_window, &dummy_window, | ||
| 2264 | &dummy_coord, &dummy_coord, | ||
| 2265 | |||
| 2266 | /* Position relative to scrollbar. */ | ||
| 2267 | &win_x, &win_y, | ||
| 2268 | |||
| 2269 | /* Mouse buttons and modifier keys. */ | ||
| 2270 | &dummy_mask)) | ||
| 2271 | { | ||
| 2272 | *f = 0; | ||
| 2273 | return; | ||
| 2274 | } | ||
| 2275 | } | ||
| 2276 | |||
| 2277 | { | ||
| 2278 | int inside_height = VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar->height)); | ||
| 2279 | int top_range = VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar->height)); | ||
| 2280 | |||
| 2281 | win_y -= VERTICAL_SCROLLBAR_TOP_BORDER; | ||
| 2282 | |||
| 2283 | if (! NILP (bar->dragging)) | ||
| 2284 | win_y -= XINT (bar->dragging); | ||
| 2285 | |||
| 2286 | if (win_y < 0) | ||
| 2287 | win_y = 0; | ||
| 2288 | if (win_y > top_range) | ||
| 2289 | win_y = top_range; | ||
| 2290 | |||
| 2291 | *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | ||
| 2292 | *bar_window = bar->window; | ||
| 2293 | |||
| 2294 | if (! NILP (bar->dragging)) | ||
| 2295 | *part = scrollbar_handle; | ||
| 2296 | else if (win_y < XINT (bar->start)) | ||
| 2297 | *part = scrollbar_above_handle; | ||
| 2298 | else if (win_y < XINT (bar->end) + VERTICAL_SCROLLBAR_MIN_HANDLE) | ||
| 2299 | *part = scrollbar_handle; | ||
| 2300 | else | ||
| 2301 | *part = scrollbar_below_handle; | ||
| 2302 | |||
| 2303 | XSET (*x, Lisp_Int, win_y); | ||
| 2304 | XSET (*y, Lisp_Int, top_range); | ||
| 2305 | *time = last_mouse_movement_time; | ||
| 2306 | } | ||
| 2307 | |||
| 2308 | mouse_moved = 0; | ||
| 2309 | last_mouse_scrollbar = Qnil; | ||
| 2310 | } | ||
| 2311 | |||
| 2137 | 2312 | ||
| 2138 | 2313 | ||
| 2139 | /* The main X event-reading loop - XTread_socket. */ | 2314 | /* The main X event-reading loop - XTread_socket. */ |
| @@ -2322,7 +2497,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2322 | dumprectangle (x_window_to_frame (event.xexpose.window), | 2497 | dumprectangle (x_window_to_frame (event.xexpose.window), |
| 2323 | event.xexpose.x, event.xexpose.y, | 2498 | event.xexpose.x, event.xexpose.y, |
| 2324 | event.xexpose.width, event.xexpose.height); | 2499 | event.xexpose.width, event.xexpose.height); |
| 2325 | x_scrollbar_background_expose (f, &event); | ||
| 2326 | } | 2500 | } |
| 2327 | } | 2501 | } |
| 2328 | else | 2502 | else |
| @@ -2345,7 +2519,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2345 | event.xgraphicsexpose.x, event.xgraphicsexpose.y, | 2519 | event.xgraphicsexpose.x, event.xgraphicsexpose.y, |
| 2346 | event.xgraphicsexpose.width, | 2520 | event.xgraphicsexpose.width, |
| 2347 | event.xgraphicsexpose.height); | 2521 | event.xgraphicsexpose.height); |
| 2348 | x_scrollbar_background_expose (f, &event); | ||
| 2349 | } | 2522 | } |
| 2350 | break; | 2523 | break; |
| 2351 | 2524 | ||
| @@ -2477,7 +2650,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2477 | { | 2650 | { |
| 2478 | bufp->kind = non_ascii_keystroke; | 2651 | bufp->kind = non_ascii_keystroke; |
| 2479 | XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50); | 2652 | XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50); |
| 2480 | bufp->frame = f; | 2653 | XSET (bufp->frame_or_window, Lisp_Frame, f); |
| 2481 | bufp->modifiers = x_convert_modifiers (modifiers); | 2654 | bufp->modifiers = x_convert_modifiers (modifiers); |
| 2482 | bufp->timestamp = event.xkey.time; | 2655 | bufp->timestamp = event.xkey.time; |
| 2483 | bufp++; | 2656 | bufp++; |
| @@ -2494,7 +2667,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2494 | *copy_buffer |= METABIT; | 2667 | *copy_buffer |= METABIT; |
| 2495 | bufp->kind = ascii_keystroke; | 2668 | bufp->kind = ascii_keystroke; |
| 2496 | XSET (bufp->code, Lisp_Int, *copy_buffer); | 2669 | XSET (bufp->code, Lisp_Int, *copy_buffer); |
| 2497 | bufp->frame = f; | 2670 | XSET (bufp->frame_or_window, Lisp_Frame, f); |
| 2498 | bufp->timestamp = event.xkey.time; | 2671 | bufp->timestamp = event.xkey.time; |
| 2499 | bufp++; | 2672 | bufp++; |
| 2500 | } | 2673 | } |
| @@ -2503,7 +2676,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2503 | { | 2676 | { |
| 2504 | bufp->kind = ascii_keystroke; | 2677 | bufp->kind = ascii_keystroke; |
| 2505 | XSET (bufp->code, Lisp_Int, copy_buffer[i]); | 2678 | XSET (bufp->code, Lisp_Int, copy_buffer[i]); |
| 2506 | bufp->frame = f; | 2679 | XSET (bufp->frame_or_window, Lisp_Frame, f); |
| 2507 | bufp->timestamp = event.xkey.time; | 2680 | bufp->timestamp = event.xkey.time; |
| 2508 | bufp++; | 2681 | bufp++; |
| 2509 | } | 2682 | } |
| @@ -2553,7 +2726,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2553 | bufp->kind = ascii_keystroke; | 2726 | bufp->kind = ascii_keystroke; |
| 2554 | XSET (bufp->code, Lisp_Int, where_mapping[i]); | 2727 | XSET (bufp->code, Lisp_Int, where_mapping[i]); |
| 2555 | XSET (bufp->time, Lisp_Int, event.xkey.time); | 2728 | XSET (bufp->time, Lisp_Int, event.xkey.time); |
| 2556 | bufp->frame = f; | 2729 | XSET (bufp->frame_or_window, Lisp_Frame, f); |
| 2557 | bufp++; | 2730 | bufp++; |
| 2558 | } | 2731 | } |
| 2559 | count += nbytes; | 2732 | count += nbytes; |
| @@ -2668,14 +2841,14 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2668 | { | 2841 | { |
| 2669 | f = x_window_to_frame (event.xmotion.window); | 2842 | f = x_window_to_frame (event.xmotion.window); |
| 2670 | if (f) | 2843 | if (f) |
| 2671 | note_mouse_position (f, &event.xmotion); | 2844 | note_mouse_movement (f, &event.xmotion); |
| 2672 | else | 2845 | else |
| 2673 | { | 2846 | { |
| 2674 | struct scrollbar *bar = | 2847 | struct scrollbar *bar = |
| 2675 | x_window_to_scrollbar (event.xmotion.window); | 2848 | x_window_to_scrollbar (event.xmotion.window); |
| 2676 | 2849 | ||
| 2677 | if (bar) | 2850 | if (bar) |
| 2678 | x_scrollbar_handle_motion (bar, &event); | 2851 | x_scrollbar_note_movement (bar, &event); |
| 2679 | } | 2852 | } |
| 2680 | } | 2853 | } |
| 2681 | break; | 2854 | break; |
| @@ -2768,13 +2941,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2768 | { | 2941 | { |
| 2769 | bufp->kind = ascii_keystroke; | 2942 | bufp->kind = ascii_keystroke; |
| 2770 | bufp->code = (char) 'X' & 037; /* C-x */ | 2943 | bufp->code = (char) 'X' & 037; /* C-x */ |
| 2771 | bufp->frame = f; | 2944 | XSET (bufp->frame_or_window, Lisp_Frame, f); |
| 2772 | XSET (bufp->time, Lisp_Int, event.xkey.time); | 2945 | XSET (bufp->time, Lisp_Int, event.xkey.time); |
| 2773 | bufp++; | 2946 | bufp++; |
| 2774 | 2947 | ||
| 2775 | bufp->kind = ascii_keystroke; | 2948 | bufp->kind = ascii_keystroke; |
| 2776 | bufp->code = (char) 0; /* C-@ */ | 2949 | bufp->code = (char) 0; /* C-@ */ |
| 2777 | bufp->frame = f; | 2950 | XSET (bufp->frame_or_window, Lisp_Frame, f); |
| 2778 | XSET (bufp->time, Lisp_Int, event.xkey.time); | 2951 | XSET (bufp->time, Lisp_Int, event.xkey.time); |
| 2779 | bufp++; | 2952 | bufp++; |
| 2780 | 2953 | ||
| @@ -2914,15 +3087,12 @@ static void | |||
| 2914 | x_draw_box (f) | 3087 | x_draw_box (f) |
| 2915 | struct frame *f; | 3088 | struct frame *f; |
| 2916 | { | 3089 | { |
| 2917 | int left = f->cursor_x * FONT_WIDTH (f->display.x->font) | 3090 | int left = CHAR_TO_PIXEL_COL (f, f->cursor_x); |
| 2918 | + f->display.x->internal_border_width; | 3091 | int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y); |
| 2919 | int top = f->cursor_y * FONT_HEIGHT (f->display.x->font) | ||
| 2920 | + f->display.x->internal_border_width; | ||
| 2921 | int width = FONT_WIDTH (f->display.x->font); | 3092 | int width = FONT_WIDTH (f->display.x->font); |
| 2922 | int height = FONT_HEIGHT (f->display.x->font); | 3093 | int height = FONT_HEIGHT (f->display.x->font); |
| 2923 | 3094 | ||
| 2924 | #ifdef HAVE_X11 | 3095 | #ifdef HAVE_X11 |
| 2925 | /* Perhaps we should subtract 1 from width and height... */ | ||
| 2926 | XDrawRectangle (x_current_display, FRAME_X_WINDOW (f), | 3096 | XDrawRectangle (x_current_display, FRAME_X_WINDOW (f), |
| 2927 | f->display.x->cursor_gc, | 3097 | f->display.x->cursor_gc, |
| 2928 | left, top, width - 1, height - 1); | 3098 | left, top, width - 1, height - 1); |
| @@ -2962,18 +3132,10 @@ clear_cursor (f) | |||
| 2962 | 3132 | ||
| 2963 | #ifdef HAVE_X11 | 3133 | #ifdef HAVE_X11 |
| 2964 | x_display_cursor (f, 0); | 3134 | x_display_cursor (f, 0); |
| 2965 | #if 0 | ||
| 2966 | XClearArea (x_current_display, FRAME_X_WINDOW (f), | ||
| 2967 | f->phys_cursor_x * FONT_WIDTH (f->display.x->font) | ||
| 2968 | + f->display.x->internal_border_width, | ||
| 2969 | f->phys_cursor_y * FONT_HEIGHT (f->display.x->font) | ||
| 2970 | + f->display.x->internal_border_width, | ||
| 2971 | FONT_WIDTH (f->display.x->font) + 1, FONT_HEIGHT (f->display.x->font) + 1, False); | ||
| 2972 | #endif /* ! 0 */ | ||
| 2973 | #else /* ! defined (HAVE_X11) */ | 3135 | #else /* ! defined (HAVE_X11) */ |
| 2974 | XPixSet (FRAME_X_WINDOW (f), | 3136 | XPixSet (FRAME_X_WINDOW (f), |
| 2975 | f->phys_cursor_x * FONT_WIDTH (f->display.x->font) + f->display.x->internal_border_width, | 3137 | CHAR_TO_PIXEL_COL (f, f->phys_cursor_x), |
| 2976 | f->phys_cursor_y * FONT_HEIGHT (f->display.x->font) + f->display.x->internal_border_width, | 3138 | CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y), |
| 2977 | FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font), | 3139 | FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font), |
| 2978 | f->display.x->background_pixel); | 3140 | f->display.x->background_pixel); |
| 2979 | #endif /* ! defined (HAVE_X11) */ | 3141 | #endif /* ! defined (HAVE_X11) */ |
| @@ -2998,10 +3160,8 @@ x_display_bar_cursor (f, on) | |||
| 2998 | if (phys_x >= 0 && | 3160 | if (phys_x >= 0 && |
| 2999 | (!on || phys_x != f->cursor_x || phys_y != f->cursor_y)) | 3161 | (!on || phys_x != f->cursor_x || phys_y != f->cursor_y)) |
| 3000 | { | 3162 | { |
| 3001 | x1 = phys_x * FONT_WIDTH (f->display.x->font) | 3163 | x1 = CHAR_TO_PIXEL_COL (f, phys_x); |
| 3002 | + f->display.x->internal_border_width; | 3164 | y1 = CHAR_TO_PIXEL_ROW (f, phys_y) - 1; |
| 3003 | y1 = phys_y * FONT_HEIGHT (f->display.x->font) | ||
| 3004 | + f->display.x->internal_border_width - 1; | ||
| 3005 | y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; | 3165 | y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; |
| 3006 | 3166 | ||
| 3007 | XDrawLine (x_current_display, FRAME_X_WINDOW (f), | 3167 | XDrawLine (x_current_display, FRAME_X_WINDOW (f), |
| @@ -3012,10 +3172,8 @@ x_display_bar_cursor (f, on) | |||
| 3012 | 3172 | ||
| 3013 | if (on && f == x_highlight_frame) | 3173 | if (on && f == x_highlight_frame) |
| 3014 | { | 3174 | { |
| 3015 | x1 = f->cursor_x * FONT_WIDTH (f->display.x->font) | 3175 | x1 = CHAR_TO_PIXEL_COL (f, f->cursor_x); |
| 3016 | + f->display.x->internal_border_width; | 3176 | y1 = CHAR_TO_PIXEL_ROW (f, f->cursor_y) - 1; |
| 3017 | y1 = f->cursor_y * FONT_HEIGHT (f->display.x->font) | ||
| 3018 | + f->display.x->internal_border_width - 1; | ||
| 3019 | y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; | 3177 | y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; |
| 3020 | 3178 | ||
| 3021 | XDrawLine (x_current_display, FRAME_X_WINDOW (f), | 3179 | XDrawLine (x_current_display, FRAME_X_WINDOW (f), |
| @@ -3042,10 +3200,8 @@ x_draw_single_glyph (f, row, column, glyph, highlight) | |||
| 3042 | int highlight; | 3200 | int highlight; |
| 3043 | { | 3201 | { |
| 3044 | dumpglyphs (f, | 3202 | dumpglyphs (f, |
| 3045 | (column * FONT_WIDTH (f->display.x->font) | 3203 | CHAR_TO_PIXEL_COL (f, column), |
| 3046 | + f->display.x->internal_border_width), | 3204 | CHAR_TO_PIXEL_ROW (f, row), |
| 3047 | (row * FONT_HEIGHT (f->display.x->font) | ||
| 3048 | + f->display.x->internal_border_width), | ||
| 3049 | &glyph, 1, highlight, f->display.x->font); | 3205 | &glyph, 1, highlight, f->display.x->font); |
| 3050 | } | 3206 | } |
| 3051 | 3207 | ||
| @@ -3311,16 +3467,18 @@ x_text_icon (f, icon_name) | |||
| 3311 | 3467 | ||
| 3312 | /* Handling X errors. */ | 3468 | /* Handling X errors. */ |
| 3313 | 3469 | ||
| 3314 | /* A handler for SIGPIPE, when it occurs on the X server's connection. | 3470 | /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the |
| 3315 | This basically does an orderly shutdown of Emacs. */ | 3471 | X server's connection, or an error reported via the X protocol. */ |
| 3316 | 3472 | ||
| 3317 | static SIGTYPE | 3473 | static SIGTYPE |
| 3318 | x_connection_closed () | 3474 | x_connection_closed () |
| 3319 | { | 3475 | { |
| 3320 | if (_Xdebug) | 3476 | if (_Xdebug) |
| 3321 | abort (); | 3477 | abort (); |
| 3322 | else | 3478 | |
| 3323 | Fkill_emacs (make_number (70)); | 3479 | shut_down_emacs (0); |
| 3480 | |||
| 3481 | exit (70); | ||
| 3324 | } | 3482 | } |
| 3325 | 3483 | ||
| 3326 | /* An X error handler which prints an error message and then kills Emacs. | 3484 | /* An X error handler which prints an error message and then kills Emacs. |
| @@ -3333,10 +3491,6 @@ x_error_quitter (display, error) | |||
| 3333 | { | 3491 | { |
| 3334 | char buf[256]; | 3492 | char buf[256]; |
| 3335 | 3493 | ||
| 3336 | /* While we're testing Emacs 19, we'll just dump core whenever we | ||
| 3337 | get an X error, so we can figure out why it happened. */ | ||
| 3338 | abort (); | ||
| 3339 | |||
| 3340 | /* Note that there is no real way portable across R3/R4 to get the | 3494 | /* Note that there is no real way portable across R3/R4 to get the |
| 3341 | original error handler. */ | 3495 | original error handler. */ |
| 3342 | 3496 | ||
| @@ -3344,6 +3498,10 @@ x_error_quitter (display, error) | |||
| 3344 | fprintf (stderr, "X protocol error: %s on protocol request %d\n", | 3498 | fprintf (stderr, "X protocol error: %s on protocol request %d\n", |
| 3345 | buf, error->request_code); | 3499 | buf, error->request_code); |
| 3346 | 3500 | ||
| 3501 | /* While we're testing Emacs 19, we'll just dump core whenever we | ||
| 3502 | get an X error, so we can figure out why it happened. */ | ||
| 3503 | abort (); | ||
| 3504 | |||
| 3347 | x_connection_closed (); | 3505 | x_connection_closed (); |
| 3348 | } | 3506 | } |
| 3349 | 3507 | ||
| @@ -3613,7 +3771,6 @@ x_set_window_size (f, cols, rows) | |||
| 3613 | { | 3771 | { |
| 3614 | int pixelwidth, pixelheight; | 3772 | int pixelwidth, pixelheight; |
| 3615 | int mask; | 3773 | int mask; |
| 3616 | int ibw = f->display.x->internal_border_width; | ||
| 3617 | 3774 | ||
| 3618 | BLOCK_INPUT; | 3775 | BLOCK_INPUT; |
| 3619 | 3776 | ||
| @@ -3635,7 +3792,7 @@ x_set_window_size (f, cols, rows) | |||
| 3635 | change request eventually, and we'll hear how it went when the | 3792 | change request eventually, and we'll hear how it went when the |
| 3636 | ConfigureNotify event gets here. */ | 3793 | ConfigureNotify event gets here. */ |
| 3637 | FRAME_WIDTH (f) = cols; | 3794 | FRAME_WIDTH (f) = cols; |
| 3638 | FRAME_WIDTH (f) = rows; | 3795 | FRAME_HEIGHT (f) = rows; |
| 3639 | PIXEL_WIDTH (f) = pixelwidth; | 3796 | PIXEL_WIDTH (f) = pixelwidth; |
| 3640 | PIXEL_HEIGHT (f) = pixelheight; | 3797 | PIXEL_HEIGHT (f) = pixelheight; |
| 3641 | 3798 | ||
| @@ -3647,10 +3804,11 @@ x_set_window_size (f, cols, rows) | |||
| 3647 | x_set_resize_hint (f) | 3804 | x_set_resize_hint (f) |
| 3648 | struct frame *f; | 3805 | struct frame *f; |
| 3649 | { | 3806 | { |
| 3650 | 3807 | XSetResizeHint (FRAME_X_WINDOW (f), | |
| 3651 | XSetResizeHint (FRAME_X_WINDOW (f), 2 * f->display.x->internal_border_width, | 3808 | 2 * f->display.x->internal_border_width, |
| 3652 | 2 * f->display.x->internal_border_width, | 3809 | 2 * f->display.x->internal_border_width, |
| 3653 | FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font)); | 3810 | FONT_WIDTH (f->display.x->font), |
| 3811 | FONT_HEIGHT (f->display.x->font)); | ||
| 3654 | } | 3812 | } |
| 3655 | #endif /* HAVE_X11 */ | 3813 | #endif /* HAVE_X11 */ |
| 3656 | 3814 | ||
| @@ -3664,12 +3822,8 @@ x_set_mouse_position (f, x, y) | |||
| 3664 | 3822 | ||
| 3665 | x_raise_frame (f); | 3823 | x_raise_frame (f); |
| 3666 | 3824 | ||
| 3667 | pix_x = (f->display.x->internal_border_width | 3825 | pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2; |
| 3668 | + x * FONT_WIDTH (f->display.x->font) | 3826 | pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2; |
| 3669 | + FONT_WIDTH (f->display.x->font) / 2); | ||
| 3670 | pix_y = (f->display.x->internal_border_width | ||
| 3671 | + y * FONT_HEIGHT (f->display.x->font) | ||
| 3672 | + FONT_HEIGHT (f->display.x->font) / 2); | ||
| 3673 | 3827 | ||
| 3674 | if (pix_x < 0) pix_x = 0; | 3828 | if (pix_x < 0) pix_x = 0; |
| 3675 | if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f); | 3829 | if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f); |
| @@ -4016,8 +4170,8 @@ x_wm_set_size_hint (f, prompting) | |||
| 4016 | size_hints.width = PIXEL_WIDTH (f); | 4170 | size_hints.width = PIXEL_WIDTH (f); |
| 4017 | size_hints.width_inc = FONT_WIDTH (f->display.x->font); | 4171 | size_hints.width_inc = FONT_WIDTH (f->display.x->font); |
| 4018 | size_hints.height_inc = FONT_HEIGHT (f->display.x->font); | 4172 | size_hints.height_inc = FONT_HEIGHT (f->display.x->font); |
| 4019 | size_hints.max_width = PIXEL_TO_CHAR_WIDTH (f, x_screen_width); | 4173 | size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0); |
| 4020 | size_hints.max_height = PIXEL_TO_CHAR_HEIGHT (f, x_screen_height); | 4174 | size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0); |
| 4021 | 4175 | ||
| 4022 | { | 4176 | { |
| 4023 | int base_width, base_height; | 4177 | int base_width, base_height; |
| @@ -4128,17 +4282,6 @@ x_term_init (display_name) | |||
| 4128 | extern int old_fcntl_owner; | 4282 | extern int old_fcntl_owner; |
| 4129 | #endif /* ! defined (F_SETOWN) */ | 4283 | #endif /* ! defined (F_SETOWN) */ |
| 4130 | 4284 | ||
| 4131 | { | ||
| 4132 | fprintf (stderr, "\ | ||
| 4133 | Hey! The Emacs 19 sources currently contain incomplete changes | ||
| 4134 | for scrollbars, and don't run properly under X! | ||
| 4135 | |||
| 4136 | It is supposed to work under termcap, though. | ||
| 4137 | |||
| 4138 | -JimB"); | ||
| 4139 | } | ||
| 4140 | |||
| 4141 | |||
| 4142 | x_focus_frame = x_highlight_frame = 0; | 4285 | x_focus_frame = x_highlight_frame = 0; |
| 4143 | 4286 | ||
| 4144 | x_current_display = XOpenDisplay (display_name); | 4287 | x_current_display = XOpenDisplay (display_name); |
| @@ -4243,7 +4386,7 @@ It is supposed to work under termcap, though. | |||
| 4243 | reassert_line_highlight_hook = XTreassert_line_highlight; | 4386 | reassert_line_highlight_hook = XTreassert_line_highlight; |
| 4244 | mouse_position_hook = XTmouse_position; | 4387 | mouse_position_hook = XTmouse_position; |
| 4245 | frame_rehighlight_hook = XTframe_rehighlight; | 4388 | frame_rehighlight_hook = XTframe_rehighlight; |
| 4246 | set_vertical_scrollbar_hook = XTset_scrollbar; | 4389 | set_vertical_scrollbar_hook = XTset_vertical_scrollbar; |
| 4247 | condemn_scrollbars_hook = XTcondemn_scrollbars; | 4390 | condemn_scrollbars_hook = XTcondemn_scrollbars; |
| 4248 | redeem_scrollbar_hook = XTredeem_scrollbar; | 4391 | redeem_scrollbar_hook = XTredeem_scrollbar; |
| 4249 | judge_scrollbars_hook = XTjudge_scrollbars; | 4392 | judge_scrollbars_hook = XTjudge_scrollbars; |
| @@ -4274,6 +4417,8 @@ syms_of_xterm () | |||
| 4274 | { | 4417 | { |
| 4275 | staticpro (&invocation_name); | 4418 | staticpro (&invocation_name); |
| 4276 | invocation_name = Qnil; | 4419 | invocation_name = Qnil; |
| 4420 | |||
| 4421 | staticpro (&last_mouse_scrollbar); | ||
| 4277 | } | 4422 | } |
| 4278 | #endif /* ! defined (HAVE_X11) */ | 4423 | #endif /* ! defined (HAVE_X11) */ |
| 4279 | #endif /* ! defined (HAVE_X_WINDOWS) */ | 4424 | #endif /* ! defined (HAVE_X_WINDOWS) */ |