X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fguicast%2Fbcwindowbase.C;h=c57cd6203c8f6569a1b24b6feb7c2cfbb7d9f6a9;hp=a362095e3405c0084f0e170460465d1248076152;hb=0c48864cab7b37268025485c6a227f36b3420030;hpb=5d8a7826b0f80f00622e46baf75453995a76e343 diff --git a/cinelerra-5.1/guicast/bcwindowbase.C b/cinelerra-5.1/guicast/bcwindowbase.C index a362095e..c57cd620 100644 --- a/cinelerra-5.1/guicast/bcwindowbase.C +++ b/cinelerra-5.1/guicast/bcwindowbase.C @@ -57,7 +57,9 @@ #include #include +#ifdef HAVE_XV #include +#endif #include #include #include @@ -205,9 +207,10 @@ BC_WindowBase::~BC_WindowBase() XFree(xinerama_info); xinerama_screens = 0; xinerama_info = 0; +#ifdef HAVE_XV if( xvideo_port_id >= 0 ) XvUngrabPort(display, xvideo_port_id, CurrentTime); - +#endif unlock_window(); // Must be last reference to display. // _XftDisplayInfo needs a lock. @@ -221,6 +224,7 @@ BC_WindowBase::~BC_WindowBase() } resize_history.remove_all_objects(); + delete grab_lock; #ifndef SINGLE_THREAD common_events.remove_all_objects(); @@ -250,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; @@ -343,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; @@ -869,8 +875,11 @@ int BC_WindowBase::keysym_lookup(XEvent *event) wkey_string_length = 0; if( input_context ) { + wchar_t wkey[4]; wkey_string_length = XwcLookupString(input_context, - (XKeyEvent*)event, wkey_string, 4, &keysym, 0); + (XKeyEvent*)event, wkey, 4, &keysym, 0); + for( int i=0; itype != 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"); } @@ -1016,8 +1030,8 @@ if( debug && event->type != ClientMessage ) { //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number); event_win = event->xany.window; - if (button_number < 6) { - if(button_number < 4) + if( button_number < 6 ) { + if( button_number < 4 ) button_down = 1; button_pressed = event->xbutton.button; button_time1 = button_time2; @@ -1030,23 +1044,20 @@ if( debug && event->type != ClientMessage ) { drag_x2 = cursor_x + get_resources()->drag_radius; drag_y1 = cursor_y - get_resources()->drag_radius; drag_y2 = cursor_y + get_resources()->drag_radius; - - if((long)(button_time3 - button_time1) < resources->double_click * 2) - { - triple_click = 1; - button_time3 = button_time2 = button_time1 = 0; - } - if((long)(button_time3 - button_time2) < resources->double_click) - { - double_click = 1; -// button_time3 = button_time2 = button_time1 = 0; - } - else - { - triple_click = 0; - double_click = 0; + if( button_number < 4 ) { + if((long)(button_time3 - button_time1) < resources->double_click * 2) { + triple_click = 1; + button_time3 = button_time2 = button_time1 = 0; + } + if((long)(button_time3 - button_time2) < resources->double_click) { + double_click = 1; +// button_time3 = button_time2 = button_time1 = 0; + } + else { + triple_click = 0; + double_click = 0; + } } - dispatch_button_press(); } break; @@ -1261,35 +1272,8 @@ if( debug && event->type != ClientMessage ) { case XK_F10: key_pressed = KEY_F10; break; case XK_F11: key_pressed = KEY_F11; break; case XK_F12: key_pressed = KEY_F12; break; - +// activates remote case XK_Menu: key_pressed = KPMENU; break; /* menu */ -// remote control -// above case XK_KP_Enter: key_pressed = KPENTER; break; /* check */ - case XF86XK_MenuKB: key_pressed = KPMENU; break; /* menu */ -// intercepted case XF86XK_PowerDown: key_pressed = KPPOWER; break; /* Power */ - case XF86XK_Launch1: key_pressed = KPTV; break; /* TV */ - case XF86XK_Launch2: key_pressed = KPDVD; break; /* DVD */ -// intercepted case XF86XK_WWW: key_pressed = KPWWEB; break; /* WEB */ - case XF86XK_Launch3: key_pressed = KPBOOK; break; /* book */ - case XF86XK_Launch4: key_pressed = KPHAND; break; /* hand */ - case XF86XK_Reply: key_pressed = KPTMR; break; /* timer */ - case SunXK_Front: key_pressed = KPMAXW; break; /* max */ -// above case XK_Left: key_pressed = LEFT; break; /* left */ -// above case XK_Right: key_pressed = RIGHT; break; /* right */ -// above case XK_Down: key_pressed = DOWN; break; /* down */ -// above case XK_Up: key_pressed = UP; break; /* up */ -// above case XK_SPACE: key_pressed = KPSPACE; break; /* ok */ -// intercepted case XF86XK_AudioRaiseVolume: key_pressed = KPVOLU; break; /* VOL + */ -// intercepted case XF86XK_AudioMute: key_pressed = KPMUTE; break; /* MUTE */ -// intercepted case XF86XK_AudioLowerVolume: key_pressed = KPVOLD; break; /* VOL - */ - case XF86XK_ScrollUp: key_pressed = KPCHUP; break; /* CH + */ - case XF86XK_ScrollDown: key_pressed = KPCHDN; break; /* CH - */ - case XF86XK_AudioRecord: key_pressed = KPRECD; break; /* ( o) red */ - case XF86XK_Forward: key_pressed = KPPLAY; break; /* ( >) */ - case XK_Redo: key_pressed = KPFWRD; break; /* (>>) */ - case XF86XK_Back: key_pressed = KPBACK; break; /* (<<) */ - case XK_Cancel: key_pressed = KPSTOP; break; /* ([]) */ - case XK_Pause: key_pressed = KPAUSE; break; /* ('') */ default: key_pressed = keysym & 0xff; @@ -1747,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; @@ -2448,7 +2516,7 @@ void BC_WindowBase::init_glyphs() "`abcdefghijklmnopqrstuvwxyz{|}~"); for( int font=SMALLFONT; font<=LARGEFONT; ++font ) { set_font(font); - draw_text(5,5, text, 0); + draw_text(5,5, text); } set_font(cur_font); XUngrabServer(display); @@ -2462,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) @@ -2971,10 +3043,10 @@ int BC_WindowBase::get_text_width(int font, const char *text, int length) return w; } -int BC_WindowBase::get_text_width(int font, const wchar_t *text, int length) +int BC_WindowBase::get_text_width(int font, const wchr_t *text, int length) { int i, j, w = 0; - if( length < 0 ) length = wcslen(text); + if( length < 0 ) length = wstrlen(text); for( i=j=0; iuse_xvideo || // disabled !get_resources()->use_shm ) // Only local server is fast enough. return -1; @@ -3187,8 +3260,10 @@ int BC_WindowBase::grab_port_id(int color_model) } XvFreeAdaptorInfo(info); - return xvideo_port_id; +#else + return -1; +#endif } @@ -3436,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() { @@ -3928,9 +4022,9 @@ void BC_WindowBase::get_pop_cursor(int &px, int &py, int lock_window) get_abs_cursor(px, py, lock_window); if( px < xmargin ) px = xmargin; if( py < ymargin ) py = ymargin; - int wd = get_screen_w(lock_window,-1) - xmargin; + int wd = get_screen_x(lock_window,-1) + get_screen_w(lock_window,-1) - xmargin; if( px > wd ) px = wd; - int ht = get_screen_h(lock_window,-1) - ymargin; + int ht = get_screen_y(lock_window,-1) + get_screen_h(lock_window,-1) - ymargin; if( py > ht ) py = ht; } int BC_WindowBase::get_pop_cursor_x(int lock_window) @@ -4031,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; @@ -4066,7 +4166,7 @@ int BC_WindowBase::ctrl_down() return top_level->ctrl_mask; } -wchar_t* BC_WindowBase::get_wkeystring(int *length) +wchr_t* BC_WindowBase::get_wkeystring(int *length) { if(length) *length = top_level->wkey_string_length; @@ -4241,6 +4341,8 @@ void BC_WindowBase::set_force_tooltip(int v) int BC_WindowBase::raise_window(int do_flush) { + if( hidden ) return 1; + if( wait_viewable(500) ) return 1; XRaiseWindow(top_level->display, win); if(do_flush) XFlush(top_level->display); return 0; @@ -4376,6 +4478,10 @@ void BC_WindowBase::init_resources(float scale) int wx, wy, ww, wh; int cins = info.xinerama_big_screen(); if( !info.xinerama_geometry(cins, wx, wy, ww, wh) ) { + int sh = ww * 9 / 16; + int sw = wh * 16 / 9; + if( sw < ww ) ww = sw; + if( sh < wh ) wh = sh; if( (x_scale = ww/1920.) < 1 ) x_scale = 1; if( (y_scale = wh/1080.) < 1 ) y_scale = 1; } @@ -4657,3 +4763,15 @@ void BC_WindowBase::focus() XSetInputFocus(top_level->display, top_level->win, RevertToParent, CurrentTime); } +int BC_WindowBase::wait_viewable(int ms) +{ + Timer timer; + XWindowAttributes xwa; + do { + XGetWindowAttributes(top_level->display, top_level->win, &xwa); + if( xwa.map_state == IsViewable ) return 0; + usleep(10000); + } while( timer.get_difference() < ms ); + return 1; +} +