rework histogram_bezier, init wm icon set_icon(gg), update de.po+msg/txt
[goodguy/history.git] / cinelerra-5.1 / guicast / bcwindowbase.C
index 791aa0c856ccfb84252f3f9dced1afd7c0c70ea5..1ef0d5939cc8e697ae71ffe3a94b2bbcdc894b3b 100644 (file)
@@ -36,7 +36,7 @@
 #include "bcwindowbase.h"
 #include "bcwindowevents.h"
 #include "bccmodels.h"
-#include "colors.h"
+#include "bccolors.h"
 #include "condition.h"
 #include "cursors.h"
 #include "bchash.h"
@@ -46,6 +46,7 @@
 #include "mutex.h"
 #include "sizes.h"
 #include "vframe.h"
+#include "workarounds.h"
 
 #ifdef HAVE_GL
 #include <GL/gl.h>
@@ -61,7 +62,6 @@
 #include <X11/XF86keysym.h>
 #include <X11/Sunkeysym.h>
 
-
 BC_ResizeCall::BC_ResizeCall(int w, int h)
 {
        this->w = w;
@@ -85,9 +85,8 @@ Window XGroupLeader = 0;
 Mutex BC_KeyboardHandlerLock::keyboard_listener_mutex("keyboard_listener",0);
 ArrayList<BC_KeyboardHandler*> BC_KeyboardHandler::listeners;
 
-BC_WindowBase::BC_WindowBase(int opts)
+BC_WindowBase::BC_WindowBase()
 {
-       this->options = opts;
 //printf("BC_WindowBase::BC_WindowBase 1\n");
        BC_WindowBase::initialize();
 }
@@ -118,7 +117,6 @@ BC_WindowBase::~BC_WindowBase()
                top_level->dequeue_events(win);
 #endif
 // drop active window refs to this
-               if(top_level->active_grab == this) top_level->active_grab = 0;
                if(top_level->active_menubar == this) top_level->active_menubar = 0;
                if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
                if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
@@ -130,6 +128,7 @@ BC_WindowBase::~BC_WindowBase()
                parent_window->subwindows->remove(this);
        }
 
+       if(grab_active) grab_active->active_grab = 0;
        if(icon_window) delete icon_window;
        if(window_type == POPUP_WINDOW)
                parent_window->remove_popup(this);
@@ -147,13 +146,13 @@ BC_WindowBase::~BC_WindowBase()
 
        delete pixmap;
 
+//printf("delete glx=%08x, win=%08x %s\n", (unsigned)glx_win, (unsigned)win, title);
 #ifdef HAVE_GL
-       if( get_resources()->get_synchronous() &&
-               (top_level->options & GLX_WINDOW) && glx_win != 0 )
+       if( get_resources()->get_synchronous() && glx_win != 0 ) {
                get_resources()->get_synchronous()->delete_window(this);
-       else
+       }
 #endif
-               XDestroyWindow(top_level->display, win);
+       XDestroyWindow(top_level->display, win);
 
        if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
        if(icon_pixmap) delete icon_pixmap;
@@ -177,13 +176,17 @@ BC_WindowBase::~BC_WindowBase()
                         &BC_WindowBase::mediumfont,
                         &BC_WindowBase::largefont,
                         &BC_WindowBase::bigfont,
+                        &BC_WindowBase::clockfont,
                };
                for( int i=sizeof(xfont)/sizeof(xfont[0]); --i>=0; )
                        XFreeFont(display, this->*xfont[i]);
 
-// bug in X causes XRenderExtensionInfo to be damaged if this is done here
-//  left to be done in XCloseDisplay by Xlib.
-#if defined(HAVE_XFT) && 0
+#ifdef HAVE_XFT
+// prevents a bug when Xft closes with unrefd fonts
+               FcPattern *defaults = FcPatternCreate();
+               FcPatternAddInteger(defaults, "maxunreffonts", 0);
+               XftDefaultSet(display, defaults);
+
                static void *BC_WindowBase::*xft_font[] = {
                         &BC_WindowBase::smallfont_xft,
                         &BC_WindowBase::mediumfont_xft,
@@ -192,10 +195,11 @@ BC_WindowBase::~BC_WindowBase()
                         &BC_WindowBase::bold_smallfont_xft,
                         &BC_WindowBase::bold_mediumfont_xft,
                         &BC_WindowBase::bold_largefont_xft,
+                        &BC_WindowBase::clockfont_xft,
                };
                for( int i=sizeof(xft_font)/sizeof(xft_font[0]); --i>=0; ) {
                        XftFont *xft = (XftFont *)(this->*xft_font[i]);
-                       if( xft ) XftFontClose (display, xft);
+                       if( xft ) xftFontClose (display, xft);
                }
 #endif
                finit_im();
@@ -210,23 +214,15 @@ BC_WindowBase::~BC_WindowBase()
                        XvUngrabPort(display, xvideo_port_id, CurrentTime);
 
                unlock_window();
-// Can't close display if another thread is waiting for events.
-// Synchronous thread must delete display it owns a GLX_WINDOW
 // Must be last reference to display.
-#ifndef SINGLE_THREAD
-#ifdef HAVE_GL
-               if( (options & GLX_DISPLAY) != 0 && get_resources()->get_synchronous() ) {
-                       printf(_("BC_WindowBase::~BC_WindowBase window deleted but opengl deletion is not\n"
-                               "implemented for BC_Pixmap.\n"));
-                       get_resources()->get_synchronous()->delete_display(this);
-               }
-               else
-#endif
-                       XCloseDisplay(display);
+// _XftDisplayInfo needs a lock.
+               get_resources()->create_window_lock->lock("BC_WindowBase::~BC_WindowBase");
+               XCloseDisplay(display);
+               get_resources()->create_window_lock->unlock();
+
 // clipboard uses a different display connection
                clipboard->stop_clipboard();
                delete clipboard;
-#endif // SINGLE_THREAD
        }
 
        resize_history.remove_all_objects();
@@ -261,6 +257,7 @@ int BC_WindowBase::initialize()
        keys_return[0] = 0;
        is_deleting = 0;
        window_lock = 0;
+       resend_event_window = 0;
        x = 0;
        y = 0;
        w = 0;
