r1053: Add Russian translation.
[cinelerra_cv.git] / guicast / bcwindowbase.C
blobb90d383955c1546467c0a3a384ac9adca2dff3f3
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 "bcsignals.h"
11 #include "bcsubwindow.h"
12 #include "bcsynchronous.h"
13 #include "bctimer.h"
14 #include "bcwidgetgrid.h"
15 #include "bcwindowbase.h"
16 #include "bcwindowevents.h"
17 #include "colormodels.h"
18 #include "colors.h"
19 #include "condition.h"
20 #include "cursors.h"
21 #include "bchash.h"
22 #include "fonts.h"
23 #include "keys.h"
24 #include "language.h"
25 #include "mutex.h"
26 #include "sizes.h"
27 #include "vframe.h"
29 #ifdef HAVE_GL
30 #include <GL/gl.h>
31 #endif
32 #include <string.h>
33 #include <unistd.h>
35 #include <X11/extensions/Xvlib.h>
36 #include <X11/extensions/shape.h>
39 BC_ResizeCall::BC_ResizeCall(int w, int h)
41         this->w = w;
42         this->h = h;
55 BC_Resources BC_WindowBase::resources;
57 Window XGroupLeader = 0;
59 BC_WindowBase::BC_WindowBase()
61 //printf("BC_WindowBase::BC_WindowBase 1\n");
62         BC_WindowBase::initialize();
65 BC_WindowBase::~BC_WindowBase()
67 #ifdef HAVE_LIBXXF86VM
68    if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
69    {
70            restore_vm();   
71    }
72 #endif
74         hide_tooltip();
75         if(window_type != MAIN_WINDOW)
76         {
77                 if(top_level->active_menubar == this) top_level->active_menubar = 0;
78                 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
79                 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
80 // Remove pointer from parent window to this
81                 parent_window->subwindows->remove(this);
82         }
85 // Delete the subwindows
86         is_deleting = 1;
87         if(subwindows)
88         {
89                 while(subwindows->total)
90                 {
91 // Subwindow removes its own pointer
92                         delete subwindows->values[0];
93                 }
94                 delete subwindows;
95         }
97         if(widgetgrids)
98         {
99                 while (widgetgrids->total) 
100                 {
101                         delete widgetgrids->last();
102                         widgetgrids->remove();
103                 }
104                 delete widgetgrids;
105         }
106                 
108         delete pixmap;
110 // Destroyed in synchronous thread if gl context exists.
111 #ifdef HAVE_GL
112         if(!gl_win_context || !get_resources()->get_synchronous())
113 #endif
114                 XDestroyWindow(top_level->display, win);
116         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
117         if(icon_pixmap) delete icon_pixmap;
118         if(temp_bitmap) delete temp_bitmap;
124         if(window_type == MAIN_WINDOW) 
125         {
126                 XFreeGC(display, gc);
127 #ifdef HAVE_XFT
128                 if(largefont_xft) 
129                         XftFontClose (display, (XftFont*)largefont_xft);
130                 if(mediumfont_xft) 
131                         XftFontClose (display, (XftFont*)mediumfont_xft);
132                 if(smallfont_xft) 
133                         XftFontClose (display, (XftFont*)smallfont_xft);
134 #endif
135                 flush();
136 // Can't close display if another thread is waiting for events.
137 // Synchronous thread must delete display if gl_context exists.
138 #ifdef HAVE_GL
139                 if(!gl_win_context || !get_resources()->get_synchronous())
140 #endif
141                         XCloseDisplay(display);
142                 clipboard->stop_clipboard();
143                 delete clipboard;
144         }
145         else
146         {
147                 flush();
148         }
150 // Must be last reference to display.
151 // This only works if it's a MAIN_WINDOW since the display deletion for
152 // a subwindow is not determined by the subwindow.
153 #ifdef HAVE_GL
154         if(gl_win_context && get_resources()->get_synchronous())
155         {
156                 printf("BC_WindowBase::~BC_WindowBase window deleted but opengl deletion is not\n"
157                         "implemented for BC_Pixmap.\n");
158                 get_resources()->get_synchronous()->delete_window(this);
159         }
160 #endif
162         resize_history.remove_all_objects();
163         common_events.remove_all_objects();
164         delete event_lock;
165         delete event_condition;
167         UNSET_ALL_LOCKS(this)
170 int BC_WindowBase::initialize()
172         test_keypress = 0;
173         is_deleting = 0;
174         window_lock = 0;
175         x = 0; 
176         y = 0; 
177         w = 0; 
178         h = 0;
179         bg_color = -1;
180         top_level = 0;
181         parent_window = 0;
182         subwindows = 0;
183         widgetgrids = 0;
184         xvideo_port_id = -1;
185         video_on = 0;
186         motion_events = 0;
187         resize_events = 0;
188         translation_events = 0;
189         ctrl_mask = shift_mask = alt_mask = 0;
190         cursor_x = cursor_y = button_number = 0;
191         button_down = 0;
192         button_pressed = 0;
193         button_time1 = button_time2 = 0;
194         double_click = 0;
195         last_motion_win = 0;
196         key_pressed = 0;
197         active_menubar = 0;
198         active_popup_menu = 0;
199         active_subwindow = 0;
200         pixmap = 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_color = BLACK;
209         current_cursor = ARROW_CURSOR;
210         hourglass_total = 0;
211         is_dragging = 0;
212         shared_bg_pixmap = 0;
213         icon_pixmap = 0;
214         window_type = MAIN_WINDOW;
215         translation_count = 0;
216         x_correction = y_correction = 0;
217         temp_bitmap = 0;
218         tooltip_on = 0;
219         temp_cursor = 0;
220         toggle_value = 0;
221         toggle_drag = 0;
222         has_focus = 0;
223         is_hourglass = 0;
224         is_transparent = 0;
225 #ifdef HAVE_LIBXXF86VM
226     vm_switched = 0;
227 #endif
228         largefont_xft = 0;
229         mediumfont_xft = 0;
230         smallfont_xft = 0;
231 // Need these right away since put_event is called before run_window sometimes.
232         event_lock = new Mutex("BC_WindowBase::event_lock");
233         event_condition = new Condition(0, "BC_WindowBase::event_condition");
234         cursor_timer = new Timer;
235         event_thread = 0;
236 #ifdef HAVE_GL
237         gl_win_context = 0;
238 #endif
240         return 0;
243 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
244                         LeaveWindowMask | \
245                         ButtonPressMask | \
246                         ButtonReleaseMask | \
247                         PointerMotionMask | \
248                         FocusChangeMask
249                         
251 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
252                                 char *title, 
253                                 int x,
254                                 int y,
255                                 int w, 
256                                 int h, 
257                                 int minw, 
258                                 int minh, 
259                                 int allow_resize,
260                                 int private_color, 
261                                 int hide,
262                                 int bg_color,
263                                 char *display_name,
264                                 int window_type,
265                                 BC_Pixmap *bg_pixmap,
266                                 int group_it)
268         XSetWindowAttributes attr;
269         unsigned long mask;
270         XSizeHints size_hints;
271         int root_w;
272         int root_h;
273 #ifdef HAVE_LIBXXF86VM
274     int vm;
275 #endif
277         id = get_resources()->get_id();
280         get_resources()->create_window_lock->lock("BC_WindowBase::create_window");
282     if(parent_window) top_level = parent_window->top_level;
284 #ifdef HAVE_LIBXXF86VM
285     if(window_type == VIDMODE_SCALED_WINDOW)
286             closest_vm(&vm,&w,&h);
287 #endif
289         this->x = x;
290         this->y = y;
291         this->w = w;
292         this->h = h;
293         this->bg_color = bg_color;
294         this->window_type = window_type;
295         this->hidden = hide;
296         this->private_color = private_color;
297         this->parent_window = parent_window;
298         this->bg_pixmap = bg_pixmap;
299         this->allow_resize = allow_resize;
300         strcpy(this->title, _(title));
301         if(bg_pixmap) shared_bg_pixmap = 1;
303         if(parent_window) top_level = parent_window->top_level;
305         subwindows = new BC_SubWindowList;
306         widgetgrids = new BC_WidgetGridList;
308 // Mandatory setup
309         if(window_type == MAIN_WINDOW)
310         {
311                 top_level = this;
312                 parent_window = this;
314 // This function must be the first Xlib
315 // function a multi-threaded program calls
316                 XInitThreads();
319 // get the display connection
320                 display = init_display(display_name);
321 //              event_display = init_display(display_name);
323 // Fudge window placement
324                 root_w = get_root_w(1, 0);
325                 root_h = get_root_h(0);
326                 if(this->x + this->w > root_w) this->x = root_w - this->w;
327                 if(this->y + this->h > root_h) this->y = root_h - this->h;
328                 if(this->x < 0) this->x = 0;
329                 if(this->y < 0) this->y = 0;
330                 screen = DefaultScreen(display);
331                 rootwin = RootWindow(display, screen);
334                 vis = DefaultVisual(display, screen);
335                 default_depth = DefaultDepth(display, screen);
337                 client_byte_order = (*(u_int32_t*)"a   ") & 0x00000001;
338                 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
341 // This must be done before fonts to know if antialiasing is available.
342                 init_colors();
343 // get the resources
344                 if(resources.use_shm < 0) resources.initialize_display(this);
345                 x_correction = get_resources()->get_left_border();
346                 y_correction = get_resources()->get_top_border();
348                 if(this->bg_color == -1)
349                         this->bg_color = resources.get_bg_color();
351 // printf("bcwindowbase 1 %s\n", title);
352 // if(window_type == MAIN_WINDOW) sleep(1);
353 // printf("bcwindowbase 10\n");
354                 init_fonts();
355                 init_gc();
356                 init_cursors();
358 // Create the window
359                 mask = CWEventMask | 
360                                 CWBackPixel | 
361                                 CWColormap | 
362                                 CWCursor;
364                 attr.event_mask = DEFAULT_EVENT_MASKS |
365                         StructureNotifyMask | 
366                         KeyPressMask;
368                 attr.background_pixel = get_color(this->bg_color);
369                 attr.colormap = cmap;
370                 attr.cursor = get_cursor_struct(ARROW_CURSOR);
372                 win = XCreateWindow(display, 
373                         rootwin, 
374                         this->x, 
375                         this->y, 
376                         this->w, 
377                         this->h, 
378                         0, 
379                         top_level->default_depth, 
380                         InputOutput, 
381                         vis, 
382                         mask, 
383                         &attr);
385                 XGetNormalHints(display, win, &size_hints);
387                 size_hints.flags = PSize | PMinSize | PMaxSize;
388                 size_hints.width = this->w;
389                 size_hints.height = this->h;
390                 size_hints.min_width = allow_resize ? minw : this->w;
391                 size_hints.max_width = allow_resize ? 32767 : this->w; 
392                 size_hints.min_height = allow_resize ? minh : this->h;
393                 size_hints.max_height = allow_resize ? 32767 : this->h; 
394                 if(x > -BC_INFINITY && x < BC_INFINITY)
395                 {
396                         size_hints.flags |= PPosition;
397                         size_hints.x = this->x;
398                         size_hints.y = this->y;
399                 }
401                 XSetStandardProperties(display, 
402                         win, 
403                         title, 
404                         title, 
405                         None, 
406                         0, 
407                         0, 
408                         &size_hints);
409                 get_atoms();
410                 
411                 clipboard = new BC_Clipboard(display_name);
412                 clipboard->start_clipboard();
414                 if (group_it)
415                 {
416                         Atom ClientLeaderXAtom;
417                         if (XGroupLeader == 0)
418                                 XGroupLeader = win;
419                         char *instance_name = "cinelerra";
420                         char *class_name = "Cinelerra";
421                         XClassHint *class_hints = XAllocClassHint(); 
422                         class_hints->res_name = instance_name;
423                         class_hints->res_class = class_name;
424                         XSetClassHint(top_level->display, win, class_hints);
425                         XFree(class_hints);
426                         ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
427                         XChangeProperty(display, 
428                                         win, 
429                                         ClientLeaderXAtom, 
430                                         XA_WINDOW, 
431                                         32, 
432                                         PropModeReplace, 
433                                         (unsigned char *)&XGroupLeader, 
434                                         true);
436                 }
437                 
438         }
440 #ifdef HAVE_LIBXXF86VM
441     if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
442     {
443             scale_vm (vm);
444             vm_switched = 1;
445     }
446 #endif
448 #ifdef HAVE_LIBXXF86VM
449     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
450 #else
451     if(window_type == POPUP_WINDOW)
452 #endif
453         {
454                 mask = CWEventMask | 
455                         CWBackPixel | 
456                         CWColormap | 
457                         CWOverrideRedirect | 
458                         CWSaveUnder | 
459                         CWCursor;
461                 attr.event_mask = DEFAULT_EVENT_MASKS |
462                         KeyPressMask;
464                 if(this->bg_color == -1)
465                         this->bg_color = resources.get_bg_color();
466                 attr.background_pixel = top_level->get_color(bg_color);
467                 attr.colormap = top_level->cmap;
468                 if(top_level->is_hourglass)
469                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
470                 else
471                         attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
472                 attr.override_redirect = True;
473                 attr.save_under = True;
475                 win = XCreateWindow(top_level->display, 
476                         top_level->rootwin, 
477                         this->x, 
478                         this->y, 
479                         this->w, 
480                         this->h, 
481                         0, 
482                         top_level->default_depth, 
483                         InputOutput, 
484                         top_level->vis, 
485                         mask, 
486                         &attr);
487         }
489         if(window_type == SUB_WINDOW)
490         {
491                 mask = CWBackPixel | 
492                         CWEventMask | 
493                         CWCursor;
494                 attr.event_mask = DEFAULT_EVENT_MASKS;
495                 attr.background_pixel = top_level->get_color(this->bg_color);
496                 if(top_level->is_hourglass)
497                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
498                 else
499                         attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
500                 win = XCreateWindow(top_level->display, 
501                         parent_window->win, 
502                         this->x, 
503                         this->y, 
504                         this->w, 
505                         this->h, 
506                         0, 
507                         top_level->default_depth, 
508                         InputOutput, 
509                         top_level->vis, 
510                         mask, 
511                         &attr);
512                 init_window_shape();
513                 XMapWindow(top_level->display, win);
514         }
516 // Create pixmap for all windows
517         pixmap = new BC_Pixmap(this, this->w, this->h);
520 // Set up options for main window
521         if(window_type == MAIN_WINDOW)
522         {
523                 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
524                 {
525                         this->bg_pixmap = new BC_Pixmap(this, 
526                                 get_resources()->bg_image, 
527                                 PIXMAP_OPAQUE);
528                 }
530                 if(!hidden) show_window();
532         }
537         draw_background(0, 0, this->w, this->h);
538         flash();
540 // Set up options for popup window
541 #ifdef HAVE_LIBXXF86VM
542     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
543 #else
544     if(window_type == POPUP_WINDOW)
545 #endif
546         {
547                 init_window_shape();
548                 if(!hidden) show_window();
549         }
550         get_resources()->create_window_lock->unlock();
552         return 0;
555 Display* BC_WindowBase::init_display(char *display_name)
557         Display* display;
559         if(display_name && display_name[0] == 0) display_name = NULL;
560         if((display = XOpenDisplay(display_name)) == NULL)
561         {
562                 printf("BC_WindowBase::init_display: cannot connect to X server %s\n", 
563                         display_name);
564                 if(getenv("DISPLAY") == NULL)
565         {
566                         printf("'DISPLAY' environment variable not set.\n");
567                         exit(1);
568                 }
569                 else
570 // Try again with default display.
571                 {
572                         if((display = XOpenDisplay(0)) == NULL)
573                         {
574                                 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
575                                 exit(1);
576                         }
577                 }
578         }
579         return display;
582 Display* BC_WindowBase::get_display()
584         return top_level->display;
587 int BC_WindowBase::get_screen()
589         return top_level->screen;
592 int BC_WindowBase::run_window()
594         done = 0;
595         return_value = 0;
598 // Events may have been sent before run_window so can't initialize them here.
600 // Start tooltips
601         if(window_type == MAIN_WINDOW)
602         {
603 //              tooltip_id = get_repeat_id();
604                 set_repeat(get_resources()->tooltip_delay);
605         }
607 // Start X server events
608         event_thread = new BC_WindowEvents(this);
609         event_thread->start();
611 // Start common events
612         while(!done)
613         {
614                 dispatch_event();
615         }
617         unset_all_repeaters();
618         hide_tooltip();
619         delete event_thread;
620         event_thread = 0;
621         event_condition->reset();
622         common_events.remove_all_objects();
623         done = 0;
625         return return_value;
628 int BC_WindowBase::get_key_masks(XEvent *event)
630 // printf("BC_WindowBase::get_key_masks %llx\n", 
631 // event->xkey.state);
632 // ctrl key down
633         ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
634 // shift key down
635         shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
636         alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
637         return 0;
646 int BC_WindowBase::dispatch_event()
648         XEvent *event = 0;
649     Window tempwin;
650         KeySym keysym;
651         char keys_return[2];
652         int result;
653         XClientMessageEvent *ptr;
654         int temp;
655         int cancel_resize, cancel_translation;
657         key_pressed = 0;
659 // If an event is waiting get it, otherwise
660 // wait for next event only if there are no compressed events.
661         if(get_event_count() || 
662                 (!motion_events && !resize_events && !translation_events))
663         {
664 //              XNextEvent(display, event);
665                 event = get_event();
666 // Lock out window deletions
667                 lock_window("BC_WindowBase::dispatch_event 1");
668 //              get_key_masks(event);
669         }
670         else
671 // Handle compressed events
672         {
673                 lock_window("BC_WindowBase::dispatch_event 2");
674                 if(resize_events)
675                         dispatch_resize_event(last_resize_w, last_resize_h);
676                 else
677                 if(motion_events)
678                         dispatch_motion_event();
679                 else
680                 if(translation_events)
681                         dispatch_translation_event();
683                 unlock_window();
684                 return 0;
685         }
687 //printf("1 %s %p %d\n", title, event, event->type);
688         switch(event->type)
689         {
690                 case ClientMessage:
691 // Clear the resize buffer
692                         if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
693 // Clear the motion buffer since this can clear the window
694                         if(motion_events)
695                         {
696                                 dispatch_motion_event();
697                         }
699                         ptr = (XClientMessageEvent*)event;
702                 if(ptr->message_type == ProtoXAtom && 
703                                 ptr->data.l[0] == DelWinXAtom)
704                 {
705                                 close_event();
706                         }
707                         else
708                         if(ptr->message_type == RepeaterXAtom)
709                         {
710                                 dispatch_repeat_event(ptr->data.l[0]);
711 // Make sure the repeater still exists.
712 //                              for(int i = 0; i < repeaters.total; i++)
713 //                              {
714 //                                      if(repeaters.values[i]->repeat_id == ptr->data.l[0])
715 //                                      {
716 //                                              dispatch_repeat_event_master(ptr->data.l[0]);
717 //                                              break;
718 //                                      }
719 //                              }
720                         }
721                         else
722                         if(ptr->message_type == SetDoneXAtom)
723                         {
724                                 done = 1;
725                         } else
726                         { // We currently use X marshalling for xatom events, we can switch to something else later
727                                 recieve_custom_xatoms((xatom_event *)ptr);
728                         }
729                         break;
731                 case FocusIn:
732                         has_focus = 1;
733                         dispatch_focus_in();
734                         break;
736                 case FocusOut:
737                         has_focus = 0;
738                         dispatch_focus_out();
739                         break;
741 // Maximized
742                 case MapNotify:
743                         break;
745 // Minimized
746                 case UnmapNotify:
747                         break;
749                 case ButtonPress:
750                         get_key_masks(event);
751                         cursor_x = event->xbutton.x;
752                         cursor_y = event->xbutton.y;
753                         button_number = event->xbutton.button;
754                         event_win = event->xany.window;
755                         if (button_number != 4 && button_number != 5)
756                                 button_down = 1;
757                         button_pressed = event->xbutton.button;
758                         button_time1 = button_time2;
759                         button_time2 = event->xbutton.time;
760                         drag_x = cursor_x;
761                         drag_y = cursor_y;
762                         drag_win = event_win;
763                         drag_x1 = cursor_x - get_resources()->drag_radius;
764                         drag_x2 = cursor_x + get_resources()->drag_radius;
765                         drag_y1 = cursor_y - get_resources()->drag_radius;
766                         drag_y2 = cursor_y + get_resources()->drag_radius;
768                         if(button_time2 - button_time1 < resources.double_click)
769                         {
770 // Ignore triple clicks
771                                 double_click = 1; 
772                                 button_time2 = button_time1 = 0; 
773                         }
774                         else 
775                                 double_click = 0;
777                         dispatch_button_press();
778                         break;
780                 case ButtonRelease:
781                         get_key_masks(event);
782                         button_number = event->xbutton.button;
783                         event_win = event->xany.window;
784                         if (button_number != 4 && button_number != 5) 
785                                 button_down = 0;
787                         dispatch_button_release();
789                         break;
791                 case Expose:
792                         event_win = event->xany.window;
793                         dispatch_expose_event();
794                         break;
796                 case MotionNotify:
797                         get_key_masks(event);
798 // Dispatch previous motion event if this is a subsequent motion from a different window
799                         if(motion_events && last_motion_win != event->xany.window)
800                         {
801                                 dispatch_motion_event();
802                         }
804 // Buffer the current motion
805                         motion_events = 1;
806                         last_motion_x = event->xmotion.x;
807                         last_motion_y = event->xmotion.y;
808                         last_motion_win = event->xany.window;
809                         break;
811                 case ConfigureNotify:
812                         get_key_masks(event);
813                         XTranslateCoordinates(top_level->display, 
814                                 top_level->win, 
815                                 top_level->rootwin, 
816                                 0, 
817                                 0, 
818                                 &last_translate_x, 
819                                 &last_translate_y, 
820                                 &tempwin);
821                         last_resize_w = event->xconfigure.width;
822                         last_resize_h = event->xconfigure.height;
824                         cancel_resize = 0;
825                         cancel_translation = 0;
827 // Resize history prevents responses to recursive resize requests
828                         for(int i = 0; i < resize_history.total && !cancel_resize; i++)
829                         {
830                                 if(resize_history.values[i]->w == last_resize_w &&
831                                         resize_history.values[i]->h == last_resize_h)
832                                 {
833                                         delete resize_history.values[i];
834                                         resize_history.remove_number(i);
835                                         cancel_resize = 1;
836                                 }
837                         }
839                         if(last_resize_w == w && last_resize_h == h)
840                                 cancel_resize = 1;
842                         if(!cancel_resize)
843                         {
844                                 resize_events = 1;
845                         }
847                         if((last_translate_x == x && last_translate_y == y))
848                                 cancel_translation = 1;
850                         if(!cancel_translation)
851                         {
852                                 translation_events = 1;
853                         }
855                         translation_count++;
856                         break;
858                 case KeyPress:
859                         get_key_masks(event);
860                         keys_return[0] = 0;
861                         XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
863 // printf("BC_WindowBase::dispatch_event 2 %llx\n", 
864 // event->xkey.state);
865 // block out control keys
866                         if(keysym > 0xffe0 && keysym < 0xffff) break;
869                         if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
872                         switch(keysym)
873                         {
874 // block out extra keys
875                         case XK_Alt_L:      
876                         case XK_Alt_R:      
877                         case XK_Shift_L:    
878                         case XK_Shift_R:    
879                         case XK_Control_L:  
880                         case XK_Control_R:  
881                                         key_pressed = 0;         
882                                         break;
884 // Translate key codes
885                                 case XK_Return:     key_pressed = RETURN;    break;
886                         case XK_Up:         key_pressed = UP;        break;
887                                 case XK_Down:       key_pressed = DOWN;      break;
888                                 case XK_Left:       key_pressed = LEFT;      break;
889                         case XK_Right:      key_pressed = RIGHT;     break;
890                         case XK_Next:       key_pressed = PGDN;      break;
891                         case XK_Prior:      key_pressed = PGUP;      break;
892                         case XK_BackSpace:  key_pressed = BACKSPACE; break;
893                         case XK_Escape:     key_pressed = ESC;       break;
894                         case XK_Tab:
895                                         if(shift_down())
896                                                 key_pressed = LEFTTAB;
897                                         else
898                                                 key_pressed = TAB;       
899                                         break;
900                                 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
901                                 case XK_underscore: key_pressed = '_';       break;
902                         case XK_asciitilde: key_pressed = '~';       break;
903                                 case XK_Delete:     key_pressed = DELETE;    break;
904                                 case XK_Home:       key_pressed = HOME;      break;
905                                 case XK_End:        key_pressed = END;       break;
907 // number pad
908                                 case XK_KP_Enter:       key_pressed = KPENTER;   break;
909                                 case XK_KP_Add:         key_pressed = KPPLUS;    break;
910                                 case XK_KP_1:
911                                 case XK_KP_End:         key_pressed = KP1;       break;
912                                 case XK_KP_2:
913                                 case XK_KP_Down:        key_pressed = KP2;       break;
914                                 case XK_KP_3:
915                                 case XK_KP_Page_Down:   key_pressed = KP3;       break;
916                                 case XK_KP_4:
917                                 case XK_KP_Left:        key_pressed = KP4;       break;
918                                 case XK_KP_5:
919                                 case XK_KP_Begin:       key_pressed = KP5;       break;
920                                 case XK_KP_6:
921                                 case XK_KP_Right:       key_pressed = KP6;       break;
922                                 case XK_KP_0:
923                                 case XK_KP_Insert:      key_pressed = KPINS;     break;
924                                 case XK_KP_Decimal:
925                                 case XK_KP_Delete:      key_pressed = KPDEL;     break;
926                         default:           
927                                         //key_pressed = keys_return[0]; 
928                                         key_pressed = keysym & 0xff;
929                                         break;
930                         }
932 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
933                         result = dispatch_keypress_event();
934 // Handle some default keypresses
935                         if(!result)
936                         {
937                                 if(key_pressed == 'w' ||
938                                         key_pressed == 'W')
939                                 {
940                                         close_event();
941                                 }
942                         }
943                         break;
945                 case LeaveNotify:
946                         event_win = event->xany.window;
947                         dispatch_cursor_leave();
948                         break;
950                 case EnterNotify:
951                         event_win = event->xany.window;
952                         cursor_x = event->xcrossing.x;
953                         cursor_y = event->xcrossing.y;
954                         dispatch_cursor_enter();
955                         break;
956         }
957 //printf("100 %s %p %d\n", title, event, event->type);
959         unlock_window();
960         if(event) delete event;
961         return 0;
964 int BC_WindowBase::dispatch_expose_event()
966         int result = 0;
967         for(int i = 0; i < subwindows->total && !result; i++)
968         {
969                 result = subwindows->values[i]->dispatch_expose_event();
970         }
972 // Propagate to user
973         if(!result) expose_event();
974         return result;
977 int BC_WindowBase::dispatch_resize_event(int w, int h)
979 // Can't store new w and h until the event is handles 
980 // because bcfilebox depends on the old w and h to
981 // reposition widgets.
982         if(window_type == MAIN_WINDOW)
983         {
984                 resize_events = 0;
985                 delete pixmap;
986                 pixmap = new BC_Pixmap(this, w, h);
988                 clear_box(0, 0, w, h);
989         }
991 // Propagate to subwindows
992         for(int i = 0; i < subwindows->total; i++)
993         {
994                 subwindows->values[i]->dispatch_resize_event(w, h);
995         }
997 // Propagate to user
998         resize_event(w, h);
1000         if(window_type == MAIN_WINDOW)
1001         {
1002                 this->w = w;
1003                 this->h = h;
1004         }
1005         return 0;
1008 int BC_WindowBase::dispatch_translation_event()
1010         translation_events = 0;
1011         if(window_type == MAIN_WINDOW)
1012         {
1013                 prev_x = x;
1014                 prev_y = y;
1015                 x = last_translate_x;
1016                 y = last_translate_y;
1017 // Correct for window manager offsets
1018                 x -= x_correction;
1019                 y -= y_correction;
1020         }
1022         for(int i = 0; i < subwindows->total; i++)
1023         {
1024                 subwindows->values[i]->dispatch_translation_event();
1025         }
1027         translation_event();
1028         return 0;
1031 int BC_WindowBase::dispatch_motion_event()
1033         int result = 0;
1034         unhide_cursor();
1036         if(top_level == this)
1037         {
1038                 event_win = last_motion_win;
1039                 motion_events = 0;
1041 // Test for grab
1042                 if(get_button_down() && !active_menubar && !active_popup_menu)
1043                 {
1044                         if(!result)
1045                         {
1046                                 cursor_x = last_motion_x;
1047                                 cursor_y = last_motion_y;
1048                                 result = dispatch_drag_motion();
1049                         }
1051                         if(!result && 
1052                                 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 || 
1053                                 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1054                         {
1055                                 cursor_x = drag_x;
1056                                 cursor_y = drag_y;
1058                                 result = dispatch_drag_start();
1059                         }
1060                 }
1061                 cursor_x = last_motion_x;
1062                 cursor_y = last_motion_y;
1064                 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1065                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1066                 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1067         }
1069         for(int i = 0; i < subwindows->total && !result; i++)
1070         {
1071                 result = subwindows->values[i]->dispatch_motion_event();
1072         }
1075         if(!result) result = cursor_motion_event();    // give to user
1076         return result;
1079 int BC_WindowBase::dispatch_keypress_event()
1081         int result = 0;
1082         if(top_level == this)
1083         {
1084                 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1085         }
1087         for(int i = 0; i < subwindows->total && !result; i++)
1088         {
1089                 result = subwindows->values[i]->dispatch_keypress_event();
1090         }
1092         if(!result) result = keypress_event();
1094         return result;
1097 int BC_WindowBase::dispatch_focus_in()
1099         for(int i = 0; i < subwindows->total; i++)
1100         {
1101                 subwindows->values[i]->dispatch_focus_in();
1102         }
1104         focus_in_event();
1106         return 0;
1109 int BC_WindowBase::dispatch_focus_out()
1111         for(int i = 0; i < subwindows->total; i++)
1112         {
1113                 subwindows->values[i]->dispatch_focus_out();
1114         }
1116         focus_out_event();
1118         return 0;
1121 int BC_WindowBase::get_has_focus()
1123         return top_level->has_focus;
1126 int BC_WindowBase::get_deleting()
1128         if(is_deleting) return 1;
1129         if(parent_window && parent_window->get_deleting()) return 1;
1130         return 0;
1133 int BC_WindowBase::dispatch_button_press()
1135         int result = 0;
1136         if(top_level == this)
1137         {
1138                 if(active_menubar) result = active_menubar->dispatch_button_press();
1139                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1140                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1141         }
1143         for(int i = 0; i < subwindows->total && !result; i++)
1144         {
1145                 result = subwindows->values[i]->dispatch_button_press();
1146         }
1148         if(!result) result = button_press_event();
1150         return result;
1153 int BC_WindowBase::dispatch_button_release()
1155         int result = 0;
1156         if(top_level == this)
1157         {
1158                 if(active_menubar) result = active_menubar->dispatch_button_release();
1159                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1160                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1161                 if(!result && button_number != 4 && button_number != 5)
1162                         result = dispatch_drag_stop();
1163         }
1165         for(int i = 0; i < subwindows->total && !result; i++)
1166         {
1167                 result = subwindows->values[i]->dispatch_button_release();
1168         }
1170         if(!result)
1171         {
1172                 result = button_release_event();
1173         }
1175         return result;
1179 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1182 // all repeat event handlers get called and decide based on activity and duration
1183 // whether to respond
1184         for(int i = 0; i < subwindows->total; i++)
1185         {
1186                 subwindows->values[i]->dispatch_repeat_event(duration);
1187         }
1190         repeat_event(duration);
1194 // Unlock next repeat signal
1195         if(window_type == MAIN_WINDOW)
1196         {
1197                 for(int i = 0; i < repeaters.total; i++)
1198                 {
1199                         if(repeaters.values[i]->delay == duration)
1200                         {
1201                                 repeaters.values[i]->repeat_lock->unlock();
1202                         }
1203                 }
1204         }
1206         return 0;
1209 void BC_WindowBase::unhide_cursor()
1211         if(is_transparent)
1212         {
1213                 is_transparent = 0;
1214                 if(top_level->is_hourglass)
1215                         set_cursor(HOURGLASS_CURSOR, 1);
1216                 else
1217                         set_cursor(current_cursor, 1);
1218         }
1219         cursor_timer->update();
1223 void BC_WindowBase::update_video_cursor()
1225         if(video_on && !is_transparent)
1226         {
1227                 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1228                 {
1229                         is_transparent = 1;
1230                         set_cursor(TRANSPARENT_CURSOR, 1);
1231                         cursor_timer->update();
1232                 }
1233         }
1234         else
1235         {
1236                 cursor_timer->update();
1237         }
1241 int BC_WindowBase::dispatch_cursor_leave()
1243         unhide_cursor();
1245         for(int i = 0; i < subwindows->total; i++)
1246         {
1247                 subwindows->values[i]->dispatch_cursor_leave();
1248         }
1250         cursor_leave_event();
1251         return 0;
1254 int BC_WindowBase::dispatch_cursor_enter()
1256         int result = 0;
1258         unhide_cursor();
1260         if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1261         if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1262         if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1264         for(int i = 0; !result && i < subwindows->total; i++)
1265         {
1266                 result = subwindows->values[i]->dispatch_cursor_enter();
1267         }
1269         if(!result) result = cursor_enter_event();
1270         return result;
1273 int BC_WindowBase::cursor_enter_event()
1275         return 0;
1278 int BC_WindowBase::cursor_leave_event()
1280         return 0;
1283 int BC_WindowBase::close_event()
1285         set_done(1);
1286         return 1;
1289 int BC_WindowBase::dispatch_drag_start()
1291         int result = 0;
1292         if(active_menubar) result = active_menubar->dispatch_drag_start();
1293         if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1294         if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1295         
1296         for(int i = 0; i < subwindows->total && !result; i++)
1297         {
1298                 result = subwindows->values[i]->dispatch_drag_start();
1299         }
1301         if(!result) result = is_dragging = drag_start_event();
1302         return result;
1305 int BC_WindowBase::dispatch_drag_stop()
1307         int result = 0;
1309         for(int i = 0; i < subwindows->total && !result; i++)
1310         {
1311                 result = subwindows->values[i]->dispatch_drag_stop();
1312         }
1314         if(is_dragging && !result) 
1315         {
1316                 drag_stop_event();
1317                 is_dragging = 0;
1318                 result = 1;
1319         }
1321         return result;
1324 int BC_WindowBase::dispatch_drag_motion()
1326         int result = 0;
1327         for(int i = 0; i < subwindows->total && !result; i++)
1328         {
1329                 result = subwindows->values[i]->dispatch_drag_motion();
1330         }
1331         
1332         if(is_dragging && !result)
1333         {
1334                 drag_motion_event();
1335                 result = 1;
1336         }
1337         
1338         return result;
1345 int BC_WindowBase::show_tooltip(int w, int h)
1347         Window tempwin;
1349         if(!tooltip_on && get_resources()->tooltips_enabled)
1350         {
1351                 int i, j, x, y;
1352                 top_level->hide_tooltip();
1354                 tooltip_on = 1;
1355                 if(w < 0)
1356                         w = get_text_width(MEDIUMFONT, tooltip_text);
1358                 if(h < 0)
1359                         h = get_text_height(MEDIUMFONT, tooltip_text);
1361                 w += TOOLTIP_MARGIN * 2;
1362                 h += TOOLTIP_MARGIN * 2;
1364                 XTranslateCoordinates(top_level->display, 
1365                                 win, 
1366                                 top_level->rootwin, 
1367                                 get_w(), 
1368                                 get_h(), 
1369                                 &x, 
1370                                 &y, 
1371                                 &tempwin);
1372                 tooltip_popup = new BC_Popup(top_level, 
1373                                         x,
1374                                         y,
1375                                         w, 
1376                                         h, 
1377                                         get_resources()->tooltip_bg_color);
1379                 draw_tooltip();
1380                 tooltip_popup->set_font(MEDIUMFONT);
1381                 tooltip_popup->flash();
1382                 tooltip_popup->flush();
1383         }
1384         return 0;
1387 int BC_WindowBase::hide_tooltip()
1389         if(subwindows)
1390                 for(int i = 0; i < subwindows->total; i++)
1391                 {
1392                         subwindows->values[i]->hide_tooltip();
1393                 }
1395         if(tooltip_on)
1396         {
1397                 tooltip_on = 0;
1398                 delete tooltip_popup;
1399                 tooltip_popup = 0;
1400         }
1401         return 0;
1404 int BC_WindowBase::set_tooltip(char *text)
1406         strcpy(this->tooltip_text, text);
1407 // Update existing tooltip if it is visible
1408         if(tooltip_on)
1409         {
1410                 draw_tooltip();
1411                 tooltip_popup->flash();
1412         }
1413         return 0;
1416 // signal the event handler to repeat
1417 int BC_WindowBase::set_repeat(int64_t duration)
1419         if(duration <= 0)
1420         {
1421                 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1422                 return 0;
1423         }
1424         if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1426 // test repeater database for duplicates
1427         for(int i = 0; i < repeaters.total; i++)
1428         {
1429 // Already exists
1430                 if(repeaters.values[i]->delay == duration)
1431                 {
1432                         repeaters.values[i]->start_repeating();
1433                         return 0;
1434                 }
1435         }
1437         BC_Repeater *repeater = new BC_Repeater(this, duration);
1438         repeater->initialize();
1439         repeaters.append(repeater);
1440     repeater->start_repeating();
1441         return 0;
1444 int BC_WindowBase::unset_repeat(int64_t duration)
1446         if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1448         BC_Repeater *repeater = 0;
1449         for(int i = 0; i < repeaters.total; i++)
1450         {
1451                 if(repeaters.values[i]->delay == duration)
1452                 {
1453                         repeaters.values[i]->stop_repeating();
1454                 }
1455         }
1456         return 0;
1460 int BC_WindowBase::unset_all_repeaters()
1462         for(int i = 0; i < repeaters.total; i++)
1463         {
1464                 repeaters.values[i]->stop_repeating();
1465         }
1466         repeaters.remove_all_objects();
1467         return 0;
1470 // long BC_WindowBase::get_repeat_id()
1471 // {
1472 //      return top_level->next_repeat_id++;
1473 // }
1476 int BC_WindowBase::arm_repeat(int64_t duration)
1478         XEvent *event = new XEvent;
1479         XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1480         ptr->type = ClientMessage;
1481         ptr->message_type = RepeaterXAtom;
1482         ptr->format = 32;
1483         ptr->data.l[0] = duration;
1485 // Couldn't use XSendEvent since it locked up randomly.
1486         put_event(event);
1487 //      XSendEvent(top_level->event_display, 
1488 //              top_level->win, 
1489 //              0, 
1490 //              0, 
1491 //              event);
1492 //      flush();
1493         return 0;
1496 int BC_WindowBase::recieve_custom_xatoms(xatom_event *event)
1498         return 0;
1501 int BC_WindowBase::send_custom_xatom(xatom_event *event)
1503         XEvent *myevent = new XEvent;
1504         XClientMessageEvent *ptr = (XClientMessageEvent*)myevent;
1505         ptr->type = ClientMessage;
1506         ptr->message_type = event->message_type;
1507         ptr->format = event->format;
1508         ptr->data.l[0] = event->data.l[0];
1509         ptr->data.l[1] = event->data.l[1];
1510         ptr->data.l[2] = event->data.l[2];
1511         ptr->data.l[3] = event->data.l[3];
1512         ptr->data.l[4] = event->data.l[4];
1514         put_event(myevent);
1515         return 0;
1520 Atom BC_WindowBase::create_xatom(char *atom_name)
1522         return XInternAtom(display, atom_name, False);
1525 int BC_WindowBase::get_atoms()
1527         SetDoneXAtom =  create_xatom("BC_REPEAT_EVENT");
1528         RepeaterXAtom = create_xatom("BC_CLOSE_EVENT");
1529         DelWinXAtom =   create_xatom("WM_DELETE_WINDOW");
1530         if(ProtoXAtom = create_xatom("WM_PROTOCOLS"))
1531                 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1532         return 0;
1533         
1537 void BC_WindowBase::init_cursors()
1539         arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1540         cross_cursor = XCreateFontCursor(display, XC_crosshair);
1541         ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1542         vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1543         hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1544         move_cursor = XCreateFontCursor(display, XC_fleur);
1545         left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1546         right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1547         upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1548         upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1549         upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1550         downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1551         downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1552         hourglass_cursor = XCreateFontCursor(display, XC_watch);
1555         char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
1556         Colormap colormap = DefaultColormap(display, screen);
1557         Pixmap pixmap_bottom = XCreateBitmapFromData(display, 
1558                 rootwin,
1559                 cursor_data, 
1560                 8,
1561                 8);
1562         XColor black, dummy;
1563     XAllocNamedColor(display, colormap, "black", &black, &dummy);
1564         transparent_cursor = XCreatePixmapCursor(display,
1565                 pixmap_bottom,
1566                 pixmap_bottom,
1567                 &black,
1568                 &black,
1569                 0,
1570                 0);
1571 //      XDefineCursor(display, win, transparent_cursor);
1572         XFreePixmap(display, pixmap_bottom);
1575 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1577         int color_model;
1578         switch(depth)
1579         {
1580                 case 8:
1581                         color_model = BC_RGB8;
1582                         break;
1583                 case 16:
1584                         color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1585                         break;
1586                 case 24:
1587                         color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1588                         break;
1589                 case 32:
1590                         color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1591                         break;
1592         }
1593         return color_model;
1596 int BC_WindowBase::init_colors()
1598         total_colors = 0;
1599         current_color_value = current_color_pixel = 0;
1601 // Get the real depth
1602         char *data = 0;
1603         XImage *ximage;
1604         ximage = XCreateImage(top_level->display, 
1605                                         top_level->vis, 
1606                                         top_level->default_depth, 
1607                                         ZPixmap, 
1608                                         0, 
1609                                         data, 
1610                                         16, 
1611                                         16, 
1612                                         8, 
1613                                         0);
1614         bits_per_pixel = ximage->bits_per_pixel;
1615         XDestroyImage(ximage);
1617         color_model = evaluate_color_model(client_byte_order, 
1618                 server_byte_order, 
1619                 bits_per_pixel);
1620 // Get the color model
1621         switch(color_model)
1622         {
1623                 case BC_RGB8:
1624                         if(private_color)
1625                         {
1626                                 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1627                                 create_private_colors();
1628                         }
1629                         else
1630                         {
1631                                 cmap = DefaultColormap(display, screen);
1632                                 create_shared_colors();
1633                         }
1635                         allocate_color_table();
1636 // No antialiasing
1637                         get_resources()->use_xft = 0;
1638                         break;
1640                 default:
1641                         cmap = DefaultColormap(display, screen);
1642                         break;
1643         }
1644         return 0;
1647 int BC_WindowBase::create_private_colors()
1649         int color;
1650         total_colors = 256;
1652         for(int i = 0; i < 255; i++)
1653         {
1654                 color = (i & 0xc0) << 16;
1655                 color += (i & 0x38) << 10;
1656                 color += (i & 0x7) << 5;
1657                 color_table[i][0] = color;
1658         }
1659         create_shared_colors();        // overwrite the necessary colors on the table
1660         return 0;
1664 int BC_WindowBase::create_color(int color)
1666         if(total_colors == 256)
1667         {
1668 // replace the closest match with an exact match
1669                 color_table[get_color_rgb8(color)][0] = color;
1670         }
1671         else
1672         {
1673 // add the color to the table
1674                 color_table[total_colors][0] = color;
1675                 total_colors++;
1676         }
1677         return 0;
1680 int BC_WindowBase::create_shared_colors()
1682         create_color(BLACK);
1683         create_color(WHITE);   
1685         create_color(LTGREY);  
1686         create_color(MEGREY);  
1687         create_color(MDGREY);  
1688         create_color(DKGREY);                           
1690         create_color(LTCYAN);  
1691         create_color(MECYAN);  
1692         create_color(MDCYAN);  
1693         create_color(DKCYAN);  
1695         create_color(LTGREEN); 
1696         create_color(GREEN);   
1697         create_color(DKGREEN); 
1699         create_color(LTPINK);  
1700         create_color(PINK);
1701         create_color(RED);     
1703         create_color(LTBLUE);  
1704         create_color(BLUE);    
1705         create_color(DKBLUE);  
1707         create_color(LTYELLOW); 
1708         create_color(MEYELLOW); 
1709         create_color(MDYELLOW); 
1710         create_color(DKYELLOW); 
1712         create_color(LTPURPLE); 
1713         create_color(MEPURPLE); 
1714         create_color(MDPURPLE); 
1715         create_color(DKPURPLE); 
1717         create_color(FGGREY); 
1718         create_color(MNBLUE);
1719         create_color(ORANGE);
1720         create_color(FTGREY);
1722         return 0;
1725 int BC_WindowBase::allocate_color_table()
1727         int red, green, blue, color;
1728         int result;
1729         XColor col;
1731         for(int i = 0; i < total_colors; i++)
1732         {
1733                 color = color_table[i][0];
1734                 red = (color & 0xFF0000) >> 16;
1735                 green = (color & 0x00FF00) >> 8;
1736                 blue = color & 0xFF;
1738                 col.flags = DoRed | DoGreen | DoBlue;
1739                 col.red   = red<<8   | red;
1740                 col.green = green<<8 | green;
1741                 col.blue  = blue<<8  | blue;
1743                 XAllocColor(display, cmap, &col);
1744                 color_table[i][1] = col.pixel;
1745         }
1747         XInstallColormap(display, cmap);
1748         return 0;
1751 int BC_WindowBase::init_window_shape()
1753         if(bg_pixmap && bg_pixmap->use_alpha()) 
1754         {
1755                 XShapeCombineMask(top_level->display,
1756                 this->win,
1757                 ShapeBounding,
1758                 0,
1759                 0,
1760                 bg_pixmap->get_alpha(),
1761                 ShapeSet);
1762         }
1763         return 0;
1767 int BC_WindowBase::init_gc()
1769         unsigned long gcmask;
1770         gcmask = GCFont | GCGraphicsExposures;
1772         XGCValues gcvalues;
1773         gcvalues.font = mediumfont->fid;        // set the font
1774         gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
1775         gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1776         return 0;
1779 int BC_WindowBase::init_fonts()
1781         if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL)
1782                 if((largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1783                         largefont = XLoadQueryFont(display, "fixed"); 
1785         if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL)
1786                 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1787                         mediumfont = XLoadQueryFont(display, "fixed"); 
1789         if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL)
1790                 if((smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1791                         smallfont = XLoadQueryFont(display, "fixed");
1793         init_xft();
1794         if(get_resources()->use_fontset)
1795         {
1796                 char **m, *d;
1797                 int n;
1799 // FIXME: should check the m,d,n values
1800                 if((largefontset = XCreateFontSet(display, 
1801                         resources.large_fontset,
1802             &m, 
1803                         &n, 
1804                         &d)) == 0)
1805             largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1806                 if((mediumfontset = XCreateFontSet(display, 
1807                         resources.medium_fontset,
1808             &m, 
1809                         &n, 
1810                         &d)) == 0)
1811             mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1812                 if((smallfontset = XCreateFontSet(display, 
1813                         resources.small_fontset,
1814             &m, 
1815                         &n, 
1816                         &d)) == 0)
1817             smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1819                 if(largefontset && mediumfontset && smallfontset)
1820                 {
1821                         curr_fontset = mediumfontset;
1822                         get_resources()->use_fontset = 1;
1823                 }
1824                 else
1825                 {
1826                         curr_fontset = 0;
1827                         get_resources()->use_fontset = 0;
1828                 }
1829         }
1831         return 0;
1835 void BC_WindowBase::init_xft()
1837 #ifdef HAVE_XFT
1838         if(!(largefont_xft = XftFontOpenXlfd(display,
1839                 screen,
1840                 resources.large_font_xft)))
1841                 if(!(largefont_xft = XftFontOpenXlfd(display,
1842                         screen,
1843                         resources.large_font_xft2)))
1844                         largefont_xft = XftFontOpenXlfd(display,
1845                         screen,
1846                         "fixed");
1849         if(!(mediumfont_xft = XftFontOpenXlfd(display,
1850                   screen,
1851                   resources.medium_font_xft)))
1852                 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1853                           screen,
1854                           resources.medium_font_xft2)))
1855                         mediumfont_xft = XftFontOpenXlfd(display,
1856                         screen,
1857                         "fixed");
1860         if(!(smallfont_xft = XftFontOpenXlfd(display,
1861               screen,
1862               resources.small_font_xft)))
1863                 if(!(smallfont_xft = XftFontOpenXlfd(display,
1864                   screen,
1865                   resources.small_font_xft2)))
1866                           smallfont_xft = XftFontOpenXlfd(display,
1867                           screen,
1868                           "fixed");
1871 // Extension failed to locate fonts
1872         if(!largefont_xft || !mediumfont_xft || !smallfont_xft)
1873         {
1874                 printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1875                         resources.large_font_xft,
1876                         largefont_xft,
1877                         resources.medium_font_xft,
1878                         mediumfont_xft,
1879                         resources.small_font_xft,
1880                         smallfont_xft);
1881                 get_resources()->use_xft = 0;
1882         }
1883 #endif
1887 int BC_WindowBase::get_color(int64_t color) 
1889 // return pixel of color
1890 // use this only for drawing subwindows not for bitmaps
1891          int i, test, difference, result;
1893         switch(color_model)
1894         {
1895                 case BC_RGB8:
1896                         if(private_color)
1897                         {
1898                                 return get_color_rgb8(color);
1899                         }
1900                         else
1901                         {
1902 // test last color looked up
1903                                 if(current_color_value == color) return current_color_pixel;
1905 // look up in table
1906                                 current_color_value = color;
1907                                 for(i = 0; i < total_colors; i++)
1908                                 {
1909                                         if(color_table[i][0] == color)
1910                                         {
1911                                                 current_color_pixel = color_table[i][1];
1912                                                 return current_color_pixel;
1913                                         }
1914                                 }
1916 // find nearest match
1917                                 difference = 0xFFFFFF;
1919                                 for(i = 0, result = 0; i < total_colors; i++)
1920                                 {
1921                                         test = abs((int)(color_table[i][0] - color));
1923                                         if(test < difference) 
1924                                         {
1925                                                 current_color_pixel = color_table[i][1]; 
1926                                                 difference = test;
1927                                         }
1928                                 }
1930                                 return current_color_pixel;
1931                         }
1932                         break;  
1934                 case BC_RGB565:
1935                         return get_color_rgb16(color);
1936                         break;
1938                 case BC_BGR565:
1939                         return get_color_bgr16(color);
1940                         break;
1942                 case BC_RGB888:
1943                 case BC_BGR888:
1944                         if(client_byte_order == server_byte_order)
1945                                 return color;
1946                         else
1947                                 get_color_bgr24(color);
1948                         break;
1950                 default:
1951                         return color;
1952                         break;  
1953         }
1954         return 0;
1957 int BC_WindowBase::get_color_rgb8(int color)
1959         int pixel;
1961         pixel = (color & 0xc00000) >> 16;
1962         pixel += (color & 0xe000) >> 10;
1963         pixel += (color & 0xe0) >> 5;
1964         return pixel;
1967 int64_t BC_WindowBase::get_color_rgb16(int color)
1969         int64_t result;
1970         result = (color & 0xf80000) >> 8;
1971         result += (color & 0xfc00) >> 5;
1972         result += (color & 0xf8) >> 3;
1973         
1974         return result;
1977 int64_t BC_WindowBase::get_color_bgr16(int color)
1979         int64_t result;
1980         result = (color & 0xf80000) >> 19;
1981         result += (color & 0xfc00) >> 5;
1982         result += (color & 0xf8) << 8;
1984         return result;
1987 int64_t BC_WindowBase::get_color_bgr24(int color)
1989         int64_t result;
1990         result = (color & 0xff) << 16;
1991         result += (color & 0xff00);
1992         result += (color & 0xff0000) >> 16;
1993         return result;
1996 void BC_WindowBase::start_video()
1998         cursor_timer->update();
1999         video_on = 1;
2000 //      set_color(BLACK);
2001 //      draw_box(0, 0, get_w(), get_h());
2002 //      flash();
2005 void BC_WindowBase::stop_video()
2007         video_on = 0;
2008         unhide_cursor();
2013 int64_t BC_WindowBase::get_color()
2015         return top_level->current_color;
2018 void BC_WindowBase::set_color(int64_t color)
2020         top_level->current_color = color;
2021         XSetForeground(top_level->display, 
2022                 top_level->gc, 
2023                 top_level->get_color(color));
2026 void BC_WindowBase::set_opaque()
2028         XSetFunction(top_level->display, top_level->gc, GXcopy);
2031 void BC_WindowBase::set_inverse() 
2033         XSetFunction(top_level->display, top_level->gc, GXxor);
2036 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2038         switch(cursor)
2039         {
2040                 case ARROW_CURSOR:         return top_level->arrow_cursor;                 break;
2041                 case CROSS_CURSOR:         return top_level->cross_cursor;
2042                 case IBEAM_CURSOR:         return top_level->ibeam_cursor;                 break;
2043                 case VSEPARATE_CURSOR:     return top_level->vseparate_cursor;             break;
2044                 case HSEPARATE_CURSOR:     return top_level->hseparate_cursor;             break;
2045                 case MOVE_CURSOR:              return top_level->move_cursor;                  break;
2046                 case LEFT_CURSOR:          return top_level->left_cursor;                  break;
2047                 case RIGHT_CURSOR:         return top_level->right_cursor;                 break;
2048                 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;         break;
2049                 case UPLEFT_RESIZE:        return top_level->upleft_resize_cursor;         break;
2050                 case UPRIGHT_RESIZE:       return top_level->upright_resize_cursor;        break;
2051                 case DOWNLEFT_RESIZE:      return top_level->downleft_resize_cursor;       break;
2052                 case DOWNRIGHT_RESIZE:     return top_level->downright_resize_cursor;      break;
2053                 case HOURGLASS_CURSOR:     return top_level->hourglass_cursor;                 break;
2054                 case TRANSPARENT_CURSOR:   return top_level->transparent_cursor;               break;
2055         }
2056         return 0;
2059 void BC_WindowBase::set_cursor(int cursor, int override)
2061 // don't change cursor if overridden
2062         if((!top_level->is_hourglass && !is_transparent) || 
2063                 override)
2064         {
2065                 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2066                 flush();
2067         }
2069         if(!override) current_cursor = cursor;
2072 void BC_WindowBase::set_x_cursor(int cursor)
2074         temp_cursor = XCreateFontCursor(top_level->display, cursor);
2075         XDefineCursor(top_level->display, win, temp_cursor);
2076         current_cursor = cursor;
2077         flush();
2080 int BC_WindowBase::get_cursor()
2082         return current_cursor;
2085 void BC_WindowBase::start_hourglass()
2087         top_level->start_hourglass_recursive();
2088         top_level->flush();
2091 void BC_WindowBase::stop_hourglass()
2093         top_level->stop_hourglass_recursive();
2094         top_level->flush();
2097 void BC_WindowBase::start_hourglass_recursive()
2099         if(this == top_level)
2100         {
2101                 hourglass_total++;
2102                 is_hourglass = 1;
2103         }
2105         if(!is_transparent)
2106         {
2107                 set_cursor(HOURGLASS_CURSOR, 1);
2108                 for(int i = 0; i < subwindows->total; i++)
2109                 {
2110                         subwindows->values[i]->start_hourglass_recursive();
2111                 }
2112         }
2115 void BC_WindowBase::stop_hourglass_recursive()
2117         if(this == top_level)
2118         {
2119                 if(hourglass_total == 0) return;
2120                 top_level->hourglass_total--;
2121         }
2123         if(!top_level->hourglass_total)
2124         {
2125                 top_level->is_hourglass = 0;
2127 // Cause set_cursor to perform change
2128                 if(!is_transparent)
2129                         set_cursor(current_cursor, 1);
2131                 for(int i = 0; i < subwindows->total; i++)
2132                 {
2133                         subwindows->values[i]->stop_hourglass_recursive();
2134                 }
2135         }
2143 XFontStruct* BC_WindowBase::get_font_struct(int font)
2145 // Clear out unrelated flags
2146         if(font & BOLDFACE) font ^= BOLDFACE;
2147         
2148         switch(font)
2149         {
2150                 case MEDIUMFONT: return top_level->mediumfont; break;
2151                 case SMALLFONT:  return top_level->smallfont;  break;
2152                 case LARGEFONT:  return top_level->largefont;  break;
2153         }
2154         return 0;
2157 XFontSet BC_WindowBase::get_fontset(int font)
2159         XFontSet fs = 0;
2161         if(get_resources()->use_fontset)
2162         {
2163                 switch(font)
2164                 {
2165                         case SMALLFONT:  fs = top_level->smallfontset; break;
2166                         case LARGEFONT:  fs = top_level->largefontset; break;
2167                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2168                 }
2169         }
2171         return fs;
2174 #ifdef HAVE_XFT
2175 XftFont* BC_WindowBase::get_xft_struct(int font)
2177 // Clear out unrelated flags
2178         if(font & BOLDFACE) font ^= BOLDFACE;
2180         switch(font)
2181         {
2182                 case MEDIUMFONT:   return (XftFont*)top_level->mediumfont_xft; break;
2183                 case SMALLFONT:    return (XftFont*)top_level->smallfont_xft;  break;
2184                 case LARGEFONT:    return (XftFont*)top_level->largefont_xft;  break;
2185         }
2187         return 0;
2189 #endif
2201 void BC_WindowBase::set_font(int font)
2203         top_level->current_font = font;
2206 #ifdef HAVE_XFT
2207         if(get_resources()->use_xft)
2208         {
2209                 ;
2210         }
2211         else
2212 #endif
2213         if(get_resources()->use_fontset)
2214         {
2215                 set_fontset(font);
2216         }
2218         if(get_font_struct(font))
2219         {
2220                 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2221         }
2223         return;
2226 void BC_WindowBase::set_fontset(int font)
2228         XFontSet fs = 0;
2230         if(get_resources()->use_fontset)
2231         {
2232                 switch(font)
2233                 {
2234                         case SMALLFONT:  fs = top_level->smallfontset; break;
2235                         case LARGEFONT:  fs = top_level->largefontset; break;
2236                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2237                 }
2238         }
2240         curr_fontset = fs;
2244 XFontSet BC_WindowBase::get_curr_fontset(void)
2246         if(get_resources()->use_fontset)
2247                 return curr_fontset;
2248         return 0;
2251 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2253 #ifdef HAVE_XFT
2254         if(get_resources()->use_xft && get_xft_struct(font))
2255         {
2256                 XGlyphInfo extents;
2257                 XftTextExtents8(top_level->display,
2258                         get_xft_struct(font),
2259                         (FcChar8*)text, 
2260                         length,
2261                         &extents);
2262                 return extents.xOff;
2263         }
2264         else
2265 #endif
2266         if(get_resources()->use_fontset && top_level->get_fontset(font))
2267                 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2268         else
2269         if(get_font_struct(font)) 
2270                 return XTextWidth(get_font_struct(font), text, length);
2271         else
2272         {
2273                 int w = 0;
2274                 switch(font)
2275                 {
2276                         case MEDIUM_7SEGMENT:
2277                                 return get_resources()->medium_7segment[0]->get_w() * length;
2278                                 break;
2280                         default:
2281                                 return 0;
2282                 }
2283                 return w;
2284         }
2287 int BC_WindowBase::get_text_width(int font, char *text, int length)
2289         int i, j, w = 0, line_w = 0;
2290         if(length < 0) length = strlen(text);
2292         for(i = 0, j = 0; i <= length; i++)
2293         {
2294                 line_w = 0;
2295                 if(text[i] == '\n')
2296                 {
2297                         line_w = get_single_text_width(font, &text[j], i - j);
2298                         j = i + 1;
2299                 }
2300                 else
2301                 if(text[i] == 0)
2302                 {
2303                         line_w = get_single_text_width(font, &text[j], length - j);
2304                 }
2305                 if(line_w > w) w = line_w;
2306         }
2308         if(i > length && w == 0)
2309         {
2310                 w = get_single_text_width(font, text, length);
2311         }
2313         return w;
2316 int BC_WindowBase::get_text_ascent(int font)
2318 #ifdef HAVE_XFT
2319         if(get_resources()->use_xft && get_xft_struct(font))
2320         {
2321                 XGlyphInfo extents;
2322                 XftTextExtents8(top_level->display,
2323                         get_xft_struct(font),
2324                         (FcChar8*)"O", 
2325                         1,
2326                         &extents);
2327                 return extents.y + 2;
2328         }
2329         else
2330 #endif
2331         if(get_resources()->use_fontset && top_level->get_fontset(font))
2332         {
2333         XFontSetExtents *extents;
2335         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2336         return -extents->max_logical_extent.y;
2337         }
2338         else
2339         if(get_font_struct(font))
2340                 return top_level->get_font_struct(font)->ascent;
2341         else
2342         switch(font)
2343         {
2344                 case MEDIUM_7SEGMENT:
2345                         return get_resources()->medium_7segment[0]->get_h();
2346                         break;
2348                 default:
2349                         return 0;
2350         }
2353 int BC_WindowBase::get_text_descent(int font)
2355 #ifdef HAVE_XFT
2356         if(get_resources()->use_xft && get_xft_struct(font))
2357         {
2358                 XGlyphInfo extents;
2359                 XftTextExtents8(top_level->display,
2360                         get_xft_struct(font),
2361                         (FcChar8*)"j", 
2362                         1,
2363                         &extents);
2364                 return extents.height - extents.y;
2365         }
2366         else
2367 #endif
2368     if(get_resources()->use_fontset && top_level->get_fontset(font))
2369     {
2370         XFontSetExtents *extents;
2372         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2373         return (extents->max_logical_extent.height
2374                         + extents->max_logical_extent.y);
2375     }
2376     else
2377         if(get_font_struct(font))
2378                 return top_level->get_font_struct(font)->descent;
2379         else
2380         switch(font)
2381         {
2382                 default:
2383                         return 0;
2384         }
2387 int BC_WindowBase::get_text_height(int font, char *text)
2389         if(!text) return get_text_ascent(font) + get_text_descent(font);
2391 // Add height of lines
2392         int h = 0, i, length = strlen(text);
2393         for(i = 0; i <= length; i++)
2394         {
2395                 if(text[i] == '\n')
2396                         h++;
2397                 else
2398                 if(text[i] == 0)
2399                         h++;
2400         }
2401         return h * (get_text_ascent(font) + get_text_descent(font));
2404 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2406         if(color_model < 0) color_model = top_level->get_color_model();
2407         return new BC_Bitmap(top_level, w, h, color_model);
2410 int BC_WindowBase::accel_available(int color_model, int lock_it)
2412         if(window_type != MAIN_WINDOW) 
2413                 return top_level->accel_available(color_model, lock_it);
2415         int result = 0;
2417         if(lock_it) lock_window("BC_WindowBase::accel_available");
2418         switch(color_model)
2419         {
2420                 case BC_YUV420P:
2421                         result = grab_port_id(this, color_model);
2422                         if(result >= 0)
2423                         {
2424                                 xvideo_port_id = result;
2425                                 result = 1;
2426                         }
2427                         else
2428                                 result = 0;
2429                         break;
2431                 case BC_YUV422P:
2432                         result = 0;
2433                         break;
2435                 case BC_YUV422:
2436 //printf("BC_WindowBase::accel_available 1\n");
2437                         result = grab_port_id(this, color_model);
2438 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2439                         if(result >= 0)
2440                         {
2441                                 xvideo_port_id = result;
2442                                 result = 1;
2443                         }
2444                         else
2445                                 result = 0;
2446 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2447                         break;
2449                 default:
2450                         result = 0;
2451                         break;
2452         }
2454         if(lock_it) unlock_window();
2455 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2456         return result;
2460 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2462         int numFormats, i, j, k;
2463         unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2464         int port_id = -1;
2465     XvAdaptorInfo *info;
2466     XvImageFormatValues *formats;
2467         int x_color_model;
2469         if(!get_resources()->use_xvideo) return -1;
2471 // Translate from color_model to X color model
2472         x_color_model = cmodel_bc_to_x(color_model);
2474 // Only local server is fast enough.
2475         if(!resources.use_shm) return -1;
2477 // XV extension is available
2478     if(Success != XvQueryExtension(window->display, 
2479                                   &ver, 
2480                                   &rev, 
2481                                   &reqBase, 
2482                                   &eventBase, 
2483                                   &errorBase))
2484     {
2485                 return -1;
2486     }
2488 // XV adaptors are available
2489         XvQueryAdaptors(window->display, 
2490                 DefaultRootWindow(window->display), 
2491                 &numAdapt, 
2492                 &info);
2494         if(!numAdapt)
2495         {
2496                 return -1;
2497         }
2499 // Get adaptor with desired color model
2500     for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2501     {
2502 /* adaptor supports XvImages */
2503                 if(info[i].type & XvImageMask) 
2504                 {  
2505                 formats = XvListImageFormats(window->display, 
2506                                                         info[i].base_id, 
2507                                                         &numFormats);
2508 // for(j = 0; j < numFormats; j++)
2509 //      printf("%08x\n", formats[j].id);
2511                 for(j = 0; j < numFormats && xvideo_port_id < 0; j++) 
2512                 {
2513 /* this adaptor supports the desired format */
2514                                 if(formats[j].id == x_color_model)
2515                                 {
2516 /* Try to grab a port */
2517                                         for(k = 0; k < info[i].num_ports; k++)
2518                                         {
2519 /* Got a port */
2520                                                 if(Success == XvGrabPort(top_level->display, 
2521                                                         info[i].base_id + k, 
2522                                                         CurrentTime))
2523                                                 {
2524 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2525                                                         xvideo_port_id = info[i].base_id + k;
2526                                                         break;
2527                                                 }
2528                                         }
2529                                 }
2530                         }
2531                 if(formats) XFree(formats);
2532                 }
2533         }
2535     XvFreeAdaptorInfo(info);
2537         return xvideo_port_id;
2541 int BC_WindowBase::show_window(int flush) 
2543         XMapWindow(top_level->display, win); 
2544         if(flush) XFlush(top_level->display);
2545 //      XSync(top_level->display, 0);
2546         hidden = 0; 
2547         return 0;
2550 int BC_WindowBase::hide_window(int flush) 
2552         XUnmapWindow(top_level->display, win); 
2553         if(flush) XFlush(top_level->display);
2554         hidden = 1; 
2555         return 0;
2558 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2560         subwindows->append((BC_SubWindow*)menu_bar);
2562         menu_bar->parent_window = this;
2563         menu_bar->top_level = this->top_level;
2564         menu_bar->initialize();
2565         return menu_bar;
2568 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2570         subwindows->append(subwindow);
2572         if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2574 // parent window must be set before the subwindow initialization
2575         subwindow->parent_window = this;
2576         subwindow->top_level = this->top_level;
2578 // Execute derived initialization
2579         subwindow->initialize();
2580         return subwindow;
2584 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2586         return add_subwindow(subwindow);
2589 BC_WidgetGrid* BC_WindowBase::add_widgetgrid(BC_WidgetGrid *widgetgrid)
2591         widgetgrids->append(widgetgrid);
2592         return widgetgrid;
2596 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2598         set_opaque();
2599         XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
2600         if(x >= 0)
2601         {
2602                 XClearArea(top_level->display, win, x, y, w, h, 0);
2603         }
2604         else
2605         {
2606                 XClearWindow(top_level->display, win);
2607         }
2609         if(flush)
2610                 this->flush();
2611         return 0;
2614 int BC_WindowBase::flash(int flush)
2616         flash(-1, -1, -1, -1, flush);
2619 void BC_WindowBase::flush()
2621         XFlush(top_level->display);
2624 void BC_WindowBase::sync_display()
2626         XSync(top_level->display, False);
2629 int BC_WindowBase::get_window_lock()
2631         return top_level->window_lock;
2634 int BC_WindowBase::lock_window(char *location) 
2636         if(top_level && top_level != this)
2637         {
2638                 top_level->lock_window(location);
2639         }
2640         else
2641         if(top_level)
2642         {
2643                 SET_LOCK(this, title, location);
2644                 XLockDisplay(top_level->display);
2645                 SET_LOCK2
2646                 top_level->window_lock = 1;
2647         }
2648         else
2649         {
2650                 printf("BC_WindowBase::lock_window top_level NULL\n");
2651         }
2652         return 0;
2655 int BC_WindowBase::unlock_window() 
2657         if(top_level && top_level != this)
2658         {
2659                 top_level->unlock_window();
2660         }
2661         else
2662         if(top_level)
2663         {
2664                 UNSET_LOCK(this);
2665                 top_level->window_lock = 0;
2666                 XUnlockDisplay(top_level->display);
2667         }
2668         else
2669         {
2670                 printf("BC_WindowBase::unlock_window top_level NULL\n");
2671         }
2672         return 0;
2675 void BC_WindowBase::set_done(int return_value)
2677         if(window_type != MAIN_WINDOW)
2678                 top_level->set_done(return_value);
2679         else
2680         {
2681                 XEvent *event = new XEvent;
2682                 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2684                 event->type = ClientMessage;
2685                 ptr->message_type = SetDoneXAtom;
2686                 ptr->format = 32;
2687                 this->return_value = return_value;
2689 // May lock up here because XSendEvent doesn't work too well 
2690 // asynchronous with XNextEvent.
2691 // This causes BC_WindowEvents to forward a copy of the event to run_window where 
2692 // it is deleted.
2694 // Deletion of event_thread is done at the end of BC_WindowBase::run_window() - by calling the destructor
2695                 put_event(event);
2696         } 
2699 int BC_WindowBase::get_w()
2701         return w;
2704 int BC_WindowBase::get_h()
2706         return h;
2709 int BC_WindowBase::get_x()
2711         return x;
2714 int BC_WindowBase::get_y()
2716         return y;
2719 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2721         if(lock_display) lock_window("BC_WindowBase::get_root_w");
2722         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2723         int result = WidthOfScreen(screen_ptr);
2724 // Wider than 16:9, narrower than dual head
2725         if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2727         if(lock_display) unlock_window();
2728         return result;
2731 int BC_WindowBase::get_root_h(int lock_display)
2733         if(lock_display) lock_window("BC_WindowBase::get_root_h");
2734         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2735         int result = HeightOfScreen(screen_ptr);
2736         if(lock_display) unlock_window();
2737         return result;
2740 // Bottom right corner
2741 int BC_WindowBase::get_x2()
2743         return w + x;
2746 int BC_WindowBase::get_y2()
2748         return y + h;
2751 int BC_WindowBase::get_video_on()
2753         return video_on;
2756 int BC_WindowBase::get_hidden()
2758         return top_level->hidden;
2761 int BC_WindowBase::cursor_inside()
2763         return (top_level->cursor_x >= 0 && 
2764                         top_level->cursor_y >= 0 && 
2765                         top_level->cursor_x < w && 
2766                         top_level->cursor_y < h);
2769 BC_WindowBase* BC_WindowBase::get_top_level()
2771         return top_level;
2774 BC_WindowBase* BC_WindowBase::get_parent()
2776         return parent_window;
2779 int BC_WindowBase::get_color_model()
2781         return top_level->color_model;
2784 BC_Resources* BC_WindowBase::get_resources()
2786         return &BC_WindowBase::resources;
2789 BC_Synchronous* BC_WindowBase::get_synchronous()
2791         return BC_WindowBase::resources.get_synchronous();
2794 int BC_WindowBase::get_bg_color()
2796         return bg_color;
2799 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2801         return bg_pixmap;
2804 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2806         top_level->active_subwindow = subwindow;
2809 int BC_WindowBase::activate()
2811         return 0;
2814 int BC_WindowBase::deactivate()
2816         if(window_type == MAIN_WINDOW)
2817         {
2818                 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2819                 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2820                 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2822                 top_level->active_menubar = 0;
2823                 top_level->active_popup_menu = 0;
2824                 top_level->active_subwindow = 0;
2825         }
2826         return 0;
2829 int BC_WindowBase::cycle_textboxes(int amount)
2831         int result = 0;
2832         BC_WindowBase *new_textbox = 0;
2834         if(amount > 0)
2835         {
2836                 BC_WindowBase *first_textbox = 0;
2837                 find_next_textbox(&first_textbox, &new_textbox, result);
2838                 if(!new_textbox) new_textbox = first_textbox;
2839                 
2840         }
2841         else
2842         if(amount < 0)
2843         {
2844                 BC_WindowBase *last_textbox = 0;
2845                 find_prev_textbox(&last_textbox, &new_textbox, result);
2846                 if(!new_textbox) new_textbox = last_textbox;
2847                 
2848         }
2850         if(new_textbox != active_subwindow)
2851         {
2852                 deactivate();
2853                 new_textbox->activate();
2854         }
2855         
2856         return 0;
2859 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2861 // Search subwindows for textbox
2862         for(int i = 0; i < subwindows->total && result < 2; i++)
2863         {
2864                 BC_WindowBase *test_subwindow = subwindows->values[i];
2865                 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2866         }
2868         if(result < 2)
2869         {
2870                 if(uses_text())
2871                 {
2872                         if(!*first_textbox) *first_textbox = this;
2874                         if(result < 1)
2875                         {
2876                                 if(top_level->active_subwindow == this)
2877                                         result++;
2878                         }
2879                         else
2880                         {
2881                                 result++;
2882                                 *next_textbox = this;
2883                         }
2884                 }
2885         }
2886         return 0;
2889 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2891         if(result < 2)
2892         {
2893                 if(uses_text())
2894                 {
2895                         if(!*last_textbox) *last_textbox = this;
2897                         if(result < 1)
2898                         {
2899                                 if(top_level->active_subwindow == this)
2900                                         result++;
2901                         }
2902                         else
2903                         {
2904                                 result++;
2905                                 *prev_textbox = this;
2906                         }
2907                 }
2908         }
2910 // Search subwindows for textbox
2911         for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2912         {
2913                 BC_WindowBase *test_subwindow = subwindows->values[i];
2914                 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2915         }
2916         return 0;
2919 BC_Clipboard* BC_WindowBase::get_clipboard()
2921         return top_level->clipboard;
2924 int BC_WindowBase::get_relative_cursor_x()
2926         int abs_x, abs_y, x, y, win_x, win_y;
2927         unsigned int temp_mask;
2928         Window temp_win;
2930         XQueryPointer(top_level->display, 
2931            top_level->win, 
2932            &temp_win, 
2933            &temp_win,
2934        &abs_x, 
2935            &abs_y, 
2936            &win_x, 
2937            &win_y, 
2938            &temp_mask);
2940         XTranslateCoordinates(top_level->display, 
2941                         top_level->rootwin, 
2942                         win, 
2943                         abs_x, 
2944                         abs_y, 
2945                         &x, 
2946                         &y, 
2947                         &temp_win);
2949         return x;
2952 int BC_WindowBase::get_relative_cursor_y()
2954         int abs_x, abs_y, x, y, win_x, win_y;
2955         unsigned int temp_mask;
2956         Window temp_win;
2958         XQueryPointer(top_level->display, 
2959            top_level->win, 
2960            &temp_win, 
2961            &temp_win,
2962        &abs_x, 
2963            &abs_y, 
2964            &win_x, 
2965            &win_y, 
2966            &temp_mask);
2968         XTranslateCoordinates(top_level->display, 
2969                         top_level->rootwin, 
2970                         win, 
2971                         abs_x, 
2972                         abs_y, 
2973                         &x, 
2974                         &y, 
2975                         &temp_win);
2977         return y;
2980 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2982         int abs_x, abs_y, win_x, win_y;
2983         unsigned int temp_mask;
2984         Window temp_win;
2986         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2987         XQueryPointer(top_level->display, 
2988                 top_level->win, 
2989                 &temp_win, 
2990                 &temp_win,
2991                 &abs_x, 
2992                 &abs_y, 
2993                 &win_x, 
2994                 &win_y, 
2995                 &temp_mask);
2996         if(lock_window) this->unlock_window();
2997         return abs_x;
3000 int BC_WindowBase::get_abs_cursor_y(int lock_window)
3002         int abs_x, abs_y, win_x, win_y;
3003         unsigned int temp_mask;
3004         Window temp_win;
3006         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
3007         XQueryPointer(top_level->display, 
3008                 top_level->win, 
3009                 &temp_win, 
3010                 &temp_win,
3011         &abs_x, 
3012                 &abs_y, 
3013                 &win_x, 
3014                 &win_y, 
3015                 &temp_mask);
3016         if(lock_window) this->unlock_window();
3017         return abs_y;
3020 int BC_WindowBase::match_window(Window win) 
3022         if (this->win == win) return 1;
3023         int result = 0;
3024         for(int i = 0; i < subwindows->total; i++)
3025         {
3026                 result = subwindows->values[i]->match_window(win);
3027                 if (result) return result;
3028         }
3029         return 0;
3033 int BC_WindowBase::get_cursor_over_window()
3035         if(top_level != this) return top_level->get_cursor_over_window();
3037         int abs_x, abs_y, win_x, win_y;
3038         unsigned int temp_mask;
3039         Window temp_win1, temp_win2;
3041         if (!XQueryPointer(display, 
3042                 win, 
3043                 &temp_win1, 
3044                 &temp_win2,
3045                 &abs_x, 
3046                 &abs_y, 
3047                 &win_x, 
3048                 &win_y, 
3049                 &temp_mask))
3050                 return 0;
3052         int result = match_window(temp_win2)    ;
3053         return result;
3056 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
3058         int x, y;
3059         Window tempwin;
3061         translate_coordinates(top_level->event_win, 
3062                 pov->win,
3063                 top_level->cursor_x,
3064                 top_level->cursor_y,
3065                 &x,
3066                 &y);
3067         return x;
3070 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
3072         int x, y;
3073         Window tempwin;
3075         translate_coordinates(top_level->event_win, 
3076                 pov->win,
3077                 top_level->cursor_x,
3078                 top_level->cursor_y,
3079                 &x,
3080                 &y);
3081         return y;
3084 int BC_WindowBase::get_drag_x()
3086         return top_level->drag_x;
3089 int BC_WindowBase::get_drag_y()
3091         return top_level->drag_y;
3094 int BC_WindowBase::get_cursor_x()
3096         return top_level->cursor_x;
3099 int BC_WindowBase::get_cursor_y()
3101         return top_level->cursor_y;
3104 int BC_WindowBase::is_event_win()
3106         return this->win == top_level->event_win;
3109 void BC_WindowBase::set_dragging(int value)
3111         is_dragging = value;
3114 int BC_WindowBase::get_dragging()
3116         return is_dragging;
3119 int BC_WindowBase::get_buttonpress()
3121         return top_level->button_number;
3124 int BC_WindowBase::get_button_down()
3126         return top_level->button_down;
3129 int BC_WindowBase::alt_down()
3131         return top_level->alt_mask;
3134 int BC_WindowBase::shift_down()
3136         return top_level->shift_mask;
3139 int BC_WindowBase::ctrl_down()
3141         return top_level->ctrl_mask;
3145 int BC_WindowBase::get_keypress()
3147         return top_level->key_pressed;
3150 int BC_WindowBase::get_double_click()
3152         return top_level->double_click;
3155 int BC_WindowBase::get_bgcolor()
3157         return bg_color;
3160 int BC_WindowBase::resize_window(int w, int h)
3162         if(window_type == MAIN_WINDOW && !allow_resize)
3163         {
3164                 XSizeHints size_hints;
3165                 size_hints.flags = PSize | PMinSize | PMaxSize;
3166                 size_hints.width = w;
3167                 size_hints.height = h;
3168                 size_hints.min_width = w;
3169                 size_hints.max_width = w; 
3170                 size_hints.min_height = h;
3171                 size_hints.max_height = h; 
3172                 XSetNormalHints(top_level->display, win, &size_hints);
3173         }
3174         XResizeWindow(top_level->display, win, w, h);
3176         this->w = w;
3177         this->h = h;
3178         delete pixmap;
3179         pixmap = new BC_Pixmap(this, w, h);
3181 // Propagate to menubar
3182         for(int i = 0; i < subwindows->total; i++)
3183         {
3184                 subwindows->values[i]->dispatch_resize_event(w, h);
3185         }
3187         draw_background(0, 0, w, h);
3188         if(top_level == this && get_resources()->recursive_resizing)
3189                 resize_history.append(new BC_ResizeCall(w, h));
3190         return 0;
3193 // The only way for resize events to be propagated is by updating the internal w and h
3194 int BC_WindowBase::resize_event(int w, int h)
3196         if(window_type == MAIN_WINDOW)
3197         {
3198                 this->w = w;
3199                 this->h = h;
3200         }
3201         return 0;
3204 int BC_WindowBase::reposition_widget(int x, int y, int w, int h) 
3206   return(reposition_window(x, y, w, h));
3209 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3211         int resize = 0;
3213 // Some tools set their own dimensions before calling this, causing the 
3214 // resize check to skip.
3215         this->x = x;
3216         this->y = y;
3218         if(w > 0 && w != this->w)
3219         {
3220                 resize = 1;
3221                 this->w = w;
3222         }
3224         if(h > 0 && h != this->h)
3225         {
3226                 resize = 1;
3227                 this->h = h;
3228         }
3230 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3232         if(this->w <= 0)
3233                 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3234         if(this->h <= 0)
3235                 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3237         if(translation_count && window_type == MAIN_WINDOW)
3238         {
3239 // KDE shifts window right and down.
3240 // FVWM leaves window alone and adds border around it.
3241                 XMoveResizeWindow(top_level->display, 
3242                         win, 
3243                         x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x, 
3244                         y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y, 
3245                         this->w,
3246                         this->h);
3247         }
3248         else
3249         {
3250                 XMoveResizeWindow(top_level->display, 
3251                         win, 
3252                         x, 
3253                         y, 
3254                         this->w, 
3255                         this->h);
3256         }
3258         if(resize)
3259         {
3260                 delete pixmap;
3261                 pixmap = new BC_Pixmap(this, this->w, this->h);
3262 // Propagate to menubar
3263                 for(int i = 0; i < subwindows->total; i++)
3264                 {
3265                         subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3266                 }
3268 //              draw_background(0, 0, w, h);
3269         }
3271         return 0;
3274 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3276         get_resources()->tooltips_enabled = tooltips_enabled;
3277         return 0;
3280 int BC_WindowBase::raise_window(int do_flush)
3282         XRaiseWindow(top_level->display, win);
3283         if(do_flush) XFlush(top_level->display);
3284         return 0;
3287 void BC_WindowBase::set_background(VFrame *bitmap)
3289         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3291         bg_pixmap = new BC_Pixmap(this, 
3292                         bitmap, 
3293                         PIXMAP_OPAQUE);
3294         shared_bg_pixmap = 0;
3295         draw_background(0, 0, w, h);
3298 void BC_WindowBase::set_title(char *text)
3300         XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0); 
3301         strcpy(this->title, _(text));
3302         flush();
3305 char* BC_WindowBase::get_title()
3307         return title;
3310 int BC_WindowBase::get_toggle_value()
3312         return toggle_value;
3315 int BC_WindowBase::get_toggle_drag()
3317         return toggle_drag;
3320 int BC_WindowBase::set_icon(VFrame *data)
3322         if(icon_pixmap) delete icon_pixmap;
3323         icon_pixmap = new BC_Pixmap(top_level, 
3324                 data, 
3325                 PIXMAP_ALPHA,
3326                 1);
3328         icon_window = new BC_Popup(this, 
3329                 (int)BC_INFINITY, 
3330                 (int)BC_INFINITY, 
3331                 icon_pixmap->get_w(), 
3332                 icon_pixmap->get_h(), 
3333                 -1, 
3334                 1, // All windows are hidden initially
3335                 icon_pixmap);
3337         XWMHints wm_hints;
3338         wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3339         wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3340         wm_hints.icon_mask = icon_pixmap->get_alpha();
3341         wm_hints.icon_window = icon_window->win;
3342         wm_hints.window_group = XGroupLeader;
3344 // for(int i = 0; i < 1000; i++)
3345 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3346 // printf("\n");
3348         XSetWMHints(top_level->display, top_level->win, &wm_hints);
3349         XSync(top_level->display, 0);
3350         return 0;
3353 int BC_WindowBase::set_w(int w)
3355         this->w = w;
3356         return 0;
3359 int BC_WindowBase::set_h(int h)
3361         this->h = h;
3362         return 0;
3365 int BC_WindowBase::load_defaults(BC_Hash *defaults)
3367         BC_Resources *resources = get_resources();
3368         char string[BCTEXTLEN];
3369         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3370         {
3371                 sprintf(string, "FILEBOX_HISTORY%d", i);
3372                 resources->filebox_history[i][0] = 0;
3373                 defaults->get(string, resources->filebox_history[i]);
3374         }
3375         resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3376         resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3377         resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3378         defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3379         return 0;
3382 int BC_WindowBase::save_defaults(BC_Hash *defaults)
3384         BC_Resources *resources = get_resources();
3385         char string[BCTEXTLEN];
3386         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3387         {
3388                 sprintf(string, "FILEBOX_HISTORY%d", i);
3389                 defaults->update(string, resources->filebox_history[i]);
3390         }
3391         defaults->update("FILEBOX_MODE", resources->filebox_mode);
3392         defaults->update("FILEBOX_W", resources->filebox_w);
3393         defaults->update("FILEBOX_H", resources->filebox_h);
3394         defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3395         return 0;
3400 // For some reason XTranslateCoordinates can take a long time to return.
3401 // We work around this by only calling it when the event windows are different.
3402 void BC_WindowBase::translate_coordinates(Window src_w, 
3403                 Window dest_w,
3404                 int src_x,
3405                 int src_y,
3406                 int *dest_x_return,
3407                 int *dest_y_return)
3409         Window tempwin = 0;
3410 //Timer timer;
3411 //timer.update();
3412         if(src_w == dest_w)
3413         {
3414                 *dest_x_return = src_x;
3415                 *dest_y_return = src_y;
3416         }
3417         else
3418         {
3419                 XTranslateCoordinates(top_level->display, 
3420                         src_w, 
3421                         dest_w, 
3422                         src_x, 
3423                         src_y, 
3424                         dest_x_return, 
3425                         dest_y_return,
3426                         &tempwin);
3427 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3428         }
3437 #ifdef HAVE_LIBXXF86VM
3438 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3440    int foo,bar;
3441    *vm = 0;
3442    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3443            int vm_count,i;
3444            XF86VidModeModeInfo **vm_modelines;
3445            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3446            for (i = 0; i < vm_count; i++) {
3447                    if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3448                            *vm = i;
3449            }
3450            display = top_level->display;
3451            if (vm_modelines[*vm]->hdisplay == *width)
3452                    *vm = -1;
3453            else
3454            {
3455                    *width = vm_modelines[*vm]->hdisplay;
3456                    *height = vm_modelines[*vm]->vdisplay;
3457            }
3458    }
3461 void BC_WindowBase::scale_vm(int vm)
3463    int foo,bar,dotclock;
3464    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3465    {
3466            int vm_count;
3467            XF86VidModeModeInfo **vm_modelines;
3468            XF86VidModeModeLine vml;
3469            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3470            XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3471            orig_modeline.dotclock = dotclock;
3472            orig_modeline.hdisplay = vml.hdisplay;
3473            orig_modeline.hsyncstart = vml.hsyncstart;
3474            orig_modeline.hsyncend = vml.hsyncend;
3475            orig_modeline.htotal = vml.htotal;
3476            orig_modeline.vdisplay = vml.vdisplay;
3477            orig_modeline.vsyncstart = vml.vsyncstart;
3478            orig_modeline.vsyncend = vml.vsyncend;
3479            orig_modeline.vtotal = vml.vtotal;
3480            orig_modeline.flags = vml.flags;
3481            orig_modeline.privsize = vml.privsize;
3482            // orig_modeline.private = vml.private;
3483            XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3484            XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3485            XFlush(top_level->display);
3486    }
3489 void BC_WindowBase::restore_vm()
3491    XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3492    XFlush(top_level->display);
3496 #endif
3516 int BC_WindowBase::get_event_count()
3518         event_lock->lock("BC_WindowBase::get_event_count");
3519         int result = common_events.total;
3520         event_lock->unlock();
3521         return result;
3524 XEvent* BC_WindowBase::get_event()
3526         XEvent *result = 0;
3527         while(!done && !result)
3528         {
3529                 event_condition->lock("BC_WindowBase::get_event");
3530                 event_lock->lock("BC_WindowBase::get_event");
3532                 if(common_events.total && !done)
3533                 {
3534                         result = common_events.values[0];
3535                         common_events.remove_number(0);
3536                 }
3538                 event_lock->unlock();
3539         }
3540         return result;
3543 void BC_WindowBase::put_event(XEvent *event)
3545         event_lock->lock("BC_WindowBase::put_event");
3546         common_events.append(event);
3547         event_lock->unlock();
3548         event_condition->unlock();
3551 int BC_WindowBase::get_id()
3553         return id;