colorpicker upgrades, titler fixes
[goodguy/history.git] / cinelerra-5.1 / guicast / bcwindowbase.C
index c54685a41070cb335d2c2989badacf69202ce4c3..823d81aa609b18099724ca341cd2d24d2e876dfd 100644 (file)
@@ -53,6 +53,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <wchar.h>
+#include <typeinfo>
 
 #include <X11/extensions/Xinerama.h>
 #include <X11/extensions/Xvlib.h>
@@ -112,17 +113,23 @@ BC_WindowBase::~BC_WindowBase()
        {
 // stop event input
                XSelectInput(top_level->display, this->win, 0);
-               motion_events = resize_events = translation_events = 0;
+               XSync(top_level->display,0);
 #ifndef SINGLE_THREAD
                top_level->dequeue_events(win);
 #endif
+// drop active window refs to this
                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;
+// drop motion window refs to this
+               if(top_level->motion_events && top_level->last_motion_win == this->win)
+                       top_level->motion_events = 0;
+
 // Remove pointer from parent window to this
                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);
@@ -249,6 +256,7 @@ int BC_WindowBase::initialize()
        done = 0;
        done_set = 0;
        window_running = 0;
+       display_lock_owner = 0;
        test_keypress = 0;
        keys_return[0] = 0;
        is_deleting = 0;
@@ -282,6 +290,8 @@ int BC_WindowBase::initialize()
        event_win = 0;
        last_motion_win = 0;
        key_pressed = 0;
+       active_grab = 0;
+       grab_active = 0;
        active_menubar = 0;
        active_popup_menu = 0;
        active_subwindow = 0;
@@ -953,7 +963,10 @@ locking_message = event->xclient.message_type;
 //   event_names[event->type] : "Unknown");
 //}
 
-
+       if( active_grab && active_grab->grab_event(event) ) {
+               unlock_window();
+               return 0;
+       }
 
 
        switch(event->type) {
@@ -1858,6 +1871,10 @@ int BC_WindowBase::set_tooltip(const char *text)
        }
        return 0;
 }
+void BC_WindowBase::set_tooltip_done(int v)
+{
+       tooltip_done = v;
+}
 
 // signal the event handler to repeat
 int BC_WindowBase::set_repeat(int64_t duration)
@@ -2015,7 +2032,7 @@ void BC_WindowBase::init_cursors()
        hourglass_cursor = XCreateFontCursor(display, XC_watch);
 
 
-       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);
@@ -2025,6 +2042,49 @@ void BC_WindowBase::init_cursors()
                pixmap_bottom, pixmap_bottom, &black, &black, 0, 0);
 //     XDefineCursor(display, win, transparent_cursor);
        XFreePixmap(display, pixmap_bottom);
+
+       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
+       grabbed_cursor = XCreatePixmapCursor(display, img_xpm,msk_xpm, &fc,&bc, iw2,ih2);
+       XFreePixmap(display, img_xpm);
+       XFreePixmap(display, msk_xpm);
 }
 
 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
@@ -2815,7 +2875,7 @@ int BC_WindowBase::get_single_text_width(int font, const char *text, int length)
        if(get_resources()->use_fontset && top_level->get_fontset(font))
                return XmbTextEscapement(top_level->get_fontset(font), text, length);
        else
