Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcwindowbase.C
index 9f3e2123c843c7e0f336ae1d4c53105b03b04a71..adaaa6e266f779464b5d12099179a8aad94c9f6c 100644 (file)
@@ -254,6 +254,7 @@ int BC_WindowBase::initialize()
        display_lock_owner = 0;
        test_keypress = 0;
        keys_return[0] = 0;
+       context_help_keyword[0] = 0;
        is_deleting = 0;
        window_lock = 0;
        resend_event_window = 0;
@@ -1172,6 +1173,24 @@ if( debug && event->type != ClientMessage ) {
 //__LINE__,
 //keysym);
 
+// force setting modifiers state if a modifier key pressed
+               switch( keysym ) {
+               case XK_Alt_L:
+               case XK_Alt_R:
+                       alt_mask = 1;
+                       break;
+               case XK_Shift_L:
+               case XK_Shift_R:
+                       shift_mask = 1;
+                       break;
+               case XK_Control_L:
+               case XK_Control_R:
+                       ctrl_mask = 1;
+                       break;
+               default:
+                       break;
+               }
+
 // block out control keys
                if(keysym > 0xffe0 && keysym < 0xffff) break;
 // block out Alt_GR key
@@ -1308,8 +1327,26 @@ if( debug && event->type != ClientMessage ) {
 
        case KeyRelease:
                XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
+               get_key_masks(event->xkey.state);
+// force clearing modifiers state if a modifier key released
+               switch( keysym ) {
+               case XK_Alt_L:
+               case XK_Alt_R:
+                       alt_mask = 0;
+                       break;
+               case XK_Shift_L:
+               case XK_Shift_R:
+                       shift_mask = 0;
+                       break;
+               case XK_Control_L:
+               case XK_Control_R:
+                       ctrl_mask = 0;
+                       break;
+               default:
+                       break;
+               }
                dispatch_keyrelease_event();
-// printf("BC_WindowBase::dispatch_event KeyRelease keysym=0x%x keystate=0x%lld\n",
+// printf("BC_WindowBase::dispatch_event KeyRelease keysym=%#lx keystate=%04x\n",
 // keysym, event->xkey.state);
                break;
 
@@ -1730,6 +1767,90 @@ int BC_WindowBase::close_event()
        return 1;
 }
 
+// *** CONTEXT_HELP ***
+// This basic implementation serves solely for context help.
+// We are handling Alt/H only. Any subclass requiring more sophisticated
+// processing of keystrokes has to provide its own overloaded handler.
+int BC_WindowBase::keypress_event()
+{
+//     printf("BC_WindowBase::keypress_event: %d\n", get_keypress());
+       return context_help_check_and_show();
+}
+
+// The stuff up to END_CONTEXT_HELP serves solely for context help
+void BC_WindowBase::context_help_set_keyword(const char *keyword)
+{
+       if (keyword) strcpy(context_help_keyword, keyword);
+}
+
+const char *BC_WindowBase::context_help_get_keyword()
+{
+// If we have context_help_keyword defined here, return it.
+// Otherwise recursively track widget hierarchy up to top_level
+// and return the nearest found nonempty keyword.
+// If nothing found, the special keyword "TOC" is returned.
+       if (context_help_keyword[0] || this == top_level ||
+           this == parent_window || ! parent_window) {
+               if (! context_help_keyword[0] && this == top_level)
+                       context_help_set_keyword("TOC");
+               return context_help_keyword;
+       }
+       return parent_window->context_help_get_keyword();
+}
+
+void BC_WindowBase::context_help_show(const char *keyword)
+{
+       char cmd[BCTEXTLEN];
+
+       if (! keyword) return;
+
+       sprintf(cmd, "\"%s/doc/ContextManual.pl\" \"%s\"", getenv("CIN_DAT"),
+               keyword);
+//     printf("BC_WindowBase::context_help_show(%s):\n%s\n", keyword, cmd);
+
+// ContextManual.pl starts browser in background, so system() should not block
+       system(cmd);
+}
+
+void BC_WindowBase::context_help_show()
+{
+       context_help_show(context_help_get_keyword());
+}
+
+int BC_WindowBase::context_help_check_and_show(const char *keyword)
+{
+       if (! keyword)    return 0;
+       if (! keyword[0]) return 0;
+
+// We are handling Alt/H only
+       if (get_keypress() != 'h' || ! alt_down()) return 0;
+
+// Restrict cursor location to that widget keystroke occured in
+       if (! is_tooltip_event_win() || ! cursor_inside()) return 0;
+
+       context_help_show(keyword);
+       return 1;
+}
+
+int BC_WindowBase::context_help_check_and_show()
+{
+       const char *keyword;
+
+// We are handling Alt/H only
+       if (get_keypress() != 'h' || ! alt_down()) return 0;
+
+// Restrict cursor location, so any subwindow can define its own help keyword
+       if (! is_tooltip_event_win() || ! cursor_inside()) return 0;
+
+// If a widget has not defined its own help keyword, the parent can provide it
+       keyword = context_help_get_keyword();
+       if (! keyword[0]) return 0;
+
+       context_help_show(keyword);
+       return 1;
+}
+// *** END_CONTEXT_HELP ***
+
 int BC_WindowBase::dispatch_drag_start()
 {
        int result = 0;
@@ -2445,7 +2566,11 @@ void BC_WindowBase::init_im()
        if(!(input_method = XOpenIM(display, NULL, NULL, NULL)))
        {
                printf("BC_WindowBase::init_im: Could not open input method.\n");
+               XSetLocaleModifiers("@im=local");
+               if(!(input_method = XOpenIM(display, NULL, NULL, NULL))) {
+               printf("BC_WindowBase::init_im: Could not open input method local.\n");
                exit(1);
+               }
        }
        if(XGetIMValues(input_method, XNQueryInputStyle, &xim_styles, NULL) ||
                        xim_styles == NULL)
@@ -4036,6 +4161,12 @@ int BC_WindowBase::is_event_win()
        return this->win == top_level->event_win;
 }
 
+int BC_WindowBase::is_tooltip_event_win()
+{
+       return this->win == top_level->event_win ||
+               tooltip_popup && tooltip_popup->win == top_level->event_win;
+}
+
 void BC_WindowBase::set_dragging(int value)
 {
        is_dragging = value;