@@ -291,9 +288,11 @@ int BC_WindowBase::initialize()
        last_motion_win = 0;
        key_pressed = 0;
        active_grab = 0;
+       grab_active = 0;
        active_menubar = 0;
        active_popup_menu = 0;
        active_subwindow = 0;
+       cursor_entered = 0;
        pixmap = 0;
        bg_pixmap = 0;
        _7segment_pixmaps = 0;
@@ -301,7 +300,6 @@ int BC_WindowBase::initialize()
        force_tooltip = 0;
 //     next_repeat_id = 0;
        tooltip_popup = 0;
-       tooltip_done = 0;
        current_font = MEDIUMFONT;
        current_color = BLACK;
        current_cursor = ARROW_CURSOR;
@@ -324,16 +322,24 @@ int BC_WindowBase::initialize()
 #ifdef HAVE_LIBXXF86VM
        vm_switched = 0;
 #endif
-       smallfont_xft = 0;
-       bold_largefont_xft = 0;
-       bold_mediumfont_xft = 0;
-       bold_smallfont_xft = 0;
        input_method = 0;
        input_context = 0;
 
+       smallfont = 0;
+       mediumfont = 0;
+       largefont = 0;
+       bigfont = 0;
+       clockfont = 0;
+
+       smallfont_xft = 0;
        mediumfont_xft = 0;
        largefont_xft = 0;
        bigfont_xft = 0;
+       clockfont_xft = 0;
+
+       bold_smallfont_xft = 0;
+       bold_mediumfont_xft = 0;
+       bold_largefont_xft = 0;
 #ifdef SINGLE_THREAD
        completion_lock = new Condition(0, "BC_WindowBase::completion_lock");
 #else
@@ -370,22 +376,10 @@ int BC_WindowBase::initialize()
                        FocusChangeMask
 
 
-int BC_WindowBase::create_window(BC_WindowBase *parent_window,
-                               const char *title,
-                               int x,
-                               int y,
-                               int w,
-                               int h,
-                               int minw,
-                               int minh,
-                               int allow_resize,
-                               int private_color,
-                               int hide,
-                               int bg_color,
-                               const char *display_name,
-                               int window_type,
-                               BC_Pixmap *bg_pixmap,
-                               int group_it)
+int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title,
+               int x, int y, int w, int h, int minw, int minh, int allow_resize,
+               int private_color, int hide, int bg_color, const char *display_name,
+               int window_type, BC_Pixmap *bg_pixmap, int group_it)
 {
        XSetWindowAttributes attr;
        unsigned long mask;
@@ -397,12 +391,8 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window,
 #endif
 
        id = get_resources()->get_id();
-       int need_lock = 0;
        if(parent_window) top_level = parent_window->top_level;
-       if( top_level ) { // need this to avoid deadlock with Xlib's locks
-               need_lock = 1;
-               lock_window("BC_WindowBase::create_window");
-       }
+       if( top_level ) lock_window("BC_WindowBase::create_window");
        get_resources()->create_window_lock->lock("BC_WindowBase::create_window");
 
 #ifdef HAVE_LIBXXF86VM
@@ -426,7 +416,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window,
        else
                this->display_name[0] = 0;
 
-       put_title(_(title));
+       put_title(title);
        if(bg_pixmap) shared_bg_pixmap = 1;
 
        subwindows = new BC_SubWindowList;
@@ -452,6 +442,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window,
                if( shm_completion_event < 0 ) shm_completion_event =
                        ShmCompletion + XShmGetEventBase(display);
 #endif
+               lock_window("BC_WindowBase::create_window 1");
 
                screen = DefaultScreen(display);
                rootwin = RootWindow(display, screen);
@@ -529,24 +520,11 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window,
                        size_hints.x = this->x;
                        size_hints.y = this->y;
                }
-
-               char *txlist[2];
-               txlist[0] = this->title;
-               txlist[1] = 0;
-               XTextProperty titleprop;
-               if(options & WINDOW_UTF8)
-                       Xutf8TextListToTextProperty(display, txlist,  1,
-                               XUTF8StringStyle, &titleprop);
-               else
-                       XmbTextListToTextProperty(display, txlist, 1,
-                               XStdICCTextStyle, &titleprop);
-               XSetWMProperties(display, win, &titleprop, &titleprop,
-                       0, 0, &size_hints, 0, 0);
-               XFree(titleprop.value);
+               XSetWMProperties(display, win, 0, 0, 0, 0, &size_hints, 0, 0);
                get_atoms();
-
+               set_title(title);
 #ifndef SINGLE_THREAD
-               clipboard = new BC_Clipboard(display_name);
+               clipboard = new BC_Clipboard(this);
                clipboard->start_clipboard();
 #endif
 
@@ -568,6 +546,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window,
                                PropModeReplace, (unsigned char *)&XGroupLeader, true);
                }
                init_im();
+               set_icon(get_resources()->default_icon);
        }
 
 #ifdef HAVE_LIBXXF86VM
@@ -658,7 +637,7 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window,
                if(!hidden) show_window();
        }
        get_resources()->create_window_lock->unlock();
-       if(need_lock) unlock_window();
+       unlock_window();
 
        return 0;
 }
@@ -683,6 +662,15 @@ Display* BC_WindowBase::init_display(const char *display_name)
                        }
                }
        }
+
+       static int xsynch = -1;
+       if( xsynch < 0 ) {
+               const char *cp = getenv("CIN_XSYNCH");
+               xsynch = !cp ? 0 : atoi(cp);
+       }
+       if( xsynch > 0 )
+               XSynchronize(display, True);
+
        return display;
 }
 
@@ -962,12 +950,15 @@ locking_message = event->xclient.message_type;
 //   event_names[event->type] : "Unknown");
 //}
 
