3

I have a Motif app running on a Raspberry Pi. For debugging purposes I am using an X Windows server on my PC and SSH tunneling X through Putty. It may also be worth noting that when I initially run the app, the input goes to the SSH shell/Putty window. Clicking in the app window or on one of its buttons stops the input going to the Putty window.

The widget hierarchy is:

Top level shell->Scrolled window->Form->RowColumn

The row column widget then contains an arbitrary number of button widgets.

I have registered an event handler with KeyPressMask on the top level shell, and when that didn't work, on the RowColumn and all buttons. It is never getting called. The first button created gets the focus (as shown visually by its border) but that only changes when I click on another button with the mouse (click events are successfully detected).

I have tried fiddling with XmNkeyboardFocusPolicy on the top level shell. I have tried calling XtSetKeyboardFocus() for the row column widget and the first button. I have tried specifying XmNtraversalOn as True when creating the buttons. Nothing works. I am totally frustrated.

I have made the button click callback report the value of XtIsSensitive() for the widget it is called for (which should be the button) and it reports a value of 1 (== True I presume).

I am happy to use the built-in Motif traversal routines, as long as I can also simulate/detect button activation when the return key is pressed. I am also happy to write my own traversal routines by explicitly detecting pushed keys. I really don't care. I just want to be able to navigate easily by pressing buttons on a keyboard!

Thanks in advance to anyone who can help solve my problem.

After more experimentation I have found that if I run my app directly by putting it in my .xinitrc then traversal works fine, and pressing space makes the button flash as if pressed, but doesn't actually cause the button to do anything.

If however I run the standard window manager by removing my xinitrc file and typing "startx" at the console prompt, and then open a terminal and run my app from the command line, then I get the same behaviour as when running it across the network to a window manager on my PC.

It occurs to me that this might be TTY based. When running via .xinitrc the app has no TTY when started (I believe), but when started directly from a command prompt then of course it does have a TTY. Could the TTY somehow be consuming all the keyboard input or something?

AlastairG
  • 4,119
  • 5
  • 26
  • 41
  • Return/space, I don't really care. I think I need to close this question. When using the Raspberry Pi directly, it all works fine. The problem only seems to happen when using the XWin server provided with Cygwin. – AlastairG Feb 17 '14 at 11:17
  • Actually that's only when running directly in xinitrc. I've updated the question with extra information now. – AlastairG Feb 22 '14 at 12:24
  • I never did solve this at all. I worked around it, first by manually simulating traversal when receiving a key press message from an Android app I wrote, and then extending that to work with remote control key presses detected via CEC. – AlastairG Jan 05 '17 at 16:31

1 Answers1

2

By default, you navigate the buttons in the Row Column using the arrow keys and activate the button with the space key.

This is because the widgets traversed with TAB must be in the TAB group. The Row Column widget is in the TAB group, but the push buttons are not. The TAB key will select the Row Column widget and select the first push button. The arrow keys can then be used to move to other buttons.

The default key for activating the button is the space key, to use another key you have to override the default event translation table.

Here's an example program that uses tab to traverse and return to activate the buttons

#include <Xm/Xm.h>
#include <Xm/MainW.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>

int main(int argc, char* argv[]) {
  XtSetLanguageProc(NULL, NULL, NULL);
  XtAppContext app;

  Widget toplevel = XtVaOpenApplication(&app, "traverse", NULL, 0, &argc, argv, NULL,
                                        sessionShellWidgetClass, NULL);

  Widget main_w = XmCreateMainWindow (toplevel, "main_w", NULL, 0);
  Widget mainrc = XtVaCreateWidget("mainrc", xmRowColumnWidgetClass, main_w,
                   XmNpacking, XmPACK_COLUMN,
                   XmNnumColumns, 3,
                   XmNentryBorder, 1,
                   NULL);
  for (int i=0; i<9; i++) {
    Widget b = XtVaCreateWidget("button", xmPushButtonWidgetClass, mainrc,
                XmNnavigationType, XmTAB_GROUP, // Make button a Tab Group
                NULL);
    // Specify Return key to activate button
    XtOverrideTranslations (b, XtParseTranslationTable ("<Key>Return: ArmAndActivate()"));
    XtManageChild(b);
  } 

  XtManageChild(mainrc);
  XtManageChild(main_w);
  XtRealizeWidget(toplevel);
  XtAppMainLoop(app);

  return 0;
}
parkydr
  • 7,596
  • 3
  • 32
  • 42
  • That translation override looks useful, so thanks for that. However it suffers exactly the same problem as my program. – AlastairG Feb 22 '14 at 12:33