2 #include "bcclipboard.h"
3 #include "bcdisplayinfo.h"
7 #include "bcpopupmenu.h"
8 #include "bcrepeater.h"
9 #include "bcresources.h"
10 #include "bcsignals.h"
11 #include "bcsubwindow.h"
12 #include "bcsynchronous.h"
14 #include "bcwidgetgrid.h"
15 #include "bcwindowbase.h"
16 #include "bcwindowevents.h"
17 #include "colormodels.h"
19 #include "condition.h"
35 #include <X11/extensions/Xvlib.h>
36 #include <X11/extensions/shape.h>
39 BC_ResizeCall::BC_ResizeCall(int w, int h)
55 BC_Resources BC_WindowBase::resources;
57 Window XGroupLeader = 0;
59 BC_WindowBase::BC_WindowBase()
61 //printf("BC_WindowBase::BC_WindowBase 1\n");
62 BC_WindowBase::initialize();
65 BC_WindowBase::~BC_WindowBase()
67 #ifdef HAVE_LIBXXF86VM
68 if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
75 if(window_type != MAIN_WINDOW)
77 if(top_level->active_menubar == this) top_level->active_menubar = 0;
78 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
79 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
80 // Remove pointer from parent window to this
81 parent_window->subwindows->remove(this);
85 // Delete the subwindows
89 while(subwindows->total)
91 // Subwindow removes its own pointer
92 delete subwindows->values[0];
99 while (widgetgrids->total)
101 delete widgetgrids->last();
102 widgetgrids->remove();
110 // Destroyed in synchronous thread if gl context exists.
112 if(!gl_win_context || !get_resources()->get_synchronous())
114 XDestroyWindow(top_level->display, win);
116 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
117 if(icon_pixmap) delete icon_pixmap;
118 if(temp_bitmap) delete temp_bitmap;
124 if(window_type == MAIN_WINDOW)
126 XFreeGC(display, gc);
129 XftFontClose (display, (XftFont*)largefont_xft);
131 XftFontClose (display, (XftFont*)mediumfont_xft);
133 XftFontClose (display, (XftFont*)smallfont_xft);
136 // Can't close display if another thread is waiting for events.
137 // Synchronous thread must delete display if gl_context exists.
139 if(!gl_win_context || !get_resources()->get_synchronous())
141 XCloseDisplay(display);
142 clipboard->stop_clipboard();
150 // Must be last reference to display.
151 // This only works if it's a MAIN_WINDOW since the display deletion for
152 // a subwindow is not determined by the subwindow.
154 if(gl_win_context && get_resources()->get_synchronous())
156 printf("BC_WindowBase::~BC_WindowBase window deleted but opengl deletion is not\n"
157 "implemented for BC_Pixmap.\n");
158 get_resources()->get_synchronous()->delete_window(this);
162 resize_history.remove_all_objects();
163 common_events.remove_all_objects();
165 delete event_condition;
167 UNSET_ALL_LOCKS(this)
170 int BC_WindowBase::initialize()
188 translation_events = 0;
189 ctrl_mask = shift_mask = alt_mask = 0;
190 cursor_x = cursor_y = button_number = 0;
193 button_time1 = button_time2 = 0;
198 active_popup_menu = 0;
199 active_subwindow = 0;
203 persistant_tooltip = 0;
204 // next_repeat_id = 0;
207 current_font = MEDIUMFONT;
208 current_color = BLACK;
209 current_cursor = ARROW_CURSOR;
212 shared_bg_pixmap = 0;
214 window_type = MAIN_WINDOW;
215 translation_count = 0;
216 x_correction = y_correction = 0;
225 #ifdef HAVE_LIBXXF86VM
231 // Need these right away since put_event is called before run_window sometimes.
232 event_lock = new Mutex("BC_WindowBase::event_lock");
233 event_condition = new Condition(0, "BC_WindowBase::event_condition");
234 cursor_timer = new Timer;
243 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
246 ButtonReleaseMask | \
247 PointerMotionMask | \
251 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
265 BC_Pixmap *bg_pixmap,
268 XSetWindowAttributes attr;
270 XSizeHints size_hints;
273 #ifdef HAVE_LIBXXF86VM
277 id = get_resources()->get_id();
280 get_resources()->create_window_lock->lock("BC_WindowBase::create_window");
282 if(parent_window) top_level = parent_window->top_level;
284 #ifdef HAVE_LIBXXF86VM
285 if(window_type == VIDMODE_SCALED_WINDOW)
286 closest_vm(&vm,&w,&h);
293 this->bg_color = bg_color;
294 this->window_type = window_type;
296 this->private_color = private_color;
297 this->parent_window = parent_window;
298 this->bg_pixmap = bg_pixmap;
299 this->allow_resize = allow_resize;
300 strcpy(this->title, _(title));
301 if(bg_pixmap) shared_bg_pixmap = 1;
303 if(parent_window) top_level = parent_window->top_level;
305 subwindows = new BC_SubWindowList;
306 widgetgrids = new BC_WidgetGridList;
309 if(window_type == MAIN_WINDOW)
312 parent_window = this;
314 // This function must be the first Xlib
315 // function a multi-threaded program calls
319 // get the display connection
320 display = init_display(display_name);
321 // event_display = init_display(display_name);
323 // Fudge window placement
324 root_w = get_root_w(1, 0);
325 root_h = get_root_h(0);
326 if(this->x + this->w > root_w) this->x = root_w - this->w;
327 if(this->y + this->h > root_h) this->y = root_h - this->h;
328 if(this->x < 0) this->x = 0;
329 if(this->y < 0) this->y = 0;
330 screen = DefaultScreen(display);
331 rootwin = RootWindow(display, screen);
334 vis = DefaultVisual(display, screen);
335 default_depth = DefaultDepth(display, screen);
337 client_byte_order = (*(u_int32_t*)"a ") & 0x00000001;
338 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
341 // This must be done before fonts to know if antialiasing is available.
344 if(resources.use_shm < 0) resources.initialize_display(this);
345 x_correction = get_resources()->get_left_border();
346 y_correction = get_resources()->get_top_border();
348 if(this->bg_color == -1)
349 this->bg_color = resources.get_bg_color();
351 // printf("bcwindowbase 1 %s\n", title);
352 // if(window_type == MAIN_WINDOW) sleep(1);
353 // printf("bcwindowbase 10\n");
364 attr.event_mask = DEFAULT_EVENT_MASKS |
365 StructureNotifyMask |
368 attr.background_pixel = get_color(this->bg_color);
369 attr.colormap = cmap;
370 attr.cursor = get_cursor_struct(ARROW_CURSOR);
372 win = XCreateWindow(display,
379 top_level->default_depth,
385 XGetNormalHints(display, win, &size_hints);
387 size_hints.flags = PSize | PMinSize | PMaxSize;
388 size_hints.width = this->w;
389 size_hints.height = this->h;
390 size_hints.min_width = allow_resize ? minw : this->w;
391 size_hints.max_width = allow_resize ? 32767 : this->w;
392 size_hints.min_height = allow_resize ? minh : this->h;
393 size_hints.max_height = allow_resize ? 32767 : this->h;
394 if(x > -BC_INFINITY && x < BC_INFINITY)
396 size_hints.flags |= PPosition;
397 size_hints.x = this->x;
398 size_hints.y = this->y;
401 XSetStandardProperties(display,
411 clipboard = new BC_Clipboard(display_name);
412 clipboard->start_clipboard();
416 Atom ClientLeaderXAtom;
417 if (XGroupLeader == 0)
419 char *instance_name = "cinelerra";
420 char *class_name = "Cinelerra";
421 XClassHint *class_hints = XAllocClassHint();
422 class_hints->res_name = instance_name;
423 class_hints->res_class = class_name;
424 XSetClassHint(top_level->display, win, class_hints);
426 ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
427 XChangeProperty(display,
433 (unsigned char *)&XGroupLeader,
440 #ifdef HAVE_LIBXXF86VM
441 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
448 #ifdef HAVE_LIBXXF86VM
449 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
451 if(window_type == POPUP_WINDOW)
461 attr.event_mask = DEFAULT_EVENT_MASKS |
464 if(this->bg_color == -1)
465 this->bg_color = resources.get_bg_color();
466 attr.background_pixel = top_level->get_color(bg_color);
467 attr.colormap = top_level->cmap;
468 if(top_level->is_hourglass)
469 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
471 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
472 attr.override_redirect = True;
473 attr.save_under = True;
475 win = XCreateWindow(top_level->display,
482 top_level->default_depth,
489 if(window_type == SUB_WINDOW)
494 attr.event_mask = DEFAULT_EVENT_MASKS;
495 attr.background_pixel = top_level->get_color(this->bg_color);
496 if(top_level->is_hourglass)
497 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
499 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
500 win = XCreateWindow(top_level->display,
507 top_level->default_depth,
513 XMapWindow(top_level->display, win);
516 // Create pixmap for all windows
517 pixmap = new BC_Pixmap(this, this->w, this->h);
520 // Set up options for main window
521 if(window_type == MAIN_WINDOW)
523 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
525 this->bg_pixmap = new BC_Pixmap(this,
526 get_resources()->bg_image,
530 if(!hidden) show_window();
537 draw_background(0, 0, this->w, this->h);
540 // Set up options for popup window
541 #ifdef HAVE_LIBXXF86VM
542 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
544 if(window_type == POPUP_WINDOW)
548 if(!hidden) show_window();
550 get_resources()->create_window_lock->unlock();
555 Display* BC_WindowBase::init_display(char *display_name)
559 if(display_name && display_name[0] == 0) display_name = NULL;
560 if((display = XOpenDisplay(display_name)) == NULL)
562 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
564 if(getenv("DISPLAY") == NULL)
566 printf("'DISPLAY' environment variable not set.\n");
570 // Try again with default display.
572 if((display = XOpenDisplay(0)) == NULL)
574 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
582 Display* BC_WindowBase::get_display()
584 return top_level->display;
587 int BC_WindowBase::get_screen()
589 return top_level->screen;
592 int BC_WindowBase::run_window()
598 // Events may have been sent before run_window so can't initialize them here.
601 if(window_type == MAIN_WINDOW)
603 // tooltip_id = get_repeat_id();
604 set_repeat(get_resources()->tooltip_delay);
607 // Start X server events
608 event_thread = new BC_WindowEvents(this);
609 event_thread->start();
611 // Start common events
617 unset_all_repeaters();
621 event_condition->reset();
622 common_events.remove_all_objects();
628 int BC_WindowBase::get_key_masks(XEvent *event)
630 // printf("BC_WindowBase::get_key_masks %llx\n",
631 // event->xkey.state);
633 ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
635 shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
636 alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
646 int BC_WindowBase::dispatch_event()
653 XClientMessageEvent *ptr;
655 int cancel_resize, cancel_translation;
659 // If an event is waiting get it, otherwise
660 // wait for next event only if there are no compressed events.
661 if(get_event_count() ||
662 (!motion_events && !resize_events && !translation_events))
664 // XNextEvent(display, event);
666 // Lock out window deletions
667 lock_window("BC_WindowBase::dispatch_event 1");
668 // get_key_masks(event);
671 // Handle compressed events
673 lock_window("BC_WindowBase::dispatch_event 2");
675 dispatch_resize_event(last_resize_w, last_resize_h);
678 dispatch_motion_event();
680 if(translation_events)
681 dispatch_translation_event();
687 //printf("1 %s %p %d\n", title, event, event->type);
691 // Clear the resize buffer
692 if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
693 // Clear the motion buffer since this can clear the window
696 dispatch_motion_event();
699 ptr = (XClientMessageEvent*)event;
702 if(ptr->message_type == ProtoXAtom &&
703 ptr->data.l[0] == DelWinXAtom)
708 if(ptr->message_type == RepeaterXAtom)
710 dispatch_repeat_event(ptr->data.l[0]);
711 // Make sure the repeater still exists.
712 // for(int i = 0; i < repeaters.total; i++)
714 // if(repeaters.values[i]->repeat_id == ptr->data.l[0])
716 // dispatch_repeat_event_master(ptr->data.l[0]);
722 if(ptr->message_type == SetDoneXAtom)
726 { // We currently use X marshalling for xatom events, we can switch to something else later
727 recieve_custom_xatoms((xatom_event *)ptr);
738 dispatch_focus_out();
750 get_key_masks(event);
751 cursor_x = event->xbutton.x;
752 cursor_y = event->xbutton.y;
753 button_number = event->xbutton.button;
754 event_win = event->xany.window;
755 if (button_number != 4 && button_number != 5)
757 button_pressed = event->xbutton.button;
758 button_time1 = button_time2;
759 button_time2 = event->xbutton.time;
762 drag_win = event_win;
763 drag_x1 = cursor_x - get_resources()->drag_radius;
764 drag_x2 = cursor_x + get_resources()->drag_radius;
765 drag_y1 = cursor_y - get_resources()->drag_radius;
766 drag_y2 = cursor_y + get_resources()->drag_radius;
768 if(button_time2 - button_time1 < resources.double_click)
770 // Ignore triple clicks
772 button_time2 = button_time1 = 0;
777 dispatch_button_press();
781 get_key_masks(event);
782 button_number = event->xbutton.button;
783 event_win = event->xany.window;
784 if (button_number != 4 && button_number != 5)
787 dispatch_button_release();
792 event_win = event->xany.window;
793 dispatch_expose_event();
797 get_key_masks(event);
798 // Dispatch previous motion event if this is a subsequent motion from a different window
799 if(motion_events && last_motion_win != event->xany.window)
801 dispatch_motion_event();
804 // Buffer the current motion
806 last_motion_x = event->xmotion.x;
807 last_motion_y = event->xmotion.y;
808 last_motion_win = event->xany.window;
811 case ConfigureNotify:
812 get_key_masks(event);
813 XTranslateCoordinates(top_level->display,
821 last_resize_w = event->xconfigure.width;
822 last_resize_h = event->xconfigure.height;
825 cancel_translation = 0;
827 // Resize history prevents responses to recursive resize requests
828 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
830 if(resize_history.values[i]->w == last_resize_w &&
831 resize_history.values[i]->h == last_resize_h)
833 delete resize_history.values[i];
834 resize_history.remove_number(i);
839 if(last_resize_w == w && last_resize_h == h)
847 if((last_translate_x == x && last_translate_y == y))
848 cancel_translation = 1;
850 if(!cancel_translation)
852 translation_events = 1;
859 get_key_masks(event);
861 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
863 // printf("BC_WindowBase::dispatch_event 2 %llx\n",
864 // event->xkey.state);
865 // block out control keys
866 if(keysym > 0xffe0 && keysym < 0xffff) break;
869 if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
874 // block out extra keys
884 // Translate key codes
885 case XK_Return: key_pressed = RETURN; break;
886 case XK_Up: key_pressed = UP; break;
887 case XK_Down: key_pressed = DOWN; break;
888 case XK_Left: key_pressed = LEFT; break;
889 case XK_Right: key_pressed = RIGHT; break;
890 case XK_Next: key_pressed = PGDN; break;
891 case XK_Prior: key_pressed = PGUP; break;
892 case XK_BackSpace: key_pressed = BACKSPACE; break;
893 case XK_Escape: key_pressed = ESC; break;
896 key_pressed = LEFTTAB;
900 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
901 case XK_underscore: key_pressed = '_'; break;
902 case XK_asciitilde: key_pressed = '~'; break;
903 case XK_Delete: key_pressed = DELETE; break;
904 case XK_Home: key_pressed = HOME; break;
905 case XK_End: key_pressed = END; break;
908 case XK_KP_Enter: key_pressed = KPENTER; break;
909 case XK_KP_Add: key_pressed = KPPLUS; break;
911 case XK_KP_End: key_pressed = KP1; break;
913 case XK_KP_Down: key_pressed = KP2; break;
915 case XK_KP_Page_Down: key_pressed = KP3; break;
917 case XK_KP_Left: key_pressed = KP4; break;
919 case XK_KP_Begin: key_pressed = KP5; break;
921 case XK_KP_Right: key_pressed = KP6; break;
923 case XK_KP_Insert: key_pressed = KPINS; break;
925 case XK_KP_Delete: key_pressed = KPDEL; break;
927 //key_pressed = keys_return[0];
928 key_pressed = keysym & 0xff;
932 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
933 result = dispatch_keypress_event();
934 // Handle some default keypresses
937 if(key_pressed == 'w' ||
946 event_win = event->xany.window;
947 dispatch_cursor_leave();
951 event_win = event->xany.window;
952 cursor_x = event->xcrossing.x;
953 cursor_y = event->xcrossing.y;
954 dispatch_cursor_enter();
957 //printf("100 %s %p %d\n", title, event, event->type);
960 if(event) delete event;
964 int BC_WindowBase::dispatch_expose_event()
967 for(int i = 0; i < subwindows->total && !result; i++)
969 result = subwindows->values[i]->dispatch_expose_event();
973 if(!result) expose_event();
977 int BC_WindowBase::dispatch_resize_event(int w, int h)
979 // Can't store new w and h until the event is handles
980 // because bcfilebox depends on the old w and h to
981 // reposition widgets.
982 if(window_type == MAIN_WINDOW)
986 pixmap = new BC_Pixmap(this, w, h);
988 clear_box(0, 0, w, h);
991 // Propagate to subwindows
992 for(int i = 0; i < subwindows->total; i++)
994 subwindows->values[i]->dispatch_resize_event(w, h);
1000 if(window_type == MAIN_WINDOW)
1008 int BC_WindowBase::dispatch_translation_event()
1010 translation_events = 0;
1011 if(window_type == MAIN_WINDOW)
1015 x = last_translate_x;
1016 y = last_translate_y;
1017 // Correct for window manager offsets
1022 for(int i = 0; i < subwindows->total; i++)
1024 subwindows->values[i]->dispatch_translation_event();
1027 translation_event();
1031 int BC_WindowBase::dispatch_motion_event()
1036 if(top_level == this)
1038 event_win = last_motion_win;
1042 if(get_button_down() && !active_menubar && !active_popup_menu)
1046 cursor_x = last_motion_x;
1047 cursor_y = last_motion_y;
1048 result = dispatch_drag_motion();
1052 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
1053 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1058 result = dispatch_drag_start();
1061 cursor_x = last_motion_x;
1062 cursor_y = last_motion_y;
1064 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1065 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1066 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1069 for(int i = 0; i < subwindows->total && !result; i++)
1071 result = subwindows->values[i]->dispatch_motion_event();
1075 if(!result) result = cursor_motion_event(); // give to user
1079 int BC_WindowBase::dispatch_keypress_event()
1082 if(top_level == this)
1084 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1087 for(int i = 0; i < subwindows->total && !result; i++)
1089 result = subwindows->values[i]->dispatch_keypress_event();
1092 if(!result) result = keypress_event();
1097 int BC_WindowBase::dispatch_focus_in()
1099 for(int i = 0; i < subwindows->total; i++)
1101 subwindows->values[i]->dispatch_focus_in();
1109 int BC_WindowBase::dispatch_focus_out()
1111 for(int i = 0; i < subwindows->total; i++)
1113 subwindows->values[i]->dispatch_focus_out();
1121 int BC_WindowBase::get_has_focus()
1123 return top_level->has_focus;
1126 int BC_WindowBase::get_deleting()
1128 if(is_deleting) return 1;
1129 if(parent_window && parent_window->get_deleting()) return 1;
1133 int BC_WindowBase::dispatch_button_press()
1136 if(top_level == this)
1138 if(active_menubar) result = active_menubar->dispatch_button_press();
1139 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1140 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1143 for(int i = 0; i < subwindows->total && !result; i++)
1145 result = subwindows->values[i]->dispatch_button_press();
1148 if(!result) result = button_press_event();
1153 int BC_WindowBase::dispatch_button_release()
1156 if(top_level == this)
1158 if(active_menubar) result = active_menubar->dispatch_button_release();
1159 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1160 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1161 if(!result && button_number != 4 && button_number != 5)
1162 result = dispatch_drag_stop();
1165 for(int i = 0; i < subwindows->total && !result; i++)
1167 result = subwindows->values[i]->dispatch_button_release();
1172 result = button_release_event();
1179 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1182 // all repeat event handlers get called and decide based on activity and duration
1183 // whether to respond
1184 for(int i = 0; i < subwindows->total; i++)
1186 subwindows->values[i]->dispatch_repeat_event(duration);
1190 repeat_event(duration);
1194 // Unlock next repeat signal
1195 if(window_type == MAIN_WINDOW)
1197 for(int i = 0; i < repeaters.total; i++)
1199 if(repeaters.values[i]->delay == duration)
1201 repeaters.values[i]->repeat_lock->unlock();
1209 void BC_WindowBase::unhide_cursor()
1214 if(top_level->is_hourglass)
1215 set_cursor(HOURGLASS_CURSOR, 1);
1217 set_cursor(current_cursor, 1);
1219 cursor_timer->update();
1223 void BC_WindowBase::update_video_cursor()
1225 if(video_on && !is_transparent)
1227 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1230 set_cursor(TRANSPARENT_CURSOR, 1);
1231 cursor_timer->update();
1236 cursor_timer->update();
1241 int BC_WindowBase::dispatch_cursor_leave()
1245 for(int i = 0; i < subwindows->total; i++)
1247 subwindows->values[i]->dispatch_cursor_leave();
1250 cursor_leave_event();
1254 int BC_WindowBase::dispatch_cursor_enter()
1260 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1261 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1262 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1264 for(int i = 0; !result && i < subwindows->total; i++)
1266 result = subwindows->values[i]->dispatch_cursor_enter();
1269 if(!result) result = cursor_enter_event();
1273 int BC_WindowBase::cursor_enter_event()
1278 int BC_WindowBase::cursor_leave_event()
1283 int BC_WindowBase::close_event()
1289 int BC_WindowBase::dispatch_drag_start()
1292 if(active_menubar) result = active_menubar->dispatch_drag_start();
1293 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1294 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1296 for(int i = 0; i < subwindows->total && !result; i++)
1298 result = subwindows->values[i]->dispatch_drag_start();
1301 if(!result) result = is_dragging = drag_start_event();
1305 int BC_WindowBase::dispatch_drag_stop()
1309 for(int i = 0; i < subwindows->total && !result; i++)
1311 result = subwindows->values[i]->dispatch_drag_stop();
1314 if(is_dragging && !result)
1324 int BC_WindowBase::dispatch_drag_motion()
1327 for(int i = 0; i < subwindows->total && !result; i++)
1329 result = subwindows->values[i]->dispatch_drag_motion();
1332 if(is_dragging && !result)
1334 drag_motion_event();
1345 int BC_WindowBase::show_tooltip(int w, int h)
1349 if(!tooltip_on && get_resources()->tooltips_enabled)
1352 top_level->hide_tooltip();
1356 w = get_text_width(MEDIUMFONT, tooltip_text);
1359 h = get_text_height(MEDIUMFONT, tooltip_text);
1361 w += TOOLTIP_MARGIN * 2;
1362 h += TOOLTIP_MARGIN * 2;
1364 XTranslateCoordinates(top_level->display,
1372 tooltip_popup = new BC_Popup(top_level,
1377 get_resources()->tooltip_bg_color);
1380 tooltip_popup->set_font(MEDIUMFONT);
1381 tooltip_popup->flash();
1382 tooltip_popup->flush();
1387 int BC_WindowBase::hide_tooltip()
1390 for(int i = 0; i < subwindows->total; i++)
1392 subwindows->values[i]->hide_tooltip();
1398 delete tooltip_popup;
1404 int BC_WindowBase::set_tooltip(char *text)
1406 strcpy(this->tooltip_text, text);
1407 // Update existing tooltip if it is visible
1411 tooltip_popup->flash();
1416 // signal the event handler to repeat
1417 int BC_WindowBase::set_repeat(int64_t duration)
1421 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1424 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1426 // test repeater database for duplicates
1427 for(int i = 0; i < repeaters.total; i++)
1430 if(repeaters.values[i]->delay == duration)
1432 repeaters.values[i]->start_repeating();
1437 BC_Repeater *repeater = new BC_Repeater(this, duration);
1438 repeater->initialize();
1439 repeaters.append(repeater);
1440 repeater->start_repeating();
1444 int BC_WindowBase::unset_repeat(int64_t duration)
1446 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1448 BC_Repeater *repeater = 0;
1449 for(int i = 0; i < repeaters.total; i++)
1451 if(repeaters.values[i]->delay == duration)
1453 repeaters.values[i]->stop_repeating();
1460 int BC_WindowBase::unset_all_repeaters()
1462 for(int i = 0; i < repeaters.total; i++)
1464 repeaters.values[i]->stop_repeating();
1466 repeaters.remove_all_objects();
1470 // long BC_WindowBase::get_repeat_id()
1472 // return top_level->next_repeat_id++;
1476 int BC_WindowBase::arm_repeat(int64_t duration)
1478 XEvent *event = new XEvent;
1479 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1480 ptr->type = ClientMessage;
1481 ptr->message_type = RepeaterXAtom;
1483 ptr->data.l[0] = duration;
1485 // Couldn't use XSendEvent since it locked up randomly.
1487 // XSendEvent(top_level->event_display,
1496 int BC_WindowBase::recieve_custom_xatoms(xatom_event *event)
1501 int BC_WindowBase::send_custom_xatom(xatom_event *event)
1503 XEvent *myevent = new XEvent;
1504 XClientMessageEvent *ptr = (XClientMessageEvent*)myevent;
1505 ptr->type = ClientMessage;
1506 ptr->message_type = event->message_type;
1507 ptr->format = event->format;
1508 ptr->data.l[0] = event->data.l[0];
1509 ptr->data.l[1] = event->data.l[1];
1510 ptr->data.l[2] = event->data.l[2];
1511 ptr->data.l[3] = event->data.l[3];
1512 ptr->data.l[4] = event->data.l[4];
1520 Atom BC_WindowBase::create_xatom(char *atom_name)
1522 return XInternAtom(display, atom_name, False);
1525 int BC_WindowBase::get_atoms()
1527 SetDoneXAtom = create_xatom("BC_REPEAT_EVENT");
1528 RepeaterXAtom = create_xatom("BC_CLOSE_EVENT");
1529 DelWinXAtom = create_xatom("WM_DELETE_WINDOW");
1530 if(ProtoXAtom = create_xatom("WM_PROTOCOLS"))
1531 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1537 void BC_WindowBase::init_cursors()
1539 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1540 cross_cursor = XCreateFontCursor(display, XC_crosshair);
1541 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1542 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1543 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1544 move_cursor = XCreateFontCursor(display, XC_fleur);
1545 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1546 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1547 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1548 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1549 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1550 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1551 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1552 hourglass_cursor = XCreateFontCursor(display, XC_watch);
1555 char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
1556 Colormap colormap = DefaultColormap(display, screen);
1557 Pixmap pixmap_bottom = XCreateBitmapFromData(display,
1562 XColor black, dummy;
1563 XAllocNamedColor(display, colormap, "black", &black, &dummy);
1564 transparent_cursor = XCreatePixmapCursor(display,
1571 // XDefineCursor(display, win, transparent_cursor);
1572 XFreePixmap(display, pixmap_bottom);
1575 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1581 color_model = BC_RGB8;
1584 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1587 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1590 color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1596 int BC_WindowBase::init_colors()
1599 current_color_value = current_color_pixel = 0;
1601 // Get the real depth
1604 ximage = XCreateImage(top_level->display,
1606 top_level->default_depth,
1614 bits_per_pixel = ximage->bits_per_pixel;
1615 XDestroyImage(ximage);
1617 color_model = evaluate_color_model(client_byte_order,
1620 // Get the color model
1626 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1627 create_private_colors();
1631 cmap = DefaultColormap(display, screen);
1632 create_shared_colors();
1635 allocate_color_table();
1637 get_resources()->use_xft = 0;
1641 cmap = DefaultColormap(display, screen);
1647 int BC_WindowBase::create_private_colors()
1652 for(int i = 0; i < 255; i++)
1654 color = (i & 0xc0) << 16;
1655 color += (i & 0x38) << 10;
1656 color += (i & 0x7) << 5;
1657 color_table[i][0] = color;
1659 create_shared_colors(); // overwrite the necessary colors on the table
1664 int BC_WindowBase::create_color(int color)
1666 if(total_colors == 256)
1668 // replace the closest match with an exact match
1669 color_table[get_color_rgb8(color)][0] = color;
1673 // add the color to the table
1674 color_table[total_colors][0] = color;
1680 int BC_WindowBase::create_shared_colors()
1682 create_color(BLACK);
1683 create_color(WHITE);
1685 create_color(LTGREY);
1686 create_color(MEGREY);
1687 create_color(MDGREY);
1688 create_color(DKGREY);
1690 create_color(LTCYAN);
1691 create_color(MECYAN);
1692 create_color(MDCYAN);
1693 create_color(DKCYAN);
1695 create_color(LTGREEN);
1696 create_color(GREEN);
1697 create_color(DKGREEN);
1699 create_color(LTPINK);
1703 create_color(LTBLUE);
1705 create_color(DKBLUE);
1707 create_color(LTYELLOW);
1708 create_color(MEYELLOW);
1709 create_color(MDYELLOW);
1710 create_color(DKYELLOW);
1712 create_color(LTPURPLE);
1713 create_color(MEPURPLE);
1714 create_color(MDPURPLE);
1715 create_color(DKPURPLE);
1717 create_color(FGGREY);
1718 create_color(MNBLUE);
1719 create_color(ORANGE);
1720 create_color(FTGREY);
1725 int BC_WindowBase::allocate_color_table()
1727 int red, green, blue, color;
1731 for(int i = 0; i < total_colors; i++)
1733 color = color_table[i][0];
1734 red = (color & 0xFF0000) >> 16;
1735 green = (color & 0x00FF00) >> 8;
1736 blue = color & 0xFF;
1738 col.flags = DoRed | DoGreen | DoBlue;
1739 col.red = red<<8 | red;
1740 col.green = green<<8 | green;
1741 col.blue = blue<<8 | blue;
1743 XAllocColor(display, cmap, &col);
1744 color_table[i][1] = col.pixel;
1747 XInstallColormap(display, cmap);
1751 int BC_WindowBase::init_window_shape()
1753 if(bg_pixmap && bg_pixmap->use_alpha())
1755 XShapeCombineMask(top_level->display,
1760 bg_pixmap->get_alpha(),
1767 int BC_WindowBase::init_gc()
1769 unsigned long gcmask;
1770 gcmask = GCFont | GCGraphicsExposures;
1773 gcvalues.font = mediumfont->fid; // set the font
1774 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
1775 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1779 int BC_WindowBase::init_fonts()
1781 if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL)
1782 if((largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1783 largefont = XLoadQueryFont(display, "fixed");
1785 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL)
1786 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1787 mediumfont = XLoadQueryFont(display, "fixed");
1789 if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL)
1790 if((smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1791 smallfont = XLoadQueryFont(display, "fixed");
1794 if(get_resources()->use_fontset)
1799 // FIXME: should check the m,d,n values
1800 if((largefontset = XCreateFontSet(display,
1801 resources.large_fontset,
1805 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1806 if((mediumfontset = XCreateFontSet(display,
1807 resources.medium_fontset,
1811 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1812 if((smallfontset = XCreateFontSet(display,
1813 resources.small_fontset,
1817 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1819 if(largefontset && mediumfontset && smallfontset)
1821 curr_fontset = mediumfontset;
1822 get_resources()->use_fontset = 1;
1827 get_resources()->use_fontset = 0;
1835 void BC_WindowBase::init_xft()
1838 if(!(largefont_xft = XftFontOpenXlfd(display,
1840 resources.large_font_xft)))
1841 if(!(largefont_xft = XftFontOpenXlfd(display,
1843 resources.large_font_xft2)))
1844 largefont_xft = XftFontOpenXlfd(display,
1849 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1851 resources.medium_font_xft)))
1852 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1854 resources.medium_font_xft2)))
1855 mediumfont_xft = XftFontOpenXlfd(display,
1860 if(!(smallfont_xft = XftFontOpenXlfd(display,
1862 resources.small_font_xft)))
1863 if(!(smallfont_xft = XftFontOpenXlfd(display,
1865 resources.small_font_xft2)))
1866 smallfont_xft = XftFontOpenXlfd(display,
1871 // Extension failed to locate fonts
1872 if(!largefont_xft || !mediumfont_xft || !smallfont_xft)
1874 printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1875 resources.large_font_xft,
1877 resources.medium_font_xft,
1879 resources.small_font_xft,
1881 get_resources()->use_xft = 0;
1887 int BC_WindowBase::get_color(int64_t color)
1889 // return pixel of color
1890 // use this only for drawing subwindows not for bitmaps
1891 int i, test, difference, result;
1898 return get_color_rgb8(color);
1902 // test last color looked up
1903 if(current_color_value == color) return current_color_pixel;
1906 current_color_value = color;
1907 for(i = 0; i < total_colors; i++)
1909 if(color_table[i][0] == color)
1911 current_color_pixel = color_table[i][1];
1912 return current_color_pixel;
1916 // find nearest match
1917 difference = 0xFFFFFF;
1919 for(i = 0, result = 0; i < total_colors; i++)
1921 test = abs((int)(color_table[i][0] - color));
1923 if(test < difference)
1925 current_color_pixel = color_table[i][1];
1930 return current_color_pixel;
1935 return get_color_rgb16(color);
1939 return get_color_bgr16(color);
1944 if(client_byte_order == server_byte_order)
1947 get_color_bgr24(color);
1957 int BC_WindowBase::get_color_rgb8(int color)
1961 pixel = (color & 0xc00000) >> 16;
1962 pixel += (color & 0xe000) >> 10;
1963 pixel += (color & 0xe0) >> 5;
1967 int64_t BC_WindowBase::get_color_rgb16(int color)
1970 result = (color & 0xf80000) >> 8;
1971 result += (color & 0xfc00) >> 5;
1972 result += (color & 0xf8) >> 3;
1977 int64_t BC_WindowBase::get_color_bgr16(int color)
1980 result = (color & 0xf80000) >> 19;
1981 result += (color & 0xfc00) >> 5;
1982 result += (color & 0xf8) << 8;
1987 int64_t BC_WindowBase::get_color_bgr24(int color)
1990 result = (color & 0xff) << 16;
1991 result += (color & 0xff00);
1992 result += (color & 0xff0000) >> 16;
1996 void BC_WindowBase::start_video()
1998 cursor_timer->update();
2000 // set_color(BLACK);
2001 // draw_box(0, 0, get_w(), get_h());
2005 void BC_WindowBase::stop_video()
2013 int64_t BC_WindowBase::get_color()
2015 return top_level->current_color;
2018 void BC_WindowBase::set_color(int64_t color)
2020 top_level->current_color = color;
2021 XSetForeground(top_level->display,
2023 top_level->get_color(color));
2026 void BC_WindowBase::set_opaque()
2028 XSetFunction(top_level->display, top_level->gc, GXcopy);
2031 void BC_WindowBase::set_inverse()
2033 XSetFunction(top_level->display, top_level->gc, GXxor);
2036 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2040 case ARROW_CURSOR: return top_level->arrow_cursor; break;
2041 case CROSS_CURSOR: return top_level->cross_cursor;
2042 case IBEAM_CURSOR: return top_level->ibeam_cursor; break;
2043 case VSEPARATE_CURSOR: return top_level->vseparate_cursor; break;
2044 case HSEPARATE_CURSOR: return top_level->hseparate_cursor; break;
2045 case MOVE_CURSOR: return top_level->move_cursor; break;
2046 case LEFT_CURSOR: return top_level->left_cursor; break;
2047 case RIGHT_CURSOR: return top_level->right_cursor; break;
2048 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor; break;
2049 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor; break;
2050 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor; break;
2051 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor; break;
2052 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor; break;
2053 case HOURGLASS_CURSOR: return top_level->hourglass_cursor; break;
2054 case TRANSPARENT_CURSOR: return top_level->transparent_cursor; break;
2059 void BC_WindowBase::set_cursor(int cursor, int override)
2061 // don't change cursor if overridden
2062 if((!top_level->is_hourglass && !is_transparent) ||
2065 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2069 if(!override) current_cursor = cursor;
2072 void BC_WindowBase::set_x_cursor(int cursor)
2074 temp_cursor = XCreateFontCursor(top_level->display, cursor);
2075 XDefineCursor(top_level->display, win, temp_cursor);
2076 current_cursor = cursor;
2080 int BC_WindowBase::get_cursor()
2082 return current_cursor;
2085 void BC_WindowBase::start_hourglass()
2087 top_level->start_hourglass_recursive();
2091 void BC_WindowBase::stop_hourglass()
2093 top_level->stop_hourglass_recursive();
2097 void BC_WindowBase::start_hourglass_recursive()
2099 if(this == top_level)
2107 set_cursor(HOURGLASS_CURSOR, 1);
2108 for(int i = 0; i < subwindows->total; i++)
2110 subwindows->values[i]->start_hourglass_recursive();
2115 void BC_WindowBase::stop_hourglass_recursive()
2117 if(this == top_level)
2119 if(hourglass_total == 0) return;
2120 top_level->hourglass_total--;
2123 if(!top_level->hourglass_total)
2125 top_level->is_hourglass = 0;
2127 // Cause set_cursor to perform change
2129 set_cursor(current_cursor, 1);
2131 for(int i = 0; i < subwindows->total; i++)
2133 subwindows->values[i]->stop_hourglass_recursive();
2143 XFontStruct* BC_WindowBase::get_font_struct(int font)
2145 // Clear out unrelated flags
2146 if(font & BOLDFACE) font ^= BOLDFACE;
2150 case MEDIUMFONT: return top_level->mediumfont; break;
2151 case SMALLFONT: return top_level->smallfont; break;
2152 case LARGEFONT: return top_level->largefont; break;
2157 XFontSet BC_WindowBase::get_fontset(int font)
2161 if(get_resources()->use_fontset)
2165 case SMALLFONT: fs = top_level->smallfontset; break;
2166 case LARGEFONT: fs = top_level->largefontset; break;
2167 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2175 XftFont* BC_WindowBase::get_xft_struct(int font)
2177 // Clear out unrelated flags
2178 if(font & BOLDFACE) font ^= BOLDFACE;
2182 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft; break;
2183 case SMALLFONT: return (XftFont*)top_level->smallfont_xft; break;
2184 case LARGEFONT: return (XftFont*)top_level->largefont_xft; break;
2201 void BC_WindowBase::set_font(int font)
2203 top_level->current_font = font;
2207 if(get_resources()->use_xft)
2213 if(get_resources()->use_fontset)
2218 if(get_font_struct(font))
2220 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2226 void BC_WindowBase::set_fontset(int font)
2230 if(get_resources()->use_fontset)
2234 case SMALLFONT: fs = top_level->smallfontset; break;
2235 case LARGEFONT: fs = top_level->largefontset; break;
2236 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2244 XFontSet BC_WindowBase::get_curr_fontset(void)
2246 if(get_resources()->use_fontset)
2247 return curr_fontset;
2251 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2254 if(get_resources()->use_xft && get_xft_struct(font))
2257 XftTextExtents8(top_level->display,
2258 get_xft_struct(font),
2262 return extents.xOff;
2266 if(get_resources()->use_fontset && top_level->get_fontset(font))
2267 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2269 if(get_font_struct(font))
2270 return XTextWidth(get_font_struct(font), text, length);
2276 case MEDIUM_7SEGMENT:
2277 return get_resources()->medium_7segment[0]->get_w() * length;
2287 int BC_WindowBase::get_text_width(int font, char *text, int length)
2289 int i, j, w = 0, line_w = 0;
2290 if(length < 0) length = strlen(text);
2292 for(i = 0, j = 0; i <= length; i++)
2297 line_w = get_single_text_width(font, &text[j], i - j);
2303 line_w = get_single_text_width(font, &text[j], length - j);
2305 if(line_w > w) w = line_w;
2308 if(i > length && w == 0)
2310 w = get_single_text_width(font, text, length);
2316 int BC_WindowBase::get_text_ascent(int font)
2319 if(get_resources()->use_xft && get_xft_struct(font))
2322 XftTextExtents8(top_level->display,
2323 get_xft_struct(font),
2327 return extents.y + 2;
2331 if(get_resources()->use_fontset && top_level->get_fontset(font))
2333 XFontSetExtents *extents;
2335 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2336 return -extents->max_logical_extent.y;
2339 if(get_font_struct(font))
2340 return top_level->get_font_struct(font)->ascent;
2344 case MEDIUM_7SEGMENT:
2345 return get_resources()->medium_7segment[0]->get_h();
2353 int BC_WindowBase::get_text_descent(int font)
2356 if(get_resources()->use_xft && get_xft_struct(font))
2359 XftTextExtents8(top_level->display,
2360 get_xft_struct(font),
2364 return extents.height - extents.y;
2368 if(get_resources()->use_fontset && top_level->get_fontset(font))
2370 XFontSetExtents *extents;
2372 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2373 return (extents->max_logical_extent.height
2374 + extents->max_logical_extent.y);
2377 if(get_font_struct(font))
2378 return top_level->get_font_struct(font)->descent;
2387 int BC_WindowBase::get_text_height(int font, char *text)
2389 if(!text) return get_text_ascent(font) + get_text_descent(font);
2391 // Add height of lines
2392 int h = 0, i, length = strlen(text);
2393 for(i = 0; i <= length; i++)
2401 return h * (get_text_ascent(font) + get_text_descent(font));
2404 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2406 if(color_model < 0) color_model = top_level->get_color_model();
2407 return new BC_Bitmap(top_level, w, h, color_model);
2410 int BC_WindowBase::accel_available(int color_model, int lock_it)
2412 if(window_type != MAIN_WINDOW)
2413 return top_level->accel_available(color_model, lock_it);
2417 if(lock_it) lock_window("BC_WindowBase::accel_available");
2421 result = grab_port_id(this, color_model);
2424 xvideo_port_id = result;
2436 //printf("BC_WindowBase::accel_available 1\n");
2437 result = grab_port_id(this, color_model);
2438 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2441 xvideo_port_id = result;
2446 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2454 if(lock_it) unlock_window();
2455 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2460 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2462 int numFormats, i, j, k;
2463 unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2465 XvAdaptorInfo *info;
2466 XvImageFormatValues *formats;
2469 if(!get_resources()->use_xvideo) return -1;
2471 // Translate from color_model to X color model
2472 x_color_model = cmodel_bc_to_x(color_model);
2474 // Only local server is fast enough.
2475 if(!resources.use_shm) return -1;
2477 // XV extension is available
2478 if(Success != XvQueryExtension(window->display,
2488 // XV adaptors are available
2489 XvQueryAdaptors(window->display,
2490 DefaultRootWindow(window->display),
2499 // Get adaptor with desired color model
2500 for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2502 /* adaptor supports XvImages */
2503 if(info[i].type & XvImageMask)
2505 formats = XvListImageFormats(window->display,
2508 // for(j = 0; j < numFormats; j++)
2509 // printf("%08x\n", formats[j].id);
2511 for(j = 0; j < numFormats && xvideo_port_id < 0; j++)
2513 /* this adaptor supports the desired format */
2514 if(formats[j].id == x_color_model)
2516 /* Try to grab a port */
2517 for(k = 0; k < info[i].num_ports; k++)
2520 if(Success == XvGrabPort(top_level->display,
2521 info[i].base_id + k,
2524 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2525 xvideo_port_id = info[i].base_id + k;
2531 if(formats) XFree(formats);
2535 XvFreeAdaptorInfo(info);
2537 return xvideo_port_id;
2541 int BC_WindowBase::show_window(int flush)
2543 XMapWindow(top_level->display, win);
2544 if(flush) XFlush(top_level->display);
2545 // XSync(top_level->display, 0);
2550 int BC_WindowBase::hide_window(int flush)
2552 XUnmapWindow(top_level->display, win);
2553 if(flush) XFlush(top_level->display);
2558 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2560 subwindows->append((BC_SubWindow*)menu_bar);
2562 menu_bar->parent_window = this;
2563 menu_bar->top_level = this->top_level;
2564 menu_bar->initialize();
2568 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2570 subwindows->append(subwindow);
2572 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2574 // parent window must be set before the subwindow initialization
2575 subwindow->parent_window = this;
2576 subwindow->top_level = this->top_level;
2578 // Execute derived initialization
2579 subwindow->initialize();
2584 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2586 return add_subwindow(subwindow);
2589 BC_WidgetGrid* BC_WindowBase::add_widgetgrid(BC_WidgetGrid *widgetgrid)
2591 widgetgrids->append(widgetgrid);
2596 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2599 XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
2602 XClearArea(top_level->display, win, x, y, w, h, 0);
2606 XClearWindow(top_level->display, win);
2614 int BC_WindowBase::flash(int flush)
2616 flash(-1, -1, -1, -1, flush);
2619 void BC_WindowBase::flush()
2621 XFlush(top_level->display);
2624 void BC_WindowBase::sync_display()
2626 XSync(top_level->display, False);
2629 int BC_WindowBase::get_window_lock()
2631 return top_level->window_lock;
2634 int BC_WindowBase::lock_window(char *location)
2636 if(top_level && top_level != this)
2638 top_level->lock_window(location);
2643 SET_LOCK(this, title, location);
2644 XLockDisplay(top_level->display);
2646 top_level->window_lock = 1;
2650 printf("BC_WindowBase::lock_window top_level NULL\n");
2655 int BC_WindowBase::unlock_window()
2657 if(top_level && top_level != this)
2659 top_level->unlock_window();
2665 top_level->window_lock = 0;
2666 XUnlockDisplay(top_level->display);
2670 printf("BC_WindowBase::unlock_window top_level NULL\n");
2675 void BC_WindowBase::set_done(int return_value)
2677 if(window_type != MAIN_WINDOW)
2678 top_level->set_done(return_value);
2681 XEvent *event = new XEvent;
2682 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2684 event->type = ClientMessage;
2685 ptr->message_type = SetDoneXAtom;
2687 this->return_value = return_value;
2689 // May lock up here because XSendEvent doesn't work too well
2690 // asynchronous with XNextEvent.
2691 // This causes BC_WindowEvents to forward a copy of the event to run_window where
2694 // Deletion of event_thread is done at the end of BC_WindowBase::run_window() - by calling the destructor
2699 int BC_WindowBase::get_w()
2704 int BC_WindowBase::get_h()
2709 int BC_WindowBase::get_x()
2714 int BC_WindowBase::get_y()
2719 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2721 if(lock_display) lock_window("BC_WindowBase::get_root_w");
2722 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2723 int result = WidthOfScreen(screen_ptr);
2724 // Wider than 16:9, narrower than dual head
2725 if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2727 if(lock_display) unlock_window();
2731 int BC_WindowBase::get_root_h(int lock_display)
2733 if(lock_display) lock_window("BC_WindowBase::get_root_h");
2734 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2735 int result = HeightOfScreen(screen_ptr);
2736 if(lock_display) unlock_window();
2740 // Bottom right corner
2741 int BC_WindowBase::get_x2()
2746 int BC_WindowBase::get_y2()
2751 int BC_WindowBase::get_video_on()
2756 int BC_WindowBase::get_hidden()
2758 return top_level->hidden;
2761 int BC_WindowBase::cursor_inside()
2763 return (top_level->cursor_x >= 0 &&
2764 top_level->cursor_y >= 0 &&
2765 top_level->cursor_x < w &&
2766 top_level->cursor_y < h);
2769 BC_WindowBase* BC_WindowBase::get_top_level()
2774 BC_WindowBase* BC_WindowBase::get_parent()
2776 return parent_window;
2779 int BC_WindowBase::get_color_model()
2781 return top_level->color_model;
2784 BC_Resources* BC_WindowBase::get_resources()
2786 return &BC_WindowBase::resources;
2789 BC_Synchronous* BC_WindowBase::get_synchronous()
2791 return BC_WindowBase::resources.get_synchronous();
2794 int BC_WindowBase::get_bg_color()
2799 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2804 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2806 top_level->active_subwindow = subwindow;
2809 int BC_WindowBase::activate()
2814 int BC_WindowBase::deactivate()
2816 if(window_type == MAIN_WINDOW)
2818 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2819 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2820 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2822 top_level->active_menubar = 0;
2823 top_level->active_popup_menu = 0;
2824 top_level->active_subwindow = 0;
2829 int BC_WindowBase::cycle_textboxes(int amount)
2832 BC_WindowBase *new_textbox = 0;
2836 BC_WindowBase *first_textbox = 0;
2837 find_next_textbox(&first_textbox, &new_textbox, result);
2838 if(!new_textbox) new_textbox = first_textbox;
2844 BC_WindowBase *last_textbox = 0;
2845 find_prev_textbox(&last_textbox, &new_textbox, result);
2846 if(!new_textbox) new_textbox = last_textbox;
2850 if(new_textbox != active_subwindow)
2853 new_textbox->activate();
2859 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2861 // Search subwindows for textbox
2862 for(int i = 0; i < subwindows->total && result < 2; i++)
2864 BC_WindowBase *test_subwindow = subwindows->values[i];
2865 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2872 if(!*first_textbox) *first_textbox = this;
2876 if(top_level->active_subwindow == this)
2882 *next_textbox = this;
2889 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2895 if(!*last_textbox) *last_textbox = this;
2899 if(top_level->active_subwindow == this)
2905 *prev_textbox = this;
2910 // Search subwindows for textbox
2911 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2913 BC_WindowBase *test_subwindow = subwindows->values[i];
2914 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2919 BC_Clipboard* BC_WindowBase::get_clipboard()
2921 return top_level->clipboard;
2924 int BC_WindowBase::get_relative_cursor_x()
2926 int abs_x, abs_y, x, y, win_x, win_y;
2927 unsigned int temp_mask;
2930 XQueryPointer(top_level->display,
2940 XTranslateCoordinates(top_level->display,
2952 int BC_WindowBase::get_relative_cursor_y()
2954 int abs_x, abs_y, x, y, win_x, win_y;
2955 unsigned int temp_mask;
2958 XQueryPointer(top_level->display,
2968 XTranslateCoordinates(top_level->display,
2980 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2982 int abs_x, abs_y, win_x, win_y;
2983 unsigned int temp_mask;
2986 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2987 XQueryPointer(top_level->display,
2996 if(lock_window) this->unlock_window();
3000 int BC_WindowBase::get_abs_cursor_y(int lock_window)
3002 int abs_x, abs_y, win_x, win_y;
3003 unsigned int temp_mask;
3006 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
3007 XQueryPointer(top_level->display,
3016 if(lock_window) this->unlock_window();
3020 int BC_WindowBase::match_window(Window win)
3022 if (this->win == win) return 1;
3024 for(int i = 0; i < subwindows->total; i++)
3026 result = subwindows->values[i]->match_window(win);
3027 if (result) return result;
3033 int BC_WindowBase::get_cursor_over_window()
3035 if(top_level != this) return top_level->get_cursor_over_window();
3037 int abs_x, abs_y, win_x, win_y;
3038 unsigned int temp_mask;
3039 Window temp_win1, temp_win2;
3041 if (!XQueryPointer(display,
3052 int result = match_window(temp_win2) ;
3056 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
3061 translate_coordinates(top_level->event_win,
3063 top_level->cursor_x,
3064 top_level->cursor_y,
3070 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
3075 translate_coordinates(top_level->event_win,
3077 top_level->cursor_x,
3078 top_level->cursor_y,
3084 int BC_WindowBase::get_drag_x()
3086 return top_level->drag_x;
3089 int BC_WindowBase::get_drag_y()
3091 return top_level->drag_y;
3094 int BC_WindowBase::get_cursor_x()
3096 return top_level->cursor_x;
3099 int BC_WindowBase::get_cursor_y()
3101 return top_level->cursor_y;
3104 int BC_WindowBase::is_event_win()
3106 return this->win == top_level->event_win;
3109 void BC_WindowBase::set_dragging(int value)
3111 is_dragging = value;
3114 int BC_WindowBase::get_dragging()
3119 int BC_WindowBase::get_buttonpress()
3121 return top_level->button_number;
3124 int BC_WindowBase::get_button_down()
3126 return top_level->button_down;
3129 int BC_WindowBase::alt_down()
3131 return top_level->alt_mask;
3134 int BC_WindowBase::shift_down()
3136 return top_level->shift_mask;
3139 int BC_WindowBase::ctrl_down()
3141 return top_level->ctrl_mask;
3145 int BC_WindowBase::get_keypress()
3147 return top_level->key_pressed;
3150 int BC_WindowBase::get_double_click()
3152 return top_level->double_click;
3155 int BC_WindowBase::get_bgcolor()
3160 int BC_WindowBase::resize_window(int w, int h)
3162 if(window_type == MAIN_WINDOW && !allow_resize)
3164 XSizeHints size_hints;
3165 size_hints.flags = PSize | PMinSize | PMaxSize;
3166 size_hints.width = w;
3167 size_hints.height = h;
3168 size_hints.min_width = w;
3169 size_hints.max_width = w;
3170 size_hints.min_height = h;
3171 size_hints.max_height = h;
3172 XSetNormalHints(top_level->display, win, &size_hints);
3174 XResizeWindow(top_level->display, win, w, h);
3179 pixmap = new BC_Pixmap(this, w, h);
3181 // Propagate to menubar
3182 for(int i = 0; i < subwindows->total; i++)
3184 subwindows->values[i]->dispatch_resize_event(w, h);
3187 draw_background(0, 0, w, h);
3188 if(top_level == this && get_resources()->recursive_resizing)
3189 resize_history.append(new BC_ResizeCall(w, h));
3193 // The only way for resize events to be propagated is by updating the internal w and h
3194 int BC_WindowBase::resize_event(int w, int h)
3196 if(window_type == MAIN_WINDOW)
3204 int BC_WindowBase::reposition_widget(int x, int y, int w, int h)
3206 return(reposition_window(x, y, w, h));
3209 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3213 // Some tools set their own dimensions before calling this, causing the
3214 // resize check to skip.
3218 if(w > 0 && w != this->w)
3224 if(h > 0 && h != this->h)
3230 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3233 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3235 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3237 if(translation_count && window_type == MAIN_WINDOW)
3239 // KDE shifts window right and down.
3240 // FVWM leaves window alone and adds border around it.
3241 XMoveResizeWindow(top_level->display,
3243 x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x,
3244 y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y,
3250 XMoveResizeWindow(top_level->display,
3261 pixmap = new BC_Pixmap(this, this->w, this->h);
3262 // Propagate to menubar
3263 for(int i = 0; i < subwindows->total; i++)
3265 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3268 // draw_background(0, 0, w, h);
3274 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3276 get_resources()->tooltips_enabled = tooltips_enabled;
3280 int BC_WindowBase::raise_window(int do_flush)
3282 XRaiseWindow(top_level->display, win);
3283 if(do_flush) XFlush(top_level->display);
3287 void BC_WindowBase::set_background(VFrame *bitmap)
3289 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3291 bg_pixmap = new BC_Pixmap(this,
3294 shared_bg_pixmap = 0;
3295 draw_background(0, 0, w, h);
3298 void BC_WindowBase::set_title(char *text)
3300 XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0);
3301 strcpy(this->title, _(text));
3305 char* BC_WindowBase::get_title()
3310 int BC_WindowBase::get_toggle_value()
3312 return toggle_value;
3315 int BC_WindowBase::get_toggle_drag()
3320 int BC_WindowBase::set_icon(VFrame *data)
3322 if(icon_pixmap) delete icon_pixmap;
3323 icon_pixmap = new BC_Pixmap(top_level,
3328 icon_window = new BC_Popup(this,
3331 icon_pixmap->get_w(),
3332 icon_pixmap->get_h(),
3334 1, // All windows are hidden initially
3338 wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3339 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3340 wm_hints.icon_mask = icon_pixmap->get_alpha();
3341 wm_hints.icon_window = icon_window->win;
3342 wm_hints.window_group = XGroupLeader;
3344 // for(int i = 0; i < 1000; i++)
3345 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3348 XSetWMHints(top_level->display, top_level->win, &wm_hints);
3349 XSync(top_level->display, 0);
3353 int BC_WindowBase::set_w(int w)
3359 int BC_WindowBase::set_h(int h)
3365 int BC_WindowBase::load_defaults(BC_Hash *defaults)
3367 BC_Resources *resources = get_resources();
3368 char string[BCTEXTLEN];
3369 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3371 sprintf(string, "FILEBOX_HISTORY%d", i);
3372 resources->filebox_history[i][0] = 0;
3373 defaults->get(string, resources->filebox_history[i]);
3375 resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3376 resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3377 resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3378 defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3382 int BC_WindowBase::save_defaults(BC_Hash *defaults)
3384 BC_Resources *resources = get_resources();
3385 char string[BCTEXTLEN];
3386 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3388 sprintf(string, "FILEBOX_HISTORY%d", i);
3389 defaults->update(string, resources->filebox_history[i]);
3391 defaults->update("FILEBOX_MODE", resources->filebox_mode);
3392 defaults->update("FILEBOX_W", resources->filebox_w);
3393 defaults->update("FILEBOX_H", resources->filebox_h);
3394 defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3400 // For some reason XTranslateCoordinates can take a long time to return.
3401 // We work around this by only calling it when the event windows are different.
3402 void BC_WindowBase::translate_coordinates(Window src_w,
3414 *dest_x_return = src_x;
3415 *dest_y_return = src_y;
3419 XTranslateCoordinates(top_level->display,
3427 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3437 #ifdef HAVE_LIBXXF86VM
3438 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3442 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3444 XF86VidModeModeInfo **vm_modelines;
3445 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3446 for (i = 0; i < vm_count; i++) {
3447 if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3450 display = top_level->display;
3451 if (vm_modelines[*vm]->hdisplay == *width)
3455 *width = vm_modelines[*vm]->hdisplay;
3456 *height = vm_modelines[*vm]->vdisplay;
3461 void BC_WindowBase::scale_vm(int vm)
3463 int foo,bar,dotclock;
3464 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3467 XF86VidModeModeInfo **vm_modelines;
3468 XF86VidModeModeLine vml;
3469 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3470 XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3471 orig_modeline.dotclock = dotclock;
3472 orig_modeline.hdisplay = vml.hdisplay;
3473 orig_modeline.hsyncstart = vml.hsyncstart;
3474 orig_modeline.hsyncend = vml.hsyncend;
3475 orig_modeline.htotal = vml.htotal;
3476 orig_modeline.vdisplay = vml.vdisplay;
3477 orig_modeline.vsyncstart = vml.vsyncstart;
3478 orig_modeline.vsyncend = vml.vsyncend;
3479 orig_modeline.vtotal = vml.vtotal;
3480 orig_modeline.flags = vml.flags;
3481 orig_modeline.privsize = vml.privsize;
3482 // orig_modeline.private = vml.private;
3483 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3484 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3485 XFlush(top_level->display);
3489 void BC_WindowBase::restore_vm()
3491 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3492 XFlush(top_level->display);
3516 int BC_WindowBase::get_event_count()
3518 event_lock->lock("BC_WindowBase::get_event_count");
3519 int result = common_events.total;
3520 event_lock->unlock();
3524 XEvent* BC_WindowBase::get_event()
3527 while(!done && !result)
3529 event_condition->lock("BC_WindowBase::get_event");
3530 event_lock->lock("BC_WindowBase::get_event");
3532 if(common_events.total && !done)
3534 result = common_events.values[0];
3535 common_events.remove_number(0);
3538 event_lock->unlock();
3543 void BC_WindowBase::put_event(XEvent *event)
3545 event_lock->lock("BC_WindowBase::put_event");
3546 common_events.append(event);
3547 event_lock->unlock();
3548 event_condition->unlock();
3551 int BC_WindowBase::get_id()