-       if( active_grab && active_grab->grab_event(event) ) {
+       if( active_grab ) {
                unlock_window();
-               return 0;
+               active_grab->lock_window("BC_WindowBase::dispatch_event 3");
+               result = active_grab->grab_event(event);
+               active_grab->unlock_window();
+               if( result ) return result;
+               lock_window("BC_WindowBase::dispatch_event 4");
        }
 
-
        switch(event->type) {
        case ClientMessage:
 // Clear the resize buffer
@@ -1006,7 +997,7 @@ locking_message = event->xclient.message_type;
                        done = 1;
                        } else
                        { // We currently use X marshalling for xatom events, we can switch to something else later
-                               recieve_custom_xatoms((xatom_event *)ptr);
+                               receive_custom_xatoms((xatom_event *)ptr);
                }
                break;
 
@@ -1029,6 +1020,10 @@ locking_message = event->xclient.message_type;
                break;
 
        case ButtonPress:
+               if(motion_events)
+               {
+                       dispatch_motion_event();
+               }
                get_key_masks(event->xbutton.state);
                cursor_x = event->xbutton.x;
                cursor_y = event->xbutton.y;
@@ -1073,6 +1068,10 @@ locking_message = event->xclient.message_type;
                break;
 
        case ButtonRelease:
+               if(motion_events)
+               {
+                       dispatch_motion_event();
+               }
                get_key_masks(event->xbutton.state);
                button_number = event->xbutton.button;
                event_win = event->xany.window;
@@ -1256,6 +1255,20 @@ locking_message = event->xclient.message_type;
                case XK_KP_Insert:      key_pressed = KPINS;    break;
                case XK_KP_Decimal:
                case XK_KP_Delete:      key_pressed = KPDEL;    break;
+
+               case XK_F1:             key_pressed = KEY_F1;   break;
+               case XK_F2:             key_pressed = KEY_F2;   break;
+               case XK_F3:             key_pressed = KEY_F3;   break;
+               case XK_F4:             key_pressed = KEY_F4;   break;
+               case XK_F5:             key_pressed = KEY_F5;   break;
+               case XK_F6:             key_pressed = KEY_F6;   break;
+               case XK_F7:             key_pressed = KEY_F7;   break;
+               case XK_F8:             key_pressed = KEY_F8;   break;
+               case XK_F9:             key_pressed = KEY_F9;   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;
+
                case XK_Menu:           key_pressed = KPMENU;   break;  /* menu */
 // remote control
 // above       case XK_KP_Enter:       key_pressed = KPENTER;  break;  /* check */
@@ -1325,16 +1338,33 @@ locking_message = event->xclient.message_type;
                break;
 
        case LeaveNotify:
+               if( event->xcrossing.mode != NotifyNormal ) break;
+               cursor_entered = 0;
                event_win = event->xany.window;
                dispatch_cursor_leave();
                break;
 
        case EnterNotify:
+               if( event->xcrossing.mode != NotifyNormal ) break;
+
+               if( !cursor_entered ) {
+                       for( int i=0; i<popups.size(); ++i ) {  // popups always take focus
+                               if( popups[i]->win == event->xcrossing.window )
+                               cursor_entered = 1;
+                       }
+                       if( !cursor_entered && get_resources()->grab_input_focus &&
+                           !event->xcrossing.focus && event->xcrossing.window == win ) {
+                               cursor_entered = 1;
+                       }
+                       if( cursor_entered )
+                               focus();
+               }
                event_win = event->xany.window;
                cursor_x = event->xcrossing.x;
                cursor_y = event->xcrossing.y;
                dispatch_cursor_enter();
                break;
+
        default:
                break;
        }
@@ -1343,7 +1373,14 @@ locking_message = event->xclient.message_type;
 
 #ifndef SINGLE_THREAD
        unlock_window();
-       if(event) delete event;
+       if(event) {
+               if( resend_event_window ) {
+                       resend_event_window->put_event(event);
+                       resend_event_window = 0;
+               }
+               else
+                       delete event;
+       }
 #else
 //     if(done) completion_lock->unlock();
 #endif
@@ -1770,69 +1807,54 @@ int BC_WindowBase::dispatch_drag_motion()
 }
 
 
-
-
-
-int BC_WindowBase::show_tooltip(int w, int h)
+int BC_WindowBase::show_tooltip(const char *text, int x, int y, int w, int h)
 {
-       Window tempwin;
-
-       if(tooltip_text && !tooltip_on &&
-               (force_tooltip || get_resources()->tooltips_enabled))
-       {
-               int x, y;
+// default text
+       int forced = !text ? force_tooltip : 1;
+       if( !text ) text = tooltip_text;
+       if( !text || (!forced && !get_resources()->tooltips_enabled) ) {
                top_level->hide_tooltip();
-
+               return 1;
+       }
+// default w,h
+       if(w < 0) w = get_text_width(MEDIUMFONT, text)  + TOOLTIP_MARGIN * 2;
+       if(h < 0) h = get_text_height(MEDIUMFONT, text) + TOOLTIP_MARGIN * 2;
+// default x,y (win relative)
+       if( x < 0 ) x = get_w();
+       if( y < 0 ) y = get_h();
+       int wx, wy;
+       get_root_coordinates(x, y, &wx, &wy);
+// keep the tip inside the window/display
+       int x0 = top_level->get_x(), x1 = x0 + top_level->get_w();
+       int x2 = top_level->get_screen_x(0, -1) + top_level->get_screen_w(0, -1);
+       if( x1 > x2 ) x1 = x2;
+       if( wx < x0 ) wx = x0;
+       if( wx >= (x1-=w) ) wx = x1;
+       int y0 = top_level->get_y(), y1 = y0 + top_level->get_h();
+       int y2 = top_level->get_root_h(0);
+       if( y1 > y2 ) y1 = y2;
+       if( wy < y0 ) wy = y0;
+       if( wy >= (y1-=h) ) wy = y1;
+// avoid tip under cursor (flickers)
+       int abs_x, abs_y;
+       get_abs_cursor(abs_x,abs_y, 0);
+       if( wx < abs_x && abs_x < wx+w && wy < abs_y && abs_y < wy+h ) {
+               if( wx-abs_x < wy-abs_y )
+                       wx = abs_x+1;
+               else
+                       wy = abs_y+1;
+       }
+       if( !tooltip_on ) {
                tooltip_on = 1;
-               if(w < 0)
-                       w = get_text_width(MEDIUMFONT, tooltip_text);
-
-               if(h < 0)
-                       h = get_text_height(MEDIUMFONT, tooltip_text);
-
-               w += TOOLTIP_MARGIN * 2;
-               h += TOOLTIP_MARGIN * 2;
-
-               XTranslateCoordinates(top_level->display, win,
-                               top_level->rootwin, get_w(), get_h(),
-                               &x, &y, &tempwin);
-               // keep the tip inside the window/display
-               int top_x = top_level->get_x();
-               if( x < top_x ) x = top_x;
-               int top_w = top_x + top_level->get_w();
-               int lmt_w = top_level->get_screen_x(0, -1) + top_level->get_screen_w(0, -1);
-               if( top_w < lmt_w ) lmt_w = top_w;
-               if( x+w > lmt_w ) x = lmt_w-w;
-               if( x < 0 ) x = 0;
-               int top_y = top_level->get_y();
-               if( y < top_y ) y = top_y;
-               int top_h = top_y + top_level->get_h();
-               int lmt_h = top_level->get_root_h(0);
-               if( top_h < lmt_h ) lmt_h = top_h;
-               if( y+h > lmt_h ) y = lmt_h-h;
-               if( y < 0 ) y = 0;
-               int abs_x, abs_y, win_x, win_y;
-               unsigned int temp_mask;
-               Window temp_win;
-               XQueryPointer(top_level->display, top_level->win,
-                       &temp_win, &temp_win, &abs_x, &abs_y,
-                       &win_x, &win_y, &temp_mask);
-               // check for cursor inside popup
-               if( x < abs_x && abs_x < x+w && y < abs_y && abs_y < y+h )
-               {
-                       if( x-abs_x < y-abs_y )
-                               x = abs_x+1;
-                       else
-                               y = abs_y+1;
-               }
-               tooltip_popup = new BC_Popup(top_level, x, y, w, h,
-                                       get_resources()->tooltip_bg_color);
-
-               draw_tooltip();
-               tooltip_popup->set_font(MEDIUMFONT);
-               tooltip_popup->flash();
-               tooltip_popup->flush();
+               tooltip_popup = new BC_Popup(top_level, wx, wy, w, h,
+                               get_resources()->tooltip_bg_color);
        }
+       else
+               tooltip_popup->reposition_window(wx, wy, w, h);
+
+       draw_tooltip(text);
+       tooltip_popup->flash();
+       tooltip_popup->flush();
        return 0;
 }
 
@@ -1870,7 +1892,6 @@ int BC_WindowBase::set_tooltip(const char *text)
        }
        return 0;
 }
