aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-07-04 16:40:20 +0800
committerPo Lu2023-07-04 16:40:20 +0800
commit8ed8f08ed2ff297754d6db83983d3f8f2822c599 (patch)
tree4e5545280bc671f4d9952cc70826b86ce6c76b18 /src
parent2963924d803e2d0247169f477c31d4c91281928b (diff)
downloademacs-8ed8f08ed2ff297754d6db83983d3f8f2822c599.tar.gz
emacs-8ed8f08ed2ff297754d6db83983d3f8f2822c599.zip
Implement a tool bar containing modifier keys
* doc/emacs/frames.texi (Tool Bars): Describe modifier bars. * doc/lispref/keymaps.texi (Extended Menu Items, Tool Bar): Document changes to tool bar menu item handling and secondary tool bars. * etc/NEWS: Announce changes. * lisp/simple.el (event-apply-modifier): Correctly apply Ctrl and Shift modifiers to lower case ASCII key events that already have other modifiers applied. * lisp/tool-bar.el (tool-bar--cache-key) (tool-bar--secondary-cache-key): New defsubsts. (tool-bar--flush-cache): Flush secondary tool bar cache. (tool-bar-make-keymap): Include secondary tool bar if necessary. (tool-bar-make-keymap-1): New arg MAP. Generate a keymap for that map if specified, else default to tool-bar-map. (set-text-conversion-style, tool-bar-apply-modifiers) (overriding-text-conversion-style) (tool-bar-event-apply-alt-modifier) (tool-bar-event-apply-super-modifier) (tool-bar-event-apply-hyper-modifier) (tool-bar-event-apply-shift-modifier) (tool-bar-event-apply-control-modifier) (tool-bar-event-apply-meta-modifier, modifier-bar-mode): New functions. * src/dispextern.h (enum tool_bar_item_idx): Add TOOL_BAR_ITEM_WRAP. * src/frame.c (make_frame): Clear new field `tool_bar_wraps_p'. * src/frame.h (struct frame): New field `tool_bar_wraps_p'. * src/keyboard.c (parse_tool_bar_item): Handle QCwrap properties in tool bar menu items. (syms_of_keyboard): New defsym QCwrap. * src/xdisp.c (build_desired_tool_bar_string): Clear f->tool_bar_wraps_p and set it appropriately. Insert new line characters in the tool bar string upon encountering a wrap character. (display_tool_bar_line): Stop at EOB, not line end. Reseat on the next line upon encountering EOL characters. (redisplay_tool_bar): Allow rows to be different heights if explicit new lines are present upon the tool bar string.
Diffstat (limited to 'src')
-rw-r--r--src/dispextern.h6
-rw-r--r--src/frame.c1
-rw-r--r--src/frame.h4
-rw-r--r--src/keyboard.c42
-rw-r--r--src/xdisp.c100
5 files changed, 134 insertions, 19 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index 402972d33d9..cf67121809f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3364,9 +3364,13 @@ enum tool_bar_item_idx
3364 /* If we shall show the label only below the icon and not beside it. */ 3364 /* If we shall show the label only below the icon and not beside it. */
3365 TOOL_BAR_ITEM_VERT_ONLY, 3365 TOOL_BAR_ITEM_VERT_ONLY,
3366 3366
3367 /* Whether or not this tool bar item is hidden and should cause
3368 subsequent items to be displayed on a new line. */
3369 TOOL_BAR_ITEM_WRAP,
3370
3367 /* Sentinel = number of slots in tool_bar_items occupied by one 3371 /* Sentinel = number of slots in tool_bar_items occupied by one
3368 tool-bar item. */ 3372 tool-bar item. */
3369 TOOL_BAR_ITEM_NSLOTS 3373 TOOL_BAR_ITEM_NSLOTS,
3370}; 3374};
3371 3375
3372 3376
diff --git a/src/frame.c b/src/frame.c
index 65711106671..35881ce6de1 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -986,6 +986,7 @@ make_frame (bool mini_p)
986 f->last_tab_bar_item = -1; 986 f->last_tab_bar_item = -1;
987#ifndef HAVE_EXT_TOOL_BAR 987#ifndef HAVE_EXT_TOOL_BAR
988 f->last_tool_bar_item = -1; 988 f->last_tool_bar_item = -1;
989 f->tool_bar_wraps_p = false;
989#endif 990#endif
990#ifdef NS_IMPL_COCOA 991#ifdef NS_IMPL_COCOA
991 f->ns_appearance = ns_appearance_system_default; 992 f->ns_appearance = ns_appearance_system_default;
diff --git a/src/frame.h b/src/frame.h
index 8142dec456b..8ed9c0f37d8 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -344,6 +344,10 @@ struct frame
344 /* Set to true to minimize tool-bar height even when 344 /* Set to true to minimize tool-bar height even when
345 auto-resize-tool-bar is set to grow-only. */ 345 auto-resize-tool-bar is set to grow-only. */
346 bool_bf minimize_tool_bar_window_p : 1; 346 bool_bf minimize_tool_bar_window_p : 1;
347
348 /* Whether or not the tool bar contains a ``new line'' item. If
349 true, tool bar rows will be allowed to differ in height. */
350 bool_bf tool_bar_wraps_p : 1;
347#endif 351#endif
348 352
349#ifdef HAVE_EXT_TOOL_BAR 353#ifdef HAVE_EXT_TOOL_BAR
diff --git a/src/keyboard.c b/src/keyboard.c
index 19fdbd11724..b33fbf8f155 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -9325,7 +9325,13 @@ set_prop (ptrdiff_t idx, Lisp_Object val)
9325 9325
9326 - `:label LABEL-STRING'. 9326 - `:label LABEL-STRING'.
9327 9327
9328 A text label to show with the tool bar button if labels are enabled. */ 9328 A text label to show with the tool bar button if labels are
9329 enabled.
9330
9331 - `:wrap WRAP'
9332
9333 WRAP specifies whether to hide this item but display subsequent
9334 tool bar items on a new line. */
9329 9335
9330static bool 9336static bool
9331parse_tool_bar_item (Lisp_Object key, Lisp_Object item) 9337parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
@@ -9333,7 +9339,15 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
9333 Lisp_Object filter = Qnil; 9339 Lisp_Object filter = Qnil;
9334 Lisp_Object caption; 9340 Lisp_Object caption;
9335 int i; 9341 int i;
9336 bool have_label = false; 9342 bool have_label;
9343#ifndef HAVE_EXT_TOOL_BAR
9344 bool is_wrap;
9345#endif /* HAVE_EXT_TOOL_BAR */
9346
9347 have_label = false;
9348#ifndef HAVE_EXT_TOOL_BAR
9349 is_wrap = false;
9350#endif /* HAVE_EXT_TOOL_BAR */
9337 9351
9338 /* Definition looks like `(menu-item CAPTION BINDING PROPS...)'. 9352 /* Definition looks like `(menu-item CAPTION BINDING PROPS...)'.
9339 Rule out items that aren't lists, don't start with 9353 Rule out items that aren't lists, don't start with
@@ -9469,6 +9483,20 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
9469 else if (EQ (ikey, QCrtl)) 9483 else if (EQ (ikey, QCrtl))
9470 /* ':rtl STRING' */ 9484 /* ':rtl STRING' */
9471 set_prop (TOOL_BAR_ITEM_RTL_IMAGE, value); 9485 set_prop (TOOL_BAR_ITEM_RTL_IMAGE, value);
9486 else if (EQ (ikey, QCwrap))
9487 {
9488#ifndef HAVE_EXT_TOOL_BAR
9489 /* This specifies whether the tool bar item should be hidden
9490 but cause subsequent items to be displayed on a new
9491 line. */
9492 set_prop (TOOL_BAR_ITEM_WRAP, value);
9493 is_wrap = !NILP (value);
9494#else /* HAVE_EXT_TOOL_BAR */
9495 /* Line wrapping isn't supported on builds utilizing
9496 external tool bars. */
9497 return false;
9498#endif /* !HAVE_EXT_TOOL_BAR */
9499 }
9472 } 9500 }
9473 9501
9474 9502
@@ -9529,6 +9557,15 @@ parse_tool_bar_item (Lisp_Object key, Lisp_Object item)
9529 if (CONSP (get_keymap (PROP (TOOL_BAR_ITEM_BINDING), 0, 1))) 9557 if (CONSP (get_keymap (PROP (TOOL_BAR_ITEM_BINDING), 0, 1)))
9530 return 0; 9558 return 0;
9531 9559
9560
9561#ifndef HAVE_EXT_TOOL_BAR
9562 /* If the menu item is actually a line wrap, make sure it isn't
9563 visible or enabled. */
9564
9565 if (is_wrap)
9566 set_prop (TOOL_BAR_ITEM_ENABLED_P, Qnil);
9567#endif /* !HAVE_EXT_TOOL_BAR */
9568
9532 /* If there is a key binding, add it to the help, which will be 9569 /* If there is a key binding, add it to the help, which will be
9533 displayed as a tooltip for this entry. */ 9570 displayed as a tooltip for this entry. */
9534 Lisp_Object binding = PROP (TOOL_BAR_ITEM_BINDING); 9571 Lisp_Object binding = PROP (TOOL_BAR_ITEM_BINDING);
@@ -12482,6 +12519,7 @@ syms_of_keyboard (void)
12482 DEFSYM (Qhelp_echo, "help-echo"); 12519 DEFSYM (Qhelp_echo, "help-echo");
12483 DEFSYM (Qhelp_echo_inhibit_substitution, "help-echo-inhibit-substitution"); 12520 DEFSYM (Qhelp_echo_inhibit_substitution, "help-echo-inhibit-substitution");
12484 DEFSYM (QCrtl, ":rtl"); 12521 DEFSYM (QCrtl, ":rtl");
12522 DEFSYM (QCwrap, ":wrap");
12485 12523
12486 staticpro (&item_properties); 12524 staticpro (&item_properties);
12487 item_properties = Qnil; 12525 item_properties = Qnil;
diff --git a/src/xdisp.c b/src/xdisp.c
index 43c628b73d8..d09116b3fb5 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -15000,7 +15000,10 @@ update_tool_bar (struct frame *f, bool save_match_data)
15000 15000
15001/* Set F->desired_tool_bar_string to a Lisp string representing frame 15001/* Set F->desired_tool_bar_string to a Lisp string representing frame
15002 F's desired tool-bar contents. F->tool_bar_items must have 15002 F's desired tool-bar contents. F->tool_bar_items must have
15003 been set up previously by calling prepare_menu_bars. */ 15003 been set up previously by calling prepare_menu_bars.
15004
15005 Also set F->tool_bar_wraps_p to whether or not the tool bar
15006 contains explicit line breaking items. */
15004 15007
15005static void 15008static void
15006build_desired_tool_bar_string (struct frame *f) 15009build_desired_tool_bar_string (struct frame *f)
@@ -15022,9 +15025,11 @@ build_desired_tool_bar_string (struct frame *f)
15022 size_needed = f->n_tool_bar_items; 15025 size_needed = f->n_tool_bar_items;
15023 15026
15024 /* Reuse f->desired_tool_bar_string, if possible. */ 15027 /* Reuse f->desired_tool_bar_string, if possible. */
15028
15025 if (size < size_needed || NILP (f->desired_tool_bar_string)) 15029 if (size < size_needed || NILP (f->desired_tool_bar_string))
15026 fset_desired_tool_bar_string 15030 /* Don't initialize the contents of this string yet, as they will
15027 (f, Fmake_string (make_fixnum (size_needed), make_fixnum (' '), Qnil)); 15031 be set within the loop below. */
15032 fset_desired_tool_bar_string (f, make_uninit_string (size_needed));
15028 else 15033 else
15029 { 15034 {
15030 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil); 15035 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
@@ -15032,6 +15037,8 @@ build_desired_tool_bar_string (struct frame *f)
15032 props, f->desired_tool_bar_string); 15037 props, f->desired_tool_bar_string);
15033 } 15038 }
15034 15039
15040 f->tool_bar_wraps_p = false;
15041
15035 /* Put a `display' property on the string for the images to display, 15042 /* Put a `display' property on the string for the images to display,
15036 put a `menu_item' property on tool-bar items with a value that 15043 put a `menu_item' property on tool-bar items with a value that
15037 is the index of the item in F's tool-bar item vector. */ 15044 is the index of the item in F's tool-bar item vector. */
@@ -15044,6 +15051,21 @@ build_desired_tool_bar_string (struct frame *f)
15044 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); 15051 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15045 int hmargin, vmargin, relief, idx, end; 15052 int hmargin, vmargin, relief, idx, end;
15046 15053
15054 if (!NILP (PROP (TOOL_BAR_ITEM_WRAP)))
15055 {
15056 /* This is a line wrap. Instead of building a tool bar
15057 item, display a new line character instead. */
15058 SSET (f->desired_tool_bar_string, i, '\n');
15059
15060 /* Set F->tool_bar_wraps_p. This tells redisplay_tool_bar
15061 to allow individual rows to be different heights. */
15062 f->tool_bar_wraps_p = true;
15063 continue;
15064 }
15065
15066 /* Replace this with a space character. */
15067 SSET (f->desired_tool_bar_string, i, ' ');
15068
15047 /* If image is a vector, choose the image according to the 15069 /* If image is a vector, choose the image according to the
15048 button state. */ 15070 button state. */
15049 image = PROP (TOOL_BAR_ITEM_IMAGES); 15071 image = PROP (TOOL_BAR_ITEM_IMAGES);
@@ -15155,6 +15177,16 @@ build_desired_tool_bar_string (struct frame *f)
15155 props, f->desired_tool_bar_string); 15177 props, f->desired_tool_bar_string);
15156#undef PROP 15178#undef PROP
15157 } 15179 }
15180
15181 /* Now replace each character between i and the end of the tool bar
15182 string with spaces, to prevent stray newlines from accumulating
15183 when the number of tool bar items decreases. `size' is 0 if the
15184 tool bar string is new, but in that case the string will have
15185 been completely initialized anyway. */
15186
15187 for (; i < size; ++i)
15188 /* Replace this with a space character. */
15189 SSET (f->desired_tool_bar_string, i, ' ');
15158} 15190}
15159 15191
15160 15192
@@ -15168,7 +15200,10 @@ build_desired_tool_bar_string (struct frame *f)
15168 If HEIGHT is -1, we are counting needed tool-bar lines, so don't 15200 If HEIGHT is -1, we are counting needed tool-bar lines, so don't
15169 count a final empty row in case the tool-bar width exactly matches 15201 count a final empty row in case the tool-bar width exactly matches
15170 the window width. 15202 the window width.
15171*/ 15203
15204 HEIGHT may also be -1 if there is an explicit line wrapping item
15205 inside the tool bar; in that case, allow individual rows of the
15206 tool bar to differ in height. */
15172 15207
15173static void 15208static void
15174display_tool_bar_line (struct it *it, int height) 15209display_tool_bar_line (struct it *it, int height)
@@ -15232,8 +15267,18 @@ display_tool_bar_line (struct it *it, int height)
15232 ++i; 15267 ++i;
15233 } 15268 }
15234 15269
15235 /* Stop at line end. */ 15270 /* Stop at the end of the iterator, and move to the next line
15271 upon a '\n' appearing in the tool bar string. Tool bar
15272 strings may contain multiple new line characters when
15273 explicit wrap items are encountered. */
15274
15236 if (ITERATOR_AT_END_OF_LINE_P (it)) 15275 if (ITERATOR_AT_END_OF_LINE_P (it))
15276 {
15277 reseat_at_next_visible_line_start (it, false);
15278 break;
15279 }
15280
15281 if (ITERATOR_AT_END_P (it))
15237 break; 15282 break;
15238 15283
15239 set_iterator_to_next (it, true); 15284 set_iterator_to_next (it, true);
@@ -15260,7 +15305,8 @@ display_tool_bar_line (struct it *it, int height)
15260 last->left_box_line_p = true; 15305 last->left_box_line_p = true;
15261 15306
15262 /* Make line the desired height and center it vertically. */ 15307 /* Make line the desired height and center it vertically. */
15263 if ((height -= it->max_ascent + it->max_descent) > 0) 15308 if (height != -1
15309 && (height -= it->max_ascent + it->max_descent) > 0)
15264 { 15310 {
15265 /* Don't add more than one line height. */ 15311 /* Don't add more than one line height. */
15266 height %= FRAME_LINE_HEIGHT (it->f); 15312 height %= FRAME_LINE_HEIGHT (it->f);
@@ -15294,6 +15340,7 @@ display_tool_bar_line (struct it *it, int height)
15294/* Value is the number of pixels needed to make all tool-bar items of 15340/* Value is the number of pixels needed to make all tool-bar items of
15295 frame F visible. The actual number of glyph rows needed is 15341 frame F visible. The actual number of glyph rows needed is
15296 returned in *N_ROWS if non-NULL. */ 15342 returned in *N_ROWS if non-NULL. */
15343
15297static int 15344static int
15298tool_bar_height (struct frame *f, int *n_rows, bool pixelwise) 15345tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15299{ 15346{
@@ -15371,7 +15418,9 @@ redisplay_tool_bar (struct frame *f)
15371 struct window *w; 15418 struct window *w;
15372 struct it it; 15419 struct it it;
15373 struct glyph_row *row; 15420 struct glyph_row *row;
15421 bool change_height_p;
15374 15422
15423 change_height_p = false;
15375 f->tool_bar_redisplayed = true; 15424 f->tool_bar_redisplayed = true;
15376 15425
15377 /* If frame hasn't a tool-bar window or if it is zero-height, don't 15426 /* If frame hasn't a tool-bar window or if it is zero-height, don't
@@ -15455,18 +15504,39 @@ redisplay_tool_bar (struct frame *f)
15455 border = 0; 15504 border = 0;
15456 15505
15457 rows = f->n_tool_bar_rows; 15506 rows = f->n_tool_bar_rows;
15458 height = max (1, (it.last_visible_y - border) / rows);
15459 extra = it.last_visible_y - border - height * rows;
15460 15507
15461 while (it.current_y < it.last_visible_y) 15508 if (f->tool_bar_wraps_p)
15462 { 15509 {
15463 int h = 0; 15510 /* If the tool bar contains explicit line wrapping items,
15464 if (extra > 0 && rows-- > 0) 15511 don't force each row to have a fixed height. */
15512
15513 while (!ITERATOR_AT_END_P (&it))
15514 display_tool_bar_line (&it, -1);
15515
15516 /* Because changes to individual tool bar items may now
15517 change the height of the tool bar, adjust the height of
15518 the tool bar window if it is different from the tool bar
15519 height in any way. */
15520
15521 if (it.current_y != it.last_visible_y)
15522 change_height_p = true;
15523 }
15524 else
15525 {
15526 height = max (1, (it.last_visible_y - border) / rows);
15527 extra = it.last_visible_y - border - height * rows;
15528
15529 while (it.current_y < it.last_visible_y)
15465 { 15530 {
15466 h = (extra + rows - 1) / rows; 15531 int h = 0;
15467 extra -= h; 15532 if (extra > 0 && rows-- > 0)
15533 {
15534 h = (extra + rows - 1) / rows;
15535 extra -= h;
15536 }
15537
15538 display_tool_bar_line (&it, height + h);
15468 } 15539 }
15469 display_tool_bar_line (&it, height + h);
15470 } 15540 }
15471 } 15541 }
15472 else 15542 else
@@ -15482,8 +15552,6 @@ redisplay_tool_bar (struct frame *f)
15482 15552
15483 if (!NILP (Vauto_resize_tool_bars)) 15553 if (!NILP (Vauto_resize_tool_bars))
15484 { 15554 {
15485 bool change_height_p = false;
15486
15487 /* If we couldn't display everything, change the tool-bar's 15555 /* If we couldn't display everything, change the tool-bar's
15488 height if there is room for more. */ 15556 height if there is room for more. */
15489 if (IT_STRING_CHARPOS (it) < it.end_charpos) 15557 if (IT_STRING_CHARPOS (it) < it.end_charpos)