#include <string.h>
#include <unistd.h>
#include <wchar.h>
+#include <typeinfo>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xvlib.h>
#endif
#ifdef HAVE_LIBXXF86VM
- if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
- {
- restore_vm();
- }
+ if(window_type == VIDMODE_SCALED_WINDOW && vm_switched) {
+ restore_vm();
+ }
#endif
+ is_deleting = 1;
hide_tooltip();
if(window_type != MAIN_WINDOW)
{
+// stop event input
+ XSelectInput(top_level->display, this->win, 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_grab == this) top_level->active_grab = 0;
if(top_level->active_menubar == this) top_level->active_menubar = 0;
if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
+// 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(icon_window) delete icon_window;
- if(window_type == POPUP_WINDOW) parent_window->remove_popup(this);
+ if(window_type == POPUP_WINDOW)
+ parent_window->remove_popup(this);
// Delete the subwindows
- is_deleting = 1;
if(subwindows)
{
while(subwindows->total)
}
#endif
finit_im();
-
flush();
sync_display();
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.
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;
active_menubar = 0;
active_popup_menu = 0;
active_subwindow = 0;
glx_win = 0;
#endif
+ flash_enabled = 1;
+ win = 0;
return 0;
}
}
-
-
-
draw_background(0, 0, this->w, this->h);
flash(-1, -1, -1, -1, 0);
return ret;
}
-pthread_t locking_task = -1;
+pthread_t locking_task = (pthread_t)-1L;
int locking_event = -1;
int locking_message = -1;
// event_names[event->type] : "Unknown");
//}
-
+ if( active_grab && active_grab->grab_event(event) ) {
+ unlock_window();
+ return 0;
+ }
switch(event->type) {
// 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;
// return top_level->next_repeat_id++;
// }
+XEvent *BC_WindowBase::new_xevent()
+{
+ XEvent *event = new XEvent;
+ memset(event, 0, sizeof(*event));
+ return event;
+}
#ifndef SINGLE_THREAD
int BC_WindowBase::arm_repeat(int64_t duration)
{
- XEvent *event = new XEvent;
+ XEvent *event = new_xevent();
XClientMessageEvent *ptr = (XClientMessageEvent*)event;
ptr->type = ClientMessage;
ptr->message_type = RepeaterXAtom;
int BC_WindowBase::send_custom_xatom(xatom_event *event)
{
- XEvent *myevent = new XEvent;
+#ifndef SINGLE_THREAD
+ XEvent *myevent = new_xevent();
XClientMessageEvent *ptr = (XClientMessageEvent*)myevent;
ptr->type = ClientMessage;
ptr->message_type = event->message_type;
ptr->data.l[4] = event->data.l[4];
put_event(myevent);
+#endif
return 0;
}
int BC_WindowBase::get_atoms()
{
- SetDoneXAtom = create_xatom("BC_REPEAT_EVENT");
- RepeaterXAtom = create_xatom("BC_CLOSE_EVENT");
- DelWinXAtom = create_xatom("WM_DELETE_WINDOW");
- ProtoXAtom = create_xatom("WM_PROTOCOLS");
SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
+ DestroyAtom = XInternAtom(display, "BC_DESTROY_WINDOW", False);
DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
if( (ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False)) != 0 )
XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32,
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_text_width(int font, const wchar_t *text, int length)
{
- int i, j, w = 0, line_w = 0;
+ int i, j, w = 0;
+ if( length < 0 ) length = wcslen(text);
- 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);
#else // SINGLE_THREAD
init_wait();
if( !event_thread ) return;
- XEvent *event = new XEvent;
+ XEvent *event = new_xevent();
XClientMessageEvent *ptr = (XClientMessageEvent*)event;
event->type = ClientMessage;
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::grab(BC_WindowBase *window)
+{
+ if( window->active_grab && this != window->active_grab ) return 0;
+ window->active_grab = this;
+ return 1;
+}
+int BC_WindowBase::ungrab(BC_WindowBase *window)
+{
+ if( window->active_grab && this != window->active_grab ) return 0;
+ window->active_grab = 0;
+ return 1;
+}
+
int BC_WindowBase::get_w()
{
return w;
{
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()
+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;
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);
}
void BC_WindowBase::put_title(const char *text)
{
- if( BC_Resources::locale_utf8 ) {
- char *bp=this->title, *ep = bp+sizeof(this->title)-1;
- for( const char *cp=text; *cp!=0 && bp<ep; ) {
- if( *cp < 0 ) { do { *bp++ = *cp++; } while( *cp < 0 ); continue; }
- if( *cp < ' ' ) { *bp++ = ' '; ++cp; continue; }
- *bp++ = *cp++;
- }
- *bp = 0;
- }
- else
- strcpy(this->title, text);
+ char *cp = this->title, *ep = cp+sizeof(this->title)-1;
+ for( const unsigned char *bp = (const unsigned char *)text; *bp && cp<ep; ++bp )
+ *cp++ = *bp >= ' ' ? *bp : ' ';
+ *cp = 0;
}
void BC_WindowBase::set_title(const char *text)
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,
event_condition->unlock();
}
+void BC_WindowBase::dequeue_events(Window win)
+{
+ event_lock->lock("BC_WindowBase::dequeue_events");
+
+ int out = 0, total = common_events.size();
+ for( int in=0; in<total; ++in ) {
+ if( common_events[in]->xany.window == win ) continue;
+ common_events[out++] = common_events[in];
+ }
+ common_events.total = out;
+
+ event_lock->unlock();
+}
+
#endif // SINGLE_THREAD
int BC_WindowBase::get_id()
}
+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();
+}
+