#include <typeinfo>
#include <X11/extensions/Xinerama.h>
+#ifdef HAVE_XV
#include <X11/extensions/Xvlib.h>
+#endif
#include <X11/extensions/shape.h>
#include <X11/XF86keysym.h>
#include <X11/Sunkeysym.h>
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.
}
resize_history.remove_all_objects();
+ delete grab_lock;
#ifndef SINGLE_THREAD
common_events.remove_all_objects();
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;
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;
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; i<wkey_string_length; ++i )
+ wkey_string[i] = wkey[i];
//printf("keysym_lookup 1 %d %d %lx %x %x %x %x\n", wkey_string_length, keysym,
// wkey_string[0], wkey_string[1], wkey_string[2], wkey_string[3]);
}
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");
}
//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;
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;
//__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
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;
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;
"`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);
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)
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; i<length && text[i]; ++i ) {
if( text[i] != '\n' ) continue;
int BC_WindowBase::grab_port_id(int color_model)
{
+#ifdef HAVE_XV
if( !get_resources()->use_xvideo || // disabled
!get_resources()->use_shm ) // Only local server is fast enough.
return -1;
}
XvFreeAdaptorInfo(info);
-
return xvideo_port_id;
+#else
+ return -1;
+#endif
}
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()
{
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)
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;
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;
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;
}