rest of Termux related mods from Andrew
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcwindowbase.C
index a2cccd2cf4da8abac6f37276c0af1ce4516aeabf..c57cd6203c8f6569a1b24b6feb7c2cfbb7d9f6a9 100644 (file)
@@ -224,6 +224,7 @@ BC_WindowBase::~BC_WindowBase()
        }
 
        resize_history.remove_all_objects();
+       delete grab_lock;
 
 #ifndef SINGLE_THREAD
        common_events.remove_all_objects();
@@ -253,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;
@@ -346,6 +348,7 @@ int BC_WindowBase::initialize()
        event_condition = new Condition(0, "BC_WindowBase::event_condition");
        init_lock = new Condition(0, "BC_WindowBase::init_lock");
 #endif
+       grab_lock = new Mutex("BC_WindowBase::grab_lock");
 
        cursor_timer = new Timer;
        event_thread = 0;
@@ -959,10 +962,15 @@ if( debug && event->type != ClientMessage ) {
 }
 
        if( active_grab ) {
+               grab_lock->lock("BC_WindowBase::dispatch_event 3");
                unlock_window();
-               active_grab->lock_window("BC_WindowBase::dispatch_event 3");
-               result = active_grab->grab_event(event);
-               active_grab->unlock_window();
+               result = 0;
+               if( active_grab ) {
+                       active_grab->lock_window("BC_WindowBase::dispatch_event 3");
+                       result = active_grab->grab_event(event);
+                       active_grab->unlock_window();
+               }
+               grab_lock->unlock();
                if( result ) return result;
                lock_window("BC_WindowBase::dispatch_event 4");
        }
@@ -1723,6 +1731,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;
@@ -2438,7 +2530,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)
@@ -3415,17 +3511,36 @@ void BC_WindowBase::close(int return_value)
 
 int BC_WindowBase::grab(BC_WindowBase *window)
 {
-       if( window->active_grab && this != window->active_grab ) return 0;
-       window->active_grab = this;
-       this->grab_active = window;
-       return 1;
+       int ret = 0;
+       BC_WindowBase *grab_window = window->active_grab;
+       if( grab_window ) {
+               int locked = get_window_lock();
+               if( locked ) unlock_window();
+               grab_window->lock_window("BC_WindowBase::grab(BC_WindowBase");
+               grab_window->handle_ungrab();
+               grab_window->unlock_window();
+               if( locked ) lock_window("BC_WindowBase::grab(BC_WindowBase");
+       }
+       window->grab_lock->lock("BC_WindowBase::grab");
+       if( !window->active_grab ) {
+               window->active_grab = this;
+               this->grab_active = window;
+               ret = 1;
+       }
+       window->grab_lock->unlock();
+       return ret;
 }
 int BC_WindowBase::ungrab(BC_WindowBase *window)
 {
-       if( window->active_grab && this != window->active_grab ) return 0;
-       window->active_grab = 0;
-       this->grab_active = 0;
-       return 1;
+       int ret = 0;
+       window->grab_lock->lock("BC_WindowBase::ungrab");
+       if( this == window->active_grab ) {
+               window->active_grab = 0;
+               this->grab_active = 0;
+               ret = 1;
+       }
+       window->grab_lock->unlock();
+       return ret;
 }
 int BC_WindowBase::grab_event_count()
 {
@@ -4010,6 +4125,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;