#include "bcwindowbase.h"
#include "bcwindowevents.h"
#include "bccmodels.h"
-#include "colors.h"
+#include "bccolors.h"
#include "condition.h"
#include "cursors.h"
#include "bchash.h"
#include <string.h>
#include <unistd.h>
#include <wchar.h>
+#include <typeinfo>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xvlib.h>
{
// 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);
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,
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.
}
else
#endif
+ {
+// _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;
done = 0;
done_set = 0;
window_running = 0;
+ display_lock_owner = 0;
test_keypress = 0;
keys_return[0] = 0;
is_deleting = 0;
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;
+ cursor_entered = 0;
pixmap = 0;
bg_pixmap = 0;
_7segment_pixmaps = 0;
force_tooltip = 0;
// next_repeat_id = 0;
tooltip_popup = 0;
- tooltip_done = 0;
current_font = MEDIUMFONT;
current_color = BLACK;
current_cursor = ARROW_CURSOR;
#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
glx_win = 0;
#endif
+ flash_enabled = 1;
win = 0;
return 0;
}
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;
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
}
-
-
-
draw_background(0, 0, this->w, this->h);
flash(-1, -1, -1, -1, 0);
}
}
}
+
+ 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;
}
// 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:
break;
case LeaveNotify:
+ if( cursor_entered && event->xcrossing.window == win ) {
+ cursor_entered = 0;
+ }
event_win = event->xany.window;
dispatch_cursor_leave();
break;
case EnterNotify:
+ if( !cursor_entered && event->xcrossing.window == win ) {
+ if( !event->xcrossing.focus && get_resources()->grab_input_focus ) {
+ XSetInputFocus(display, win, RevertToParent, CurrentTime);
+ }
+ cursor_entered = 1;
+ }
event_win = event->xany.window;
cursor_x = event->xcrossing.x;
cursor_y = event->xcrossing.y;
dispatch_cursor_enter();
break;
+
default:
break;
}
// 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;
}
-
-
-
-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;
}
}
return 0;
}
-
// signal the event handler to repeat
int BC_WindowBase::set_repeat(int64_t duration)
{
int BC_WindowBase::send_custom_xatom(xatom_event *event)
{
+#ifndef SINGLE_THREAD
XEvent *myevent = new_xevent();
XClientMessageEvent *ptr = (XClientMessageEvent*)myevent;
ptr->type = ClientMessage;
ptr->data.l[4] = event->data.l[4];
put_event(myevent);
+#endif
return 0;
}
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);
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;
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)
{
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;
}
if(!(bigfont_xft =
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] == '-' ?
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);
#endif // HAVE_XFT
}
{
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;
}
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;
}
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;
}
}
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;
#endif
-
-
-
-
-
-
-
int BC_WindowBase::get_current_font()
{
return top_level->current_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;
}
}
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
{
}
}
-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;
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;
}
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; j<numFormats && xvideo_port_id<0; ++j ) {
+ if( formats[j].id != x_color_model ) continue;
+// this adaptor supports the desired format, grab a port
+ for( int k=0; k<numPorts; ++k ) {
+ if( Success == XvGrabPort(top_level->display,
+ 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);
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);
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)
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
{
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;
}
#endif
}
-int BC_WindowBase::get_relative_cursor_x()
+Atom BC_WindowBase::to_clipboard(const char *data, long len, int clipboard_num)
{
- int abs_x, abs_y, x, y, win_x, win_y;
- unsigned int temp_mask;
- Window temp_win;
+ return get_clipboard()->to_clipboard(this, data, len, clipboard_num);
+}
- XQueryPointer(top_level->display, top_level->win,
- &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
- &temp_mask);
+long BC_WindowBase::from_clipboard(char *data, long maxlen, int clipboard_num)
+{
+ return get_clipboard()->from_clipboard(data, maxlen, clipboard_num);
+}
- XTranslateCoordinates(top_level->display, top_level->rootwin,
- win, abs_x, abs_y, &x, &y, &temp_win);
+long BC_WindowBase::clipboard_len(int clipboard_num)
+{
+ return get_clipboard()->clipboard_len(clipboard_num);
+}
- return x;
+int BC_WindowBase::do_selection_clear(Window win)
+{
+ top_level->event_win = win;
+ return dispatch_selection_clear();
}
-int BC_WindowBase::get_relative_cursor_y()
+int BC_WindowBase::dispatch_selection_clear()
{
- int abs_x, abs_y, x, y, win_x, win_y;
+ 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_xy(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");
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);
-
+ 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 lock_window)
+{
+ 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;
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()
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;
}
{
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++)
{
{
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);
}
*cp = 0;
}
-void BC_WindowBase::set_title(const char *text)
+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));
-
- 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);
-
+ 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();
}
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,
}
+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();
+}
+