diff options
| author | Jim Blandy | 1992-12-24 06:21:14 +0000 |
|---|---|---|
| committer | Jim Blandy | 1992-12-24 06:21:14 +0000 |
| commit | f451eb1325e3c003d074a810e4096cf9979953b8 (patch) | |
| tree | 1bd7587ed2219bdcaad8b56b44c66b0d68fdc864 /src | |
| parent | 179956b9a45158eafca42eb0d9071281a63bd3c2 (diff) | |
| download | emacs-f451eb1325e3c003d074a810e4096cf9979953b8.tar.gz emacs-f451eb1325e3c003d074a810e4096cf9979953b8.zip | |
* frame.h (struct frame): New fields `can_have_scrollbars' and
`has_vertical_scrollbars'.
(FRAME_CAN_HAVE_SCROLLBARS, FRAME_HAS_VERTICAL_SCROLLBARS): New
accessors, for both the MULTI_FRAME and non-MULTI_FRAME.
(VERTICAL_SCROLLBAR_WIDTH, WINDOW_VERTICAL_SCROLLBAR,
WINDOW_VERTICAL_SCROLLBAR_COLUMN,
WINDOW_VERTICAL_SCROLLBAR_HEIGHT): New macros.
* window.h (struct window): New field `vertical_scrollbar'.
* xterm.h (struct x_display): vertical_scrollbars,
judge_timestamp, vertical_scrollbar_extra: New fields.
(struct scrollbar): New struct.
(VERTICAL_SCROLLBAR_PIXEL_WIDTH, VERTICAL_SCROLLBAR_PIXEL_HEIGHT,
VERTICAL_SCROLLBAR_LEFT_BORDER, VERTICAL_SCROLLBAR_RIGHT_BORDER,
VERTICAL_SCROLLBAR_TOP_BORDER, VERTICAL_SCROLLBAR_BOTTOM_BORDER,
CHAR_TO_PIXEL_WIDTH, CHAR_TO_PIXEL_HEIGHT, PIXEL_TO_CHAR_WIDTH,
PIXEL_TO_CHAR_HEIGHT): New accessors and macros.
* frame.c (make_frame): Initialize the `can_have_scrollbars' and
`has_vertical_scrollbars' fields of the frame.
* term.c (term_init): Note that TERMCAP terminals don't support
scrollbars.
(mouse_position_hook): Document new args.
(set_vertical_scrollbar_hook, condemn_scrollbars_hook,
redeem_scrollbar_hook, judge_scrollbars_hook): New hooks.
* termhooks.h: Declare and document them.
(enum scrollbar_part): New type.
(struct input_event): Describe the new form of the scrollbar_click
event type. Change `part' from a Lisp_Object to an enum
scrollbar_part. Add a new field `scrollbar'.
* keyboard.c (kbd_buffer_get_event): Pass appropriate new
parameters to *mouse_position_hook, and make_lispy_movement.
* xfns.c (x_set_vertical_scrollbar): New function.
(x_figure_window_size): Use new macros to calculate frame size.
(Fx_create_frame): Note that X Windows frames do support scroll
bars. Default to "yes".
* xterm.c: #include <X11/cursorfont.h> and "window.h".
(x_vertical_scrollbar_cursor): New variable.
(x_term_init): Initialize it.
(last_mouse_bar, last_mouse_bar_frame, last_mouse_part,
last_mouse_scroll_range_start, last_mouse_scroll_range_end): New
variables.
(XTmouse_position): Use them to return scrollbar movement events.
Take new arguments, for that purpose.
(x_window_to_scrollbar, x_scrollbar_create,
x_scrollbar_set_handle, x_scrollbar_remove, x_scrollbar_move,
XTset_scrollbar, XTcondemn_scrollbars, XTredeem_scrollbar,
XTjudge_scrollbars, x_scrollbar_expose,
x_scrollbar_background_expose, x_scrollbar_handle_click,
x_scrollbar_handle_motion): New functions to implement scrollbars.
(x_term_init): Set the termhooks.h hooks to point to them.
(x_set_window_size): Use new macros to calculate frame size. Set
vertical_scrollbar_extra field.
(x_make_frame_visible): Use the frame accessor
FRAME_HAS_VERTICAL_SCROLLBARS to decide if we need to map the
frame's subwindows as well.
(XTread_socket): Use new size-calculation macros from xterm.h when
processing ConfigureNotify events.
(x_wm_set_size_hint): Use PIXEL_TO_CHAR_WIDTH and
PIXEL_TO_CHAR_HEIGHT macros.
* ymakefile (xdisp.o): This now depends on termhooks.h.
(xterm.o): This now depends on window.h.
* xterm.h (struct x_display): Delete v_scrollbar, v_thumbup,
v_thumbdown, v_slider, h_scrollbar, h_thumbup,
h_thumbdown, h_slider, v_scrollbar_width, h_scrollbar_height
fields.
* keyboard.c (Qvscrollbar_part, Qvslider_part, Qvthumbup_part,
Qvthumbdown_part, Qhscrollbar_part, Qhslider_part, Qhthumbup_part,
Qhthumbdown_part, Qscrollbar_click): Deleted; part of an obsolete
interface.
(head_table): Removed from here as well.
(syms_of_keyboard): And here.
* keyboard.h: And here.
(POSN_SCROLLBAR_BUTTON): Removed.
* xscrollbar.h: File removed - no longer necessary.
* xfns.c: Don't #include it any more.
(Qhorizontal_scroll_bar, Qvertical_scroll_bar): Deleted.
(syms_of_xfns): Don't initialize or staticpro them.
(gray_bits): Salvaged from xscrollbar.h.
(x_window_to_scrollbar): Deleted.
(x_set_horizontal_scrollbar): Deleted.
(enum x_frame_parm, x_frame_parms): Remove references to
x_set_horizontal_scrollbar.
(x_set_foreground_color, x_set_background_color,
x_set_border_pixel): Remove special code to support scrollbars.
(Fx_create_frame): Remove old scrollbar setup code.
(install_vertical_scrollbar, install_horizontal_scrollbar,
adjust_scrollbars, x_resize_scrollbars): Deleted.
* xterm.c (construct_mouse_click): This doesn't need to take care of
scrollbar clicks anymore.
(XTread_socket): Remove old code to support scrollbars. Call new
functions instead for events which occur in scrollbar windows.
(XTupdate_end): Remove call to adjust_scrollbars; the main
redisplay code takes care of that now.
(enum window_type): Deleted.
* ymakefile: Note that xfns.o no longer depends on xscrollbar.h.
* xterm.c (x_set_mouse_position): Clip mouse position to be within
frame.
* xterm.c: Adjust the first line of each page to have a reasonable
description. This makes pages-directory more useful.
* xterm.c (x_do_pending_expose): Declare this routine only if
HAVE_X11 is not #defined; X11 doesn't need it.
(XTread_socket): Protect call to x_do_pending_expose with `#ifdef
HAVE_X11'.
* xterm.c (notice_mouse_movement): Deleted; obsolete and unused.
Properly handle focus shift events, so the cursor is filled and
hollow at the appropriate times, even in titleless windows.
* xterm.c (x_focus_event_frame): New variable.
(XTread_socket): When we receive a FocusIn event that's not
NotifyPointer, record the frame in x_focus_event_frame. When we
receive a FocusOut event that's not NotifyPointer, clear it. When
we get a LeaveNotify event, don't take it seriously if we still
have focus.
* xterm.c (XTread_socket): Remove special code in EnterNotify case
to handle scrollbars and fake mouse motion events.
Change the meaning of focus redirection to make switching windows
work properly. Fredirect_frame_focus has the details.
* frame.h (focus_frame): Doc fix.
[not MULTI_FRAME] (FRAME_FOCUS_FRAME): Make this Qnil, which
indicates no focus redirection, instead of zero, which is
selected_frame.
* frame.c (make_frame): Initialize f->focus_frame to Qnil, rather
than making it point to frame itself.
(Fselect_frame): If changing the selected frame from FOO to BAR,
make all redirections to FOO shift to BAR as well. Doc fix.
(Fredirect_frame_focus): Doc fix. Accept nil as a valid
redirection, not just as a default for FRAME.
(Fframe_focus): Doc fix.
* keyboard.c (kbd_buffer_store_event, kbd_buffer_get_event): Deal
with focus redirections being nil.
* xterm.c (XTframe_rehighlight): Doc fix. Deal with focus
redirections being nil.
* xterm.c (x_error_quitter): Just abort, so we can look at the
core to see what happened.
It's a pain to remember that you can't assign to FRAME->visible.
Let's change all references to the `visible' member of struct
frame to use the accessor macros, and then write a setter for the
`visible' field that does the right thing.
* frame.h (FRAME_VISIBLE_P): Make this not an l-value.
(FRAME_SET_VISIBLE): New macro.
* frame.c (make_terminal_frame, Fdelete_frame): Use FRAME_SET_VISIBLE.
(Fframe_visible_p, Fvisible_frame_list): Use FRAME_VISIBLE_P and
FRAME_ICONIFIED_P.
* dispnew.c (Fredraw_display): Use the FRAME_VISIBLE_P and
FRAME_GARBAGED_P accessors.
* xdisp.c (redisplay): Use the FRAME_VISIBLE_P accessor.
* xfns.c (x_set_foreground_color, x_set_background_color,
x_set_cursor_color, x_set_border_pixel, x_set_icon_type): Use the
FRAME_VISIBLE_P accessor.
(Fx_create_frame): Use FRAME_SET_VISIBILITY.
* xterm.c (clear_cursor, x_display_bar_cursor,
x_display_box_cursor): Use FRAME_SET_VISIBILITY.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 1003 |
1 files changed, 699 insertions, 304 deletions
diff --git a/src/xterm.c b/src/xterm.c index 57933e35f31..70d5c9bab0d 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -38,6 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 38 | /* This may include sys/types.h, and that somehow loses | 38 | /* This may include sys/types.h, and that somehow loses |
| 39 | if this is not done before the other system files. */ | 39 | if this is not done before the other system files. */ |
| 40 | #include "xterm.h" | 40 | #include "xterm.h" |
| 41 | #include <X11/cursorfont.h> | ||
| 41 | 42 | ||
| 42 | #ifndef USG | 43 | #ifndef USG |
| 43 | /* Load sys/types.h if not already loaded. | 44 | /* Load sys/types.h if not already loaded. |
| @@ -89,6 +90,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 89 | #include "frame.h" | 90 | #include "frame.h" |
| 90 | #include "disptab.h" | 91 | #include "disptab.h" |
| 91 | #include "buffer.h" | 92 | #include "buffer.h" |
| 93 | #include "window.h" | ||
| 92 | 94 | ||
| 93 | #ifdef HAVE_X11 | 95 | #ifdef HAVE_X11 |
| 94 | #define XMapWindow XMapRaised /* Raise them when mapping. */ | 96 | #define XMapWindow XMapRaised /* Raise them when mapping. */ |
| @@ -105,8 +107,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 105 | 107 | ||
| 106 | /* Nonzero means we must reprint all windows | 108 | /* Nonzero means we must reprint all windows |
| 107 | because 1) we received an ExposeWindow event | 109 | because 1) we received an ExposeWindow event |
| 108 | or 2) we received too many ExposeRegion events to record. */ | 110 | or 2) we received too many ExposeRegion events to record. |
| 109 | 111 | ||
| 112 | This is never needed under X11. */ | ||
| 110 | static int expose_all_windows; | 113 | static int expose_all_windows; |
| 111 | 114 | ||
| 112 | /* Nonzero means we must reprint all icon windows. */ | 115 | /* Nonzero means we must reprint all icon windows. */ |
| @@ -159,6 +162,9 @@ Lisp_Object invocation_name; | |||
| 159 | 162 | ||
| 160 | Display *x_current_display; | 163 | Display *x_current_display; |
| 161 | 164 | ||
| 165 | /* The cursor to use for vertical scrollbars on x_current_display. */ | ||
| 166 | static Cursor x_vertical_scrollbar_cursor; | ||
| 167 | |||
| 162 | /* Frame being updated by update_frame. */ | 168 | /* Frame being updated by update_frame. */ |
| 163 | /* This is set by XTupdate_begin and looked at by all the | 169 | /* This is set by XTupdate_begin and looked at by all the |
| 164 | XT functions. It is zero while not inside an update. | 170 | XT functions. It is zero while not inside an update. |
| @@ -168,9 +174,18 @@ Display *x_current_display; | |||
| 168 | static struct frame *updating_frame; | 174 | static struct frame *updating_frame; |
| 169 | 175 | ||
| 170 | /* The frame (if any) which has the X window that has keyboard focus. | 176 | /* The frame (if any) which has the X window that has keyboard focus. |
| 171 | Zero if none. This is examined by Ffocus_frame in frame.c. */ | 177 | Zero if none. This is examined by Ffocus_frame in frame.c. Note |
| 178 | that a mere EnterNotify event can set this; if you need to know the | ||
| 179 | last frame specified in a FocusIn or FocusOut event, use | ||
| 180 | x_focus_event_frame. */ | ||
| 172 | struct frame *x_focus_frame; | 181 | struct frame *x_focus_frame; |
| 173 | 182 | ||
| 183 | /* The last frame mentioned in a FocusIn or FocusOut event. This is | ||
| 184 | separate from x_focus_frame, because whether or not LeaveNotify | ||
| 185 | events cause us to lose focus depends on whether or not we have | ||
| 186 | received a FocusIn event for it. */ | ||
| 187 | struct frame *x_focus_event_frame; | ||
| 188 | |||
| 174 | /* The frame which currently has the visual highlight, and should get | 189 | /* The frame which currently has the visual highlight, and should get |
| 175 | keyboard input (other sorts of input have the frame encoded in the | 190 | keyboard input (other sorts of input have the frame encoded in the |
| 176 | event). It points to the X focus frame's selected window's | 191 | event). It points to the X focus frame's selected window's |
| @@ -260,7 +275,9 @@ static int XTcursor_to (); | |||
| 260 | static int XTclear_end_of_line (); | 275 | static int XTclear_end_of_line (); |
| 261 | 276 | ||
| 262 | 277 | ||
| 263 | /* These hooks are called by update_frame at the beginning and end | 278 | /* Starting and ending updates. |
| 279 | |||
| 280 | These hooks are called by update_frame at the beginning and end | ||
| 264 | of a frame update. We record in `updating_frame' the identity | 281 | of a frame update. We record in `updating_frame' the identity |
| 265 | of the frame being updated, so that the XT... functions do not | 282 | of the frame being updated, so that the XT... functions do not |
| 266 | need to take a frame as argument. Most of the XT... functions | 283 | need to take a frame as argument. Most of the XT... functions |
| @@ -289,7 +306,9 @@ XTupdate_begin (f) | |||
| 289 | UNBLOCK_INPUT; | 306 | UNBLOCK_INPUT; |
| 290 | } | 307 | } |
| 291 | 308 | ||
| 309 | #ifndef HAVE_X11 | ||
| 292 | static void x_do_pending_expose (); | 310 | static void x_do_pending_expose (); |
| 311 | #endif | ||
| 293 | 312 | ||
| 294 | static | 313 | static |
| 295 | XTupdate_end (f) | 314 | XTupdate_end (f) |
| @@ -304,9 +323,8 @@ XTupdate_end (f) | |||
| 304 | BLOCK_INPUT; | 323 | BLOCK_INPUT; |
| 305 | #ifndef HAVE_X11 | 324 | #ifndef HAVE_X11 |
| 306 | dumpqueue (); | 325 | dumpqueue (); |
| 307 | #endif /* HAVE_X11 */ | ||
| 308 | adjust_scrollbars (f); | ||
| 309 | x_do_pending_expose (); | 326 | x_do_pending_expose (); |
| 327 | #endif /* HAVE_X11 */ | ||
| 310 | 328 | ||
| 311 | x_display_cursor (f, 1); | 329 | x_display_cursor (f, 1); |
| 312 | 330 | ||
| @@ -356,8 +374,8 @@ XTreset_terminal_modes () | |||
| 356 | /* XTclear_frame (); */ | 374 | /* XTclear_frame (); */ |
| 357 | } | 375 | } |
| 358 | 376 | ||
| 359 | /* Set the nominal cursor position of the frame: | 377 | /* Set the nominal cursor position of the frame. |
| 360 | where display update commands will take effect. | 378 | This is where display update commands will take effect. |
| 361 | This does not affect the place where the cursor-box is displayed. */ | 379 | This does not affect the place where the cursor-box is displayed. */ |
| 362 | 380 | ||
| 363 | static int | 381 | static int |
| @@ -524,8 +542,8 @@ dumpglyphs (f, left, top, gp, n, hl, font) | |||
| 524 | } | 542 | } |
| 525 | #endif /* ! 0 */ | 543 | #endif /* ! 0 */ |
| 526 | 544 | ||
| 527 | /* Output some text at the nominal frame cursor position, | 545 | /* Output some text at the nominal frame cursor position. |
| 528 | advancing the cursor over the text. | 546 | Advance the cursor over the text. |
| 529 | Output LEN glyphs at START. | 547 | Output LEN glyphs at START. |
| 530 | 548 | ||
| 531 | `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight, | 549 | `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight, |
| @@ -577,7 +595,8 @@ XTwrite_glyphs (start, len) | |||
| 577 | UNBLOCK_INPUT; | 595 | UNBLOCK_INPUT; |
| 578 | } | 596 | } |
| 579 | 597 | ||
| 580 | /* Erase the current text line from the nominal cursor position (inclusive) | 598 | /* Clear to the end of the line. |
| 599 | Erase the current text line from the nominal cursor position (inclusive) | ||
| 581 | to column FIRST_UNUSED (exclusive). The idea is that everything | 600 | to column FIRST_UNUSED (exclusive). The idea is that everything |
| 582 | from FIRST_UNUSED onward is already erased. */ | 601 | from FIRST_UNUSED onward is already erased. */ |
| 583 | 602 | ||
| @@ -758,8 +777,9 @@ XTring_bell () | |||
| 758 | } | 777 | } |
| 759 | } | 778 | } |
| 760 | 779 | ||
| 761 | /* Insert and delete character are not supposed to be used | 780 | /* Insert and delete character. |
| 762 | because we are supposed to turn off the feature of using them. */ | 781 | These are not supposed to be used because we are supposed to turn |
| 782 | off the feature of using them. */ | ||
| 763 | 783 | ||
| 764 | static | 784 | static |
| 765 | XTinsert_glyphs (start, len) | 785 | XTinsert_glyphs (start, len) |
| @@ -794,8 +814,8 @@ XTset_terminal_window (n) | |||
| 794 | flexlines = n; | 814 | flexlines = n; |
| 795 | } | 815 | } |
| 796 | 816 | ||
| 797 | /* Perform an insert-lines operation, inserting N lines | 817 | /* Perform an insert-lines operation. |
| 798 | at a vertical position curs_y. */ | 818 | Insert N lines at a vertical position curs_y. */ |
| 799 | 819 | ||
| 800 | static void | 820 | static void |
| 801 | stufflines (n) | 821 | stufflines (n) |
| @@ -955,6 +975,7 @@ XTins_del_lines (vpos, n) | |||
| 955 | UNBLOCK_INPUT; | 975 | UNBLOCK_INPUT; |
| 956 | } | 976 | } |
| 957 | 977 | ||
| 978 | /* Support routines for exposure events. */ | ||
| 958 | static void clear_cursor (); | 979 | static void clear_cursor (); |
| 959 | 980 | ||
| 960 | /* Output into a rectangle of an X-window (for frame F) | 981 | /* Output into a rectangle of an X-window (for frame F) |
| @@ -1072,10 +1093,11 @@ dumpqueue () | |||
| 1072 | } | 1093 | } |
| 1073 | #endif /* HAVE_X11 */ | 1094 | #endif /* HAVE_X11 */ |
| 1074 | 1095 | ||
| 1075 | /* Process all expose events that are pending. | 1096 | /* Process all expose events that are pending, for X10. |
| 1076 | Redraws the cursor if necessary on any frame that | 1097 | Redraws the cursor if necessary on any frame that |
| 1077 | is not in the process of being updated with update_frame. */ | 1098 | is not in the process of being updated with update_frame. */ |
| 1078 | 1099 | ||
| 1100 | #ifndef HAVE_X11 | ||
| 1079 | static void | 1101 | static void |
| 1080 | x_do_pending_expose () | 1102 | x_do_pending_expose () |
| 1081 | { | 1103 | { |
| @@ -1139,6 +1161,7 @@ x_do_pending_expose () | |||
| 1139 | dumpqueue (); | 1161 | dumpqueue (); |
| 1140 | #endif /* ! defined (HAVE_X11) */ | 1162 | #endif /* ! defined (HAVE_X11) */ |
| 1141 | } | 1163 | } |
| 1164 | #endif | ||
| 1142 | 1165 | ||
| 1143 | #ifdef HAVE_X11 | 1166 | #ifdef HAVE_X11 |
| 1144 | static void | 1167 | static void |
| @@ -1245,9 +1268,9 @@ x_new_focus_frame (frame) | |||
| 1245 | } | 1268 | } |
| 1246 | 1269 | ||
| 1247 | 1270 | ||
| 1248 | /* The focus has changed, or we have make a frame's selected window | 1271 | /* The focus has changed, or we have redirected a frame's focus to |
| 1249 | point to a window on a different frame (this happens with global | 1272 | another frame (this happens when a frame uses a surrogate |
| 1250 | minibuffer frames). Shift the highlight as appropriate. */ | 1273 | minibuffer frame). Shift the highlight as appropriate. */ |
| 1251 | static void | 1274 | static void |
| 1252 | XTframe_rehighlight () | 1275 | XTframe_rehighlight () |
| 1253 | { | 1276 | { |
| @@ -1255,10 +1278,15 @@ XTframe_rehighlight () | |||
| 1255 | 1278 | ||
| 1256 | if (x_focus_frame) | 1279 | if (x_focus_frame) |
| 1257 | { | 1280 | { |
| 1258 | x_highlight_frame = XFRAME (FRAME_FOCUS_FRAME (x_focus_frame)); | 1281 | x_highlight_frame = |
| 1259 | if (x_highlight_frame->display.nothing == 0) | 1282 | ((XTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame) |
| 1260 | XSET (FRAME_FOCUS_FRAME (x_focus_frame), Lisp_Frame, | 1283 | ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame)) |
| 1261 | (x_highlight_frame = x_focus_frame)); | 1284 | : x_focus_frame); |
| 1285 | if (! FRAME_LIVE_P (x_highlight_frame)) | ||
| 1286 | { | ||
| 1287 | FRAME_FOCUS_FRAME (x_focus_frame) = Qnil; | ||
| 1288 | x_highlight_frame = x_focus_frame; | ||
| 1289 | } | ||
| 1262 | } | 1290 | } |
| 1263 | else | 1291 | else |
| 1264 | x_highlight_frame = 0; | 1292 | x_highlight_frame = 0; |
| @@ -1272,114 +1300,6 @@ XTframe_rehighlight () | |||
| 1272 | } | 1300 | } |
| 1273 | } | 1301 | } |
| 1274 | 1302 | ||
| 1275 | enum window_type | ||
| 1276 | { | ||
| 1277 | no_window, | ||
| 1278 | scrollbar_window, | ||
| 1279 | text_window, | ||
| 1280 | }; | ||
| 1281 | |||
| 1282 | /* Position of the mouse in characters */ | ||
| 1283 | unsigned int x_mouse_x, x_mouse_y; | ||
| 1284 | |||
| 1285 | /* Offset in buffer of character under the pointer, or 0. */ | ||
| 1286 | extern int mouse_buffer_offset; | ||
| 1287 | |||
| 1288 | extern int buffer_posn_from_coords (); | ||
| 1289 | |||
| 1290 | /* Symbols from xfns.c to denote the different parts of a window. */ | ||
| 1291 | extern Lisp_Object Qmodeline_part, Qtext_part; | ||
| 1292 | |||
| 1293 | #if 0 | ||
| 1294 | /* Set *RESULT to an emacs input_event corresponding to MOTION_EVENT. | ||
| 1295 | F is the frame in which the event occurred. | ||
| 1296 | |||
| 1297 | WINDOW_TYPE says whether the event happened in a scrollbar window | ||
| 1298 | or a text window, affecting the format of the event created. | ||
| 1299 | |||
| 1300 | PART specifies which part of the scrollbar the event happened in, | ||
| 1301 | if WINDOW_TYPE == scrollbar_window. | ||
| 1302 | |||
| 1303 | If the mouse is over the same character as the last time we checked, | ||
| 1304 | don't return an event; set result->kind to no_event. */ | ||
| 1305 | |||
| 1306 | static void | ||
| 1307 | notice_mouse_movement (result, motion_event, f, window_type, part) | ||
| 1308 | struct input_event *result; | ||
| 1309 | XMotionEvent motion_event; | ||
| 1310 | struct frame *f; | ||
| 1311 | int window_type; | ||
| 1312 | Lisp_Object part; | ||
| 1313 | { | ||
| 1314 | int x, y, root_x, root_y, pix_x, pix_y; | ||
| 1315 | unsigned int keys_and_buttons; | ||
| 1316 | Window w, root_window; | ||
| 1317 | |||
| 1318 | /* Unless we decide otherwise below, return a non-event. */ | ||
| 1319 | result->kind = no_event; | ||
| 1320 | |||
| 1321 | if (XQueryPointer (x_current_display, | ||
| 1322 | FRAME_X_WINDOW (f), | ||
| 1323 | &root_window, &w, | ||
| 1324 | &root_x, &root_y, &pix_x, &pix_y, | ||
| 1325 | &keys_and_buttons) | ||
| 1326 | == False) | ||
| 1327 | return; | ||
| 1328 | |||
| 1329 | #if 0 | ||
| 1330 | if (w == None) /* Mouse no longer in window. */ | ||
| 1331 | return Qnil; | ||
| 1332 | #endif /* ! 0 */ | ||
| 1333 | |||
| 1334 | pixel_to_glyph_translation (f, pix_x, pix_y, &x, &y); | ||
| 1335 | if (x == x_mouse_x && y == x_mouse_y) | ||
| 1336 | return; | ||
| 1337 | |||
| 1338 | x_mouse_x = x; | ||
| 1339 | x_mouse_y = y; | ||
| 1340 | |||
| 1341 | /* What sort of window are we in now? */ | ||
| 1342 | if (window_type == text_window) /* Text part */ | ||
| 1343 | { | ||
| 1344 | int modeline_p; | ||
| 1345 | |||
| 1346 | Vmouse_window = window_from_coordinates (f, x, y, &modeline_p); | ||
| 1347 | |||
| 1348 | if (XTYPE (Vmouse_window) == Lisp_Window) | ||
| 1349 | mouse_buffer_offset | ||
| 1350 | = buffer_posn_from_coords (XWINDOW (Vmouse_window), x, y); | ||
| 1351 | else | ||
| 1352 | mouse_buffer_offset = 0; | ||
| 1353 | |||
| 1354 | if (EQ (Vmouse_window, Qnil)) | ||
| 1355 | Vmouse_frame_part = Qnil; | ||
| 1356 | else if (modeline_p) | ||
| 1357 | Vmouse_frame_part = Qmodeline_part; | ||
| 1358 | else | ||
| 1359 | Vmouse_frame_part = Qtext_part; | ||
| 1360 | |||
| 1361 | result->kind = window_sys_event; | ||
| 1362 | result->code = Qmouse_moved; | ||
| 1363 | |||
| 1364 | return; | ||
| 1365 | } | ||
| 1366 | else if (window_type == scrollbar_window) /* Scrollbar */ | ||
| 1367 | { | ||
| 1368 | Vmouse_window = f->selected_window; | ||
| 1369 | mouse_buffer_offset = 0; | ||
| 1370 | Vmouse_frame_part = part; | ||
| 1371 | |||
| 1372 | result->kind = window_sys_event; | ||
| 1373 | result->code = Qmouse_moved; | ||
| 1374 | |||
| 1375 | return; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | return; | ||
| 1379 | } | ||
| 1380 | #endif /* ! 0 */ | ||
| 1381 | |||
| 1382 | |||
| 1383 | /* Mouse clicks and mouse movement. Rah. */ | 1303 | /* Mouse clicks and mouse movement. Rah. */ |
| 1384 | #ifdef HAVE_X11 | 1304 | #ifdef HAVE_X11 |
| 1385 | 1305 | ||
| @@ -1531,30 +1451,21 @@ x_convert_modifiers (state) | |||
| 1531 | | ((state & x_meta_mod_mask) ? meta_modifier : 0)); | 1451 | | ((state & x_meta_mod_mask) ? meta_modifier : 0)); |
| 1532 | } | 1452 | } |
| 1533 | 1453 | ||
| 1534 | extern struct frame *x_window_to_scrollbar (); | ||
| 1535 | extern Lisp_Object Vmouse_event; | ||
| 1536 | |||
| 1537 | /* Prepare a mouse-event in *RESULT for placement in the input queue. | 1454 | /* Prepare a mouse-event in *RESULT for placement in the input queue. |
| 1538 | 1455 | ||
| 1539 | If the event is a button press, then note that we have grabbed | 1456 | If the event is a button press, then note that we have grabbed |
| 1540 | the mouse. | 1457 | the mouse. */ |
| 1541 | |||
| 1542 | If PART and PREFIX are 0, then the event occurred in the text part; | ||
| 1543 | otherwise it happened in a scrollbar. */ | ||
| 1544 | 1458 | ||
| 1545 | static Lisp_Object | 1459 | static Lisp_Object |
| 1546 | construct_mouse_click (result, event, f, part, prefix) | 1460 | construct_mouse_click (result, event, f) |
| 1547 | struct input_event *result; | 1461 | struct input_event *result; |
| 1548 | XButtonEvent *event; | 1462 | XButtonEvent *event; |
| 1549 | struct frame *f; | 1463 | struct frame *f; |
| 1550 | int prefix; | ||
| 1551 | Lisp_Object part; | ||
| 1552 | { | 1464 | { |
| 1553 | /* Initialize those fields text and scrollbar clicks hold in common. | 1465 | /* Make the event type no_event; we'll change that when we decide |
| 1554 | Make the event type no_event; we'll change that when we decide | ||
| 1555 | otherwise. */ | 1466 | otherwise. */ |
| 1556 | result->kind = no_event; | 1467 | result->kind = mouse_click; |
| 1557 | XSET (result->code, Lisp_Int, event->button); | 1468 | XSET (result->code, Lisp_Int, event->button - Button1); |
| 1558 | result->timestamp = event->time; | 1469 | result->timestamp = event->time; |
| 1559 | result->modifiers = (x_convert_modifiers (event->state) | 1470 | result->modifiers = (x_convert_modifiers (event->state) |
| 1560 | | (event->type == ButtonRelease | 1471 | | (event->type == ButtonRelease |
| @@ -1575,33 +1486,14 @@ construct_mouse_click (result, event, f, part, prefix) | |||
| 1575 | Vmouse_depressed = Qnil; | 1486 | Vmouse_depressed = Qnil; |
| 1576 | } | 1487 | } |
| 1577 | 1488 | ||
| 1578 | if (! NILP (part)) /* Scrollbar event */ | 1489 | { |
| 1579 | { | 1490 | int row, column; |
| 1580 | int pos, len; | ||
| 1581 | |||
| 1582 | pos = event->y - (f->display.x->v_scrollbar_width - 2); | ||
| 1583 | x_mouse_x = pos; | ||
| 1584 | len = ((FONT_HEIGHT (f->display.x->font) * f->height) | ||
| 1585 | + f->display.x->internal_border_width | ||
| 1586 | - (2 * (f->display.x->v_scrollbar_width - 2))); | ||
| 1587 | x_mouse_y = len; | ||
| 1588 | |||
| 1589 | result->kind = scrollbar_click; | ||
| 1590 | result->part = part; | ||
| 1591 | XSET (result->x, Lisp_Int, (f->display.x->top_pos - event->y)); | ||
| 1592 | XSET (result->y, Lisp_Int, f->display.x->pixel_height); | ||
| 1593 | result->frame = f; | ||
| 1594 | } | ||
| 1595 | else /* Text Window Event */ | ||
| 1596 | { | ||
| 1597 | int row, column; | ||
| 1598 | 1491 | ||
| 1599 | pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); | 1492 | pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); |
| 1600 | result->kind = mouse_click; | 1493 | XFASTINT (result->x) = column; |
| 1601 | XFASTINT (result->x) = column; | 1494 | XFASTINT (result->y) = row; |
| 1602 | XFASTINT (result->y) = row; | 1495 | result->frame = f; |
| 1603 | result->frame = f; | 1496 | } |
| 1604 | } | ||
| 1605 | } | 1497 | } |
| 1606 | 1498 | ||
| 1607 | 1499 | ||
| @@ -1628,6 +1520,15 @@ construct_mouse_click (result, event, f, part, prefix) | |||
| 1628 | static FRAME_PTR last_mouse_frame; | 1520 | static FRAME_PTR last_mouse_frame; |
| 1629 | static XRectangle last_mouse_glyph; | 1521 | static XRectangle last_mouse_glyph; |
| 1630 | 1522 | ||
| 1523 | /* If the last-checked mouse motion was in a scrollbar, this is that | ||
| 1524 | scrollbar, the part being dragged, and the limits it is moving in. | ||
| 1525 | Otherwise, this is zero. */ | ||
| 1526 | static struct scrollbar *last_mouse_bar; | ||
| 1527 | static FRAME_PTR last_mouse_bar_frame; | ||
| 1528 | static enum scrollbar_part last_mouse_part; | ||
| 1529 | static int last_mouse_scroll_range_start; | ||
| 1530 | static int last_mouse_scroll_range_end; | ||
| 1531 | |||
| 1631 | /* This is a hack. We would really prefer that XTmouse_position would | 1532 | /* This is a hack. We would really prefer that XTmouse_position would |
| 1632 | return the time associated with the position it returns, but there | 1533 | return the time associated with the position it returns, but there |
| 1633 | doesn't seem to be any way to wrest the timestamp from the server | 1534 | doesn't seem to be any way to wrest the timestamp from the server |
| @@ -1679,8 +1580,10 @@ note_mouse_position (frame, event) | |||
| 1679 | */ | 1580 | */ |
| 1680 | 1581 | ||
| 1681 | static void | 1582 | static void |
| 1682 | XTmouse_position (f, x, y, time) | 1583 | XTmouse_position (f, bar, part, x, y, time) |
| 1683 | FRAME_PTR *f; | 1584 | FRAME_PTR *f; |
| 1585 | struct scrollbar **bar; | ||
| 1586 | enum scrollbar_part *part; | ||
| 1684 | Lisp_Object *x, *y; | 1587 | Lisp_Object *x, *y; |
| 1685 | unsigned long *time; | 1588 | unsigned long *time; |
| 1686 | { | 1589 | { |
| @@ -1724,17 +1627,35 @@ XTmouse_position (f, x, y, time) | |||
| 1724 | try instead. */ | 1627 | try instead. */ |
| 1725 | guess = root; | 1628 | guess = root; |
| 1726 | 1629 | ||
| 1727 | *f = last_mouse_frame = x_window_to_frame (guess); | 1630 | if (last_mouse_bar) |
| 1728 | if (! *f) | 1631 | { |
| 1729 | *x = *y = Qnil; | 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 | } | ||
| 1730 | else | 1644 | else |
| 1731 | { | 1645 | { |
| 1732 | pixel_to_glyph_coords (*f, ix, iy, &ix, &iy, &last_mouse_glyph); | 1646 | *f = last_mouse_frame = x_window_to_frame (guess); |
| 1733 | XSET (*x, Lisp_Int, ix); | 1647 | if (! *f) |
| 1734 | XSET (*y, Lisp_Int, iy); | 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 | } | ||
| 1735 | } | 1655 | } |
| 1736 | 1656 | ||
| 1737 | mouse_moved = 0; | 1657 | mouse_moved = 0; |
| 1658 | last_mouse_bar = 0; | ||
| 1738 | 1659 | ||
| 1739 | /* I don't know how to find the time for the last movement; it seems | 1660 | /* I don't know how to find the time for the last movement; it seems |
| 1740 | like XQueryPointer ought to return it, but it doesn't. So, we'll | 1661 | like XQueryPointer ought to return it, but it doesn't. So, we'll |
| @@ -1750,6 +1671,472 @@ XTmouse_position (f, x, y, time) | |||
| 1750 | #define XEvent XKeyPressedEvent | 1671 | #define XEvent XKeyPressedEvent |
| 1751 | #endif /* ! defined (HAVE_X11) */ | 1672 | #endif /* ! defined (HAVE_X11) */ |
| 1752 | 1673 | ||
| 1674 | /* Scrollbar support. */ | ||
| 1675 | |||
| 1676 | /* Map an X window that implements a scroll bar to the struct | ||
| 1677 | scrollbar representing it. */ | ||
| 1678 | static struct scrollbar * | ||
| 1679 | x_window_to_scrollbar (window_id) | ||
| 1680 | Window window_id; | ||
| 1681 | { | ||
| 1682 | Lisp_Object tail, frame; | ||
| 1683 | struct frame *f; | ||
| 1684 | |||
| 1685 | for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) | ||
| 1686 | { | ||
| 1687 | struct scrollbar *bar; | ||
| 1688 | Lisp_Object frame = XCONS (tail)->car; | ||
| 1689 | |||
| 1690 | /* All elements of Vframe_list should be frames. */ | ||
| 1691 | if (XTYPE (frame) != Lisp_Frame) | ||
| 1692 | abort (); | ||
| 1693 | |||
| 1694 | /* Scan this frame's scrollbar list for a scrollbar with the | ||
| 1695 | right window ID. */ | ||
| 1696 | for (bar = XFRAME (frame)->display.x->vertical_scrollbars; | ||
| 1697 | bar; | ||
| 1698 | bar = bar->next) | ||
| 1699 | if (bar->window == window_id) | ||
| 1700 | return bar; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | return 0; | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | |||
| 1707 | /* Open a new X window to serve as a scrollbar. */ | ||
| 1708 | static struct scrollbar * | ||
| 1709 | x_scrollbar_create (frame, top, left, width, height) | ||
| 1710 | FRAME_PTR frame; | ||
| 1711 | int top, left, width, height; | ||
| 1712 | { | ||
| 1713 | struct x_display *d = frame->display.x; | ||
| 1714 | |||
| 1715 | /* We can't signal a malloc error from within redisplay, so call | ||
| 1716 | malloc instead of xmalloc. */ | ||
| 1717 | struct scrollbar *bar = | ||
| 1718 | (struct scrollbar *) malloc (sizeof (struct scrollbar)); | ||
| 1719 | |||
| 1720 | if (! bar) | ||
| 1721 | return 0; | ||
| 1722 | |||
| 1723 | BLOCK_INPUT; | ||
| 1724 | |||
| 1725 | { | ||
| 1726 | XSetWindowAttributes a; | ||
| 1727 | unsigned long mask; | ||
| 1728 | |||
| 1729 | a.background_pixel = d->background_pixel; | ||
| 1730 | a.border_pixel = d->foreground_pixel; | ||
| 1731 | a.event_mask = (KeyPressMask | ||
| 1732 | | ButtonPressMask | ButtonReleaseMask | ||
| 1733 | | ButtonMotionMask); | ||
| 1734 | a.cursor = x_vertical_scrollbar_cursor; | ||
| 1735 | |||
| 1736 | mask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor); | ||
| 1737 | |||
| 1738 | bar->window = | ||
| 1739 | XCreateWindow (x_current_display, FRAME_X_WINDOW (frame), | ||
| 1740 | |||
| 1741 | /* Position and size of scrollbar. */ | ||
| 1742 | top, left, width, height, | ||
| 1743 | |||
| 1744 | /* Border width, depth, class, and visual. */ | ||
| 1745 | 1, CopyFromParent, CopyFromParent, CopyFromParent, | ||
| 1746 | |||
| 1747 | /* Attributes. */ | ||
| 1748 | mask, &a); | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | bar->frame = frame; | ||
| 1752 | bar->top = top; | ||
| 1753 | bar->left = left; | ||
| 1754 | bar->width = width; | ||
| 1755 | bar->height = height; | ||
| 1756 | bar->start = bar->end = 0; | ||
| 1757 | bar->judge_timestamp = d->judge_timestamp; | ||
| 1758 | bar->dragging = -1; | ||
| 1759 | |||
| 1760 | /* Add bar to its frame's list of scroll bars. */ | ||
| 1761 | bar->next = d->vertical_scrollbars; | ||
| 1762 | d->vertical_scrollbars = bar; | ||
| 1763 | |||
| 1764 | XMapWindow (x_current_display, bar->window); | ||
| 1765 | |||
| 1766 | UNBLOCK_INPUT; | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | /* Draw BAR's handle in the proper position. */ | ||
| 1770 | static void | ||
| 1771 | x_scrollbar_set_handle (bar, start, end) | ||
| 1772 | struct scrollbar *bar; | ||
| 1773 | int start, end; | ||
| 1774 | { | ||
| 1775 | BLOCK_INPUT; | ||
| 1776 | |||
| 1777 | { | ||
| 1778 | int inside_width = (bar->width | ||
| 1779 | - VERTICAL_SCROLLBAR_LEFT_BORDER | ||
| 1780 | - VERTICAL_SCROLLBAR_RIGHT_BORDER); | ||
| 1781 | int inside_height = (bar->height | ||
| 1782 | - VERTICAL_SCROLLBAR_TOP_BORDER | ||
| 1783 | - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | ||
| 1784 | |||
| 1785 | /* Make sure the values are reasonable, and try to preserve | ||
| 1786 | the distance between start and end. */ | ||
| 1787 | if (end < start) | ||
| 1788 | end = start; | ||
| 1789 | if (start < VERTICAL_SCROLLBAR_TOP_BORDER) | ||
| 1790 | { | ||
| 1791 | end = VERTICAL_SCROLLBAR_TOP_BORDER + (end - start); | ||
| 1792 | start = VERTICAL_SCROLLBAR_TOP_BORDER; | ||
| 1793 | } | ||
| 1794 | if (end > bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | ||
| 1795 | { | ||
| 1796 | start = ((bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | ||
| 1797 | - (end - start)); | ||
| 1798 | end = bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER; | ||
| 1799 | } | ||
| 1800 | if (start < VERTICAL_SCROLLBAR_TOP_BORDER) | ||
| 1801 | start = VERTICAL_SCROLLBAR_TOP_BORDER; | ||
| 1802 | |||
| 1803 | /* Draw the empty space above the handle. */ | ||
| 1804 | XClearArea (x_current_display, bar->window, | ||
| 1805 | |||
| 1806 | /* x, y, width, height, and exposures. */ | ||
| 1807 | VERTICAL_SCROLLBAR_LEFT_BORDER, | ||
| 1808 | VERTICAL_SCROLLBAR_TOP_BORDER, | ||
| 1809 | inside_width + 1, start + 1, | ||
| 1810 | False); | ||
| 1811 | |||
| 1812 | /* Draw the handle itself. */ | ||
| 1813 | XFillRectangle (x_current_display, bar->window, | ||
| 1814 | bar->frame->display.x->normal_gc, | ||
| 1815 | |||
| 1816 | /* x, y, width, height */ | ||
| 1817 | VERTICAL_SCROLLBAR_LEFT_BORDER, start, | ||
| 1818 | inside_width, (end - start) + 1); | ||
| 1819 | |||
| 1820 | |||
| 1821 | /* Draw the empty space below the handle. */ | ||
| 1822 | XClearArea (x_current_display, bar->window, | ||
| 1823 | |||
| 1824 | /* x, y, width, height, and exposures. */ | ||
| 1825 | VERTICAL_SCROLLBAR_LEFT_BORDER, | ||
| 1826 | VERTICAL_SCROLLBAR_TOP_BORDER + end, | ||
| 1827 | inside_width + 1, (inside_height - end) + 1, | ||
| 1828 | False); | ||
| 1829 | |||
| 1830 | bar->start = start; | ||
| 1831 | bar->end = end; | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | UNBLOCK_INPUT; | ||
| 1835 | } | ||
| 1836 | |||
| 1837 | /* Remove the scrollbar BAR. */ | ||
| 1838 | static void | ||
| 1839 | x_scrollbar_remove (bar) | ||
| 1840 | struct scrollbar *bar; | ||
| 1841 | { | ||
| 1842 | BLOCK_INPUT; | ||
| 1843 | |||
| 1844 | /* Remove bar from the frame's list. */ | ||
| 1845 | { | ||
| 1846 | struct scrollbar **ptr; | ||
| 1847 | |||
| 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 | } | ||
| 1857 | |||
| 1858 | /* Destroy the window. */ | ||
| 1859 | XDestroyWindow (x_current_display, bar->window); | ||
| 1860 | |||
| 1861 | /* Free the storage. */ | ||
| 1862 | free (bar); | ||
| 1863 | |||
| 1864 | UNBLOCK_INPUT; | ||
| 1865 | } | ||
| 1866 | |||
| 1867 | static void | ||
| 1868 | x_scrollbar_move (bar, top, left, width, height) | ||
| 1869 | struct scrollbar *bar; | ||
| 1870 | int top, left, width, height; | ||
| 1871 | { | ||
| 1872 | BLOCK_INPUT; | ||
| 1873 | |||
| 1874 | { | ||
| 1875 | XWindowChanges wc; | ||
| 1876 | unsigned int mask = 0; | ||
| 1877 | |||
| 1878 | wc.x = left; | ||
| 1879 | wc.y = top; | ||
| 1880 | wc.width = width; | ||
| 1881 | wc.height = height; | ||
| 1882 | |||
| 1883 | if (left != bar->left) mask |= CWX; | ||
| 1884 | if (top != bar->top) mask |= CWY; | ||
| 1885 | if (width != bar->width) mask |= CWWidth; | ||
| 1886 | if (height != bar->height) mask |= CWHeight; | ||
| 1887 | |||
| 1888 | XConfigureWindow (x_current_display, bar->window, mask, &wc); | ||
| 1889 | } | ||
| 1890 | |||
| 1891 | UNBLOCK_INPUT; | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | /* Set BAR to be the vertical scroll bar for WINDOW. Set its handle | ||
| 1895 | to indicate that we are displaying PORTION characters out of a | ||
| 1896 | total of WHOLE characters, starting at POSITION. Return BAR. If | ||
| 1897 | BAR is zero, create a new scrollbar and return a pointer to it. */ | ||
| 1898 | static struct scrollbar * | ||
| 1899 | XTset_scrollbar (bar, window, portion, whole, position) | ||
| 1900 | struct scrollbar *bar; | ||
| 1901 | struct window *window; | ||
| 1902 | int portion, whole, position; | ||
| 1903 | { | ||
| 1904 | FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); | ||
| 1905 | struct x_display *d = f->display.x; | ||
| 1906 | int top = XINT (window->top); | ||
| 1907 | int left = WINDOW_VERTICAL_SCROLLBAR_COLUMN (window); | ||
| 1908 | int height = WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window); | ||
| 1909 | |||
| 1910 | /* Where should this scrollbar be, pixelwise? */ | ||
| 1911 | int pixel_top = (d->internal_border_width + top * FONT_HEIGHT (d->font)); | ||
| 1912 | int pixel_left = (d->internal_border_width + left * FONT_WIDTH (d->font)); | ||
| 1913 | int pixel_width = VERTICAL_SCROLLBAR_PIXEL_WIDTH (f); | ||
| 1914 | int pixel_height = VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f, height); | ||
| 1915 | |||
| 1916 | /* Does the scrollbar exist yet? */ | ||
| 1917 | if (! bar) | ||
| 1918 | bar = x_scrollbar_create (f, | ||
| 1919 | pixel_top, pixel_left, | ||
| 1920 | pixel_width, pixel_height); | ||
| 1921 | else | ||
| 1922 | /* It may just need to be moved and resized. */ | ||
| 1923 | x_scrollbar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); | ||
| 1924 | |||
| 1925 | /* Set the scrollbar's current state, unless we're currently being | ||
| 1926 | dragged. */ | ||
| 1927 | |||
| 1928 | if (bar && bar->dragging == -1) | ||
| 1929 | { | ||
| 1930 | int inside_height = (pixel_height | ||
| 1931 | - VERTICAL_SCROLLBAR_TOP_BORDER | ||
| 1932 | - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | ||
| 1933 | int start = (position * inside_height) / whole; | ||
| 1934 | int end = ((position + portion) * inside_height) / whole; | ||
| 1935 | |||
| 1936 | x_scrollbar_set_handle (bar, start, end); | ||
| 1937 | } | ||
| 1938 | |||
| 1939 | return bar; | ||
| 1940 | } | ||
| 1941 | |||
| 1942 | /* The following three hooks are used when we're doing a thorough | ||
| 1943 | redisplay of the frame. We don't explicitly know which scrollbars | ||
| 1944 | are going to be deleted, because keeping track of when windows go | ||
| 1945 | away is a real pain - can you say set-window-configuration? | ||
| 1946 | Instead, we just assert at the beginning of redisplay that *all* | ||
| 1947 | scrollbars are to be removed, and then save scrollbars from the | ||
| 1948 | firey pit when we actually redisplay their window. */ | ||
| 1949 | |||
| 1950 | /* Arrange for all scrollbars on FRAME to be removed at the next call | ||
| 1951 | to `*judge_scrollbars_hook'. A scrollbar may be spared if | ||
| 1952 | `*redeem_scrollbar_hook' is applied to it before the judgement. */ | ||
| 1953 | static void | ||
| 1954 | XTcondemn_scrollbars (frame) | ||
| 1955 | FRAME_PTR frame; | ||
| 1956 | { | ||
| 1957 | /* Any scrollbars which don't get caught up to this will be deleted. */ | ||
| 1958 | frame->display.x->judge_timestamp++; | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | /* Unmark BAR for deletion in this judgement cycle. */ | ||
| 1962 | static void | ||
| 1963 | XTredeem_scrollbar (bar) | ||
| 1964 | struct scrollbar *bar; | ||
| 1965 | { | ||
| 1966 | bar->judge_timestamp = bar->frame->display.x->judge_timestamp; | ||
| 1967 | } | ||
| 1968 | |||
| 1969 | /* Remove all scrollbars on FRAME that haven't been saved since the | ||
| 1970 | last call to `*condemn_scrollbars_hook'. */ | ||
| 1971 | static void | ||
| 1972 | XTjudge_scrollbars(frame) | ||
| 1973 | FRAME_PTR frame; | ||
| 1974 | { | ||
| 1975 | int judge_timestamp = frame->display.x->judge_timestamp; | ||
| 1976 | struct scrollbar *bar, *next; | ||
| 1977 | |||
| 1978 | for (bar = frame->display.x->vertical_scrollbars; bar; bar = next) | ||
| 1979 | { | ||
| 1980 | next = bar->next; | ||
| 1981 | if (bar->judge_timestamp < judge_timestamp) | ||
| 1982 | x_scrollbar_remove (bar); | ||
| 1983 | } | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | |||
| 1987 | /* Handle an Expose or GraphicsExpose event on a scrollbar. */ | ||
| 1988 | static void | ||
| 1989 | x_scrollbar_expose (bar, event) | ||
| 1990 | struct scrollbar *bar; | ||
| 1991 | XEvent *event; | ||
| 1992 | { | ||
| 1993 | BLOCK_INPUT; | ||
| 1994 | |||
| 1995 | x_scrollbar_set_handle (bar, bar->start, bar->end); | ||
| 1996 | |||
| 1997 | /* Draw the extra-thick border on the right. */ | ||
| 1998 | XFillRectangle (x_current_display, bar->window, | ||
| 1999 | bar->frame->display.x->normal_gc, | ||
| 2000 | |||
| 2001 | /* x, y, width, height */ | ||
| 2002 | bar->width - VERTICAL_SCROLLBAR_RIGHT_BORDER, 0, | ||
| 2003 | VERTICAL_SCROLLBAR_RIGHT_BORDER, bar->height + 1); | ||
| 2004 | |||
| 2005 | UNBLOCK_INPUT; | ||
| 2006 | } | ||
| 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 | |||
| 2022 | /* Clear it out. */ | ||
| 2023 | XClearArea (x_current_display, FRAME_X_WINDOW (frame), | ||
| 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 | |||
| 2039 | UNBLOCK_INPUT; | ||
| 2040 | } | ||
| 2041 | |||
| 2042 | /* Handle a mouse click on the scrollbar BAR. If *EMACS_EVENT's kind | ||
| 2043 | is set to something other than no_event, it is enqueued. */ | ||
| 2044 | static void | ||
| 2045 | x_scrollbar_handle_click (bar, event, emacs_event) | ||
| 2046 | struct scrollbar *bar; | ||
| 2047 | XEvent *event; | ||
| 2048 | struct input_event *emacs_event; | ||
| 2049 | { | ||
| 2050 | emacs_event->kind = scrollbar_click; | ||
| 2051 | XSETINT (emacs_event->code, event->xbutton.button - Button1); | ||
| 2052 | emacs_event->modifiers = | ||
| 2053 | (x_convert_modifiers (event->xbutton.state) | ||
| 2054 | | (event->type == ButtonRelease | ||
| 2055 | ? up_modifier | ||
| 2056 | : down_modifier)); | ||
| 2057 | emacs_event->part = | ||
| 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; | ||
| 2076 | |||
| 2077 | if (event->type == ButtonPress | ||
| 2078 | && emacs_event->part == scrollbar_handle) | ||
| 2079 | bar->dragging = event->xbutton.x - bar->start; | ||
| 2080 | else | ||
| 2081 | { | ||
| 2082 | int new_start = event->xbutton.x - bar->dragging; | ||
| 2083 | int new_end = new_start + (bar->end - bar->start); | ||
| 2084 | |||
| 2085 | x_scrollbar_set_handle (bar, new_start, new_end); | ||
| 2086 | bar->dragging = -1; | ||
| 2087 | } | ||
| 2088 | } | ||
| 2089 | |||
| 2090 | |||
| 2091 | /* Handle some mouse motion while someone is dragging the scrollbar. */ | ||
| 2092 | static void | ||
| 2093 | x_scrollbar_handle_motion (bar, event) | ||
| 2094 | struct scrollbar *bar; | ||
| 2095 | XEvent *event; | ||
| 2096 | { | ||
| 2097 | last_mouse_movement_time = event->xmotion.time; | ||
| 2098 | |||
| 2099 | mouse_moved = 1; | ||
| 2100 | last_mouse_bar = 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 | |||
| 2111 | /* If we're dragging the bar, display it. */ | ||
| 2112 | if (bar->dragging != -1) | ||
| 2113 | { | ||
| 2114 | /* Where should the handle be now? */ | ||
| 2115 | int new_start = event->xmotion.x - bar->dragging; | ||
| 2116 | |||
| 2117 | if (new_start != bar->start) | ||
| 2118 | { | ||
| 2119 | int new_end = new_start + (bar->end - bar->start); | ||
| 2120 | |||
| 2121 | x_scrollbar_set_handle (bar, new_start, new_end); | ||
| 2122 | } | ||
| 2123 | } | ||
| 2124 | |||
| 2125 | /* Call XQueryPointer so we'll get an event the next time the mouse | ||
| 2126 | moves and we can see *still* on the same position. */ | ||
| 2127 | { | ||
| 2128 | int dummy; | ||
| 2129 | |||
| 2130 | XQueryPointer (event->xmotion.display, event->xmotion.window, | ||
| 2131 | (Window *) &dummy, (Window *) &dummy, | ||
| 2132 | &dummy, &dummy, &dummy, &dummy, | ||
| 2133 | (unsigned int *) &dummy); | ||
| 2134 | } | ||
| 2135 | } | ||
| 2136 | |||
| 2137 | |||
| 2138 | |||
| 2139 | /* The main X event-reading loop - XTread_socket. */ | ||
| 1753 | 2140 | ||
| 1754 | /* Timestamp of enter window event. This is only used by XTread_socket, | 2141 | /* Timestamp of enter window event. This is only used by XTread_socket, |
| 1755 | but we have to put it out here, since static variables within functions | 2142 | but we have to put it out here, since static variables within functions |
| @@ -1931,19 +2318,35 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 1931 | SET_FRAME_GARBAGED (f); | 2318 | SET_FRAME_GARBAGED (f); |
| 1932 | } | 2319 | } |
| 1933 | else | 2320 | else |
| 1934 | dumprectangle (x_window_to_frame (event.xexpose.window), | 2321 | { |
| 1935 | event.xexpose.x, event.xexpose.y, | 2322 | dumprectangle (x_window_to_frame (event.xexpose.window), |
| 1936 | event.xexpose.width, event.xexpose.height); | 2323 | event.xexpose.x, event.xexpose.y, |
| 2324 | event.xexpose.width, event.xexpose.height); | ||
| 2325 | x_scrollbar_background_expose (f, &event); | ||
| 2326 | } | ||
| 2327 | } | ||
| 2328 | else | ||
| 2329 | { | ||
| 2330 | struct scrollbar *bar | ||
| 2331 | = x_window_to_scrollbar (event.xexpose.window); | ||
| 2332 | |||
| 2333 | if (bar) | ||
| 2334 | x_scrollbar_expose (bar, &event); | ||
| 1937 | } | 2335 | } |
| 1938 | break; | 2336 | break; |
| 1939 | 2337 | ||
| 1940 | case GraphicsExpose: /* This occurs when an XCopyArea's | 2338 | case GraphicsExpose: /* This occurs when an XCopyArea's |
| 1941 | source area was obscured or not | 2339 | source area was obscured or not |
| 1942 | available.*/ | 2340 | available.*/ |
| 1943 | dumprectangle (x_window_to_frame (event.xgraphicsexpose.drawable), | 2341 | f = x_window_to_frame (event.xgraphicsexpose.drawable); |
| 1944 | event.xgraphicsexpose.x, event.xgraphicsexpose.y, | 2342 | if (f) |
| 1945 | event.xgraphicsexpose.width, | 2343 | { |
| 1946 | event.xgraphicsexpose.height); | 2344 | dumprectangle (f, |
| 2345 | event.xgraphicsexpose.x, event.xgraphicsexpose.y, | ||
| 2346 | event.xgraphicsexpose.width, | ||
| 2347 | event.xgraphicsexpose.height); | ||
| 2348 | x_scrollbar_background_expose (f, &event); | ||
| 2349 | } | ||
| 1947 | break; | 2350 | break; |
| 1948 | 2351 | ||
| 1949 | case NoExpose: /* This occurs when an XCopyArea's | 2352 | case NoExpose: /* This occurs when an XCopyArea's |
| @@ -2000,20 +2403,15 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2000 | 2403 | ||
| 2001 | #ifdef HAVE_X11 | 2404 | #ifdef HAVE_X11 |
| 2002 | case UnmapNotify: | 2405 | case UnmapNotify: |
| 2003 | { | 2406 | f = x_window_to_frame (event.xunmap.window); |
| 2004 | XWMHints *hints; | 2407 | if (f) /* F may no longer exist if |
| 2005 | |||
| 2006 | f = x_window_to_frame (event.xunmap.window); | ||
| 2007 | if (f) /* F may no longer exist if | ||
| 2008 | the frame was deleted. */ | 2408 | the frame was deleted. */ |
| 2009 | { | 2409 | { |
| 2010 | /* While a frame is unmapped, display generation is | 2410 | /* While a frame is unmapped, display generation is |
| 2011 | disabled; you don't want to spend time updating a | 2411 | disabled; you don't want to spend time updating a |
| 2012 | display that won't ever be seen. */ | 2412 | display that won't ever be seen. */ |
| 2013 | f->async_visible = 0; | 2413 | f->async_visible = 0; |
| 2014 | x_mouse_x = x_mouse_y = -1; | 2414 | } |
| 2015 | } | ||
| 2016 | } | ||
| 2017 | break; | 2415 | break; |
| 2018 | 2416 | ||
| 2019 | case MapNotify: | 2417 | case MapNotify: |
| @@ -2046,6 +2444,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2046 | #ifdef HAVE_X11 | 2444 | #ifdef HAVE_X11 |
| 2047 | case KeyPress: | 2445 | case KeyPress: |
| 2048 | f = x_window_to_frame (event.xkey.window); | 2446 | f = x_window_to_frame (event.xkey.window); |
| 2447 | |||
| 2049 | if (f != 0) | 2448 | if (f != 0) |
| 2050 | { | 2449 | { |
| 2051 | KeySym keysym; | 2450 | KeySym keysym; |
| @@ -2165,18 +2564,18 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2165 | #endif /* ! defined (HAVE_X11) */ | 2564 | #endif /* ! defined (HAVE_X11) */ |
| 2166 | 2565 | ||
| 2167 | #ifdef HAVE_X11 | 2566 | #ifdef HAVE_X11 |
| 2567 | |||
| 2568 | /* Here's a possible interpretation of the whole | ||
| 2569 | FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a | ||
| 2570 | FocusIn event, you have to get a FocusOut event before you | ||
| 2571 | relinquish the focus. If you haven't received a FocusIn event, | ||
| 2572 | then a mere LeaveNotify is enough to free you. */ | ||
| 2573 | |||
| 2168 | case EnterNotify: | 2574 | case EnterNotify: |
| 2169 | f = x_window_to_frame (event.xcrossing.window); | 2575 | f = x_window_to_frame (event.xcrossing.window); |
| 2170 | 2576 | ||
| 2171 | if (event.xcrossing.detail == NotifyInferior) /* Left Scrollbar */ | 2577 | if (event.xcrossing.focus) /* Entered Window */ |
| 2172 | ; | ||
| 2173 | else if (event.xcrossing.focus) /* Entered Window */ | ||
| 2174 | { | 2578 | { |
| 2175 | /* If we decide we want to generate an event to be seen | ||
| 2176 | by the rest of Emacs, we put it here. */ | ||
| 2177 | struct input_event emacs_event; | ||
| 2178 | emacs_event.kind = no_event; | ||
| 2179 | |||
| 2180 | /* Avoid nasty pop/raise loops. */ | 2579 | /* Avoid nasty pop/raise loops. */ |
| 2181 | if (f && (!(f->auto_raise) | 2580 | if (f && (!(f->auto_raise) |
| 2182 | || !(f->auto_lower) | 2581 | || !(f->auto_lower) |
| @@ -2185,58 +2584,45 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2185 | x_new_focus_frame (f); | 2584 | x_new_focus_frame (f); |
| 2186 | enter_timestamp = event.xcrossing.time; | 2585 | enter_timestamp = event.xcrossing.time; |
| 2187 | } | 2586 | } |
| 2188 | #if 0 | ||
| 2189 | else if ((f = x_window_to_scrollbar (event.xcrossing.window, | ||
| 2190 | &part, &prefix))) | ||
| 2191 | /* Fake a motion event */ | ||
| 2192 | notice_mouse_movement (&emacs_event, | ||
| 2193 | event.xmotion, f, scrollbar_window, | ||
| 2194 | part); | ||
| 2195 | #endif /* ! 0 */ | ||
| 2196 | |||
| 2197 | #if 0 | ||
| 2198 | if (! EQ (Vx_send_mouse_movement_events, Qnil) | ||
| 2199 | && numchars >= 1 | ||
| 2200 | && emacs_event.kind != no_event) | ||
| 2201 | { | ||
| 2202 | bcopy (&emacs_event, bufp, sizeof (struct input_event)); | ||
| 2203 | bufp++; | ||
| 2204 | count++; | ||
| 2205 | numchars--; | ||
| 2206 | } | ||
| 2207 | #endif /* ! 0 */ | ||
| 2208 | } | 2587 | } |
| 2209 | else if (f == x_focus_frame) | 2588 | else if (f == x_focus_frame) |
| 2210 | x_new_focus_frame (0); | 2589 | x_new_focus_frame (0); |
| 2211 | #if 0 | ||
| 2212 | else if (f = x_window_to_frame (event.xcrossing.window)) | ||
| 2213 | x_mouse_frame = f; | ||
| 2214 | #endif /* ! 0 */ | ||
| 2215 | 2590 | ||
| 2216 | break; | 2591 | break; |
| 2217 | 2592 | ||
| 2218 | case FocusIn: | 2593 | case FocusIn: |
| 2219 | f = x_window_to_frame (event.xfocus.window); | 2594 | f = x_window_to_frame (event.xfocus.window); |
| 2595 | if (event.xfocus.detail != NotifyPointer) | ||
| 2596 | x_focus_event_frame = f; | ||
| 2220 | if (f) | 2597 | if (f) |
| 2221 | x_new_focus_frame (f); | 2598 | x_new_focus_frame (f); |
| 2222 | break; | 2599 | break; |
| 2223 | 2600 | ||
| 2601 | |||
| 2224 | case LeaveNotify: | 2602 | case LeaveNotify: |
| 2225 | if (event.xcrossing.detail != NotifyInferior | 2603 | f = x_window_to_frame (event.xcrossing.window); |
| 2226 | && event.xcrossing.subwindow == None | ||
| 2227 | && event.xcrossing.mode == NotifyNormal) | ||
| 2228 | { | ||
| 2229 | f = x_window_to_frame (event.xcrossing.window); | ||
| 2230 | 2604 | ||
| 2231 | if (event.xcrossing.focus) | 2605 | if (event.xcrossing.focus) |
| 2606 | { | ||
| 2607 | if (! x_focus_event_frame) | ||
| 2608 | x_new_focus_frame (0); | ||
| 2609 | else | ||
| 2232 | x_new_focus_frame (f); | 2610 | x_new_focus_frame (f); |
| 2233 | else if (f == x_focus_frame) | 2611 | } |
| 2612 | else | ||
| 2613 | { | ||
| 2614 | if (f == x_focus_event_frame) | ||
| 2615 | x_focus_event_frame = 0; | ||
| 2616 | if (f == x_focus_frame) | ||
| 2234 | x_new_focus_frame (0); | 2617 | x_new_focus_frame (0); |
| 2235 | } | 2618 | } |
| 2236 | break; | 2619 | break; |
| 2237 | 2620 | ||
| 2238 | case FocusOut: | 2621 | case FocusOut: |
| 2239 | f = x_window_to_frame (event.xfocus.window); | 2622 | f = x_window_to_frame (event.xfocus.window); |
| 2623 | if (event.xfocus.detail != NotifyPointer | ||
| 2624 | && f == x_focus_event_frame) | ||
| 2625 | x_focus_event_frame = 0; | ||
| 2240 | if (f && f == x_focus_frame) | 2626 | if (f && f == x_focus_frame) |
| 2241 | x_new_focus_frame (0); | 2627 | x_new_focus_frame (0); |
| 2242 | break; | 2628 | break; |
| @@ -2283,13 +2669,14 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2283 | f = x_window_to_frame (event.xmotion.window); | 2669 | f = x_window_to_frame (event.xmotion.window); |
| 2284 | if (f) | 2670 | if (f) |
| 2285 | note_mouse_position (f, &event.xmotion); | 2671 | note_mouse_position (f, &event.xmotion); |
| 2286 | #if 0 | 2672 | else |
| 2287 | else if ((f = x_window_to_scrollbar (event.xmotion.window, | ||
| 2288 | &part, &prefix))) | ||
| 2289 | { | 2673 | { |
| 2290 | What should go here? | 2674 | struct scrollbar *bar = |
| 2675 | x_window_to_scrollbar (event.xmotion.window); | ||
| 2676 | |||
| 2677 | if (bar) | ||
| 2678 | x_scrollbar_handle_motion (bar, &event); | ||
| 2291 | } | 2679 | } |
| 2292 | #endif /* ! 0 */ | ||
| 2293 | } | 2680 | } |
| 2294 | break; | 2681 | break; |
| 2295 | 2682 | ||
| @@ -2300,14 +2687,8 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2300 | if (!f) | 2687 | if (!f) |
| 2301 | break; | 2688 | break; |
| 2302 | 2689 | ||
| 2303 | columns = ((event.xconfigure.width - | 2690 | columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width); |
| 2304 | (2 * f->display.x->internal_border_width) | 2691 | rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height); |
| 2305 | - f->display.x->v_scrollbar_width) | ||
| 2306 | / FONT_WIDTH (f->display.x->font)); | ||
| 2307 | rows = ((event.xconfigure.height - | ||
| 2308 | (2 * f->display.x->internal_border_width) | ||
| 2309 | - f->display.x->h_scrollbar_height) | ||
| 2310 | / FONT_HEIGHT (f->display.x->font)); | ||
| 2311 | 2692 | ||
| 2312 | /* Even if the number of character rows and columns has | 2693 | /* Even if the number of character rows and columns has |
| 2313 | not changed, the font size may have changed, so we need | 2694 | not changed, the font size may have changed, so we need |
| @@ -2318,7 +2699,6 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2318 | || event.xconfigure.height != f->display.x->pixel_height) | 2699 | || event.xconfigure.height != f->display.x->pixel_height) |
| 2319 | { | 2700 | { |
| 2320 | change_frame_size (f, rows, columns, 0, 1); | 2701 | change_frame_size (f, rows, columns, 0, 1); |
| 2321 | x_resize_scrollbars (f); | ||
| 2322 | SET_FRAME_GARBAGED (f); | 2702 | SET_FRAME_GARBAGED (f); |
| 2323 | } | 2703 | } |
| 2324 | 2704 | ||
| @@ -2339,21 +2719,19 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2339 | 2719 | ||
| 2340 | f = x_window_to_frame (event.xbutton.window); | 2720 | f = x_window_to_frame (event.xbutton.window); |
| 2341 | if (f) | 2721 | if (f) |
| 2342 | if (!x_focus_frame || (f == x_focus_frame)) | 2722 | { |
| 2343 | construct_mouse_click (&emacs_event, | 2723 | if (!x_focus_frame || (f == x_focus_frame)) |
| 2344 | &event, f, Qnil, 0); | 2724 | construct_mouse_click (&emacs_event, |
| 2345 | else | 2725 | &event, f, Qnil, 0); |
| 2346 | continue; | 2726 | } |
| 2347 | else | 2727 | else |
| 2348 | if ((f = x_window_to_scrollbar (event.xbutton.window, | 2728 | { |
| 2349 | &part, &prefix))) | 2729 | struct scrollbar *bar = |
| 2350 | { | 2730 | x_window_to_scrollbar (event.xbutton.window); |
| 2351 | if (!x_focus_frame || (selected_frame == x_focus_frame)) | 2731 | |
| 2352 | construct_mouse_click (&emacs_event, | 2732 | if (bar) |
| 2353 | &event, f, part, prefix); | 2733 | x_scrollbar_handle_click (bar, &event, &emacs_event); |
| 2354 | else | 2734 | } |
| 2355 | continue; | ||
| 2356 | } | ||
| 2357 | 2735 | ||
| 2358 | if (numchars >= 1 && emacs_event.kind != no_event) | 2736 | if (numchars >= 1 && emacs_event.kind != no_event) |
| 2359 | { | 2737 | { |
| @@ -2452,8 +2830,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected) | |||
| 2452 | #endif /* ! defined (HAVE_SELECT) */ | 2830 | #endif /* ! defined (HAVE_SELECT) */ |
| 2453 | #endif /* ! 0 */ | 2831 | #endif /* ! 0 */ |
| 2454 | 2832 | ||
| 2833 | #ifndef HAVE_X11 | ||
| 2455 | if (updating_frame == 0) | 2834 | if (updating_frame == 0) |
| 2456 | x_do_pending_expose (); | 2835 | x_do_pending_expose (); |
| 2836 | #endif | ||
| 2457 | 2837 | ||
| 2458 | UNBLOCK_INPUT; | 2838 | UNBLOCK_INPUT; |
| 2459 | return count; | 2839 | return count; |
| @@ -2525,6 +2905,9 @@ x_read_exposes () | |||
| 2525 | #endif /* HAVE_X11 */ | 2905 | #endif /* HAVE_X11 */ |
| 2526 | 2906 | ||
| 2527 | 2907 | ||
| 2908 | /* Drawing the cursor. */ | ||
| 2909 | |||
| 2910 | |||
| 2528 | /* Draw a hollow box cursor. Don't change the inside of the box. */ | 2911 | /* Draw a hollow box cursor. Don't change the inside of the box. */ |
| 2529 | 2912 | ||
| 2530 | static void | 2913 | static void |
| @@ -2573,7 +2956,7 @@ clear_cursor (f) | |||
| 2573 | { | 2956 | { |
| 2574 | int mask; | 2957 | int mask; |
| 2575 | 2958 | ||
| 2576 | if (! f->visible | 2959 | if (! FRAME_VISIBLE_P (f) |
| 2577 | || f->phys_cursor_x < 0) | 2960 | || f->phys_cursor_x < 0) |
| 2578 | return; | 2961 | return; |
| 2579 | 2962 | ||
| @@ -2608,7 +2991,7 @@ x_display_bar_cursor (f, on) | |||
| 2608 | register int y1; | 2991 | register int y1; |
| 2609 | register int y2; | 2992 | register int y2; |
| 2610 | 2993 | ||
| 2611 | if (! f->visible || (! on && f->phys_cursor_x < 0)) | 2994 | if (! FRAME_VISIBLE_P (f) || (! on && f->phys_cursor_x < 0)) |
| 2612 | return; | 2995 | return; |
| 2613 | 2996 | ||
| 2614 | #ifdef HAVE_X11 | 2997 | #ifdef HAVE_X11 |
| @@ -2685,7 +3068,7 @@ x_display_box_cursor (f, on) | |||
| 2685 | curs_y = FRAME_CURSOR_Y (f); | 3068 | curs_y = FRAME_CURSOR_Y (f); |
| 2686 | } | 3069 | } |
| 2687 | 3070 | ||
| 2688 | if (! f->visible) | 3071 | if (! FRAME_VISIBLE_P (f)) |
| 2689 | return; | 3072 | return; |
| 2690 | 3073 | ||
| 2691 | /* If cursor is off and we want it off, return quickly. */ | 3074 | /* If cursor is off and we want it off, return quickly. */ |
| @@ -2950,6 +3333,10 @@ x_error_quitter (display, error) | |||
| 2950 | { | 3333 | { |
| 2951 | char buf[256]; | 3334 | char buf[256]; |
| 2952 | 3335 | ||
| 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 | |||
| 2953 | /* Note that there is no real way portable across R3/R4 to get the | 3340 | /* Note that there is no real way portable across R3/R4 to get the |
| 2954 | original error handler. */ | 3341 | original error handler. */ |
| 2955 | 3342 | ||
| @@ -3041,6 +3428,8 @@ x_trace_wire () | |||
| 3041 | #endif /* ! 0 */ | 3428 | #endif /* ! 0 */ |
| 3042 | 3429 | ||
| 3043 | 3430 | ||
| 3431 | /* Changing the font of the frame. */ | ||
| 3432 | |||
| 3044 | /* Set the font of the x-window specified by frame F | 3433 | /* Set the font of the x-window specified by frame F |
| 3045 | to the font named NEWNAME. This is safe to use | 3434 | to the font named NEWNAME. This is safe to use |
| 3046 | even before F has an actual x-window. */ | 3435 | even before F has an actual x-window. */ |
| @@ -3171,6 +3560,8 @@ x_new_font (f, newname) | |||
| 3171 | } | 3560 | } |
| 3172 | #endif /* ! defined (HAVE_X11) */ | 3561 | #endif /* ! defined (HAVE_X11) */ |
| 3173 | 3562 | ||
| 3563 | /* X Window sizes and positions. */ | ||
| 3564 | |||
| 3174 | x_calc_absolute_position (f) | 3565 | x_calc_absolute_position (f) |
| 3175 | struct frame *f; | 3566 | struct frame *f; |
| 3176 | { | 3567 | { |
| @@ -3227,10 +3618,12 @@ x_set_window_size (f, cols, rows) | |||
| 3227 | BLOCK_INPUT; | 3618 | BLOCK_INPUT; |
| 3228 | 3619 | ||
| 3229 | check_frame_size (f, &rows, &cols); | 3620 | check_frame_size (f, &rows, &cols); |
| 3230 | pixelwidth = (cols * FONT_WIDTH (f->display.x->font) + 2 * ibw | 3621 | f->display.x->vertical_scrollbar_extra = |
| 3231 | + f->display.x->v_scrollbar_width); | 3622 | (FRAME_HAS_VERTICAL_SCROLLBARS (f) |
| 3232 | pixelheight = (rows * FONT_HEIGHT (f->display.x->font) + 2 * ibw | 3623 | ? VERTICAL_SCROLLBAR_PIXEL_WIDTH (f) |
| 3233 | + f->display.x->h_scrollbar_height); | 3624 | : 0); |
| 3625 | pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols); | ||
| 3626 | pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows); | ||
| 3234 | 3627 | ||
| 3235 | #ifdef HAVE_X11 | 3628 | #ifdef HAVE_X11 |
| 3236 | x_wm_set_size_hint (f, 0); | 3629 | x_wm_set_size_hint (f, 0); |
| @@ -3261,6 +3654,7 @@ x_set_resize_hint (f) | |||
| 3261 | } | 3654 | } |
| 3262 | #endif /* HAVE_X11 */ | 3655 | #endif /* HAVE_X11 */ |
| 3263 | 3656 | ||
| 3657 | /* Mouse warping, focus shifting, raising and lowering. */ | ||
| 3264 | 3658 | ||
| 3265 | x_set_mouse_position (f, x, y) | 3659 | x_set_mouse_position (f, x, y) |
| 3266 | struct frame *f; | 3660 | struct frame *f; |
| @@ -3270,28 +3664,20 @@ x_set_mouse_position (f, x, y) | |||
| 3270 | 3664 | ||
| 3271 | x_raise_frame (f); | 3665 | x_raise_frame (f); |
| 3272 | 3666 | ||
| 3273 | if (x < 0) | 3667 | pix_x = (f->display.x->internal_border_width |
| 3274 | pix_x = (FRAME_WIDTH (f) | 3668 | + x * FONT_WIDTH (f->display.x->font) |
| 3275 | * FONT_WIDTH (f->display.x->font) | 3669 | + FONT_WIDTH (f->display.x->font) / 2); |
| 3276 | + 2 * f->display.x->internal_border_width | 3670 | pix_y = (f->display.x->internal_border_width |
| 3277 | + f->display.x->v_scrollbar_width) / 2; | 3671 | + y * FONT_HEIGHT (f->display.x->font) |
| 3278 | else | 3672 | + FONT_HEIGHT (f->display.x->font) / 2); |
| 3279 | pix_x = x * FONT_WIDTH (f->display.x->font) + 2; /* add 2 pixels to each | 3673 | |
| 3280 | dimension to move the | 3674 | if (pix_x < 0) pix_x = 0; |
| 3281 | mouse into the char | 3675 | if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f); |
| 3282 | cell */ | 3676 | |
| 3283 | 3677 | if (pix_y < 0) pix_y = 0; | |
| 3284 | if (y < 0) | 3678 | if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f); |
| 3285 | pix_y = (FRAME_HEIGHT (f) | ||
| 3286 | * FONT_HEIGHT (f->display.x->font) | ||
| 3287 | + 2 * f->display.x->internal_border_width | ||
| 3288 | + f->display.x->h_scrollbar_height) / 2; | ||
| 3289 | else | ||
| 3290 | pix_y = y * FONT_HEIGHT (f->display.x->font) + 2; | ||
| 3291 | 3679 | ||
| 3292 | BLOCK_INPUT; | 3680 | BLOCK_INPUT; |
| 3293 | x_mouse_x = x; | ||
| 3294 | x_mouse_y = y; | ||
| 3295 | 3681 | ||
| 3296 | XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y); | 3682 | XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y); |
| 3297 | UNBLOCK_INPUT; | 3683 | UNBLOCK_INPUT; |
| @@ -3368,7 +3754,7 @@ x_make_frame_visible (f) | |||
| 3368 | x_wm_set_window_state (f, NormalState); | 3754 | x_wm_set_window_state (f, NormalState); |
| 3369 | 3755 | ||
| 3370 | XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); | 3756 | XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); |
| 3371 | if (f->display.x->v_scrollbar != 0 || f->display.x->h_scrollbar != 0) | 3757 | if (FRAME_HAS_VERTICAL_SCROLLBARS (f)) |
| 3372 | XMapSubwindows (x_current_display, FRAME_X_WINDOW (f)); | 3758 | XMapSubwindows (x_current_display, FRAME_X_WINDOW (f)); |
| 3373 | #else /* ! defined (HAVE_X11) */ | 3759 | #else /* ! defined (HAVE_X11) */ |
| 3374 | XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); | 3760 | XMapWindow (XDISPLAY FRAME_X_WINDOW (f)); |
| @@ -3535,6 +3921,8 @@ x_destroy_window (f, displ) | |||
| 3535 | x_highlight_frame = 0; | 3921 | x_highlight_frame = 0; |
| 3536 | } | 3922 | } |
| 3537 | 3923 | ||
| 3924 | /* Manage event queues for X10. */ | ||
| 3925 | |||
| 3538 | #ifndef HAVE_X11 | 3926 | #ifndef HAVE_X11 |
| 3539 | 3927 | ||
| 3540 | /* Manage event queues. | 3928 | /* Manage event queues. |
| @@ -3607,6 +3995,8 @@ mouse_event_pending_p () | |||
| 3607 | } | 3995 | } |
| 3608 | #endif /* HAVE_X11 */ | 3996 | #endif /* HAVE_X11 */ |
| 3609 | 3997 | ||
| 3998 | /* Setting window manager hints. */ | ||
| 3999 | |||
| 3610 | #ifdef HAVE_X11 | 4000 | #ifdef HAVE_X11 |
| 3611 | 4001 | ||
| 3612 | x_wm_set_size_hint (f, prompting) | 4002 | x_wm_set_size_hint (f, prompting) |
| @@ -3626,19 +4016,14 @@ x_wm_set_size_hint (f, prompting) | |||
| 3626 | size_hints.width = PIXEL_WIDTH (f); | 4016 | size_hints.width = PIXEL_WIDTH (f); |
| 3627 | size_hints.width_inc = FONT_WIDTH (f->display.x->font); | 4017 | size_hints.width_inc = FONT_WIDTH (f->display.x->font); |
| 3628 | size_hints.height_inc = FONT_HEIGHT (f->display.x->font); | 4018 | size_hints.height_inc = FONT_HEIGHT (f->display.x->font); |
| 3629 | size_hints.max_width = | 4019 | size_hints.max_width = PIXEL_TO_CHAR_WIDTH (f, x_screen_width); |
| 3630 | (x_screen_width - ((2 * f->display.x->internal_border_width) | 4020 | size_hints.max_height = PIXEL_TO_CHAR_HEIGHT (f, x_screen_height); |
| 3631 | + f->display.x->v_scrollbar_width)); | 4021 | |
| 3632 | size_hints.max_height = | ||
| 3633 | (x_screen_height - ((2 * f->display.x->internal_border_width) | ||
| 3634 | + f->display.x->h_scrollbar_height)); | ||
| 3635 | { | 4022 | { |
| 3636 | int base_width, base_height; | 4023 | int base_width, base_height; |
| 3637 | 4024 | ||
| 3638 | base_width = ((2 * f->display.x->internal_border_width) | 4025 | base_width = CHAR_TO_PIXEL_WIDTH (f, 0); |
| 3639 | + f->display.x->v_scrollbar_width); | 4026 | base_height = CHAR_TO_PIXEL_HEIGHT (f, 0); |
| 3640 | base_height = ((2 * f->display.x->internal_border_width) | ||
| 3641 | + f->display.x->h_scrollbar_height); | ||
| 3642 | 4027 | ||
| 3643 | { | 4028 | { |
| 3644 | int min_rows = 0, min_cols = 0; | 4029 | int min_rows = 0, min_cols = 0; |
| @@ -3731,6 +4116,8 @@ x_wm_set_icon_position (f, icon_x, icon_y) | |||
| 3731 | } | 4116 | } |
| 3732 | 4117 | ||
| 3733 | 4118 | ||
| 4119 | /* Initialization. */ | ||
| 4120 | |||
| 3734 | void | 4121 | void |
| 3735 | x_term_init (display_name) | 4122 | x_term_init (display_name) |
| 3736 | char *display_name; | 4123 | char *display_name; |
| @@ -3784,7 +4171,11 @@ x_term_init (display_name) | |||
| 3784 | 4171 | ||
| 3785 | /* Figure out which modifier bits mean what. */ | 4172 | /* Figure out which modifier bits mean what. */ |
| 3786 | x_find_modifier_meanings (); | 4173 | x_find_modifier_meanings (); |
| 3787 | 4174 | ||
| 4175 | /* Get the scrollbar cursor. */ | ||
| 4176 | x_vertical_scrollbar_cursor = | ||
| 4177 | XCreateFontCursor (x_current_display, XC_sb_v_double_arrow); | ||
| 4178 | |||
| 3788 | /* Watch for PropertyNotify events on the root window; we use them | 4179 | /* Watch for PropertyNotify events on the root window; we use them |
| 3789 | to figure out when to invalidate our cache of the cut buffers. */ | 4180 | to figure out when to invalidate our cache of the cut buffers. */ |
| 3790 | x_watch_cut_buffer_cache (); | 4181 | x_watch_cut_buffer_cache (); |
| @@ -3839,8 +4230,12 @@ x_term_init (display_name) | |||
| 3839 | read_socket_hook = XTread_socket; | 4230 | read_socket_hook = XTread_socket; |
| 3840 | cursor_to_hook = XTcursor_to; | 4231 | cursor_to_hook = XTcursor_to; |
| 3841 | reassert_line_highlight_hook = XTreassert_line_highlight; | 4232 | reassert_line_highlight_hook = XTreassert_line_highlight; |
| 3842 | frame_rehighlight_hook = XTframe_rehighlight; | ||
| 3843 | mouse_position_hook = XTmouse_position; | 4233 | mouse_position_hook = XTmouse_position; |
| 4234 | frame_rehighlight_hook = XTframe_rehighlight; | ||
| 4235 | set_vertical_scrollbar_hook = XTset_scrollbar; | ||
| 4236 | condemn_scrollbars_hook = XTcondemn_scrollbars; | ||
| 4237 | redeem_scrollbar_hook = XTredeem_scrollbar; | ||
| 4238 | judge_scrollbars_hook = XTjudge_scrollbars; | ||
| 3844 | 4239 | ||
| 3845 | scroll_region_ok = 1; /* we'll scroll partial frames */ | 4240 | scroll_region_ok = 1; /* we'll scroll partial frames */ |
| 3846 | char_ins_del_ok = 0; /* just as fast to write the line */ | 4241 | char_ins_del_ok = 0; /* just as fast to write the line */ |