X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fguicast%2Fbcwindowbase.C;h=fae98cb186b9315572190fa6abd940e3d2f84a0b;hp=8322837d3302ef1f39378a45bc1225d417007518;hb=2264753cd1968c95829dc01d3d9c394eacff34dc;hpb=b0adaf11e855fd84af935d879848467a957d6c67 diff --git a/cinelerra-5.1/guicast/bcwindowbase.C b/cinelerra-5.1/guicast/bcwindowbase.C index 8322837d..fae98cb1 100644 --- a/cinelerra-5.1/guicast/bcwindowbase.C +++ b/cinelerra-5.1/guicast/bcwindowbase.C @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -112,16 +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); @@ -173,9 +181,10 @@ BC_WindowBase::~BC_WindowBase() 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 +// past bug in X caused XRenderExtensionInfo to be damaged +// if this is done here. left to be done in XCloseDisplay by Xlib. +// works in more modern systems, and needed for leak testing. +#if defined(HAVE_XFT) && defined(VALGRIND) static void *BC_WindowBase::*xft_font[] = { &BC_WindowBase::smallfont_xft, &BC_WindowBase::mediumfont_xft, @@ -198,6 +207,8 @@ BC_WindowBase::~BC_WindowBase() XFree(xinerama_info); xinerama_screens = 0; xinerama_info = 0; + if( xvideo_port_id >= 0 ) + XvUngrabPort(display, xvideo_port_id, CurrentTime); unlock_window(); // Can't close display if another thread is waiting for events. @@ -246,6 +257,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; @@ -279,6 +291,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; @@ -289,7 +303,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; @@ -343,6 +356,7 @@ int BC_WindowBase::initialize() glx_win = 0; #endif + flash_enabled = 1; win = 0; return 0; } @@ -630,9 +644,6 @@ int BC_WindowBase::create_window(BC_WindowBase *parent_window, } - - - draw_background(0, 0, this->w, this->h); flash(-1, -1, -1, -1, 0); @@ -673,6 +684,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; } @@ -887,7 +907,7 @@ int BC_WindowBase::keysym_lookup(XEvent *event) return ret; } -pthread_t locking_task = -1; +pthread_t locking_task = (pthread_t)-1L; int locking_event = -1; int locking_message = -1; @@ -952,8 +972,14 @@ locking_message = event->xclient.message_type; // event_names[event->type] : "Unknown"); //} - - + if( active_grab ) { + unlock_window(); + 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: @@ -1357,32 +1383,40 @@ int BC_WindowBase::dispatch_resize_event(int w, int h) // Can't store new w and h until the event is handles // because bcfilebox depends on the old w and h to // reposition widgets. - if(window_type == MAIN_WINDOW) - { + if( window_type == MAIN_WINDOW ) { + flash_enabled = 0; resize_events = 0; + delete pixmap; pixmap = new BC_Pixmap(this, w, h); - clear_box(0, 0, w, h); } // Propagate to subwindows - for(int i = 0; i < subwindows->total; i++) - { + for(int i = 0; i < subwindows->total; i++) { subwindows->values[i]->dispatch_resize_event(w, h); } // Propagate to user resize_event(w, h); - if(window_type == MAIN_WINDOW) - { + if( window_type == MAIN_WINDOW ) { this->w = w; this->h = h; + dispatch_flash(); + flush(); } return 0; } +int BC_WindowBase::dispatch_flash() +{ + flash_enabled = 1; + for(int i = 0; i < subwindows->total; i++) + subwindows->values[i]->dispatch_flash(); + return flash(0); +} + int BC_WindowBase::dispatch_translation_event() { translation_events = 0; @@ -1749,69 +1783,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_xy(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; } @@ -1849,7 +1868,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) { @@ -1950,6 +1968,7 @@ int BC_WindowBase::recieve_custom_xatoms(xatom_event *event) int BC_WindowBase::send_custom_xatom(xatom_event *event) { +#ifndef SINGLE_THREAD XEvent *myevent = new_xevent(); XClientMessageEvent *ptr = (XClientMessageEvent*)myevent; ptr->type = ClientMessage; @@ -1962,6 +1981,7 @@ int BC_WindowBase::send_custom_xatom(xatom_event *event) ptr->data.l[4] = event->data.l[4]; put_event(myevent); +#endif return 0; } @@ -2002,9 +2022,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); @@ -2165,6 +2185,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>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; @@ -2560,21 +2627,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; } @@ -2804,7 +2872,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 { @@ -2822,26 +2890,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; ibyte1 = (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; @@ -2873,27 +2921,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 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; } @@ -2987,119 +3029,76 @@ void BC_WindowBase::init_wait() int BC_WindowBase::accel_available(int color_model, int lock_it) { - if(window_type != MAIN_WINDOW) + if( window_type != MAIN_WINDOW ) return top_level->accel_available(color_model, lock_it); + if( lock_it ) + lock_window("BC_WindowBase::accel_available"); - int result = 0; - - if(lock_it) lock_window("BC_WindowBase::accel_available"); - switch(color_model) - { - case BC_YUV420P: - result = grab_port_id(this, color_model); - if(result >= 0) - { - xvideo_port_id = result; - result = 1; - } - else - result = 0; - break; - - case BC_YUV422P: - result = 0; - break; + switch(color_model) { + case BC_YUV420P: + grab_port_id(color_model); + break; - case BC_YUV422: -//printf("BC_WindowBase::accel_available 1\n"); - result = grab_port_id(this, color_model); -//printf("BC_WindowBase::accel_available 2 %d\n", result); - if(result >= 0) - { - xvideo_port_id = result; - result = 1; - } - else - result = 0; -//printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id); - break; + case BC_YUV422: + grab_port_id(color_model); + break; - default: - result = 0; - break; + default: + break; } - if(lock_it) unlock_window(); -//printf("BC_WindowBase::accel_available %d %d\n", color_model, result); - return result; + if( lock_it ) + unlock_window(); +//printf("BC_WindowBase::accel_available %d %d\n", color_model, xvideo_port_id); + return xvideo_port_id >= 0 ? 1 : 0; } -int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model) +int BC_WindowBase::grab_port_id(int color_model) { - int numFormats, i, j, k; - unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase; - XvAdaptorInfo *info; - XvImageFormatValues *formats; - int x_color_model; - - if(!get_resources()->use_xvideo) return -1; - -// Translate from color_model to X color model - x_color_model = BC_CModels::bc_to_x(color_model); - -// Only local server is fast enough. - if(!resources.use_shm) return -1; + if( !get_resources()->use_xvideo || // disabled + !get_resources()->use_shm ) // Only local server is fast enough. + return -1; + if( xvideo_port_id >= 0 ) + return xvideo_port_id; -// XV extension is available - if(Success != XvQueryExtension(window->display, &ver, &rev, - &reqBase, &eventBase, &errorBase)) { + unsigned int ver, rev, reqBase, eventBase, errorBase; + if( Success != XvQueryExtension(display, // XV extension is available + &ver, &rev, &reqBase, &eventBase, &errorBase) ) return -1; - } // XV adaptors are available - XvQueryAdaptors(window->display, - DefaultRootWindow(window->display), - &numAdapt, &info); - - if(!numAdapt) { + unsigned int numAdapt = 0; + XvAdaptorInfo *info = 0; + XvQueryAdaptors(display, DefaultRootWindow(display), &numAdapt, &info); + if( !numAdapt ) return -1; - } + +// Translate from color_model to X color model + int x_color_model = BC_CModels::bc_to_x(color_model); // Get adaptor with desired color model - for(i = 0; i < (int)numAdapt && xvideo_port_id == -1; i++) { -/* adaptor supports XvImages */ - if(info[i].type & XvImageMask) - { - formats = XvListImageFormats(window->display, - info[i].base_id, - &numFormats); -// for(j = 0; j < numFormats; j++) -// printf("%08x\n", formats[j].id); - - int numPorts = info[i].num_ports; - for(j = 0; j < (int)numFormats && xvideo_port_id < 0; j++) - { -/* this adaptor supports the desired format */ - if(formats[j].id == x_color_model) - { -/* Try to grab a port */ - for(k = 0; k < numPorts; k++) - { -/* Got a port */ - if(Success == XvGrabPort(top_level->display, - info[i].base_id + k, - CurrentTime)) - { + for( int i = 0; i < (int)numAdapt && xvideo_port_id == -1; i++) { + if( !(info[i].type & XvImageMask) || !info[i].num_ports ) continue; +// adaptor supports XvImages + int numFormats = 0, numPorts = info[i].num_ports; + XvImageFormatValues *formats = + XvListImageFormats(display, info[i].base_id, &numFormats); + if( !formats ) continue; + + for( int j=0; jdisplay, + info[i].base_id+k, CurrentTime) ) { //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id); - xvideo_port_id = info[i].base_id + k; - break; - } - } + xvideo_port_id = info[i].base_id + k; + break; } } - if(formats) XFree(formats); } + XFree(formats); } XvFreeAdaptorInfo(info); @@ -3187,6 +3186,7 @@ BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow) int BC_WindowBase::flash(int x, int y, int w, int h, int flush) { + if( !top_level->flash_enabled ) return 0; //printf("BC_WindowBase::flash %d %d %d %d %d\n", __LINE__, w, h, this->w, this->h); set_opaque(); XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap); @@ -3319,14 +3319,14 @@ 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); - } #endif + } } void BC_WindowBase::close(int return_value) @@ -3335,24 +3335,47 @@ void BC_WindowBase::close(int return_value) set_done(return_value); } -int BC_WindowBase::get_w() +int BC_WindowBase::grab(BC_WindowBase *window) { - return w; + if( window->active_grab && this != window->active_grab ) return 0; + window->active_grab = this; + this->grab_active = window; + return 1; } - -int BC_WindowBase::get_h() +int BC_WindowBase::ungrab(BC_WindowBase *window) { - return h; + if( window->active_grab && this != window->active_grab ) return 0; + window->active_grab = 0; + this->grab_active = 0; + return 1; } - -int BC_WindowBase::get_x() +int BC_WindowBase::grab_buttons() { - return x; + 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_y() +void BC_WindowBase::ungrab_buttons() { - return y; + XUngrabButton(top_level->display, AnyButton, AnyModifier, top_level->rootwin); + set_active_subwindow(0); + unhide_cursor(); +} +void BC_WindowBase::grab_cursor() +{ + 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 @@ -3555,13 +3578,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; } @@ -3665,66 +3696,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; @@ -3758,11 +3806,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() @@ -3787,13 +3834,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; } @@ -3978,6 +4027,7 @@ int BC_WindowBase::reposition_window(int x, int y, int w, int h) { delete pixmap; pixmap = new BC_Pixmap(this, this->w, this->h); + clear_box(0,0, this->w, this->h); // Propagate to menubar for(int i = 0; i < subwindows->total; i++) { @@ -4028,9 +4078,7 @@ void BC_WindowBase::set_background(VFrame *bitmap) { if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap; - bg_pixmap = new BC_Pixmap(this, - bitmap, - PIXMAP_OPAQUE); + bg_pixmap = new BC_Pixmap(this, bitmap, PIXMAP_OPAQUE); shared_bg_pixmap = 0; draw_background(0, 0, w, h); } @@ -4097,10 +4145,7 @@ int BC_WindowBase::get_toggle_drag() int BC_WindowBase::set_icon(VFrame *data) { if(icon_pixmap) delete icon_pixmap; - icon_pixmap = new BC_Pixmap(top_level, - data, - PIXMAP_ALPHA, - 1); + icon_pixmap = new BC_Pixmap(top_level, data, PIXMAP_ALPHA, 1); if(icon_window) delete icon_window; icon_window = new BC_Popup(this, @@ -4391,3 +4436,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(); +} +