2 #include "bcclipboard.h"
3 #include "bcdisplayinfo.h"
7 #include "bcpopupmenu.h"
8 #include "bcrepeater.h"
9 #include "bcresources.h"
10 #include "bcsignals.h"
11 #include "bcsubwindow.h"
12 #include "bcwindowbase.h"
13 #include "bcwindowevents.h"
14 #include "colormodels.h"
16 #include "condition.h"
31 #include <X11/extensions/Xvlib.h>
32 #include <X11/extensions/shape.h>
35 BC_ResizeCall::BC_ResizeCall(int w, int h)
50 Mutex BC_WindowBase::opengl_lock;
52 BC_Resources BC_WindowBase::resources;
54 BC_WindowBase::BC_WindowBase()
56 //printf("BC_WindowBase::BC_WindowBase 1\n");
57 BC_WindowBase::initialize();
60 BC_WindowBase::~BC_WindowBase()
63 #ifdef HAVE_LIBXXF86VM
64 if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
71 if(window_type != MAIN_WINDOW)
73 if(top_level->active_menubar == this) top_level->active_menubar = 0;
74 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
75 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
76 parent_window->subwindows->remove(this);
81 for(int i = 0; i < subwindows->total; i++)
83 delete subwindows->values[i];
88 XFreePixmap(top_level->display, pixmap);
89 XDestroyWindow(top_level->display, win);
91 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
92 if(icon_pixmap) delete icon_pixmap;
93 if(temp_bitmap) delete temp_bitmap;
96 if(window_type == MAIN_WINDOW)
102 XftFontClose (display, (XftFont*)largefont_xft);
104 XftFontClose (display, (XftFont*)mediumfont_xft);
106 XftFontClose (display, (XftFont*)smallfont_xft);
109 // Can't close display if another thread is waiting for events
110 XCloseDisplay(display);
111 // XCloseDisplay(event_display);
112 clipboard->stop_clipboard();
120 resize_history.remove_all_objects();
121 common_events.remove_all_objects();
123 delete event_condition;
124 UNSET_ALL_LOCKS(this)
127 int BC_WindowBase::initialize()
142 translation_events = 0;
143 ctrl_mask = shift_mask = alt_mask = 0;
144 cursor_x = cursor_y = button_number = 0;
147 button_time1 = button_time2 = 0;
152 active_popup_menu = 0;
153 active_subwindow = 0;
156 persistant_tooltip = 0;
157 // next_repeat_id = 0;
160 current_font = MEDIUMFONT;
161 current_cursor = ARROW_CURSOR;
162 current_color = BLACK;
164 shared_bg_pixmap = 0;
166 window_type = MAIN_WINDOW;
167 translation_count = 0;
168 x_correction = y_correction = 0;
175 #ifdef HAVE_LIBXXF86VM
182 // Need these right away since put_event is called before run_window sometimes.
183 event_lock = new Mutex("BC_WindowBase::event_lock");
184 event_condition = new Condition(0, "BC_WindowBase::event_condition");
190 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
193 ButtonReleaseMask | \
194 PointerMotionMask | \
198 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
212 BC_Pixmap *bg_pixmap)
214 XSetWindowAttributes attr;
216 XSizeHints size_hints;
219 #ifdef HAVE_LIBXXF86VM
223 if(parent_window) top_level = parent_window->top_level;
225 #ifdef HAVE_LIBXXF86VM
226 if(window_type == VIDMODE_SCALED_WINDOW)
227 closest_vm(&vm,&w,&h);
234 this->bg_color = bg_color;
235 this->window_type = window_type;
237 this->private_color = private_color;
238 this->parent_window = parent_window;
239 this->bg_pixmap = bg_pixmap;
240 this->allow_resize = allow_resize;
241 strcpy(this->title, _(title));
242 if(bg_pixmap) shared_bg_pixmap = 1;
244 if(parent_window) top_level = parent_window->top_level;
246 subwindows = new BC_SubWindowList;
249 if(window_type == MAIN_WINDOW)
252 parent_window = this;
254 // This function must be the first Xlib
255 // function a multi-threaded program calls
259 // get the display connection
260 display = init_display(display_name);
261 // event_display = init_display(display_name);
263 // Fudge window placement
264 root_w = get_root_w(1, 0);
265 root_h = get_root_h(0);
266 if(this->x + this->w > root_w) this->x = root_w - this->w;
267 if(this->y + this->h > root_h) this->y = root_h - this->h;
268 if(this->x < 0) this->x = 0;
269 if(this->y < 0) this->y = 0;
270 screen = DefaultScreen(display);
272 rootwin = RootWindow(display, screen);
273 vis = DefaultVisual(display, screen);
274 default_depth = DefaultDepth(display, screen);
275 client_byte_order = (*(u_int32_t*)"a ") & 0x00000001;
276 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
280 // This must be done before fonts to know if antialiasing is available.
283 if(resources.use_shm < 0) resources.initialize_display(this);
284 x_correction = get_resources()->get_left_border();
285 y_correction = get_resources()->get_top_border();
287 if(this->bg_color == -1)
288 this->bg_color = resources.get_bg_color();
299 attr.event_mask = DEFAULT_EVENT_MASKS |
300 StructureNotifyMask |
303 attr.background_pixel = get_color(this->bg_color);
304 attr.colormap = cmap;
305 attr.cursor = get_cursor_struct(ARROW_CURSOR);
307 win = XCreateWindow(display,
314 top_level->default_depth,
320 XGetNormalHints(display, win, &size_hints);
322 size_hints.flags = PSize | PMinSize | PMaxSize;
323 size_hints.width = this->w;
324 size_hints.height = this->h;
325 size_hints.min_width = allow_resize ? minw : this->w;
326 size_hints.max_width = allow_resize ? 32767 : this->w;
327 size_hints.min_height = allow_resize ? minh : this->h;
328 size_hints.max_height = allow_resize ? 32767 : this->h;
329 if(x > -BC_INFINITY && x < BC_INFINITY)
331 size_hints.flags |= PPosition;
332 size_hints.x = this->x;
333 size_hints.y = this->y;
336 XSetStandardProperties(display,
346 clipboard = new BC_Clipboard(display_name);
347 clipboard->start_clipboard();
350 #ifdef HAVE_LIBXXF86VM
351 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
358 #ifdef HAVE_LIBXXF86VM
359 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
361 if(window_type == POPUP_WINDOW)
371 attr.event_mask = DEFAULT_EVENT_MASKS;
373 if(this->bg_color == -1)
374 this->bg_color = resources.get_bg_color();
375 attr.background_pixel = top_level->get_color(bg_color);
376 attr.colormap = top_level->cmap;
377 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
378 attr.override_redirect = True;
379 attr.save_under = True;
381 win = XCreateWindow(top_level->display,
388 top_level->default_depth,
395 if(window_type == SUB_WINDOW)
397 mask = CWBackPixel | CWEventMask;
398 attr.event_mask = DEFAULT_EVENT_MASKS;
399 attr.background_pixel = top_level->get_color(this->bg_color);
400 win = XCreateWindow(top_level->display,
407 top_level->default_depth,
413 XMapWindow(top_level->display, win);
416 // Create pixmap for all windows
417 pixmap = XCreatePixmap(top_level->display,
421 top_level->default_depth);
423 // Create truetype rendering surface
425 if(get_resources()->use_xft)
427 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n",
428 // top_level->display,
432 xft_drawable = XftDrawCreate(top_level->display,
436 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n",
438 // top_level->display,
445 // Set up options for main window
446 if(window_type == MAIN_WINDOW)
448 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
450 this->bg_pixmap = new BC_Pixmap(this,
451 get_resources()->bg_image,
455 if(!hidden) show_window();
462 draw_background(0, 0, this->w, this->h);
465 // Set up options for popup window
466 #ifdef HAVE_LIBXXF86VM
467 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
469 if(window_type == POPUP_WINDOW)
473 if(!hidden) show_window();
478 Display* BC_WindowBase::init_display(char *display_name)
482 if(display_name && display_name[0] == 0) display_name = NULL;
483 if((display = XOpenDisplay(display_name)) == NULL)
485 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
487 if(getenv("DISPLAY") == NULL)
489 printf("'DISPLAY' environment variable not set.\n");
493 // Try again with default display.
495 if((display = XOpenDisplay(0)) == NULL)
497 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
505 int BC_WindowBase::run_window()
511 // Events may have been sent before run_window so can't initialize them here.
514 if(window_type == MAIN_WINDOW)
516 // tooltip_id = get_repeat_id();
517 set_repeat(get_resources()->tooltip_delay);
520 // Start X server events
521 event_thread = new BC_WindowEvents(this);
522 event_thread->start();
524 // Start common events
530 unset_all_repeaters();
534 event_condition->reset();
535 common_events.remove_all_objects();
541 int BC_WindowBase::get_key_masks(XEvent *event)
544 ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
546 shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
547 alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
557 int BC_WindowBase::dispatch_event()
564 XClientMessageEvent *ptr;
566 int cancel_resize, cancel_translation;
570 // If an event is waiting get it, otherwise
571 // wait for next event only if there are no compressed events.
572 if(/* XPending(display) */
574 (!motion_events && !resize_events && !translation_events))
576 // XNextEvent(display, event);
578 // Lock out window deletions
579 lock_window("BC_WindowBase::dispatch_event 1");
580 get_key_masks(event);
583 // Handle compressed events
585 lock_window("BC_WindowBase::dispatch_event 2");
587 dispatch_resize_event(last_resize_w, last_resize_h);
590 dispatch_motion_event();
592 if(translation_events)
593 dispatch_translation_event();
599 //printf("1 %s %p %d\n", title, event, event->type);
603 // Clear the resize buffer
604 if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
605 // Clear the motion buffer since this can clear the window
606 if(motion_events) dispatch_motion_event();
608 ptr = (XClientMessageEvent*)event;
611 if(ptr->message_type == ProtoXAtom &&
612 ptr->data.l[0] == DelWinXAtom)
617 if(ptr->message_type == RepeaterXAtom)
619 dispatch_repeat_event(ptr->data.l[0]);
620 // Make sure the repeater still exists.
621 // for(int i = 0; i < repeaters.total; i++)
623 // if(repeaters.values[i]->repeat_id == ptr->data.l[0])
625 // dispatch_repeat_event_master(ptr->data.l[0]);
631 if(ptr->message_type == SetDoneXAtom)
644 dispatch_focus_out();
648 cursor_x = event->xbutton.x;
649 cursor_y = event->xbutton.y;
650 button_number = event->xbutton.button;
651 event_win = event->xany.window;
653 button_pressed = event->xbutton.button;
654 button_time1 = button_time2;
655 button_time2 = event->xbutton.time;
658 drag_win = event_win;
659 drag_x1 = cursor_x - get_resources()->drag_radius;
660 drag_x2 = cursor_x + get_resources()->drag_radius;
661 drag_y1 = cursor_y - get_resources()->drag_radius;
662 drag_y2 = cursor_y + get_resources()->drag_radius;
664 if(button_time2 - button_time1 < resources.double_click)
666 // Ignore triple clicks
668 button_time2 = button_time1 = 0;
673 dispatch_button_press();
677 button_number = event->xbutton.button;
678 event_win = event->xany.window;
681 dispatch_button_release();
685 event_win = event->xany.window;
686 dispatch_expose_event();
690 // Dispatch previous motion event if this is a subsequent motion from a different window
691 if(motion_events && last_motion_win != event->xany.window)
693 dispatch_motion_event();
696 // Buffer the current motion
698 last_motion_x = event->xmotion.x;
699 last_motion_y = event->xmotion.y;
700 last_motion_win = event->xany.window;
703 case ConfigureNotify:
704 XTranslateCoordinates(top_level->display,
712 last_resize_w = event->xconfigure.width;
713 last_resize_h = event->xconfigure.height;
716 cancel_translation = 0;
718 // Resize history prevents responses to recursive resize requests
719 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
721 if(resize_history.values[i]->w == last_resize_w &&
722 resize_history.values[i]->h == last_resize_h)
724 delete resize_history.values[i];
725 resize_history.remove_number(i);
730 if(last_resize_w == w && last_resize_h == h)
738 if((last_translate_x == x && last_translate_y == y))
739 cancel_translation = 1;
741 if(!cancel_translation)
743 translation_events = 1;
751 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
752 //printf("BC_WindowBase::dispatch_event %08x\n", keys_return[0]);
753 // block out control keys
754 if(keysym > 0xffe0 && keysym < 0xffff) break;
757 // block out extra keys
767 // Translate key codes
768 case XK_Return: key_pressed = RETURN; break;
769 case XK_Up: key_pressed = UP; break;
770 case XK_Down: key_pressed = DOWN; break;
771 case XK_Left: key_pressed = LEFT; break;
772 case XK_Right: key_pressed = RIGHT; break;
773 case XK_Next: key_pressed = PGDN; break;
774 case XK_Prior: key_pressed = PGUP; break;
775 case XK_BackSpace: key_pressed = BACKSPACE; break;
776 case XK_Escape: key_pressed = ESC; break;
779 key_pressed = LEFTTAB;
783 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
784 case XK_underscore: key_pressed = '_'; break;
785 case XK_asciitilde: key_pressed = '~'; break;
786 case XK_Delete: key_pressed = DELETE; break;
787 case XK_Home: key_pressed = HOME; break;
788 case XK_End: key_pressed = END; break;
791 case XK_KP_Enter: key_pressed = KPENTER; break;
792 case XK_KP_Add: key_pressed = KPPLUS; break;
794 case XK_KP_End: key_pressed = KP1; break;
796 case XK_KP_Down: key_pressed = KP2; break;
798 case XK_KP_Page_Down: key_pressed = KP3; break;
800 case XK_KP_Left: key_pressed = KP4; break;
802 case XK_KP_Begin: key_pressed = KP5; break;
804 case XK_KP_Right: key_pressed = KP6; break;
806 case XK_KP_Insert: key_pressed = KPINS; break;
808 case XK_KP_Delete: key_pressed = KPDEL; break;
810 //key_pressed = keys_return[0];
811 key_pressed = keysym & 0xff;
815 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
816 result = dispatch_keypress_event();
817 // Handle some default keypresses
820 if(key_pressed == 'w' ||
829 event_win = event->xany.window;
830 dispatch_cursor_leave();
834 event_win = event->xany.window;
835 cursor_x = event->xcrossing.x;
836 cursor_y = event->xcrossing.y;
837 dispatch_cursor_enter();
840 //printf("100 %s %p %d\n", title, event, event->type);
843 if(event) delete event;
847 int BC_WindowBase::dispatch_expose_event()
850 for(int i = 0; i < subwindows->total && !result; i++)
852 result = subwindows->values[i]->dispatch_expose_event();
856 if(!result) expose_event();
860 int BC_WindowBase::dispatch_resize_event(int w, int h)
862 if(window_type == MAIN_WINDOW)
865 // Can't store w and h here because bcfilebox depends on the old w and h to
866 // reposition widgets.
867 XFreePixmap(top_level->display, pixmap);
868 pixmap = XCreatePixmap(top_level->display,
872 top_level->default_depth);
873 clear_box(0, 0, w, h);
876 // Propagate to subwindows
877 for(int i = 0; i < subwindows->total; i++)
879 subwindows->values[i]->dispatch_resize_event(w, h);
885 if(window_type == MAIN_WINDOW)
893 int BC_WindowBase::dispatch_translation_event()
895 translation_events = 0;
896 if(window_type == MAIN_WINDOW)
900 x = last_translate_x;
901 y = last_translate_y;
902 // Correct for window manager offsets
907 for(int i = 0; i < subwindows->total; i++)
909 subwindows->values[i]->dispatch_translation_event();
916 int BC_WindowBase::dispatch_motion_event()
920 if(top_level == this)
922 event_win = last_motion_win;
926 if(get_button_down() && !active_menubar && !active_popup_menu)
930 cursor_x = last_motion_x;
931 cursor_y = last_motion_y;
932 result = dispatch_drag_motion();
936 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
937 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
942 result = dispatch_drag_start();
945 cursor_x = last_motion_x;
946 cursor_y = last_motion_y;
948 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
949 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
950 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
953 for(int i = 0; i < subwindows->total && !result; i++)
955 result = subwindows->values[i]->dispatch_motion_event();
958 if(!result) result = cursor_motion_event(); // give to user
962 int BC_WindowBase::dispatch_keypress_event()
965 if(top_level == this)
967 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
970 for(int i = 0; i < subwindows->total && !result; i++)
972 result = subwindows->values[i]->dispatch_keypress_event();
975 if(!result) result = keypress_event();
980 int BC_WindowBase::dispatch_focus_in()
982 for(int i = 0; i < subwindows->total; i++)
984 subwindows->values[i]->dispatch_focus_in();
992 int BC_WindowBase::dispatch_focus_out()
994 for(int i = 0; i < subwindows->total; i++)
996 subwindows->values[i]->dispatch_focus_out();
1004 int BC_WindowBase::get_has_focus()
1006 return top_level->has_focus;
1009 int BC_WindowBase::dispatch_button_press()
1012 if(top_level == this)
1014 if(active_menubar) result = active_menubar->dispatch_button_press();
1015 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1016 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1019 for(int i = 0; i < subwindows->total && !result; i++)
1021 result = subwindows->values[i]->dispatch_button_press();
1024 if(!result) result = button_press_event();
1029 int BC_WindowBase::dispatch_button_release()
1032 if(top_level == this)
1034 if(active_menubar) result = active_menubar->dispatch_button_release();
1035 //printf("BC_WindowBase::dispatch_button_release 1 %d\n", result);
1036 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1037 //printf("BC_WindowBase::dispatch_button_release 2 %p %d\n", active_subwindow, result);
1038 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1039 //printf("BC_WindowBase::dispatch_button_release 3 %d\n", result);
1040 if(!result) result = dispatch_drag_stop();
1042 //printf("BC_WindowBase::dispatch_button_release 4 %d\n", result);
1044 for(int i = 0; i < subwindows->total && !result; i++)
1046 result = subwindows->values[i]->dispatch_button_release();
1048 //printf("BC_WindowBase::dispatch_button_release 5 %d\n", result);
1052 result = button_release_event();
1054 //printf("BC_WindowBase::dispatch_button_release 6 %d\n", result);
1059 // int BC_WindowBase::dispatch_repeat_event_master(long duration)
1062 // BC_Repeater *repeater;
1064 // // Unlock the repeater if it still exists.
1065 // for(int i = 0; i < repeaters.total; i++)
1067 // if(repeaters.values[i]->repeat_id == repeat_id)
1069 // repeater = repeaters.values[i];
1070 // if(repeater->interrupted)
1073 // if(interrupt_now)
1076 // repeater->join();
1077 // repeaters.remove(repeater);
1083 // // Propogate to subwindows
1084 // if(active_menubar) result = active_menubar->dispatch_repeat_event(repeat_id);
1085 // if(!result && active_subwindow) result = active_subwindow->dispatch_repeat_event(repeat_id);
1086 // if(!result) result = dispatch_repeat_event(repeat_id);
1087 // repeater->repeat_mutex.unlock();
1089 // i = repeaters.total;
1096 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1098 // all repeat event handlers get called and decide based on activity and duration
1099 // whether to respond
1100 for(int i = 0; i < subwindows->total; i++)
1102 subwindows->values[i]->dispatch_repeat_event(duration);
1104 repeat_event(duration);
1106 // Unlock next signal
1107 if(window_type == MAIN_WINDOW)
1109 for(int i = 0; i < repeaters.total; i++)
1111 if(repeaters.values[i]->delay == duration)
1113 repeaters.values[i]->repeat_lock->unlock();
1121 int BC_WindowBase::dispatch_cursor_leave()
1123 for(int i = 0; i < subwindows->total; i++)
1125 subwindows->values[i]->dispatch_cursor_leave();
1128 cursor_leave_event();
1132 int BC_WindowBase::dispatch_cursor_enter()
1136 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1137 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1138 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1140 for(int i = 0; !result && i < subwindows->total; i++)
1142 result = subwindows->values[i]->dispatch_cursor_enter();
1145 if(!result) result = cursor_enter_event();
1149 int BC_WindowBase::cursor_enter_event()
1154 int BC_WindowBase::cursor_leave_event()
1159 int BC_WindowBase::close_event()
1165 int BC_WindowBase::dispatch_drag_start()
1168 if(active_menubar) result = active_menubar->dispatch_drag_start();
1169 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1170 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1172 for(int i = 0; i < subwindows->total && !result; i++)
1174 result = subwindows->values[i]->dispatch_drag_start();
1177 if(!result) result = is_dragging = drag_start_event();
1181 int BC_WindowBase::dispatch_drag_stop()
1185 for(int i = 0; i < subwindows->total && !result; i++)
1187 result = subwindows->values[i]->dispatch_drag_stop();
1190 if(is_dragging && !result)
1200 int BC_WindowBase::dispatch_drag_motion()
1203 for(int i = 0; i < subwindows->total && !result; i++)
1205 result = subwindows->values[i]->dispatch_drag_motion();
1208 if(is_dragging && !result)
1210 drag_motion_event();
1221 int BC_WindowBase::show_tooltip(int w, int h)
1225 if(!tooltip_on && get_resources()->tooltips_enabled)
1228 top_level->hide_tooltip();
1232 w = get_text_width(MEDIUMFONT, tooltip_text);
1235 h = get_text_height(MEDIUMFONT, tooltip_text);
1237 w += TOOLTIP_MARGIN * 2;
1238 h += TOOLTIP_MARGIN * 2;
1240 XTranslateCoordinates(top_level->display,
1248 tooltip_popup = new BC_Popup(top_level,
1253 get_resources()->tooltip_bg_color);
1256 tooltip_popup->set_font(MEDIUMFONT);
1257 tooltip_popup->flash();
1258 tooltip_popup->flush();
1263 int BC_WindowBase::hide_tooltip()
1266 for(int i = 0; i < subwindows->total; i++)
1268 subwindows->values[i]->hide_tooltip();
1274 delete tooltip_popup;
1280 int BC_WindowBase::set_tooltip(char *text)
1282 strcpy(this->tooltip_text, text);
1283 // Update existing tooltip if it is visible
1287 tooltip_popup->flash();
1292 // signal the event handler to repeat
1293 int BC_WindowBase::set_repeat(int64_t duration)
1297 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1300 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1302 // test repeater database for duplicates
1303 for(int i = 0; i < repeaters.total; i++)
1306 if(repeaters.values[i]->delay == duration)
1308 repeaters.values[i]->start_repeating();
1313 BC_Repeater *repeater = new BC_Repeater(this, duration);
1314 repeater->initialize();
1315 repeaters.append(repeater);
1316 repeater->start_repeating();
1320 int BC_WindowBase::unset_repeat(int64_t duration)
1322 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1324 BC_Repeater *repeater = 0;
1325 for(int i = 0; i < repeaters.total; i++)
1327 if(repeaters.values[i]->delay == duration)
1329 repeaters.values[i]->stop_repeating();
1336 int BC_WindowBase::unset_all_repeaters()
1338 for(int i = 0; i < repeaters.total; i++)
1340 repeaters.values[i]->stop_repeating();
1342 repeaters.remove_all_objects();
1346 // long BC_WindowBase::get_repeat_id()
1348 // return top_level->next_repeat_id++;
1351 int BC_WindowBase::arm_repeat(int64_t duration)
1353 XEvent *event = new XEvent;
1354 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1355 ptr->type = ClientMessage;
1356 ptr->message_type = RepeaterXAtom;
1358 ptr->data.l[0] = duration;
1360 // Couldn't use XSendEvent since it locked up randomly.
1362 // XSendEvent(top_level->event_display,
1371 int BC_WindowBase::get_atoms()
1373 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
1374 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1375 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
1376 if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1377 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1381 void BC_WindowBase::init_cursors()
1383 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1384 cross_cursor = XCreateFontCursor(display, XC_crosshair);
1385 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1386 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1387 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1388 move_cursor = XCreateFontCursor(display, XC_fleur);
1389 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1390 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1391 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1392 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1393 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1394 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1395 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1398 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1404 color_model = BC_RGB8;
1407 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1410 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1413 color_model = server_byte_order ? BC_BGR8888 : BC_RGBA8888;
1419 int BC_WindowBase::init_colors()
1422 current_color_value = current_color_pixel = 0;
1424 // Get the real depth
1427 ximage = XCreateImage(top_level->display,
1429 top_level->default_depth,
1437 bits_per_pixel = ximage->bits_per_pixel;
1438 XDestroyImage(ximage);
1440 color_model = evaluate_color_model(client_byte_order,
1443 // Get the color model
1449 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1450 create_private_colors();
1454 cmap = DefaultColormap(display, screen);
1455 create_shared_colors();
1458 allocate_color_table();
1460 get_resources()->use_xft = 0;
1464 cmap = DefaultColormap(display, screen);
1470 int BC_WindowBase::create_private_colors()
1475 for(int i = 0; i < 255; i++)
1477 color = (i & 0xc0) << 16;
1478 color += (i & 0x38) << 10;
1479 color += (i & 0x7) << 5;
1480 color_table[i][0] = color;
1482 create_shared_colors(); // overwrite the necessary colors on the table
1487 int BC_WindowBase::create_color(int color)
1489 if(total_colors == 256)
1491 // replace the closest match with an exact match
1492 color_table[get_color_rgb8(color)][0] = color;
1496 // add the color to the table
1497 color_table[total_colors][0] = color;
1503 int BC_WindowBase::create_shared_colors()
1505 create_color(BLACK);
1506 create_color(WHITE);
1508 create_color(LTGREY);
1509 create_color(MEGREY);
1510 create_color(MDGREY);
1511 create_color(DKGREY);
1513 create_color(LTCYAN);
1514 create_color(MECYAN);
1515 create_color(MDCYAN);
1516 create_color(DKCYAN);
1518 create_color(LTGREEN);
1519 create_color(GREEN);
1520 create_color(DKGREEN);
1522 create_color(LTPINK);
1526 create_color(LTBLUE);
1528 create_color(DKBLUE);
1530 create_color(LTYELLOW);
1531 create_color(MEYELLOW);
1532 create_color(MDYELLOW);
1533 create_color(DKYELLOW);
1535 create_color(LTPURPLE);
1536 create_color(MEPURPLE);
1537 create_color(MDPURPLE);
1538 create_color(DKPURPLE);
1540 create_color(FGGREY);
1541 create_color(MNBLUE);
1542 create_color(ORANGE);
1543 create_color(FTGREY);
1548 int BC_WindowBase::allocate_color_table()
1550 int red, green, blue, color;
1554 for(int i = 0; i < total_colors; i++)
1556 color = color_table[i][0];
1557 red = (color & 0xFF0000) >> 16;
1558 green = (color & 0x00FF00) >> 8;
1559 blue = color & 0xFF;
1561 col.flags = DoRed | DoGreen | DoBlue;
1562 col.red = red<<8 | red;
1563 col.green = green<<8 | green;
1564 col.blue = blue<<8 | blue;
1566 XAllocColor(display, cmap, &col);
1567 color_table[i][1] = col.pixel;
1570 XInstallColormap(display, cmap);
1574 int BC_WindowBase::init_window_shape()
1576 if(bg_pixmap && bg_pixmap->use_alpha())
1578 XShapeCombineMask(top_level->display,
1583 bg_pixmap->get_alpha(),
1590 int BC_WindowBase::init_gc()
1592 unsigned long gcmask;
1593 gcmask = GCFont | GCGraphicsExposures;
1596 gcvalues.font = mediumfont->fid; // set the font
1597 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
1598 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1602 int BC_WindowBase::init_fonts()
1604 if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL &&
1605 (largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1606 largefont = XLoadQueryFont(display, "fixed");
1608 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL &&
1609 (mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1610 mediumfont = XLoadQueryFont(display, "fixed");
1612 if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL &&
1613 (smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1614 smallfont = XLoadQueryFont(display, "fixed");
1617 if(get_resources()->use_xft)
1621 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
1623 if(!(largefont_xft = XftFontOpenXlfd(display,
1625 resources.large_font_xft)))
1627 largefont_xft = XftFontOpenXlfd(display,
1631 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
1632 if(!(largefont_xft = XftFontOpenXlfd(display,
1634 resources.large_font_xft)))
1636 largefont_xft = XftFontOpenXlfd(display,
1640 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
1643 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1645 resources.medium_font_xft)))
1647 mediumfont_xft = XftFontOpenXlfd(display,
1653 if(!(smallfont_xft = XftFontOpenXlfd(display,
1655 resources.small_font_xft)))
1657 smallfont_xft = XftFontOpenXlfd(display,
1662 //printf("BC_WindowBase::init_fonts 100 %s %p\n",
1663 //resources.medium_font,
1666 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
1667 resources.large_font_xft,
1669 resources.medium_font_xft,
1671 resources.small_font_xft,
1674 // Extension failed to locate fonts
1675 if(!largefontset || !mediumfontset || !smallfontset)
1677 printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1678 resources.large_font_xft,
1680 resources.medium_font_xft,
1682 resources.small_font_xft,
1684 get_resources()->use_xft = 0;
1689 if(get_resources()->use_fontset)
1694 // FIXME: should check the m,d,n values
1695 if((largefontset = XCreateFontSet(display,
1696 resources.large_fontset,
1700 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1701 if((mediumfontset = XCreateFontSet(display,
1702 resources.medium_fontset,
1706 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1707 if((smallfontset = XCreateFontSet(display,
1708 resources.small_fontset,
1712 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1714 if(largefontset && mediumfontset && smallfontset)
1716 curr_fontset = mediumfontset;
1717 get_resources()->use_fontset = 1;
1722 get_resources()->use_fontset = 0;
1729 int BC_WindowBase::get_color(int64_t color)
1731 // return pixel of color
1732 // use this only for drawing subwindows not for bitmaps
1733 int i, test, difference, result;
1740 return get_color_rgb8(color);
1744 // test last color looked up
1745 if(current_color_value == color) return current_color_pixel;
1748 current_color_value = color;
1749 for(i = 0; i < total_colors; i++)
1751 if(color_table[i][0] == color)
1753 current_color_pixel = color_table[i][1];
1754 return current_color_pixel;
1758 // find nearest match
1759 difference = 0xFFFFFF;
1761 for(i = 0, result = 0; i < total_colors; i++)
1763 test = abs((int)(color_table[i][0] - color));
1765 if(test < difference)
1767 current_color_pixel = color_table[i][1];
1772 return current_color_pixel;
1777 return get_color_rgb16(color);
1781 return get_color_bgr16(color);
1786 if(client_byte_order == server_byte_order)
1789 get_color_bgr24(color);
1799 int BC_WindowBase::get_color_rgb8(int color)
1803 pixel = (color & 0xc00000) >> 16;
1804 pixel += (color & 0xe000) >> 10;
1805 pixel += (color & 0xe0) >> 5;
1809 int64_t BC_WindowBase::get_color_rgb16(int color)
1812 result = (color & 0xf80000) >> 8;
1813 result += (color & 0xfc00) >> 5;
1814 result += (color & 0xf8) >> 3;
1819 int64_t BC_WindowBase::get_color_bgr16(int color)
1822 result = (color & 0xf80000) >> 19;
1823 result += (color & 0xfc00) >> 5;
1824 result += (color & 0xf8) << 8;
1829 int64_t BC_WindowBase::get_color_bgr24(int color)
1832 result = (color & 0xff) << 16;
1833 result += (color & 0xff00);
1834 result += (color & 0xff0000) >> 16;
1838 int BC_WindowBase::video_is_on()
1843 void BC_WindowBase::start_video()
1847 draw_box(0, 0, get_w(), get_h());
1851 void BC_WindowBase::stop_video()
1858 int64_t BC_WindowBase::get_color()
1860 return top_level->current_color;
1863 void BC_WindowBase::set_color(int64_t color)
1865 top_level->current_color = color;
1866 XSetForeground(top_level->display,
1868 top_level->get_color(color));
1871 void BC_WindowBase::set_opaque()
1873 XSetFunction(top_level->display, top_level->gc, GXcopy);
1876 void BC_WindowBase::set_inverse()
1878 XSetFunction(top_level->display, top_level->gc, GXxor);
1881 Cursor BC_WindowBase::get_cursor_struct(int cursor)
1885 case ARROW_CURSOR: return top_level->arrow_cursor; break;
1886 case CROSS_CURSOR: return top_level->cross_cursor;
1887 case IBEAM_CURSOR: return top_level->ibeam_cursor; break;
1888 case VSEPARATE_CURSOR: return top_level->vseparate_cursor; break;
1889 case HSEPARATE_CURSOR: return top_level->hseparate_cursor; break;
1890 case MOVE_CURSOR: return top_level->move_cursor; break;
1891 case LEFT_CURSOR: return top_level->left_cursor; break;
1892 case RIGHT_CURSOR: return top_level->right_cursor; break;
1893 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor; break;
1894 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor; break;
1895 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor; break;
1896 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor; break;
1897 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor; break;
1902 void BC_WindowBase::set_cursor(int cursor)
1904 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
1905 current_cursor = cursor;
1909 void BC_WindowBase::set_x_cursor(int cursor)
1911 temp_cursor = XCreateFontCursor(top_level->display, cursor);
1912 XDefineCursor(top_level->display, win, temp_cursor);
1913 current_cursor = cursor;
1917 int BC_WindowBase::get_cursor()
1919 return current_cursor;
1928 XFontStruct* BC_WindowBase::get_font_struct(int font)
1930 // Clear out unrelated flags
1931 if(font & BOLDFACE) font ^= BOLDFACE;
1935 case MEDIUMFONT: return top_level->mediumfont; break;
1936 case SMALLFONT: return top_level->smallfont; break;
1937 case LARGEFONT: return top_level->largefont; break;
1942 XFontSet BC_WindowBase::get_fontset(int font)
1946 if(get_resources()->use_fontset)
1950 case SMALLFONT: fs = top_level->smallfontset; break;
1951 case LARGEFONT: fs = top_level->largefontset; break;
1952 case MEDIUMFONT: fs = top_level->mediumfontset; break;
1960 XftFont* BC_WindowBase::get_xft_struct(int font)
1962 // Clear out unrelated flags
1963 if(font & BOLDFACE) font ^= BOLDFACE;
1967 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft; break;
1968 case SMALLFONT: return (XftFont*)top_level->smallfont_xft; break;
1969 case LARGEFONT: return (XftFont*)top_level->largefont_xft; break;
1986 void BC_WindowBase::set_font(int font)
1988 top_level->current_font = font;
1992 if(get_resources()->use_xft)
1998 if(get_resources()->use_fontset)
2003 if(get_font_struct(font))
2005 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2011 void BC_WindowBase::set_fontset(int font)
2015 if(get_resources()->use_fontset)
2019 case SMALLFONT: fs = top_level->smallfontset; break;
2020 case LARGEFONT: fs = top_level->largefontset; break;
2021 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2029 XFontSet BC_WindowBase::get_curr_fontset(void)
2031 if(get_resources()->use_fontset)
2032 return curr_fontset;
2036 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2039 if(get_resources()->use_xft && get_xft_struct(font))
2042 XftTextExtents8(top_level->display,
2043 get_xft_struct(font),
2047 return extents.xOff;
2051 if(get_resources()->use_fontset && top_level->get_fontset(font))
2052 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2054 if(get_font_struct(font))
2055 return XTextWidth(get_font_struct(font), text, length);
2061 case MEDIUM_7SEGMENT:
2062 return get_resources()->medium_7segment[0]->get_w() * length;
2072 int BC_WindowBase::get_text_width(int font, char *text, int length)
2074 int i, j, w = 0, line_w = 0;
2075 if(length < 0) length = strlen(text);
2077 for(i = 0, j = 0; i <= length; i++)
2082 line_w = get_single_text_width(font, &text[j], i - j);
2088 line_w = get_single_text_width(font, &text[j], length - j);
2090 if(line_w > w) w = line_w;
2093 if(i > length && w == 0)
2095 w = get_single_text_width(font, text, length);
2101 int BC_WindowBase::get_text_ascent(int font)
2104 if(get_resources()->use_xft && get_xft_struct(font))
2107 XftTextExtents8(top_level->display,
2108 get_xft_struct(font),
2116 if(get_resources()->use_fontset && top_level->get_fontset(font))
2118 XFontSetExtents *extents;
2120 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2121 return -extents->max_logical_extent.y;
2124 if(get_font_struct(font))
2125 return top_level->get_font_struct(font)->ascent;
2129 case MEDIUM_7SEGMENT:
2130 return get_resources()->medium_7segment[0]->get_h();
2138 int BC_WindowBase::get_text_descent(int font)
2141 if(get_resources()->use_xft && get_xft_struct(font))
2144 XftTextExtents8(top_level->display,
2145 get_xft_struct(font),
2149 return extents.height - extents.y;
2153 if(get_resources()->use_fontset && top_level->get_fontset(font))
2155 XFontSetExtents *extents;
2157 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2158 return (extents->max_logical_extent.height
2159 + extents->max_logical_extent.y);
2162 if(get_font_struct(font))
2163 return top_level->get_font_struct(font)->descent;
2172 int BC_WindowBase::get_text_height(int font, char *text)
2174 if(!text) return get_text_ascent(font) + get_text_descent(font);
2176 // Add height of lines
2177 int h = 0, i, length = strlen(text);
2178 for(i = 0; i <= length; i++)
2186 return h * (get_text_ascent(font) + get_text_descent(font));
2189 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2191 if(color_model < 0) color_model = top_level->get_color_model();
2192 return new BC_Bitmap(top_level, w, h, color_model);
2195 int BC_WindowBase::accel_available(int color_model)
2197 if(window_type != MAIN_WINDOW)
2198 return top_level->accel_available(color_model);
2205 result = grab_port_id(this, color_model);
2208 xvideo_port_id = result;
2220 //printf("BC_WindowBase::accel_available 1\n");
2221 result = grab_port_id(this, color_model);
2222 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2225 xvideo_port_id = result;
2230 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2237 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2242 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2244 int numFormats, i, j, k;
2245 unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2247 XvAdaptorInfo *info;
2248 XvImageFormatValues *formats;
2251 if(!get_resources()->use_xvideo) return -1;
2253 // Translate from color_model to X color model
2254 x_color_model = cmodel_bc_to_x(color_model);
2256 // Only local server is fast enough.
2257 if(!resources.use_shm) return -1;
2259 // XV extension is available
2260 if(Success != XvQueryExtension(window->display,
2270 // XV adaptors are available
2271 XvQueryAdaptors(window->display,
2272 DefaultRootWindow(window->display),
2281 // Get adaptor with desired color model
2282 for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2284 /* adaptor supports XvImages */
2285 if(info[i].type & XvImageMask)
2287 formats = XvListImageFormats(window->display,
2290 // for(j = 0; j < numFormats; j++)
2291 // printf("%08x\n", formats[j].id);
2293 for(j = 0; j < numFormats && xvideo_port_id < 0; j++)
2295 /* this adaptor supports the desired format */
2296 if(formats[j].id == x_color_model)
2298 /* Try to grab a port */
2299 for(k = 0; k < info[i].num_ports; k++)
2302 if(Success == XvGrabPort(top_level->display,
2303 info[i].base_id + k,
2306 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2307 xvideo_port_id = info[i].base_id + k;
2313 if(formats) XFree(formats);
2317 XvFreeAdaptorInfo(info);
2319 return xvideo_port_id;
2323 int BC_WindowBase::show_window(int flush)
2325 XMapWindow(top_level->display, win);
2326 if(flush) XFlush(top_level->display);
2327 // XSync(top_level->display, 0);
2332 int BC_WindowBase::hide_window(int flush)
2334 XUnmapWindow(top_level->display, win);
2335 if(flush) XFlush(top_level->display);
2340 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2342 subwindows->append((BC_SubWindow*)menu_bar);
2344 menu_bar->parent_window = this;
2345 menu_bar->top_level = this->top_level;
2346 menu_bar->initialize();
2350 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2352 subwindows->append(subwindow);
2354 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2356 // parent window must be set before the subwindow initialization
2357 subwindow->parent_window = this;
2358 subwindow->top_level = this->top_level;
2360 // Execute derived initialization
2361 subwindow->initialize();
2366 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2368 return add_subwindow(subwindow);
2371 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2374 XSetWindowBackgroundPixmap(top_level->display, win, pixmap);
2377 XClearArea(top_level->display, win, x, y, w, h, 0);
2381 XClearWindow(top_level->display, win);
2389 int BC_WindowBase::flash(int flush)
2391 flash(-1, -1, -1, -1, flush);
2394 void BC_WindowBase::flush()
2396 XFlush(top_level->display);
2399 void BC_WindowBase::sync_display()
2401 XSync(top_level->display, False);
2404 int BC_WindowBase::get_window_lock()
2406 return top_level->window_lock;
2409 int BC_WindowBase::lock_window(char *location)
2411 if(top_level && top_level != this)
2413 top_level->lock_window(location);
2418 SET_LOCK(this, title, location);
2419 XLockDisplay(top_level->display);
2421 top_level->window_lock = 1;
2425 printf("BC_WindowBase::lock_window top_level NULL\n");
2430 int BC_WindowBase::unlock_window()
2432 if(top_level && top_level != this)
2434 top_level->unlock_window();
2440 top_level->window_lock = 0;
2441 XUnlockDisplay(top_level->display);
2445 printf("BC_WindowBase::unlock_window top_level NULL\n");
2450 void BC_WindowBase::set_done(int return_value)
2452 if(window_type != MAIN_WINDOW)
2453 top_level->set_done(return_value);
2457 XEvent *event = new XEvent;
2458 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2460 event->type = ClientMessage;
2461 ptr->message_type = SetDoneXAtom;
2463 this->return_value = return_value;
2465 // May lock up here because XSendEvent doesn't work too well
2466 // asynchronous with XNextEvent.
2467 // This causes BC_WindowEvents to forward a copy of the event to run_window where
2469 event_thread->done = 1;
2480 int BC_WindowBase::get_w()
2485 int BC_WindowBase::get_h()
2490 int BC_WindowBase::get_x()
2495 int BC_WindowBase::get_y()
2500 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2502 if(lock_display) lock_window("BC_WindowBase::get_root_w");
2503 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2504 int result = WidthOfScreen(screen_ptr);
2505 // Wider than 16:9, narrower than dual head
2506 if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2508 if(lock_display) unlock_window();
2512 int BC_WindowBase::get_root_h(int lock_display)
2514 if(lock_display) lock_window("BC_WindowBase::get_root_h");
2515 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2516 int result = HeightOfScreen(screen_ptr);
2517 if(lock_display) unlock_window();
2521 // Bottom right corner
2522 int BC_WindowBase::get_x2()
2527 int BC_WindowBase::get_y2()
2532 int BC_WindowBase::get_hidden()
2534 return top_level->hidden;
2537 int BC_WindowBase::cursor_inside()
2539 return (top_level->cursor_x >= 0 &&
2540 top_level->cursor_y >= 0 &&
2541 top_level->cursor_x < w &&
2542 top_level->cursor_y < h);
2545 BC_WindowBase* BC_WindowBase::get_top_level()
2550 BC_WindowBase* BC_WindowBase::get_parent()
2552 return parent_window;
2555 int BC_WindowBase::get_color_model()
2557 return top_level->color_model;
2560 BC_Resources* BC_WindowBase::get_resources()
2562 return &BC_WindowBase::resources;
2565 int BC_WindowBase::get_bg_color()
2570 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2575 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2577 top_level->active_subwindow = subwindow;
2580 int BC_WindowBase::activate()
2585 int BC_WindowBase::deactivate()
2587 if(window_type == MAIN_WINDOW)
2589 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2590 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2591 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2593 top_level->active_menubar = 0;
2594 top_level->active_popup_menu = 0;
2595 top_level->active_subwindow = 0;
2600 int BC_WindowBase::cycle_textboxes(int amount)
2603 BC_WindowBase *new_textbox = 0;
2607 BC_WindowBase *first_textbox = 0;
2608 find_next_textbox(&first_textbox, &new_textbox, result);
2609 if(!new_textbox) new_textbox = first_textbox;
2615 BC_WindowBase *last_textbox = 0;
2616 find_prev_textbox(&last_textbox, &new_textbox, result);
2617 if(!new_textbox) new_textbox = last_textbox;
2621 if(new_textbox != active_subwindow)
2624 new_textbox->activate();
2630 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2632 // Search subwindows for textbox
2633 for(int i = 0; i < subwindows->total && result < 2; i++)
2635 BC_WindowBase *test_subwindow = subwindows->values[i];
2636 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2643 if(!*first_textbox) *first_textbox = this;
2647 if(top_level->active_subwindow == this)
2653 *next_textbox = this;
2660 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2666 if(!*last_textbox) *last_textbox = this;
2670 if(top_level->active_subwindow == this)
2676 *prev_textbox = this;
2681 // Search subwindows for textbox
2682 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2684 BC_WindowBase *test_subwindow = subwindows->values[i];
2685 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2690 BC_Clipboard* BC_WindowBase::get_clipboard()
2692 return top_level->clipboard;
2695 int BC_WindowBase::get_relative_cursor_x()
2697 int abs_x, abs_y, x, y, win_x, win_y;
2698 unsigned int temp_mask;
2701 XQueryPointer(top_level->display,
2711 XTranslateCoordinates(top_level->display,
2723 int BC_WindowBase::get_relative_cursor_y()
2725 int abs_x, abs_y, x, y, win_x, win_y;
2726 unsigned int temp_mask;
2729 XQueryPointer(top_level->display,
2739 XTranslateCoordinates(top_level->display,
2751 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2753 int abs_x, abs_y, win_x, win_y;
2754 unsigned int temp_mask;
2757 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2758 XQueryPointer(top_level->display,
2767 if(lock_window) this->unlock_window();
2771 int BC_WindowBase::get_abs_cursor_y(int lock_window)
2773 int abs_x, abs_y, win_x, win_y;
2774 unsigned int temp_mask;
2777 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
2778 XQueryPointer(top_level->display,
2787 if(lock_window) this->unlock_window();
2791 int BC_WindowBase::match_window(Window win)
2793 if (this->win == win) return 1;
2795 for(int i = 0; i < subwindows->total; i++)
2797 result = subwindows->values[i]->match_window(win);
2798 if (result) return result;
2804 int BC_WindowBase::get_cursor_over_window()
2806 if(top_level != this) return top_level->get_cursor_over_window();
2808 int abs_x, abs_y, win_x, win_y;
2809 unsigned int temp_mask;
2810 Window temp_win1, temp_win2;
2812 if (!XQueryPointer(display,
2823 int result = match_window(temp_win2) ;
2827 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
2832 translate_coordinates(top_level->event_win,
2834 top_level->cursor_x,
2835 top_level->cursor_y,
2841 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
2846 translate_coordinates(top_level->event_win,
2848 top_level->cursor_x,
2849 top_level->cursor_y,
2855 int BC_WindowBase::get_drag_x()
2857 return top_level->drag_x;
2860 int BC_WindowBase::get_drag_y()
2862 return top_level->drag_y;
2865 int BC_WindowBase::get_cursor_x()
2867 return top_level->cursor_x;
2870 int BC_WindowBase::get_cursor_y()
2872 return top_level->cursor_y;
2875 int BC_WindowBase::is_event_win()
2877 return this->win == top_level->event_win;
2880 void BC_WindowBase::set_dragging(int value)
2882 is_dragging = value;
2885 int BC_WindowBase::get_dragging()
2890 int BC_WindowBase::get_buttonpress()
2892 return top_level->button_number;
2895 int BC_WindowBase::get_button_down()
2897 return top_level->button_down;
2900 int BC_WindowBase::alt_down()
2902 return top_level->alt_mask;
2905 int BC_WindowBase::shift_down()
2907 return top_level->shift_mask;
2910 int BC_WindowBase::ctrl_down()
2912 return top_level->ctrl_mask;
2916 int BC_WindowBase::get_keypress()
2918 return top_level->key_pressed;
2921 int BC_WindowBase::get_double_click()
2923 return top_level->double_click;
2926 int BC_WindowBase::get_bgcolor()
2931 int BC_WindowBase::resize_window(int w, int h)
2933 if(window_type == MAIN_WINDOW && !allow_resize)
2935 XSizeHints size_hints;
2936 size_hints.flags = PSize | PMinSize | PMaxSize;
2937 size_hints.width = w;
2938 size_hints.height = h;
2939 size_hints.min_width = w;
2940 size_hints.max_width = w;
2941 size_hints.min_height = h;
2942 size_hints.max_height = h;
2943 XSetNormalHints(top_level->display, win, &size_hints);
2945 XResizeWindow(top_level->display, win, w, h);
2949 XFreePixmap(top_level->display, pixmap);
2950 pixmap = XCreatePixmap(top_level->display, win, w, h, top_level->default_depth);
2952 // Propagate to menubar
2953 for(int i = 0; i < subwindows->total; i++)
2955 subwindows->values[i]->dispatch_resize_event(w, h);
2958 draw_background(0, 0, w, h);
2959 if(top_level == this && get_resources()->recursive_resizing)
2960 resize_history.append(new BC_ResizeCall(w, h));
2964 // The only way for resize events to be propagated is by updating the internal w and h
2965 int BC_WindowBase::resize_event(int w, int h)
2967 if(window_type == MAIN_WINDOW)
2975 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
2979 // Some tools set their own dimensions before calling this, causing the
2980 // resize check to skip.
2984 if(w > 0 && w != this->w)
2990 if(h > 0 && h != this->h)
2996 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
2999 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3001 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3003 if(translation_count && window_type == MAIN_WINDOW)
3005 // KDE shifts window right and down.
3006 // FVWM leaves window alone and adds border around it.
3007 XMoveResizeWindow(top_level->display,
3009 x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x,
3010 y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y,
3016 XMoveResizeWindow(top_level->display,
3026 XFreePixmap(top_level->display, pixmap);
3027 pixmap = XCreatePixmap(top_level->display,
3031 top_level->default_depth);
3033 // Propagate to menubar
3034 for(int i = 0; i < subwindows->total; i++)
3036 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3039 // draw_background(0, 0, w, h);
3045 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3047 get_resources()->tooltips_enabled = tooltips_enabled;
3051 int BC_WindowBase::raise_window(int do_flush)
3053 XRaiseWindow(top_level->display, win);
3054 if(do_flush) XFlush(top_level->display);
3058 void BC_WindowBase::set_background(VFrame *bitmap)
3060 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3062 bg_pixmap = new BC_Pixmap(this,
3065 shared_bg_pixmap = 0;
3066 draw_background(0, 0, w, h);
3069 void BC_WindowBase::set_title(char *text)
3071 XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0);
3072 strcpy(this->title, _(text));
3076 char* BC_WindowBase::get_title()
3081 int BC_WindowBase::get_toggle_value()
3083 return toggle_value;
3086 int BC_WindowBase::get_toggle_drag()
3091 int BC_WindowBase::set_icon(VFrame *data)
3093 if(icon_pixmap) delete icon_pixmap;
3094 icon_pixmap = new BC_Pixmap(top_level,
3099 icon_window = new BC_Popup(this,
3102 icon_pixmap->get_w(),
3103 icon_pixmap->get_h(),
3105 1, // All windows are hidden initially
3109 wm_hints.flags = IconPixmapHint | IconMaskHint | IconWindowHint;
3110 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3111 wm_hints.icon_mask = icon_pixmap->get_alpha();
3112 wm_hints.icon_window = icon_window->win;
3113 // for(int i = 0; i < 1000; i++)
3114 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3117 XSetWMHints(top_level->display, top_level->win, &wm_hints);
3118 XSync(top_level->display, 0);
3122 int BC_WindowBase::set_w(int w)
3128 int BC_WindowBase::set_h(int h)
3134 int BC_WindowBase::load_defaults(Defaults *defaults)
3136 get_resources()->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3137 get_resources()->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3138 get_resources()->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3139 defaults->get("FILEBOX_FILTER", get_resources()->filebox_filter);
3143 int BC_WindowBase::save_defaults(Defaults *defaults)
3145 defaults->update("FILEBOX_MODE", get_resources()->filebox_mode);
3146 defaults->update("FILEBOX_W", get_resources()->filebox_w);
3147 //printf("BC_ListBox::cursor_motion_event 1 %lld\n", timer.get_difference());
3148 defaults->update("FILEBOX_H", get_resources()->filebox_h);
3149 defaults->update("FILEBOX_FILTER", get_resources()->filebox_filter);
3155 // For some reason XTranslateCoordinates can take a long time to return.
3156 // We work around this by only calling it when the event windows are different.
3157 void BC_WindowBase::translate_coordinates(Window src_w,
3169 *dest_x_return = src_x;
3170 *dest_y_return = src_y;
3174 XTranslateCoordinates(top_level->display,
3182 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3192 #ifdef HAVE_LIBXXF86VM
3193 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3197 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3199 XF86VidModeModeInfo **vm_modelines;
3200 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3201 for (i = 0; i < vm_count; i++) {
3202 if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3205 display = top_level->display;
3206 if (vm_modelines[*vm]->hdisplay == *width)
3210 *width = vm_modelines[*vm]->hdisplay;
3211 *height = vm_modelines[*vm]->vdisplay;
3216 void BC_WindowBase::scale_vm(int vm)
3218 int foo,bar,dotclock;
3219 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3222 XF86VidModeModeInfo **vm_modelines;
3223 XF86VidModeModeLine vml;
3224 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3225 XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3226 orig_modeline.dotclock = dotclock;
3227 orig_modeline.hdisplay = vml.hdisplay;
3228 orig_modeline.hsyncstart = vml.hsyncstart;
3229 orig_modeline.hsyncend = vml.hsyncend;
3230 orig_modeline.htotal = vml.htotal;
3231 orig_modeline.vdisplay = vml.vdisplay;
3232 orig_modeline.vsyncstart = vml.vsyncstart;
3233 orig_modeline.vsyncend = vml.vsyncend;
3234 orig_modeline.vtotal = vml.vtotal;
3235 orig_modeline.flags = vml.flags;
3236 orig_modeline.privsize = vml.privsize;
3237 // orig_modeline.private = vml.private;
3238 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3239 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3240 XFlush(top_level->display);
3244 void BC_WindowBase::restore_vm()
3246 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3247 XFlush(top_level->display);
3258 GLXContext glXCreateContext(Display *dpy,
3260 GLXContext shareList,
3263 int glXMakeCurrent(Display *dpy,
3267 void glXSwapBuffers(Display *dpy,
3273 void BC_WindowBase::enable_opengl()
3275 lock_window("BC_WindowBase::enable_opengl");
3278 XVisualInfo viproto;
3279 XVisualInfo *visinfo;
3282 //printf("BC_WindowBase::enable_opengl 1\n");
3283 viproto.screen = top_level->screen;
3284 visinfo = XGetVisualInfo(top_level->display,
3288 //printf("BC_WindowBase::enable_opengl 1 %p\n", visinfo);
3290 gl_context = glXCreateContext(top_level->display,
3294 //printf("BC_WindowBase::enable_opengl 1\n");
3296 glXMakeCurrent(top_level->display,
3300 unsigned long valuemask = CWEventMask;
3301 XSetWindowAttributes attributes;
3302 attributes.event_mask = DEFAULT_EVENT_MASKS |
3304 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3306 opengl_lock.unlock();
3308 //printf("BC_WindowBase::enable_opengl 2\n");
3311 void BC_WindowBase::disable_opengl()
3313 unsigned long valuemask = CWEventMask;
3314 XSetWindowAttributes attributes;
3315 attributes.event_mask = DEFAULT_EVENT_MASKS;
3316 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3319 void BC_WindowBase::lock_opengl()
3321 lock_window("BC_WindowBase::lock_opengl");
3323 glXMakeCurrent(top_level->display,
3328 void BC_WindowBase::unlock_opengl()
3330 opengl_lock.unlock();
3334 void BC_WindowBase::flip_opengl()
3336 glXSwapBuffers(top_level->display, win);
3340 int BC_WindowBase::get_event_count()
3342 event_lock->lock("BC_WindowBase::get_event_count");
3343 int result = common_events.total;
3344 event_lock->unlock();
3348 XEvent* BC_WindowBase::get_event()
3351 while(!done && !result)
3353 event_condition->lock("BC_WindowBase::get_event");
3354 event_lock->lock("BC_WindowBase::get_event");
3355 if(common_events.total && !done)
3357 result = common_events.values[0];
3358 common_events.remove_number(0);
3360 event_lock->unlock();
3365 void BC_WindowBase::put_event(XEvent *event)
3367 event_lock->lock("BC_WindowBase::put_event");
3368 common_events.append(event);
3369 event_lock->unlock();
3370 event_condition->unlock();