#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();
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;
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;
// Not a fix, but much better than nothing.
static int inited = 0;
if( inited ) return;
+ XGrabServer(display);
+ XSync(display, 0);
inited = 1;
int cur_font = current_font;
// locale encodings, needed glyphs to be preloaded
"`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);
}
void BC_WindowBase::init_im()
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;
return h * rowh;
}
+// truncate the text with ... & return a new string
+char *BC_WindowBase::get_truncated_text(int font, const char *text, int max_w)
+{
+ char *result = cstrdup(text);
+ int text_w = get_text_width(font, text);
+ int ci = -1, len = strlen(text);
+ if( text_w > max_w ) {
+// get center of string
+ int cx = text_w/2, best = INT_MAX;
+ for( int i=1; i<=len; ++i ) {
+ int cw = get_text_width(font, text, i);
+ if( abs(cw-cx) < abs(best-cx) ) {
+ best = cw; ci = i;
+ }
+ }
+ }
+ if( ci > 0 && ci < len-1 ) {
+// insert ... in the center
+ result[ci-1] = result[ci] = result[ci+1] = '.';
+
+ while( ci-2>=0 && ci+2<(int)strlen(result) &&
+ get_text_width(font, result) > max_w ) {
+// take away a character from the longer side
+ int left_w = get_text_width(font, result, ci-2);
+ int right_w = get_text_width(font, result + ci+3);
+ int i = left_w > right_w ? --ci-1 : ci+2;
+ while( (result[i]=result[i+1])!=0 ) ++i;
+ }
+ }
+
+ return result;
+}
+
BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
{
if(color_model < 0) color_model = top_level->get_color_model();
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 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 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;
flush();
}
+// must be RGBA8888
+void BC_WindowBase::set_net_icon(VFrame *data)
+{
+ int width = data->get_w(), height = data->get_h();
+ int size = 2 + width * height;
+ unsigned long *icon_data = new unsigned long[size];
+ unsigned long *lp = icon_data;
+ *lp++ = width; *lp++ = height;
+ uint8_t **rows = data->get_rows();
+ for( int y=0; y<height; ++y ) {
+ unsigned *up = (unsigned *)rows[y];
+ for( int x=0; x<width; ++x )
+ *lp++ = *(unsigned *)up++;
+ }
+ Atom NetWMIcon = XInternAtom(display, "_NET_WM_ICON", True);
+ XChangeProperty(top_level->display, top_level->win, NetWMIcon,
+ XA_CARDINAL, 32, PropModeReplace, (unsigned char *)icon_data, size);
+ delete [] icon_data;
+}
+
const char *BC_WindowBase::get_title()
{
return title;
icon_pixmap = new BC_Pixmap(top_level, data, PIXMAP_ALPHA, 1);
if(icon_window) delete icon_window;
- icon_window = new BC_Popup(this,
- (int)BC_INFINITY,
- (int)BC_INFINITY,
- icon_pixmap->get_w(),
- icon_pixmap->get_h(),
- -1,
- 1, // All windows are hidden initially
+ icon_window = new BC_Popup(this, 0, 0,
+ icon_pixmap->get_w(), icon_pixmap->get_h(),
+ -1, 1, // All windows are hidden initially
icon_pixmap);
- XWMHints wm_hints;
- wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
+ XWMHints wm_hints; memset(&wm_hints, 0, sizeof(wm_hints));
+ wm_hints.flags = IconPixmapHint; // | IconMaskHint | IconWindowHint;
wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
wm_hints.icon_mask = icon_pixmap->get_alpha();
wm_hints.icon_window = icon_window->win;
- wm_hints.window_group = XGroupLeader;
+ if( XGroupLeader ) {
+ wm_hints.flags |= WindowGroupHint;
+ wm_hints.window_group = XGroupLeader;
+ }
// for(int i = 0; i < 1000; i++)
// printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
// printf("\n");
XSetWMHints(top_level->display, top_level->win, &wm_hints);
+
+ set_net_icon(data);
XSync(top_level->display, 0);
return 0;
}
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;
}
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;
+}
+