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"
13 #include "bcwidgetgrid.h"
14 #include "bcwindowbase.h"
15 #include "bcwindowevents.h"
16 #include "colormodels.h"
18 #include "condition.h"
34 #include <X11/extensions/Xvlib.h>
35 #include <X11/extensions/shape.h>
38 BC_ResizeCall::BC_ResizeCall(int w, int h)
53 Mutex BC_WindowBase::opengl_lock;
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 // NOTE: since the value is itself a subwindow, the
92 // recursion removes the item from subwindows
93 delete subwindows->values[0];
100 while (widgetgrids->total)
102 delete widgetgrids->last();
103 widgetgrids->remove();
111 XDestroyWindow(top_level->display, win);
113 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
114 if(icon_pixmap) delete icon_pixmap;
115 if(temp_bitmap) delete temp_bitmap;
121 if(window_type == MAIN_WINDOW)
123 XFreeGC(display, gc);
126 XftFontClose (display, (XftFont*)largefont_xft);
128 XftFontClose (display, (XftFont*)mediumfont_xft);
130 XftFontClose (display, (XftFont*)smallfont_xft);
133 // Can't close display if another thread is waiting for events
134 XCloseDisplay(display);
135 // XCloseDisplay(event_display);
136 clipboard->stop_clipboard();
144 resize_history.remove_all_objects();
145 common_events.remove_all_objects();
147 delete event_condition;
149 UNSET_ALL_LOCKS(this)
152 int BC_WindowBase::initialize()
170 translation_events = 0;
171 ctrl_mask = shift_mask = alt_mask = 0;
172 cursor_x = cursor_y = button_number = 0;
175 button_time1 = button_time2 = 0;
180 active_popup_menu = 0;
181 active_subwindow = 0;
185 persistant_tooltip = 0;
186 // next_repeat_id = 0;
189 current_font = MEDIUMFONT;
190 current_color = BLACK;
191 current_cursor = ARROW_CURSOR;
194 shared_bg_pixmap = 0;
196 window_type = MAIN_WINDOW;
197 translation_count = 0;
198 x_correction = y_correction = 0;
207 #ifdef HAVE_LIBXXF86VM
214 // Need these right away since put_event is called before run_window sometimes.
215 event_lock = new Mutex("BC_WindowBase::event_lock");
216 event_condition = new Condition(0, "BC_WindowBase::event_condition");
217 cursor_timer = new Timer;
223 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
226 ButtonReleaseMask | \
227 PointerMotionMask | \
231 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
245 BC_Pixmap *bg_pixmap,
248 XSetWindowAttributes attr;
250 XSizeHints size_hints;
253 #ifdef HAVE_LIBXXF86VM
257 if(parent_window) top_level = parent_window->top_level;
259 #ifdef HAVE_LIBXXF86VM
260 if(window_type == VIDMODE_SCALED_WINDOW)
261 closest_vm(&vm,&w,&h);
268 this->bg_color = bg_color;
269 this->window_type = window_type;
271 this->private_color = private_color;
272 this->parent_window = parent_window;
273 this->bg_pixmap = bg_pixmap;
274 this->allow_resize = allow_resize;
275 strcpy(this->title, _(title));
276 if(bg_pixmap) shared_bg_pixmap = 1;
278 if(parent_window) top_level = parent_window->top_level;
280 subwindows = new BC_SubWindowList;
281 widgetgrids = new BC_WidgetGridList;
284 if(window_type == MAIN_WINDOW)
287 parent_window = this;
289 // This function must be the first Xlib
290 // function a multi-threaded program calls
294 // get the display connection
295 display = init_display(display_name);
296 // event_display = init_display(display_name);
298 // Fudge window placement
299 root_w = get_root_w(1, 0);
300 root_h = get_root_h(0);
301 if(this->x + this->w > root_w) this->x = root_w - this->w;
302 if(this->y + this->h > root_h) this->y = root_h - this->h;
303 if(this->x < 0) this->x = 0;
304 if(this->y < 0) this->y = 0;
305 screen = DefaultScreen(display);
306 rootwin = RootWindow(display, screen);
309 vis = DefaultVisual(display, screen);
310 default_depth = DefaultDepth(display, screen);
312 client_byte_order = (*(u_int32_t*)"a ") & 0x00000001;
313 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
316 // This must be done before fonts to know if antialiasing is available.
319 if(resources.use_shm < 0) resources.initialize_display(this);
320 x_correction = get_resources()->get_left_border();
321 y_correction = get_resources()->get_top_border();
323 if(this->bg_color == -1)
324 this->bg_color = resources.get_bg_color();
326 // printf("bcwindowbase 1 %s\n", title);
327 // if(window_type == MAIN_WINDOW) sleep(1);
328 // printf("bcwindowbase 10\n");
339 attr.event_mask = DEFAULT_EVENT_MASKS |
340 StructureNotifyMask |
343 attr.background_pixel = get_color(this->bg_color);
344 attr.colormap = cmap;
345 attr.cursor = get_cursor_struct(ARROW_CURSOR);
347 win = XCreateWindow(display,
354 top_level->default_depth,
360 XGetNormalHints(display, win, &size_hints);
362 size_hints.flags = PSize | PMinSize | PMaxSize;
363 size_hints.width = this->w;
364 size_hints.height = this->h;
365 size_hints.min_width = allow_resize ? minw : this->w;
366 size_hints.max_width = allow_resize ? 32767 : this->w;
367 size_hints.min_height = allow_resize ? minh : this->h;
368 size_hints.max_height = allow_resize ? 32767 : this->h;
369 if(x > -BC_INFINITY && x < BC_INFINITY)
371 size_hints.flags |= PPosition;
372 size_hints.x = this->x;
373 size_hints.y = this->y;
376 XSetStandardProperties(display,
386 clipboard = new BC_Clipboard(display_name);
387 clipboard->start_clipboard();
391 Atom ClientLeaderXAtom;
392 if (XGroupLeader == 0)
394 char *instance_name = "cinelerra";
395 char *class_name = "Cinelerra";
396 XClassHint *class_hints = XAllocClassHint();
397 class_hints->res_name = instance_name;
398 class_hints->res_class = class_name;
399 XSetClassHint(top_level->display, win, class_hints);
401 ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
402 XChangeProperty(display,
408 (unsigned char *)&XGroupLeader,
415 #ifdef HAVE_LIBXXF86VM
416 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
423 #ifdef HAVE_LIBXXF86VM
424 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
426 if(window_type == POPUP_WINDOW)
436 attr.event_mask = DEFAULT_EVENT_MASKS |
439 if(this->bg_color == -1)
440 this->bg_color = resources.get_bg_color();
441 attr.background_pixel = top_level->get_color(bg_color);
442 attr.colormap = top_level->cmap;
443 if(top_level->is_hourglass)
444 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
446 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
447 attr.override_redirect = True;
448 attr.save_under = True;
450 win = XCreateWindow(top_level->display,
457 top_level->default_depth,
464 if(window_type == SUB_WINDOW)
469 attr.event_mask = DEFAULT_EVENT_MASKS;
470 attr.background_pixel = top_level->get_color(this->bg_color);
471 if(top_level->is_hourglass)
472 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
474 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
475 win = XCreateWindow(top_level->display,
482 top_level->default_depth,
488 XMapWindow(top_level->display, win);
491 // Create pixmap for all windows
492 pixmap = new BC_Pixmap(this, this->w, this->h);
495 // Create truetype rendering surface
497 if(get_resources()->use_xft)
499 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n",
500 // top_level->display,
504 xft_drawable = XftDrawCreate(top_level->display,
508 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n",
510 // top_level->display,
517 // Set up options for main window
518 if(window_type == MAIN_WINDOW)
520 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
522 this->bg_pixmap = new BC_Pixmap(this,
523 get_resources()->bg_image,
527 if(!hidden) show_window();
534 draw_background(0, 0, this->w, this->h);
537 // Set up options for popup window
538 #ifdef HAVE_LIBXXF86VM
539 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
541 if(window_type == POPUP_WINDOW)
545 if(!hidden) show_window();
550 Display* BC_WindowBase::init_display(char *display_name)
554 if(display_name && display_name[0] == 0) display_name = NULL;
555 if((display = XOpenDisplay(display_name)) == NULL)
557 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
559 if(getenv("DISPLAY") == NULL)
561 printf("'DISPLAY' environment variable not set.\n");
565 // Try again with default display.
567 if((display = XOpenDisplay(0)) == NULL)
569 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
577 int BC_WindowBase::run_window()
583 // Events may have been sent before run_window so can't initialize them here.
586 if(window_type == MAIN_WINDOW)
588 // tooltip_id = get_repeat_id();
589 set_repeat(get_resources()->tooltip_delay);
592 // Start X server events
593 event_thread = new BC_WindowEvents(this);
594 event_thread->start();
596 // Start common events
602 unset_all_repeaters();
606 event_condition->reset();
607 common_events.remove_all_objects();
613 int BC_WindowBase::get_key_masks(XEvent *event)
615 // printf("BC_WindowBase::get_key_masks %llx\n",
616 // event->xkey.state);
618 ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
620 shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
621 alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
631 int BC_WindowBase::dispatch_event()
638 XClientMessageEvent *ptr;
640 int cancel_resize, cancel_translation;
644 // If an event is waiting get it, otherwise
645 // wait for next event only if there are no compressed events.
646 if(get_event_count() ||
647 (!motion_events && !resize_events && !translation_events))
649 // XNextEvent(display, event);
651 // Lock out window deletions
652 lock_window("BC_WindowBase::dispatch_event 1");
653 // get_key_masks(event);
656 // Handle compressed events
658 lock_window("BC_WindowBase::dispatch_event 2");
660 dispatch_resize_event(last_resize_w, last_resize_h);
663 dispatch_motion_event();
665 if(translation_events)
666 dispatch_translation_event();
672 //printf("1 %s %p %d\n", title, event, event->type);
676 get_key_masks(event);
677 // Clear the resize buffer
678 if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
679 // Clear the motion buffer since this can clear the window
682 dispatch_motion_event();
685 ptr = (XClientMessageEvent*)event;
688 if(ptr->message_type == ProtoXAtom &&
689 ptr->data.l[0] == DelWinXAtom)
694 if(ptr->message_type == RepeaterXAtom)
696 dispatch_repeat_event(ptr->data.l[0]);
697 // Make sure the repeater still exists.
698 // for(int i = 0; i < repeaters.total; i++)
700 // if(repeaters.values[i]->repeat_id == ptr->data.l[0])
702 // dispatch_repeat_event_master(ptr->data.l[0]);
708 if(ptr->message_type == SetDoneXAtom)
721 dispatch_focus_out();
733 get_key_masks(event);
734 cursor_x = event->xbutton.x;
735 cursor_y = event->xbutton.y;
736 button_number = event->xbutton.button;
737 event_win = event->xany.window;
738 if (button_number != 4 && button_number != 5)
740 button_pressed = event->xbutton.button;
741 button_time1 = button_time2;
742 button_time2 = event->xbutton.time;
745 drag_win = event_win;
746 drag_x1 = cursor_x - get_resources()->drag_radius;
747 drag_x2 = cursor_x + get_resources()->drag_radius;
748 drag_y1 = cursor_y - get_resources()->drag_radius;
749 drag_y2 = cursor_y + get_resources()->drag_radius;
751 if(button_time2 - button_time1 < resources.double_click)
753 // Ignore triple clicks
755 button_time2 = button_time1 = 0;
760 dispatch_button_press();
764 get_key_masks(event);
765 button_number = event->xbutton.button;
766 event_win = event->xany.window;
767 if (button_number != 4 && button_number != 5)
770 dispatch_button_release();
775 event_win = event->xany.window;
776 dispatch_expose_event();
780 get_key_masks(event);
781 // Dispatch previous motion event if this is a subsequent motion from a different window
782 if(motion_events && last_motion_win != event->xany.window)
784 dispatch_motion_event();
787 // Buffer the current motion
789 last_motion_x = event->xmotion.x;
790 last_motion_y = event->xmotion.y;
791 last_motion_win = event->xany.window;
794 case ConfigureNotify:
795 get_key_masks(event);
796 XTranslateCoordinates(top_level->display,
804 last_resize_w = event->xconfigure.width;
805 last_resize_h = event->xconfigure.height;
808 cancel_translation = 0;
810 // Resize history prevents responses to recursive resize requests
811 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
813 if(resize_history.values[i]->w == last_resize_w &&
814 resize_history.values[i]->h == last_resize_h)
816 delete resize_history.values[i];
817 resize_history.remove_number(i);
822 if(last_resize_w == w && last_resize_h == h)
830 if((last_translate_x == x && last_translate_y == y))
831 cancel_translation = 1;
833 if(!cancel_translation)
835 translation_events = 1;
842 get_key_masks(event);
844 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
846 // printf("BC_WindowBase::dispatch_event 2 %llx\n",
847 // event->xkey.state);
848 // block out control keys
849 if(keysym > 0xffe0 && keysym < 0xffff) break;
852 if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
857 // block out extra keys
867 // Translate key codes
868 case XK_Return: key_pressed = RETURN; break;
869 case XK_Up: key_pressed = UP; break;
870 case XK_Down: key_pressed = DOWN; break;
871 case XK_Left: key_pressed = LEFT; break;
872 case XK_Right: key_pressed = RIGHT; break;
873 case XK_Next: key_pressed = PGDN; break;
874 case XK_Prior: key_pressed = PGUP; break;
875 case XK_BackSpace: key_pressed = BACKSPACE; break;
876 case XK_Escape: key_pressed = ESC; break;
879 key_pressed = LEFTTAB;
883 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
884 case XK_underscore: key_pressed = '_'; break;
885 case XK_asciitilde: key_pressed = '~'; break;
886 case XK_Delete: key_pressed = DELETE; break;
887 case XK_Home: key_pressed = HOME; break;
888 case XK_End: key_pressed = END; break;
891 case XK_KP_Enter: key_pressed = KPENTER; break;
892 case XK_KP_Add: key_pressed = KPPLUS; break;
894 case XK_KP_End: key_pressed = KP1; break;
896 case XK_KP_Down: key_pressed = KP2; break;
898 case XK_KP_Page_Down: key_pressed = KP3; break;
900 case XK_KP_Left: key_pressed = KP4; break;
902 case XK_KP_Begin: key_pressed = KP5; break;
904 case XK_KP_Right: key_pressed = KP6; break;
906 case XK_KP_Insert: key_pressed = KPINS; break;
908 case XK_KP_Delete: key_pressed = KPDEL; break;
910 //key_pressed = keys_return[0];
911 key_pressed = keysym & 0xff;
915 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
916 result = dispatch_keypress_event();
917 // Handle some default keypresses
920 if(key_pressed == 'w' ||
929 event_win = event->xany.window;
930 dispatch_cursor_leave();
934 event_win = event->xany.window;
935 cursor_x = event->xcrossing.x;
936 cursor_y = event->xcrossing.y;
937 dispatch_cursor_enter();
940 //printf("100 %s %p %d\n", title, event, event->type);
943 if(event) delete event;
947 int BC_WindowBase::dispatch_expose_event()
950 for(int i = 0; i < subwindows->total && !result; i++)
952 result = subwindows->values[i]->dispatch_expose_event();
956 if(!result) expose_event();
960 int BC_WindowBase::dispatch_resize_event(int w, int h)
962 // Can't store new w and h until the event is handles
963 // because bcfilebox depends on the old w and h to
964 // reposition widgets.
965 if(window_type == MAIN_WINDOW)
969 pixmap = new BC_Pixmap(this, w, h);
971 clear_box(0, 0, w, h);
974 // Propagate to subwindows
975 for(int i = 0; i < subwindows->total; i++)
977 subwindows->values[i]->dispatch_resize_event(w, h);
983 if(window_type == MAIN_WINDOW)
991 int BC_WindowBase::dispatch_translation_event()
993 translation_events = 0;
994 if(window_type == MAIN_WINDOW)
998 x = last_translate_x;
999 y = last_translate_y;
1000 // Correct for window manager offsets
1005 for(int i = 0; i < subwindows->total; i++)
1007 subwindows->values[i]->dispatch_translation_event();
1010 translation_event();
1014 int BC_WindowBase::dispatch_motion_event()
1019 if(top_level == this)
1021 event_win = last_motion_win;
1025 if(get_button_down() && !active_menubar && !active_popup_menu)
1029 cursor_x = last_motion_x;
1030 cursor_y = last_motion_y;
1031 result = dispatch_drag_motion();
1035 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
1036 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1041 result = dispatch_drag_start();
1044 cursor_x = last_motion_x;
1045 cursor_y = last_motion_y;
1047 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1048 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1049 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1052 for(int i = 0; i < subwindows->total && !result; i++)
1054 result = subwindows->values[i]->dispatch_motion_event();
1058 if(!result) result = cursor_motion_event(); // give to user
1062 int BC_WindowBase::dispatch_keypress_event()
1065 if(top_level == this)
1067 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1070 for(int i = 0; i < subwindows->total && !result; i++)
1072 result = subwindows->values[i]->dispatch_keypress_event();
1075 if(!result) result = keypress_event();
1080 int BC_WindowBase::dispatch_focus_in()
1082 for(int i = 0; i < subwindows->total; i++)
1084 subwindows->values[i]->dispatch_focus_in();
1092 int BC_WindowBase::dispatch_focus_out()
1094 for(int i = 0; i < subwindows->total; i++)
1096 subwindows->values[i]->dispatch_focus_out();
1104 int BC_WindowBase::get_has_focus()
1106 return top_level->has_focus;
1109 int BC_WindowBase::get_deleting()
1111 if(is_deleting) return 1;
1112 if(parent_window && parent_window->get_deleting()) return 1;
1116 int BC_WindowBase::dispatch_button_press()
1119 if(top_level == this)
1121 if(active_menubar) result = active_menubar->dispatch_button_press();
1122 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1123 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1126 for(int i = 0; i < subwindows->total && !result; i++)
1128 result = subwindows->values[i]->dispatch_button_press();
1131 if(!result) result = button_press_event();
1136 int BC_WindowBase::dispatch_button_release()
1139 if(top_level == this)
1141 if(active_menubar) result = active_menubar->dispatch_button_release();
1142 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1143 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1144 if(!result && button_number != 4 && button_number != 5)
1145 result = dispatch_drag_stop();
1148 for(int i = 0; i < subwindows->total && !result; i++)
1150 result = subwindows->values[i]->dispatch_button_release();
1155 result = button_release_event();
1162 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1165 // all repeat event handlers get called and decide based on activity and duration
1166 // whether to respond
1167 for(int i = 0; i < subwindows->total; i++)
1169 subwindows->values[i]->dispatch_repeat_event(duration);
1173 repeat_event(duration);
1177 // Unlock next repeat signal
1178 if(window_type == MAIN_WINDOW)
1180 for(int i = 0; i < repeaters.total; i++)
1182 if(repeaters.values[i]->delay == duration)
1184 repeaters.values[i]->repeat_lock->unlock();
1192 void BC_WindowBase::unhide_cursor()
1197 if(top_level->is_hourglass)
1198 set_cursor(HOURGLASS_CURSOR, 1);
1200 set_cursor(current_cursor, 1);
1202 cursor_timer->update();
1206 void BC_WindowBase::update_video_cursor()
1208 if(video_on && !is_transparent)
1210 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1213 set_cursor(TRANSPARENT_CURSOR, 1);
1214 cursor_timer->update();
1219 cursor_timer->update();
1224 int BC_WindowBase::dispatch_cursor_leave()
1228 for(int i = 0; i < subwindows->total; i++)
1230 subwindows->values[i]->dispatch_cursor_leave();
1233 cursor_leave_event();
1237 int BC_WindowBase::dispatch_cursor_enter()
1243 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1244 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1245 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1247 for(int i = 0; !result && i < subwindows->total; i++)
1249 result = subwindows->values[i]->dispatch_cursor_enter();
1252 if(!result) result = cursor_enter_event();
1256 int BC_WindowBase::cursor_enter_event()
1261 int BC_WindowBase::cursor_leave_event()
1266 int BC_WindowBase::close_event()
1272 int BC_WindowBase::dispatch_drag_start()
1275 if(active_menubar) result = active_menubar->dispatch_drag_start();
1276 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1277 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1279 for(int i = 0; i < subwindows->total && !result; i++)
1281 result = subwindows->values[i]->dispatch_drag_start();
1284 if(!result) result = is_dragging = drag_start_event();
1288 int BC_WindowBase::dispatch_drag_stop()
1292 for(int i = 0; i < subwindows->total && !result; i++)
1294 result = subwindows->values[i]->dispatch_drag_stop();
1297 if(is_dragging && !result)
1307 int BC_WindowBase::dispatch_drag_motion()
1310 for(int i = 0; i < subwindows->total && !result; i++)
1312 result = subwindows->values[i]->dispatch_drag_motion();
1315 if(is_dragging && !result)
1317 drag_motion_event();
1328 int BC_WindowBase::show_tooltip(int w, int h)
1332 if(!tooltip_on && get_resources()->tooltips_enabled)
1335 top_level->hide_tooltip();
1339 w = get_text_width(MEDIUMFONT, tooltip_text);
1342 h = get_text_height(MEDIUMFONT, tooltip_text);
1344 w += TOOLTIP_MARGIN * 2;
1345 h += TOOLTIP_MARGIN * 2;
1347 XTranslateCoordinates(top_level->display,
1355 tooltip_popup = new BC_Popup(top_level,
1360 get_resources()->tooltip_bg_color);
1363 tooltip_popup->set_font(MEDIUMFONT);
1364 tooltip_popup->flash();
1365 tooltip_popup->flush();
1370 int BC_WindowBase::hide_tooltip()
1373 for(int i = 0; i < subwindows->total; i++)
1375 subwindows->values[i]->hide_tooltip();
1381 delete tooltip_popup;
1387 int BC_WindowBase::set_tooltip(char *text)
1389 strcpy(this->tooltip_text, text);
1390 // Update existing tooltip if it is visible
1394 tooltip_popup->flash();
1399 // signal the event handler to repeat
1400 int BC_WindowBase::set_repeat(int64_t duration)
1404 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1407 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1409 // test repeater database for duplicates
1410 for(int i = 0; i < repeaters.total; i++)
1413 if(repeaters.values[i]->delay == duration)
1415 repeaters.values[i]->start_repeating();
1420 BC_Repeater *repeater = new BC_Repeater(this, duration);
1421 repeater->initialize();
1422 repeaters.append(repeater);
1423 repeater->start_repeating();
1427 int BC_WindowBase::unset_repeat(int64_t duration)
1429 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1431 BC_Repeater *repeater = 0;
1432 for(int i = 0; i < repeaters.total; i++)
1434 if(repeaters.values[i]->delay == duration)
1436 repeaters.values[i]->stop_repeating();
1443 int BC_WindowBase::unset_all_repeaters()
1445 for(int i = 0; i < repeaters.total; i++)
1447 repeaters.values[i]->stop_repeating();
1449 repeaters.remove_all_objects();
1453 // long BC_WindowBase::get_repeat_id()
1455 // return top_level->next_repeat_id++;
1458 int BC_WindowBase::arm_repeat(int64_t duration)
1460 XEvent *event = new XEvent;
1461 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1462 ptr->type = ClientMessage;
1463 ptr->message_type = RepeaterXAtom;
1465 ptr->data.l[0] = duration;
1467 // Couldn't use XSendEvent since it locked up randomly.
1469 // XSendEvent(top_level->event_display,
1478 int BC_WindowBase::get_atoms()
1480 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
1481 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1482 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
1483 if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1484 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1488 void BC_WindowBase::init_cursors()
1490 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1491 cross_cursor = XCreateFontCursor(display, XC_crosshair);
1492 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1493 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1494 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1495 move_cursor = XCreateFontCursor(display, XC_fleur);
1496 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1497 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1498 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1499 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1500 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1501 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1502 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1503 hourglass_cursor = XCreateFontCursor(display, XC_watch);
1506 char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
1507 Colormap colormap = DefaultColormap(display, screen);
1508 Pixmap pixmap_bottom = XCreateBitmapFromData(display,
1513 XColor black, dummy;
1514 XAllocNamedColor(display, colormap, "black", &black, &dummy);
1515 transparent_cursor = XCreatePixmapCursor(display,
1522 // XDefineCursor(display, win, transparent_cursor);
1523 XFreePixmap(display, pixmap_bottom);
1526 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1532 color_model = BC_RGB8;
1535 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1538 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1541 color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1547 int BC_WindowBase::init_colors()
1550 current_color_value = current_color_pixel = 0;
1552 // Get the real depth
1555 ximage = XCreateImage(top_level->display,
1557 top_level->default_depth,
1565 bits_per_pixel = ximage->bits_per_pixel;
1566 XDestroyImage(ximage);
1568 color_model = evaluate_color_model(client_byte_order,
1571 // Get the color model
1577 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1578 create_private_colors();
1582 cmap = DefaultColormap(display, screen);
1583 create_shared_colors();
1586 allocate_color_table();
1588 get_resources()->use_xft = 0;
1592 cmap = DefaultColormap(display, screen);
1598 int BC_WindowBase::create_private_colors()
1603 for(int i = 0; i < 255; i++)
1605 color = (i & 0xc0) << 16;
1606 color += (i & 0x38) << 10;
1607 color += (i & 0x7) << 5;
1608 color_table[i][0] = color;
1610 create_shared_colors(); // overwrite the necessary colors on the table
1615 int BC_WindowBase::create_color(int color)
1617 if(total_colors == 256)
1619 // replace the closest match with an exact match
1620 color_table[get_color_rgb8(color)][0] = color;
1624 // add the color to the table
1625 color_table[total_colors][0] = color;
1631 int BC_WindowBase::create_shared_colors()
1633 create_color(BLACK);
1634 create_color(WHITE);
1636 create_color(LTGREY);
1637 create_color(MEGREY);
1638 create_color(MDGREY);
1639 create_color(DKGREY);
1641 create_color(LTCYAN);
1642 create_color(MECYAN);
1643 create_color(MDCYAN);
1644 create_color(DKCYAN);
1646 create_color(LTGREEN);
1647 create_color(GREEN);
1648 create_color(DKGREEN);
1650 create_color(LTPINK);
1654 create_color(LTBLUE);
1656 create_color(DKBLUE);
1658 create_color(LTYELLOW);
1659 create_color(MEYELLOW);
1660 create_color(MDYELLOW);
1661 create_color(DKYELLOW);
1663 create_color(LTPURPLE);
1664 create_color(MEPURPLE);
1665 create_color(MDPURPLE);
1666 create_color(DKPURPLE);
1668 create_color(FGGREY);
1669 create_color(MNBLUE);
1670 create_color(ORANGE);
1671 create_color(FTGREY);
1676 int BC_WindowBase::allocate_color_table()
1678 int red, green, blue, color;
1682 for(int i = 0; i < total_colors; i++)
1684 color = color_table[i][0];
1685 red = (color & 0xFF0000) >> 16;
1686 green = (color & 0x00FF00) >> 8;
1687 blue = color & 0xFF;
1689 col.flags = DoRed | DoGreen | DoBlue;
1690 col.red = red<<8 | red;
1691 col.green = green<<8 | green;
1692 col.blue = blue<<8 | blue;
1694 XAllocColor(display, cmap, &col);
1695 color_table[i][1] = col.pixel;
1698 XInstallColormap(display, cmap);
1702 int BC_WindowBase::init_window_shape()
1704 if(bg_pixmap && bg_pixmap->use_alpha())
1706 XShapeCombineMask(top_level->display,
1711 bg_pixmap->get_alpha(),
1718 int BC_WindowBase::init_gc()
1720 unsigned long gcmask;
1721 gcmask = GCFont | GCGraphicsExposures;
1724 gcvalues.font = mediumfont->fid; // set the font
1725 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
1726 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1730 int BC_WindowBase::init_fonts()
1732 if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL)
1733 if((largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1734 largefont = XLoadQueryFont(display, "fixed");
1736 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL)
1737 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1738 mediumfont = XLoadQueryFont(display, "fixed");
1740 if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL)
1741 if((smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1742 smallfont = XLoadQueryFont(display, "fixed");
1745 if(get_resources()->use_xft)
1749 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
1751 if(!(largefont_xft = XftFontOpenXlfd(display,
1753 resources.large_font_xft)))
1755 largefont_xft = XftFontOpenXlfd(display,
1759 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
1760 if(!(largefont_xft = XftFontOpenXlfd(display,
1762 resources.large_font_xft)))
1764 largefont_xft = XftFontOpenXlfd(display,
1768 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
1771 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1773 resources.medium_font_xft)))
1775 mediumfont_xft = XftFontOpenXlfd(display,
1781 if(!(smallfont_xft = XftFontOpenXlfd(display,
1783 resources.small_font_xft)))
1785 smallfont_xft = XftFontOpenXlfd(display,
1790 //printf("BC_WindowBase::init_fonts 100 %s %p\n",
1791 //resources.medium_font,
1794 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
1795 resources.large_font_xft,
1797 resources.medium_font_xft,
1799 resources.small_font_xft,
1802 // Extension failed to locate fonts
1803 if(!largefontset || !mediumfontset || !smallfontset)
1805 printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1806 resources.large_font_xft,
1808 resources.medium_font_xft,
1810 resources.small_font_xft,
1812 get_resources()->use_xft = 0;
1817 if(get_resources()->use_fontset)
1822 // FIXME: should check the m,d,n values
1823 if((largefontset = XCreateFontSet(display,
1824 resources.large_fontset,
1828 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1829 if((mediumfontset = XCreateFontSet(display,
1830 resources.medium_fontset,
1834 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1835 if((smallfontset = XCreateFontSet(display,
1836 resources.small_fontset,
1840 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1842 if(largefontset && mediumfontset && smallfontset)
1844 curr_fontset = mediumfontset;
1845 get_resources()->use_fontset = 1;
1850 get_resources()->use_fontset = 0;
1859 int BC_WindowBase::get_color(int64_t color)
1861 // return pixel of color
1862 // use this only for drawing subwindows not for bitmaps
1863 int i, test, difference, result;
1870 return get_color_rgb8(color);
1874 // test last color looked up
1875 if(current_color_value == color) return current_color_pixel;
1878 current_color_value = color;
1879 for(i = 0; i < total_colors; i++)
1881 if(color_table[i][0] == color)
1883 current_color_pixel = color_table[i][1];
1884 return current_color_pixel;
1888 // find nearest match
1889 difference = 0xFFFFFF;
1891 for(i = 0, result = 0; i < total_colors; i++)
1893 test = abs((int)(color_table[i][0] - color));
1895 if(test < difference)
1897 current_color_pixel = color_table[i][1];
1902 return current_color_pixel;
1907 return get_color_rgb16(color);
1911 return get_color_bgr16(color);
1916 if(client_byte_order == server_byte_order)
1919 get_color_bgr24(color);
1929 int BC_WindowBase::get_color_rgb8(int color)
1933 pixel = (color & 0xc00000) >> 16;
1934 pixel += (color & 0xe000) >> 10;
1935 pixel += (color & 0xe0) >> 5;
1939 int64_t BC_WindowBase::get_color_rgb16(int color)
1942 result = (color & 0xf80000) >> 8;
1943 result += (color & 0xfc00) >> 5;
1944 result += (color & 0xf8) >> 3;
1949 int64_t BC_WindowBase::get_color_bgr16(int color)
1952 result = (color & 0xf80000) >> 19;
1953 result += (color & 0xfc00) >> 5;
1954 result += (color & 0xf8) << 8;
1959 int64_t BC_WindowBase::get_color_bgr24(int color)
1962 result = (color & 0xff) << 16;
1963 result += (color & 0xff00);
1964 result += (color & 0xff0000) >> 16;
1968 void BC_WindowBase::start_video()
1970 cursor_timer->update();
1972 // set_color(BLACK);
1973 // draw_box(0, 0, get_w(), get_h());
1977 void BC_WindowBase::stop_video()
1985 int64_t BC_WindowBase::get_color()
1987 return top_level->current_color;
1990 void BC_WindowBase::set_color(int64_t color)
1992 top_level->current_color = color;
1993 XSetForeground(top_level->display,
1995 top_level->get_color(color));
1998 void BC_WindowBase::set_opaque()
2000 XSetFunction(top_level->display, top_level->gc, GXcopy);
2003 void BC_WindowBase::set_inverse()
2005 XSetFunction(top_level->display, top_level->gc, GXxor);
2008 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2012 case ARROW_CURSOR: return top_level->arrow_cursor; break;
2013 case CROSS_CURSOR: return top_level->cross_cursor;
2014 case IBEAM_CURSOR: return top_level->ibeam_cursor; break;
2015 case VSEPARATE_CURSOR: return top_level->vseparate_cursor; break;
2016 case HSEPARATE_CURSOR: return top_level->hseparate_cursor; break;
2017 case MOVE_CURSOR: return top_level->move_cursor; break;
2018 case LEFT_CURSOR: return top_level->left_cursor; break;
2019 case RIGHT_CURSOR: return top_level->right_cursor; break;
2020 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor; break;
2021 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor; break;
2022 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor; break;
2023 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor; break;
2024 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor; break;
2025 case HOURGLASS_CURSOR: return top_level->hourglass_cursor; break;
2026 case TRANSPARENT_CURSOR: return top_level->transparent_cursor; break;
2031 void BC_WindowBase::set_cursor(int cursor, int override)
2033 // don't change cursor if overridden
2034 if((!top_level->is_hourglass && !is_transparent) ||
2037 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2041 if(!override) current_cursor = cursor;
2044 void BC_WindowBase::set_x_cursor(int cursor)
2046 temp_cursor = XCreateFontCursor(top_level->display, cursor);
2047 XDefineCursor(top_level->display, win, temp_cursor);
2048 current_cursor = cursor;
2052 int BC_WindowBase::get_cursor()
2054 return current_cursor;
2057 void BC_WindowBase::start_hourglass()
2059 top_level->start_hourglass_recursive();
2063 void BC_WindowBase::stop_hourglass()
2065 top_level->stop_hourglass_recursive();
2069 void BC_WindowBase::start_hourglass_recursive()
2071 if(this == top_level)
2079 set_cursor(HOURGLASS_CURSOR, 1);
2080 for(int i = 0; i < subwindows->total; i++)
2082 subwindows->values[i]->start_hourglass_recursive();
2087 void BC_WindowBase::stop_hourglass_recursive()
2089 if(this == top_level)
2091 if(hourglass_total == 0) return;
2092 top_level->hourglass_total--;
2095 if(!top_level->hourglass_total)
2097 top_level->is_hourglass = 0;
2099 // Cause set_cursor to perform change
2101 set_cursor(current_cursor, 1);
2103 for(int i = 0; i < subwindows->total; i++)
2105 subwindows->values[i]->stop_hourglass_recursive();
2115 XFontStruct* BC_WindowBase::get_font_struct(int font)
2117 // Clear out unrelated flags
2118 if(font & BOLDFACE) font ^= BOLDFACE;
2122 case MEDIUMFONT: return top_level->mediumfont; break;
2123 case SMALLFONT: return top_level->smallfont; break;
2124 case LARGEFONT: return top_level->largefont; break;
2129 XFontSet BC_WindowBase::get_fontset(int font)
2133 if(get_resources()->use_fontset)
2137 case SMALLFONT: fs = top_level->smallfontset; break;
2138 case LARGEFONT: fs = top_level->largefontset; break;
2139 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2147 XftFont* BC_WindowBase::get_xft_struct(int font)
2149 // Clear out unrelated flags
2150 if(font & BOLDFACE) font ^= BOLDFACE;
2154 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft; break;
2155 case SMALLFONT: return (XftFont*)top_level->smallfont_xft; break;
2156 case LARGEFONT: return (XftFont*)top_level->largefont_xft; break;
2173 void BC_WindowBase::set_font(int font)
2175 top_level->current_font = font;
2179 if(get_resources()->use_xft)
2185 if(get_resources()->use_fontset)
2190 if(get_font_struct(font))
2192 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2198 void BC_WindowBase::set_fontset(int font)
2202 if(get_resources()->use_fontset)
2206 case SMALLFONT: fs = top_level->smallfontset; break;
2207 case LARGEFONT: fs = top_level->largefontset; break;
2208 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2216 XFontSet BC_WindowBase::get_curr_fontset(void)
2218 if(get_resources()->use_fontset)
2219 return curr_fontset;
2223 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2226 if(get_resources()->use_xft && get_xft_struct(font))
2229 XftTextExtents8(top_level->display,
2230 get_xft_struct(font),
2234 return extents.xOff;
2238 if(get_resources()->use_fontset && top_level->get_fontset(font))
2239 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2241 if(get_font_struct(font))
2242 return XTextWidth(get_font_struct(font), text, length);
2248 case MEDIUM_7SEGMENT:
2249 return get_resources()->medium_7segment[0]->get_w() * length;
2259 int BC_WindowBase::get_text_width(int font, char *text, int length)
2261 int i, j, w = 0, line_w = 0;
2262 if(length < 0) length = strlen(text);
2264 for(i = 0, j = 0; i <= length; i++)
2269 line_w = get_single_text_width(font, &text[j], i - j);
2275 line_w = get_single_text_width(font, &text[j], length - j);
2277 if(line_w > w) w = line_w;
2280 if(i > length && w == 0)
2282 w = get_single_text_width(font, text, length);
2288 int BC_WindowBase::get_text_ascent(int font)
2291 if(get_resources()->use_xft && get_xft_struct(font))
2294 XftTextExtents8(top_level->display,
2295 get_xft_struct(font),
2303 if(get_resources()->use_fontset && top_level->get_fontset(font))
2305 XFontSetExtents *extents;
2307 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2308 return -extents->max_logical_extent.y;
2311 if(get_font_struct(font))
2312 return top_level->get_font_struct(font)->ascent;
2316 case MEDIUM_7SEGMENT:
2317 return get_resources()->medium_7segment[0]->get_h();
2325 int BC_WindowBase::get_text_descent(int font)
2328 if(get_resources()->use_xft && get_xft_struct(font))
2331 XftTextExtents8(top_level->display,
2332 get_xft_struct(font),
2336 return extents.height - extents.y;
2340 if(get_resources()->use_fontset && top_level->get_fontset(font))
2342 XFontSetExtents *extents;
2344 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2345 return (extents->max_logical_extent.height
2346 + extents->max_logical_extent.y);
2349 if(get_font_struct(font))
2350 return top_level->get_font_struct(font)->descent;
2359 int BC_WindowBase::get_text_height(int font, char *text)
2361 if(!text) return get_text_ascent(font) + get_text_descent(font);
2363 // Add height of lines
2364 int h = 0, i, length = strlen(text);
2365 for(i = 0; i <= length; i++)
2373 return h * (get_text_ascent(font) + get_text_descent(font));
2376 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2378 if(color_model < 0) color_model = top_level->get_color_model();
2379 return new BC_Bitmap(top_level, w, h, color_model);
2382 int BC_WindowBase::accel_available(int color_model, int lock_it)
2384 if(window_type != MAIN_WINDOW)
2385 return top_level->accel_available(color_model, lock_it);
2389 if(lock_it) lock_window("BC_WindowBase::accel_available");
2393 result = grab_port_id(this, color_model);
2396 xvideo_port_id = result;
2408 //printf("BC_WindowBase::accel_available 1\n");
2409 result = grab_port_id(this, color_model);
2410 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2413 xvideo_port_id = result;
2418 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2426 if(lock_it) unlock_window();
2427 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2432 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2434 int numFormats, i, j, k;
2435 unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2437 XvAdaptorInfo *info;
2438 XvImageFormatValues *formats;
2441 if(!get_resources()->use_xvideo) return -1;
2443 // Translate from color_model to X color model
2444 x_color_model = cmodel_bc_to_x(color_model);
2446 // Only local server is fast enough.
2447 if(!resources.use_shm) return -1;
2449 // XV extension is available
2450 if(Success != XvQueryExtension(window->display,
2460 // XV adaptors are available
2461 XvQueryAdaptors(window->display,
2462 DefaultRootWindow(window->display),
2471 // Get adaptor with desired color model
2472 for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2474 /* adaptor supports XvImages */
2475 if(info[i].type & XvImageMask)
2477 formats = XvListImageFormats(window->display,
2480 // for(j = 0; j < numFormats; j++)
2481 // printf("%08x\n", formats[j].id);
2483 for(j = 0; j < numFormats && xvideo_port_id < 0; j++)
2485 /* this adaptor supports the desired format */
2486 if(formats[j].id == x_color_model)
2488 /* Try to grab a port */
2489 for(k = 0; k < info[i].num_ports; k++)
2492 if(Success == XvGrabPort(top_level->display,
2493 info[i].base_id + k,
2496 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2497 xvideo_port_id = info[i].base_id + k;
2503 if(formats) XFree(formats);
2507 XvFreeAdaptorInfo(info);
2509 return xvideo_port_id;
2513 int BC_WindowBase::show_window(int flush)
2515 XMapWindow(top_level->display, win);
2516 if(flush) XFlush(top_level->display);
2517 // XSync(top_level->display, 0);
2522 int BC_WindowBase::hide_window(int flush)
2524 XUnmapWindow(top_level->display, win);
2525 if(flush) XFlush(top_level->display);
2530 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2532 subwindows->append((BC_SubWindow*)menu_bar);
2534 menu_bar->parent_window = this;
2535 menu_bar->top_level = this->top_level;
2536 menu_bar->initialize();
2540 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2542 subwindows->append(subwindow);
2544 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2546 // parent window must be set before the subwindow initialization
2547 subwindow->parent_window = this;
2548 subwindow->top_level = this->top_level;
2550 // Execute derived initialization
2551 subwindow->initialize();
2556 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2558 return add_subwindow(subwindow);
2561 BC_WidgetGrid* BC_WindowBase::add_widgetgrid(BC_WidgetGrid *widgetgrid)
2563 widgetgrids->append(widgetgrid);
2568 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2571 XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
2574 XClearArea(top_level->display, win, x, y, w, h, 0);
2578 XClearWindow(top_level->display, win);
2586 int BC_WindowBase::flash(int flush)
2588 flash(-1, -1, -1, -1, flush);
2591 void BC_WindowBase::flush()
2593 XFlush(top_level->display);
2596 void BC_WindowBase::sync_display()
2598 XSync(top_level->display, False);
2601 int BC_WindowBase::get_window_lock()
2603 return top_level->window_lock;
2606 int BC_WindowBase::lock_window(char *location)
2608 if(top_level && top_level != this)
2610 top_level->lock_window(location);
2615 SET_LOCK(this, title, location);
2616 XLockDisplay(top_level->display);
2618 top_level->window_lock = 1;
2622 printf("BC_WindowBase::lock_window top_level NULL\n");
2627 int BC_WindowBase::unlock_window()
2629 if(top_level && top_level != this)
2631 top_level->unlock_window();
2637 top_level->window_lock = 0;
2638 XUnlockDisplay(top_level->display);
2642 printf("BC_WindowBase::unlock_window top_level NULL\n");
2647 void BC_WindowBase::set_done(int return_value)
2649 if(window_type != MAIN_WINDOW)
2650 top_level->set_done(return_value);
2654 XEvent *event = new XEvent;
2655 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2657 event->type = ClientMessage;
2658 ptr->message_type = SetDoneXAtom;
2660 this->return_value = return_value;
2662 // May lock up here because XSendEvent doesn't work too well
2663 // asynchronous with XNextEvent.
2664 // This causes BC_WindowEvents to forward a copy of the event to run_window where
2666 event_thread->done = 1;
2677 int BC_WindowBase::get_w()
2682 int BC_WindowBase::get_h()
2687 int BC_WindowBase::get_x()
2692 int BC_WindowBase::get_y()
2697 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2699 if(lock_display) lock_window("BC_WindowBase::get_root_w");
2700 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2701 int result = WidthOfScreen(screen_ptr);
2702 // Wider than 16:9, narrower than dual head
2703 if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2705 if(lock_display) unlock_window();
2709 int BC_WindowBase::get_root_h(int lock_display)
2711 if(lock_display) lock_window("BC_WindowBase::get_root_h");
2712 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2713 int result = HeightOfScreen(screen_ptr);
2714 if(lock_display) unlock_window();
2718 // Bottom right corner
2719 int BC_WindowBase::get_x2()
2724 int BC_WindowBase::get_y2()
2729 int BC_WindowBase::get_video_on()
2734 int BC_WindowBase::get_hidden()
2736 return top_level->hidden;
2739 int BC_WindowBase::cursor_inside()
2741 return (top_level->cursor_x >= 0 &&
2742 top_level->cursor_y >= 0 &&
2743 top_level->cursor_x < w &&
2744 top_level->cursor_y < h);
2747 BC_WindowBase* BC_WindowBase::get_top_level()
2752 BC_WindowBase* BC_WindowBase::get_parent()
2754 return parent_window;
2757 int BC_WindowBase::get_color_model()
2759 return top_level->color_model;
2762 BC_Resources* BC_WindowBase::get_resources()
2764 return &BC_WindowBase::resources;
2767 int BC_WindowBase::get_bg_color()
2772 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2777 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2779 top_level->active_subwindow = subwindow;
2782 int BC_WindowBase::activate()
2787 int BC_WindowBase::deactivate()
2789 if(window_type == MAIN_WINDOW)
2791 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2792 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2793 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2795 top_level->active_menubar = 0;
2796 top_level->active_popup_menu = 0;
2797 top_level->active_subwindow = 0;
2802 int BC_WindowBase::cycle_textboxes(int amount)
2805 BC_WindowBase *new_textbox = 0;
2809 BC_WindowBase *first_textbox = 0;
2810 find_next_textbox(&first_textbox, &new_textbox, result);
2811 if(!new_textbox) new_textbox = first_textbox;
2817 BC_WindowBase *last_textbox = 0;
2818 find_prev_textbox(&last_textbox, &new_textbox, result);
2819 if(!new_textbox) new_textbox = last_textbox;
2823 if(new_textbox != active_subwindow)
2826 new_textbox->activate();
2832 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2834 // Search subwindows for textbox
2835 for(int i = 0; i < subwindows->total && result < 2; i++)
2837 BC_WindowBase *test_subwindow = subwindows->values[i];
2838 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2845 if(!*first_textbox) *first_textbox = this;
2849 if(top_level->active_subwindow == this)
2855 *next_textbox = this;
2862 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2868 if(!*last_textbox) *last_textbox = this;
2872 if(top_level->active_subwindow == this)
2878 *prev_textbox = this;
2883 // Search subwindows for textbox
2884 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2886 BC_WindowBase *test_subwindow = subwindows->values[i];
2887 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2892 BC_Clipboard* BC_WindowBase::get_clipboard()
2894 return top_level->clipboard;
2897 int BC_WindowBase::get_relative_cursor_x()
2899 int abs_x, abs_y, x, y, win_x, win_y;
2900 unsigned int temp_mask;
2903 XQueryPointer(top_level->display,
2913 XTranslateCoordinates(top_level->display,
2925 int BC_WindowBase::get_relative_cursor_y()
2927 int abs_x, abs_y, x, y, win_x, win_y;
2928 unsigned int temp_mask;
2931 XQueryPointer(top_level->display,
2941 XTranslateCoordinates(top_level->display,
2953 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2955 int abs_x, abs_y, win_x, win_y;
2956 unsigned int temp_mask;
2959 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2960 XQueryPointer(top_level->display,
2969 if(lock_window) this->unlock_window();
2973 int BC_WindowBase::get_abs_cursor_y(int lock_window)
2975 int abs_x, abs_y, win_x, win_y;
2976 unsigned int temp_mask;
2979 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
2980 XQueryPointer(top_level->display,
2989 if(lock_window) this->unlock_window();
2993 int BC_WindowBase::match_window(Window win)
2995 if (this->win == win) return 1;
2997 for(int i = 0; i < subwindows->total; i++)
2999 result = subwindows->values[i]->match_window(win);
3000 if (result) return result;
3006 int BC_WindowBase::get_cursor_over_window()
3008 if(top_level != this) return top_level->get_cursor_over_window();
3010 int abs_x, abs_y, win_x, win_y;
3011 unsigned int temp_mask;
3012 Window temp_win1, temp_win2;
3014 if (!XQueryPointer(display,
3025 int result = match_window(temp_win2) ;
3029 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
3034 translate_coordinates(top_level->event_win,
3036 top_level->cursor_x,
3037 top_level->cursor_y,
3043 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
3048 translate_coordinates(top_level->event_win,
3050 top_level->cursor_x,
3051 top_level->cursor_y,
3057 int BC_WindowBase::get_drag_x()
3059 return top_level->drag_x;
3062 int BC_WindowBase::get_drag_y()
3064 return top_level->drag_y;
3067 int BC_WindowBase::get_cursor_x()
3069 return top_level->cursor_x;
3072 int BC_WindowBase::get_cursor_y()
3074 return top_level->cursor_y;
3077 int BC_WindowBase::is_event_win()
3079 return this->win == top_level->event_win;
3082 void BC_WindowBase::set_dragging(int value)
3084 is_dragging = value;
3087 int BC_WindowBase::get_dragging()
3092 int BC_WindowBase::get_buttonpress()
3094 return top_level->button_number;
3097 int BC_WindowBase::get_button_down()
3099 return top_level->button_down;
3102 int BC_WindowBase::alt_down()
3104 return top_level->alt_mask;
3107 int BC_WindowBase::shift_down()
3109 return top_level->shift_mask;
3112 int BC_WindowBase::ctrl_down()
3114 return top_level->ctrl_mask;
3118 int BC_WindowBase::get_keypress()
3120 return top_level->key_pressed;
3123 int BC_WindowBase::get_double_click()
3125 return top_level->double_click;
3128 int BC_WindowBase::get_bgcolor()
3133 int BC_WindowBase::resize_window(int w, int h)
3135 if(window_type == MAIN_WINDOW && !allow_resize)
3137 XSizeHints size_hints;
3138 size_hints.flags = PSize | PMinSize | PMaxSize;
3139 size_hints.width = w;
3140 size_hints.height = h;
3141 size_hints.min_width = w;
3142 size_hints.max_width = w;
3143 size_hints.min_height = h;
3144 size_hints.max_height = h;
3145 XSetNormalHints(top_level->display, win, &size_hints);
3147 XResizeWindow(top_level->display, win, w, h);
3152 pixmap = new BC_Pixmap(this, w, h);
3154 // Propagate to menubar
3155 for(int i = 0; i < subwindows->total; i++)
3157 subwindows->values[i]->dispatch_resize_event(w, h);
3160 draw_background(0, 0, w, h);
3161 if(top_level == this && get_resources()->recursive_resizing)
3162 resize_history.append(new BC_ResizeCall(w, h));
3166 // The only way for resize events to be propagated is by updating the internal w and h
3167 int BC_WindowBase::resize_event(int w, int h)
3169 if(window_type == MAIN_WINDOW)
3177 int BC_WindowBase::reposition_widget(int x, int y, int w, int h)
3179 return(reposition_window(x, y, w, h));
3182 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3186 // Some tools set their own dimensions before calling this, causing the
3187 // resize check to skip.
3191 if(w > 0 && w != this->w)
3197 if(h > 0 && h != this->h)
3203 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3206 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3208 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3210 if(translation_count && window_type == MAIN_WINDOW)
3212 // KDE shifts window right and down.
3213 // FVWM leaves window alone and adds border around it.
3214 XMoveResizeWindow(top_level->display,
3216 x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x,
3217 y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y,
3223 XMoveResizeWindow(top_level->display,
3234 pixmap = new BC_Pixmap(this, this->w, this->h);
3235 // Propagate to menubar
3236 for(int i = 0; i < subwindows->total; i++)
3238 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3241 // draw_background(0, 0, w, h);
3247 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3249 get_resources()->tooltips_enabled = tooltips_enabled;
3253 int BC_WindowBase::raise_window(int do_flush)
3255 XRaiseWindow(top_level->display, win);
3256 if(do_flush) XFlush(top_level->display);
3260 void BC_WindowBase::set_background(VFrame *bitmap)
3262 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3264 bg_pixmap = new BC_Pixmap(this,
3267 shared_bg_pixmap = 0;
3268 draw_background(0, 0, w, h);
3271 void BC_WindowBase::set_title(char *text)
3273 XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0);
3274 strcpy(this->title, _(text));
3278 char* BC_WindowBase::get_title()
3283 int BC_WindowBase::get_toggle_value()
3285 return toggle_value;
3288 int BC_WindowBase::get_toggle_drag()
3293 int BC_WindowBase::set_icon(VFrame *data)
3295 if(icon_pixmap) delete icon_pixmap;
3296 icon_pixmap = new BC_Pixmap(top_level,
3301 icon_window = new BC_Popup(this,
3304 icon_pixmap->get_w(),
3305 icon_pixmap->get_h(),
3307 1, // All windows are hidden initially
3311 wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3312 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3313 wm_hints.icon_mask = icon_pixmap->get_alpha();
3314 wm_hints.icon_window = icon_window->win;
3315 wm_hints.window_group = XGroupLeader;
3317 // for(int i = 0; i < 1000; i++)
3318 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3321 XSetWMHints(top_level->display, top_level->win, &wm_hints);
3322 XSync(top_level->display, 0);
3326 int BC_WindowBase::set_w(int w)
3332 int BC_WindowBase::set_h(int h)
3338 int BC_WindowBase::load_defaults(BC_Hash *defaults)
3340 BC_Resources *resources = get_resources();
3341 char string[BCTEXTLEN];
3342 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3344 sprintf(string, "FILEBOX_HISTORY%d", i);
3345 resources->filebox_history[i][0] = 0;
3346 defaults->get(string, resources->filebox_history[i]);
3348 resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3349 resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3350 resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3351 defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3355 int BC_WindowBase::save_defaults(BC_Hash *defaults)
3357 BC_Resources *resources = get_resources();
3358 char string[BCTEXTLEN];
3359 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3361 sprintf(string, "FILEBOX_HISTORY%d", i);
3362 defaults->update(string, resources->filebox_history[i]);
3364 defaults->update("FILEBOX_MODE", resources->filebox_mode);
3365 defaults->update("FILEBOX_W", resources->filebox_w);
3366 defaults->update("FILEBOX_H", resources->filebox_h);
3367 defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3373 // For some reason XTranslateCoordinates can take a long time to return.
3374 // We work around this by only calling it when the event windows are different.
3375 void BC_WindowBase::translate_coordinates(Window src_w,
3387 *dest_x_return = src_x;
3388 *dest_y_return = src_y;
3392 XTranslateCoordinates(top_level->display,
3400 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3410 #ifdef HAVE_LIBXXF86VM
3411 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3415 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3417 XF86VidModeModeInfo **vm_modelines;
3418 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3419 for (i = 0; i < vm_count; i++) {
3420 if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3423 display = top_level->display;
3424 if (vm_modelines[*vm]->hdisplay == *width)
3428 *width = vm_modelines[*vm]->hdisplay;
3429 *height = vm_modelines[*vm]->vdisplay;
3434 void BC_WindowBase::scale_vm(int vm)
3436 int foo,bar,dotclock;
3437 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3440 XF86VidModeModeInfo **vm_modelines;
3441 XF86VidModeModeLine vml;
3442 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3443 XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3444 orig_modeline.dotclock = dotclock;
3445 orig_modeline.hdisplay = vml.hdisplay;
3446 orig_modeline.hsyncstart = vml.hsyncstart;
3447 orig_modeline.hsyncend = vml.hsyncend;
3448 orig_modeline.htotal = vml.htotal;
3449 orig_modeline.vdisplay = vml.vdisplay;
3450 orig_modeline.vsyncstart = vml.vsyncstart;
3451 orig_modeline.vsyncend = vml.vsyncend;
3452 orig_modeline.vtotal = vml.vtotal;
3453 orig_modeline.flags = vml.flags;
3454 orig_modeline.privsize = vml.privsize;
3455 // orig_modeline.private = vml.private;
3456 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3457 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3458 XFlush(top_level->display);
3462 void BC_WindowBase::restore_vm()
3464 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3465 XFlush(top_level->display);
3476 GLXContext glXCreateContext(Display *dpy,
3478 GLXContext shareList,
3481 int glXMakeCurrent(Display *dpy,
3485 void glXSwapBuffers(Display *dpy,
3491 void BC_WindowBase::enable_opengl()
3493 lock_window("BC_WindowBase::enable_opengl");
3496 XVisualInfo viproto;
3497 XVisualInfo *visinfo;
3500 viproto.screen = top_level->screen;
3501 visinfo = XGetVisualInfo(top_level->display,
3506 gl_context = glXCreateContext(top_level->display,
3511 glXMakeCurrent(top_level->display,
3515 // Need expose events for 3D
3516 unsigned long valuemask = CWEventMask;
3517 XSetWindowAttributes attributes;
3518 attributes.event_mask = DEFAULT_EVENT_MASKS |
3520 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3522 opengl_lock.unlock();
3526 void BC_WindowBase::disable_opengl()
3528 unsigned long valuemask = CWEventMask;
3529 XSetWindowAttributes attributes;
3530 attributes.event_mask = DEFAULT_EVENT_MASKS;
3531 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3534 void BC_WindowBase::lock_opengl()
3536 lock_window("BC_WindowBase::lock_opengl");
3538 glXMakeCurrent(top_level->display,
3543 void BC_WindowBase::unlock_opengl()
3545 opengl_lock.unlock();
3549 void BC_WindowBase::flip_opengl()
3551 glXSwapBuffers(top_level->display, win);
3555 int BC_WindowBase::get_event_count()
3557 event_lock->lock("BC_WindowBase::get_event_count");
3558 int result = common_events.total;
3559 event_lock->unlock();
3563 XEvent* BC_WindowBase::get_event()
3566 while(!done && !result)
3568 event_condition->lock("BC_WindowBase::get_event");
3569 event_lock->lock("BC_WindowBase::get_event");
3571 if(common_events.total && !done)
3573 result = common_events.values[0];
3574 common_events.remove_number(0);
3577 event_lock->unlock();
3582 void BC_WindowBase::put_event(XEvent *event)
3584 event_lock->lock("BC_WindowBase::put_event");
3585 common_events.append(event);
3586 event_lock->unlock();
3587 event_condition->unlock();