-
 // signal the event handler to repeat
 int BC_WindowBase::set_repeat(int64_t duration)
 {
@@ -1964,7 +1985,7 @@ int BC_WindowBase::arm_repeat(int64_t duration)
 }
 #endif
 
-int BC_WindowBase::recieve_custom_xatoms(xatom_event *event)
+int BC_WindowBase::receive_custom_xatoms(xatom_event *event)
 {
        return 0;
 }
@@ -2025,9 +2046,9 @@ void BC_WindowBase::init_cursors()
        downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
        downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
        hourglass_cursor = XCreateFontCursor(display, XC_watch);
+       grabbed_cursor = create_grab_cursor();
 
-
-       char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
+       static char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
        Colormap colormap = DefaultColormap(display, screen);
        Pixmap pixmap_bottom = XCreateBitmapFromData(display,
                rootwin, cursor_data, 8, 8);
@@ -2188,6 +2209,53 @@ int BC_WindowBase::create_shared_colors()
        return 0;
 }
 
+Cursor BC_WindowBase::create_grab_cursor()
+{
+       int iw = 23, iw1 = iw-1, iw2 = iw/2;
+       int ih = 23, ih1 = ih-1, ih2 = ih/2;
+       VFrame grab(iw,ih,BC_RGB888);
+       grab.clear_frame();
+       grab.set_pixel_color(RED);   // fg
+       grab.draw_smooth(iw2,0,   iw1,0,   iw1,ih2);
+       grab.draw_smooth(iw1,ih2, iw1,ih1, iw2,ih1);
+       grab.draw_smooth(iw2,ih1, 0,ih1,   0,ih2);
+       grab.draw_smooth(0,ih2,   0,0,     iw2,0);
+       grab.set_pixel_color(WHITE); // bg
+       grab.draw_line(0,ih2,     iw2-2,ih2);
+       grab.draw_line(iw2+2,ih2, iw1,ih2);
+       grab.draw_line(iw2,0,     iw2,ih2-2);
+       grab.draw_line(iw2,ih2+2, iw2,ih1);
+
+       int bpl = (iw+7)/8, isz = bpl * ih;
+       char img[isz];  memset(img, 0, isz);
+       char msk[isz];  memset(msk, 0, isz);
+       unsigned char **rows = grab.get_rows();
+       for( int iy=0; iy<ih; ++iy ) {
+               char *op = img + iy*bpl;
+               char *mp = msk + iy*bpl;
+               unsigned char *ip = rows[iy];
+               for( int ix=0; ix<iw; ++ix,ip+=3 ) {
+                       if( ip[0] ) mp[ix>>3] |= (1<<(ix&7));
+                       if( !ip[1] ) op[ix>>3] |= (1<<(ix&7));
+               }
+       }
+       unsigned long white_pix = WhitePixel(display, screen);
+       unsigned long black_pix = BlackPixel(display, screen);
+       Pixmap img_xpm = XCreatePixmapFromBitmapData(display, rootwin,
+               img, iw,ih, white_pix,black_pix, 1);
+       Pixmap msk_xpm = XCreatePixmapFromBitmapData(display, rootwin,
+               msk, iw,ih, white_pix,black_pix, 1);
+
+       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
+       Cursor cursor = XCreatePixmapCursor(display, img_xpm,msk_xpm, &fc,&bc, iw2,ih2);
+       XFreePixmap(display, img_xpm);
+       XFreePixmap(display, msk_xpm);
+       return cursor;
+}
+
 int BC_WindowBase::allocate_color_table()
 {
        int red, green, blue, color;
@@ -2256,6 +2324,10 @@ int BC_WindowBase::init_fonts()
                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)