-       if(get_font_struct(font)) 
+       if(get_font_struct(font))
                return XTextWidth(get_font_struct(font), text, length);
        else
        {
@@ -2884,27 +2944,21 @@ int BC_WindowBase::get_text_width(int font, const char *text, int length)
 
 int BC_WindowBase::get_text_width(int font, const wchar_t *text, int length)
 {
-       int i, j, w = 0, line_w = 0;
-
-       if(length < 0) length = wcslen(text);
+       int i, j, w = 0;
+       if( length < 0 ) length = wcslen(text);
 
-       for(i = 0, j = 0; i <= length; i++)
-       {
-               line_w = 0;
-               if(text[i] == '\n')
-               {
-                       line_w = get_single_text_width(font, &text[j], i - j);
-                       j = i + 1;
+       for( i=j=0; i<length && text[i]; ++i ) {
+               if( text[i] != '\n' ) continue;
+               if( i > j ) {
+                       int lw = get_single_text_width(font, &text[j], i-j);
+                       if( w < lw ) w = lw;
                }
-               else
-               if(text[i] == 0)
-                       line_w = get_single_text_width(font, &text[j], length - j);
-
-               if(line_w > w) w = line_w;
+               j = i + 1;
+       }
+       if( j < length ) {
+               int lw = get_single_text_width(font, &text[j], length-j);
+               if( w < lw ) w = lw;
        }
-
-       if(i > length && w == 0)
-               w = get_single_text_width(font, text, length);
 
        return w;
 }
@@ -3288,9 +3342,9 @@ void BC_WindowBase::set_done(int return_value)
                ptr->message_type = SetDoneXAtom;
                ptr->format = 32;
                this->return_value = return_value;
-// May lock up here because XSendEvent doesn't work too well 
+// May lock up here because XSendEvent doesn't work too well
 // asynchronous with XNextEvent.
-// This causes BC_WindowEvents to forward a copy of the event to run_window where 
+// This causes BC_WindowEvents to forward a copy of the event to run_window where
 // it is deleted.
 // Deletion of event_thread is done at the end of BC_WindowBase::run_window() - by calling the destructor
                put_event(event);
@@ -3304,6 +3358,46 @@ void BC_WindowBase::close(int return_value)
        set_done(return_value);
 }
 
+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::grab_buttons()
+{
+       XSync(top_level->display, False);
+       if( XGrabButton(top_level->display, AnyButton, AnyModifier,
+                       top_level->rootwin, True, ButtonPressMask | ButtonReleaseMask,
+                       GrabModeAsync, GrabModeSync, None, grabbed_cursor) == GrabSuccess ) {
+               set_active_subwindow(this);
+               return 0;
+       }
+       return 1;
+}
+void BC_WindowBase::ungrab_buttons()
+{
+       XUngrabButton(top_level->display, AnyButton, AnyModifier, top_level->rootwin);
+       set_active_subwindow(0);
+       unhide_cursor();
+}
+void BC_WindowBase::grab_cursor()
+{
+       XDefineCursor(top_level->display, top_level->rootwin, grabbed_cursor);
+}
+void BC_WindowBase::ungrab_cursor()
+{
+       XUndefineCursor(top_level->display, top_level->rootwin);
+}
+
 int BC_WindowBase::get_w()
 {
        return w;
@@ -3524,13 +3618,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;
 }
@@ -3634,66 +3736,83 @@ BC_Clipboard* BC_WindowBase::get_clipboard()
 #endif
 }
 
-int BC_WindowBase::get_relative_cursor_x()
+void BC_WindowBase::get_relative_cursor_xy(int &x, int &y, int lock_window)
 {
-       int abs_x, abs_y, x, y, win_x, win_y;
+       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");
        XQueryPointer(top_level->display, top_level->win,
           &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
           &temp_mask);
 
        XTranslateCoordinates(top_level->display, top_level->rootwin,
           win, abs_x, abs_y, &x, &y, &temp_win);
-
+       if(lock_window) this->unlock_window();
+}
+int BC_WindowBase::get_relative_cursor_x(int lock_window)
+{
+       int x, y;
+       get_relative_cursor_xy(x, y, lock_window);
        return x;
 }
-
-int BC_WindowBase::get_relative_cursor_y()
+int BC_WindowBase::get_relative_cursor_y(int lock_window)
 {
-       int abs_x, abs_y, x, 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);
-
-       XTranslateCoordinates(top_level->display,
-          top_level->rootwin, win, abs_x, abs_y, &x, &y, &temp_win);
-
+       int x, y;
+       get_relative_cursor_xy(x, y, lock_window);
        return y;
 }
 
