#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>
}
-
-
-
-
-
int BC_WindowBase::shm_completion_event = -1;
-
-
-
-BC_Resources BC_WindowBase::resources;
-
+BC_Resources *BC_WindowBase::resources = 0;
Window XGroupLeader = 0;
Mutex BC_KeyboardHandlerLock::keyboard_listener_mutex("keyboard_listener",0);
//printf("delete glx=%08x, win=%08x %s\n", (unsigned)glx_win, (unsigned)win, title);
#ifdef HAVE_GL
if( get_resources()->get_synchronous() && glx_win != 0 ) {
+ if( window_type == MAIN_WINDOW )
+ unlock_window();
get_resources()->get_synchronous()->delete_window(this);
+ if( window_type == MAIN_WINDOW )
+ lock_window("BC_WindowBase::delete_window");
}
#endif
XDestroyWindow(top_level->display, win);
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;
vis = get_glx_visual(display);
if( !vis )
#endif
+ {
+ int mask = VisualDepthMask | VisualClassMask;
+ static XVisualInfo vinfo;
+ memset(&vinfo, 0, sizeof(vinfo));
+ vinfo.depth = 24;
+ vinfo.c_class = TrueColor;
+ int nitems = 0;
+ XVisualInfo *vis_info = XGetVisualInfo(display, mask, &vinfo, &nitems);
+ vis = vis_info && nitems>0 ? vis_info[0].visual : 0;
+ if( vis_info ) XFree(vis_info);
+ }
+ if( !vis )
vis = DefaultVisual(display, screen);
-
default_depth = DefaultDepth(display, screen);
client_byte_order = (*(const u_int32_t*)"a ") & 0x00000001;
// This must be done before fonts to know if antialiasing is available.
init_colors();
// get the resources
- if(resources.use_shm < 0) resources.initialize_display(this);
+ if(resources->use_shm < 0) resources->initialize_display(this);
x_correction = BC_DisplayInfo::get_left_border();
y_correction = BC_DisplayInfo::get_top_border();
if(this->y < 0) this->y = 0;
if(this->bg_color == -1)
- this->bg_color = resources.get_bg_color();
+ this->bg_color = resources->get_bg_color();
// printf("bcwindowbase 1 %s\n", title);
// if(window_type == MAIN_WINDOW) sleep(1);
mask = CWEventMask | CWBackPixel | CWColormap |
CWOverrideRedirect | CWSaveUnder | CWCursor;
- attr.event_mask = DEFAULT_EVENT_MASKS |
- KeyPressMask |
- KeyReleaseMask;
+ attr.event_mask = DEFAULT_EVENT_MASKS | ExposureMask |
+ KeyPressMask | KeyReleaseMask;
if(this->bg_color == -1)
- this->bg_color = resources.get_bg_color();
+ this->bg_color = resources->get_bg_color();
attr.background_pixel = top_level->get_color(bg_color);
attr.colormap = top_level->cmap;
if(top_level->is_hourglass)
}
if(!hidden) show_window();
-
+ init_glyphs();
}
draw_background(0, 0, this->w, this->h);
if(display_name && display_name[0] == 0) display_name = NULL;
if((display = XOpenDisplay(display_name)) == NULL) {
- printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
+ printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
display_name);
- if(getenv("DISPLAY") == NULL) {
+ if(getenv("DISPLAY") == NULL) {
printf(_("'DISPLAY' environment variable not set.\n"));
- exit(1);
+ exit(1);
}
- else {
// Try again with default display.
- if((display = XOpenDisplay(0)) == NULL) {
- printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
- exit(1);
- }
+ if((display = XOpenDisplay(0)) == NULL) {
+ printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
+ exit(1);
}
}
init_lock->unlock();
// Handle common events
- while(!done)
- {
- dispatch_event(0);
+ while( !done ) {
+ dispatch_event();
}
unset_all_repeaters();
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]);
Status stat;
- int ret = Xutf8LookupString(input_context, (XKeyEvent*)event,
+ int ret = Xutf8LookupString(input_context, (XKeyEvent*)event,
keys_return, KEYPRESSLEN, &keysym, &stat);
//printf("keysym_lookup 2 %d %d %lx %x %x\n", ret, stat, keysym, keys_return[0], keys_return[1]);
if( stat == XLookupBoth ) return ret;
int locking_event = -1;
int locking_message = -1;
-int BC_WindowBase::dispatch_event(XEvent *event)
+int BC_WindowBase::dispatch_event()
{
Window tempwin;
int result;
XClientMessageEvent *ptr;
int cancel_resize, cancel_translation;
- const int debug = 0;
+ volatile static int debug = 0;
+ XEvent *event;
key_pressed = 0;
-//static const char *event_names[] = {
-// "Reply", "Error", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify",
-// "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose",
-// "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify",
-// "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
-// "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear",
-// "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify",
-// "GenericEvent", "LASTEvent",
-//};
-//
-//if(debug)
-//if(event->type != ClientMessage) {
-// printf("BC_WindowBase::dispatch_event %d %s %p %d (%s)\n",
-//__LINE__, title, event, event->type,
-// event->type>=0 && event->type<sizeof(event_names)/sizeof(event_names[0]) ?
-// event_names[event->type] : "Unknown");
-//}
+if( debug && event->type != ClientMessage ) {
+ static const char *event_names[] = {
+ "Reply", "Error", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify",
+ "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose",
+ "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify",
+ "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
+ "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear",
+ "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify",
+ "GenericEvent", "LASTEvent",
+ };
+ const int nevents = sizeof(event_names)/sizeof(event_names[0]);
+
+ printf("BC_WindowBase::dispatch_event %d %s %p %d (%s)\n", __LINE__,
+ title, event, event->type, event->type>=0 && event->type<nevents ?
+ event_names[event->type] : "Unknown");
+}
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");
}
switch(event->type) {
case ClientMessage:
// Clear the resize buffer
- if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
+ if( resize_events )
+ dispatch_resize_event(last_resize_w, last_resize_h);
// Clear the motion buffer since this can clear the window
- if(motion_events)
- {
+ if( motion_events )
dispatch_motion_event();
- }
ptr = (XClientMessageEvent*)event;
-
-
- if(ptr->message_type == ProtoXAtom &&
- (Atom)ptr->data.l[0] == DelWinXAtom)
- {
+ if( ptr->message_type == ProtoXAtom &&
+ (Atom)ptr->data.l[0] == DelWinXAtom ) {
close_event();
}
- else
- if(ptr->message_type == RepeaterXAtom)
- {
+ else if( ptr->message_type == RepeaterXAtom ) {
dispatch_repeat_event(ptr->data.l[0]);
-// Make sure the repeater still exists.
-// for(int i = 0; i < repeaters.total; i++)
-// {
-// if(repeaters.values[i]->repeat_id == ptr->data.l[0])
-// {
-// dispatch_repeat_event_master(ptr->data.l[0]);
-// break;
-// }
-// }
}
- else
- if(ptr->message_type == SetDoneXAtom)
- {
+ else if( ptr->message_type == SetDoneXAtom ) {
done = 1;
- } else
- { // We currently use X marshalling for xatom events, we can switch to something else later
- receive_custom_xatoms((xatom_event *)ptr);
+ }
+ else {
+ receive_custom_xatoms((xatom_event *)ptr);
}
break;
//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 Expose:
event_win = event->xany.window;
- dispatch_expose_event();
+ result = 0;
+ for( int i=0; !result && i<popups.size(); ++i ) { // popups take focus
+ if( popups[i]->win == event_win )
+ result = popups[i]->dispatch_expose_event();
+ }
+ if( !result )
+ result = dispatch_expose_event();
break;
case MotionNotify:
}
else {
#endif
-
- switch(keysym) {
+// shuttle speed codes
+ if( keysym >= SKEY_MIN && keysym <= SKEY_MAX ) {
+ key_pressed = keysym;
+ }
+ else switch( keysym ) {
// block out extra keys
case XK_Alt_L:
case XK_Alt_R:
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;
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;
char *data = 0;
XImage *ximage;
ximage = XCreateImage(top_level->display,
- top_level->vis,
- top_level->default_depth,
- ZPixmap,
- 0,
- data,
- 16,
- 16,
- 8,
- 0);
+ top_level->vis, top_level->default_depth,
+ ZPixmap, 0, data, 16, 16, 8, 0);
bits_per_pixel = ximage->bits_per_pixel;
XDestroyImage(ximage);
switch(color_model)
{
case BC_RGB8:
- if(private_color)
- {
- cmap = XCreateColormap(display, rootwin, vis, AllocNone);
+ if(private_color) {
+ cmap = XCreateColormap(display, rootwin, vis, AllocNone);
create_private_colors();
}
- else
- {
+ else {
cmap = DefaultColormap(display, screen);
create_shared_colors();
}
XColor fc, bc;
fc.flags = bc.flags = DoRed | DoGreen | DoBlue;
fc.red = 0xffff; fc.green = fc.blue = 0; // fg
- bc.red = bc.green = bc.blue = 0x0000; // bg
+ bc.red = 0xffff; bc.green = 0xffff; bc.blue = 0x0000; // bg
Cursor cursor = XCreatePixmapCursor(display, img_xpm,msk_xpm, &fc,&bc, iw2,ih2);
XFreePixmap(display, img_xpm);
XFreePixmap(display, msk_xpm);
int BC_WindowBase::init_fonts()
{
- if( !(smallfont = XLoadQueryFont(display, _(resources.small_font))) )
- if( !(smallfont = XLoadQueryFont(display, _(resources.small_font2))) )
+ if( !(smallfont = XLoadQueryFont(display, _(resources->small_font))) )
+ if( !(smallfont = XLoadQueryFont(display, _(resources->small_font2))) )
smallfont = XLoadQueryFont(display, "fixed");
- if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font))) )
- if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) )
+ if( !(mediumfont = XLoadQueryFont(display, _(resources->medium_font))) )
+ if( !(mediumfont = XLoadQueryFont(display, _(resources->medium_font2))) )
mediumfont = XLoadQueryFont(display, "fixed");
- if( !(largefont = XLoadQueryFont(display, _(resources.large_font))) )
- if( !(largefont = XLoadQueryFont(display, _(resources.large_font2))) )
+ if( !(largefont = XLoadQueryFont(display, _(resources->large_font))) )
+ if( !(largefont = XLoadQueryFont(display, _(resources->large_font2))) )
largefont = XLoadQueryFont(display, "fixed");
- if( !(bigfont = XLoadQueryFont(display, _(resources.big_font))) )
- if( !(bigfont = XLoadQueryFont(display, _(resources.big_font2))) )
+ if( !(bigfont = XLoadQueryFont(display, _(resources->big_font))) )
+ if( !(bigfont = XLoadQueryFont(display, _(resources->big_font2))) )
bigfont = XLoadQueryFont(display, "fixed");
- if((clockfont = XLoadQueryFont(display, _(resources.clock_font))) == NULL)
- if((clockfont = XLoadQueryFont(display, _(resources.clock_font2))) == NULL)
+ if((clockfont = XLoadQueryFont(display, _(resources->clock_font))) == NULL)
+ if((clockfont = XLoadQueryFont(display, _(resources->clock_font2))) == NULL)
clockfont = XLoadQueryFont(display, "fixed");
init_xft();
int n;
// FIXME: should check the m,d,n values
- smallfontset = XCreateFontSet(display, resources.small_fontset, &m, &n, &d);
+ smallfontset = XCreateFontSet(display, resources->small_fontset, &m, &n, &d);
if( !smallfontset )
smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
- mediumfontset = XCreateFontSet(display, resources.medium_fontset, &m, &n, &d);
+ mediumfontset = XCreateFontSet(display, resources->medium_fontset, &m, &n, &d);
if( !mediumfontset )
mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
- largefontset = XCreateFontSet(display, resources.large_fontset, &m, &n, &d);
+ largefontset = XCreateFontSet(display, resources->large_fontset, &m, &n, &d);
if( !largefontset )
largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
- bigfontset = XCreateFontSet(display, resources.big_fontset, &m, &n, &d);
+ bigfontset = XCreateFontSet(display, resources->big_fontset, &m, &n, &d);
if( !bigfontset )
bigfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
- clockfontset = XCreateFontSet(display, resources.clock_fontset, &m, &n, &d);
+ clockfontset = XCreateFontSet(display, resources->clock_fontset, &m, &n, &d);
if( !clockfontset )
clockfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
if(clockfontset && bigfontset && largefontset && mediumfontset && smallfontset) {
static Mutex xft_init_lock("BC_WindowBase::xft_init_lock", 0);
xft_init_lock.lock("BC_WindowBase::init_xft");
if(!(smallfont_xft =
- (resources.small_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.small_font_xft) :
- xftFontOpenName(display, screen, resources.small_font_xft))) )
+ (resources->small_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->small_font_xft) :
+ xftFontOpenName(display, screen, resources->small_font_xft))) )
if(!(smallfont_xft =
- xftFontOpenXlfd(display, screen, resources.small_font_xft2)))
+ xftFontOpenXlfd(display, screen, resources->small_font_xft2)))
smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
if(!(mediumfont_xft =
- (resources.medium_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.medium_font_xft) :
- xftFontOpenName(display, screen, resources.medium_font_xft))) )
+ (resources->medium_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->medium_font_xft) :
+ xftFontOpenName(display, screen, resources->medium_font_xft))) )
if(!(mediumfont_xft =
- xftFontOpenXlfd(display, screen, resources.medium_font_xft2)))
+ xftFontOpenXlfd(display, screen, resources->medium_font_xft2)))
mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
if(!(largefont_xft =
- (resources.large_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.large_font_xft) :
- xftFontOpenName(display, screen, resources.large_font_xft))) )
+ (resources->large_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->large_font_xft) :
+ xftFontOpenName(display, screen, resources->large_font_xft))) )
if(!(largefont_xft =
- xftFontOpenXlfd(display, screen, resources.large_font_xft2)))
+ xftFontOpenXlfd(display, screen, resources->large_font_xft2)))
largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
if(!(bigfont_xft =
- (resources.big_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.big_font_xft) :
- xftFontOpenName(display, screen, resources.big_font_xft))) )
+ (resources->big_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->big_font_xft) :
+ xftFontOpenName(display, screen, resources->big_font_xft))) )
if(!(bigfont_xft =
- xftFontOpenXlfd(display, screen, resources.big_font_xft2)))
+ xftFontOpenXlfd(display, screen, resources->big_font_xft2)))
bigfont_xft = xftFontOpenXlfd(display, screen, "fixed");
if(!(clockfont_xft =
- (resources.clock_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.clock_font_xft) :
- xftFontOpenName(display, screen, resources.clock_font_xft))) )
+ (resources->clock_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->clock_font_xft) :
+ xftFontOpenName(display, screen, resources->clock_font_xft))) )
clockfont_xft = xftFontOpenXlfd(display, screen, "fixed");
if(!(bold_smallfont_xft =
- (resources.small_b_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.small_b_font_xft) :
- xftFontOpenName(display, screen, resources.small_b_font_xft))) )
+ (resources->small_b_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->small_b_font_xft) :
+ xftFontOpenName(display, screen, resources->small_b_font_xft))) )
bold_smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
if(!(bold_mediumfont_xft =
- (resources.medium_b_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.medium_b_font_xft) :
- xftFontOpenName(display, screen, resources.medium_b_font_xft))) )
+ (resources->medium_b_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->medium_b_font_xft) :
+ xftFontOpenName(display, screen, resources->medium_b_font_xft))) )
bold_mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
if(!(bold_largefont_xft =
- (resources.large_b_font_xft[0] == '-' ?
- xftFontOpenXlfd(display, screen, resources.large_b_font_xft) :
- xftFontOpenName(display, screen, resources.large_b_font_xft))) )
+ (resources->large_b_font_xft[0] == '-' ?
+ xftFontOpenXlfd(display, screen, resources->large_b_font_xft) :
+ xftFontOpenName(display, screen, resources->large_b_font_xft))) )
bold_largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
if( !smallfont_xft || !mediumfont_xft || !largefont_xft || !bigfont_xft ||
!clockfont_xft ) {
printf("BC_WindowBase::init_fonts: no xft fonts found:"
" %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n",
- resources.small_font_xft, smallfont_xft,
- resources.medium_font_xft, mediumfont_xft,
- resources.large_font_xft, largefont_xft,
- resources.big_font_xft, bigfont_xft,
- resources.clock_font_xft, clockfont_xft,
- resources.small_b_font_xft, bold_smallfont_xft,
- resources.medium_b_font_xft, bold_mediumfont_xft,
- resources.large_b_font_xft, bold_largefont_xft);
+ resources->small_font_xft, smallfont_xft,
+ resources->medium_font_xft, mediumfont_xft,
+ resources->large_font_xft, largefont_xft,
+ resources->big_font_xft, bigfont_xft,
+ resources->clock_font_xft, clockfont_xft,
+ resources->small_b_font_xft, bold_smallfont_xft,
+ resources->medium_b_font_xft, bold_mediumfont_xft,
+ resources->large_b_font_xft, bold_largefont_xft);
get_resources()->use_xft = 0;
exit(1);
}
#endif // HAVE_XFT
}
+void BC_WindowBase::init_glyphs()
+{
+// draw all ascii char glyphs
+// There are problems with some/my graphics boards/drivers
+// which cause some glyphs to be munged if draws occur while
+// the font is being loaded. This code fills the font caches
+// by drawing all the ascii glyphs before the system starts.
+// 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
+ const char *text = _( // ascii 0x20...0x7e
+ " !\"#$%&'()*+,-./0123456789:;<=>?"
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
+ "`abcdefghijklmnopqrstuvwxyz{|}~");
+ for( int font=SMALLFONT; font<=LARGEFONT; ++font ) {
+ set_font(font);
+ draw_text(5,5, text);
+ }
+ set_font(cur_font);
+ XUngrabServer(display);
+}
+
void BC_WindowBase::init_im()
{
XIMStyles *xim_styles;
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
}
if(top_level)
{
UNSET_LOCK(this);
-
-// if(!top_level->window_lock)
-// {
-// printf("BC_WindowBase::unlock_window %d %s already unlocked\n",
-// __LINE__,
-// title);
-// }
+ if( !top_level->window_lock ) {
+ printf("BC_WindowBase::unlock_window %s not locked\n", title);
+ booby();
+ }
if( top_level->window_lock > 0 )
if( --top_level->window_lock == 0 )
top_level->display_lock_owner = 0;
return 0;
}
+int BC_WindowBase::break_lock()
+{
+ if( !top_level ) return 0;
+ if( top_level != this ) return top_level->break_lock();
+ if( top_level->display_lock_owner != pthread_self() ) return 0;
+ if( top_level->window_lock != 1 ) return 0;
+ UNSET_LOCK(this);
+ window_lock = 0;
+ display_lock_owner = 0;
+#ifdef SINGLE_THREAD
+ BC_Display::unlock_display();
+#else
+ XUnlockDisplay(display);
+#endif
+ return 1;
+}
+
void BC_WindowBase::set_done(int return_value)
{
if(done_set) return;
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()
{
}
void BC_WindowBase::ungrab_cursor()
{
- XUngrabPointer(top_level->display, CurrentTime);
+ XUngrabPointer(top_level->display, CurrentTime);
}
// for get_root_w/h
BC_Resources* BC_WindowBase::get_resources()
{
- return &BC_WindowBase::resources;
+ return BC_WindowBase::resources;
}
BC_Synchronous* BC_WindowBase::get_synchronous()
{
- return BC_WindowBase::resources.get_synchronous();
+ return BC_WindowBase::resources->get_synchronous();
}
int BC_WindowBase::get_bg_color()
void BC_WindowBase::get_pop_cursor(int &px, int &py, int lock_window)
{
- int margin = 100;
+ int xmargin = xS(100), ymargin = yS(100);
get_abs_cursor(px, py, lock_window);
- if( px < margin ) px = margin;
- if( py < margin ) py = margin;
- int wd = get_screen_w(lock_window,-1) - margin;
+ if( px < xmargin ) px = xmargin;
+ if( py < ymargin ) py = ymargin;
+ 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) - margin;
+ 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;
size_hints.max_width = w;
size_hints.min_height = h;
size_hints.max_height = h;
+ if( this->x > -BC_INFINITY && this->x < BC_INFINITY ) {
+ size_hints.flags |= PPosition;
+ size_hints.x = this->x;
+ size_hints.y = this->y;
+ }
XSetNormalHints(top_level->display, win, &size_hints);
}
XResizeWindow(top_level->display, win, w, h);
{
// KDE shifts window right and down.
// FVWM leaves window alone and adds border around it.
- XMoveResizeWindow(top_level->display,
- win,
+ XMoveResizeWindow(top_level->display, win,
x - BC_DisplayInfo::auto_reposition_x,
y - BC_DisplayInfo::auto_reposition_y,
- this->w,
- this->h);
+ this->w, this->h);
}
else
{
- XMoveResizeWindow(top_level->display,
- win,
- x,
- y,
- this->w,
- this->h);
+ XMoveResizeWindow(top_level->display, win, x, y,
+ this->w, this->h);
}
if(resize)
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;
}
+void BC_WindowBase::init_resources(float scale)
+{
+ if( resources ) return;
+ XInitThreads();
+ const char *env = getenv("BC_SCALE");
+ if( env ) scale = atof(env);
+ float x_scale = 1, y_scale = 1;
+ if( scale <= 0 ) {
+ BC_DisplayInfo info;
+ 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;
+ }
+ }
+ else
+ x_scale = y_scale = scale;
+ // constructor sets BC_WindowBase::resources
+ new BC_Resources(x_scale, y_scale);
+}
+void BC_WindowBase::finit_resources()
+{
+ delete resources; resources = 0;
+}
+
int BC_WindowBase::set_w(int w)
{
this->w = w;
int BC_WindowBase::load_defaults(BC_Hash *defaults)
{
- BC_Resources *resources = get_resources();
char string[BCTEXTLEN];
int newest_id = - 1;
for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
int BC_WindowBase::save_defaults(BC_Hash *defaults)
{
- BC_Resources *resources = get_resources();
char string[BCTEXTLEN];
for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
{
// For some reason XTranslateCoordinates can take a long time to return.
// We work around this by only calling it when the event windows are different.
-void BC_WindowBase::translate_coordinates(Window src_w,
- Window dest_w,
- int src_x,
- int src_y,
- int *dest_x_return,
- int *dest_y_return)
+void BC_WindowBase::translate_coordinates(Window src_w, Window dest_w,
+ int src_x, int src_y, int *dest_x_return, int *dest_y_return)
{
Window tempwin = 0;
//Timer timer;
}
else
{
- XTranslateCoordinates(top_level->display,
- src_w,
- dest_w,
- src_x,
- src_y,
- dest_x_return,
- dest_y_return,
- &tempwin);
+ XTranslateCoordinates(top_level->display, src_w, dest_w,
+ src_x, src_y, dest_x_return, dest_y_return, &tempwin);
//printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
}
}
}
-
-
-
-
#ifdef HAVE_LIBXXF86VM
void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
{
- int foo,bar;
- *vm = 0;
- if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
- int vm_count,i;
- XF86VidModeModeInfo **vm_modelines;
- XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
- for (i = 0; i < vm_count; i++) {
- if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
- *vm = i;
- }
- display = top_level->display;
- if (vm_modelines[*vm]->hdisplay == *width)
- *vm = -1;
- else
- {
- *width = vm_modelines[*vm]->hdisplay;
- *height = vm_modelines[*vm]->vdisplay;
- }
- }
+ int foo,bar;
+ *vm = 0;
+ if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
+ int vm_count,i;
+ XF86VidModeModeInfo **vm_modelines;
+ XF86VidModeGetAllModeLines(top_level->display,
+ XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
+ for( i = 0; i < vm_count; i++ ) {
+ if( vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay &&
+ vm_modelines[i]->hdisplay >= *width )
+ *vm = i;
+ }
+ display = top_level->display;
+ if( vm_modelines[*vm]->hdisplay == *width )
+ *vm = -1;
+ else {
+ *width = vm_modelines[*vm]->hdisplay;
+ *height = vm_modelines[*vm]->vdisplay;
+ }
+ }
}
void BC_WindowBase::scale_vm(int vm)
{
- int foo,bar,dotclock;
- if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
- {
- int vm_count;
- XF86VidModeModeInfo **vm_modelines;
- XF86VidModeModeLine vml;
- XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
- XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
- orig_modeline.dotclock = dotclock;
- orig_modeline.hdisplay = vml.hdisplay;
- orig_modeline.hsyncstart = vml.hsyncstart;
- orig_modeline.hsyncend = vml.hsyncend;
- orig_modeline.htotal = vml.htotal;
- orig_modeline.vdisplay = vml.vdisplay;
- orig_modeline.vsyncstart = vml.vsyncstart;
- orig_modeline.vsyncend = vml.vsyncend;
- orig_modeline.vtotal = vml.vtotal;
- orig_modeline.flags = vml.flags;
- orig_modeline.privsize = vml.privsize;
- // orig_modeline.private = vml.private;
- XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
- XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
- XFlush(top_level->display);
- }
+ int foo,bar,dotclock;
+ if( XF86VidModeQueryExtension(top_level->display,&foo,&bar) ) {
+ int vm_count;
+ XF86VidModeModeInfo **vm_modelines;
+ XF86VidModeModeLine vml;
+ XF86VidModeGetAllModeLines(top_level->display,
+ XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
+ XF86VidModeGetModeLine(top_level->display,
+ XDefaultScreen(top_level->display), &dotclock,&vml);
+ orig_modeline.dotclock = dotclock;
+ orig_modeline.hdisplay = vml.hdisplay;
+ orig_modeline.hsyncstart = vml.hsyncstart;
+ orig_modeline.hsyncend = vml.hsyncend;
+ orig_modeline.htotal = vml.htotal;
+ orig_modeline.vdisplay = vml.vdisplay;
+ orig_modeline.vsyncstart = vml.vsyncstart;
+ orig_modeline.vsyncend = vml.vsyncend;
+ orig_modeline.vtotal = vml.vtotal;
+ orig_modeline.flags = vml.flags;
+ orig_modeline.privsize = vml.privsize;
+ // orig_modeline.private = vml.private;
+ XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
+ XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
+ XFlush(top_level->display);
+ }
}
void BC_WindowBase::restore_vm()
{
- XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
- XFlush(top_level->display);
+ XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
+ XFlush(top_level->display);
}
-
-
#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
#ifndef SINGLE_THREAD
int BC_WindowBase::get_event_count()
{
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;
+}
+