+                       clockfont = XLoadQueryFont(display, "fixed");
+
        init_xft();
        if(get_resources()->use_fontset)
        {
@@ -2274,8 +2346,11 @@ int BC_WindowBase::init_fonts()
                        largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
                bigfontset = XCreateFontSet(display, resources.big_fontset, &m, &n, &d);
                if( !bigfontset )
-                       largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
-               if(bigfontset && largefontset && mediumfontset && smallfontset) {
+                       bigfontset = XCreateFontSet(display, "fixed,*", &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) {
                        curr_fontset = mediumfontset;
                        get_resources()->use_fontset = 1;
                }
@@ -2292,66 +2367,79 @@ void BC_WindowBase::init_xft()
 {
 #ifdef HAVE_XFT
        if( !get_resources()->use_xft ) return;
+// apparently, xft is not reentrant, more than this is needed
+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))) )
+                       xftFontOpenXlfd(display, screen, resources.small_font_xft) :
+                       xftFontOpenName(display, screen, resources.small_font_xft))) )
                if(!(smallfont_xft =
-                       XftFontOpenXlfd(display, screen, resources.small_font_xft2)))
-                       smallfont_xft = XftFontOpenXlfd(display, screen, "fixed");
+                       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))) )
+                       xftFontOpenXlfd(display, screen, resources.medium_font_xft) :
+                       xftFontOpenName(display, screen, resources.medium_font_xft))) )
                if(!(mediumfont_xft =
-                       XftFontOpenXlfd(display, screen, resources.medium_font_xft2)))
-                       mediumfont_xft = XftFontOpenXlfd(display, screen, "fixed");
+                       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))) )
+                       xftFontOpenXlfd(display, screen, resources.large_font_xft) :
+                       xftFontOpenName(display, screen, resources.large_font_xft))) )
                if(!(largefont_xft =
-                       XftFontOpenXlfd(display, screen, resources.large_font_xft2)))
-                       largefont_xft = XftFontOpenXlfd(display, screen, "fixed");
+                       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))) )
+                       xftFontOpenXlfd(display, screen, resources.big_font_xft) :
+                       xftFontOpenName(display, screen, resources.big_font_xft))) )
                if(!(bigfont_xft =
-                       XftFontOpenXlfd(display, screen, resources.big_font_xft2)))
-                       bigfont_xft = XftFontOpenXlfd(display, screen, "fixed");
+                       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))) )
+               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))) )
-               bold_smallfont_xft = XftFontOpenXlfd(display, screen, "fixed");
+                       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))) )
-               bold_mediumfont_xft = XftFontOpenXlfd(display, screen, "fixed");
+                       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))) )
-               bold_largefont_xft = XftFontOpenXlfd(display, screen, "fixed");
+                       xftFontOpenXlfd(display, screen, resources.large_b_font_xft) :
+                       xftFontOpenName(display, screen, resources.large_b_font_xft))) )
+               bold_largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
 
-// Extension failed to locate fonts
        if( !smallfont_xft || !mediumfont_xft || !largefont_xft || !bigfont_xft ||
-           !bold_largefont_xft || !bold_mediumfont_xft || !bold_largefont_xft ) {
+           !bold_largefont_xft || !bold_mediumfont_xft || !bold_largefont_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 %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);
                get_resources()->use_xft = 0;
                exit(1);
        }
+// _XftDisplayInfo needs a lock.
+       xftDefaultHasRender(display);
+xft_init_lock.unlock();
 #endif // HAVE_XFT
 }
 
@@ -2583,21 +2671,22 @@ Cursor BC_WindowBase::get_cursor_struct(int cursor)
 {
        switch(cursor)
        {
-               case ARROW_CURSOR:         return top_level->arrow_cursor;                 break;
+               case ARROW_CURSOR:         return top_level->arrow_cursor;
                case CROSS_CURSOR:         return top_level->cross_cursor;
-               case IBEAM_CURSOR:         return top_level->ibeam_cursor;                 break;
-               case VSEPARATE_CURSOR:     return top_level->vseparate_cursor;             break;
-               case HSEPARATE_CURSOR:     return top_level->hseparate_cursor;             break;
-               case MOVE_CURSOR:              return top_level->move_cursor;                  break;
-               case LEFT_CURSOR:          return top_level->left_cursor;                  break;
-               case RIGHT_CURSOR:         return top_level->right_cursor;                 break;
-               case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;         break;
-               case UPLEFT_RESIZE:        return top_level->upleft_resize_cursor;         break;
-               case UPRIGHT_RESIZE:       return top_level->upright_resize_cursor;        break;
-               case DOWNLEFT_RESIZE:      return top_level->downleft_resize_cursor;       break;
-               case DOWNRIGHT_RESIZE:     return top_level->downright_resize_cursor;      break;
-               case HOURGLASS_CURSOR:     return top_level->hourglass_cursor;                 break;
-               case TRANSPARENT_CURSOR:   return top_level->transparent_cursor;               break;
+               case IBEAM_CURSOR:         return top_level->ibeam_cursor;
+               case VSEPARATE_CURSOR:     return top_level->vseparate_cursor;
+               case HSEPARATE_CURSOR:     return top_level->hseparate_cursor;
+               case MOVE_CURSOR:          return top_level->move_cursor;
+               case LEFT_CURSOR:          return top_level->left_cursor;
+               case RIGHT_CURSOR:         return top_level->right_cursor;
+               case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;
+               case UPLEFT_RESIZE:        return top_level->upleft_resize_cursor;
+               case UPRIGHT_RESIZE:       return top_level->upright_resize_cursor;
+               case DOWNLEFT_RESIZE:      return top_level->downleft_resize_cursor;
+               case DOWNRIGHT_RESIZE:     return top_level->downright_resize_cursor;
+               case HOURGLASS_CURSOR:     return top_level->hourglass_cursor;
+               case TRANSPARENT_CURSOR:   return top_level->transparent_cursor;
+               case GRABBED_CURSOR:       return top_level->grabbed_cursor;
        }
        return 0;
 }
@@ -2701,6 +2790,7 @@ XFontStruct* BC_WindowBase::get_font_struct(int font)
                case MEDIUMFONT: return top_level->mediumfont; break;
                case LARGEFONT:  return top_level->largefont;  break;
                case BIGFONT:    return top_level->bigfont;    break;
+               case CLOCKFONT:  return top_level->clockfont;  break;
        }
        return 0;
 }
@@ -2716,6 +2806,7 @@ XFontSet BC_WindowBase::get_fontset(int font)
                        case MEDIUMFONT: fs = top_level->mediumfontset; break;
                        case LARGEFONT:  fs = top_level->largefontset; break;
                        case BIGFONT:    fs = top_level->bigfontset;   break;