-int BC_WindowBase::get_abs_cursor_x(int lock_window)
+void BC_WindowBase::get_abs_cursor_xy(int &abs_x, int &abs_y, int lock_window)
 {
-       int abs_x, abs_y, win_x, win_y;
+       int win_x, win_y;
        unsigned int temp_mask;
        Window temp_win;
 
-       if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
+       if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_xy");
        XQueryPointer(top_level->display, top_level->win,
                &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
                &temp_mask);
        if(lock_window) this->unlock_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);
        return abs_x;
 }
-
 int BC_WindowBase::get_abs_cursor_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_abs_cursor_y");
-       XQueryPointer(top_level->display, top_level->win,
-               &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
-               &temp_mask);
-       if(lock_window) this->unlock_window();
+       int abs_x, abs_y;
+       get_abs_cursor_xy(abs_x, abs_y, lock_window);
        return abs_y;
 }
 
+void BC_WindowBase::get_pop_cursor_xy(int &px, int &py, int lock_window)
+{
+       int margin = 100;
+       get_abs_cursor_xy(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 > wd ) px = wd;
+       int ht = get_screen_h(lock_window,-1) - margin;
+       if( py > ht ) py = ht;
+}
+int BC_WindowBase::get_pop_cursor_x(int lock_window)
+{
+       int px, py;
+       get_pop_cursor_xy(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);
+       return py;
+}
+
 int BC_WindowBase::match_window(Window win)
 {
        if (this->win == win) return 1;
@@ -3727,11 +3846,10 @@ int BC_WindowBase::get_cursor_over_window()
 
 int BC_WindowBase::cursor_above()
 {
-       int rx = get_relative_cursor_x();
-       if( rx < 0 || rx >= get_w() ) return 0;
-       int ry = get_relative_cursor_y();
-       if( ry < 0 || ry >= get_h() ) return 0;
-       return 1;
+       int rx, ry;
+       get_relative_cursor_xy(rx, ry);
+       return rx < 0 || rx >= get_w() ||
+               ry < 0 || ry >= get_h() ? 0 : 1;
 }
 
 int BC_WindowBase::get_drag_x()
@@ -3756,13 +3874,15 @@ int BC_WindowBase::get_cursor_y()
 
 int BC_WindowBase::dump_windows()
 {
-       printf("\tBC_WindowBase::dump_windows window=%p win=%p\n",
-               this, (void*)this->win);
+       printf("\tBC_WindowBase::dump_windows window=%p win=%p '%s', %dx%d+%d+%d %s\n",
+               this, (void*)this->win, title, w,h,x,y, typeid(*this).name());
        for(int i = 0; i < subwindows->size(); i++)
                subwindows->get(i)->dump_windows();
-       for(int i = 0; i < popups.size(); i++)
-               printf("\tBC_WindowBase::dump_windows popup=%p win=%p\n",
-                       popups.get(i), (void*)popups.get(i)->win);
+       for(int i = 0; i < popups.size(); i++) {
+               BC_WindowBase *p = popups[i];
+               printf("\tBC_WindowBase::dump_windows popup=%p win=%p '%s', %dx%d+%d+%d %s\n",
+                       p, (void*)p->win, p->title, p->w,p->h,p->x,p->y, typeid(*p).name());
+       }
        return 0;
 }
 
@@ -4356,3 +4476,15 @@ BC_Pixmap *BC_WindowBase::create_pixmap(VFrame *vframe)
 }
 
 
+void BC_WindowBase::flicker(int n, int ms)
+{
+       int color = get_bg_color();
+       for( int i=2*n; --i>=0; ) {
+               set_inverse();          set_bg_color(WHITE);
+               clear_box(0,0, w,h);    flash(1);
+               sync_display();         Timer::delay(ms);
+       }
+       set_bg_color(color);
+       set_opaque();
+}
+