2 #include "bcclipboard.h"
3 #include "bcdisplayinfo.h"
7 #include "bcpopupmenu.h"
8 #include "bcrepeater.h"
9 #include "bcresources.h"
10 #include "bcsignals.h"
11 #include "bcsubwindow.h"
12 #include "bcsynchronous.h"
14 #include "bcwidgetgrid.h"
15 #include "bcwindowbase.h"
16 #include "bcwindowevents.h"
17 #include "colormodels.h"
19 #include "condition.h"
35 #include <X11/extensions/Xvlib.h>
36 #include <X11/extensions/shape.h>
39 BC_ResizeCall::BC_ResizeCall(int w, int h)
55 BC_Resources BC_WindowBase::resources;
57 Window XGroupLeader = 0;
59 BC_WindowBase::BC_WindowBase()
61 //printf("BC_WindowBase::BC_WindowBase 1\n");
62 BC_WindowBase::initialize();
65 BC_WindowBase::~BC_WindowBase()
67 #ifdef HAVE_LIBXXF86VM
68 if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
75 if(window_type != MAIN_WINDOW)
77 if(top_level->active_menubar == this) top_level->active_menubar = 0;
78 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
79 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
80 // Remove pointer from parent window to this
81 parent_window->subwindows->remove(this);
85 // Delete the subwindows
89 while(subwindows->total)
91 // Subwindow removes its own pointer
92 delete subwindows->values[0];
99 while (widgetgrids->total)
101 delete widgetgrids->last();
102 widgetgrids->remove();
110 // Destroyed in synchronous thread if gl context exists.
112 if(!gl_win_context || !get_resources()->get_synchronous())
114 XDestroyWindow(top_level->display, win);
116 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
117 if(icon_pixmap) delete icon_pixmap;
118 if(temp_bitmap) delete temp_bitmap;
124 if(window_type == MAIN_WINDOW)
126 XFreeGC(display, gc);
129 XftFontClose (display, (XftFont*)largefont_xft);
131 XftFontClose (display, (XftFont*)mediumfont_xft);
133 XftFontClose (display, (XftFont*)smallfont_xft);
136 // Can't close display if another thread is waiting for events.
137 // Synchronous thread must delete display if gl_context exists.
139 if(!gl_win_context || !get_resources()->get_synchronous())
141 XCloseDisplay(display);
142 clipboard->stop_clipboard();
150 // Must be last reference to display.
151 // This only works if it's a MAIN_WINDOW since the display deletion for
152 // a subwindow is not determined by the subwindow.
154 if(gl_win_context && get_resources()->get_synchronous())
156 printf("BC_WindowBase::~BC_WindowBase window deleted but opengl deletion is not\n"
157 "implemented for BC_Pixmap.\n");
158 get_resources()->get_synchronous()->delete_window(this);
162 resize_history.remove_all_objects();
163 common_events.remove_all_objects();
165 delete event_condition;
167 UNSET_ALL_LOCKS(this)
170 int BC_WindowBase::initialize()
188 translation_events = 0;
189 ctrl_mask = shift_mask = alt_mask = 0;
190 cursor_x = cursor_y = button_number = 0;
193 button_time1 = button_time2 = 0;
198 active_popup_menu = 0;
199 active_subwindow = 0;
203 persistant_tooltip = 0;
204 // next_repeat_id = 0;
207 current_font = MEDIUMFONT;
208 current_color = BLACK;
209 current_cursor = ARROW_CURSOR;
212 shared_bg_pixmap = 0;
214 window_type = MAIN_WINDOW;
215 translation_count = 0;
216 x_correction = y_correction = 0;
225 #ifdef HAVE_LIBXXF86VM
232 // Need these right away since put_event is called before run_window sometimes.
233 event_lock = new Mutex("BC_WindowBase::event_lock");
234 event_condition = new Condition(0, "BC_WindowBase::event_condition");
235 cursor_timer = new Timer;
244 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
247 ButtonReleaseMask | \
248 PointerMotionMask | \
252 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
266 BC_Pixmap *bg_pixmap,
269 XSetWindowAttributes attr;
271 XSizeHints size_hints;
274 #ifdef HAVE_LIBXXF86VM
278 id = get_resources()->get_id();
280 if(parent_window) top_level = parent_window->top_level;
282 #ifdef HAVE_LIBXXF86VM
283 if(window_type == VIDMODE_SCALED_WINDOW)
284 closest_vm(&vm,&w,&h);
291 this->bg_color = bg_color;
292 this->window_type = window_type;
294 this->private_color = private_color;
295 this->parent_window = parent_window;
296 this->bg_pixmap = bg_pixmap;
297 this->allow_resize = allow_resize;
298 strcpy(this->title, _(title));
299 if(bg_pixmap) shared_bg_pixmap = 1;
301 if(parent_window) top_level = parent_window->top_level;
303 subwindows = new BC_SubWindowList;
304 widgetgrids = new BC_WidgetGridList;
307 if(window_type == MAIN_WINDOW)
310 parent_window = this;
312 // This function must be the first Xlib
313 // function a multi-threaded program calls
317 // get the display connection
318 display = init_display(display_name);
319 // event_display = init_display(display_name);
321 // Fudge window placement
322 root_w = get_root_w(1, 0);
323 root_h = get_root_h(0);
324 if(this->x + this->w > root_w) this->x = root_w - this->w;
325 if(this->y + this->h > root_h) this->y = root_h - this->h;
326 if(this->x < 0) this->x = 0;
327 if(this->y < 0) this->y = 0;
328 screen = DefaultScreen(display);
329 rootwin = RootWindow(display, screen);
332 vis = DefaultVisual(display, screen);
333 default_depth = DefaultDepth(display, screen);
335 client_byte_order = (*(u_int32_t*)"a ") & 0x00000001;
336 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
339 // This must be done before fonts to know if antialiasing is available.
342 if(resources.use_shm < 0) resources.initialize_display(this);
343 x_correction = get_resources()->get_left_border();
344 y_correction = get_resources()->get_top_border();
346 if(this->bg_color == -1)
347 this->bg_color = resources.get_bg_color();
349 // printf("bcwindowbase 1 %s\n", title);
350 // if(window_type == MAIN_WINDOW) sleep(1);
351 // printf("bcwindowbase 10\n");
362 attr.event_mask = DEFAULT_EVENT_MASKS |
363 StructureNotifyMask |
366 attr.background_pixel = get_color(this->bg_color);
367 attr.colormap = cmap;
368 attr.cursor = get_cursor_struct(ARROW_CURSOR);
370 win = XCreateWindow(display,
377 top_level->default_depth,
383 XGetNormalHints(display, win, &size_hints);
385 size_hints.flags = PSize | PMinSize | PMaxSize;
386 size_hints.width = this->w;
387 size_hints.height = this->h;
388 size_hints.min_width = allow_resize ? minw : this->w;
389 size_hints.max_width = allow_resize ? 32767 : this->w;
390 size_hints.min_height = allow_resize ? minh : this->h;
391 size_hints.max_height = allow_resize ? 32767 : this->h;
392 if(x > -BC_INFINITY && x < BC_INFINITY)
394 size_hints.flags |= PPosition;
395 size_hints.x = this->x;
396 size_hints.y = this->y;
399 XSetStandardProperties(display,
409 clipboard = new BC_Clipboard(display_name);
410 clipboard->start_clipboard();
414 Atom ClientLeaderXAtom;
415 if (XGroupLeader == 0)
417 char *instance_name = "cinelerra";
418 char *class_name = "Cinelerra";
419 XClassHint *class_hints = XAllocClassHint();
420 class_hints->res_name = instance_name;
421 class_hints->res_class = class_name;
422 XSetClassHint(top_level->display, win, class_hints);
424 ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
425 XChangeProperty(display,
431 (unsigned char *)&XGroupLeader,
438 #ifdef HAVE_LIBXXF86VM
439 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
446 #ifdef HAVE_LIBXXF86VM
447 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
449 if(window_type == POPUP_WINDOW)
459 attr.event_mask = DEFAULT_EVENT_MASKS |
462 if(this->bg_color == -1)
463 this->bg_color = resources.get_bg_color();
464 attr.background_pixel = top_level->get_color(bg_color);
465 attr.colormap = top_level->cmap;
466 if(top_level->is_hourglass)
467 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
469 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
470 attr.override_redirect = True;
471 attr.save_under = True;
473 win = XCreateWindow(top_level->display,
480 top_level->default_depth,
487 if(window_type == SUB_WINDOW)
492 attr.event_mask = DEFAULT_EVENT_MASKS;
493 attr.background_pixel = top_level->get_color(this->bg_color);
494 if(top_level->is_hourglass)
495 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
497 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
498 win = XCreateWindow(top_level->display,
505 top_level->default_depth,
511 XMapWindow(top_level->display, win);
514 // Create pixmap for all windows
515 pixmap = new BC_Pixmap(this, this->w, this->h);
518 // Create truetype rendering surface
520 if(get_resources()->use_xft)
522 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n",
523 // top_level->display,
527 xft_drawable = XftDrawCreate(top_level->display,
531 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n",
533 // top_level->display,
540 // Set up options for main window
541 if(window_type == MAIN_WINDOW)
543 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
545 this->bg_pixmap = new BC_Pixmap(this,
546 get_resources()->bg_image,
550 if(!hidden) show_window();
557 draw_background(0, 0, this->w, this->h);
560 // Set up options for popup window
561 #ifdef HAVE_LIBXXF86VM
562 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
564 if(window_type == POPUP_WINDOW)
568 if(!hidden) show_window();
573 Display* BC_WindowBase::init_display(char *display_name)
577 if(display_name && display_name[0] == 0) display_name = NULL;
578 if((display = XOpenDisplay(display_name)) == NULL)
580 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
582 if(getenv("DISPLAY") == NULL)
584 printf("'DISPLAY' environment variable not set.\n");
588 // Try again with default display.
590 if((display = XOpenDisplay(0)) == NULL)
592 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
600 Display* BC_WindowBase::get_display()
602 return top_level->display;
605 int BC_WindowBase::get_screen()
607 return top_level->screen;
610 int BC_WindowBase::run_window()
616 // Events may have been sent before run_window so can't initialize them here.
619 if(window_type == MAIN_WINDOW)
621 // tooltip_id = get_repeat_id();
622 set_repeat(get_resources()->tooltip_delay);
625 // Start X server events
626 event_thread = new BC_WindowEvents(this);
627 event_thread->start();
629 // Start common events
635 unset_all_repeaters();
639 event_condition->reset();
640 common_events.remove_all_objects();
646 int BC_WindowBase::get_key_masks(XEvent *event)
648 // printf("BC_WindowBase::get_key_masks %llx\n",
649 // event->xkey.state);
651 ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
653 shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
654 alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
664 int BC_WindowBase::dispatch_event()
671 XClientMessageEvent *ptr;
673 int cancel_resize, cancel_translation;
677 // If an event is waiting get it, otherwise
678 // wait for next event only if there are no compressed events.
679 if(get_event_count() ||
680 (!motion_events && !resize_events && !translation_events))
682 // XNextEvent(display, event);
684 // Lock out window deletions
685 lock_window("BC_WindowBase::dispatch_event 1");
686 // get_key_masks(event);
689 // Handle compressed events
691 lock_window("BC_WindowBase::dispatch_event 2");
693 dispatch_resize_event(last_resize_w, last_resize_h);
696 dispatch_motion_event();
698 if(translation_events)
699 dispatch_translation_event();
705 //printf("1 %s %p %d\n", title, event, event->type);
709 get_key_masks(event);
710 // Clear the resize buffer
711 if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
712 // Clear the motion buffer since this can clear the window
715 dispatch_motion_event();
718 ptr = (XClientMessageEvent*)event;
721 if(ptr->message_type == ProtoXAtom &&
722 ptr->data.l[0] == DelWinXAtom)
727 if(ptr->message_type == RepeaterXAtom)
729 dispatch_repeat_event(ptr->data.l[0]);
730 // Make sure the repeater still exists.
731 // for(int i = 0; i < repeaters.total; i++)
733 // if(repeaters.values[i]->repeat_id == ptr->data.l[0])
735 // dispatch_repeat_event_master(ptr->data.l[0]);
741 if(ptr->message_type == SetDoneXAtom)
754 dispatch_focus_out();
766 get_key_masks(event);
767 cursor_x = event->xbutton.x;
768 cursor_y = event->xbutton.y;
769 button_number = event->xbutton.button;
770 event_win = event->xany.window;
771 if (button_number != 4 && button_number != 5)
773 button_pressed = event->xbutton.button;
774 button_time1 = button_time2;
775 button_time2 = event->xbutton.time;
778 drag_win = event_win;
779 drag_x1 = cursor_x - get_resources()->drag_radius;
780 drag_x2 = cursor_x + get_resources()->drag_radius;
781 drag_y1 = cursor_y - get_resources()->drag_radius;
782 drag_y2 = cursor_y + get_resources()->drag_radius;
784 if(button_time2 - button_time1 < resources.double_click)
786 // Ignore triple clicks
788 button_time2 = button_time1 = 0;
793 dispatch_button_press();
797 get_key_masks(event);
798 button_number = event->xbutton.button;
799 event_win = event->xany.window;
800 if (button_number != 4 && button_number != 5)
803 dispatch_button_release();
808 event_win = event->xany.window;
809 dispatch_expose_event();
813 get_key_masks(event);
814 // Dispatch previous motion event if this is a subsequent motion from a different window
815 if(motion_events && last_motion_win != event->xany.window)
817 dispatch_motion_event();
820 // Buffer the current motion
822 last_motion_x = event->xmotion.x;
823 last_motion_y = event->xmotion.y;
824 last_motion_win = event->xany.window;
827 case ConfigureNotify:
828 get_key_masks(event);
829 XTranslateCoordinates(top_level->display,
837 last_resize_w = event->xconfigure.width;
838 last_resize_h = event->xconfigure.height;
841 cancel_translation = 0;
843 // Resize history prevents responses to recursive resize requests
844 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
846 if(resize_history.values[i]->w == last_resize_w &&
847 resize_history.values[i]->h == last_resize_h)
849 delete resize_history.values[i];
850 resize_history.remove_number(i);
855 if(last_resize_w == w && last_resize_h == h)
863 if((last_translate_x == x && last_translate_y == y))
864 cancel_translation = 1;
866 if(!cancel_translation)
868 translation_events = 1;
875 get_key_masks(event);
877 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
879 // printf("BC_WindowBase::dispatch_event 2 %llx\n",
880 // event->xkey.state);
881 // block out control keys
882 if(keysym > 0xffe0 && keysym < 0xffff) break;
885 if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
890 // block out extra keys
900 // Translate key codes
901 case XK_Return: key_pressed = RETURN; break;
902 case XK_Up: key_pressed = UP; break;
903 case XK_Down: key_pressed = DOWN; break;
904 case XK_Left: key_pressed = LEFT; break;
905 case XK_Right: key_pressed = RIGHT; break;
906 case XK_Next: key_pressed = PGDN; break;
907 case XK_Prior: key_pressed = PGUP; break;
908 case XK_BackSpace: key_pressed = BACKSPACE; break;
909 case XK_Escape: key_pressed = ESC; break;
912 key_pressed = LEFTTAB;
916 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
917 case XK_underscore: key_pressed = '_'; break;
918 case XK_asciitilde: key_pressed = '~'; break;
919 case XK_Delete: key_pressed = DELETE; break;
920 case XK_Home: key_pressed = HOME; break;
921 case XK_End: key_pressed = END; break;
924 case XK_KP_Enter: key_pressed = KPENTER; break;
925 case XK_KP_Add: key_pressed = KPPLUS; break;
927 case XK_KP_End: key_pressed = KP1; break;
929 case XK_KP_Down: key_pressed = KP2; break;
931 case XK_KP_Page_Down: key_pressed = KP3; break;
933 case XK_KP_Left: key_pressed = KP4; break;
935 case XK_KP_Begin: key_pressed = KP5; break;
937 case XK_KP_Right: key_pressed = KP6; break;
939 case XK_KP_Insert: key_pressed = KPINS; break;
941 case XK_KP_Delete: key_pressed = KPDEL; break;
943 //key_pressed = keys_return[0];
944 key_pressed = keysym & 0xff;
948 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
949 result = dispatch_keypress_event();
950 // Handle some default keypresses
953 if(key_pressed == 'w' ||
962 event_win = event->xany.window;
963 dispatch_cursor_leave();
967 event_win = event->xany.window;
968 cursor_x = event->xcrossing.x;
969 cursor_y = event->xcrossing.y;
970 dispatch_cursor_enter();
973 //printf("100 %s %p %d\n", title, event, event->type);
976 if(event) delete event;
980 int BC_WindowBase::dispatch_expose_event()
983 for(int i = 0; i < subwindows->total && !result; i++)
985 result = subwindows->values[i]->dispatch_expose_event();
989 if(!result) expose_event();
993 int BC_WindowBase::dispatch_resize_event(int w, int h)
995 // Can't store new w and h until the event is handles
996 // because bcfilebox depends on the old w and h to
997 // reposition widgets.
998 if(window_type == MAIN_WINDOW)
1002 pixmap = new BC_Pixmap(this, w, h);
1004 clear_box(0, 0, w, h);
1007 // Propagate to subwindows
1008 for(int i = 0; i < subwindows->total; i++)
1010 subwindows->values[i]->dispatch_resize_event(w, h);
1013 // Propagate to user
1016 if(window_type == MAIN_WINDOW)
1024 int BC_WindowBase::dispatch_translation_event()
1026 translation_events = 0;
1027 if(window_type == MAIN_WINDOW)
1031 x = last_translate_x;
1032 y = last_translate_y;
1033 // Correct for window manager offsets
1038 for(int i = 0; i < subwindows->total; i++)
1040 subwindows->values[i]->dispatch_translation_event();
1043 translation_event();
1047 int BC_WindowBase::dispatch_motion_event()
1052 if(top_level == this)
1054 event_win = last_motion_win;
1058 if(get_button_down() && !active_menubar && !active_popup_menu)
1062 cursor_x = last_motion_x;
1063 cursor_y = last_motion_y;
1064 result = dispatch_drag_motion();
1068 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
1069 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1074 result = dispatch_drag_start();
1077 cursor_x = last_motion_x;
1078 cursor_y = last_motion_y;
1080 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1081 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1082 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1085 for(int i = 0; i < subwindows->total && !result; i++)
1087 result = subwindows->values[i]->dispatch_motion_event();
1091 if(!result) result = cursor_motion_event(); // give to user
1095 int BC_WindowBase::dispatch_keypress_event()
1098 if(top_level == this)
1100 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1103 for(int i = 0; i < subwindows->total && !result; i++)
1105 result = subwindows->values[i]->dispatch_keypress_event();
1108 if(!result) result = keypress_event();
1113 int BC_WindowBase::dispatch_focus_in()
1115 for(int i = 0; i < subwindows->total; i++)
1117 subwindows->values[i]->dispatch_focus_in();
1125 int BC_WindowBase::dispatch_focus_out()
1127 for(int i = 0; i < subwindows->total; i++)
1129 subwindows->values[i]->dispatch_focus_out();
1137 int BC_WindowBase::get_has_focus()
1139 return top_level->has_focus;
1142 int BC_WindowBase::get_deleting()
1144 if(is_deleting) return 1;
1145 if(parent_window && parent_window->get_deleting()) return 1;
1149 int BC_WindowBase::dispatch_button_press()
1152 if(top_level == this)
1154 if(active_menubar) result = active_menubar->dispatch_button_press();
1155 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1156 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1159 for(int i = 0; i < subwindows->total && !result; i++)
1161 result = subwindows->values[i]->dispatch_button_press();
1164 if(!result) result = button_press_event();
1169 int BC_WindowBase::dispatch_button_release()
1172 if(top_level == this)
1174 if(active_menubar) result = active_menubar->dispatch_button_release();
1175 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1176 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1177 if(!result && button_number != 4 && button_number != 5)
1178 result = dispatch_drag_stop();
1181 for(int i = 0; i < subwindows->total && !result; i++)
1183 result = subwindows->values[i]->dispatch_button_release();
1188 result = button_release_event();
1195 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1198 // all repeat event handlers get called and decide based on activity and duration
1199 // whether to respond
1200 for(int i = 0; i < subwindows->total; i++)
1202 subwindows->values[i]->dispatch_repeat_event(duration);
1206 repeat_event(duration);
1210 // Unlock next repeat signal
1211 if(window_type == MAIN_WINDOW)
1213 for(int i = 0; i < repeaters.total; i++)
1215 if(repeaters.values[i]->delay == duration)
1217 repeaters.values[i]->repeat_lock->unlock();
1225 void BC_WindowBase::unhide_cursor()
1230 if(top_level->is_hourglass)
1231 set_cursor(HOURGLASS_CURSOR, 1);
1233 set_cursor(current_cursor, 1);
1235 cursor_timer->update();
1239 void BC_WindowBase::update_video_cursor()
1241 if(video_on && !is_transparent)
1243 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1246 set_cursor(TRANSPARENT_CURSOR, 1);
1247 cursor_timer->update();
1252 cursor_timer->update();
1257 int BC_WindowBase::dispatch_cursor_leave()
1261 for(int i = 0; i < subwindows->total; i++)
1263 subwindows->values[i]->dispatch_cursor_leave();
1266 cursor_leave_event();
1270 int BC_WindowBase::dispatch_cursor_enter()
1276 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1277 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1278 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1280 for(int i = 0; !result && i < subwindows->total; i++)
1282 result = subwindows->values[i]->dispatch_cursor_enter();
1285 if(!result) result = cursor_enter_event();
1289 int BC_WindowBase::cursor_enter_event()
1294 int BC_WindowBase::cursor_leave_event()
1299 int BC_WindowBase::close_event()
1305 int BC_WindowBase::dispatch_drag_start()
1308 if(active_menubar) result = active_menubar->dispatch_drag_start();
1309 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1310 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1312 for(int i = 0; i < subwindows->total && !result; i++)
1314 result = subwindows->values[i]->dispatch_drag_start();
1317 if(!result) result = is_dragging = drag_start_event();
1321 int BC_WindowBase::dispatch_drag_stop()
1325 for(int i = 0; i < subwindows->total && !result; i++)
1327 result = subwindows->values[i]->dispatch_drag_stop();
1330 if(is_dragging && !result)
1340 int BC_WindowBase::dispatch_drag_motion()
1343 for(int i = 0; i < subwindows->total && !result; i++)
1345 result = subwindows->values[i]->dispatch_drag_motion();
1348 if(is_dragging && !result)
1350 drag_motion_event();
1361 int BC_WindowBase::show_tooltip(int w, int h)
1365 if(!tooltip_on && get_resources()->tooltips_enabled)
1368 top_level->hide_tooltip();
1372 w = get_text_width(MEDIUMFONT, tooltip_text);
1375 h = get_text_height(MEDIUMFONT, tooltip_text);
1377 w += TOOLTIP_MARGIN * 2;
1378 h += TOOLTIP_MARGIN * 2;
1380 XTranslateCoordinates(top_level->display,
1388 tooltip_popup = new BC_Popup(top_level,
1393 get_resources()->tooltip_bg_color);
1396 tooltip_popup->set_font(MEDIUMFONT);
1397 tooltip_popup->flash();
1398 tooltip_popup->flush();
1403 int BC_WindowBase::hide_tooltip()
1406 for(int i = 0; i < subwindows->total; i++)
1408 subwindows->values[i]->hide_tooltip();
1414 delete tooltip_popup;
1420 int BC_WindowBase::set_tooltip(char *text)
1422 strcpy(this->tooltip_text, text);
1423 // Update existing tooltip if it is visible
1427 tooltip_popup->flash();
1432 // signal the event handler to repeat
1433 int BC_WindowBase::set_repeat(int64_t duration)
1437 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1440 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1442 // test repeater database for duplicates
1443 for(int i = 0; i < repeaters.total; i++)
1446 if(repeaters.values[i]->delay == duration)
1448 repeaters.values[i]->start_repeating();
1453 BC_Repeater *repeater = new BC_Repeater(this, duration);
1454 repeater->initialize();
1455 repeaters.append(repeater);
1456 repeater->start_repeating();
1460 int BC_WindowBase::unset_repeat(int64_t duration)
1462 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1464 BC_Repeater *repeater = 0;
1465 for(int i = 0; i < repeaters.total; i++)
1467 if(repeaters.values[i]->delay == duration)
1469 repeaters.values[i]->stop_repeating();
1476 int BC_WindowBase::unset_all_repeaters()
1478 for(int i = 0; i < repeaters.total; i++)
1480 repeaters.values[i]->stop_repeating();
1482 repeaters.remove_all_objects();
1486 // long BC_WindowBase::get_repeat_id()
1488 // return top_level->next_repeat_id++;
1491 int BC_WindowBase::arm_repeat(int64_t duration)
1493 XEvent *event = new XEvent;
1494 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1495 ptr->type = ClientMessage;
1496 ptr->message_type = RepeaterXAtom;
1498 ptr->data.l[0] = duration;
1500 // Couldn't use XSendEvent since it locked up randomly.
1502 // XSendEvent(top_level->event_display,
1511 int BC_WindowBase::get_atoms()
1513 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
1514 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1515 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
1516 if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1517 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1521 void BC_WindowBase::init_cursors()
1523 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1524 cross_cursor = XCreateFontCursor(display, XC_crosshair);
1525 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1526 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1527 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1528 move_cursor = XCreateFontCursor(display, XC_fleur);
1529 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1530 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1531 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1532 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1533 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1534 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1535 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1536 hourglass_cursor = XCreateFontCursor(display, XC_watch);
1539 char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
1540 Colormap colormap = DefaultColormap(display, screen);
1541 Pixmap pixmap_bottom = XCreateBitmapFromData(display,
1546 XColor black, dummy;
1547 XAllocNamedColor(display, colormap, "black", &black, &dummy);
1548 transparent_cursor = XCreatePixmapCursor(display,
1555 // XDefineCursor(display, win, transparent_cursor);
1556 XFreePixmap(display, pixmap_bottom);
1559 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1565 color_model = BC_RGB8;
1568 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1571 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1574 color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1580 int BC_WindowBase::init_colors()
1583 current_color_value = current_color_pixel = 0;
1585 // Get the real depth
1588 ximage = XCreateImage(top_level->display,
1590 top_level->default_depth,
1598 bits_per_pixel = ximage->bits_per_pixel;
1599 XDestroyImage(ximage);
1601 color_model = evaluate_color_model(client_byte_order,
1604 // Get the color model
1610 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1611 create_private_colors();
1615 cmap = DefaultColormap(display, screen);
1616 create_shared_colors();
1619 allocate_color_table();
1621 get_resources()->use_xft = 0;
1625 cmap = DefaultColormap(display, screen);
1631 int BC_WindowBase::create_private_colors()
1636 for(int i = 0; i < 255; i++)
1638 color = (i & 0xc0) << 16;
1639 color += (i & 0x38) << 10;
1640 color += (i & 0x7) << 5;
1641 color_table[i][0] = color;
1643 create_shared_colors(); // overwrite the necessary colors on the table
1648 int BC_WindowBase::create_color(int color)
1650 if(total_colors == 256)
1652 // replace the closest match with an exact match
1653 color_table[get_color_rgb8(color)][0] = color;
1657 // add the color to the table
1658 color_table[total_colors][0] = color;
1664 int BC_WindowBase::create_shared_colors()
1666 create_color(BLACK);
1667 create_color(WHITE);
1669 create_color(LTGREY);
1670 create_color(MEGREY);
1671 create_color(MDGREY);
1672 create_color(DKGREY);
1674 create_color(LTCYAN);
1675 create_color(MECYAN);
1676 create_color(MDCYAN);
1677 create_color(DKCYAN);
1679 create_color(LTGREEN);
1680 create_color(GREEN);
1681 create_color(DKGREEN);
1683 create_color(LTPINK);
1687 create_color(LTBLUE);
1689 create_color(DKBLUE);
1691 create_color(LTYELLOW);
1692 create_color(MEYELLOW);
1693 create_color(MDYELLOW);
1694 create_color(DKYELLOW);
1696 create_color(LTPURPLE);
1697 create_color(MEPURPLE);
1698 create_color(MDPURPLE);
1699 create_color(DKPURPLE);
1701 create_color(FGGREY);
1702 create_color(MNBLUE);
1703 create_color(ORANGE);
1704 create_color(FTGREY);
1709 int BC_WindowBase::allocate_color_table()
1711 int red, green, blue, color;
1715 for(int i = 0; i < total_colors; i++)
1717 color = color_table[i][0];
1718 red = (color & 0xFF0000) >> 16;
1719 green = (color & 0x00FF00) >> 8;
1720 blue = color & 0xFF;
1722 col.flags = DoRed | DoGreen | DoBlue;
1723 col.red = red<<8 | red;
1724 col.green = green<<8 | green;
1725 col.blue = blue<<8 | blue;
1727 XAllocColor(display, cmap, &col);
1728 color_table[i][1] = col.pixel;
1731 XInstallColormap(display, cmap);
1735 int BC_WindowBase::init_window_shape()
1737 if(bg_pixmap && bg_pixmap->use_alpha())
1739 XShapeCombineMask(top_level->display,
1744 bg_pixmap->get_alpha(),
1751 int BC_WindowBase::init_gc()
1753 unsigned long gcmask;
1754 gcmask = GCFont | GCGraphicsExposures;
1757 gcvalues.font = mediumfont->fid; // set the font
1758 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
1759 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1763 int BC_WindowBase::init_fonts()
1765 if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL)
1766 if((largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1767 largefont = XLoadQueryFont(display, "fixed");
1769 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL)
1770 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1771 mediumfont = XLoadQueryFont(display, "fixed");
1773 if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL)
1774 if((smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1775 smallfont = XLoadQueryFont(display, "fixed");
1778 if(get_resources()->use_xft)
1782 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
1784 if(!(largefont_xft = XftFontOpenXlfd(display,
1786 resources.large_font_xft)))
1788 largefont_xft = XftFontOpenXlfd(display,
1792 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
1793 if(!(largefont_xft = XftFontOpenXlfd(display,
1795 resources.large_font_xft)))
1797 largefont_xft = XftFontOpenXlfd(display,
1801 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
1804 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1806 resources.medium_font_xft)))
1808 mediumfont_xft = XftFontOpenXlfd(display,
1814 if(!(smallfont_xft = XftFontOpenXlfd(display,
1816 resources.small_font_xft)))
1818 smallfont_xft = XftFontOpenXlfd(display,
1823 //printf("BC_WindowBase::init_fonts 100 %s %p\n",
1824 //resources.medium_font,
1827 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
1828 resources.large_font_xft,
1830 resources.medium_font_xft,
1832 resources.small_font_xft,
1835 // Extension failed to locate fonts
1836 if(!largefontset || !mediumfontset || !smallfontset)
1838 printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1839 resources.large_font_xft,
1841 resources.medium_font_xft,
1843 resources.small_font_xft,
1845 get_resources()->use_xft = 0;
1850 if(get_resources()->use_fontset)
1855 // FIXME: should check the m,d,n values
1856 if((largefontset = XCreateFontSet(display,
1857 resources.large_fontset,
1861 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1862 if((mediumfontset = XCreateFontSet(display,
1863 resources.medium_fontset,
1867 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1868 if((smallfontset = XCreateFontSet(display,
1869 resources.small_fontset,
1873 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1875 if(largefontset && mediumfontset && smallfontset)
1877 curr_fontset = mediumfontset;
1878 get_resources()->use_fontset = 1;
1883 get_resources()->use_fontset = 0;
1892 int BC_WindowBase::get_color(int64_t color)
1894 // return pixel of color
1895 // use this only for drawing subwindows not for bitmaps
1896 int i, test, difference, result;
1903 return get_color_rgb8(color);
1907 // test last color looked up
1908 if(current_color_value == color) return current_color_pixel;
1911 current_color_value = color;
1912 for(i = 0; i < total_colors; i++)
1914 if(color_table[i][0] == color)
1916 current_color_pixel = color_table[i][1];
1917 return current_color_pixel;
1921 // find nearest match
1922 difference = 0xFFFFFF;
1924 for(i = 0, result = 0; i < total_colors; i++)
1926 test = abs((int)(color_table[i][0] - color));
1928 if(test < difference)
1930 current_color_pixel = color_table[i][1];
1935 return current_color_pixel;
1940 return get_color_rgb16(color);
1944 return get_color_bgr16(color);
1949 if(client_byte_order == server_byte_order)
1952 get_color_bgr24(color);
1962 int BC_WindowBase::get_color_rgb8(int color)
1966 pixel = (color & 0xc00000) >> 16;
1967 pixel += (color & 0xe000) >> 10;
1968 pixel += (color & 0xe0) >> 5;
1972 int64_t BC_WindowBase::get_color_rgb16(int color)
1975 result = (color & 0xf80000) >> 8;
1976 result += (color & 0xfc00) >> 5;
1977 result += (color & 0xf8) >> 3;
1982 int64_t BC_WindowBase::get_color_bgr16(int color)
1985 result = (color & 0xf80000) >> 19;
1986 result += (color & 0xfc00) >> 5;
1987 result += (color & 0xf8) << 8;
1992 int64_t BC_WindowBase::get_color_bgr24(int color)
1995 result = (color & 0xff) << 16;
1996 result += (color & 0xff00);
1997 result += (color & 0xff0000) >> 16;
2001 void BC_WindowBase::start_video()
2003 cursor_timer->update();
2005 // set_color(BLACK);
2006 // draw_box(0, 0, get_w(), get_h());
2010 void BC_WindowBase::stop_video()
2018 int64_t BC_WindowBase::get_color()
2020 return top_level->current_color;
2023 void BC_WindowBase::set_color(int64_t color)
2025 top_level->current_color = color;
2026 XSetForeground(top_level->display,
2028 top_level->get_color(color));
2031 void BC_WindowBase::set_opaque()
2033 XSetFunction(top_level->display, top_level->gc, GXcopy);
2036 void BC_WindowBase::set_inverse()
2038 XSetFunction(top_level->display, top_level->gc, GXxor);
2041 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2045 case ARROW_CURSOR: return top_level->arrow_cursor; break;
2046 case CROSS_CURSOR: return top_level->cross_cursor;
2047 case IBEAM_CURSOR: return top_level->ibeam_cursor; break;
2048 case VSEPARATE_CURSOR: return top_level->vseparate_cursor; break;
2049 case HSEPARATE_CURSOR: return top_level->hseparate_cursor; break;
2050 case MOVE_CURSOR: return top_level->move_cursor; break;
2051 case LEFT_CURSOR: return top_level->left_cursor; break;
2052 case RIGHT_CURSOR: return top_level->right_cursor; break;
2053 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor; break;
2054 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor; break;
2055 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor; break;
2056 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor; break;
2057 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor; break;
2058 case HOURGLASS_CURSOR: return top_level->hourglass_cursor; break;
2059 case TRANSPARENT_CURSOR: return top_level->transparent_cursor; break;
2064 void BC_WindowBase::set_cursor(int cursor, int override)
2066 // don't change cursor if overridden
2067 if((!top_level->is_hourglass && !is_transparent) ||
2070 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2074 if(!override) current_cursor = cursor;
2077 void BC_WindowBase::set_x_cursor(int cursor)
2079 temp_cursor = XCreateFontCursor(top_level->display, cursor);
2080 XDefineCursor(top_level->display, win, temp_cursor);
2081 current_cursor = cursor;
2085 int BC_WindowBase::get_cursor()
2087 return current_cursor;
2090 void BC_WindowBase::start_hourglass()
2092 top_level->start_hourglass_recursive();
2096 void BC_WindowBase::stop_hourglass()
2098 top_level->stop_hourglass_recursive();
2102 void BC_WindowBase::start_hourglass_recursive()
2104 if(this == top_level)
2112 set_cursor(HOURGLASS_CURSOR, 1);
2113 for(int i = 0; i < subwindows->total; i++)
2115 subwindows->values[i]->start_hourglass_recursive();
2120 void BC_WindowBase::stop_hourglass_recursive()
2122 if(this == top_level)
2124 if(hourglass_total == 0) return;
2125 top_level->hourglass_total--;
2128 if(!top_level->hourglass_total)
2130 top_level->is_hourglass = 0;
2132 // Cause set_cursor to perform change
2134 set_cursor(current_cursor, 1);
2136 for(int i = 0; i < subwindows->total; i++)
2138 subwindows->values[i]->stop_hourglass_recursive();
2148 XFontStruct* BC_WindowBase::get_font_struct(int font)
2150 // Clear out unrelated flags
2151 if(font & BOLDFACE) font ^= BOLDFACE;
2155 case MEDIUMFONT: return top_level->mediumfont; break;
2156 case SMALLFONT: return top_level->smallfont; break;
2157 case LARGEFONT: return top_level->largefont; break;
2162 XFontSet BC_WindowBase::get_fontset(int font)
2166 if(get_resources()->use_fontset)
2170 case SMALLFONT: fs = top_level->smallfontset; break;
2171 case LARGEFONT: fs = top_level->largefontset; break;
2172 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2180 XftFont* BC_WindowBase::get_xft_struct(int font)
2182 // Clear out unrelated flags
2183 if(font & BOLDFACE) font ^= BOLDFACE;
2187 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft; break;
2188 case SMALLFONT: return (XftFont*)top_level->smallfont_xft; break;
2189 case LARGEFONT: return (XftFont*)top_level->largefont_xft; break;
2206 void BC_WindowBase::set_font(int font)
2208 top_level->current_font = font;
2212 if(get_resources()->use_xft)
2218 if(get_resources()->use_fontset)
2223 if(get_font_struct(font))
2225 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2231 void BC_WindowBase::set_fontset(int font)
2235 if(get_resources()->use_fontset)
2239 case SMALLFONT: fs = top_level->smallfontset; break;
2240 case LARGEFONT: fs = top_level->largefontset; break;
2241 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2249 XFontSet BC_WindowBase::get_curr_fontset(void)
2251 if(get_resources()->use_fontset)
2252 return curr_fontset;
2256 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2259 if(get_resources()->use_xft && get_xft_struct(font))
2262 XftTextExtents8(top_level->display,
2263 get_xft_struct(font),
2267 return extents.xOff;
2271 if(get_resources()->use_fontset && top_level->get_fontset(font))
2272 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2274 if(get_font_struct(font))
2275 return XTextWidth(get_font_struct(font), text, length);
2281 case MEDIUM_7SEGMENT:
2282 return get_resources()->medium_7segment[0]->get_w() * length;
2292 int BC_WindowBase::get_text_width(int font, char *text, int length)
2294 int i, j, w = 0, line_w = 0;
2295 if(length < 0) length = strlen(text);
2297 for(i = 0, j = 0; i <= length; i++)
2302 line_w = get_single_text_width(font, &text[j], i - j);
2308 line_w = get_single_text_width(font, &text[j], length - j);
2310 if(line_w > w) w = line_w;
2313 if(i > length && w == 0)
2315 w = get_single_text_width(font, text, length);
2321 int BC_WindowBase::get_text_ascent(int font)
2324 if(get_resources()->use_xft && get_xft_struct(font))
2327 XftTextExtents8(top_level->display,
2328 get_xft_struct(font),
2332 return extents.y + 2;
2336 if(get_resources()->use_fontset && top_level->get_fontset(font))
2338 XFontSetExtents *extents;
2340 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2341 return -extents->max_logical_extent.y;
2344 if(get_font_struct(font))
2345 return top_level->get_font_struct(font)->ascent;
2349 case MEDIUM_7SEGMENT:
2350 return get_resources()->medium_7segment[0]->get_h();
2358 int BC_WindowBase::get_text_descent(int font)
2361 if(get_resources()->use_xft && get_xft_struct(font))
2364 XftTextExtents8(top_level->display,
2365 get_xft_struct(font),
2369 return extents.height - extents.y;
2373 if(get_resources()->use_fontset && top_level->get_fontset(font))
2375 XFontSetExtents *extents;
2377 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2378 return (extents->max_logical_extent.height
2379 + extents->max_logical_extent.y);
2382 if(get_font_struct(font))
2383 return top_level->get_font_struct(font)->descent;
2392 int BC_WindowBase::get_text_height(int font, char *text)
2394 if(!text) return get_text_ascent(font) + get_text_descent(font);
2396 // Add height of lines
2397 int h = 0, i, length = strlen(text);
2398 for(i = 0; i <= length; i++)
2406 return h * (get_text_ascent(font) + get_text_descent(font));
2409 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2411 if(color_model < 0) color_model = top_level->get_color_model();
2412 return new BC_Bitmap(top_level, w, h, color_model);
2415 int BC_WindowBase::accel_available(int color_model, int lock_it)
2417 if(window_type != MAIN_WINDOW)
2418 return top_level->accel_available(color_model, lock_it);
2422 if(lock_it) lock_window("BC_WindowBase::accel_available");
2426 result = grab_port_id(this, color_model);
2429 xvideo_port_id = result;
2441 //printf("BC_WindowBase::accel_available 1\n");
2442 result = grab_port_id(this, color_model);
2443 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2446 xvideo_port_id = result;
2451 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2459 if(lock_it) unlock_window();
2460 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2465 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2467 int numFormats, i, j, k;
2468 unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2470 XvAdaptorInfo *info;
2471 XvImageFormatValues *formats;
2474 if(!get_resources()->use_xvideo) return -1;
2476 // Translate from color_model to X color model
2477 x_color_model = cmodel_bc_to_x(color_model);
2479 // Only local server is fast enough.
2480 if(!resources.use_shm) return -1;
2482 // XV extension is available
2483 if(Success != XvQueryExtension(window->display,
2493 // XV adaptors are available
2494 XvQueryAdaptors(window->display,
2495 DefaultRootWindow(window->display),
2504 // Get adaptor with desired color model
2505 for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2507 /* adaptor supports XvImages */
2508 if(info[i].type & XvImageMask)
2510 formats = XvListImageFormats(window->display,
2513 // for(j = 0; j < numFormats; j++)
2514 // printf("%08x\n", formats[j].id);
2516 for(j = 0; j < numFormats && xvideo_port_id < 0; j++)
2518 /* this adaptor supports the desired format */
2519 if(formats[j].id == x_color_model)
2521 /* Try to grab a port */
2522 for(k = 0; k < info[i].num_ports; k++)
2525 if(Success == XvGrabPort(top_level->display,
2526 info[i].base_id + k,
2529 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2530 xvideo_port_id = info[i].base_id + k;
2536 if(formats) XFree(formats);
2540 XvFreeAdaptorInfo(info);
2542 return xvideo_port_id;
2546 int BC_WindowBase::show_window(int flush)
2548 XMapWindow(top_level->display, win);
2549 if(flush) XFlush(top_level->display);
2550 // XSync(top_level->display, 0);
2555 int BC_WindowBase::hide_window(int flush)
2557 XUnmapWindow(top_level->display, win);
2558 if(flush) XFlush(top_level->display);
2563 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2565 subwindows->append((BC_SubWindow*)menu_bar);
2567 menu_bar->parent_window = this;
2568 menu_bar->top_level = this->top_level;
2569 menu_bar->initialize();
2573 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2575 subwindows->append(subwindow);
2577 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2579 // parent window must be set before the subwindow initialization
2580 subwindow->parent_window = this;
2581 subwindow->top_level = this->top_level;
2583 // Execute derived initialization
2584 subwindow->initialize();
2589 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2591 return add_subwindow(subwindow);
2594 BC_WidgetGrid* BC_WindowBase::add_widgetgrid(BC_WidgetGrid *widgetgrid)
2596 widgetgrids->append(widgetgrid);
2601 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2604 XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
2607 XClearArea(top_level->display, win, x, y, w, h, 0);
2611 XClearWindow(top_level->display, win);
2619 int BC_WindowBase::flash(int flush)
2621 flash(-1, -1, -1, -1, flush);
2624 void BC_WindowBase::flush()
2626 XFlush(top_level->display);
2629 void BC_WindowBase::sync_display()
2631 XSync(top_level->display, False);
2634 int BC_WindowBase::get_window_lock()
2636 return top_level->window_lock;
2639 int BC_WindowBase::lock_window(char *location)
2641 if(top_level && top_level != this)
2643 top_level->lock_window(location);
2648 SET_LOCK(this, title, location);
2649 XLockDisplay(top_level->display);
2651 top_level->window_lock = 1;
2655 printf("BC_WindowBase::lock_window top_level NULL\n");
2660 int BC_WindowBase::unlock_window()
2662 if(top_level && top_level != this)
2664 top_level->unlock_window();
2670 top_level->window_lock = 0;
2671 XUnlockDisplay(top_level->display);
2675 printf("BC_WindowBase::unlock_window top_level NULL\n");
2680 void BC_WindowBase::set_done(int return_value)
2682 if(window_type != MAIN_WINDOW)
2683 top_level->set_done(return_value);
2687 XEvent *event = new XEvent;
2688 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2690 event->type = ClientMessage;
2691 ptr->message_type = SetDoneXAtom;
2693 this->return_value = return_value;
2695 // May lock up here because XSendEvent doesn't work too well
2696 // asynchronous with XNextEvent.
2697 // This causes BC_WindowEvents to forward a copy of the event to run_window where
2699 event_thread->done = 1;
2710 int BC_WindowBase::get_w()
2715 int BC_WindowBase::get_h()
2720 int BC_WindowBase::get_x()
2725 int BC_WindowBase::get_y()
2730 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2732 if(lock_display) lock_window("BC_WindowBase::get_root_w");
2733 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2734 int result = WidthOfScreen(screen_ptr);
2735 // Wider than 16:9, narrower than dual head
2736 if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2738 if(lock_display) unlock_window();
2742 int BC_WindowBase::get_root_h(int lock_display)
2744 if(lock_display) lock_window("BC_WindowBase::get_root_h");
2745 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2746 int result = HeightOfScreen(screen_ptr);
2747 if(lock_display) unlock_window();
2751 // Bottom right corner
2752 int BC_WindowBase::get_x2()
2757 int BC_WindowBase::get_y2()
2762 int BC_WindowBase::get_video_on()
2767 int BC_WindowBase::get_hidden()
2769 return top_level->hidden;
2772 int BC_WindowBase::cursor_inside()
2774 return (top_level->cursor_x >= 0 &&
2775 top_level->cursor_y >= 0 &&
2776 top_level->cursor_x < w &&
2777 top_level->cursor_y < h);
2780 BC_WindowBase* BC_WindowBase::get_top_level()
2785 BC_WindowBase* BC_WindowBase::get_parent()
2787 return parent_window;
2790 int BC_WindowBase::get_color_model()
2792 return top_level->color_model;
2795 BC_Resources* BC_WindowBase::get_resources()
2797 return &BC_WindowBase::resources;
2800 BC_Synchronous* BC_WindowBase::get_synchronous()
2802 return BC_WindowBase::resources.get_synchronous();
2805 int BC_WindowBase::get_bg_color()
2810 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2815 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2817 top_level->active_subwindow = subwindow;
2820 int BC_WindowBase::activate()
2825 int BC_WindowBase::deactivate()
2827 if(window_type == MAIN_WINDOW)
2829 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2830 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2831 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2833 top_level->active_menubar = 0;
2834 top_level->active_popup_menu = 0;
2835 top_level->active_subwindow = 0;
2840 int BC_WindowBase::cycle_textboxes(int amount)
2843 BC_WindowBase *new_textbox = 0;
2847 BC_WindowBase *first_textbox = 0;
2848 find_next_textbox(&first_textbox, &new_textbox, result);
2849 if(!new_textbox) new_textbox = first_textbox;
2855 BC_WindowBase *last_textbox = 0;
2856 find_prev_textbox(&last_textbox, &new_textbox, result);
2857 if(!new_textbox) new_textbox = last_textbox;
2861 if(new_textbox != active_subwindow)
2864 new_textbox->activate();
2870 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2872 // Search subwindows for textbox
2873 for(int i = 0; i < subwindows->total && result < 2; i++)
2875 BC_WindowBase *test_subwindow = subwindows->values[i];
2876 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2883 if(!*first_textbox) *first_textbox = this;
2887 if(top_level->active_subwindow == this)
2893 *next_textbox = this;
2900 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2906 if(!*last_textbox) *last_textbox = this;
2910 if(top_level->active_subwindow == this)
2916 *prev_textbox = this;
2921 // Search subwindows for textbox
2922 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2924 BC_WindowBase *test_subwindow = subwindows->values[i];
2925 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2930 BC_Clipboard* BC_WindowBase::get_clipboard()
2932 return top_level->clipboard;
2935 int BC_WindowBase::get_relative_cursor_x()
2937 int abs_x, abs_y, x, y, win_x, win_y;
2938 unsigned int temp_mask;
2941 XQueryPointer(top_level->display,
2951 XTranslateCoordinates(top_level->display,
2963 int BC_WindowBase::get_relative_cursor_y()
2965 int abs_x, abs_y, x, y, win_x, win_y;
2966 unsigned int temp_mask;
2969 XQueryPointer(top_level->display,
2979 XTranslateCoordinates(top_level->display,
2991 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2993 int abs_x, abs_y, win_x, win_y;
2994 unsigned int temp_mask;
2997 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2998 XQueryPointer(top_level->display,
3007 if(lock_window) this->unlock_window();
3011 int BC_WindowBase::get_abs_cursor_y(int lock_window)
3013 int abs_x, abs_y, win_x, win_y;
3014 unsigned int temp_mask;
3017 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
3018 XQueryPointer(top_level->display,
3027 if(lock_window) this->unlock_window();
3031 int BC_WindowBase::match_window(Window win)
3033 if (this->win == win) return 1;
3035 for(int i = 0; i < subwindows->total; i++)
3037 result = subwindows->values[i]->match_window(win);
3038 if (result) return result;
3044 int BC_WindowBase::get_cursor_over_window()
3046 if(top_level != this) return top_level->get_cursor_over_window();
3048 int abs_x, abs_y, win_x, win_y;
3049 unsigned int temp_mask;
3050 Window temp_win1, temp_win2;
3052 if (!XQueryPointer(display,
3063 int result = match_window(temp_win2) ;
3067 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
3072 translate_coordinates(top_level->event_win,
3074 top_level->cursor_x,
3075 top_level->cursor_y,
3081 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
3086 translate_coordinates(top_level->event_win,
3088 top_level->cursor_x,
3089 top_level->cursor_y,
3095 int BC_WindowBase::get_drag_x()
3097 return top_level->drag_x;
3100 int BC_WindowBase::get_drag_y()
3102 return top_level->drag_y;
3105 int BC_WindowBase::get_cursor_x()
3107 return top_level->cursor_x;
3110 int BC_WindowBase::get_cursor_y()
3112 return top_level->cursor_y;
3115 int BC_WindowBase::is_event_win()
3117 return this->win == top_level->event_win;
3120 void BC_WindowBase::set_dragging(int value)
3122 is_dragging = value;
3125 int BC_WindowBase::get_dragging()
3130 int BC_WindowBase::get_buttonpress()
3132 return top_level->button_number;
3135 int BC_WindowBase::get_button_down()
3137 return top_level->button_down;
3140 int BC_WindowBase::alt_down()
3142 return top_level->alt_mask;
3145 int BC_WindowBase::shift_down()
3147 return top_level->shift_mask;
3150 int BC_WindowBase::ctrl_down()
3152 return top_level->ctrl_mask;
3156 int BC_WindowBase::get_keypress()
3158 return top_level->key_pressed;
3161 int BC_WindowBase::get_double_click()
3163 return top_level->double_click;
3166 int BC_WindowBase::get_bgcolor()
3171 int BC_WindowBase::resize_window(int w, int h)
3173 if(window_type == MAIN_WINDOW && !allow_resize)
3175 XSizeHints size_hints;
3176 size_hints.flags = PSize | PMinSize | PMaxSize;
3177 size_hints.width = w;
3178 size_hints.height = h;
3179 size_hints.min_width = w;
3180 size_hints.max_width = w;
3181 size_hints.min_height = h;
3182 size_hints.max_height = h;
3183 XSetNormalHints(top_level->display, win, &size_hints);
3185 XResizeWindow(top_level->display, win, w, h);
3190 pixmap = new BC_Pixmap(this, w, h);
3192 // Propagate to menubar
3193 for(int i = 0; i < subwindows->total; i++)
3195 subwindows->values[i]->dispatch_resize_event(w, h);
3198 draw_background(0, 0, w, h);
3199 if(top_level == this && get_resources()->recursive_resizing)
3200 resize_history.append(new BC_ResizeCall(w, h));
3204 // The only way for resize events to be propagated is by updating the internal w and h
3205 int BC_WindowBase::resize_event(int w, int h)
3207 if(window_type == MAIN_WINDOW)
3215 int BC_WindowBase::reposition_widget(int x, int y, int w, int h)
3217 return(reposition_window(x, y, w, h));
3220 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3224 // Some tools set their own dimensions before calling this, causing the
3225 // resize check to skip.
3229 if(w > 0 && w != this->w)
3235 if(h > 0 && h != this->h)
3241 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3244 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3246 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3248 if(translation_count && window_type == MAIN_WINDOW)
3250 // KDE shifts window right and down.
3251 // FVWM leaves window alone and adds border around it.
3252 XMoveResizeWindow(top_level->display,
3254 x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x,
3255 y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y,
3261 XMoveResizeWindow(top_level->display,
3272 pixmap = new BC_Pixmap(this, this->w, this->h);
3273 // Propagate to menubar
3274 for(int i = 0; i < subwindows->total; i++)
3276 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3279 // draw_background(0, 0, w, h);
3285 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3287 get_resources()->tooltips_enabled = tooltips_enabled;
3291 int BC_WindowBase::raise_window(int do_flush)
3293 XRaiseWindow(top_level->display, win);
3294 if(do_flush) XFlush(top_level->display);
3298 void BC_WindowBase::set_background(VFrame *bitmap)
3300 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3302 bg_pixmap = new BC_Pixmap(this,
3305 shared_bg_pixmap = 0;
3306 draw_background(0, 0, w, h);
3309 void BC_WindowBase::set_title(char *text)
3311 XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0);
3312 strcpy(this->title, _(text));
3316 char* BC_WindowBase::get_title()
3321 int BC_WindowBase::get_toggle_value()
3323 return toggle_value;
3326 int BC_WindowBase::get_toggle_drag()
3331 int BC_WindowBase::set_icon(VFrame *data)
3333 if(icon_pixmap) delete icon_pixmap;
3334 icon_pixmap = new BC_Pixmap(top_level,
3339 icon_window = new BC_Popup(this,
3342 icon_pixmap->get_w(),
3343 icon_pixmap->get_h(),
3345 1, // All windows are hidden initially
3349 wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3350 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3351 wm_hints.icon_mask = icon_pixmap->get_alpha();
3352 wm_hints.icon_window = icon_window->win;
3353 wm_hints.window_group = XGroupLeader;
3355 // for(int i = 0; i < 1000; i++)
3356 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3359 XSetWMHints(top_level->display, top_level->win, &wm_hints);
3360 XSync(top_level->display, 0);
3364 int BC_WindowBase::set_w(int w)
3370 int BC_WindowBase::set_h(int h)
3376 int BC_WindowBase::load_defaults(BC_Hash *defaults)
3378 BC_Resources *resources = get_resources();
3379 char string[BCTEXTLEN];
3380 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3382 sprintf(string, "FILEBOX_HISTORY%d", i);
3383 resources->filebox_history[i][0] = 0;
3384 defaults->get(string, resources->filebox_history[i]);
3386 resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3387 resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3388 resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3389 defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3393 int BC_WindowBase::save_defaults(BC_Hash *defaults)
3395 BC_Resources *resources = get_resources();
3396 char string[BCTEXTLEN];
3397 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3399 sprintf(string, "FILEBOX_HISTORY%d", i);
3400 defaults->update(string, resources->filebox_history[i]);
3402 defaults->update("FILEBOX_MODE", resources->filebox_mode);
3403 defaults->update("FILEBOX_W", resources->filebox_w);
3404 defaults->update("FILEBOX_H", resources->filebox_h);
3405 defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3411 // For some reason XTranslateCoordinates can take a long time to return.
3412 // We work around this by only calling it when the event windows are different.
3413 void BC_WindowBase::translate_coordinates(Window src_w,
3425 *dest_x_return = src_x;
3426 *dest_y_return = src_y;
3430 XTranslateCoordinates(top_level->display,
3438 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3448 #ifdef HAVE_LIBXXF86VM
3449 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3453 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3455 XF86VidModeModeInfo **vm_modelines;
3456 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3457 for (i = 0; i < vm_count; i++) {
3458 if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3461 display = top_level->display;
3462 if (vm_modelines[*vm]->hdisplay == *width)
3466 *width = vm_modelines[*vm]->hdisplay;
3467 *height = vm_modelines[*vm]->vdisplay;
3472 void BC_WindowBase::scale_vm(int vm)
3474 int foo,bar,dotclock;
3475 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3478 XF86VidModeModeInfo **vm_modelines;
3479 XF86VidModeModeLine vml;
3480 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3481 XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3482 orig_modeline.dotclock = dotclock;
3483 orig_modeline.hdisplay = vml.hdisplay;
3484 orig_modeline.hsyncstart = vml.hsyncstart;
3485 orig_modeline.hsyncend = vml.hsyncend;
3486 orig_modeline.htotal = vml.htotal;
3487 orig_modeline.vdisplay = vml.vdisplay;
3488 orig_modeline.vsyncstart = vml.vsyncstart;
3489 orig_modeline.vsyncend = vml.vsyncend;
3490 orig_modeline.vtotal = vml.vtotal;
3491 orig_modeline.flags = vml.flags;
3492 orig_modeline.privsize = vml.privsize;
3493 // orig_modeline.private = vml.private;
3494 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3495 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3496 XFlush(top_level->display);
3500 void BC_WindowBase::restore_vm()
3502 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3503 XFlush(top_level->display);
3527 int BC_WindowBase::get_event_count()
3529 event_lock->lock("BC_WindowBase::get_event_count");
3530 int result = common_events.total;
3531 event_lock->unlock();
3535 XEvent* BC_WindowBase::get_event()
3538 while(!done && !result)
3540 event_condition->lock("BC_WindowBase::get_event");
3541 event_lock->lock("BC_WindowBase::get_event");
3543 if(common_events.total && !done)
3545 result = common_events.values[0];
3546 common_events.remove_number(0);
3549 event_lock->unlock();
3554 void BC_WindowBase::put_event(XEvent *event)
3556 event_lock->lock("BC_WindowBase::put_event");
3557 common_events.append(event);
3558 event_lock->unlock();
3559 event_condition->unlock();
3562 int BC_WindowBase::get_id()