diff --git a/src/Fl.cxx b/src/Fl.cxx
index daf5e44..082a885 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -54,9 +54,15 @@
 #include <stdlib.h>
 #include "flstring.h"
 
-#if defined(DEBUG) || defined(DEBUG_WATCH)
+#define DEBUG_SHORTCUT
+
+#if defined(DEBUG_SHORTCUT)
+#include <FL/names.h>
+#endif // DEBUG_SHORTCUT
+
+#if defined(DEBUG) || defined(DEBUG_WATCH) || defined(DEBUG_SHORTCUT)
 #  include <stdio.h>
-#endif // DEBUG || DEBUG_WATCH
+#endif // DEBUG || DEBUG_WATCH || DEBUG_SHORTCUT
 
 #ifdef WIN32
 #  include <ole2.h>
@@ -1133,6 +1139,41 @@ void fl_throw_focus(Fl_Widget *o) {
 
 ////////////////////////////////////////////////////////////////
 
+// Find the first active widget, i.e. one where active_r() would be
+// true, starting at the widget wi and walking up the widget hierarchy
+// to the top level window.
+//
+// In other words: find_active() returns an active group that contains
+// the inactive widget and all inactive parent groups.
+//
+// This is used to send FL_SHORTCUT events to the Fl::belowmouse() widget
+// in case the target widget itself is inactive. In this case the event
+// is sent to the first active parent.
+//
+// This prevents sending events to inactive widgets that might get the
+// input focus otherwise. The search is fast and light and avoids calling
+// inactive_r() multiple times.
+// See STR #3216.
+//
+// Returns: first active widget "above" the widget wi or NULL if no widget
+// is active. May return the top level window.
+
+static Fl_Widget *find_active(Fl_Widget *wi) {
+
+  const Fl_Widget *found = 0;
+
+  for (const Fl_Widget* o = wi; o; o = o->parent()) {
+    if (o->active()) {
+      if (!found) found = o;
+    } else {
+      found = 0;
+    }
+  }
+  return (Fl_Widget*)found;
+}
+
+////////////////////////////////////////////////////////////////
+
 // Call to->handle(), but first replace the mouse x/y with the correct
 // values to account for nested windows. 'window' is the outermost
 // window the event was posted to by the system:
@@ -1149,7 +1190,32 @@ static int send_event(int event, Fl_Widget* to, Fl_Window* window) {
     if (w->type()>=FL_WINDOW) {dx -= w->x(); dy -= w->y();}
   int save_x = Fl::e_x; Fl::e_x += dx;
   int save_y = Fl::e_y; Fl::e_y += dy;
+
+#ifdef DEBUG_SHORTCUT
+  if (event == FL_KEYBOARD || event == FL_SHORTCUT) {
+    printf("send_event(event=%2d %-11s e_text='%s', to=%p (wi%s) %10s %-5s %-10s  %-12.12s, window=%-9p",
+      event, fl_eventnames[event], Fl::event_text(),
+      to,to->as_window() ? "ndow" : "dget",
+      to->active_r() ? "active_r" : "inactive_r",
+      (to==Fl::focus()) ? "focus" : "",
+      (to==Fl::belowmouse()) ? "belowmouse" :
+	(to->contains(Fl::belowmouse()) ? "  <mouse>" : ""),
+      to ? to->label() : "",
+      window);
+    fflush(stdout);
+    dx += 1;	// for debugging only (to set breakpoint)
+  }
+#endif // DEBUG_SHORTCUT
+
   int ret = to->handle(Fl::e_number = event);
+
+#ifdef DEBUG_SHORTCUT
+  if (event == FL_KEYBOARD || event == FL_SHORTCUT) {
+    printf(") = %d\n",ret);
+    dx -= 1;	// for debugging only (to set breakpoint)
+  }
+#endif // DEBUG_SHORTCUT
+
   Fl::e_number = old_event;
   Fl::e_y = save_y;
   Fl::e_x = save_x;
@@ -1375,6 +1441,9 @@ int Fl::handle_(int e, Fl_Window* window)
 #ifdef DEBUG
     printf("Fl::handle(e=%d, window=%p);\n", e, window);
 #endif // DEBUG
+#ifdef DEBUG_SHORTCUT
+    printf("\n");
+#endif // DEBUG_SHORTCUT
 
     Fl_Tooltip::enter((Fl_Widget*)0);
 
@@ -1398,7 +1467,8 @@ int Fl::handle_(int e, Fl_Window* window)
     if (grab()) {wi = grab(); break;} // send it to grab window
 
     // Try it as shortcut, sending to mouse widget and all parents:
-    wi = belowmouse();
+    // wi = belowmouse();
+    wi = find_active(belowmouse()); // STR #3216
     if (!wi) {
       wi = modal();
       if (!wi) wi = window;
diff --git a/test/input.cxx b/test/input.cxx
index 33f8abc..766e5c9 100644
--- a/test/input.cxx
+++ b/test/input.cxx
@@ -87,6 +87,7 @@ int main(int argc, char **argv) {
   Fl::args(argc, argv);
   Fl::get_system_colors();
   Fl_Window *window = new Fl_Window(400,420);
+  Fl_Group *grp = new Fl_Group(0,0,400,420,"Group");
 
   int y = 10;
   input[0] = new Fl_Input(70,y,300,30,"Normal:"); y += 35;
@@ -106,7 +107,7 @@ int main(int argc, char **argv) {
   input[4]->tooltip("Input field for short text with newlines (Alt-M)");
   input[4]->wrap(1);
 
-  for (int i = 0; i < 4; i++) {
+  for (int i = 0; i < 5; i++) {
     input[i]->when(0); input[i]->callback(cb);
   }
   int y1 = y;
@@ -129,11 +130,11 @@ int main(int argc, char **argv) {
   b->callback(button_cb);
   b->tooltip("Print widgets that have changed() flag set");
 
-  b = new Fl_Light_Button(10,y,100,25," Tab Nav");
+  b = new Fl_Light_Button(10,y,100,25,"&Tab Nav");
   b->tooltip("Control tab navigation for the multiline input field");
   b->callback(tabnav_cb, (void*)input[4]);
   b->value(input[4]->tab_nav() ? 1 : 0);
-  b = new Fl_Light_Button(110,y,100,25," Arrow Nav"); y += 25;
+  b = new Fl_Light_Button(110,y,100,25,"A&rrow Nav"); y += 25;
   b->tooltip("Control horizontal arrow key focus navigation behavior.\n"
              "e.g. Fl::OPTION_ARROW_FOCUS");
   b->callback(arrownav_cb);
@@ -143,7 +144,7 @@ int main(int argc, char **argv) {
   b = new Fl_Button(220,y1,120,25,"color"); y1 += 25;
   b->color(input[0]->color()); b->callback(color_cb, (void*)0);
   b->tooltip("Color behind the text");
-  b = new Fl_Button(220,y1,120,25,"selection_color"); y1 += 25;
+  b = new Fl_Button(220,y1,120,25,"selection_&color"); y1 += 25;
   b->color(input[0]->selection_color()); b->callback(color_cb, (void*)1);
   b->labelcolor(fl_contrast(FL_BLACK,b->color()));
   b->tooltip("Color behind selected text");
@@ -151,8 +152,31 @@ int main(int argc, char **argv) {
   b->color(input[0]->textcolor()); b->callback(color_cb, (void*)2);
   b->labelcolor(fl_contrast(FL_BLACK,b->color()));
   b->tooltip("Color of the text");
-
+  grp->end();
   window->end();
+
+  window->label("Window");	// set label for test output
+  input[3]->deactivate();	// deactivate &Secret input widget
+
+#if (0)				// edit: (0) or (1) for different test scenarios
+  grp->deactivate();
+#endif
+
+  printf("\n");
+  printf("--------------------\n");
+  printf("--- test started ---\n");
+  printf("--------------------\n\n");
+
+  printf(" Group    = %p  %-12.12s  %s\n",
+    grp, grp->label(),
+    grp->active_r() ? "active" : "INACTIVE");
+
+  for (int i = 0; i < 5; i++) {
+    printf(" input[%d] = %p  %-12.12s  %s\n",
+      i, input[i], input[i]->label(),
+      input[i]->active_r() ? "active" : "INACTIVE");
+  }
+
   window->show(argc,argv);
   return Fl::run();
 }