+                       case CLOCKFONT: fs = top_level->clockfontset; break;
                }
        }
 
@@ -2730,6 +2821,7 @@ XftFont* BC_WindowBase::get_xft_struct(int font)
                case MEDIUMFONT:   return (XftFont*)top_level->mediumfont_xft;
                case LARGEFONT:    return (XftFont*)top_level->largefont_xft;
                case BIGFONT:      return (XftFont*)top_level->bigfont_xft;
+               case CLOCKFONT:    return (XftFont*)top_level->clockfont_xft;
                case MEDIUMFONT_3D: return (XftFont*)top_level->bold_mediumfont_xft;
                case SMALLFONT_3D:  return (XftFont*)top_level->bold_smallfont_xft;
                case LARGEFONT_3D:  return (XftFont*)top_level->bold_largefont_xft;
@@ -2740,13 +2832,6 @@ XftFont* BC_WindowBase::get_xft_struct(int font)
 #endif
 
 
-
-
-
-
-
-
-
 int BC_WindowBase::get_current_font()
 {
        return top_level->current_font;
@@ -2782,6 +2867,7 @@ void BC_WindowBase::set_fontset(int font)
                        case MEDIUMFONT: fs = top_level->mediumfontset; break;
                        case LARGEFONT:  fs = top_level->largefontset; break;
                        case BIGFONT:    fs = top_level->bigfontset;   break;
+                       case CLOCKFONT:  fs = top_level->clockfontset; break;
                }
        }
 
