comparison src/keyboard.c @ 53128:c9aeaeb38318

(make_lispy_position): New function for generating mouse click positions from frame and pixel coordinates. Enhanced to return buffer position and actual row/column for events outside the text area using updated mode_line_string and marginal_area_string functions. Return left-fringe and right-fringe clicks as such, rather than clicks in text area. (make_lispy_event) [USE_X_TOOLKIT, USE_GTK]: Don't call pixel_to_glyph_coords, as we never use the results. (make_lispy_event): Use make_lispy_position for MOUSE_CLICK_EVENT, WHEEL_EVENT, and DRAG_N_DROP_EVENT to replace redundant code. Eliminate unused code in WHEEL_EVENT handling. (make_lispy_movement): Use make_lispy_position.
author Kim F. Storm <storm@cua.dk>
date Sun, 23 Nov 2003 00:09:39 +0000
parents 4ccaea0e450c
children ee96f9f80b61
comparison
equal deleted inserted replaced
53127:bc14fd4782c3 53128:c9aeaeb38318
584 Lisp_Object Qmode_line; 584 Lisp_Object Qmode_line;
585 Lisp_Object Qvertical_line; 585 Lisp_Object Qvertical_line;
586 Lisp_Object Qvertical_scroll_bar; 586 Lisp_Object Qvertical_scroll_bar;
587 Lisp_Object Qmenu_bar; 587 Lisp_Object Qmenu_bar;
588 extern Lisp_Object Qleft_margin, Qright_margin; 588 extern Lisp_Object Qleft_margin, Qright_margin;
589 extern Lisp_Object Qleft_fringe, Qright_fringe;
589 590
590 Lisp_Object recursive_edit_unwind (), command_loop (); 591 Lisp_Object recursive_edit_unwind (), command_loop ();
591 Lisp_Object Fthis_command_keys (); 592 Lisp_Object Fthis_command_keys ();
592 Lisp_Object Qextended_command_history; 593 Lisp_Object Qextended_command_history;
593 EMACS_TIME timer_check (); 594 EMACS_TIME timer_check ();
4953 4954
4954 /* The number of clicks in this multiple-click. */ 4955 /* The number of clicks in this multiple-click. */
4955 4956
4956 int double_click_count; 4957 int double_click_count;
4957 4958
4959 /* Return position of a mouse click or wheel event */
4960
4961 static Lisp_Object
4962 make_lispy_position (f, x, y, time)
4963 struct frame *f;
4964 Lisp_Object *x, *y;
4965 unsigned long time;
4966 {
4967 Lisp_Object window;
4968 enum window_part part;
4969 Lisp_Object posn = Qnil;
4970 Lisp_Object extra_info = Qnil;
4971 int wx, wy;
4972
4973 /* Set `window' to the window under frame pixel coordinates (x,y) */
4974 if (f)
4975 window = window_from_coordinates (f, XINT (*x), XINT (*y),
4976 &part, &wx, &wy, 0);
4977 else
4978 window = Qnil;
4979
4980 if (WINDOWP (window))
4981 {
4982 /* It's a click in window window at frame coordinates (x,y) */
4983 struct window *w = XWINDOW (window);
4984 Lisp_Object object = Qnil;
4985 int textpos = -1, rx = -1, ry = -1;
4986
4987 /* Set event coordinates to window-relative coordinates
4988 for constructing the Lisp event below. */
4989 XSETINT (*x, wx);
4990 XSETINT (*y, wy);
4991
4992 if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
4993 {
4994 /* Mode line or header line. Look for a string under
4995 the mouse that may have a `local-map' property. */
4996 Lisp_Object string;
4997 int charpos;
4998
4999 posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
5000 rx = wx, ry = wy;
5001 string = mode_line_string (w, &rx, &ry, part, &charpos);
5002 if (STRINGP (string))
5003 object = Fcons (string, make_number (charpos));
5004 if (w == XWINDOW (selected_window))
5005 textpos = PT;
5006 else
5007 textpos = XMARKER (w->pointm)->charpos;
5008 }
5009 else if (part == ON_VERTICAL_BORDER)
5010 {
5011 posn = Qvertical_line;
5012 wx = -1;
5013 }
5014 else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
5015 {
5016 Lisp_Object string;
5017 int charpos;
5018
5019 posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
5020 rx = wx, ry = wy;
5021 string = marginal_area_string (w, &rx, &ry, part, &charpos);
5022 if (STRINGP (string))
5023 object = Fcons (string, make_number (charpos));
5024 }
5025 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
5026 {
5027 posn = (part == ON_LEFT_FRINGE) ? Qleft_fringe : Qright_fringe;
5028 rx = 0;
5029 }
5030
5031 if (textpos < 0)
5032 {
5033 Lisp_Object string;
5034 struct display_pos p;
5035 wx = max (WINDOW_LEFT_MARGIN_WIDTH (w), wx);
5036 buffer_posn_from_coords (w, &wx, &wy, &string, &p);
5037 textpos = CHARPOS (p.pos);
5038 if (rx < 0)
5039 rx = wx;
5040 if (ry < 0)
5041 ry = wy;
5042
5043 if (NILP (posn))
5044 {
5045 posn = make_number (textpos);
5046 if (STRINGP (string))
5047 object = Fcons (string,
5048 make_number (CHARPOS (p.string_pos)));
5049 }
5050 }
5051
5052 extra_info = Fcons (object,
5053 Fcons (make_number (textpos),
5054 Fcons (Fcons (make_number (rx),
5055 make_number (ry)),
5056 Qnil)));
5057 }
5058 else if (f != 0)
5059 {
5060 XSETFRAME (window, f);
5061 }
5062 else
5063 {
5064 window = Qnil;
5065 XSETFASTINT (*x, 0);
5066 XSETFASTINT (*y, 0);
5067 }
5068
5069 return Fcons (window,
5070 Fcons (posn,
5071 Fcons (Fcons (*x, *y),
5072 Fcons (make_number (time),
5073 extra_info))));
5074 }
5075
4958 /* Given a struct input_event, build the lisp event which represents 5076 /* Given a struct input_event, build the lisp event which represents
4959 it. If EVENT is 0, build a mouse movement event from the mouse 5077 it. If EVENT is 0, build a mouse movement event from the mouse
4960 movement buffer, which should have a movement event in it. 5078 movement buffer, which should have a movement event in it.
4961 5079
4962 Note that events must be passed to this function in the order they 5080 Note that events must be passed to this function in the order they
5087 int button = event->code; 5205 int button = event->code;
5088 int is_double; 5206 int is_double;
5089 Lisp_Object position; 5207 Lisp_Object position;
5090 Lisp_Object *start_pos_ptr; 5208 Lisp_Object *start_pos_ptr;
5091 Lisp_Object start_pos; 5209 Lisp_Object start_pos;
5092 Lisp_Object window;
5093 5210
5094 position = Qnil; 5211 position = Qnil;
5095 5212
5096 /* Build the position as appropriate for this mouse click. */ 5213 /* Build the position as appropriate for this mouse click. */
5097 if (event->kind == MOUSE_CLICK_EVENT) 5214 if (event->kind == MOUSE_CLICK_EVENT)
5098 { 5215 {
5099 enum window_part part;
5100 struct frame *f = XFRAME (event->frame_or_window); 5216 struct frame *f = XFRAME (event->frame_or_window);
5101 Lisp_Object posn; 5217 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
5102 Lisp_Object string_info = Qnil;
5103 int row, column; 5218 int row, column;
5104 int wx, wy; 5219 #endif
5105 5220
5106 /* Ignore mouse events that were made on frame that 5221 /* Ignore mouse events that were made on frame that
5107 have been deleted. */ 5222 have been deleted. */
5108 if (! FRAME_LIVE_P (f)) 5223 if (! FRAME_LIVE_P (f))
5109 return Qnil; 5224 return Qnil;
5110 5225
5226 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
5111 /* EVENT->x and EVENT->y are frame-relative pixel 5227 /* EVENT->x and EVENT->y are frame-relative pixel
5112 coordinates at this place. Under old redisplay, COLUMN 5228 coordinates at this place. Under old redisplay, COLUMN
5113 and ROW are set to frame relative glyph coordinates 5229 and ROW are set to frame relative glyph coordinates
5114 which are then used to determine whether this click is 5230 which are then used to determine whether this click is
5115 in a menu (non-toolkit version). */ 5231 in a menu (non-toolkit version). */
5116 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y), 5232 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
5117 &column, &row, NULL, 1); 5233 &column, &row, NULL, 1);
5118 5234
5119 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
5120 /* In the non-toolkit version, clicks on the menu bar 5235 /* In the non-toolkit version, clicks on the menu bar
5121 are ordinary button events in the event buffer. 5236 are ordinary button events in the event buffer.
5122 Distinguish them, and invoke the menu. 5237 Distinguish them, and invoke the menu.
5123 5238
5124 (In the toolkit version, the toolkit handles the menu bar 5239 (In the toolkit version, the toolkit handles the menu bar
5168 5283
5169 return Fcons (item, Fcons (position, Qnil)); 5284 return Fcons (item, Fcons (position, Qnil));
5170 } 5285 }
5171 #endif /* not USE_X_TOOLKIT && not USE_GTK */ 5286 #endif /* not USE_X_TOOLKIT && not USE_GTK */
5172 5287
5173 /* Set `window' to the window under frame pixel coordinates 5288 position = make_lispy_position (f, &event->x, &event->y,
5174 event->x/event->y. */ 5289 event->timestamp);
5175 window = window_from_coordinates (f, XINT (event->x),
5176 XINT (event->y),
5177 &part, &wx, &wy, 0);
5178
5179 if (!WINDOWP (window))
5180 {
5181 window = event->frame_or_window;
5182 posn = Qnil;
5183 }
5184 else
5185 {
5186 /* It's a click in window window at frame coordinates
5187 event->x/ event->y. */
5188 struct window *w = XWINDOW (window);
5189
5190 /* Set event coordinates to window-relative coordinates
5191 for constructing the Lisp event below. */
5192 XSETINT (event->x, wx);
5193 XSETINT (event->y, wy);
5194
5195 if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
5196 {
5197 /* Mode line or header line. Look for a string under
5198 the mouse that may have a `local-map' property. */
5199 Lisp_Object string;
5200 int charpos;
5201
5202 posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
5203 string = mode_line_string (w, wx, wy, part, &charpos);
5204 if (STRINGP (string))
5205 string_info = Fcons (string, make_number (charpos));
5206 }
5207 else if (part == ON_VERTICAL_BORDER)
5208 posn = Qvertical_line;
5209 else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
5210 {
5211 int charpos;
5212 Lisp_Object object = marginal_area_string (w, wx, wy, part,
5213 &charpos);
5214 posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
5215 if (STRINGP (object))
5216 string_info = Fcons (object, make_number (charpos));
5217 }
5218 else
5219 {
5220 Lisp_Object object;
5221 struct display_pos p;
5222 buffer_posn_from_coords (w, &wx, &wy, &object, &p);
5223 posn = make_number (CHARPOS (p.pos));
5224 if (STRINGP (object))
5225 string_info
5226 = Fcons (object,
5227 make_number (CHARPOS (p.string_pos)));
5228 }
5229 }
5230
5231 position
5232 = Fcons (window,
5233 Fcons (posn,
5234 Fcons (Fcons (event->x, event->y),
5235 Fcons (make_number (event->timestamp),
5236 (NILP (string_info)
5237 ? Qnil
5238 : Fcons (string_info, Qnil))))));
5239 } 5290 }
5240 #ifndef USE_TOOLKIT_SCROLL_BARS 5291 #ifndef USE_TOOLKIT_SCROLL_BARS
5241 else 5292 else
5242 { 5293 {
5243 /* It's a scrollbar click. */ 5294 /* It's a scrollbar click. */
5295 Lisp_Object window;
5244 Lisp_Object portion_whole; 5296 Lisp_Object portion_whole;
5245 Lisp_Object part; 5297 Lisp_Object part;
5246 5298
5247 window = event->frame_or_window; 5299 window = event->frame_or_window;
5248 portion_whole = Fcons (event->x, event->y); 5300 portion_whole = Fcons (event->x, event->y);
5403 } 5455 }
5404 5456
5405 case WHEEL_EVENT: 5457 case WHEEL_EVENT:
5406 { 5458 {
5407 Lisp_Object position; 5459 Lisp_Object position;
5408 Lisp_Object window;
5409 Lisp_Object head; 5460 Lisp_Object head;
5410 5461
5411 /* Build the position as appropriate for this mouse click. */ 5462 /* Build the position as appropriate for this mouse click. */
5412 enum window_part part;
5413 struct frame *f = XFRAME (event->frame_or_window); 5463 struct frame *f = XFRAME (event->frame_or_window);
5414 Lisp_Object posn;
5415 Lisp_Object string_info = Qnil;
5416 int row, column;
5417 int wx, wy;
5418 position = Qnil;
5419 5464
5420 /* Ignore wheel events that were made on frame that have been 5465 /* Ignore wheel events that were made on frame that have been
5421 deleted. */ 5466 deleted. */
5422 if (! FRAME_LIVE_P (f)) 5467 if (! FRAME_LIVE_P (f))
5423 return Qnil; 5468 return Qnil;
5424 5469
5425 /* EVENT->x and EVENT->y are frame-relative pixel 5470 position = make_lispy_position (f, &event->x, &event->y,
5426 coordinates at this place. Under old redisplay, COLUMN 5471 event->timestamp);
5427 and ROW are set to frame relative glyph coordinates
5428 which are then used to determine whether this click is
5429 in a menu (non-toolkit version). */
5430 pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
5431 &column, &row, NULL, 1);
5432
5433 /* Set `window' to the window under frame pixel coordinates
5434 event->x/event->y. */
5435 window = window_from_coordinates (f, XINT (event->x),
5436 XINT (event->y),
5437 &part, &wx, &wy, 0);
5438
5439 if (!WINDOWP (window))
5440 {
5441 window = event->frame_or_window;
5442 posn = Qnil;
5443 }
5444 else
5445 {
5446 /* It's a click in window window at frame coordinates
5447 event->x/ event->y. */
5448 struct window *w = XWINDOW (window);
5449
5450 /* Set event coordinates to window-relative coordinates
5451 for constructing the Lisp event below. */
5452 XSETINT (event->x, wx);
5453 XSETINT (event->y, wy);
5454
5455 if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
5456 {
5457 /* Mode line or header line. Look for a string under
5458 the mouse that may have a `local-map' property. */
5459 Lisp_Object string;
5460 int charpos;
5461
5462 posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
5463 string = mode_line_string (w, wx, wy, part, &charpos);
5464 if (STRINGP (string))
5465 string_info = Fcons (string, make_number (charpos));
5466 }
5467 else if (part == ON_VERTICAL_BORDER)
5468 posn = Qvertical_line;
5469 else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
5470 {
5471 int charpos;
5472 Lisp_Object object = marginal_area_string (w, wx, wy, part,
5473 &charpos);
5474 posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
5475 if (STRINGP (object))
5476 string_info = Fcons (object, make_number (charpos));
5477 }
5478 else
5479 {
5480 Lisp_Object object;
5481 struct display_pos p;
5482 buffer_posn_from_coords (w, &wx, &wy, &object, &p);
5483 posn = make_number (CHARPOS (p.pos));
5484 if (STRINGP (object))
5485 string_info
5486 = Fcons (object,
5487 make_number (CHARPOS (p.string_pos)));
5488 }
5489 }
5490
5491 position
5492 = Fcons (window,
5493 Fcons (posn,
5494 Fcons (Fcons (event->x, event->y),
5495 Fcons (make_number (event->timestamp),
5496 (NILP (string_info)
5497 ? Qnil
5498 : Fcons (string_info, Qnil))))));
5499 5472
5500 /* Set double or triple modifiers to indicate the wheel speed. */ 5473 /* Set double or triple modifiers to indicate the wheel speed. */
5501 { 5474 {
5502 /* On window-system frames, use the value of 5475 /* On window-system frames, use the value of
5503 double-click-fuzz as is. On other frames, interpret it 5476 double-click-fuzz as is. On other frames, interpret it
5687 } 5660 }
5688 #endif /* WINDOWSNT */ 5661 #endif /* WINDOWSNT */
5689 5662
5690 case DRAG_N_DROP_EVENT: 5663 case DRAG_N_DROP_EVENT:
5691 { 5664 {
5692 enum window_part part;
5693 FRAME_PTR f; 5665 FRAME_PTR f;
5694 Lisp_Object window; 5666 Lisp_Object head, position;
5695 Lisp_Object posn;
5696 Lisp_Object files; 5667 Lisp_Object files;
5697 int wx, wy;
5698 5668
5699 /* The frame_or_window field should be a cons of the frame in 5669 /* The frame_or_window field should be a cons of the frame in
5700 which the event occurred and a list of the filenames 5670 which the event occurred and a list of the filenames
5701 dropped. */ 5671 dropped. */
5702 if (! CONSP (event->frame_or_window)) 5672 if (! CONSP (event->frame_or_window))
5708 /* Ignore mouse events that were made on frames that 5678 /* Ignore mouse events that were made on frames that
5709 have been deleted. */ 5679 have been deleted. */
5710 if (! FRAME_LIVE_P (f)) 5680 if (! FRAME_LIVE_P (f))
5711 return Qnil; 5681 return Qnil;
5712 5682
5713 window = window_from_coordinates (f, XINT (event->x), 5683 position = make_lispy_position (f, &event->x, &event->y,
5714 XINT (event->y), 5684 event->timestamp);
5715 &part, &wx, &wy, 0); 5685
5716 5686 head = modify_event_symbol (0, event->modifiers,
5717 if (!WINDOWP (window)) 5687 Qdrag_n_drop, Qnil,
5718 { 5688 lispy_drag_n_drop_names,
5719 window = XCAR (event->frame_or_window); 5689 &drag_n_drop_syms, 1);
5720 posn = Qnil; 5690 return Fcons (head,
5721 } 5691 Fcons (position,
5722 else 5692 Fcons (files,
5723 { 5693 Qnil)));
5724 /* It's an event in window `window' at frame coordinates
5725 event->x/ event->y. */
5726 struct window *w = XWINDOW (window);
5727
5728 /* Set event coordinates to window-relative coordinates
5729 for constructing the Lisp event below. */
5730 XSETINT (event->x, wx);
5731 XSETINT (event->y, wy);
5732
5733 if (part == ON_MODE_LINE)
5734 posn = Qmode_line;
5735 else if (part == ON_VERTICAL_BORDER)
5736 posn = Qvertical_line;
5737 else if (part == ON_HEADER_LINE)
5738 posn = Qheader_line;
5739 else
5740 {
5741 Lisp_Object object;
5742 struct display_pos p;
5743 buffer_posn_from_coords (w, &wx, &wy, &object, &p);
5744 posn = make_number (CHARPOS (p.pos));
5745 }
5746 }
5747
5748 {
5749 Lisp_Object head, position;
5750
5751 position
5752 = Fcons (window,
5753 Fcons (posn,
5754 Fcons (Fcons (event->x, event->y),
5755 Fcons (make_number (event->timestamp),
5756 Qnil))));
5757
5758 head = modify_event_symbol (0, event->modifiers,
5759 Qdrag_n_drop, Qnil,
5760 lispy_drag_n_drop_names,
5761 &drag_n_drop_syms, 1);
5762 return Fcons (head,
5763 Fcons (position,
5764 Fcons (files,
5765 Qnil)));
5766 }
5767 } 5694 }
5768 #endif /* HAVE_MOUSE */ 5695 #endif /* HAVE_MOUSE */
5769 5696
5770 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 5697 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
5771 || defined (USE_GTK) 5698 || defined (USE_GTK)
5834 } 5761 }
5835 5762
5836 /* Or is it an ordinary mouse movement? */ 5763 /* Or is it an ordinary mouse movement? */
5837 else 5764 else
5838 { 5765 {
5839 enum window_part area; 5766 Lisp_Object position;
5840 Lisp_Object window; 5767
5841 Lisp_Object posn; 5768 position = make_lispy_position (frame, &x, &y, time);
5842 int wx, wy;
5843
5844 if (frame)
5845 /* It's in a frame; which window on that frame? */
5846 window = window_from_coordinates (frame, XINT (x), XINT (y),
5847 &area, &wx, &wy, 0);
5848 else
5849 window = Qnil;
5850
5851 if (WINDOWP (window))
5852 {
5853 struct window *w = XWINDOW (window);
5854
5855 /* Set window relative coordinates. */
5856 XSETINT (x, wx);
5857 XSETINT (y, wy);
5858
5859 if (area == ON_MODE_LINE)
5860 posn = Qmode_line;
5861 else if (area == ON_VERTICAL_BORDER)
5862 posn = Qvertical_line;
5863 else if (area == ON_HEADER_LINE)
5864 posn = Qheader_line;
5865 else
5866 {
5867 Lisp_Object object;
5868 struct display_pos p;
5869 buffer_posn_from_coords (w, &wx, &wy, &object, &p);
5870 posn = make_number (CHARPOS (p.pos));
5871 }
5872 }
5873 else if (frame != 0)
5874 {
5875 XSETFRAME (window, frame);
5876 posn = Qnil;
5877 }
5878 else
5879 {
5880 window = Qnil;
5881 posn = Qnil;
5882 XSETFASTINT (x, 0);
5883 XSETFASTINT (y, 0);
5884 }
5885 5769
5886 return Fcons (Qmouse_movement, 5770 return Fcons (Qmouse_movement,
5887 Fcons (Fcons (window, 5771 Fcons (position,
5888 Fcons (posn,
5889 Fcons (Fcons (x, y),
5890 Fcons (make_number (time),
5891 Qnil)))),
5892 Qnil)); 5772 Qnil));
5893 } 5773 }
5894 } 5774 }
5895 5775
5896 #endif /* HAVE_MOUSE */ 5776 #endif /* HAVE_MOUSE */