r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / guicast / bcwindowbase.C
blobe7926504d975aa1c19252de15d0158f3c9e6c0f3
1 #include "bcbitmap.h"
2 #include "bcclipboard.h"
3 #include "bcdisplayinfo.h"
4 #include "bcmenubar.h"
5 #include "bcpixmap.h"
6 #include "bcpopup.h"
7 #include "bcpopupmenu.h"
8 #include "bcrepeater.h"
9 #include "bcresources.h"
10 #include "bcsubwindow.h"
11 #include "bcwindowbase.h"
12 #include "bcbutton.h"
13 #include "colormodels.h"
14 #include "colors.h"
15 #include "cursors.h"
16 #include "defaults.h"
17 #include "fonts.h"
18 #include "keys.h"
19 #include "sizes.h"
20 #include "vframe.h"
21 #include "typeinfo"
23 #ifdef HAVE_GL
24 #include <GL/gl.h>
25 #endif
26 #include <string.h>
28 #include <X11/extensions/Xvlib.h>
29 #include <X11/extensions/shape.h>
31 #include <libintl.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)
39         this->w = w;
40         this->h = h;
44 BC_WindowTree::BC_WindowTree(Display* display, 
45         BC_WindowTree *parent_tree, 
46         Window root_win)
48         Window temp_win;
49         Window *stack;
50         int stack_total;
52         this->display = display;
53         this->win = root_win;
54         this->parent_tree = parent_tree;
56         XQueryTree(display, 
57                 root_win, 
58                 &temp_win, 
59                 &temp_win,              &stack, 
60                 (unsigned int*)&stack_total);
62         for(int i = 0; i < stack_total; i++)
63         {
64                 windows.append(new BC_WindowTree(display, this, stack[i]));
65         }
66         XFree(stack);
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++)
78         {
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];
83                 else
84                 {
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;
89                 }
90         }
94 void BC_WindowTree::dump(int indent, Window caller_win)
96         XWindowAttributes attr;
97         XGetWindowAttributes(display,
98                 win,
99                 &attr);
100         for(int i = 0; i < indent; i++)
101                 printf(" ");
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("**");
105         printf("\n");
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)
130    {
131            restore_vm();   
132    }
133 #endif
135         hide_tooltip();
136         if(window_type != MAIN_WINDOW)
137         {
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);
142         }
144         if(subwindows)
145         {
146                 for(int i = 0; i < subwindows->total; i++)
147                 {
148                         delete subwindows->values[i];
149                 }
150                 delete subwindows;
151         }
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) 
161         {
162                 
163                 XFreeGC(top_level->display, gc);
164                 flush();
165 // Can't close display if another thread is waiting for events
166                 XCloseDisplay(top_level->display);
167                 clipboard->stop_clipboard();
168                 delete clipboard;
169         }
171         resize_history.remove_all_objects();
174 int BC_WindowBase::initialize()
176         window_lock = 0;
177         x = 0; 
178         y = 0; 
179         w = 0; 
180         h = 0;
181         bg_color = -1;
182         top_level = 0;
183         parent_window = 0;
184         subwindows = 0;
185         xvideo_port_id = -1;
186         video_on = 0;
187         motion_events = 0;
188         resize_events = 0;
189         translation_events = 0;
190         ctrl_mask = shift_mask = alt_mask = 0;
191         cursor_x = cursor_y = button_number = 0;
192         button_down = 0;
193         button_pressed = 0;
194         button_time1 = button_time2 = 0;
195         double_click = 0;
196         last_motion_win = 0;
197         key_pressed = 0;
198         active_menubar = 0;
199         active_popup_menu = 0;
200         active_subwindow = 0;
201         bg_pixmap = 0;
202         tooltip_text[0] = 0;
203         persistant_tooltip = 0;
204 //      next_repeat_id = 0;
205         tooltip_popup = 0;
206         tooltip_done = 0;
207         current_font = MEDIUMFONT;
208         current_cursor = ARROW_CURSOR;
209         current_color = BLACK;
210         is_dragging = 0;
211         shared_bg_pixmap = 0;
212         icon_pixmap = 0;
213         window_type = MAIN_WINDOW;
214         translation_count = 0;
215         x_correction = y_correction = 0;
216         temp_bitmap = 0;
217         tooltip_on = 0;
218         temp_cursor = 0;
219         toggle_value = 0;
220         cancel_button = 0;
221 #ifdef HAVE_LIBXXF86VM
222    vm_switched = 0;
223 #endif
224         return 0;
227 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
228                         LeaveWindowMask | \
229                         ButtonPressMask | \
230                         ButtonReleaseMask | \
231                         PointerMotionMask
233 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
234                                 char *title, 
235                                 int x,
236                                 int y,
237                                 int w, 
238                                 int h, 
239                                 int minw, 
240                                 int minh, 
241                                 int allow_resize,
242                                 int private_color, 
243                                 int hide,
244                                 int bg_color,
245                                 char *display_name,
246                                 int window_type,
247                                 BC_Pixmap *bg_pixmap)
249 //printf("BC_WindowBase::create_window 1\n");
250         XSetWindowAttributes attr;
251         unsigned long mask;
252         XSizeHints size_hints;
253         int root_w;
254         int root_h;
255 #ifdef HAVE_LIBXXF86VM
256     int vm;
257 #endif
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);
264 #endif
266         this->x = x;
267         this->y = y;
268         this->w = w;
269         this->h = h;
270         this->bg_color = bg_color;
271         this->window_type = window_type;
272         this->hidden = hide;
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;
284 // Mandatory setup
285         if(window_type == MAIN_WINDOW)
286         {
287                 top_level = this;
288                 parent_window = this;
290 // This function must be the first Xlib
291 // function a multi-threaded program calls
292                 XInitThreads();
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;
311                 init_colors();
312 // get the resources
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();
319                 init_fonts();
320                 init_gc();
321                 init_cursors();
323 // Create the window
324                 mask = CWEventMask | 
325                                 CWBackPixel | 
326                                 CWColormap | 
327                                 CWCursor;
329                 attr.event_mask = EnterWindowMask | 
330                         LeaveWindowMask | 
331                         ButtonPressMask | 
332                         ButtonReleaseMask | 
333                         StructureNotifyMask | 
334                         KeyPressMask | 
335                         PointerMotionMask;
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, 
342                         rootwin, 
343                         this->x, 
344                         this->y, 
345                         this->w, 
346                         this->h, 
347                         0, 
348                         top_level->default_depth, 
349                         InputOutput, 
350                         vis, 
351                         mask, 
352                         &attr);
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)
364                 {
365                         size_hints.flags |= PPosition;
366                         size_hints.x = this->x;
367                         size_hints.y = this->y;
368                 }
370                 XSetStandardProperties(display, 
371                         win, 
372                         title, 
373                         title, 
374                         None, 
375                         0, 
376                         0, 
377                         &size_hints);
378                 get_atoms();
379                 
380                 clipboard = new BC_Clipboard(display_name);
381                 clipboard->start_clipboard();
382         }
384 #ifdef HAVE_LIBXXF86VM
385     if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
386     {
387             scale_vm (vm);
388             vm_switched = 1;
389     }
390 #endif
392 #ifdef HAVE_LIBXXF86VM
393     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
394 #else
395     if(window_type == POPUP_WINDOW)
396 #endif
397         {
398                 mask = CWEventMask | 
399                         CWBackPixel | 
400                         CWColormap | 
401                         CWOverrideRedirect | 
402                         CWSaveUnder | 
403                         CWCursor;
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, 
416                         top_level->rootwin, 
417                         this->x, 
418                         this->y, 
419                         this->w, 
420                         this->h, 
421                         0, 
422                         top_level->default_depth, 
423                         InputOutput, 
424                         top_level->vis, 
425                         mask, 
426                         &attr);
427         }
429         if(window_type == SUB_WINDOW)
430         {
431                 mask = CWBackPixel | CWEventMask;
432                 attr.event_mask = EnterWindowMask | 
433                                 LeaveWindowMask | 
434                                 ButtonPressMask |
435                                 ButtonReleaseMask |
436                                 PointerMotionMask;
437                 attr.background_pixel = top_level->get_color(this->bg_color);
438                 win = XCreateWindow(top_level->display, 
439                         parent_window->win, 
440                         this->x, 
441                         this->y, 
442                         this->w, 
443                         this->h, 
444                         0, 
445                         top_level->default_depth, 
446                         InputOutput, 
447                         top_level->vis, 
448                         mask, 
449                         &attr);
450                 init_window_shape();
451                 XMapWindow(top_level->display, win);
452         }
454 // Create pixmap for all windows
455         pixmap = XCreatePixmap(top_level->display, 
456                 win, 
457                 this->w, 
458                 this->h, 
459                 top_level->default_depth);
461 // Set up options for main window
462         if(window_type == MAIN_WINDOW)
463         {
464                 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
465                 {
466                         this->bg_pixmap = new BC_Pixmap(this, 
467                                 get_resources()->bg_image, 
468                                 PIXMAP_OPAQUE);
469                 }
471                 if(!hidden) show_window();
473         }
475         draw_background(0, 0, this->w, this->h);
476         flash();
478 // Set up options for popup window
479 #ifdef HAVE_LIBXXF86VM
480     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
481 #else
482     if(window_type == POPUP_WINDOW)
483 #endif
484         {
485                 init_window_shape();
486                 if(!hidden) show_window();
487         }
488         return 0;
491 Display* BC_WindowBase::init_display(char *display_name)
493         Display* display;
495         if(display_name && display_name[0] == 0) display_name = NULL;
496         if((display = XOpenDisplay(display_name)) == NULL)
497         {
498                 printf("BC_WindowBase::create_window: cannot connect to X server %s\n", 
499                         display_name);
500                 if(getenv("DISPLAY") == NULL)
501         {
502                         printf("'DISPLAY' environment variable not set.\n");
503                         exit(1);
504                 }
505                 else
506 // Try again with default display.
507                 {
508                         if((display = XOpenDisplay(0)) == NULL)
509                         {
510                                 printf("BC_WindowBase::create_window: cannot connect to default X server.\n");
511                                 exit(1);
512                         }
513                 }
514         }
515         return display;
518 int BC_WindowBase::run_window()
520         done = 0;
521         return_value = 0;
523 //printf("BC_WindowBase::run_window 1\n");
524 // Start tooltips
525         if(window_type == MAIN_WINDOW)
526         {
527 //              tooltip_id = get_repeat_id();
528                 set_repeat(get_resources()->tooltip_delay);
529         }
530 //printf("BC_WindowBase::run_window 2\n");
532         while(!done)
533         {
534                 dispatch_event();
535         }
536 //printf("BC_WindowBase::run_window 3\n");
538         unset_all_repeaters();
539 //printf("BC_WindowBase::run_window 4\n");
540         hide_tooltip();
542         return return_value;
545 int BC_WindowBase::get_key_masks(XEvent &event)
547 // ctrl key down
548         ctrl_mask = (event.xkey.state & ControlMask) ? 1 : 0;
549 // shift key down
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);
553         return 0;
562 int BC_WindowBase::dispatch_event()
564         XEvent event;
565     Window tempwin;
566         KeySym keysym;
567         char keys_return[2];
568         int result;
569         XClientMessageEvent *ptr;
570         int temp;
571         int cancel_resize, cancel_translation;
573         key_pressed = 0;
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))
580         {
581                 XNextEvent(display, &event);
582 // Lock out window deletions
583                 lock_window();
584                 get_key_masks(event);
585         }
586         else
587 // Handle compressed events
588         {
589                 lock_window();
590                 if(resize_events)
591                         dispatch_resize_event(last_resize_w, last_resize_h);
592                 else
593                 if(motion_events)
594                         dispatch_motion_event();
595                 else
596                 if(translation_events)
597                         dispatch_translation_event();
599                 unlock_window();
600                 return 0;
601         }
603 //printf("BC_WindowBase::dispatch_event 2 %s %d\n", title, event.type);
604         switch(event.type)
605         {
606                 case ClientMessage:
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)
616                 {
617                                 close_event();
618                         }
619                         else
620                         if(ptr->message_type == RepeaterXAtom)
621                         {
622                                 dispatch_repeat_event(ptr->data.l[0]);
623 // Make sure the repeater still exists.
624 //                              for(int i = 0; i < repeaters.total; i++)
625 //                              {
626 //                                      if(repeaters.values[i]->repeat_id == ptr->data.l[0])
627 //                                      {
628 //                                              dispatch_repeat_event_master(ptr->data.l[0]);
629 //                                              break;
630 //                                      }
631 //                              }
632                         }
633                         else
634                         if(ptr->message_type == SetDoneXAtom)
635                         {
636                                 done = 1;
637                         }
638                         break;
640                 case ButtonPress:
641                         cursor_x = event.xbutton.x;
642                         cursor_y = event.xbutton.y;
643                         button_number = event.xbutton.button;
644                         event_win = event.xany.window;
645                         button_down = 1;
646                         button_pressed = event.xbutton.button;
647                         button_time1 = button_time2;
648                         button_time2 = event.xbutton.time;
649                         drag_x = cursor_x;
650                         drag_y = cursor_y;
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)
658                         {
659 // Ignore triple clicks
660                                 double_click = 1; 
661                                 button_time2 = button_time1 = 0; 
662                         }
663                         else 
664                                 double_click = 0;
666                         dispatch_button_press();
667                         break;
669                 case ButtonRelease:
670                         button_number = event.xbutton.button;
671                         event_win = event.xany.window;
672                         button_down = 0;
674                         dispatch_button_release();
675                         break;
677                 case Expose:
678                         event_win = event.xany.window;
679                         dispatch_expose_event();
680                         break;
682                 case MotionNotify:
683 // Dispatch previous motion event if this is a subsequent motion from a different window
685 //Timer timer;
686 //timer.update();
688                         if(motion_events && last_motion_win != event.xany.window)
689                                 dispatch_motion_event();
691 // Buffer the current motion
692                         motion_events = 1;
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());
698                         break;
700                 case ConfigureNotify:
701                         XTranslateCoordinates(top_level->display, 
702                                 top_level->win, 
703                                 top_level->rootwin, 
704                                 0, 
705                                 0, 
706                                 &last_translate_x, 
707                                 &last_translate_y, 
708                                 &tempwin);
709                         last_resize_w = event.xconfigure.width;
710                         last_resize_h = event.xconfigure.height;
712                         cancel_resize = 0;
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++)
717                         {
718                                 if(resize_history.values[i]->w == last_resize_w &&
719                                         resize_history.values[i]->h == last_resize_h)
720                                 {
721                                         delete resize_history.values[i];
722                                         resize_history.remove_number(i);
723                                         cancel_resize = 1;
724                                 }
725                         }
727                         if(last_resize_w == w && last_resize_h == h)
728                                 cancel_resize = 1;
730                         if(!cancel_resize)
731                         {
732                                 resize_events = 1;
733                         }
735                         if((last_translate_x == x && last_translate_y == y))
736                                 cancel_translation = 1;
738                         if(!cancel_translation)
739                         {
740                                 translation_events = 1;
741                         }
743                         translation_count++;
744                         break;
746                 case KeyPress:
747                         keys_return[0] = 0;
748                         XLookupString((XKeyEvent*)&event, keys_return, 1, &keysym, 0);
750 // block out control keys
751                         if(keysym > 0xffe0 && keysym < 0xffff) break;
752                         switch(keysym)
753                         {
754 // block out extra keys
755                         case XK_Alt_L:      
756                         case XK_Alt_R:      
757                         case XK_Shift_L:    
758                         case XK_Shift_R:    
759                         case XK_Control_L:  
760                         case XK_Control_R:  
761                                         key_pressed = 0;         
762                                         break;
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;
774                         case XK_Tab:
775                                         if(shift_down())
776                                                 key_pressed = LEFTTAB;
777                                         else
778                                                 key_pressed = TAB;       
779                                         break;
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;
787 // number pad
788                                 case XK_KP_Enter:       key_pressed = KPENTER;   break;
789                                 case XK_KP_Add:         key_pressed = KPPLUS;    break;
790                                 case XK_KP_1:
791                                 case XK_KP_End:         key_pressed = KP1;       break;
792                                 case XK_KP_2:
793                                 case XK_KP_Down:        key_pressed = KP2;       break;
794                                 case XK_KP_3:
795                                 case XK_KP_Page_Down:   key_pressed = KP3;       break;
796                                 case XK_KP_4:
797                                 case XK_KP_Left:        key_pressed = KP4;       break;
798                                 case XK_KP_5:
799                                 case XK_KP_Begin:       key_pressed = KP5;       break;
800                                 case XK_KP_6:
801                                 case XK_KP_Right:       key_pressed = KP6;       break;
802                                 case XK_KP_0:
803                                 case XK_KP_Insert:      key_pressed = KPINS;     break;
804                                 case XK_KP_Decimal:
805                                 case XK_KP_Delete:      key_pressed = KPDEL;     break;
806                         default:           
807                                         //key_pressed = keys_return[0]; 
808                                         key_pressed = keysym & 0xff;
809                                         break;
810                         }
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
815                         if(!result)
816                         {
817                                 if(key_pressed == 'w' ||
818                                         key_pressed == 'W')
819                                 {
820                                         close_event();
821                                 }
822                         }
823                         break;
825                 case LeaveNotify:
826                         event_win = event.xany.window;
827                         dispatch_cursor_leave();
828                         break;
830                 case EnterNotify:
831                         event_win = event.xany.window;
832                         cursor_x = event.xcrossing.x;
833                         cursor_y = event.xcrossing.y;
834                         dispatch_cursor_enter();
835                         break;
836         }
838 //printf("BC_WindowBase::dispatch_event 3 %s\n", title);
839         unlock_window();
840         return 0;
843 int BC_WindowBase::dispatch_expose_event()
845         int result = 0;
846         for(int i = 0; i < subwindows->total && !result; i++)
847         {
848                 result = subwindows->values[i]->dispatch_expose_event();
849         }
851 // Propagate to user
852         if(!result) expose_event();
853         return result;
856 int BC_WindowBase::dispatch_resize_event(int w, int h)
858         if(window_type == MAIN_WINDOW)
859         {
860                 resize_events = 0;
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, 
865                         win, 
866                         w, 
867                         h, 
868                         top_level->default_depth);
869                 clear_box(0, 0, w, h);
870         }
872 // Propagate to subwindows
873         for(int i = 0; i < subwindows->total; i++)
874         {
875                 subwindows->values[i]->dispatch_resize_event(w, h);
876         }
878 // Propagate to user
879         resize_event(w, h);
881         if(window_type == MAIN_WINDOW)
882         {
883                 this->w = w;
884                 this->h = h;
885         }
886         return 0;
889 int BC_WindowBase::dispatch_translation_event()
891         translation_events = 0;
892         if(window_type == MAIN_WINDOW)
893         {
894                 prev_x = x;
895                 prev_y = y;
896                 x = last_translate_x;
897                 y = last_translate_y;
898 // Correct for window manager offsets
899                 x -= x_correction;
900                 y -= y_correction;
901         }
903         for(int i = 0; i < subwindows->total; i++)
904         {
905                 subwindows->values[i]->dispatch_translation_event();
906         }
908 //printf("BC_WindowBase::dispatch_translation_event 1 %p\n", this);
909         translation_event();
910         return 0;
913 int BC_WindowBase::dispatch_motion_event()
915         int result = 0;
917         if(top_level == this)
918         {
919                 event_win = last_motion_win;
920                 motion_events = 0;
922 //printf("BC_WindowBase::dispatch_motion_event 1\n");
923 // Test for grab
924                 if(get_button_down() && !active_menubar && !active_popup_menu)
925                 {
926 //printf("BC_WindowBase::dispatch_motion_event 2\n");
927                         if(!result) 
928                         {
929                                 cursor_x = last_motion_x;
930                                 cursor_y = last_motion_y;
931                                 result = dispatch_drag_motion();
932                         }
934                         if(!result && 
935                                 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 || 
936                                 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
937                         {
938                                 cursor_x = drag_x;
939                                 cursor_y = drag_y;
940 //                              if(window_tree)
941 //                              {
942 //                                      delete window_tree;
943 //                                      window_tree = 0;
944 //                              }
945 //                              if(!window_tree)
946 //                              {
947 //                                      window_tree = new BC_WindowTree(display, 
948 //                                              0, 
949 //                                              rootwin);
950 // //window_tree->dump(0, win);
951 //                              }
953                                 result = dispatch_drag_start();
954                         }
955                 }
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");
964         }
966 //printf("BC_WindowBase::dispatch_motion_event 5\n");
967         for(int i = 0; i < subwindows->total && !result; i++)
968         {
969                 result = subwindows->values[i]->dispatch_motion_event();
970         }
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");
975         return result;
978 int BC_WindowBase::dispatch_keypress_event()
980         int result = 0;
981         if(top_level == this)
982         {
983                 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
984         }
986         for(int i = 0; i < subwindows->total && !result; i++)
987         {
988                 result = subwindows->values[i]->dispatch_keypress_event();
989         }
991         if(!result) result = keypress_event();
993         return result;
996 int BC_WindowBase::dispatch_button_press()
998         int result = 0;
999         if(top_level == this)
1000         {
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();
1004         }
1006         for(int i = 0; i < subwindows->total && !result; i++)
1007         {
1008                 result = subwindows->values[i]->dispatch_button_press();
1009         }
1011         if(!result) result = button_press_event();
1013         return result;
1016 int BC_WindowBase::dispatch_button_release()
1018         int result = 0;
1019         if(top_level == this)
1020         {
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();
1028         }
1029 //printf("BC_WindowBase::dispatch_button_release 4 %d\n", result);
1031         for(int i = 0; i < subwindows->total && !result; i++)
1032         {
1033                 result = subwindows->values[i]->dispatch_button_release();
1034         }
1035 //printf("BC_WindowBase::dispatch_button_release 5 %d\n", result);
1037         if(!result)
1038         {
1039                 result = button_release_event();
1040         }
1041 //printf("BC_WindowBase::dispatch_button_release 6 %d\n", result);
1043         return result;
1046 // int BC_WindowBase::dispatch_repeat_event_master(long duration)
1047 // {
1048 //      int result = 0;
1049 //      BC_Repeater *repeater;
1050 // 
1051 // // Unlock the repeater if it still exists.
1052 //      for(int i = 0; i < repeaters.total; i++)
1053 //      {
1054 //              if(repeaters.values[i]->repeat_id == repeat_id)
1055 //              {
1056 //                      repeater = repeaters.values[i];
1057 //                      if(repeater->interrupted)
1058 //                      {
1059 // // Disregard
1060 //                              if(interrupt_now)
1061 //                              {
1062 // // Delete now
1063 //                                      repeater->join();
1064 //                                      repeaters.remove(repeater);
1065 //                                      delete repeater;
1066 //                              }
1067 //                      }
1068 //                      else
1069 //                      {
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();
1075 //                      }
1076 //                      i = repeaters.total;
1077 //              }
1078 //      }
1079 // 
1080 //      return result;
1081 // }
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++)
1088         {
1089                 subwindows->values[i]->dispatch_repeat_event(duration);
1090         }
1091         repeat_event(duration);
1093 // Unlock next signal
1094         if(window_type == MAIN_WINDOW)
1095         {
1096                 for(int i = 0; i < repeaters.total; i++)
1097                 {
1098                         if(repeaters.values[i]->delay == duration)
1099                         {
1100                                 repeaters.values[i]->repeat_lock.unlock();
1101                         }
1102                 }
1103         }
1105         return 0;
1108 int BC_WindowBase::dispatch_cursor_leave()
1110         for(int i = 0; i < subwindows->total; i++)
1111         {
1112                 subwindows->values[i]->dispatch_cursor_leave();
1113         }
1114         cursor_leave_event();
1115         return 0;
1118 int BC_WindowBase::dispatch_cursor_enter()
1120         int result = 0;
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++)
1129         {
1130                 result = subwindows->values[i]->dispatch_cursor_enter();
1131         }
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();
1136         return result;
1139 int BC_WindowBase::cursor_enter_event()
1141 //printf("BC_WindowBase::cursor_enter_event 1 %s %p\n", title, this);
1142         return 0;
1145 int BC_WindowBase::cursor_leave_event()
1147 //printf("BC_WindowBase::cursor_leave_event 1 %s %p\n", title, this);
1148         return 0;
1151 int BC_WindowBase::dispatch_drag_start()
1153         int result = 0;
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();
1157         
1158         for(int i = 0; i < subwindows->total && !result; i++)
1159         {
1160                 result = subwindows->values[i]->dispatch_drag_start();
1161         }
1163         if(!result) result = is_dragging = drag_start_event();
1164         return result;
1167 int BC_WindowBase::dispatch_drag_stop()
1169         int result = 0;
1171         for(int i = 0; i < subwindows->total && !result; i++)
1172         {
1173                 result = subwindows->values[i]->dispatch_drag_stop();
1174         }
1176         if(is_dragging && !result) 
1177         {
1178                 drag_stop_event();
1179                 is_dragging = 0;
1180                 result = 1;
1181         }
1183         return result;
1186 int BC_WindowBase::dispatch_drag_motion()
1188         int result = 0;
1189         for(int i = 0; i < subwindows->total && !result; i++)
1190         {
1191                 result = subwindows->values[i]->dispatch_drag_motion();
1192         }
1193         
1194         if(is_dragging && !result)
1195         {
1196                 drag_motion_event();
1197                 result = 1;
1198         }
1199         
1200         return result;
1207 int BC_WindowBase::show_tooltip(int w, int h)
1209         Window tempwin;
1211         if(!tooltip_on && get_resources()->tooltips_enabled)
1212         {
1213                 int i, j, x, y;
1214                 top_level->hide_tooltip();
1216                 tooltip_on = 1;
1217                 if(w < 0)
1218                         w = get_text_width(MEDIUMFONT, tooltip_text);
1220                 if(h < 0)
1221                         h = get_text_height(MEDIUMFONT, tooltip_text);
1223                 w += TOOLTIP_MARGIN * 2;
1224                 h += TOOLTIP_MARGIN * 2;
1226                 XTranslateCoordinates(top_level->display, 
1227                                 win, 
1228                                 top_level->rootwin, 
1229                                 get_w(), 
1230                                 get_h(), 
1231                                 &x, 
1232                                 &y, 
1233                                 &tempwin);
1234                 tooltip_popup = new BC_Popup(top_level, 
1235                                         x,
1236                                         y,
1237                                         w, 
1238                                         h, 
1239                                         get_resources()->tooltip_bg_color);
1241                 draw_tooltip();
1242                 tooltip_popup->set_font(MEDIUMFONT);
1243                 tooltip_popup->flash();
1244         }
1245         return 0;
1248 int BC_WindowBase::hide_tooltip()
1250         if(subwindows)
1251                 for(int i = 0; i < subwindows->total; i++)
1252                 {
1253                         subwindows->values[i]->hide_tooltip();
1254                 }
1256         if(tooltip_on)
1257         {
1258                 tooltip_on = 0;
1259                 delete tooltip_popup;
1260                 tooltip_popup = 0;
1261         }
1262         return 0;
1265 int BC_WindowBase::set_tooltip(char *text)
1267         strcpy(this->tooltip_text, text);
1268 // Update existing tooltip if it is visible
1269         if(tooltip_on)
1270         {
1271                 draw_tooltip();
1272                 tooltip_popup->flash();
1273         }
1274         return 0;
1277 // signal the event handler to repeat
1278 int BC_WindowBase::set_repeat(int64_t duration)
1280         if(duration <= 0)
1281         {
1282                 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1283                 return 0;
1284         }
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++)
1290         {
1291 // Already exists
1292                 if(repeaters.values[i]->delay == duration)
1293                 {
1294                         repeaters.values[i]->start_repeating();
1295                         return 0;
1296                 }
1297         }
1299         BC_Repeater *repeater = new BC_Repeater(this, duration);
1300         repeaters.append(repeater);
1302     repeater->start_repeating();
1303         return 0;
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++)
1312         {
1313                 if(repeaters.values[i]->delay == duration)
1314                 {
1315                         repeaters.values[i]->stop_repeating();
1316                 }
1317         }
1318         return 0;
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++)
1326         {
1327                 repeaters.values[i]->stop_repeating();
1328         }
1329 //printf("BC_WindowBase::unset_all_repeaters 1\n");
1330         repeaters.remove_all_objects();
1331 //printf("BC_WindowBase::unset_all_repeaters 2\n");
1332         return 0;
1335 // long BC_WindowBase::get_repeat_id()
1336 // {
1337 //      return top_level->next_repeat_id++;
1338 // }
1340 int BC_WindowBase::arm_repeat(int64_t duration)
1342         XEvent event;
1343         XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
1344         ptr->type = ClientMessage;
1345         ptr->message_type = RepeaterXAtom;
1346         ptr->format = 32;
1347         ptr->data.l[0] = duration;
1349         XSendEvent(display, win, 0, 0, &event);
1350         flush();
1351         return 0;
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);
1361         return 0;
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)
1383         int color_model;
1384         switch(depth)
1385         {
1386                 case 8:
1387                         color_model = BC_RGB8;
1388                         break;
1389                 case 16:
1390                         color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1391                         break;
1392                 case 24:
1393                         color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1394                         break;
1395                 case 32:
1396                         color_model = server_byte_order ? BC_BGR8888 : BC_RGBA8888;
1397                         break;
1398         }
1399         return color_model;
1402 int BC_WindowBase::init_colors()
1404         total_colors = 0;
1405         current_color_value = current_color_pixel = 0;
1407 // Get the real depth
1408         char *data = 0;
1409         XImage *ximage;
1410         ximage = XCreateImage(top_level->display, 
1411                                         top_level->vis, 
1412                                         top_level->default_depth, 
1413                                         ZPixmap, 
1414                                         0, 
1415                                         data, 
1416                                         16, 
1417                                         16, 
1418                                         8, 
1419                                         0);
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
1425         switch(color_model)
1426         {
1427                 case BC_RGB8:
1428                         if(private_color)
1429                         {
1430                                 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1431                                 create_private_colors();
1432                         }
1433                         else
1434                         {
1435                                 cmap = DefaultColormap(display, screen);
1436                                 create_shared_colors();
1437                         }
1439                         allocate_color_table();
1440                         break;
1442                 default:
1443                         cmap = DefaultColormap(display, screen);
1444                         break;
1445         }
1446         return 0;
1449 int BC_WindowBase::create_private_colors()
1451         int color;
1452         total_colors = 256;
1454         for(int i = 0; i < 255; i++)
1455         {
1456                 color = (i & 0xc0) << 16;
1457                 color += (i & 0x38) << 10;
1458                 color += (i & 0x7) << 5;
1459                 color_table[i][0] = color;
1460         }
1461         create_shared_colors();        // overwrite the necessary colors on the table
1462         return 0;
1466 int BC_WindowBase::create_color(int color)
1468         if(total_colors == 256)
1469         {
1470 // replace the closest match with an exact match
1471                 color_table[get_color_rgb8(color)][0] = color;
1472         }
1473         else
1474         {
1475 // add the color to the table
1476                 color_table[total_colors][0] = color;
1477                 total_colors++;
1478         }
1479         return 0;
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);  
1502         create_color(PINK);
1503         create_color(RED);     
1505         create_color(LTBLUE);  
1506         create_color(BLUE);    
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); 
1518         return 0;
1521 int BC_WindowBase::allocate_color_table()
1523         int red, green, blue, color;
1524         int result;
1525         XColor col;
1527         for(int i = 0; i < total_colors; i++)
1528         {
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;
1541         }
1543         XInstallColormap(display, cmap);
1544         return 0;
1547 int BC_WindowBase::init_window_shape()
1549         if(bg_pixmap && bg_pixmap->use_alpha()) 
1550         {
1551                 XShapeCombineMask(top_level->display,
1552                 this->win,
1553                 ShapeBounding,
1554                 0,
1555                 0,
1556                 bg_pixmap->get_alpha(),
1557                 ShapeSet);
1558         }
1559         return 0;
1563 int BC_WindowBase::init_gc()
1565         unsigned long gcmask;
1566         gcmask = GCFont | GCGraphicsExposures;
1568         XGCValues gcvalues;
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);
1572         return 0;
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)
1587         {
1588                 char **m, *d;
1589                 int n;
1591 // FIXME: should check the m,d,n values
1592                 if((largefontset = XCreateFontSet(display, resources.large_fontset,
1593                                                                   &m, &n, &d)) == 0)
1594                largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1595                 if((mediumfontset = XCreateFontSet(display, resources.medium_fontset,
1596                                                                   &m, &n, &d)) == 0)
1597                mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1598                 if((smallfontset = XCreateFontSet(display, resources.small_fontset,
1599                                                                   &m, &n, &d)) == 0)
1600                smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1602                 if(largefontset && mediumfontset && smallfontset)
1603                 {
1604                         curr_fontset = mediumfontset;
1605                         get_resources()->use_fontset = 1;
1606                 }
1607                 else
1608                 {
1609                         curr_fontset = 0;
1610                         get_resources()->use_fontset = 0;
1611                 }
1612         }
1614         return 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;
1623         switch(color_model)
1624         {
1625                 case BC_RGB8:
1626                         if(private_color)
1627                         {
1628                                 return get_color_rgb8(color);
1629                         }
1630                         else
1631                         {
1632 // test last color looked up
1633                                 if(current_color_value == color) return current_color_pixel;
1635 // look up in table
1636                                 current_color_value = color;
1637                                 for(i = 0; i < total_colors; i++)
1638                                 {
1639                                         if(color_table[i][0] == color)
1640                                         {
1641                                                 current_color_pixel = color_table[i][1];
1642                                                 return current_color_pixel;
1643                                         }
1644                                 }
1646 // find nearest match
1647                                 difference = 0xFFFFFF;
1649                                 for(i = 0, result = 0; i < total_colors; i++)
1650                                 {
1651                                         test = abs((int)(color_table[i][0] - color));
1653                                         if(test < difference) 
1654                                         {
1655                                                 current_color_pixel = color_table[i][1]; 
1656                                                 difference = test;
1657                                         }
1658                                 }
1660                                 return current_color_pixel;
1661                         }
1662                         break;  
1664                 case BC_RGB565:
1665                         return get_color_rgb16(color);
1666                         break;
1668                 case BC_BGR565:
1669                         return get_color_bgr16(color);
1670                         break;
1672                 case BC_RGB888:
1673                 case BC_BGR888:
1674                         if(client_byte_order == server_byte_order)
1675                                 return color;
1676                         else
1677                                 get_color_bgr24(color);
1678                         break;
1680                 default:
1681                         return color;
1682                         break;  
1683         }
1684         return 0;
1687 int BC_WindowBase::get_color_rgb8(int color)
1689         int pixel;
1691         pixel = (color & 0xc00000) >> 16;
1692         pixel += (color & 0xe000) >> 10;
1693         pixel += (color & 0xe0) >> 5;
1694         return pixel;
1697 int64_t BC_WindowBase::get_color_rgb16(int color)
1699         int64_t result;
1700         result = (color & 0xf80000) >> 8;
1701         result += (color & 0xfc00) >> 5;
1702         result += (color & 0xf8) >> 3;
1703         
1704         return result;
1707 int64_t BC_WindowBase::get_color_bgr16(int color)
1709         int64_t result;
1710         result = (color & 0xf80000) >> 19;
1711         result += (color & 0xfc00) >> 5;
1712         result += (color & 0xf8) << 8;
1714         return result;
1717 int64_t BC_WindowBase::get_color_bgr24(int color)
1719         int64_t result;
1720         result = (color & 0xff) << 16;
1721         result += (color & 0xff00);
1722         result += (color & 0xff0000) >> 16;
1723         return result;
1726 int BC_WindowBase::video_is_on()
1728         return video_on;
1731 void BC_WindowBase::start_video()
1733         video_on = 1;
1734         set_color(BLACK);
1735         draw_box(0, 0, get_w(), get_h());
1736         flash();
1739 void BC_WindowBase::stop_video()
1741         video_on = 0;
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, 
1755                 top_level->gc, 
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)
1771         switch(cursor)
1772         {
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;
1786         }
1787         return 0;
1790 void BC_WindowBase::set_cursor(int cursor)
1792         XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
1793         current_cursor = cursor;
1794         flush();
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;
1802         flush();
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;
1813         
1814         switch(font)
1815         {
1816                 case MEDIUMFONT: return top_level->mediumfont; break;
1817                 case SMALLFONT:  return top_level->smallfont;  break;
1818                 case LARGEFONT:  return top_level->largefont;  break;
1819         }
1820         return 0;
1824 void BC_WindowBase::set_font(int font)
1826         if(get_font_struct(font))
1827         {
1828                 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
1829         }
1831         top_level->current_font = font;
1832         if(get_resources()->use_fontset) set_fontset(font);
1833         return;
1837 XFontSet BC_WindowBase::get_fontset(int font)
1839         XFontSet fs = 0;
1841         if(get_resources()->use_fontset)
1842         {
1843                 switch(font)
1844                 {
1845                                 case SMALLFONT:  fs = top_level->smallfontset; break;
1846                                 case LARGEFONT:  fs = top_level->largefontset; break;
1847                                 case MEDIUMFONT: fs = top_level->mediumfontset; break;
1848                 }
1849         }
1851         return fs;
1854 XFontSet BC_WindowBase::get_curr_fontset(void)
1856         if(get_resources()->use_fontset)
1857                 return curr_fontset;
1858         return 0;
1861 void BC_WindowBase::set_fontset(int font)
1863         XFontSet fs = 0;
1865         if(get_resources()->use_fontset)
1866         {
1867                 switch(font)
1868                 {
1869                         case SMALLFONT:  fs = top_level->smallfontset; break;
1870                         case LARGEFONT:  fs = top_level->largefontset; break;
1871                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
1872                 }
1873         }
1875         curr_fontset = fs;
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);
1882         else
1883         if(get_font_struct(font)) 
1884                 return XTextWidth(get_font_struct(font), text, length);
1885         else
1886         {
1887                 int w = 0;
1888                 switch(font)
1889                 {
1890                         case MEDIUM_7SEGMENT:
1891                                 return get_resources()->medium_7segment[0]->get_w() * length;
1892                                 break;
1894                         default:
1895                                 return 0;
1896                 }
1897                 return w;
1898         }
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++)
1907         {
1908                 line_w = 0;
1909                 if(text[i] == '\n')
1910                 {
1911                         line_w = get_single_text_width(font, &text[j], i - j);
1912                         j = i + 1;
1913                 }
1914                 else
1915                 if(text[i] == 0)
1916                 {
1917                         line_w = get_single_text_width(font, &text[j], length - j);
1918                 }
1919                 if(line_w > w) w = line_w;
1920         }
1922         if(i > length && w == 0)
1923         {
1924                 w = get_single_text_width(font, text, length);
1925         }
1927         return w;
1930 int BC_WindowBase::get_text_ascent(int font)
1932         if(get_resources()->use_fontset && top_level->get_fontset(font))
1933         {
1934         XFontSetExtents *extents;
1936         extents = XExtentsOfFontSet(top_level->get_fontset(font));
1937         return -extents->max_logical_extent.y;
1938         }
1939         else
1940         if(get_font_struct(font))
1941                 return top_level->get_font_struct(font)->ascent;
1942         else
1943         switch(font)
1944         {
1945                 case MEDIUM_7SEGMENT:
1946                         return get_resources()->medium_7segment[0]->get_h();
1947                         break;
1949                 default:
1950                         return 0;
1951         }
1954 int BC_WindowBase::get_text_descent(int font)
1956     if(get_resources()->use_fontset && top_level->get_fontset(font))
1957     {
1958         XFontSetExtents *extents;
1960         extents = XExtentsOfFontSet(top_level->get_fontset(font));
1961         return (extents->max_logical_extent.height
1962                         + extents->max_logical_extent.y);
1963     }
1964     else
1965         if(get_font_struct(font))
1966                 return top_level->get_font_struct(font)->descent;
1967         else
1968         switch(font)
1969         {
1970                 default:
1971                         return 0;
1972         }
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++)
1981         {
1982                 if(text[i] == '\n')
1983                         h++;
1984                 else
1985                 if(text[i] == 0)
1986                         h++;
1987         }
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);
2002         int result = 0;
2004         switch(color_model)
2005         {
2006                 case BC_YUV420P:
2007                         result = grab_port_id(this, color_model);
2008                         if(result >= 0)
2009                         {
2010                                 xvideo_port_id = result;
2011                                 result = 1;
2012                         }
2013                         else
2014                                 result = 0;
2015                         break;
2017                 case BC_YUV422P:
2018                         result = 0;
2019                         break;
2021                 case BC_YUV422:
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);
2025                         if(result >= 0)
2026                         {
2027                                 xvideo_port_id = result;
2028                                 result = 1;
2029                         }
2030                         else
2031                                 result = 0;
2032 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2033                         break;
2035                 default:
2036                         result = 0;
2037                         break;
2038         }
2039 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2040         return 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;
2048         int port_id = -1;
2049     XvAdaptorInfo *info;
2050     XvImageFormatValues *formats;
2051         int x_color_model;
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, 
2063                                   &ver, 
2064                                   &rev, 
2065                                   &reqBase, 
2066                                   &eventBase, 
2067                                   &errorBase))
2068     {
2069                 return -1;
2070     }
2072 // XV adaptors are available
2073         XvQueryAdaptors(window->display, 
2074                 DefaultRootWindow(window->display), 
2075                 &numAdapt, 
2076                 &info);
2078         if(!numAdapt)
2079         {
2080                 return -1;
2081         }
2083 // Get adaptor with desired color model
2084     for(i = 0; i < numAdapt && port_id == -1; i++)
2085     {
2086 /* adaptor supports XvImages */
2087                 if(info[i].type & XvImageMask) 
2088                 {  
2089                 formats = XvListImageFormats(window->display, 
2090                                                         info[i].base_id, 
2091                                                         &numFormats);
2092 // for(j = 0; j < numFormats; j++)
2093 //      printf("%08x\n", formats[j].id);
2095                 for(j = 0; j < numFormats; j++) 
2096                 {
2097 /* this adaptor supports the desired format */
2098                                 if(formats[j].id == x_color_model)
2099                                 {
2100 /* Try to grab a port */
2101                                         for(k = 0; k < info[i].num_ports; k++)
2102                                         {
2103 /* Got a port */
2104                                                 if(Success == XvGrabPort(top_level->display, 
2105                                                         info[i].base_id + k, 
2106                                                         CurrentTime))
2107                                                 {
2108 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2109                                                         port_id = info[i].base_id + k;
2110                                                         break;
2111                                                 }
2112                                         }
2113                                 }
2114                         }
2115                 if(formats) XFree(formats);
2116                 }
2117         }
2119     XvFreeAdaptorInfo(info);
2121         return port_id;
2125 int BC_WindowBase::show_window() 
2127         XMapWindow(top_level->display, win); 
2128         XFlush(top_level->display);
2129 //      XSync(top_level->display, 0);
2130         hidden = 0; 
2131         return 0;
2134 int BC_WindowBase::hide_window() 
2136         XUnmapWindow(display, win); 
2137         XFlush(top_level->display);
2138         hidden = 1; 
2139         return 0;
2142 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2144         subwindows->append((BC_SubWindow*)menu_bar);
2145         
2146         menu_bar->parent_window = this;
2147         menu_bar->top_level = this->top_level;
2148         menu_bar->initialize();
2149         return menu_bar;
2152 int BC_WindowBase::close_event() {
2153         if (cancel_button) 
2154                 return(cancel_button->handle_event());
2155         else
2156                 return (0);
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))
2169         {
2170                 cancel_button = cb;
2171         }
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");
2184         return subwindow;
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)
2195         set_opaque();
2196         XSetWindowBackgroundPixmap(top_level->display, win, pixmap);
2197         if(x >= 0)
2198         {
2199                 XClearArea(top_level->display, win, x, y, w, h, 0);
2200         }
2201         else
2202         {
2203                 XClearWindow(top_level->display, win);
2204         }
2205         return 0;
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;
2227         return 0;
2230 int BC_WindowBase::unlock_window() 
2232         top_level->window_lock = 0;
2233         XUnlockDisplay(top_level->display); 
2234         return 0;
2237 void BC_WindowBase::set_done(int return_value)
2239         if(window_type != MAIN_WINDOW) 
2240                 top_level->set_done(return_value);
2241         else
2242         {
2243                 XEvent event;
2244                 XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
2246                 event.type = ClientMessage;
2247                 ptr->message_type = SetDoneXAtom;
2248                 ptr->format = 32;
2249                 XSendEvent(top_level->display, top_level->win, 0, 0, &event);
2250                 top_level->return_value = return_value;
2251                 flush();
2252         }
2255 int BC_WindowBase::get_w()
2257         return w;
2260 int BC_WindowBase::get_h()
2262         return h;
2265 int BC_WindowBase::get_x()
2267         return x;
2270 int BC_WindowBase::get_y()
2272         return 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;
2281         return result;
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()
2293         return w + x;
2296 int BC_WindowBase::get_y2()
2298         return y + h;
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()
2316         return 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()
2336         return bg_color;
2339 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2341         return bg_pixmap;
2344 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2346         top_level->active_subwindow = subwindow;
2349 int BC_WindowBase::activate()
2351         return 0;
2354 int BC_WindowBase::deactivate()
2356         if(window_type == MAIN_WINDOW)
2357         {
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;
2365         }
2366         return 0;
2369 int BC_WindowBase::cycle_textboxes(int amount)
2371         int result = 0;
2372         BC_WindowBase *new_textbox = 0;
2374         if(amount > 0)
2375         {
2376                 BC_WindowBase *first_textbox = 0;
2377                 find_next_textbox(&first_textbox, &new_textbox, result);
2378                 if(!new_textbox) new_textbox = first_textbox;
2379                 
2380         }
2381         else
2382         if(amount < 0)
2383         {
2384                 BC_WindowBase *last_textbox = 0;
2385                 find_prev_textbox(&last_textbox, &new_textbox, result);
2386                 if(!new_textbox) new_textbox = last_textbox;
2387                 
2388         }
2390         if(new_textbox != active_subwindow)
2391         {
2392                 deactivate();
2393                 new_textbox->activate();
2394         }
2395         
2396         return 0;
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++)
2403         {
2404                 BC_WindowBase *test_subwindow = subwindows->values[i];
2405                 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2406         }
2408         if(result < 2)
2409         {
2410                 if(uses_text())
2411                 {
2412                         if(!*first_textbox) *first_textbox = this;
2414                         if(result < 1)
2415                         {
2416                                 if(top_level->active_subwindow == this)
2417                                         result++;
2418                         }
2419                         else
2420                         {
2421                                 result++;
2422                                 *next_textbox = this;
2423                         }
2424                 }
2425         }
2426         return 0;
2429 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2431         if(result < 2)
2432         {
2433                 if(uses_text())
2434                 {
2435                         if(!*last_textbox) *last_textbox = this;
2437                         if(result < 1)
2438                         {
2439                                 if(top_level->active_subwindow == this)
2440                                         result++;
2441                         }
2442                         else
2443                         {
2444                                 result++;
2445                                 *prev_textbox = this;
2446                         }
2447                 }
2448         }
2450 // Search subwindows for textbox
2451         for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2452         {
2453                 BC_WindowBase *test_subwindow = subwindows->values[i];
2454                 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2455         }
2456         return 0;
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;
2468         Window temp_win;
2470         XQueryPointer(top_level->display, 
2471            top_level->win, 
2472            &temp_win, 
2473            &temp_win,
2474        &abs_x, 
2475            &abs_y, 
2476            &win_x, 
2477            &win_y, 
2478            &temp_mask);
2480         XTranslateCoordinates(top_level->display, 
2481                         top_level->rootwin, 
2482                         win, 
2483                         abs_x, 
2484                         abs_y, 
2485                         &x, 
2486                         &y, 
2487                         &temp_win);
2489         return x;
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;
2496         Window temp_win;
2498         XQueryPointer(top_level->display, 
2499            top_level->win, 
2500            &temp_win, 
2501            &temp_win,
2502        &abs_x, 
2503            &abs_y, 
2504            &win_x, 
2505            &win_y, 
2506            &temp_mask);
2508         XTranslateCoordinates(top_level->display, 
2509                         top_level->rootwin, 
2510                         win, 
2511                         abs_x, 
2512                         abs_y, 
2513                         &x, 
2514                         &y, 
2515                         &temp_win);
2517         return y;
2520 int BC_WindowBase::get_abs_cursor_x()
2522         int abs_x, abs_y, win_x, win_y;
2523         unsigned int temp_mask;
2524         Window temp_win;
2526          XQueryPointer(top_level->display, 
2527                 top_level->win, 
2528                 &temp_win, 
2529                 &temp_win,
2530         &abs_x, 
2531                 &abs_y, 
2532                 &win_x, 
2533                 &win_y, 
2534                 &temp_mask);
2535         return abs_x;
2538 int BC_WindowBase::get_abs_cursor_y()
2540         int abs_x, abs_y, win_x, win_y;
2541         unsigned int temp_mask;
2542         Window temp_win;
2544          XQueryPointer(top_level->display, 
2545                 top_level->win, 
2546                 &temp_win, 
2547                 &temp_win,
2548         &abs_x, 
2549                 &abs_y, 
2550                 &win_x, 
2551                 &win_y, 
2552                 &temp_mask);
2553         return abs_y;
2556 int BC_WindowBase::get_cursor_over_window()
2558 return 1;
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;
2563         Window temp_win;
2564 //printf("BC_WindowBase::get_cursor_over_window 2\n");
2566         XQueryPointer(display, 
2567                 win, 
2568                 &temp_win, 
2569                 &temp_win,
2570                 &abs_x, 
2571                 &abs_y, 
2572                 &win_x, 
2573                 &win_y, 
2574                 &temp_mask);
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;
2583         for( ; 
2584                 parent_node->parent_tree != window_tree; 
2585                 tree_node = parent_node, parent_node = parent_node->parent_tree)
2586         {
2587                 ;
2588         }
2590         int got_it = 0;
2591         for(int i = 0; i < parent_node->windows.total; i++)
2592         {
2593                 if(parent_node->windows.values[i] == tree_node)
2594                 {
2595                         got_it = 1;
2596                 }
2597                 else
2598                 if(got_it)
2599                 {
2600                         XWindowAttributes attr;
2601                         XGetWindowAttributes(display,
2602                                 parent_node->windows.values[i]->win,
2603                                 &attr);
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)
2609                         {
2610                                 return 0;
2611                         }
2612                 }
2613         }
2615 # if 0
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)
2620         {
2621 //printf("BC_WindowBase::get_cursor_over_window 4\n");
2622                 if(parent_node
2623                 for(int i = 0; i < parent_node->windows.total; i++)
2624                 {
2625 //printf("BC_WindowBase::get_cursor_over_window 5\n");
2626                         if(parent_node->windows.values[i] == tree_node)
2627                         {
2628 //printf("BC_WindowBase::get_cursor_over_window 6\n");
2629                                 got_it = 1;
2630                         }
2631                         else
2632                         if(got_it)
2633                         {
2634 //printf("BC_WindowBase::get_cursor_over_window 7\n");
2635                                 XWindowAttributes attr;
2636                                 XGetWindowAttributes(display,
2637                                         parent_node->windows.values[i]->win,
2638                                         &attr);
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)
2644                                 {
2645                                         return 0;
2646                                 }
2647                         }
2648 //printf("BC_WindowBase::get_cursor_over_window 8\n");
2649                 }
2650                 tree_node = parent_node;
2651                 parent_node = tree_node->parent_tree;
2652         }
2653 //printf("BC_WindowBase::get_cursor_over_window 9\n");
2655 #endif
2657 // Didn't find obstruction
2658         return 1;
2661 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
2663         int x, y;
2664         Window tempwin;
2666         translate_coordinates(top_level->event_win, 
2667                 pov->win,
2668                 top_level->cursor_x,
2669                 top_level->cursor_y,
2670                 &x,
2671                 &y);
2672         return x;
2675 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
2677         int x, y;
2678         Window tempwin;
2680         translate_coordinates(top_level->event_win, 
2681                 pov->win,
2682                 top_level->cursor_x,
2683                 top_level->cursor_y,
2684                 &x,
2685                 &y);
2686         return 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()
2721         return is_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()
2762         return bg_color;
2765 int BC_WindowBase::resize_window(int w, int h)
2767         if(window_type == MAIN_WINDOW && !allow_resize)
2768         {
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);
2778         }
2779         XResizeWindow(top_level->display, win, w, h);
2781         this->w = w;
2782         this->h = 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++)
2788         {
2789                 subwindows->values[i]->dispatch_resize_event(w, h);
2790         }
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));
2795         return 0;
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)
2802         {
2803                 this->w = w;
2804                 this->h = h;
2805         }
2806         return 0;
2809 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
2811         int resize = 0;
2813 // Some tools set their own dimensions before calling this, causing the 
2814 // resize check to skip.
2815         this->x = x;
2816         this->y = y;
2818         if(w > 0 && w != this->w)
2819         {
2820                 resize = 1;
2821                 this->w = w;
2822         }
2824         if(h > 0 && h != this->h)
2825         {
2826                 resize = 1;
2827                 this->h = h;
2828         }
2830 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
2832         if(this->w <= 0)
2833                 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
2834         if(this->h <= 0)
2835                 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
2837         if(translation_count && window_type == MAIN_WINDOW)
2838         {
2839 // KDE shifts window right and down.
2840 // FVWM leaves window alone and adds border around it.
2841                 XMoveResizeWindow(top_level->display, 
2842                         win, 
2843                         x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x, 
2844                         y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y, 
2845                         this->w,
2846                         this->h);
2847         }
2848         else
2849         {
2850                 XMoveResizeWindow(top_level->display, 
2851                         win, 
2852                         x, 
2853                         y, 
2854                         this->w, 
2855                         this->h);
2856         }
2858         if(resize)
2859         {
2860                 XFreePixmap(top_level->display, pixmap);
2861                 pixmap = XCreatePixmap(top_level->display, 
2862                         win, 
2863                         this->w, 
2864                         this->h, 
2865                         top_level->default_depth);
2867 // Propagate to menubar
2868                 for(int i = 0; i < subwindows->total; i++)
2869                 {
2870                         subwindows->values[i]->dispatch_resize_event(this->w, this->h);
2871                 }
2873 //              draw_background(0, 0, w, h);
2874         }
2876         return 0;
2879 int BC_WindowBase::set_tooltips(int tooltips_enabled)
2881         get_resources()->tooltips_enabled = tooltips_enabled;
2882         return 0;
2885 int BC_WindowBase::raise_window()
2887         XRaiseWindow(top_level->display, win);
2888         XFlush(top_level->display);
2889         return 0;
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, 
2897                         bitmap, 
2898                         PIXMAP_OPAQUE);
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);
2907         flush();
2910 char* BC_WindowBase::get_title()
2912         return 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, 
2924                 data, 
2925                 PIXMAP_ALPHA,
2926                 1);
2928         icon_window = new BC_Popup(this, 
2929                 (int)BC_INFINITY, 
2930                 (int)BC_INFINITY, 
2931                 icon_pixmap->get_w(), 
2932                 icon_pixmap->get_h(), 
2933                 -1, 
2934                 1, // All windows are hidden initially
2935                 icon_pixmap);
2937         XWMHints wm_hints;
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]);
2944 // printf("\n");
2946         XSetWMHints(top_level->display, top_level->win, &wm_hints);
2947         XSync(top_level->display, 0);
2948         return 0;
2951 int BC_WindowBase::set_w(int w)
2953         this->w = w;
2954         return 0;
2957 int BC_WindowBase::set_h(int h)
2959         this->h = h;
2960         return 0;
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);
2969         return 0;
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);
2979         return 0;
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, 
2987                 Window dest_w,
2988                 int src_x,
2989                 int src_y,
2990                 int *dest_x_return,
2991                 int *dest_y_return)
2993         Window tempwin = 0;
2994 //Timer timer;
2995 //timer.update();
2996         if(src_w == dest_w)
2997         {
2998                 *dest_x_return = src_x;
2999                 *dest_y_return = src_y;
3000         }
3001         else
3002         {
3003                 XTranslateCoordinates(top_level->display, 
3004                         src_w, 
3005                         dest_w, 
3006                         src_x, 
3007                         src_y, 
3008                         dest_x_return, 
3009                         dest_y_return,
3010                         &tempwin);
3011 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3012         }
3021 #ifdef HAVE_LIBXXF86VM
3022 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3024    int foo,bar;
3025    *vm = 0;
3026    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3027            int vm_count,i;
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)
3032                            *vm = i;
3033            }
3034            display = top_level->display;
3035            if (vm_modelines[*vm]->hdisplay == *width)
3036                    *vm = -1;
3037            else
3038            {
3039                    *width = vm_modelines[*vm]->hdisplay;
3040                    *height = vm_modelines[*vm]->vdisplay;
3041            }
3042    }
3045 void BC_WindowBase::scale_vm(int vm)
3047    int foo,bar,dotclock;
3048    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3049    {
3050            int vm_count;
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);
3070    }
3073 void BC_WindowBase::restore_vm()
3075    XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3076    XFlush(top_level->display);
3080 #endif
3083 #ifdef HAVE_GL
3085 extern "C"
3087         GLXContext glXCreateContext(Display *dpy,
3088                                XVisualInfo *vis,
3089                                GLXContext shareList,
3090                                int direct);
3091         
3092         int glXMakeCurrent(Display *dpy,
3093                        Drawable drawable,
3094                        GLXContext ctx);
3096         void glXSwapBuffers(Display *dpy,
3097                        Drawable drawable);
3102 void BC_WindowBase::enable_opengl()
3104         lock_window();
3105         opengl_lock.lock();
3107         XVisualInfo viproto;
3108         XVisualInfo *visinfo;
3109         int nvi;
3111 //printf("BC_WindowBase::enable_opengl 1\n");
3112         viproto.screen = top_level->screen;
3113         visinfo = XGetVisualInfo(top_level->display,
3114         VisualScreenMask,
3115         &viproto,
3116         &nvi);
3117 //printf("BC_WindowBase::enable_opengl 1 %p\n", visinfo);
3119         gl_context = glXCreateContext(top_level->display,
3120                 visinfo,
3121                 0,
3122                 1);
3123 //printf("BC_WindowBase::enable_opengl 1\n");
3125         glXMakeCurrent(top_level->display,
3126                 win,
3127                 gl_context);
3129         unsigned long valuemask = CWEventMask;
3130         XSetWindowAttributes attributes;
3131         attributes.event_mask = DEFAULT_EVENT_MASKS |
3132                         ExposureMask;
3133         XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3135         opengl_lock.unlock();
3136         unlock_window();
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()
3150         lock_window();
3151         opengl_lock.lock();
3152         glXMakeCurrent(top_level->display,
3153                 win,
3154                 gl_context);
3157 void BC_WindowBase::unlock_opengl()
3159         opengl_lock.unlock();
3160         unlock_window();
3163 void BC_WindowBase::flip_opengl()
3165         glXSwapBuffers(top_level->display, win);
3168 #endif