From: Pasi Kallinen Date: Sun, 17 Jan 2016 11:55:10 +0000 (+0200) Subject: X11: autoscroll extended command menu X-Git-Tag: NetHack-3.6.1_RC01~1005 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d06450817bb50486e01207b8ec48cc48382d90b6;p=nethack X11: autoscroll extended command menu When you type in the extended command menu to select a command, scroll the window so that the selected command is always in view. --- diff --git a/win/X11/winmisc.c b/win/X11/winmisc.c index 5fb874ac3..b453e9126 100644 --- a/win/X11/winmisc.c +++ b/win/X11/winmisc.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include /* for index() */ @@ -706,6 +707,60 @@ ec_dismiss() exit_x_event = TRUE; /* leave event loop */ } +void +ec_scroll_to_view() +{ + Arg args[3]; + Cardinal num_args; + Position y, h; /* ext cmd label y and height */ + Widget viewport, scrollbar, tmpw; + float s_shown, s_top; /* scrollbar pos */ + float s_min, s_max; + Position vh; /* viewport height */ + + if (extended_command_selected < 0) + return; + + /* get selected ext command label y position and height */ + num_args = 0; + XtSetArg(args[num_args], XtNy, &y); num_args++; + XtSetArg(args[num_args], XtNheight, &h); num_args++; + XtGetValues(extended_commands[extended_command_selected], args, num_args); + + /* get viewport and scrollbar widgets */ + tmpw = extended_commands[extended_command_selected]; + viewport = XtParent(tmpw); + do { + tmpw = XtParent(tmpw); + scrollbar = XtNameToWidget(tmpw, "*vertical"); + } while (!scrollbar && tmpw); + + if (scrollbar && viewport) { + /* get viewport height */ + num_args = 0; + XtSetArg(args[num_args], XtNheight, &vh); num_args++; + XtGetValues(viewport, args, num_args); + + /* get scrollbar "height" and "top" position; floats between 0-1 */ + num_args = 0; + XtSetArg(args[num_args], XtNshown, &s_shown); num_args++; + XtSetArg(args[num_args], XtNtopOfThumb, &s_top); num_args++; + XtGetValues(scrollbar, args, num_args); + + s_min = s_top * vh; + s_max = (s_top + s_shown) * vh; + + /* scroll if outside the view */ + if ((int)y <= (int)s_min) { + s_min = (float)(y / (float)vh); + XtCallCallbacks(scrollbar, XtNjumpProc, &s_min); + } else if ((int)(y + h) >= (int)s_max) { + s_min = (float)((y+h) / (float)vh) - s_shown; + XtCallCallbacks(scrollbar, XtNjumpProc, &s_min); + } + } +} + /* ARGSUSED */ void ec_key(w, event, params, num_params) @@ -792,6 +847,7 @@ Cardinal *num_params; extended_command_selected = i; swap_fg_bg(extended_commands[extended_command_selected]); } + ec_scroll_to_view(); return; } }