port 7.2 mods: align_edits foreground plugin refresh_frame tweak, rework soundlevel...
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcwindowbase.C
index 0194a758c75716853a15fe8a3d9f9a00728e06cf..f94ee16512ee7652c3339114b89cfbe2c2735f21 100644 (file)
@@ -69,17 +69,8 @@ BC_ResizeCall::BC_ResizeCall(int w, int 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);
@@ -149,7 +140,11 @@ BC_WindowBase::~BC_WindowBase()
 //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);
@@ -456,8 +451,19 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title
                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;
@@ -467,7 +473,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title
 // 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();
 
@@ -480,7 +486,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title
                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);
@@ -566,12 +572,11 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title
                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)
@@ -619,7 +624,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title
                }
 
                if(!hidden) show_window();
-
+               init_glyphs();
        }
 
        draw_background(0, 0, this->w, this->h);
@@ -648,18 +653,16 @@ Display* BC_WindowBase::init_display(const char *display_name)
 
        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);
                }
        }
 
@@ -731,9 +734,8 @@ int BC_WindowBase::run_window()
        init_lock->unlock();
 
 // Handle common events
-       while(!done)
-       {
-               dispatch_event(0);
+       while( !done ) {
+               dispatch_event();
        }
 
        unset_all_repeaters();
@@ -873,7 +875,7 @@ int BC_WindowBase::keysym_lookup(XEvent *event)
 //  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;
@@ -889,13 +891,14 @@ pthread_t locking_task = (pthread_t)-1L;
 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;
 
@@ -932,23 +935,22 @@ locking_message = event->xclient.message_type;
 
 
 
-//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 ) {
                unlock_window();
@@ -962,42 +964,25 @@ locking_message = event->xclient.message_type;
        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;
 
@@ -1031,8 +1016,7 @@ locking_message = event->xclient.message_type;
 
 //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number);
                event_win = event->xany.window;
-               if (button_number < 6)
-               {
+               if (button_number < 6) {
                        if(button_number < 4)
                                button_down = 1;
                        button_pressed = event->xbutton.button;
@@ -1047,12 +1031,12 @@ locking_message = event->xclient.message_type;
                        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)
+                       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)
+                       if((long)(button_time3 - button_time2) < resources->double_click)
                        {
                                double_click = 1;
 //                             button_time3 = button_time2 = button_time1 = 0;
@@ -1087,7 +1071,13 @@ locking_message = event->xclient.message_type;
 
        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:
@@ -1192,8 +1182,11 @@ locking_message = event->xclient.message_type;
                }
                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:
@@ -2090,15 +2083,8 @@ int BC_WindowBase::init_colors()
        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);
 
@@ -2109,13 +2095,11 @@ int BC_WindowBase::init_colors()
        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();
                        }
@@ -2311,21 +2295,21 @@ int BC_WindowBase::init_gc()
 
 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();
@@ -2335,19 +2319,19 @@ int BC_WindowBase::init_fonts()
                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) {
@@ -2371,54 +2355,54 @@ void BC_WindowBase::init_xft()
 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 ||
@@ -2426,14 +2410,14 @@ xft_init_lock.lock("BC_WindowBase::init_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);
        }
@@ -2443,6 +2427,30 @@ xft_init_lock.unlock();
 #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;
+       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, 0);
+       }
+       set_font(cur_font);
+}
+
 void BC_WindowBase::init_im()
 {
        XIMStyles *xim_styles;
@@ -3052,6 +3060,39 @@ int BC_WindowBase::get_text_height(int font, const char *text)
        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();
@@ -3316,13 +3357,10 @@ int BC_WindowBase::unlock_window()
        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;
@@ -3339,6 +3377,23 @@ int BC_WindowBase::unlock_window()
        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;
@@ -3424,7 +3479,7 @@ void BC_WindowBase::grab_cursor()
 }
 void BC_WindowBase::ungrab_cursor()
 {
-       XUngrabPointer(top_level->display, CurrentTime);
+       XUngrabPointer(top_level->display, CurrentTime);
 }
 
 // for get_root_w/h
@@ -3624,12 +3679,12 @@ int BC_WindowBase::get_color_model()
 
 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()
@@ -3866,13 +3921,13 @@ int BC_WindowBase::get_abs_cursor_y(int lock_window)
 
 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_w(lock_window,-1) - xmargin;
        if( px > wd ) px = wd;
-       int ht = get_screen_h(lock_window,-1) - margin;
+       int ht = get_screen_h(lock_window,-1) - ymargin;
        if( py > ht ) py = ht;
 }
 int BC_WindowBase::get_pop_cursor_x(int lock_window)
@@ -4057,6 +4112,11 @@ int BC_WindowBase::resize_window(int w, int h)
                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);
@@ -4128,21 +4188,15 @@ int BC_WindowBase::reposition_window(int x, int y, int w, int 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)
@@ -4240,6 +4294,26 @@ void BC_WindowBase::set_title(const char *text, int utf8)
        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;
@@ -4261,31 +4335,58 @@ int BC_WindowBase::set_icon(VFrame *data)
        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) ) {
+                       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;
@@ -4300,7 +4401,6 @@ int BC_WindowBase::set_h(int h)
 
 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++)
@@ -4333,7 +4433,6 @@ int BC_WindowBase::load_defaults(BC_Hash *defaults)
 
 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++)
        {
@@ -4362,12 +4461,8 @@ int BC_WindowBase::save_defaults(BC_Hash *defaults)
 
 // 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;
@@ -4379,14 +4474,8 @@ void BC_WindowBase::translate_coordinates(Window src_w,
        }
        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());
        }
 }
@@ -4402,88 +4491,68 @@ void BC_WindowBase::get_win_coordinates(int abs_x, int abs_y, int *x, int *y)
 }
 
 
-
-
-
-
 #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()
 {