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 "bcwindowbase.h"
13 #include "bcwindowevents.h"
14 #include "colormodels.h"
16 #include "condition.h"
31 #include <X11/extensions/Xvlib.h>
32 #include <X11/extensions/shape.h>
35 BC_ResizeCall::BC_ResizeCall(int w, int h)
50 Mutex BC_WindowBase::opengl_lock;
52 BC_Resources BC_WindowBase::resources;
54 Window XGroupLeader = 0;
56 BC_WindowBase::BC_WindowBase()
58 //printf("BC_WindowBase::BC_WindowBase 1\n");
59 BC_WindowBase::initialize();
62 BC_WindowBase::~BC_WindowBase()
65 #ifdef HAVE_LIBXXF86VM
66 if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
73 if(window_type != MAIN_WINDOW)
75 if(top_level->active_menubar == this) top_level->active_menubar = 0;
76 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
77 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
78 parent_window->subwindows->remove(this);
82 // Delete the subwindows
86 while (subwindows->total)
88 // NOTE: since the value is itself a subwindow, the
89 // recursion removes the item from subwindows
90 delete subwindows->values[0];
95 XFreePixmap(top_level->display, pixmap);
96 XDestroyWindow(top_level->display, win);
98 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
99 if(icon_pixmap) delete icon_pixmap;
100 if(temp_bitmap) delete temp_bitmap;
103 if(window_type == MAIN_WINDOW)
106 XFreeGC(display, gc);
109 XftFontClose (display, (XftFont*)largefont_xft);
111 XftFontClose (display, (XftFont*)mediumfont_xft);
113 XftFontClose (display, (XftFont*)smallfont_xft);
116 // Can't close display if another thread is waiting for events
117 XCloseDisplay(display);
118 // XCloseDisplay(event_display);
119 clipboard->stop_clipboard();
127 resize_history.remove_all_objects();
128 common_events.remove_all_objects();
130 delete event_condition;
131 UNSET_ALL_LOCKS(this)
134 int BC_WindowBase::initialize()
151 translation_events = 0;
152 ctrl_mask = shift_mask = alt_mask = 0;
153 cursor_x = cursor_y = button_number = 0;
156 button_time1 = button_time2 = 0;
161 active_popup_menu = 0;
162 active_subwindow = 0;
165 persistant_tooltip = 0;
166 // next_repeat_id = 0;
169 current_font = MEDIUMFONT;
170 current_color = BLACK;
171 prev_cursor = current_cursor = ARROW_CURSOR;
174 shared_bg_pixmap = 0;
176 window_type = MAIN_WINDOW;
177 translation_count = 0;
178 x_correction = y_correction = 0;
185 #ifdef HAVE_LIBXXF86VM
192 // Need these right away since put_event is called before run_window sometimes.
193 event_lock = new Mutex("BC_WindowBase::event_lock");
194 event_condition = new Condition(0, "BC_WindowBase::event_condition");
200 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
203 ButtonReleaseMask | \
204 PointerMotionMask | \
208 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
222 BC_Pixmap *bg_pixmap,
225 XSetWindowAttributes attr;
227 XSizeHints size_hints;
230 #ifdef HAVE_LIBXXF86VM
234 if(parent_window) top_level = parent_window->top_level;
236 #ifdef HAVE_LIBXXF86VM
237 if(window_type == VIDMODE_SCALED_WINDOW)
238 closest_vm(&vm,&w,&h);
245 this->bg_color = bg_color;
246 this->window_type = window_type;
248 this->private_color = private_color;
249 this->parent_window = parent_window;
250 this->bg_pixmap = bg_pixmap;
251 this->allow_resize = allow_resize;
252 strcpy(this->title, _(title));
253 if(bg_pixmap) shared_bg_pixmap = 1;
255 if(parent_window) top_level = parent_window->top_level;
257 subwindows = new BC_SubWindowList;
260 if(window_type == MAIN_WINDOW)
263 parent_window = this;
265 // This function must be the first Xlib
266 // function a multi-threaded program calls
270 // get the display connection
271 display = init_display(display_name);
272 // event_display = init_display(display_name);
274 // Fudge window placement
275 root_w = get_root_w(1, 0);
276 root_h = get_root_h(0);
277 if(this->x + this->w > root_w) this->x = root_w - this->w;
278 if(this->y + this->h > root_h) this->y = root_h - this->h;
279 if(this->x < 0) this->x = 0;
280 if(this->y < 0) this->y = 0;
281 screen = DefaultScreen(display);
283 rootwin = RootWindow(display, screen);
284 vis = DefaultVisual(display, screen);
285 default_depth = DefaultDepth(display, screen);
286 client_byte_order = (*(u_int32_t*)"a ") & 0x00000001;
287 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
291 // This must be done before fonts to know if antialiasing is available.
294 if(resources.use_shm < 0) resources.initialize_display(this);
295 x_correction = get_resources()->get_left_border();
296 y_correction = get_resources()->get_top_border();
298 if(this->bg_color == -1)
299 this->bg_color = resources.get_bg_color();
310 attr.event_mask = DEFAULT_EVENT_MASKS |
311 StructureNotifyMask |
314 attr.background_pixel = get_color(this->bg_color);
315 attr.colormap = cmap;
316 attr.cursor = get_cursor_struct(ARROW_CURSOR);
318 win = XCreateWindow(display,
325 top_level->default_depth,
331 XGetNormalHints(display, win, &size_hints);
333 size_hints.flags = PSize | PMinSize | PMaxSize;
334 size_hints.width = this->w;
335 size_hints.height = this->h;
336 size_hints.min_width = allow_resize ? minw : this->w;
337 size_hints.max_width = allow_resize ? 32767 : this->w;
338 size_hints.min_height = allow_resize ? minh : this->h;
339 size_hints.max_height = allow_resize ? 32767 : this->h;
340 if(x > -BC_INFINITY && x < BC_INFINITY)
342 size_hints.flags |= PPosition;
343 size_hints.x = this->x;
344 size_hints.y = this->y;
347 XSetStandardProperties(display,
357 clipboard = new BC_Clipboard(display_name);
358 clipboard->start_clipboard();
362 Atom ClientLeaderXAtom;
363 if (XGroupLeader == 0)
365 char *instance_name = "cinelerra";
366 char *class_name = "Cinelerra";
367 XClassHint *class_hints = XAllocClassHint();
368 class_hints->res_name = instance_name;
369 class_hints->res_class = class_name;
370 XSetClassHint(top_level->display, win, class_hints);
372 ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
373 XChangeProperty(display,
379 (unsigned char *)&XGroupLeader,
386 #ifdef HAVE_LIBXXF86VM
387 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
394 #ifdef HAVE_LIBXXF86VM
395 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
397 if(window_type == POPUP_WINDOW)
407 attr.event_mask = DEFAULT_EVENT_MASKS |
410 if(this->bg_color == -1)
411 this->bg_color = resources.get_bg_color();
412 attr.background_pixel = top_level->get_color(bg_color);
413 attr.colormap = top_level->cmap;
414 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
415 attr.override_redirect = True;
416 attr.save_under = True;
418 win = XCreateWindow(top_level->display,
425 top_level->default_depth,
432 if(window_type == SUB_WINDOW)
434 mask = CWBackPixel | CWEventMask;
435 attr.event_mask = DEFAULT_EVENT_MASKS;
436 attr.background_pixel = top_level->get_color(this->bg_color);
437 win = XCreateWindow(top_level->display,
444 top_level->default_depth,
450 XMapWindow(top_level->display, win);
453 // Create pixmap for all windows
454 pixmap = XCreatePixmap(top_level->display,
458 top_level->default_depth);
460 // Create truetype rendering surface
462 if(get_resources()->use_xft)
464 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n",
465 // top_level->display,
469 xft_drawable = XftDrawCreate(top_level->display,
473 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n",
475 // top_level->display,
482 // Set up options for main window
483 if(window_type == MAIN_WINDOW)
485 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
487 this->bg_pixmap = new BC_Pixmap(this,
488 get_resources()->bg_image,
492 if(!hidden) show_window();
499 draw_background(0, 0, this->w, this->h);
502 // Set up options for popup window
503 #ifdef HAVE_LIBXXF86VM
504 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
506 if(window_type == POPUP_WINDOW)
510 if(!hidden) show_window();
515 Display* BC_WindowBase::init_display(char *display_name)
519 if(display_name && display_name[0] == 0) display_name = NULL;
520 if((display = XOpenDisplay(display_name)) == NULL)
522 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
524 if(getenv("DISPLAY") == NULL)
526 printf("'DISPLAY' environment variable not set.\n");
530 // Try again with default display.
532 if((display = XOpenDisplay(0)) == NULL)
534 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
542 int BC_WindowBase::run_window()
548 // Events may have been sent before run_window so can't initialize them here.
551 if(window_type == MAIN_WINDOW)
553 // tooltip_id = get_repeat_id();
554 set_repeat(get_resources()->tooltip_delay);
557 // Start X server events
558 event_thread = new BC_WindowEvents(this);
559 event_thread->start();
561 // Start common events
567 unset_all_repeaters();
571 event_condition->reset();
572 common_events.remove_all_objects();
578 int BC_WindowBase::get_key_masks(XEvent *event)
580 // printf("BC_WindowBase::get_key_masks %llx\n",
581 // event->xkey.state);
583 ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
585 shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
586 alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
596 int BC_WindowBase::dispatch_event()
603 XClientMessageEvent *ptr;
605 int cancel_resize, cancel_translation;
609 // If an event is waiting get it, otherwise
610 // wait for next event only if there are no compressed events.
611 if(get_event_count() ||
612 (!motion_events && !resize_events && !translation_events))
614 // XNextEvent(display, event);
616 // Lock out window deletions
617 lock_window("BC_WindowBase::dispatch_event 1");
618 // get_key_masks(event);
621 // Handle compressed events
623 lock_window("BC_WindowBase::dispatch_event 2");
625 dispatch_resize_event(last_resize_w, last_resize_h);
628 dispatch_motion_event();
630 if(translation_events)
631 dispatch_translation_event();
637 //printf("1 %s %p %d\n", title, event, event->type);
641 get_key_masks(event);
642 // Clear the resize buffer
643 if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
644 // Clear the motion buffer since this can clear the window
647 dispatch_motion_event();
650 ptr = (XClientMessageEvent*)event;
653 if(ptr->message_type == ProtoXAtom &&
654 ptr->data.l[0] == DelWinXAtom)
659 if(ptr->message_type == RepeaterXAtom)
661 dispatch_repeat_event(ptr->data.l[0]);
662 // Make sure the repeater still exists.
663 // for(int i = 0; i < repeaters.total; i++)
665 // if(repeaters.values[i]->repeat_id == ptr->data.l[0])
667 // dispatch_repeat_event_master(ptr->data.l[0]);
673 if(ptr->message_type == SetDoneXAtom)
686 dispatch_focus_out();
698 get_key_masks(event);
699 cursor_x = event->xbutton.x;
700 cursor_y = event->xbutton.y;
701 button_number = event->xbutton.button;
702 event_win = event->xany.window;
703 if (button_number != 4 && button_number != 5)
705 button_pressed = event->xbutton.button;
706 button_time1 = button_time2;
707 button_time2 = event->xbutton.time;
710 drag_win = event_win;
711 drag_x1 = cursor_x - get_resources()->drag_radius;
712 drag_x2 = cursor_x + get_resources()->drag_radius;
713 drag_y1 = cursor_y - get_resources()->drag_radius;
714 drag_y2 = cursor_y + get_resources()->drag_radius;
716 if(button_time2 - button_time1 < resources.double_click)
718 // Ignore triple clicks
720 button_time2 = button_time1 = 0;
725 dispatch_button_press();
729 get_key_masks(event);
730 button_number = event->xbutton.button;
731 event_win = event->xany.window;
732 if (button_number != 4 && button_number != 5)
735 dispatch_button_release();
740 event_win = event->xany.window;
741 dispatch_expose_event();
745 get_key_masks(event);
746 // Dispatch previous motion event if this is a subsequent motion from a different window
747 if(motion_events && last_motion_win != event->xany.window)
749 dispatch_motion_event();
752 // Buffer the current motion
754 last_motion_x = event->xmotion.x;
755 last_motion_y = event->xmotion.y;
756 last_motion_win = event->xany.window;
759 case ConfigureNotify:
760 get_key_masks(event);
761 XTranslateCoordinates(top_level->display,
769 last_resize_w = event->xconfigure.width;
770 last_resize_h = event->xconfigure.height;
773 cancel_translation = 0;
775 // Resize history prevents responses to recursive resize requests
776 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
778 if(resize_history.values[i]->w == last_resize_w &&
779 resize_history.values[i]->h == last_resize_h)
781 delete resize_history.values[i];
782 resize_history.remove_number(i);
787 if(last_resize_w == w && last_resize_h == h)
795 if((last_translate_x == x && last_translate_y == y))
796 cancel_translation = 1;
798 if(!cancel_translation)
800 translation_events = 1;
807 get_key_masks(event);
809 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
811 // printf("BC_WindowBase::dispatch_event 2 %llx\n",
812 // event->xkey.state);
813 // block out control keys
814 if(keysym > 0xffe0 && keysym < 0xffff) break;
817 if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
822 // block out extra keys
832 // Translate key codes
833 case XK_Return: key_pressed = RETURN; break;
834 case XK_Up: key_pressed = UP; break;
835 case XK_Down: key_pressed = DOWN; break;
836 case XK_Left: key_pressed = LEFT; break;
837 case XK_Right: key_pressed = RIGHT; break;
838 case XK_Next: key_pressed = PGDN; break;
839 case XK_Prior: key_pressed = PGUP; break;
840 case XK_BackSpace: key_pressed = BACKSPACE; break;
841 case XK_Escape: key_pressed = ESC; break;
844 key_pressed = LEFTTAB;
848 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
849 case XK_underscore: key_pressed = '_'; break;
850 case XK_asciitilde: key_pressed = '~'; break;
851 case XK_Delete: key_pressed = DELETE; break;
852 case XK_Home: key_pressed = HOME; break;
853 case XK_End: key_pressed = END; break;
856 case XK_KP_Enter: key_pressed = KPENTER; break;
857 case XK_KP_Add: key_pressed = KPPLUS; break;
859 case XK_KP_End: key_pressed = KP1; break;
861 case XK_KP_Down: key_pressed = KP2; break;
863 case XK_KP_Page_Down: key_pressed = KP3; break;
865 case XK_KP_Left: key_pressed = KP4; break;
867 case XK_KP_Begin: key_pressed = KP5; break;
869 case XK_KP_Right: key_pressed = KP6; break;
871 case XK_KP_Insert: key_pressed = KPINS; break;
873 case XK_KP_Delete: key_pressed = KPDEL; break;
875 //key_pressed = keys_return[0];
876 key_pressed = keysym & 0xff;
880 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
881 result = dispatch_keypress_event();
882 // Handle some default keypresses
885 if(key_pressed == 'w' ||
894 event_win = event->xany.window;
895 dispatch_cursor_leave();
899 event_win = event->xany.window;
900 cursor_x = event->xcrossing.x;
901 cursor_y = event->xcrossing.y;
902 dispatch_cursor_enter();
905 //printf("100 %s %p %d\n", title, event, event->type);
908 if(event) delete event;
912 int BC_WindowBase::dispatch_expose_event()
915 for(int i = 0; i < subwindows->total && !result; i++)
917 result = subwindows->values[i]->dispatch_expose_event();
921 if(!result) expose_event();
925 int BC_WindowBase::dispatch_resize_event(int w, int h)
927 if(window_type == MAIN_WINDOW)
930 // Can't store w and h here because bcfilebox depends on the old w and h to
931 // reposition widgets.
932 XFreePixmap(top_level->display, pixmap);
933 pixmap = XCreatePixmap(top_level->display,
937 top_level->default_depth);
938 clear_box(0, 0, w, h);
941 // Propagate to subwindows
942 for(int i = 0; i < subwindows->total; i++)
944 subwindows->values[i]->dispatch_resize_event(w, h);
950 if(window_type == MAIN_WINDOW)
958 int BC_WindowBase::dispatch_translation_event()
960 translation_events = 0;
961 if(window_type == MAIN_WINDOW)
965 x = last_translate_x;
966 y = last_translate_y;
967 // Correct for window manager offsets
972 for(int i = 0; i < subwindows->total; i++)
974 subwindows->values[i]->dispatch_translation_event();
981 int BC_WindowBase::dispatch_motion_event()
985 if(top_level == this)
987 event_win = last_motion_win;
991 if(get_button_down() && !active_menubar && !active_popup_menu)
995 cursor_x = last_motion_x;
996 cursor_y = last_motion_y;
997 result = dispatch_drag_motion();
1001 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
1002 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1007 result = dispatch_drag_start();
1010 cursor_x = last_motion_x;
1011 cursor_y = last_motion_y;
1013 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1014 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1015 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1018 for(int i = 0; i < subwindows->total && !result; i++)
1020 result = subwindows->values[i]->dispatch_motion_event();
1023 if(!result) result = cursor_motion_event(); // give to user
1027 int BC_WindowBase::dispatch_keypress_event()
1030 if(top_level == this)
1032 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1035 for(int i = 0; i < subwindows->total && !result; i++)
1037 result = subwindows->values[i]->dispatch_keypress_event();
1040 if(!result) result = keypress_event();
1045 int BC_WindowBase::dispatch_focus_in()
1047 for(int i = 0; i < subwindows->total; i++)
1049 subwindows->values[i]->dispatch_focus_in();
1057 int BC_WindowBase::dispatch_focus_out()
1059 for(int i = 0; i < subwindows->total; i++)
1061 subwindows->values[i]->dispatch_focus_out();
1069 int BC_WindowBase::get_has_focus()
1071 return top_level->has_focus;
1074 int BC_WindowBase::get_deleting()
1076 if(is_deleting) return 1;
1077 if(parent_window && parent_window->get_deleting()) return 1;
1081 int BC_WindowBase::dispatch_button_press()
1084 if(top_level == this)
1086 if(active_menubar) result = active_menubar->dispatch_button_press();
1087 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1088 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1091 for(int i = 0; i < subwindows->total && !result; i++)
1093 result = subwindows->values[i]->dispatch_button_press();
1096 if(!result) result = button_press_event();
1101 int BC_WindowBase::dispatch_button_release()
1104 if(top_level == this)
1106 if(active_menubar) result = active_menubar->dispatch_button_release();
1107 //printf("BC_WindowBase::dispatch_button_release 1 %d\n", result);
1108 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1109 //printf("BC_WindowBase::dispatch_button_release 2 %p %d\n", active_subwindow, result);
1110 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1111 //printf("BC_WindowBase::dispatch_button_release 3 %d\n", result);
1112 if(!result && button_number != 4 && button_number != 5)
1113 result = dispatch_drag_stop();
1115 //printf("BC_WindowBase::dispatch_button_release 4 %d\n", result);
1117 for(int i = 0; i < subwindows->total && !result; i++)
1119 result = subwindows->values[i]->dispatch_button_release();
1121 //printf("BC_WindowBase::dispatch_button_release 5 %d\n", result);
1125 result = button_release_event();
1127 //printf("BC_WindowBase::dispatch_button_release 6 %d\n", result);
1133 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1136 // all repeat event handlers get called and decide based on activity and duration
1137 // whether to respond
1138 for(int i = 0; i < subwindows->total; i++)
1140 subwindows->values[i]->dispatch_repeat_event(duration);
1142 repeat_event(duration);
1144 // Unlock next signal
1145 if(window_type == MAIN_WINDOW)
1147 for(int i = 0; i < repeaters.total; i++)
1149 if(repeaters.values[i]->delay == duration)
1151 repeaters.values[i]->repeat_lock->unlock();
1159 int BC_WindowBase::dispatch_cursor_leave()
1161 for(int i = 0; i < subwindows->total; i++)
1163 subwindows->values[i]->dispatch_cursor_leave();
1166 cursor_leave_event();
1170 int BC_WindowBase::dispatch_cursor_enter()
1174 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1175 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1176 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1178 for(int i = 0; !result && i < subwindows->total; i++)
1180 result = subwindows->values[i]->dispatch_cursor_enter();
1183 if(!result) result = cursor_enter_event();
1187 int BC_WindowBase::cursor_enter_event()
1192 int BC_WindowBase::cursor_leave_event()
1197 int BC_WindowBase::close_event()
1203 int BC_WindowBase::dispatch_drag_start()
1206 if(active_menubar) result = active_menubar->dispatch_drag_start();
1207 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1208 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1210 for(int i = 0; i < subwindows->total && !result; i++)
1212 result = subwindows->values[i]->dispatch_drag_start();
1215 if(!result) result = is_dragging = drag_start_event();
1219 int BC_WindowBase::dispatch_drag_stop()
1223 for(int i = 0; i < subwindows->total && !result; i++)
1225 result = subwindows->values[i]->dispatch_drag_stop();
1228 if(is_dragging && !result)
1238 int BC_WindowBase::dispatch_drag_motion()
1241 for(int i = 0; i < subwindows->total && !result; i++)
1243 result = subwindows->values[i]->dispatch_drag_motion();
1246 if(is_dragging && !result)
1248 drag_motion_event();
1259 int BC_WindowBase::show_tooltip(int w, int h)
1263 if(!tooltip_on && get_resources()->tooltips_enabled)
1266 top_level->hide_tooltip();
1270 w = get_text_width(MEDIUMFONT, tooltip_text);
1273 h = get_text_height(MEDIUMFONT, tooltip_text);
1275 w += TOOLTIP_MARGIN * 2;
1276 h += TOOLTIP_MARGIN * 2;
1278 XTranslateCoordinates(top_level->display,
1286 tooltip_popup = new BC_Popup(top_level,
1291 get_resources()->tooltip_bg_color);
1294 tooltip_popup->set_font(MEDIUMFONT);
1295 tooltip_popup->flash();
1296 tooltip_popup->flush();
1301 int BC_WindowBase::hide_tooltip()
1304 for(int i = 0; i < subwindows->total; i++)
1306 subwindows->values[i]->hide_tooltip();
1312 delete tooltip_popup;
1318 int BC_WindowBase::set_tooltip(char *text)
1320 strcpy(this->tooltip_text, text);
1321 // Update existing tooltip if it is visible
1325 tooltip_popup->flash();
1330 // signal the event handler to repeat
1331 int BC_WindowBase::set_repeat(int64_t duration)
1335 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1338 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1340 // test repeater database for duplicates
1341 for(int i = 0; i < repeaters.total; i++)
1344 if(repeaters.values[i]->delay == duration)
1346 repeaters.values[i]->start_repeating();
1351 BC_Repeater *repeater = new BC_Repeater(this, duration);
1352 repeater->initialize();
1353 repeaters.append(repeater);
1354 repeater->start_repeating();
1358 int BC_WindowBase::unset_repeat(int64_t duration)
1360 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1362 BC_Repeater *repeater = 0;
1363 for(int i = 0; i < repeaters.total; i++)
1365 if(repeaters.values[i]->delay == duration)
1367 repeaters.values[i]->stop_repeating();
1374 int BC_WindowBase::unset_all_repeaters()
1376 for(int i = 0; i < repeaters.total; i++)
1378 repeaters.values[i]->stop_repeating();
1380 repeaters.remove_all_objects();
1384 // long BC_WindowBase::get_repeat_id()
1386 // return top_level->next_repeat_id++;
1389 int BC_WindowBase::arm_repeat(int64_t duration)
1391 XEvent *event = new XEvent;
1392 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1393 ptr->type = ClientMessage;
1394 ptr->message_type = RepeaterXAtom;
1396 ptr->data.l[0] = duration;
1398 // Couldn't use XSendEvent since it locked up randomly.
1400 // XSendEvent(top_level->event_display,
1409 int BC_WindowBase::get_atoms()
1411 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
1412 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1413 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
1414 if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1415 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1419 void BC_WindowBase::init_cursors()
1421 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1422 cross_cursor = XCreateFontCursor(display, XC_crosshair);
1423 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1424 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1425 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1426 move_cursor = XCreateFontCursor(display, XC_fleur);
1427 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1428 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1429 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1430 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1431 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1432 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1433 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1434 hourglass_cursor = XCreateFontCursor(display, XC_watch);
1437 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1443 color_model = BC_RGB8;
1446 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1449 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1452 color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1458 int BC_WindowBase::init_colors()
1461 current_color_value = current_color_pixel = 0;
1463 // Get the real depth
1466 ximage = XCreateImage(top_level->display,
1468 top_level->default_depth,
1476 bits_per_pixel = ximage->bits_per_pixel;
1477 XDestroyImage(ximage);
1479 color_model = evaluate_color_model(client_byte_order,
1482 // Get the color model
1488 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1489 create_private_colors();
1493 cmap = DefaultColormap(display, screen);
1494 create_shared_colors();
1497 allocate_color_table();
1499 get_resources()->use_xft = 0;
1503 cmap = DefaultColormap(display, screen);
1509 int BC_WindowBase::create_private_colors()
1514 for(int i = 0; i < 255; i++)
1516 color = (i & 0xc0) << 16;
1517 color += (i & 0x38) << 10;
1518 color += (i & 0x7) << 5;
1519 color_table[i][0] = color;
1521 create_shared_colors(); // overwrite the necessary colors on the table
1526 int BC_WindowBase::create_color(int color)
1528 if(total_colors == 256)
1530 // replace the closest match with an exact match
1531 color_table[get_color_rgb8(color)][0] = color;
1535 // add the color to the table
1536 color_table[total_colors][0] = color;
1542 int BC_WindowBase::create_shared_colors()
1544 create_color(BLACK);
1545 create_color(WHITE);
1547 create_color(LTGREY);
1548 create_color(MEGREY);
1549 create_color(MDGREY);
1550 create_color(DKGREY);
1552 create_color(LTCYAN);
1553 create_color(MECYAN);
1554 create_color(MDCYAN);
1555 create_color(DKCYAN);
1557 create_color(LTGREEN);
1558 create_color(GREEN);
1559 create_color(DKGREEN);
1561 create_color(LTPINK);
1565 create_color(LTBLUE);
1567 create_color(DKBLUE);
1569 create_color(LTYELLOW);
1570 create_color(MEYELLOW);
1571 create_color(MDYELLOW);
1572 create_color(DKYELLOW);
1574 create_color(LTPURPLE);
1575 create_color(MEPURPLE);
1576 create_color(MDPURPLE);
1577 create_color(DKPURPLE);
1579 create_color(FGGREY);
1580 create_color(MNBLUE);
1581 create_color(ORANGE);
1582 create_color(FTGREY);
1587 int BC_WindowBase::allocate_color_table()
1589 int red, green, blue, color;
1593 for(int i = 0; i < total_colors; i++)
1595 color = color_table[i][0];
1596 red = (color & 0xFF0000) >> 16;
1597 green = (color & 0x00FF00) >> 8;
1598 blue = color & 0xFF;
1600 col.flags = DoRed | DoGreen | DoBlue;
1601 col.red = red<<8 | red;
1602 col.green = green<<8 | green;
1603 col.blue = blue<<8 | blue;
1605 XAllocColor(display, cmap, &col);
1606 color_table[i][1] = col.pixel;
1609 XInstallColormap(display, cmap);
1613 int BC_WindowBase::init_window_shape()
1615 if(bg_pixmap && bg_pixmap->use_alpha())
1617 XShapeCombineMask(top_level->display,
1622 bg_pixmap->get_alpha(),
1629 int BC_WindowBase::init_gc()
1631 unsigned long gcmask;
1632 gcmask = GCFont | GCGraphicsExposures;
1635 gcvalues.font = mediumfont->fid; // set the font
1636 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
1637 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1641 int BC_WindowBase::init_fonts()
1643 if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL &&
1644 (largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1645 largefont = XLoadQueryFont(display, "fixed");
1647 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL &&
1648 (mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1649 mediumfont = XLoadQueryFont(display, "fixed");
1651 if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL &&
1652 (smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1653 smallfont = XLoadQueryFont(display, "fixed");
1656 if(get_resources()->use_xft)
1660 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
1662 if(!(largefont_xft = XftFontOpenXlfd(display,
1664 resources.large_font_xft)))
1666 largefont_xft = XftFontOpenXlfd(display,
1670 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
1671 if(!(largefont_xft = XftFontOpenXlfd(display,
1673 resources.large_font_xft)))
1675 largefont_xft = XftFontOpenXlfd(display,
1679 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
1682 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1684 resources.medium_font_xft)))
1686 mediumfont_xft = XftFontOpenXlfd(display,
1692 if(!(smallfont_xft = XftFontOpenXlfd(display,
1694 resources.small_font_xft)))
1696 smallfont_xft = XftFontOpenXlfd(display,
1701 //printf("BC_WindowBase::init_fonts 100 %s %p\n",
1702 //resources.medium_font,
1705 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
1706 resources.large_font_xft,
1708 resources.medium_font_xft,
1710 resources.small_font_xft,
1713 // Extension failed to locate fonts
1714 if(!largefontset || !mediumfontset || !smallfontset)
1716 printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1717 resources.large_font_xft,
1719 resources.medium_font_xft,
1721 resources.small_font_xft,
1723 get_resources()->use_xft = 0;
1728 if(get_resources()->use_fontset)
1733 // FIXME: should check the m,d,n values
1734 if((largefontset = XCreateFontSet(display,
1735 resources.large_fontset,
1739 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1740 if((mediumfontset = XCreateFontSet(display,
1741 resources.medium_fontset,
1745 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1746 if((smallfontset = XCreateFontSet(display,
1747 resources.small_fontset,
1751 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1753 if(largefontset && mediumfontset && smallfontset)
1755 curr_fontset = mediumfontset;
1756 get_resources()->use_fontset = 1;
1761 get_resources()->use_fontset = 0;
1768 int BC_WindowBase::get_color(int64_t color)
1770 // return pixel of color
1771 // use this only for drawing subwindows not for bitmaps
1772 int i, test, difference, result;
1779 return get_color_rgb8(color);
1783 // test last color looked up
1784 if(current_color_value == color) return current_color_pixel;
1787 current_color_value = color;
1788 for(i = 0; i < total_colors; i++)
1790 if(color_table[i][0] == color)
1792 current_color_pixel = color_table[i][1];
1793 return current_color_pixel;
1797 // find nearest match
1798 difference = 0xFFFFFF;
1800 for(i = 0, result = 0; i < total_colors; i++)
1802 test = abs((int)(color_table[i][0] - color));
1804 if(test < difference)
1806 current_color_pixel = color_table[i][1];
1811 return current_color_pixel;
1816 return get_color_rgb16(color);
1820 return get_color_bgr16(color);
1825 if(client_byte_order == server_byte_order)
1828 get_color_bgr24(color);
1838 int BC_WindowBase::get_color_rgb8(int color)
1842 pixel = (color & 0xc00000) >> 16;
1843 pixel += (color & 0xe000) >> 10;
1844 pixel += (color & 0xe0) >> 5;
1848 int64_t BC_WindowBase::get_color_rgb16(int color)
1851 result = (color & 0xf80000) >> 8;
1852 result += (color & 0xfc00) >> 5;
1853 result += (color & 0xf8) >> 3;
1858 int64_t BC_WindowBase::get_color_bgr16(int color)
1861 result = (color & 0xf80000) >> 19;
1862 result += (color & 0xfc00) >> 5;
1863 result += (color & 0xf8) << 8;
1868 int64_t BC_WindowBase::get_color_bgr24(int color)
1871 result = (color & 0xff) << 16;
1872 result += (color & 0xff00);
1873 result += (color & 0xff0000) >> 16;
1877 int BC_WindowBase::video_is_on()
1882 void BC_WindowBase::start_video()
1885 // set_color(BLACK);
1886 // draw_box(0, 0, get_w(), get_h());
1890 void BC_WindowBase::stop_video()
1897 int64_t BC_WindowBase::get_color()
1899 return top_level->current_color;
1902 void BC_WindowBase::set_color(int64_t color)
1904 top_level->current_color = color;
1905 XSetForeground(top_level->display,
1907 top_level->get_color(color));
1910 void BC_WindowBase::set_opaque()
1912 XSetFunction(top_level->display, top_level->gc, GXcopy);
1915 void BC_WindowBase::set_inverse()
1917 XSetFunction(top_level->display, top_level->gc, GXxor);
1920 Cursor BC_WindowBase::get_cursor_struct(int cursor)
1924 case ARROW_CURSOR: return top_level->arrow_cursor; break;
1925 case CROSS_CURSOR: return top_level->cross_cursor;
1926 case IBEAM_CURSOR: return top_level->ibeam_cursor; break;
1927 case VSEPARATE_CURSOR: return top_level->vseparate_cursor; break;
1928 case HSEPARATE_CURSOR: return top_level->hseparate_cursor; break;
1929 case MOVE_CURSOR: return top_level->move_cursor; break;
1930 case LEFT_CURSOR: return top_level->left_cursor; break;
1931 case RIGHT_CURSOR: return top_level->right_cursor; break;
1932 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor; break;
1933 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor; break;
1934 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor; break;
1935 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor; break;
1936 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor; break;
1937 case HOURGLASS_CURSOR: return top_level->hourglass_cursor; break;
1942 void BC_WindowBase::set_cursor(int cursor, int is_hourglass)
1944 // don't change cursor if hourglass mode unless the caller is the hourglass routine.
1945 if(is_hourglass || current_cursor != HOURGLASS_CURSOR)
1947 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
1948 current_cursor = cursor;
1952 // save new cursor for later
1954 prev_cursor = cursor;
1958 void BC_WindowBase::set_x_cursor(int cursor)
1960 temp_cursor = XCreateFontCursor(top_level->display, cursor);
1961 XDefineCursor(top_level->display, win, temp_cursor);
1962 current_cursor = cursor;
1966 int BC_WindowBase::get_cursor()
1968 return current_cursor;
1971 void BC_WindowBase::start_hourglass()
1973 top_level->start_hourglass_recursive();
1977 void BC_WindowBase::stop_hourglass()
1979 top_level->stop_hourglass_recursive();
1983 void BC_WindowBase::start_hourglass_recursive()
1985 if(this == top_level)
1988 if(current_cursor == HOURGLASS_CURSOR) return;
1991 prev_cursor = current_cursor;
1992 set_cursor(HOURGLASS_CURSOR, 1);
1993 for(int i = 0; i < subwindows->total; i++)
1995 subwindows->values[i]->start_hourglass_recursive();
1999 void BC_WindowBase::stop_hourglass_recursive()
2001 if(this == top_level)
2003 if(hourglass_total == 0) return;
2007 // Cause set_cursor to perform change
2008 set_cursor(prev_cursor, 1);
2009 for(int i = 0; i < subwindows->total; i++)
2011 subwindows->values[i]->stop_hourglass_recursive();
2020 XFontStruct* BC_WindowBase::get_font_struct(int font)
2022 // Clear out unrelated flags
2023 if(font & BOLDFACE) font ^= BOLDFACE;
2027 case MEDIUMFONT: return top_level->mediumfont; break;
2028 case SMALLFONT: return top_level->smallfont; break;
2029 case LARGEFONT: return top_level->largefont; break;
2034 XFontSet BC_WindowBase::get_fontset(int font)
2038 if(get_resources()->use_fontset)
2042 case SMALLFONT: fs = top_level->smallfontset; break;
2043 case LARGEFONT: fs = top_level->largefontset; break;
2044 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2052 XftFont* BC_WindowBase::get_xft_struct(int font)
2054 // Clear out unrelated flags
2055 if(font & BOLDFACE) font ^= BOLDFACE;
2059 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft; break;
2060 case SMALLFONT: return (XftFont*)top_level->smallfont_xft; break;
2061 case LARGEFONT: return (XftFont*)top_level->largefont_xft; break;
2078 void BC_WindowBase::set_font(int font)
2080 top_level->current_font = font;
2084 if(get_resources()->use_xft)
2090 if(get_resources()->use_fontset)
2095 if(get_font_struct(font))
2097 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2103 void BC_WindowBase::set_fontset(int font)
2107 if(get_resources()->use_fontset)
2111 case SMALLFONT: fs = top_level->smallfontset; break;
2112 case LARGEFONT: fs = top_level->largefontset; break;
2113 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2121 XFontSet BC_WindowBase::get_curr_fontset(void)
2123 if(get_resources()->use_fontset)
2124 return curr_fontset;
2128 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2131 if(get_resources()->use_xft && get_xft_struct(font))
2134 XftTextExtents8(top_level->display,
2135 get_xft_struct(font),
2139 return extents.xOff;
2143 if(get_resources()->use_fontset && top_level->get_fontset(font))
2144 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2146 if(get_font_struct(font))
2147 return XTextWidth(get_font_struct(font), text, length);
2153 case MEDIUM_7SEGMENT:
2154 return get_resources()->medium_7segment[0]->get_w() * length;
2164 int BC_WindowBase::get_text_width(int font, char *text, int length)
2166 int i, j, w = 0, line_w = 0;
2167 if(length < 0) length = strlen(text);
2169 for(i = 0, j = 0; i <= length; i++)
2174 line_w = get_single_text_width(font, &text[j], i - j);
2180 line_w = get_single_text_width(font, &text[j], length - j);
2182 if(line_w > w) w = line_w;
2185 if(i > length && w == 0)
2187 w = get_single_text_width(font, text, length);
2193 int BC_WindowBase::get_text_ascent(int font)
2196 if(get_resources()->use_xft && get_xft_struct(font))
2199 XftTextExtents8(top_level->display,
2200 get_xft_struct(font),
2208 if(get_resources()->use_fontset && top_level->get_fontset(font))
2210 XFontSetExtents *extents;
2212 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2213 return -extents->max_logical_extent.y;
2216 if(get_font_struct(font))
2217 return top_level->get_font_struct(font)->ascent;
2221 case MEDIUM_7SEGMENT:
2222 return get_resources()->medium_7segment[0]->get_h();
2230 int BC_WindowBase::get_text_descent(int font)
2233 if(get_resources()->use_xft && get_xft_struct(font))
2236 XftTextExtents8(top_level->display,
2237 get_xft_struct(font),
2241 return extents.height - extents.y;
2245 if(get_resources()->use_fontset && top_level->get_fontset(font))
2247 XFontSetExtents *extents;
2249 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2250 return (extents->max_logical_extent.height
2251 + extents->max_logical_extent.y);
2254 if(get_font_struct(font))
2255 return top_level->get_font_struct(font)->descent;
2264 int BC_WindowBase::get_text_height(int font, char *text)
2266 if(!text) return get_text_ascent(font) + get_text_descent(font);
2268 // Add height of lines
2269 int h = 0, i, length = strlen(text);
2270 for(i = 0; i <= length; i++)
2278 return h * (get_text_ascent(font) + get_text_descent(font));
2281 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2283 if(color_model < 0) color_model = top_level->get_color_model();
2284 return new BC_Bitmap(top_level, w, h, color_model);
2287 int BC_WindowBase::accel_available(int color_model, int lock_it)
2289 if(window_type != MAIN_WINDOW)
2290 return top_level->accel_available(color_model, lock_it);
2294 if(lock_it) lock_window("BC_WindowBase::accel_available");
2298 result = grab_port_id(this, color_model);
2301 xvideo_port_id = result;
2313 //printf("BC_WindowBase::accel_available 1\n");
2314 result = grab_port_id(this, color_model);
2315 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2318 xvideo_port_id = result;
2323 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2331 if(lock_it) unlock_window();
2332 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2337 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2339 int numFormats, i, j, k;
2340 unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2342 XvAdaptorInfo *info;
2343 XvImageFormatValues *formats;
2346 if(!get_resources()->use_xvideo) return -1;
2348 // Translate from color_model to X color model
2349 x_color_model = cmodel_bc_to_x(color_model);
2351 // Only local server is fast enough.
2352 if(!resources.use_shm) return -1;
2354 // XV extension is available
2355 if(Success != XvQueryExtension(window->display,
2365 // XV adaptors are available
2366 XvQueryAdaptors(window->display,
2367 DefaultRootWindow(window->display),
2376 // Get adaptor with desired color model
2377 for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2379 /* adaptor supports XvImages */
2380 if(info[i].type & XvImageMask)
2382 formats = XvListImageFormats(window->display,
2385 // for(j = 0; j < numFormats; j++)
2386 // printf("%08x\n", formats[j].id);
2388 for(j = 0; j < numFormats && xvideo_port_id < 0; j++)
2390 /* this adaptor supports the desired format */
2391 if(formats[j].id == x_color_model)
2393 /* Try to grab a port */
2394 for(k = 0; k < info[i].num_ports; k++)
2397 if(Success == XvGrabPort(top_level->display,
2398 info[i].base_id + k,
2401 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2402 xvideo_port_id = info[i].base_id + k;
2408 if(formats) XFree(formats);
2412 XvFreeAdaptorInfo(info);
2414 return xvideo_port_id;
2418 int BC_WindowBase::show_window(int flush)
2420 XMapWindow(top_level->display, win);
2421 if(flush) XFlush(top_level->display);
2422 // XSync(top_level->display, 0);
2427 int BC_WindowBase::hide_window(int flush)
2429 XUnmapWindow(top_level->display, win);
2430 if(flush) XFlush(top_level->display);
2435 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2437 subwindows->append((BC_SubWindow*)menu_bar);
2439 menu_bar->parent_window = this;
2440 menu_bar->top_level = this->top_level;
2441 menu_bar->initialize();
2445 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2447 subwindows->append(subwindow);
2449 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2451 // parent window must be set before the subwindow initialization
2452 subwindow->parent_window = this;
2453 subwindow->top_level = this->top_level;
2455 // Execute derived initialization
2456 subwindow->initialize();
2461 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2463 return add_subwindow(subwindow);
2466 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2469 XSetWindowBackgroundPixmap(top_level->display, win, pixmap);
2472 XClearArea(top_level->display, win, x, y, w, h, 0);
2476 XClearWindow(top_level->display, win);
2484 int BC_WindowBase::flash(int flush)
2486 flash(-1, -1, -1, -1, flush);
2489 void BC_WindowBase::flush()
2491 XFlush(top_level->display);
2494 void BC_WindowBase::sync_display()
2496 XSync(top_level->display, False);
2499 int BC_WindowBase::get_window_lock()
2501 return top_level->window_lock;
2504 int BC_WindowBase::lock_window(char *location)
2506 if(top_level && top_level != this)
2508 top_level->lock_window(location);
2513 SET_LOCK(this, title, location);
2514 XLockDisplay(top_level->display);
2516 top_level->window_lock = 1;
2520 printf("BC_WindowBase::lock_window top_level NULL\n");
2525 int BC_WindowBase::unlock_window()
2527 if(top_level && top_level != this)
2529 top_level->unlock_window();
2535 top_level->window_lock = 0;
2536 XUnlockDisplay(top_level->display);
2540 printf("BC_WindowBase::unlock_window top_level NULL\n");
2545 void BC_WindowBase::set_done(int return_value)
2547 if(window_type != MAIN_WINDOW)
2548 top_level->set_done(return_value);
2552 XEvent *event = new XEvent;
2553 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2555 event->type = ClientMessage;
2556 ptr->message_type = SetDoneXAtom;
2558 this->return_value = return_value;
2560 // May lock up here because XSendEvent doesn't work too well
2561 // asynchronous with XNextEvent.
2562 // This causes BC_WindowEvents to forward a copy of the event to run_window where
2564 event_thread->done = 1;
2575 int BC_WindowBase::get_w()
2580 int BC_WindowBase::get_h()
2585 int BC_WindowBase::get_x()
2590 int BC_WindowBase::get_y()
2595 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2597 if(lock_display) lock_window("BC_WindowBase::get_root_w");
2598 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2599 int result = WidthOfScreen(screen_ptr);
2600 // Wider than 16:9, narrower than dual head
2601 if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2603 if(lock_display) unlock_window();
2607 int BC_WindowBase::get_root_h(int lock_display)
2609 if(lock_display) lock_window("BC_WindowBase::get_root_h");
2610 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2611 int result = HeightOfScreen(screen_ptr);
2612 if(lock_display) unlock_window();
2616 // Bottom right corner
2617 int BC_WindowBase::get_x2()
2622 int BC_WindowBase::get_y2()
2627 int BC_WindowBase::get_video_on()
2632 int BC_WindowBase::get_hidden()
2634 return top_level->hidden;
2637 int BC_WindowBase::cursor_inside()
2639 return (top_level->cursor_x >= 0 &&
2640 top_level->cursor_y >= 0 &&
2641 top_level->cursor_x < w &&
2642 top_level->cursor_y < h);
2645 BC_WindowBase* BC_WindowBase::get_top_level()
2650 BC_WindowBase* BC_WindowBase::get_parent()
2652 return parent_window;
2655 int BC_WindowBase::get_color_model()
2657 return top_level->color_model;
2660 BC_Resources* BC_WindowBase::get_resources()
2662 return &BC_WindowBase::resources;
2665 int BC_WindowBase::get_bg_color()
2670 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2675 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2677 top_level->active_subwindow = subwindow;
2680 int BC_WindowBase::activate()
2685 int BC_WindowBase::deactivate()
2687 if(window_type == MAIN_WINDOW)
2689 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2690 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2691 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2693 top_level->active_menubar = 0;
2694 top_level->active_popup_menu = 0;
2695 top_level->active_subwindow = 0;
2700 int BC_WindowBase::cycle_textboxes(int amount)
2703 BC_WindowBase *new_textbox = 0;
2707 BC_WindowBase *first_textbox = 0;
2708 find_next_textbox(&first_textbox, &new_textbox, result);
2709 if(!new_textbox) new_textbox = first_textbox;
2715 BC_WindowBase *last_textbox = 0;
2716 find_prev_textbox(&last_textbox, &new_textbox, result);
2717 if(!new_textbox) new_textbox = last_textbox;
2721 if(new_textbox != active_subwindow)
2724 new_textbox->activate();
2730 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2732 // Search subwindows for textbox
2733 for(int i = 0; i < subwindows->total && result < 2; i++)
2735 BC_WindowBase *test_subwindow = subwindows->values[i];
2736 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2743 if(!*first_textbox) *first_textbox = this;
2747 if(top_level->active_subwindow == this)
2753 *next_textbox = this;
2760 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2766 if(!*last_textbox) *last_textbox = this;
2770 if(top_level->active_subwindow == this)
2776 *prev_textbox = this;
2781 // Search subwindows for textbox
2782 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2784 BC_WindowBase *test_subwindow = subwindows->values[i];
2785 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2790 BC_Clipboard* BC_WindowBase::get_clipboard()
2792 return top_level->clipboard;
2795 int BC_WindowBase::get_relative_cursor_x()
2797 int abs_x, abs_y, x, y, win_x, win_y;
2798 unsigned int temp_mask;
2801 XQueryPointer(top_level->display,
2811 XTranslateCoordinates(top_level->display,
2823 int BC_WindowBase::get_relative_cursor_y()
2825 int abs_x, abs_y, x, y, win_x, win_y;
2826 unsigned int temp_mask;
2829 XQueryPointer(top_level->display,
2839 XTranslateCoordinates(top_level->display,
2851 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2853 int abs_x, abs_y, win_x, win_y;
2854 unsigned int temp_mask;
2858 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2860 XQueryPointer(top_level->display,
2870 if(lock_window) this->unlock_window();
2875 int BC_WindowBase::get_abs_cursor_y(int lock_window)
2877 int abs_x, abs_y, win_x, win_y;
2878 unsigned int temp_mask;
2881 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
2882 XQueryPointer(top_level->display,
2891 if(lock_window) this->unlock_window();
2895 int BC_WindowBase::match_window(Window win)
2897 if (this->win == win) return 1;
2899 for(int i = 0; i < subwindows->total; i++)
2901 result = subwindows->values[i]->match_window(win);
2902 if (result) return result;
2908 int BC_WindowBase::get_cursor_over_window()
2910 if(top_level != this) return top_level->get_cursor_over_window();
2912 int abs_x, abs_y, win_x, win_y;
2913 unsigned int temp_mask;
2914 Window temp_win1, temp_win2;
2916 if (!XQueryPointer(display,
2927 int result = match_window(temp_win2) ;
2931 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
2936 translate_coordinates(top_level->event_win,
2938 top_level->cursor_x,
2939 top_level->cursor_y,
2945 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
2950 translate_coordinates(top_level->event_win,
2952 top_level->cursor_x,
2953 top_level->cursor_y,
2959 int BC_WindowBase::get_drag_x()
2961 return top_level->drag_x;
2964 int BC_WindowBase::get_drag_y()
2966 return top_level->drag_y;
2969 int BC_WindowBase::get_cursor_x()
2971 return top_level->cursor_x;
2974 int BC_WindowBase::get_cursor_y()
2976 return top_level->cursor_y;
2979 int BC_WindowBase::is_event_win()
2981 return this->win == top_level->event_win;
2984 void BC_WindowBase::set_dragging(int value)
2986 is_dragging = value;
2989 int BC_WindowBase::get_dragging()
2994 int BC_WindowBase::get_buttonpress()
2996 return top_level->button_number;
2999 int BC_WindowBase::get_button_down()
3001 return top_level->button_down;
3004 int BC_WindowBase::alt_down()
3006 return top_level->alt_mask;
3009 int BC_WindowBase::shift_down()
3011 return top_level->shift_mask;
3014 int BC_WindowBase::ctrl_down()
3016 return top_level->ctrl_mask;
3020 int BC_WindowBase::get_keypress()
3022 return top_level->key_pressed;
3025 int BC_WindowBase::get_double_click()
3027 return top_level->double_click;
3030 int BC_WindowBase::get_bgcolor()
3035 int BC_WindowBase::resize_window(int w, int h)
3037 if(window_type == MAIN_WINDOW && !allow_resize)
3039 XSizeHints size_hints;
3040 size_hints.flags = PSize | PMinSize | PMaxSize;
3041 size_hints.width = w;
3042 size_hints.height = h;
3043 size_hints.min_width = w;
3044 size_hints.max_width = w;
3045 size_hints.min_height = h;
3046 size_hints.max_height = h;
3047 XSetNormalHints(top_level->display, win, &size_hints);
3049 XResizeWindow(top_level->display, win, w, h);
3053 XFreePixmap(top_level->display, pixmap);
3054 pixmap = XCreatePixmap(top_level->display, win, w, h, top_level->default_depth);
3056 // Propagate to menubar
3057 for(int i = 0; i < subwindows->total; i++)
3059 subwindows->values[i]->dispatch_resize_event(w, h);
3062 draw_background(0, 0, w, h);
3063 if(top_level == this && get_resources()->recursive_resizing)
3064 resize_history.append(new BC_ResizeCall(w, h));
3068 // The only way for resize events to be propagated is by updating the internal w and h
3069 int BC_WindowBase::resize_event(int w, int h)
3071 if(window_type == MAIN_WINDOW)
3079 int BC_WindowBase::reposition_widget(int x, int y, int w, int h)
3081 return(reposition_window(x, y, w, h));
3084 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3088 // Some tools set their own dimensions before calling this, causing the
3089 // resize check to skip.
3093 if(w > 0 && w != this->w)
3099 if(h > 0 && h != this->h)
3105 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3108 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3110 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3112 if(translation_count && window_type == MAIN_WINDOW)
3114 // KDE shifts window right and down.
3115 // FVWM leaves window alone and adds border around it.
3116 XMoveResizeWindow(top_level->display,
3118 x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x,
3119 y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y,
3125 XMoveResizeWindow(top_level->display,
3135 XFreePixmap(top_level->display, pixmap);
3136 pixmap = XCreatePixmap(top_level->display,
3140 top_level->default_depth);
3142 // Propagate to menubar
3143 for(int i = 0; i < subwindows->total; i++)
3145 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3148 // draw_background(0, 0, w, h);
3154 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3156 get_resources()->tooltips_enabled = tooltips_enabled;
3160 int BC_WindowBase::raise_window(int do_flush)
3162 XRaiseWindow(top_level->display, win);
3163 if(do_flush) XFlush(top_level->display);
3167 void BC_WindowBase::set_background(VFrame *bitmap)
3169 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3171 bg_pixmap = new BC_Pixmap(this,
3174 shared_bg_pixmap = 0;
3175 draw_background(0, 0, w, h);
3178 void BC_WindowBase::set_title(char *text)
3180 XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0);
3181 strcpy(this->title, _(text));
3185 char* BC_WindowBase::get_title()
3190 int BC_WindowBase::get_toggle_value()
3192 return toggle_value;
3195 int BC_WindowBase::get_toggle_drag()
3200 int BC_WindowBase::set_icon(VFrame *data)
3202 if(icon_pixmap) delete icon_pixmap;
3203 icon_pixmap = new BC_Pixmap(top_level,
3208 icon_window = new BC_Popup(this,
3211 icon_pixmap->get_w(),
3212 icon_pixmap->get_h(),
3214 1, // All windows are hidden initially
3218 wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3219 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3220 wm_hints.icon_mask = icon_pixmap->get_alpha();
3221 wm_hints.icon_window = icon_window->win;
3222 wm_hints.window_group = XGroupLeader;
3224 // for(int i = 0; i < 1000; i++)
3225 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3228 XSetWMHints(top_level->display, top_level->win, &wm_hints);
3229 XSync(top_level->display, 0);
3233 int BC_WindowBase::set_w(int w)
3239 int BC_WindowBase::set_h(int h)
3245 int BC_WindowBase::load_defaults(Defaults *defaults)
3247 BC_Resources *resources = get_resources();
3248 char string[BCTEXTLEN];
3249 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3251 sprintf(string, "FILEBOX_HISTORY%d", i);
3252 resources->filebox_history[i][0] = 0;
3253 defaults->get(string, resources->filebox_history[i]);
3255 resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3256 resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3257 resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3258 defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3262 int BC_WindowBase::save_defaults(Defaults *defaults)
3264 BC_Resources *resources = get_resources();
3265 char string[BCTEXTLEN];
3266 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3268 sprintf(string, "FILEBOX_HISTORY%d", i);
3269 defaults->update(string, resources->filebox_history[i]);
3271 defaults->update("FILEBOX_MODE", resources->filebox_mode);
3272 defaults->update("FILEBOX_W", resources->filebox_w);
3273 defaults->update("FILEBOX_H", resources->filebox_h);
3274 defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3280 // For some reason XTranslateCoordinates can take a long time to return.
3281 // We work around this by only calling it when the event windows are different.
3282 void BC_WindowBase::translate_coordinates(Window src_w,
3294 *dest_x_return = src_x;
3295 *dest_y_return = src_y;
3299 XTranslateCoordinates(top_level->display,
3307 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3317 #ifdef HAVE_LIBXXF86VM
3318 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3322 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3324 XF86VidModeModeInfo **vm_modelines;
3325 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3326 for (i = 0; i < vm_count; i++) {
3327 if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3330 display = top_level->display;
3331 if (vm_modelines[*vm]->hdisplay == *width)
3335 *width = vm_modelines[*vm]->hdisplay;
3336 *height = vm_modelines[*vm]->vdisplay;
3341 void BC_WindowBase::scale_vm(int vm)
3343 int foo,bar,dotclock;
3344 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3347 XF86VidModeModeInfo **vm_modelines;
3348 XF86VidModeModeLine vml;
3349 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3350 XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3351 orig_modeline.dotclock = dotclock;
3352 orig_modeline.hdisplay = vml.hdisplay;
3353 orig_modeline.hsyncstart = vml.hsyncstart;
3354 orig_modeline.hsyncend = vml.hsyncend;
3355 orig_modeline.htotal = vml.htotal;
3356 orig_modeline.vdisplay = vml.vdisplay;
3357 orig_modeline.vsyncstart = vml.vsyncstart;
3358 orig_modeline.vsyncend = vml.vsyncend;
3359 orig_modeline.vtotal = vml.vtotal;
3360 orig_modeline.flags = vml.flags;
3361 orig_modeline.privsize = vml.privsize;
3362 // orig_modeline.private = vml.private;
3363 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3364 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3365 XFlush(top_level->display);
3369 void BC_WindowBase::restore_vm()
3371 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3372 XFlush(top_level->display);
3383 GLXContext glXCreateContext(Display *dpy,
3385 GLXContext shareList,
3388 int glXMakeCurrent(Display *dpy,
3392 void glXSwapBuffers(Display *dpy,
3398 void BC_WindowBase::enable_opengl()
3400 lock_window("BC_WindowBase::enable_opengl");
3403 XVisualInfo viproto;
3404 XVisualInfo *visinfo;
3407 viproto.screen = top_level->screen;
3408 visinfo = XGetVisualInfo(top_level->display,
3413 gl_context = glXCreateContext(top_level->display,
3418 glXMakeCurrent(top_level->display,
3422 // Need expose events for 3D
3423 unsigned long valuemask = CWEventMask;
3424 XSetWindowAttributes attributes;
3425 attributes.event_mask = DEFAULT_EVENT_MASKS |
3427 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3429 opengl_lock.unlock();
3433 void BC_WindowBase::disable_opengl()
3435 unsigned long valuemask = CWEventMask;
3436 XSetWindowAttributes attributes;
3437 attributes.event_mask = DEFAULT_EVENT_MASKS;
3438 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3441 void BC_WindowBase::lock_opengl()
3443 lock_window("BC_WindowBase::lock_opengl");
3445 glXMakeCurrent(top_level->display,
3450 void BC_WindowBase::unlock_opengl()
3452 opengl_lock.unlock();
3456 void BC_WindowBase::flip_opengl()
3458 glXSwapBuffers(top_level->display, win);
3462 int BC_WindowBase::get_event_count()
3464 event_lock->lock("BC_WindowBase::get_event_count");
3465 int result = common_events.total;
3466 event_lock->unlock();
3470 XEvent* BC_WindowBase::get_event()
3473 while(!done && !result)
3475 event_condition->lock("BC_WindowBase::get_event");
3476 event_lock->lock("BC_WindowBase::get_event");
3478 if(common_events.total && !done)
3480 result = common_events.values[0];
3481 common_events.remove_number(0);
3484 event_lock->unlock();
3489 void BC_WindowBase::put_event(XEvent *event)
3491 event_lock->lock("BC_WindowBase::put_event");
3492 common_events.append(event);
3493 event_lock->unlock();
3494 event_condition->unlock();