add BC_SCALE env var for hi def monitors, cleanup theme data
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcwindowbase.C
index f9e49e22aa897e2059dd1973cbf04885298a68b5..ad25943b3ae97e540d83c0dc06e33248d46f37e4 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;
-
 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;
@@ -566,9 +572,8 @@ 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();
@@ -729,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();
@@ -887,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;
 
@@ -930,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();
@@ -960,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;
 
@@ -1084,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:
@@ -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);
 
@@ -3334,6 +3320,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;
@@ -3861,13 +3864,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)
@@ -4052,6 +4055,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);
@@ -4123,21 +4131,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)
@@ -4357,12 +4359,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;
@@ -4374,14 +4372,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());
        }
 }
@@ -4397,10 +4389,6 @@ 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)
 {