@@ -2805,7 +2891,7 @@ int BC_WindowBase::get_single_text_width(int font, const char *text, int length)
 #ifdef X_HAVE_UTF8_STRING
                if(get_resources()->locale_utf8)
                {
-                       XftTextExtentsUtf8(top_level->display,
+                       xftTextExtentsUtf8(top_level->display,
                                get_xft_struct(font),
                                (const XftChar8 *)text,
                                length,
@@ -2814,7 +2900,7 @@ int BC_WindowBase::get_single_text_width(int font, const char *text, int length)
                else
 #endif
                {
-                       XftTextExtents8(top_level->display,
+                       xftTextExtents8(top_level->display,
                                get_xft_struct(font),
                                (const XftChar8 *)text,
                                length,
@@ -2845,26 +2931,6 @@ int BC_WindowBase::get_single_text_width(int font, const char *text, int length)
        }
 }
 
-int BC_WindowBase::get_single_text_width(int font, const wchar_t *text, int length)
-{
-#ifdef HAVE_XFT
-       if(get_resources()->use_xft && get_xft_struct(font)) {
-               XGlyphInfo extents;
-
-               XftTextExtents32(top_level->display, get_xft_struct(font),
-                       (const FcChar32*)text, length, &extents);
-               return extents.xOff;
-       }
-#endif
-       if(!get_font_struct(font)) return 0;
-       XChar2b xtext[length], *xp = xtext;
-       for( int i=0; i<length; ++i,++xp ) {
-               xp->byte1 = (unsigned char) (text[i] >> 8);
-               xp->byte2 = (unsigned char) (text[i] & 0xff);
-       }
-       return XTextWidth16(get_font_struct(font), xtext, length);
-}
-
 int BC_WindowBase::get_text_width(int font, const char *text, int length)
 {
        int i, j, w = 0, line_w = 0;
@@ -3314,33 +3380,51 @@ 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 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 BC_WindowBase::get_w()
+int BC_WindowBase::grab_event_count()
 {
-       return w;
+       int result = 0;
+#ifndef SINGLE_THREAD
+       result = grab_active->get_event_count();
+#endif
+       return result;
 }
-
-int BC_WindowBase::get_h()
+int BC_WindowBase::grab_buttons()
 {
-       return h;
+       XSync(top_level->display, False);
+       if( XGrabButton(top_level->display, AnyButton, AnyModifier,
+                       top_level->rootwin, True, ButtonPressMask | ButtonReleaseMask,
+                       GrabModeAsync, GrabModeSync, None, None) == GrabSuccess ) {
+               set_active_subwindow(this);
+               return 0;
+       }
+       return 1;
 }
-
-int BC_WindowBase::get_x()
+void BC_WindowBase::ungrab_buttons()
 {
-       return x;
+       XUngrabButton(top_level->display, AnyButton, AnyModifier, top_level->rootwin);
+       set_active_subwindow(0);
+       unhide_cursor();
 }
-
-int BC_WindowBase::get_y()
+void BC_WindowBase::grab_cursor()
 {
-       return y;
+       Cursor cursor_grab = get_cursor_struct(GRABBED_CURSOR);
+       XGrabPointer(top_level->display, top_level->rootwin, True,
+               PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
+               GrabModeAsync, GrabModeAsync, None, cursor_grab, CurrentTime);
+}
+void BC_WindowBase::ungrab_cursor()
+{
+       XUngrabPointer(top_level->display, CurrentTime);
 }
 
 // for get_root_w/h
@@ -3376,6 +3460,8 @@ BC_WindowBase::get_xinerama_info(int screen)
                return 0;
        }
        int top_x = get_x(), top_y = get_y();
+       if(  BC_DisplayInfo::left_border >= 0 ) top_x +=  BC_DisplayInfo::left_border;
+       if(  BC_DisplayInfo::top_border >= 0 ) top_y +=  BC_DisplayInfo::top_border;
        for( int i=0; i<xinerama_screens; ++i ) {
                int scr_y = top_y - xinerama_info[i].y_org;
                if( scr_y < 0 || scr_y >= xinerama_info[i].height ) continue;
@@ -3386,6 +3472,38 @@ BC_WindowBase::get_xinerama_info(int screen)
        return 0;
 }
 
+void BC_WindowBase::get_fullscreen_geometry(int &wx, int &wy, int &ww, int &wh)
+{
+       XineramaScreenInfo *info = top_level->get_xinerama_info(-1);
+       if( info ) {
+               wx = info->x_org;  wy = info->y_org;
+               ww = info->width;  wh = info->height;
+       }
+       else {
+               wx = get_screen_x(0, -1);
+               wy = get_screen_y(0, -1);
+               int scr_w0 = get_screen_w(0, 0);
+               int root_w = get_root_w(0);
+               int root_h = get_root_h(0);
+               if( root_w > scr_w0 ) { // multi-headed
+                       if( wx >= scr_w0 ) {
+                               // assumes right side is the big one
+                               ww = root_w - scr_w0;
+                               wh = root_h;
+                       }
+                       else {
+                               // use same aspect ratio to compute left height
+                               ww = scr_w0;
+                               wh = (w*root_h) / (root_w-scr_w0);
+                       }
+               }
+               else {
+                       ww = root_w;
+                       wh = root_h;
+               }
+       }
+}
+
 int BC_WindowBase::get_screen_x(int lock_display, int screen)
 {
        int result = -1;
@@ -3543,13 +3661,21 @@ int BC_WindowBase::deactivate()
 {
        if(window_type == MAIN_WINDOW)
        {
-               if(top_level->active_menubar) top_level->active_menubar->deactivate();
-               if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
-               if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
+               if( top_level->active_menubar ) {
+                       top_level->active_menubar->deactivate();
+                       top_level->active_menubar = 0;
+               }
+               if( top_level->active_popup_menu ) {
+                       top_level->active_popup_menu->deactivate();
+                       top_level->active_popup_menu = 0;
+               }
+               if( top_level->active_subwindow ) {
+                       top_level->active_subwindow->deactivate();
+                       top_level->active_subwindow = 0;
+               }
+               if( top_level->motion_events && top_level->last_motion_win == this->win )
+                       top_level->motion_events = 0;
 
-               top_level->active_menubar = 0;
-               top_level->active_popup_menu = 0;
-               top_level->active_subwindow = 0;
        }
        return 0;
 }
@@ -3653,13 +3779,45 @@ BC_Clipboard* BC_WindowBase::get_clipboard()
 #endif
 }
 
-void BC_WindowBase::get_relative_cursor_xy(int &x, int &y, int lock_window)
+Atom BC_WindowBase::to_clipboard(const char *data, long len, int clipboard_num)
+{
+       return get_clipboard()->to_clipboard(this, data, len, clipboard_num);
+}
+
+long BC_WindowBase::from_clipboard(char *data, long maxlen, int clipboard_num)
+{
+       return get_clipboard()->from_clipboard(data, maxlen, clipboard_num);
+}
+
+long BC_WindowBase::clipboard_len(int clipboard_num)
+{
+       return get_clipboard()->clipboard_len(clipboard_num);
+}
+
+int BC_WindowBase::do_selection_clear(Window win)
+{
+       top_level->event_win = win;
+       return dispatch_selection_clear();
+}
+
+int BC_WindowBase::dispatch_selection_clear()
+{
+       int result = 0;
+       for( int i=0; i<subwindows->total && !result; ++i )
+               result = subwindows->values[i]->dispatch_selection_clear();
+       if( !result )
+               result = selection_clear_event();
+       return result;
+}
+
+
+void BC_WindowBase::get_relative_cursor(int &x, int &y, int lock_window)
 {
        int abs_x, abs_y, win_x, win_y;
        unsigned int temp_mask;
        Window temp_win;
 
-       if(lock_window) this->lock_window("BC_WindowBase::get_relative_cursor_xy");
+       if(lock_window) this->lock_window("BC_WindowBase::get_relative_cursor");
        XQueryPointer(top_level->display, top_level->win,
           &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
           &temp_mask);
@@ -3671,23 +3829,23 @@ void BC_WindowBase::get_relative_cursor_xy(int &x, int &y, int lock_window)
 int BC_WindowBase::get_relative_cursor_x(int lock_window)
 {
        int x, y;
-       get_relative_cursor_xy(x, y, lock_window);
+       get_relative_cursor(x, y, lock_window);
        return x;
 }
 int BC_WindowBase::get_relative_cursor_y(int lock_window)
 {
        int x, y;
-       get_relative_cursor_xy(x, y, lock_window);
+       get_relative_cursor(x, y, lock_window);
        return y;
 }
 
-void BC_WindowBase::get_abs_cursor_xy(int &abs_x, int &abs_y, int lock_window)
+void BC_WindowBase::get_abs_cursor(int &abs_x, int &abs_y, int lock_window)
 {
        int win_x, win_y;
        unsigned int temp_mask;
        Window temp_win;
 
-       if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_xy");
+       if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor");
        XQueryPointer(top_level->display, top_level->win,
                &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
                &temp_mask);
@@ -3696,20 +3854,20 @@ void BC_WindowBase::get_abs_cursor_xy(int &abs_x, int &abs_y, int lock_window)
 int BC_WindowBase::get_abs_cursor_x(int lock_window)
 {
        int abs_x, abs_y;
-       get_abs_cursor_xy(abs_x, abs_y, lock_window);
+       get_abs_cursor(abs_x, abs_y, lock_window);
        return abs_x;
 }
 int BC_WindowBase::get_abs_cursor_y(int lock_window)
 {
        int abs_x, abs_y;
-       get_abs_cursor_xy(abs_x, abs_y, lock_window);
+       get_abs_cursor(abs_x, abs_y, lock_window);
        return abs_y;
 }
 
-void BC_WindowBase::get_pop_cursor_xy(int &px, int &py, int lock_window)
+void BC_WindowBase::get_pop_cursor(int &px, int &py, int lock_window)
 {
        int margin = 100;
-       get_abs_cursor_xy(px, py, lock_window);
+       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;
@@ -3720,13 +3878,13 @@ void BC_WindowBase::get_pop_cursor_xy(int &px, int &py, int lock_window)
 int BC_WindowBase::get_pop_cursor_x(int lock_window)
 {
        int px, py;
-       get_pop_cursor_xy(px, py, lock_window);
+       get_pop_cursor(px, py, lock_window);
        return px;
 }
 int BC_WindowBase::get_pop_cursor_y(int lock_window)
 {
        int px, py;
-       get_pop_cursor_xy(px, py, lock_window);
+       get_pop_cursor(px, py, lock_window);
        return py;
 }
 
@@ -3744,27 +3902,34 @@ int BC_WindowBase::match_window(Window win)
 
 int BC_WindowBase::get_cursor_over_window()
 {
-       if(top_level != this) return top_level->get_cursor_over_window();
-
        int abs_x, abs_y, win_x, win_y;
-       unsigned int temp_mask;
+       unsigned int mask_return;
        Window root_return, child_return;
 
-       int ret = XQueryPointer(display, win,
+       int ret = XQueryPointer(top_level->display, top_level->rootwin,
                &root_return, &child_return, &abs_x, &abs_y,
-               &win_x, &win_y, &temp_mask);
-//printf("BC_WindowBase::get_cursor_over_window %d %s 0x%x %d 0x%x\n",
-//  __LINE__, title, win, ret, child_return);
-
-       int result = !ret || child_return == None ? 0 :
-               match_window(child_return);
-       return result;
+               &win_x, &win_y, &mask_return);
+       if( ret && child_return == None ) ret = 0;
+       if( ret && win != child_return )
+               ret = top_level->match_window(child_return);
+// query pointer can return a window manager window with this top_level as a child
+//  for kde this can be two levels deep
+       unsigned int nchildren_return = 0;
+       Window parent_return, *children_return = 0;
+       Window top_win = top_level->win;
+       while( !ret && top_win != top_level->rootwin && top_win != root_return &&
+               XQueryTree(top_level->display, top_win, &root_return,
+                       &parent_return, &children_return, &nchildren_return) ) {
+               if( children_return ) XFree(children_return);
+               if( (top_win=parent_return) == child_return ) ret = 1;
+       }
+       return ret;
 }
 
 int BC_WindowBase::cursor_above()
 {
        int rx, ry;
-       get_relative_cursor_xy(rx, ry);
+       get_relative_cursor(rx, ry);
        return rx < 0 || rx >= get_w() ||
                ry < 0 || ry >= get_h() ? 0 : 1;
 }
@@ -4048,39 +4213,30 @@ void BC_WindowBase::put_title(const char *text)
        *cp = 0;
 }
 
-void BC_WindowBase::set_title(const char *text)
-{
-       put_title(_(text));
-
-       char *txlist[2];
-       txlist[0] = this->title;
-       txlist[1] = 0;
-
-       XTextProperty titleprop;
-       XmbTextListToTextProperty(top_level->display, txlist, 1,
-               XStdICCTextStyle, &titleprop);
-       XSetWMName(top_level->display, top_level->win, &titleprop);
-       XSetWMIconName(top_level->display, top_level->win, &titleprop);
-       XFree(titleprop.value);
-
-       flush();
-}
-
-void BC_WindowBase::set_utf8title(const char *text)
-{
-       XTextProperty titleprop;
-       char *txlist[2];
-
-       strcpy(this->title, text);
-       txlist[0] = this->title;
-       txlist[1] = 0;
-
-       Xutf8TextListToTextProperty(top_level->display, txlist,  1,
-               XUTF8StringStyle, &titleprop);
-       XSetWMName(top_level->display, top_level->win, &titleprop);
-       XSetWMIconName(top_level->display, top_level->win, &titleprop);
-       XFree(titleprop.value);
-
+void BC_WindowBase::set_title(const char *text, int utf8)
+{
+// utf8>0: wm + net_wm, utf8=0: wm only,  utf<0: net_wm only
+       put_title(text);
+       const unsigned char *wm_title = (const unsigned char *)title;
+       int title_len = strlen((const char *)title);
+       if( utf8 >= 0 ) {
+               Atom xa_wm_name = XA_WM_NAME;
+               Atom xa_icon_name = XA_WM_ICON_NAME;
+               Atom xa_string = XA_STRING;
+               XChangeProperty(display, win, xa_wm_name, xa_string, 8,
+                               PropModeReplace, wm_title, title_len);
+               XChangeProperty(display, win, xa_icon_name, xa_string, 8,
+                               PropModeReplace, wm_title, title_len);
+       }
+       if( utf8 != 0 ) {
+               Atom xa_net_wm_name = XInternAtom(display, "_NET_WM_NAME", True);
+               Atom xa_net_icon_name = XInternAtom(display, "_NET_WM_ICON_NAME", True);
+               Atom xa_utf8_string = XInternAtom(display, "UTF8_STRING", True);
+               XChangeProperty(display, win, xa_net_wm_name, xa_utf8_string, 8,
+                                       PropModeReplace, wm_title, title_len);
+               XChangeProperty(display, win, xa_net_icon_name, xa_utf8_string, 8,
+                                       PropModeReplace, wm_title, title_len);
+       }
        flush();
 }
 
@@ -4170,6 +4326,7 @@ int BC_WindowBase::load_defaults(BC_Hash *defaults)
        resources->filebox_columnwidth[1] = defaults->get("FILEBOX_WIDTH1", resources->filebox_columnwidth[1]);
        resources->filebox_columnwidth[2] = defaults->get("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
        resources->filebox_columnwidth[3] = defaults->get("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
+       resources->filebox_size_format = defaults->get("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
        defaults->get("FILEBOX_FILTER", resources->filebox_filter);
        return 0;
 }
@@ -4197,6 +4354,7 @@ int BC_WindowBase::save_defaults(BC_Hash *defaults)
        defaults->update("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
        defaults->update("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
        defaults->update("FILEBOX_FILTER", resources->filebox_filter);
+       defaults->update("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
        return 0;
 }
 
@@ -4376,6 +4534,20 @@ void BC_WindowBase::dequeue_events(Window win)
        event_lock->unlock();
 }
 
+int BC_WindowBase::resend_event(BC_WindowBase *window)
+{
+       if( resend_event_window ) return 1;
+       resend_event_window = window;
+       return 0;
+}
+
+#else
+
+int BC_WindowBase::resend_event(BC_WindowBase *window)
+{
+       return 1;
+}
+
 #endif // SINGLE_THREAD
 
 int BC_WindowBase::get_id()
@@ -4405,3 +4577,11 @@ void BC_WindowBase::flicker(int n, int ms)
        set_opaque();
 }
 
+void BC_WindowBase::focus()
+{
+       XWindowAttributes xwa;
+       XGetWindowAttributes(top_level->display, top_level->win, &xwa);
+       if( xwa.map_state == IsViewable )
+               XSetInputFocus(top_level->display, top_level->win, RevertToParent, CurrentTime);
+}
+