2 #include "bcclipboard.h"
3 #include "bcdisplayinfo.h"
7 #include "bcpopupmenu.h"
8 #include "bcrepeater.h"
9 #include "bcresources.h"
10 #include "bcsubwindow.h"
11 #include "bcwindowbase.h"
13 #include "colormodels.h"
28 #include <X11/extensions/Xvlib.h>
29 #include <X11/extensions/shape.h>
32 #define _(String) gettext(String)
33 #define gettext_noop(String) String
34 #define N_(String) gettext_noop (String)
37 BC_ResizeCall::BC_ResizeCall(int w, int h)
44 BC_WindowTree::BC_WindowTree(Display* display,
45 BC_WindowTree *parent_tree,
52 this->display = display;
54 this->parent_tree = parent_tree;
60 (unsigned int*)&stack_total);
62 for(int i = 0; i < stack_total; i++)
64 windows.append(new BC_WindowTree(display, this, stack[i]));
69 BC_WindowTree::~BC_WindowTree()
71 windows.remove_all_objects();
74 BC_WindowTree* BC_WindowTree::get_node(Window win)
76 //printf("BC_WindowTree::get_node 1\n");
77 for(int i = 0; i < windows.total; i++)
79 BC_WindowTree *result = 0;
80 //printf("BC_WindowTree::get_node 2\n");
81 if(windows.values[i]->win == win)
82 return windows.values[i];
85 //printf("BC_WindowTree::get_node 3\n");
86 result = windows.values[i]->get_node(win);
87 //printf("BC_WindowTree::get_node 4\n");
88 if(result) return result;
94 void BC_WindowTree::dump(int indent, Window caller_win)
96 XWindowAttributes attr;
97 XGetWindowAttributes(display,
100 for(int i = 0; i < indent; i++)
102 printf("x=%d y=%d w=%d h=%d win=%x subwindows=%d ",
103 attr.x, attr.y, attr.width, attr.height, win, windows.total);
104 if(caller_win == win) printf("**");
106 for(int i = 0; i < windows.total; i++)
107 windows.values[i]->dump(indent + 1, caller_win);
113 Mutex BC_WindowBase::opengl_lock;
115 BC_Resources BC_WindowBase::resources;
116 BC_WindowTree* BC_WindowBase::window_tree = 0;
118 BC_WindowBase::BC_WindowBase()
120 //printf("BC_WindowBase::BC_WindowBase 1\n");
121 BC_WindowBase::initialize();
124 BC_WindowBase::~BC_WindowBase()
126 //printf("BC_WindowBase::~BC_WindowBase 1 %s\n", title);
128 #ifdef HAVE_LIBXXF86VM
129 if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
136 if(window_type != MAIN_WINDOW)
138 if(top_level->active_menubar == this) top_level->active_menubar = 0;
139 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
140 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
141 parent_window->subwindows->remove(this);
146 for(int i = 0; i < subwindows->total; i++)
148 delete subwindows->values[i];
153 XFreePixmap(top_level->display, pixmap);
154 XDestroyWindow(top_level->display, win);
156 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
157 if(icon_pixmap) delete icon_pixmap;
158 if (temp_bitmap) delete temp_bitmap;
160 if(window_type == MAIN_WINDOW)
163 XFreeGC(top_level->display, gc);
165 // Can't close display if another thread is waiting for events
166 XCloseDisplay(top_level->display);
167 clipboard->stop_clipboard();
171 resize_history.remove_all_objects();
174 int BC_WindowBase::initialize()
189 translation_events = 0;
190 ctrl_mask = shift_mask = alt_mask = 0;
191 cursor_x = cursor_y = button_number = 0;
194 button_time1 = button_time2 = 0;
199 active_popup_menu = 0;
200 active_subwindow = 0;
203 persistant_tooltip = 0;
204 // next_repeat_id = 0;
207 current_font = MEDIUMFONT;
208 current_cursor = ARROW_CURSOR;
209 current_color = BLACK;
211 shared_bg_pixmap = 0;
213 window_type = MAIN_WINDOW;
214 translation_count = 0;
215 x_correction = y_correction = 0;
221 #ifdef HAVE_LIBXXF86VM
227 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
230 ButtonReleaseMask | \
233 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
247 BC_Pixmap *bg_pixmap)
249 //printf("BC_WindowBase::create_window 1\n");
250 XSetWindowAttributes attr;
252 XSizeHints size_hints;
255 #ifdef HAVE_LIBXXF86VM
259 if(parent_window) top_level = parent_window->top_level;
261 #ifdef HAVE_LIBXXF86VM
262 if(window_type == VIDMODE_SCALED_WINDOW)
263 closest_vm(&vm,&w,&h);
270 this->bg_color = bg_color;
271 this->window_type = window_type;
273 this->private_color = private_color;
274 this->parent_window = parent_window;
275 this->bg_pixmap = bg_pixmap;
276 this->allow_resize = allow_resize;
277 strcpy(this->title, title);
278 if(bg_pixmap) shared_bg_pixmap = 1;
280 if(parent_window) top_level = parent_window->top_level;
282 subwindows = new BC_SubWindowList;
285 if(window_type == MAIN_WINDOW)
288 parent_window = this;
290 // This function must be the first Xlib
291 // function a multi-threaded program calls
294 // get the display connection
295 display = init_display(display_name);
297 // Fudge window placement
298 root_w = get_root_w(1);
299 root_h = get_root_h();
300 if(this->x + this->w > root_w) this->x = root_w - this->w;
301 if(this->y + this->h > root_h) this->y = root_h - this->h;
302 if(this->x < 0) this->x = 0;
303 if(this->y < 0) this->y = 0;
304 screen = DefaultScreen(display);
305 rootwin = RootWindow(display, screen);
306 vis = DefaultVisual(display, screen);
307 default_depth = DefaultDepth(display, screen);
308 client_byte_order = (*(u_int32_t*)"a ") & 0x00000001;
309 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
313 if(resources.use_shm < 0) resources.initialize_display(this);
314 x_correction = get_resources()->get_left_border();
315 y_correction = get_resources()->get_top_border();
317 if(this->bg_color == -1)
318 this->bg_color = resources.get_bg_color();
329 attr.event_mask = EnterWindowMask |
333 StructureNotifyMask |
337 attr.background_pixel = get_color(this->bg_color);
338 attr.colormap = cmap;
339 attr.cursor = get_cursor_struct(ARROW_CURSOR);
341 win = XCreateWindow(display,
348 top_level->default_depth,
354 XGetNormalHints(display, win, &size_hints);
356 size_hints.flags = PSize | PMinSize | PMaxSize;
357 size_hints.width = this->w;
358 size_hints.height = this->h;
359 size_hints.min_width = allow_resize ? minw : this->w;
360 size_hints.max_width = allow_resize ? 32767 : this->w;
361 size_hints.min_height = allow_resize ? minh : this->h;
362 size_hints.max_height = allow_resize ? 32767 : this->h;
363 if(x > -BC_INFINITY && x < BC_INFINITY)
365 size_hints.flags |= PPosition;
366 size_hints.x = this->x;
367 size_hints.y = this->y;
370 XSetStandardProperties(display,
380 clipboard = new BC_Clipboard(display_name);
381 clipboard->start_clipboard();
384 #ifdef HAVE_LIBXXF86VM
385 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
392 #ifdef HAVE_LIBXXF86VM
393 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
395 if(window_type == POPUP_WINDOW)
405 attr.event_mask = DEFAULT_EVENT_MASKS;
407 if(this->bg_color == -1)
408 this->bg_color = resources.get_bg_color();
409 attr.background_pixel = top_level->get_color(bg_color);
410 attr.colormap = top_level->cmap;
411 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
412 attr.override_redirect = True;
413 attr.save_under = True;
415 win = XCreateWindow(top_level->display,
422 top_level->default_depth,
429 if(window_type == SUB_WINDOW)
431 mask = CWBackPixel | CWEventMask;
432 attr.event_mask = EnterWindowMask |
437 attr.background_pixel = top_level->get_color(this->bg_color);
438 win = XCreateWindow(top_level->display,
445 top_level->default_depth,
451 XMapWindow(top_level->display, win);
454 // Create pixmap for all windows
455 pixmap = XCreatePixmap(top_level->display,
459 top_level->default_depth);
461 // Set up options for main window
462 if(window_type == MAIN_WINDOW)
464 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
466 this->bg_pixmap = new BC_Pixmap(this,
467 get_resources()->bg_image,
471 if(!hidden) show_window();
475 draw_background(0, 0, this->w, this->h);
478 // Set up options for popup window
479 #ifdef HAVE_LIBXXF86VM
480 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
482 if(window_type == POPUP_WINDOW)
486 if(!hidden) show_window();
491 Display* BC_WindowBase::init_display(char *display_name)
495 if(display_name && display_name[0] == 0) display_name = NULL;
496 if((display = XOpenDisplay(display_name)) == NULL)
498 printf("BC_WindowBase::create_window: cannot connect to X server %s\n",
500 if(getenv("DISPLAY") == NULL)
502 printf("'DISPLAY' environment variable not set.\n");
506 // Try again with default display.
508 if((display = XOpenDisplay(0)) == NULL)
510 printf("BC_WindowBase::create_window: cannot connect to default X server.\n");
518 int BC_WindowBase::run_window()
523 //printf("BC_WindowBase::run_window 1\n");
525 if(window_type == MAIN_WINDOW)
527 // tooltip_id = get_repeat_id();
528 set_repeat(get_resources()->tooltip_delay);
530 //printf("BC_WindowBase::run_window 2\n");
536 //printf("BC_WindowBase::run_window 3\n");
538 unset_all_repeaters();
539 //printf("BC_WindowBase::run_window 4\n");
545 int BC_WindowBase::get_key_masks(XEvent &event)
548 ctrl_mask = (event.xkey.state & ControlMask) ? 1 : 0;
550 shift_mask = (event.xkey.state & ShiftMask) ? 1 : 0;
551 alt_mask = (event.xkey.state & Mod1Mask) ? 1 : 0;
552 //printf("BC_WindowBase::get_key_masks %x\n", event.xkey.state);
562 int BC_WindowBase::dispatch_event()
569 XClientMessageEvent *ptr;
571 int cancel_resize, cancel_translation;
575 // If an event is waiting get it, otherwise
576 // wait for next event only if there are no compressed events.
577 //printf("BC_WindowBase::dispatch_event 1 %p %s\n", this, title);
578 if(XPending(display) ||
579 (!motion_events && !resize_events && !translation_events))
581 XNextEvent(display, &event);
582 // Lock out window deletions
584 get_key_masks(event);
587 // Handle compressed events
591 dispatch_resize_event(last_resize_w, last_resize_h);
594 dispatch_motion_event();
596 if(translation_events)
597 dispatch_translation_event();
603 //printf("BC_WindowBase::dispatch_event 2 %s %d\n", title, event.type);
607 // Clear the resize buffer
608 if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
609 // Clear the motion buffer since this can clear the window
610 if(motion_events) dispatch_motion_event();
612 ptr = (XClientMessageEvent*)&event;
614 if(ptr->message_type == ProtoXAtom &&
615 ptr->data.l[0] == DelWinXAtom)
620 if(ptr->message_type == RepeaterXAtom)
622 dispatch_repeat_event(ptr->data.l[0]);
623 // Make sure the repeater still exists.
624 // for(int i = 0; i < repeaters.total; i++)
626 // if(repeaters.values[i]->repeat_id == ptr->data.l[0])
628 // dispatch_repeat_event_master(ptr->data.l[0]);
634 if(ptr->message_type == SetDoneXAtom)
641 cursor_x = event.xbutton.x;
642 cursor_y = event.xbutton.y;
643 button_number = event.xbutton.button;
644 event_win = event.xany.window;
646 button_pressed = event.xbutton.button;
647 button_time1 = button_time2;
648 button_time2 = event.xbutton.time;
651 drag_win = event_win;
652 drag_x1 = cursor_x - get_resources()->drag_radius;
653 drag_x2 = cursor_x + get_resources()->drag_radius;
654 drag_y1 = cursor_y - get_resources()->drag_radius;
655 drag_y2 = cursor_y + get_resources()->drag_radius;
657 if(button_time2 - button_time1 < resources.double_click)
659 // Ignore triple clicks
661 button_time2 = button_time1 = 0;
666 dispatch_button_press();
670 button_number = event.xbutton.button;
671 event_win = event.xany.window;
674 dispatch_button_release();
678 event_win = event.xany.window;
679 dispatch_expose_event();
683 // Dispatch previous motion event if this is a subsequent motion from a different window
688 if(motion_events && last_motion_win != event.xany.window)
689 dispatch_motion_event();
691 // Buffer the current motion
693 last_motion_x = event.xmotion.x;
694 last_motion_y = event.xmotion.y;
695 last_motion_win = event.xany.window;
696 //printf("BC_WindowBase::dispatch_event 1 %lld\n", timer.get_difference());
700 case ConfigureNotify:
701 XTranslateCoordinates(top_level->display,
709 last_resize_w = event.xconfigure.width;
710 last_resize_h = event.xconfigure.height;
713 cancel_translation = 0;
715 // Resize history prevents responses to recursive resize requests
716 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
718 if(resize_history.values[i]->w == last_resize_w &&
719 resize_history.values[i]->h == last_resize_h)
721 delete resize_history.values[i];
722 resize_history.remove_number(i);
727 if(last_resize_w == w && last_resize_h == h)
735 if((last_translate_x == x && last_translate_y == y))
736 cancel_translation = 1;
738 if(!cancel_translation)
740 translation_events = 1;
748 XLookupString((XKeyEvent*)&event, keys_return, 1, &keysym, 0);
750 // block out control keys
751 if(keysym > 0xffe0 && keysym < 0xffff) break;
754 // block out extra keys
764 // Translate key codes
765 case XK_Return: key_pressed = RETURN; break;
766 case XK_Up: key_pressed = UP; break;
767 case XK_Down: key_pressed = DOWN; break;
768 case XK_Left: key_pressed = LEFT; break;
769 case XK_Right: key_pressed = RIGHT; break;
770 case XK_Next: key_pressed = PGDN; break;
771 case XK_Prior: key_pressed = PGUP; break;
772 case XK_BackSpace: key_pressed = BACKSPACE; break;
773 case XK_Escape: key_pressed = ESC; break;
776 key_pressed = LEFTTAB;
780 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
781 case XK_underscore: key_pressed = '_'; break;
782 case XK_asciitilde: key_pressed = '~'; break;
783 case XK_Delete: key_pressed = DELETE; break;
784 case XK_Home: key_pressed = HOME; break;
785 case XK_End: key_pressed = END; break;
788 case XK_KP_Enter: key_pressed = KPENTER; break;
789 case XK_KP_Add: key_pressed = KPPLUS; break;
791 case XK_KP_End: key_pressed = KP1; break;
793 case XK_KP_Down: key_pressed = KP2; break;
795 case XK_KP_Page_Down: key_pressed = KP3; break;
797 case XK_KP_Left: key_pressed = KP4; break;
799 case XK_KP_Begin: key_pressed = KP5; break;
801 case XK_KP_Right: key_pressed = KP6; break;
803 case XK_KP_Insert: key_pressed = KPINS; break;
805 case XK_KP_Delete: key_pressed = KPDEL; break;
807 //key_pressed = keys_return[0];
808 key_pressed = keysym & 0xff;
812 //printf("BC_WindowBase::run_window %d %d %x\n", shift_down(), alt_down(), key_pressed);
813 result = dispatch_keypress_event();
814 // Handle some default keypresses
817 if(key_pressed == 'w' ||
826 event_win = event.xany.window;
827 dispatch_cursor_leave();
831 event_win = event.xany.window;
832 cursor_x = event.xcrossing.x;
833 cursor_y = event.xcrossing.y;
834 dispatch_cursor_enter();
838 //printf("BC_WindowBase::dispatch_event 3 %s\n", title);
843 int BC_WindowBase::dispatch_expose_event()
846 for(int i = 0; i < subwindows->total && !result; i++)
848 result = subwindows->values[i]->dispatch_expose_event();
852 if(!result) expose_event();
856 int BC_WindowBase::dispatch_resize_event(int w, int h)
858 if(window_type == MAIN_WINDOW)
861 // Can't store w and h here because bcfilebox depends on the old w and h to
862 // reposition widgets.
863 XFreePixmap(top_level->display, pixmap);
864 pixmap = XCreatePixmap(top_level->display,
868 top_level->default_depth);
869 clear_box(0, 0, w, h);
872 // Propagate to subwindows
873 for(int i = 0; i < subwindows->total; i++)
875 subwindows->values[i]->dispatch_resize_event(w, h);
881 if(window_type == MAIN_WINDOW)
889 int BC_WindowBase::dispatch_translation_event()
891 translation_events = 0;
892 if(window_type == MAIN_WINDOW)
896 x = last_translate_x;
897 y = last_translate_y;
898 // Correct for window manager offsets
903 for(int i = 0; i < subwindows->total; i++)
905 subwindows->values[i]->dispatch_translation_event();
908 //printf("BC_WindowBase::dispatch_translation_event 1 %p\n", this);
913 int BC_WindowBase::dispatch_motion_event()
917 if(top_level == this)
919 event_win = last_motion_win;
922 //printf("BC_WindowBase::dispatch_motion_event 1\n");
924 if(get_button_down() && !active_menubar && !active_popup_menu)
926 //printf("BC_WindowBase::dispatch_motion_event 2\n");
929 cursor_x = last_motion_x;
930 cursor_y = last_motion_y;
931 result = dispatch_drag_motion();
935 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
936 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
942 // delete window_tree;
947 // window_tree = new BC_WindowTree(display,
950 // //window_tree->dump(0, win);
953 result = dispatch_drag_start();
956 cursor_x = last_motion_x;
957 cursor_y = last_motion_y;
959 //printf("BC_WindowBase::dispatch_motion_event 3\n");
960 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
961 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
962 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
963 //printf("BC_WindowBase::dispatch_motion_event 4\n");
966 //printf("BC_WindowBase::dispatch_motion_event 5\n");
967 for(int i = 0; i < subwindows->total && !result; i++)
969 result = subwindows->values[i]->dispatch_motion_event();
971 //printf("BC_WindowBase::dispatch_motion_event 6\n");
973 if(!result) result = cursor_motion_event(); // give to user
974 //printf("BC_WindowBase::dispatch_motion_event 7\n");
978 int BC_WindowBase::dispatch_keypress_event()
981 if(top_level == this)
983 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
986 for(int i = 0; i < subwindows->total && !result; i++)
988 result = subwindows->values[i]->dispatch_keypress_event();
991 if(!result) result = keypress_event();
996 int BC_WindowBase::dispatch_button_press()
999 if(top_level == this)
1001 if(active_menubar) result = active_menubar->dispatch_button_press();
1002 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1003 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1006 for(int i = 0; i < subwindows->total && !result; i++)
1008 result = subwindows->values[i]->dispatch_button_press();
1011 if(!result) result = button_press_event();
1016 int BC_WindowBase::dispatch_button_release()
1019 if(top_level == this)
1021 if(active_menubar) result = active_menubar->dispatch_button_release();
1022 //printf("BC_WindowBase::dispatch_button_release 1 %d\n", result);
1023 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1024 //printf("BC_WindowBase::dispatch_button_release 2 %p %d\n", active_subwindow, result);
1025 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1026 //printf("BC_WindowBase::dispatch_button_release 3 %d\n", result);
1027 if(!result) result = dispatch_drag_stop();
1029 //printf("BC_WindowBase::dispatch_button_release 4 %d\n", result);
1031 for(int i = 0; i < subwindows->total && !result; i++)
1033 result = subwindows->values[i]->dispatch_button_release();
1035 //printf("BC_WindowBase::dispatch_button_release 5 %d\n", result);
1039 result = button_release_event();
1041 //printf("BC_WindowBase::dispatch_button_release 6 %d\n", result);
1046 // int BC_WindowBase::dispatch_repeat_event_master(long duration)
1049 // BC_Repeater *repeater;
1051 // // Unlock the repeater if it still exists.
1052 // for(int i = 0; i < repeaters.total; i++)
1054 // if(repeaters.values[i]->repeat_id == repeat_id)
1056 // repeater = repeaters.values[i];
1057 // if(repeater->interrupted)
1060 // if(interrupt_now)
1063 // repeater->join();
1064 // repeaters.remove(repeater);
1070 // // Propogate to subwindows
1071 // if(active_menubar) result = active_menubar->dispatch_repeat_event(repeat_id);
1072 // if(!result && active_subwindow) result = active_subwindow->dispatch_repeat_event(repeat_id);
1073 // if(!result) result = dispatch_repeat_event(repeat_id);
1074 // repeater->repeat_mutex.unlock();
1076 // i = repeaters.total;
1083 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1085 // all repeat event handlers get called and decide based on activity and duration
1086 // whether to respond
1087 for(int i = 0; i < subwindows->total; i++)
1089 subwindows->values[i]->dispatch_repeat_event(duration);
1091 repeat_event(duration);
1093 // Unlock next signal
1094 if(window_type == MAIN_WINDOW)
1096 for(int i = 0; i < repeaters.total; i++)
1098 if(repeaters.values[i]->delay == duration)
1100 repeaters.values[i]->repeat_lock.unlock();
1108 int BC_WindowBase::dispatch_cursor_leave()
1110 for(int i = 0; i < subwindows->total; i++)
1112 subwindows->values[i]->dispatch_cursor_leave();
1114 cursor_leave_event();
1118 int BC_WindowBase::dispatch_cursor_enter()
1122 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1123 //printf("BC_WindowBase::dispatch_cursor_enter 2 %s\n", title);
1124 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1125 //printf("BC_WindowBase::dispatch_cursor_enter 3 %s\n", title);
1126 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1128 for(int i = 0; !result && i < subwindows->total; i++)
1130 result = subwindows->values[i]->dispatch_cursor_enter();
1132 //printf("BC_WindowBase::dispatch_cursor_enter 1 %s %p\n", title, this);
1134 //printf("BC_WindowBase::dispatch_cursor_enter 5 %s %p\n", title, this);
1135 if(!result) result = cursor_enter_event();
1139 int BC_WindowBase::cursor_enter_event()
1141 //printf("BC_WindowBase::cursor_enter_event 1 %s %p\n", title, this);
1145 int BC_WindowBase::cursor_leave_event()
1147 //printf("BC_WindowBase::cursor_leave_event 1 %s %p\n", title, this);
1151 int BC_WindowBase::dispatch_drag_start()
1154 if(active_menubar) result = active_menubar->dispatch_drag_start();
1155 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1156 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1158 for(int i = 0; i < subwindows->total && !result; i++)
1160 result = subwindows->values[i]->dispatch_drag_start();
1163 if(!result) result = is_dragging = drag_start_event();
1167 int BC_WindowBase::dispatch_drag_stop()
1171 for(int i = 0; i < subwindows->total && !result; i++)
1173 result = subwindows->values[i]->dispatch_drag_stop();
1176 if(is_dragging && !result)
1186 int BC_WindowBase::dispatch_drag_motion()
1189 for(int i = 0; i < subwindows->total && !result; i++)
1191 result = subwindows->values[i]->dispatch_drag_motion();
1194 if(is_dragging && !result)
1196 drag_motion_event();
1207 int BC_WindowBase::show_tooltip(int w, int h)
1211 if(!tooltip_on && get_resources()->tooltips_enabled)
1214 top_level->hide_tooltip();
1218 w = get_text_width(MEDIUMFONT, tooltip_text);
1221 h = get_text_height(MEDIUMFONT, tooltip_text);
1223 w += TOOLTIP_MARGIN * 2;
1224 h += TOOLTIP_MARGIN * 2;
1226 XTranslateCoordinates(top_level->display,
1234 tooltip_popup = new BC_Popup(top_level,
1239 get_resources()->tooltip_bg_color);
1242 tooltip_popup->set_font(MEDIUMFONT);
1243 tooltip_popup->flash();
1248 int BC_WindowBase::hide_tooltip()
1251 for(int i = 0; i < subwindows->total; i++)
1253 subwindows->values[i]->hide_tooltip();
1259 delete tooltip_popup;
1265 int BC_WindowBase::set_tooltip(char *text)
1267 strcpy(this->tooltip_text, text);
1268 // Update existing tooltip if it is visible
1272 tooltip_popup->flash();
1277 // signal the event handler to repeat
1278 int BC_WindowBase::set_repeat(int64_t duration)
1282 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1285 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1286 //printf("BC_WindowBase::set_repeat 1 %d\n", duration);
1288 // test repeater database for duplicates
1289 for(int i = 0; i < repeaters.total; i++)
1292 if(repeaters.values[i]->delay == duration)
1294 repeaters.values[i]->start_repeating();
1299 BC_Repeater *repeater = new BC_Repeater(this, duration);
1300 repeaters.append(repeater);
1302 repeater->start_repeating();
1306 int BC_WindowBase::unset_repeat(int64_t duration)
1308 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1310 BC_Repeater *repeater = 0;
1311 for(int i = 0; i < repeaters.total; i++)
1313 if(repeaters.values[i]->delay == duration)
1315 repeaters.values[i]->stop_repeating();
1322 int BC_WindowBase::unset_all_repeaters()
1324 //printf("BC_WindowBase::unset_all_repeaters 1\n");
1325 for(int i = 0; i < repeaters.total; i++)
1327 repeaters.values[i]->stop_repeating();
1329 //printf("BC_WindowBase::unset_all_repeaters 1\n");
1330 repeaters.remove_all_objects();
1331 //printf("BC_WindowBase::unset_all_repeaters 2\n");
1335 // long BC_WindowBase::get_repeat_id()
1337 // return top_level->next_repeat_id++;
1340 int BC_WindowBase::arm_repeat(int64_t duration)
1343 XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
1344 ptr->type = ClientMessage;
1345 ptr->message_type = RepeaterXAtom;
1347 ptr->data.l[0] = duration;
1349 XSendEvent(display, win, 0, 0, &event);
1354 int BC_WindowBase::get_atoms()
1356 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
1357 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1358 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
1359 if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1360 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1364 void BC_WindowBase::init_cursors()
1366 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1367 cross_cursor = XCreateFontCursor(display, XC_crosshair);
1368 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1369 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1370 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1371 move_cursor = XCreateFontCursor(display, XC_fleur);
1372 left_cursor = XCreateFontCursor(display, XC_left_side);
1373 right_cursor = XCreateFontCursor(display, XC_right_side);
1374 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1375 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1376 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1377 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1378 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1381 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1387 color_model = BC_RGB8;
1390 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1393 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1396 color_model = server_byte_order ? BC_BGR8888 : BC_RGBA8888;
1402 int BC_WindowBase::init_colors()
1405 current_color_value = current_color_pixel = 0;
1407 // Get the real depth
1410 ximage = XCreateImage(top_level->display,
1412 top_level->default_depth,
1420 bits_per_pixel = ximage->bits_per_pixel;
1421 XDestroyImage(ximage);
1423 color_model = evaluate_color_model(client_byte_order, server_byte_order, bits_per_pixel);
1424 // Get the color model
1430 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1431 create_private_colors();
1435 cmap = DefaultColormap(display, screen);
1436 create_shared_colors();
1439 allocate_color_table();
1443 cmap = DefaultColormap(display, screen);
1449 int BC_WindowBase::create_private_colors()
1454 for(int i = 0; i < 255; i++)
1456 color = (i & 0xc0) << 16;
1457 color += (i & 0x38) << 10;
1458 color += (i & 0x7) << 5;
1459 color_table[i][0] = color;
1461 create_shared_colors(); // overwrite the necessary colors on the table
1466 int BC_WindowBase::create_color(int color)
1468 if(total_colors == 256)
1470 // replace the closest match with an exact match
1471 color_table[get_color_rgb8(color)][0] = color;
1475 // add the color to the table
1476 color_table[total_colors][0] = color;
1482 int BC_WindowBase::create_shared_colors()
1484 create_color(BLACK);
1485 create_color(WHITE);
1487 create_color(LTGREY);
1488 create_color(MEGREY);
1489 create_color(MDGREY);
1490 create_color(DKGREY);
1492 create_color(LTCYAN);
1493 create_color(MECYAN);
1494 create_color(MDCYAN);
1495 create_color(DKCYAN);
1497 create_color(LTGREEN);
1498 create_color(GREEN);
1499 create_color(DKGREEN);
1501 create_color(LTPINK);
1505 create_color(LTBLUE);
1507 create_color(DKBLUE);
1509 create_color(LTYELLOW);
1510 create_color(MEYELLOW);
1511 create_color(MDYELLOW);
1512 create_color(DKYELLOW);
1514 create_color(LTPURPLE);
1515 create_color(MEPURPLE);
1516 create_color(MDPURPLE);
1517 create_color(DKPURPLE);
1521 int BC_WindowBase::allocate_color_table()
1523 int red, green, blue, color;
1527 for(int i = 0; i < total_colors; i++)
1529 color = color_table[i][0];
1530 red = (color & 0xFF0000) >> 16;
1531 green = (color & 0x00FF00) >> 8;
1532 blue = color & 0xFF;
1534 col.flags = DoRed | DoGreen | DoBlue;
1535 col.red = red<<8 | red;
1536 col.green = green<<8 | green;
1537 col.blue = blue<<8 | blue;
1539 XAllocColor(display, cmap, &col);
1540 color_table[i][1] = col.pixel;
1543 XInstallColormap(display, cmap);
1547 int BC_WindowBase::init_window_shape()
1549 if(bg_pixmap && bg_pixmap->use_alpha())
1551 XShapeCombineMask(top_level->display,
1556 bg_pixmap->get_alpha(),
1563 int BC_WindowBase::init_gc()
1565 unsigned long gcmask;
1566 gcmask = GCFont | GCGraphicsExposures;
1569 gcvalues.font = mediumfont->fid; // set the font
1570 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
1571 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1575 int BC_WindowBase::init_fonts()
1577 if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL)
1578 largefont = XLoadQueryFont(display, "fixed");
1580 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL)
1581 mediumfont = XLoadQueryFont(display, "fixed");
1583 if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL)
1584 smallfont = XLoadQueryFont(display, "fixed");
1586 if(get_resources()->use_fontset)
1591 // FIXME: should check the m,d,n values
1592 if((largefontset = XCreateFontSet(display, resources.large_fontset,
1594 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1595 if((mediumfontset = XCreateFontSet(display, resources.medium_fontset,
1597 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1598 if((smallfontset = XCreateFontSet(display, resources.small_fontset,
1600 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1602 if(largefontset && mediumfontset && smallfontset)
1604 curr_fontset = mediumfontset;
1605 get_resources()->use_fontset = 1;
1610 get_resources()->use_fontset = 0;
1617 int BC_WindowBase::get_color(int64_t color)
1619 // return pixel of color
1620 // use this only for drawing subwindows not for bitmaps
1621 int i, test, difference, result;
1628 return get_color_rgb8(color);
1632 // test last color looked up
1633 if(current_color_value == color) return current_color_pixel;
1636 current_color_value = color;
1637 for(i = 0; i < total_colors; i++)
1639 if(color_table[i][0] == color)
1641 current_color_pixel = color_table[i][1];
1642 return current_color_pixel;
1646 // find nearest match
1647 difference = 0xFFFFFF;
1649 for(i = 0, result = 0; i < total_colors; i++)
1651 test = abs((int)(color_table[i][0] - color));
1653 if(test < difference)
1655 current_color_pixel = color_table[i][1];
1660 return current_color_pixel;
1665 return get_color_rgb16(color);
1669 return get_color_bgr16(color);
1674 if(client_byte_order == server_byte_order)
1677 get_color_bgr24(color);
1687 int BC_WindowBase::get_color_rgb8(int color)
1691 pixel = (color & 0xc00000) >> 16;
1692 pixel += (color & 0xe000) >> 10;
1693 pixel += (color & 0xe0) >> 5;
1697 int64_t BC_WindowBase::get_color_rgb16(int color)
1700 result = (color & 0xf80000) >> 8;
1701 result += (color & 0xfc00) >> 5;
1702 result += (color & 0xf8) >> 3;
1707 int64_t BC_WindowBase::get_color_bgr16(int color)
1710 result = (color & 0xf80000) >> 19;
1711 result += (color & 0xfc00) >> 5;
1712 result += (color & 0xf8) << 8;
1717 int64_t BC_WindowBase::get_color_bgr24(int color)
1720 result = (color & 0xff) << 16;
1721 result += (color & 0xff00);
1722 result += (color & 0xff0000) >> 16;
1726 int BC_WindowBase::video_is_on()
1731 void BC_WindowBase::start_video()
1735 draw_box(0, 0, get_w(), get_h());
1739 void BC_WindowBase::stop_video()
1746 int64_t BC_WindowBase::get_color()
1748 return top_level->current_color;
1751 void BC_WindowBase::set_color(int64_t color)
1753 top_level->current_color = color;
1754 XSetForeground(top_level->display,
1756 top_level->get_color(color));
1759 void BC_WindowBase::set_opaque()
1761 XSetFunction(top_level->display, top_level->gc, GXcopy);
1764 void BC_WindowBase::set_inverse()
1766 XSetFunction(top_level->display, top_level->gc, GXxor);
1769 Cursor BC_WindowBase::get_cursor_struct(int cursor)
1773 case ARROW_CURSOR: return top_level->arrow_cursor; break;
1774 case CROSS_CURSOR: return top_level->cross_cursor;
1775 case IBEAM_CURSOR: return top_level->ibeam_cursor; break;
1776 case VSEPARATE_CURSOR: return top_level->vseparate_cursor; break;
1777 case HSEPARATE_CURSOR: return top_level->hseparate_cursor; break;
1778 case MOVE_CURSOR: return top_level->move_cursor; break;
1779 case LEFT_CURSOR: return top_level->left_cursor; break;
1780 case RIGHT_CURSOR: return top_level->right_cursor; break;
1781 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor; break;
1782 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor; break;
1783 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor; break;
1784 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor; break;
1785 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor; break;
1790 void BC_WindowBase::set_cursor(int cursor)
1792 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
1793 current_cursor = cursor;
1797 void BC_WindowBase::set_x_cursor(int cursor)
1799 temp_cursor = XCreateFontCursor(top_level->display, cursor);
1800 XDefineCursor(top_level->display, win, temp_cursor);
1801 current_cursor = cursor;
1805 int BC_WindowBase::get_cursor()
1807 return current_cursor;
1810 XFontStruct* BC_WindowBase::get_font_struct(int font)
1812 if(font & BOLDFACE) font ^= BOLDFACE;
1816 case MEDIUMFONT: return top_level->mediumfont; break;
1817 case SMALLFONT: return top_level->smallfont; break;
1818 case LARGEFONT: return top_level->largefont; break;
1824 void BC_WindowBase::set_font(int font)
1826 if(get_font_struct(font))
1828 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
1831 top_level->current_font = font;
1832 if(get_resources()->use_fontset) set_fontset(font);
1837 XFontSet BC_WindowBase::get_fontset(int font)
1841 if(get_resources()->use_fontset)
1845 case SMALLFONT: fs = top_level->smallfontset; break;
1846 case LARGEFONT: fs = top_level->largefontset; break;
1847 case MEDIUMFONT: fs = top_level->mediumfontset; break;
1854 XFontSet BC_WindowBase::get_curr_fontset(void)
1856 if(get_resources()->use_fontset)
1857 return curr_fontset;
1861 void BC_WindowBase::set_fontset(int font)
1865 if(get_resources()->use_fontset)
1869 case SMALLFONT: fs = top_level->smallfontset; break;
1870 case LARGEFONT: fs = top_level->largefontset; break;
1871 case MEDIUMFONT: fs = top_level->mediumfontset; break;
1878 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
1880 if(get_resources()->use_fontset && top_level->get_fontset(font))
1881 return XmbTextEscapement(top_level->get_fontset(font), text, length);
1883 if(get_font_struct(font))
1884 return XTextWidth(get_font_struct(font), text, length);
1890 case MEDIUM_7SEGMENT:
1891 return get_resources()->medium_7segment[0]->get_w() * length;
1901 int BC_WindowBase::get_text_width(int font, char *text, int length)
1903 int i, j, w = 0, line_w = 0;
1904 if(length < 0) length = strlen(text);
1906 for(i = 0, j = 0; i <= length; i++)
1911 line_w = get_single_text_width(font, &text[j], i - j);
1917 line_w = get_single_text_width(font, &text[j], length - j);
1919 if(line_w > w) w = line_w;
1922 if(i > length && w == 0)
1924 w = get_single_text_width(font, text, length);
1930 int BC_WindowBase::get_text_ascent(int font)
1932 if(get_resources()->use_fontset && top_level->get_fontset(font))
1934 XFontSetExtents *extents;
1936 extents = XExtentsOfFontSet(top_level->get_fontset(font));
1937 return -extents->max_logical_extent.y;
1940 if(get_font_struct(font))
1941 return top_level->get_font_struct(font)->ascent;
1945 case MEDIUM_7SEGMENT:
1946 return get_resources()->medium_7segment[0]->get_h();
1954 int BC_WindowBase::get_text_descent(int font)
1956 if(get_resources()->use_fontset && top_level->get_fontset(font))
1958 XFontSetExtents *extents;
1960 extents = XExtentsOfFontSet(top_level->get_fontset(font));
1961 return (extents->max_logical_extent.height
1962 + extents->max_logical_extent.y);
1965 if(get_font_struct(font))
1966 return top_level->get_font_struct(font)->descent;
1975 int BC_WindowBase::get_text_height(int font, char *text)
1977 if(!text) return get_text_ascent(font) + get_text_descent(font);
1979 int h = 0, i, length = strlen(text);
1980 for(i = 0; i <= length; i++)
1988 return h * (get_text_ascent(font) + get_text_descent(font));
1991 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
1993 if(color_model < 0) color_model = top_level->get_color_model();
1994 return new BC_Bitmap(top_level, w, h, color_model);
1997 int BC_WindowBase::accel_available(int color_model)
1999 if(window_type != MAIN_WINDOW)
2000 return top_level->accel_available(color_model);
2007 result = grab_port_id(this, color_model);
2010 xvideo_port_id = result;
2022 //printf("BC_WindowBase::accel_available 1\n");
2023 result = grab_port_id(this, color_model);
2024 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2027 xvideo_port_id = result;
2032 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2039 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2044 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2046 int numFormats, i, j, k;
2047 unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2049 XvAdaptorInfo *info;
2050 XvImageFormatValues *formats;
2053 if(!get_resources()->use_xvideo) return -1;
2055 // Translate from color_model to X color model
2056 x_color_model = cmodel_bc_to_x(color_model);
2058 // Only local server is fast enough.
2059 if(!resources.use_shm) return -1;
2061 // XV extension is available
2062 if(Success != XvQueryExtension(window->display,
2072 // XV adaptors are available
2073 XvQueryAdaptors(window->display,
2074 DefaultRootWindow(window->display),
2083 // Get adaptor with desired color model
2084 for(i = 0; i < numAdapt && port_id == -1; i++)
2086 /* adaptor supports XvImages */
2087 if(info[i].type & XvImageMask)
2089 formats = XvListImageFormats(window->display,
2092 // for(j = 0; j < numFormats; j++)
2093 // printf("%08x\n", formats[j].id);
2095 for(j = 0; j < numFormats; j++)
2097 /* this adaptor supports the desired format */
2098 if(formats[j].id == x_color_model)
2100 /* Try to grab a port */
2101 for(k = 0; k < info[i].num_ports; k++)
2104 if(Success == XvGrabPort(top_level->display,
2105 info[i].base_id + k,
2108 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2109 port_id = info[i].base_id + k;
2115 if(formats) XFree(formats);
2119 XvFreeAdaptorInfo(info);
2125 int BC_WindowBase::show_window()
2127 XMapWindow(top_level->display, win);
2128 XFlush(top_level->display);
2129 // XSync(top_level->display, 0);
2134 int BC_WindowBase::hide_window()
2136 XUnmapWindow(display, win);
2137 XFlush(top_level->display);
2142 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2144 subwindows->append((BC_SubWindow*)menu_bar);
2146 menu_bar->parent_window = this;
2147 menu_bar->top_level = this->top_level;
2148 menu_bar->initialize();
2152 int BC_WindowBase::close_event() {
2154 return(cancel_button->handle_event());
2159 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2161 //printf("BC_WindowBase::add_subwindow 1\n");
2162 subwindows->append(subwindow);
2163 //printf("BC_WindowBase::add_subwindow 1\n");
2165 // If cancel button is present, use it when closing window
2166 // if (typeid(*subwindow) == typeid(BC_CancelButton))
2167 // but typeid doesn't cover subclasses... we have to be smarter:
2168 if (BC_CancelButton *cb = dynamic_cast<BC_CancelButton *>(subwindow))
2172 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2173 //printf("BC_WindowBase::add_subwindow 1\n");
2175 // parent window must be set before the subwindow initialization
2176 subwindow->parent_window = this;
2177 //printf("BC_WindowBase::add_subwindow 1\n");
2178 subwindow->top_level = this->top_level;
2179 //printf("BC_WindowBase::add_subwindow 1\n");
2181 // Execute derived initialization
2182 subwindow->initialize();
2183 //printf("BC_WindowBase::add_subwindow 2\n");
2188 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2190 return add_subwindow(subwindow);
2193 int BC_WindowBase::flash(int x, int y, int w, int h)
2196 XSetWindowBackgroundPixmap(top_level->display, win, pixmap);
2199 XClearArea(top_level->display, win, x, y, w, h, 0);
2203 XClearWindow(top_level->display, win);
2208 void BC_WindowBase::flush()
2210 XFlush(top_level->display);
2213 void BC_WindowBase::sync_display()
2215 XSync(top_level->display, False);
2218 int BC_WindowBase::get_window_lock()
2220 return top_level->window_lock;
2223 int BC_WindowBase::lock_window()
2225 XLockDisplay(top_level->display);
2226 top_level->window_lock = 1;
2230 int BC_WindowBase::unlock_window()
2232 top_level->window_lock = 0;
2233 XUnlockDisplay(top_level->display);
2237 void BC_WindowBase::set_done(int return_value)
2239 if(window_type != MAIN_WINDOW)
2240 top_level->set_done(return_value);
2244 XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
2246 event.type = ClientMessage;
2247 ptr->message_type = SetDoneXAtom;
2249 XSendEvent(top_level->display, top_level->win, 0, 0, &event);
2250 top_level->return_value = return_value;
2255 int BC_WindowBase::get_w()
2260 int BC_WindowBase::get_h()
2265 int BC_WindowBase::get_x()
2270 int BC_WindowBase::get_y()
2275 int BC_WindowBase::get_root_w(int ignore_dualhead)
2277 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2278 int result = WidthOfScreen(screen_ptr);
2279 // Wider than 16:9, narrower than dual head
2280 if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2284 int BC_WindowBase::get_root_h()
2286 Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2287 return HeightOfScreen(screen_ptr);
2290 // Bottom right corner
2291 int BC_WindowBase::get_x2()
2296 int BC_WindowBase::get_y2()
2301 int BC_WindowBase::get_hidden()
2303 return top_level->hidden;
2306 int BC_WindowBase::cursor_inside()
2308 return (top_level->cursor_x >= 0 &&
2309 top_level->cursor_y >= 0 &&
2310 top_level->cursor_x < w &&
2311 top_level->cursor_y < h);
2314 BC_WindowBase* BC_WindowBase::get_top_level()
2319 BC_WindowBase* BC_WindowBase::get_parent()
2321 return parent_window;
2324 int BC_WindowBase::get_color_model()
2326 return top_level->color_model;
2329 BC_Resources* BC_WindowBase::get_resources()
2331 return &BC_WindowBase::resources;
2334 int BC_WindowBase::get_bg_color()
2339 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2344 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2346 top_level->active_subwindow = subwindow;
2349 int BC_WindowBase::activate()
2354 int BC_WindowBase::deactivate()
2356 if(window_type == MAIN_WINDOW)
2358 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2359 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2360 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2362 top_level->active_menubar = 0;
2363 top_level->active_popup_menu = 0;
2364 top_level->active_subwindow = 0;
2369 int BC_WindowBase::cycle_textboxes(int amount)
2372 BC_WindowBase *new_textbox = 0;
2376 BC_WindowBase *first_textbox = 0;
2377 find_next_textbox(&first_textbox, &new_textbox, result);
2378 if(!new_textbox) new_textbox = first_textbox;
2384 BC_WindowBase *last_textbox = 0;
2385 find_prev_textbox(&last_textbox, &new_textbox, result);
2386 if(!new_textbox) new_textbox = last_textbox;
2390 if(new_textbox != active_subwindow)
2393 new_textbox->activate();
2399 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2401 // Search subwindows for textbox
2402 for(int i = 0; i < subwindows->total && result < 2; i++)
2404 BC_WindowBase *test_subwindow = subwindows->values[i];
2405 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2412 if(!*first_textbox) *first_textbox = this;
2416 if(top_level->active_subwindow == this)
2422 *next_textbox = this;
2429 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2435 if(!*last_textbox) *last_textbox = this;
2439 if(top_level->active_subwindow == this)
2445 *prev_textbox = this;
2450 // Search subwindows for textbox
2451 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2453 BC_WindowBase *test_subwindow = subwindows->values[i];
2454 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2459 BC_Clipboard* BC_WindowBase::get_clipboard()
2461 return top_level->clipboard;
2464 int BC_WindowBase::get_relative_cursor_x()
2466 int abs_x, abs_y, x, y, win_x, win_y;
2467 unsigned int temp_mask;
2470 XQueryPointer(top_level->display,
2480 XTranslateCoordinates(top_level->display,
2492 int BC_WindowBase::get_relative_cursor_y()
2494 int abs_x, abs_y, x, y, win_x, win_y;
2495 unsigned int temp_mask;
2498 XQueryPointer(top_level->display,
2508 XTranslateCoordinates(top_level->display,
2520 int BC_WindowBase::get_abs_cursor_x()
2522 int abs_x, abs_y, win_x, win_y;
2523 unsigned int temp_mask;
2526 XQueryPointer(top_level->display,
2538 int BC_WindowBase::get_abs_cursor_y()
2540 int abs_x, abs_y, win_x, win_y;
2541 unsigned int temp_mask;
2544 XQueryPointer(top_level->display,
2556 int BC_WindowBase::get_cursor_over_window()
2559 if(top_level != this) return top_level->get_cursor_over_window();
2561 int abs_x, abs_y, win_x, win_y;
2562 unsigned int temp_mask;
2564 //printf("BC_WindowBase::get_cursor_over_window 2\n");
2566 XQueryPointer(display,
2575 //printf("BC_WindowBase::get_cursor_over_window 3 %p\n", window_tree);
2577 // Get location in window tree
2578 BC_WindowTree *tree_node = window_tree->get_node(win);
2580 // KDE -> Window is overlapped by a transparent window.
2581 // FVWM -> Window is bordered by different windows.
2582 BC_WindowTree *parent_node = tree_node->parent_tree;
2584 parent_node->parent_tree != window_tree;
2585 tree_node = parent_node, parent_node = parent_node->parent_tree)
2591 for(int i = 0; i < parent_node->windows.total; i++)
2593 if(parent_node->windows.values[i] == tree_node)
2600 XWindowAttributes attr;
2601 XGetWindowAttributes(display,
2602 parent_node->windows.values[i]->win,
2605 // Obstructed by overlapping window.
2606 if(abs_x >= attr.x && abs_x < attr.x + attr.width &&
2607 abs_y >= attr.y && abs_y < attr.y + attr.height &&
2608 !attr.override_redirect)
2616 // Test every window after current node in same parent node.
2617 // Test every parent node after current parent node.
2618 // These are the overlapping windows.
2619 while(parent_node && parent_node != window_tree)
2621 //printf("BC_WindowBase::get_cursor_over_window 4\n");
2623 for(int i = 0; i < parent_node->windows.total; i++)
2625 //printf("BC_WindowBase::get_cursor_over_window 5\n");
2626 if(parent_node->windows.values[i] == tree_node)
2628 //printf("BC_WindowBase::get_cursor_over_window 6\n");
2634 //printf("BC_WindowBase::get_cursor_over_window 7\n");
2635 XWindowAttributes attr;
2636 XGetWindowAttributes(display,
2637 parent_node->windows.values[i]->win,
2640 // Obstructed by overlapping window.
2641 if(abs_x >= attr.x && abs_x < attr.x + attr.width &&
2642 abs_y >= attr.y && abs_y < attr.y + attr.height &&
2643 !attr.override_redirect)
2648 //printf("BC_WindowBase::get_cursor_over_window 8\n");
2650 tree_node = parent_node;
2651 parent_node = tree_node->parent_tree;
2653 //printf("BC_WindowBase::get_cursor_over_window 9\n");
2657 // Didn't find obstruction
2661 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
2666 translate_coordinates(top_level->event_win,
2668 top_level->cursor_x,
2669 top_level->cursor_y,
2675 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
2680 translate_coordinates(top_level->event_win,
2682 top_level->cursor_x,
2683 top_level->cursor_y,
2689 int BC_WindowBase::get_drag_x()
2691 return top_level->drag_x;
2694 int BC_WindowBase::get_drag_y()
2696 return top_level->drag_y;
2699 int BC_WindowBase::get_cursor_x()
2701 return top_level->cursor_x;
2704 int BC_WindowBase::get_cursor_y()
2706 return top_level->cursor_y;
2709 int BC_WindowBase::is_event_win()
2711 return this->win == top_level->event_win;
2714 void BC_WindowBase::set_dragging(int value)
2716 is_dragging = value;
2719 int BC_WindowBase::get_dragging()
2724 int BC_WindowBase::get_buttonpress()
2726 return top_level->button_number;
2729 int BC_WindowBase::get_button_down()
2731 return top_level->button_down;
2734 int BC_WindowBase::alt_down()
2736 return top_level->alt_mask;
2739 int BC_WindowBase::shift_down()
2741 return top_level->shift_mask;
2744 int BC_WindowBase::ctrl_down()
2746 return top_level->ctrl_mask;
2750 int BC_WindowBase::get_keypress()
2752 return top_level->key_pressed;
2755 int BC_WindowBase::get_double_click()
2757 return top_level->double_click;
2760 int BC_WindowBase::get_bgcolor()
2765 int BC_WindowBase::resize_window(int w, int h)
2767 if(window_type == MAIN_WINDOW && !allow_resize)
2769 XSizeHints size_hints;
2770 size_hints.flags = PSize | PMinSize | PMaxSize;
2771 size_hints.width = w;
2772 size_hints.height = h;
2773 size_hints.min_width = w;
2774 size_hints.max_width = w;
2775 size_hints.min_height = h;
2776 size_hints.max_height = h;
2777 XSetNormalHints(top_level->display, win, &size_hints);
2779 XResizeWindow(top_level->display, win, w, h);
2783 XFreePixmap(top_level->display, pixmap);
2784 pixmap = XCreatePixmap(top_level->display, win, w, h, top_level->default_depth);
2786 // Propagate to menubar
2787 for(int i = 0; i < subwindows->total; i++)
2789 subwindows->values[i]->dispatch_resize_event(w, h);
2792 draw_background(0, 0, w, h);
2793 if(top_level == this && get_resources()->recursive_resizing)
2794 resize_history.append(new BC_ResizeCall(w, h));
2798 // The only way for resize events to be propagated is by updating the internal w and h
2799 int BC_WindowBase::resize_event(int w, int h)
2801 if(window_type == MAIN_WINDOW)
2809 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
2813 // Some tools set their own dimensions before calling this, causing the
2814 // resize check to skip.
2818 if(w > 0 && w != this->w)
2824 if(h > 0 && h != this->h)
2830 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
2833 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
2835 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
2837 if(translation_count && window_type == MAIN_WINDOW)
2839 // KDE shifts window right and down.
2840 // FVWM leaves window alone and adds border around it.
2841 XMoveResizeWindow(top_level->display,
2843 x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x,
2844 y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y,
2850 XMoveResizeWindow(top_level->display,
2860 XFreePixmap(top_level->display, pixmap);
2861 pixmap = XCreatePixmap(top_level->display,
2865 top_level->default_depth);
2867 // Propagate to menubar
2868 for(int i = 0; i < subwindows->total; i++)
2870 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
2873 // draw_background(0, 0, w, h);
2879 int BC_WindowBase::set_tooltips(int tooltips_enabled)
2881 get_resources()->tooltips_enabled = tooltips_enabled;
2885 int BC_WindowBase::raise_window()
2887 XRaiseWindow(top_level->display, win);
2888 XFlush(top_level->display);
2892 void BC_WindowBase::set_background(VFrame *bitmap)
2894 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
2896 bg_pixmap = new BC_Pixmap(this,
2899 shared_bg_pixmap = 0;
2900 draw_background(0, 0, w, h);
2903 void BC_WindowBase::set_title(char *text)
2905 XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0);
2906 strcpy(this->title, text);
2910 char* BC_WindowBase::get_title()
2915 int BC_WindowBase::get_toggle_value()
2917 return toggle_value;
2920 int BC_WindowBase::set_icon(VFrame *data)
2922 if(icon_pixmap) delete icon_pixmap;
2923 icon_pixmap = new BC_Pixmap(top_level,
2928 icon_window = new BC_Popup(this,
2931 icon_pixmap->get_w(),
2932 icon_pixmap->get_h(),
2934 1, // All windows are hidden initially
2938 wm_hints.flags = IconPixmapHint | IconMaskHint | IconWindowHint;
2939 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
2940 wm_hints.icon_mask = icon_pixmap->get_alpha();
2941 wm_hints.icon_window = icon_window->win;
2942 // for(int i = 0; i < 1000; i++)
2943 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
2946 XSetWMHints(top_level->display, top_level->win, &wm_hints);
2947 XSync(top_level->display, 0);
2951 int BC_WindowBase::set_w(int w)
2957 int BC_WindowBase::set_h(int h)
2963 int BC_WindowBase::load_defaults(Defaults *defaults)
2965 get_resources()->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
2966 get_resources()->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
2967 get_resources()->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
2968 defaults->get("FILEBOX_FILTER", get_resources()->filebox_filter);
2972 int BC_WindowBase::save_defaults(Defaults *defaults)
2974 defaults->update("FILEBOX_MODE", get_resources()->filebox_mode);
2975 defaults->update("FILEBOX_W", get_resources()->filebox_w);
2976 //printf("BC_ListBox::cursor_motion_event 1 %lld\n", timer.get_difference());
2977 defaults->update("FILEBOX_H", get_resources()->filebox_h);
2978 defaults->update("FILEBOX_FILTER", get_resources()->filebox_filter);
2984 // For some reason XTranslateCoordinates can take a long time to return.
2985 // We work around this by only calling it when the event windows are different.
2986 void BC_WindowBase::translate_coordinates(Window src_w,
2998 *dest_x_return = src_x;
2999 *dest_y_return = src_y;
3003 XTranslateCoordinates(top_level->display,
3011 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3021 #ifdef HAVE_LIBXXF86VM
3022 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3026 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3028 XF86VidModeModeInfo **vm_modelines;
3029 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3030 for (i = 0; i < vm_count; i++) {
3031 if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3034 display = top_level->display;
3035 if (vm_modelines[*vm]->hdisplay == *width)
3039 *width = vm_modelines[*vm]->hdisplay;
3040 *height = vm_modelines[*vm]->vdisplay;
3045 void BC_WindowBase::scale_vm(int vm)
3047 int foo,bar,dotclock;
3048 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3051 XF86VidModeModeInfo **vm_modelines;
3052 XF86VidModeModeLine vml;
3053 XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3054 XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3055 orig_modeline.dotclock = dotclock;
3056 orig_modeline.hdisplay = vml.hdisplay;
3057 orig_modeline.hsyncstart = vml.hsyncstart;
3058 orig_modeline.hsyncend = vml.hsyncend;
3059 orig_modeline.htotal = vml.htotal;
3060 orig_modeline.vdisplay = vml.vdisplay;
3061 orig_modeline.vsyncstart = vml.vsyncstart;
3062 orig_modeline.vsyncend = vml.vsyncend;
3063 orig_modeline.vtotal = vml.vtotal;
3064 orig_modeline.flags = vml.flags;
3065 orig_modeline.privsize = vml.privsize;
3066 // orig_modeline.private = vml.private;
3067 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3068 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3069 XFlush(top_level->display);
3073 void BC_WindowBase::restore_vm()
3075 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3076 XFlush(top_level->display);
3087 GLXContext glXCreateContext(Display *dpy,
3089 GLXContext shareList,
3092 int glXMakeCurrent(Display *dpy,
3096 void glXSwapBuffers(Display *dpy,
3102 void BC_WindowBase::enable_opengl()
3107 XVisualInfo viproto;
3108 XVisualInfo *visinfo;
3111 //printf("BC_WindowBase::enable_opengl 1\n");
3112 viproto.screen = top_level->screen;
3113 visinfo = XGetVisualInfo(top_level->display,
3117 //printf("BC_WindowBase::enable_opengl 1 %p\n", visinfo);
3119 gl_context = glXCreateContext(top_level->display,
3123 //printf("BC_WindowBase::enable_opengl 1\n");
3125 glXMakeCurrent(top_level->display,
3129 unsigned long valuemask = CWEventMask;
3130 XSetWindowAttributes attributes;
3131 attributes.event_mask = DEFAULT_EVENT_MASKS |
3133 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3135 opengl_lock.unlock();
3137 //printf("BC_WindowBase::enable_opengl 2\n");
3140 void BC_WindowBase::disable_opengl()
3142 unsigned long valuemask = CWEventMask;
3143 XSetWindowAttributes attributes;
3144 attributes.event_mask = DEFAULT_EVENT_MASKS;
3145 XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3148 void BC_WindowBase::lock_opengl()
3152 glXMakeCurrent(top_level->display,
3157 void BC_WindowBase::unlock_opengl()
3159 opengl_lock.unlock();
3163 void BC_WindowBase::flip_opengl()
3165 glXSwapBuffers(top_level->display, win);