Mercurial > emacs
comparison src/xterm.c @ 1720:4f5e3ac5d822
* 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.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Thu, 24 Dec 1992 06:21:14 +0000 |
parents | 452ba03935d7 |
children | d738d3690836 |
comparison
equal
deleted
inserted
replaced
1719:48f539ac6921 | 1720:4f5e3ac5d822 |
---|---|
36 #include <signal.h> | 36 #include <signal.h> |
37 | 37 |
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. |
44 In some systems loading it twice is suicidal. */ | 45 In some systems loading it twice is suicidal. */ |
45 #ifndef makedev | 46 #ifndef makedev |
87 #endif /* ! 0 */ | 88 #endif /* ! 0 */ |
88 #include "gnu.h" | 89 #include "gnu.h" |
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. */ |
95 #else /* ! defined (HAVE_X11) */ | 97 #else /* ! defined (HAVE_X11) */ |
96 #include <X/Xkeyboard.h> | 98 #include <X/Xkeyboard.h> |
103 #define min(a,b) ((a)<(b) ? (a) : (b)) | 105 #define min(a,b) ((a)<(b) ? (a) : (b)) |
104 #define max(a,b) ((a)>(b) ? (a) : (b)) | 106 #define max(a,b) ((a)>(b) ? (a) : (b)) |
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. */ |
113 | 116 |
114 static int expose_all_icons; | 117 static int expose_all_icons; |
156 Lisp_Object invocation_name; | 159 Lisp_Object invocation_name; |
157 | 160 |
158 /* This is the X connection that we are using. */ | 161 /* This is the X connection that we are using. */ |
159 | 162 |
160 Display *x_current_display; | 163 Display *x_current_display; |
164 | |
165 /* The cursor to use for vertical scrollbars on x_current_display. */ | |
166 static Cursor x_vertical_scrollbar_cursor; | |
161 | 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. |
165 In that case, the XT functions assume that `selected_frame' | 171 In that case, the XT functions assume that `selected_frame' |
166 is the frame to apply to. */ | 172 is the frame to apply to. */ |
167 | 173 |
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; |
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; | |
173 | 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 |
177 frame. It differs from x_focus_frame when we're using a global | 192 frame. It differs from x_focus_frame when we're using a global |
258 void dumpborder (); | 273 void dumpborder (); |
259 static int XTcursor_to (); | 274 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 |
267 should never be called except during an update, the only exceptions | 284 should never be called except during an update, the only exceptions |
268 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */ | 285 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */ |
287 dumpqueue (); | 304 dumpqueue (); |
288 #endif /* HAVE_X11 */ | 305 #endif /* HAVE_X11 */ |
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) |
296 struct frame *f; | 315 struct frame *f; |
297 { | 316 { |
302 abort (); | 321 abort (); |
303 | 322 |
304 BLOCK_INPUT; | 323 BLOCK_INPUT; |
305 #ifndef HAVE_X11 | 324 #ifndef HAVE_X11 |
306 dumpqueue (); | 325 dumpqueue (); |
326 x_do_pending_expose (); | |
307 #endif /* HAVE_X11 */ | 327 #endif /* HAVE_X11 */ |
308 adjust_scrollbars (f); | |
309 x_do_pending_expose (); | |
310 | 328 |
311 x_display_cursor (f, 1); | 329 x_display_cursor (f, 1); |
312 | 330 |
313 updating_frame = 0; | 331 updating_frame = 0; |
314 XFlushQueue (); | 332 XFlushQueue (); |
354 XTreset_terminal_modes () | 372 XTreset_terminal_modes () |
355 { | 373 { |
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 |
364 XTcursor_to (row, col) | 382 XTcursor_to (row, col) |
365 register int row, col; | 383 register int row, col; |
522 left += len * FONT_WIDTH (font); | 540 left += len * FONT_WIDTH (font); |
523 } | 541 } |
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, |
532 controls the pixel values used for foreground and background. */ | 550 controls the pixel values used for foreground and background. */ |
533 | 551 |
575 curs_x += len; | 593 curs_x += len; |
576 | 594 |
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 |
584 static int | 603 static int |
585 XTclear_end_of_line (first_unused) | 604 XTclear_end_of_line (first_unused) |
756 XFlushQueue (); | 775 XFlushQueue (); |
757 UNBLOCK_INPUT; | 776 UNBLOCK_INPUT; |
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) |
766 register char *start; | 786 register char *start; |
767 register int len; | 787 register int len; |
792 flexlines = updating_frame->height; | 812 flexlines = updating_frame->height; |
793 else | 813 else |
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) |
802 register int n; | 822 register int n; |
803 { | 823 { |
953 scraplines (-n); | 973 scraplines (-n); |
954 XFlushQueue (); | 974 XFlushQueue (); |
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) |
961 the characters in f->phys_lines that overlap that rectangle. | 982 the characters in f->phys_lines that overlap that rectangle. |
962 TOP and LEFT are the position of the upper left corner of the rectangle. | 983 TOP and LEFT are the position of the upper left corner of the rectangle. |
1070 } | 1091 } |
1071 XFlushQueue (); | 1092 XFlushQueue (); |
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 { |
1082 int mask; | 1104 int mask; |
1083 struct frame *f; | 1105 struct frame *f; |
1137 ; | 1159 ; |
1138 #else /* ! defined (HAVE_X11) */ | 1160 #else /* ! defined (HAVE_X11) */ |
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 |
1145 frame_highlight (frame) | 1168 frame_highlight (frame) |
1146 struct frame *frame; | 1169 struct frame *frame; |
1243 | 1266 |
1244 XTframe_rehighlight (); | 1267 XTframe_rehighlight (); |
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 { |
1254 struct frame *old_highlight = x_highlight_frame; | 1277 struct frame *old_highlight = x_highlight_frame; |
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; |
1265 | 1293 |
1266 if (x_highlight_frame != old_highlight) | 1294 if (x_highlight_frame != old_highlight) |
1269 frame_unhighlight (old_highlight); | 1297 frame_unhighlight (old_highlight); |
1270 if (x_highlight_frame) | 1298 if (x_highlight_frame) |
1271 frame_highlight (x_highlight_frame); | 1299 frame_highlight (x_highlight_frame); |
1272 } | 1300 } |
1273 } | 1301 } |
1274 | |
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 | 1302 |
1383 /* Mouse clicks and mouse movement. Rah. */ | 1303 /* Mouse clicks and mouse movement. Rah. */ |
1384 #ifdef HAVE_X11 | 1304 #ifdef HAVE_X11 |
1385 | 1305 |
1386 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return | 1306 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return |
1529 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0) | 1449 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0) |
1530 | ((state & ControlMask) ? ctrl_modifier : 0) | 1450 | ((state & ControlMask) ? ctrl_modifier : 0) |
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; | 1464 { |
1551 Lisp_Object part; | 1465 /* Make the event type no_event; we'll change that when we decide |
1552 { | |
1553 /* Initialize those fields text and scrollbar clicks hold in common. | |
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 |
1561 ? up_modifier | 1472 ? up_modifier |
1562 : down_modifier)); | 1473 : down_modifier)); |
1573 x_mouse_grabbed &= ~(1 << event->button); | 1484 x_mouse_grabbed &= ~(1 << event->button); |
1574 if (!x_mouse_grabbed) | 1485 if (!x_mouse_grabbed) |
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; | 1491 |
1581 | 1492 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); |
1582 pos = event->y - (f->display.x->v_scrollbar_width - 2); | 1493 XFASTINT (result->x) = column; |
1583 x_mouse_x = pos; | 1494 XFASTINT (result->y) = row; |
1584 len = ((FONT_HEIGHT (f->display.x->font) * f->height) | 1495 result->frame = f; |
1585 + f->display.x->internal_border_width | 1496 } |
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 | |
1599 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); | |
1600 result->kind = mouse_click; | |
1601 XFASTINT (result->x) = column; | |
1602 XFASTINT (result->y) = row; | |
1603 result->frame = f; | |
1604 } | |
1605 } | 1497 } |
1606 | 1498 |
1607 | 1499 |
1608 /* Mouse movement. Rah. | 1500 /* Mouse movement. Rah. |
1609 | 1501 |
1626 | 1518 |
1627 /* Where the mouse was last time we reported a mouse event. */ | 1519 /* Where the mouse was last time we reported a mouse event. */ |
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 |
1634 along with the position query. So, we just keep track of the time | 1535 along with the position query. So, we just keep track of the time |
1635 of the last movement we received, and return that in hopes that | 1536 of the last movement we received, and return that in hopes that |
1677 position. This also calls XQueryPointer, which will cause the | 1578 position. This also calls XQueryPointer, which will cause the |
1678 server to give us another MotionNotify when the mouse moves again. | 1579 server to give us another MotionNotify when the mouse moves again. |
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 { |
1687 int ix, iy, dummy; | 1590 int ix, iy, dummy; |
1688 Display *d = x_current_display; | 1591 Display *d = x_current_display; |
1722 /* When XQueryPointer returns False, the pointer isn't in guess | 1625 /* When XQueryPointer returns False, the pointer isn't in guess |
1723 anymore, but root is the root window of the frame we should | 1626 anymore, but root is the root window of the frame we should |
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 |
1741 return the time of the last MotionNotify event we received. Note | 1662 return the time of the last MotionNotify event we received. Note |
1742 that the use of motion hints means that this isn't guaranteed to | 1663 that the use of motion hints means that this isn't guaranteed to |
1748 | 1669 |
1749 #else /* ! defined (HAVE_X11) */ | 1670 #else /* ! defined (HAVE_X11) */ |
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 |
1756 sometimes don't work. */ | 2143 sometimes don't work. */ |
1757 static Time enter_timestamp; | 2144 static Time enter_timestamp; |
1929 f->async_visible = 1; | 2316 f->async_visible = 1; |
1930 f->async_iconified = 0; | 2317 f->async_iconified = 0; |
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 |
1950 source area was completely | 2353 source area was completely |
1951 available */ | 2354 available */ |
1998 abort (); | 2401 abort (); |
1999 #endif /* ! defined (HAVE_X11) */ | 2402 #endif /* ! defined (HAVE_X11) */ |
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: |
2020 f = x_window_to_frame (event.xmap.window); | 2418 f = x_window_to_frame (event.xmap.window); |
2021 if (f) | 2419 if (f) |
2044 #endif /* ! defined (HAVE_X11) */ | 2442 #endif /* ! defined (HAVE_X11) */ |
2045 | 2443 |
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; |
2052 char copy_buffer[80]; | 2451 char copy_buffer[80]; |
2053 int modifiers = event.xkey.state; | 2452 int modifiers = event.xkey.state; |
2163 } | 2562 } |
2164 break; | 2563 break; |
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) |
2183 || (event.xcrossing.time - enter_timestamp) > 500)) | 2582 || (event.xcrossing.time - enter_timestamp) > 500)) |
2184 { | 2583 { |
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 | 2604 |
2227 && event.xcrossing.mode == NotifyNormal) | 2605 if (event.xcrossing.focus) |
2228 { | 2606 { |
2229 f = x_window_to_frame (event.xcrossing.window); | 2607 if (! x_focus_event_frame) |
2230 | 2608 x_new_focus_frame (0); |
2231 if (event.xcrossing.focus) | 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; |
2243 | 2629 |
2244 #else /* ! defined (HAVE_X11) */ | 2630 #else /* ! defined (HAVE_X11) */ |
2281 case MotionNotify: | 2667 case MotionNotify: |
2282 { | 2668 { |
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 |
2296 case ConfigureNotify: | 2683 case ConfigureNotify: |
2297 { | 2684 { |
2298 int rows, columns; | 2685 int rows, columns; |
2299 f = x_window_to_frame (event.xconfigure.window); | 2686 f = x_window_to_frame (event.xconfigure.window); |
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 |
2314 to check the pixel dimensions as well. */ | 2695 to check the pixel dimensions as well. */ |
2315 if (columns != f->width | 2696 if (columns != f->width |
2316 || rows != f->height | 2697 || rows != f->height |
2317 || event.xconfigure.width != f->display.x->pixel_width | 2698 || event.xconfigure.width != f->display.x->pixel_width |
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 |
2325 f->display.x->pixel_width = event.xconfigure.width; | 2705 f->display.x->pixel_width = event.xconfigure.width; |
2326 f->display.x->pixel_height = event.xconfigure.height; | 2706 f->display.x->pixel_height = event.xconfigure.height; |
2337 struct input_event emacs_event; | 2717 struct input_event emacs_event; |
2338 emacs_event.kind = no_event; | 2718 emacs_event.kind = no_event; |
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 { |
2360 bcopy (&emacs_event, bufp, sizeof (struct input_event)); | 2738 bcopy (&emacs_event, bufp, sizeof (struct input_event)); |
2361 bufp++; | 2739 bufp++; |
2450 kill (getpid (), SIGHUP); | 2828 kill (getpid (), SIGHUP); |
2451 } | 2829 } |
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; |
2460 } | 2840 } |
2461 | 2841 |
2523 } | 2903 } |
2524 } | 2904 } |
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 |
2531 x_draw_box (f) | 2914 x_draw_box (f) |
2532 struct frame *f; | 2915 struct frame *f; |
2571 clear_cursor (f) | 2954 clear_cursor (f) |
2572 struct frame *f; | 2955 struct frame *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 |
2580 #ifdef HAVE_X11 | 2963 #ifdef HAVE_X11 |
2581 x_display_cursor (f, 0); | 2964 x_display_cursor (f, 0); |
2606 register int phys_y = f->phys_cursor_y; | 2989 register int phys_y = f->phys_cursor_y; |
2607 register int x1; | 2990 register int x1; |
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 |
2615 if (phys_x >= 0 && | 2998 if (phys_x >= 0 && |
2616 (!on || phys_x != f->cursor_x || phys_y != f->cursor_y)) | 2999 (!on || phys_x != f->cursor_x || phys_y != f->cursor_y)) |
2683 { | 3066 { |
2684 curs_x = FRAME_CURSOR_X (f); | 3067 curs_x = FRAME_CURSOR_X (f); |
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. */ |
2692 if (!on && f->phys_cursor_x < 0) | 3075 if (!on && f->phys_cursor_x < 0) |
2693 return; | 3076 return; |
2948 Display *display; | 3331 Display *display; |
2949 XErrorEvent *error; | 3332 XErrorEvent *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 |
2956 XGetErrorText (display, error->error_code, buf, sizeof (buf)); | 3343 XGetErrorText (display, error->error_code, buf, sizeof (buf)); |
2957 fprintf (stderr, "X protocol error: %s on protocol request %d\n", | 3344 fprintf (stderr, "X protocol error: %s on protocol request %d\n", |
3039 fprintf (stderr, "Lib call: %d\n", ++x_wire_count); | 3426 fprintf (stderr, "Lib call: %d\n", ++x_wire_count); |
3040 } | 3427 } |
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. */ |
3047 | 3436 |
3048 #ifdef HAVE_X11 | 3437 #ifdef HAVE_X11 |
3169 | 3558 |
3170 return 0; | 3559 return 0; |
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 { |
3177 #ifdef HAVE_X11 | 3568 #ifdef HAVE_X11 |
3178 if (f->display.x->left_pos < 0) | 3569 if (f->display.x->left_pos < 0) |
3225 int ibw = f->display.x->internal_border_width; | 3616 int ibw = f->display.x->internal_border_width; |
3226 | 3617 |
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); |
3237 #endif /* ! defined (HAVE_X11) */ | 3630 #endif /* ! defined (HAVE_X11) */ |
3238 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight); | 3631 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight); |
3259 2 * f->display.x->internal_border_width, | 3652 2 * f->display.x->internal_border_width, |
3260 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font)); | 3653 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font)); |
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; |
3267 int x, y; | 3661 int x, y; |
3268 { | 3662 { |
3269 int pix_x, pix_y; | 3663 int pix_x, pix_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; |
3298 } | 3684 } |
3299 | 3685 |
3366 #ifdef HAVE_X11 | 3752 #ifdef HAVE_X11 |
3367 if (! EQ (Vx_no_window_manager, Qt)) | 3753 if (! EQ (Vx_no_window_manager, Qt)) |
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)); |
3375 if (f->display.x->icon_desc != 0) | 3761 if (f->display.x->icon_desc != 0) |
3376 XUnmapWindow (f->display.x->icon_desc); | 3762 XUnmapWindow (f->display.x->icon_desc); |
3533 x_focus_frame = 0; | 3919 x_focus_frame = 0; |
3534 if (f == x_highlight_frame) | 3920 if (f == x_highlight_frame) |
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. |
3541 | 3929 |
3542 This code is only used by the X10 support. | 3930 This code is only used by the X10 support. |
3605 { | 3993 { |
3606 return queue_event_count (&x_mouse_queue); | 3994 return queue_event_count (&x_mouse_queue); |
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) |
3613 struct frame *f; | 4003 struct frame *f; |
3614 long prompting; | 4004 long prompting; |
3624 size_hints.y = f->display.x->top_pos; | 4014 size_hints.y = f->display.x->top_pos; |
3625 size_hints.height = PIXEL_HEIGHT (f); | 4015 size_hints.height = PIXEL_HEIGHT (f); |
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; |
3645 check_frame_size (f, &min_rows, &min_cols); | 4030 check_frame_size (f, &min_rows, &min_cols); |
3646 | 4031 |
3729 | 4114 |
3730 XSetWMHints (x_current_display, window, &f->display.x->wm_hints); | 4115 XSetWMHints (x_current_display, window, &f->display.x->wm_hints); |
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; |
3737 { | 4124 { |
3738 Lisp_Object frame; | 4125 Lisp_Object frame; |
3782 sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname); | 4169 sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname); |
3783 } | 4170 } |
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 (); |
3791 | 4182 |
3792 dup2 (ConnectionNumber (x_current_display), 0); | 4183 dup2 (ConnectionNumber (x_current_display), 0); |
3837 update_end_hook = XTupdate_end; | 4228 update_end_hook = XTupdate_end; |
3838 set_terminal_window_hook = XTset_terminal_window; | 4229 set_terminal_window_hook = XTset_terminal_window; |
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; |
4233 mouse_position_hook = XTmouse_position; | |
3842 frame_rehighlight_hook = XTframe_rehighlight; | 4234 frame_rehighlight_hook = XTframe_rehighlight; |
3843 mouse_position_hook = XTmouse_position; | 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 */ |
3847 line_ins_del_ok = 1; /* we'll just blt 'em */ | 4242 line_ins_del_ok = 1; /* we'll just blt 'em */ |
3848 fast_clear_end_of_line = 1; /* X does this well */ | 4243 fast_clear_end_of_line = 1; /* X does this well */ |