r851: Merge 2.1:
[cinelerra_cv/ct.git] / guicast / bcwindowbase.C
blobd02bdcb60bde2af79be9a14f38091b74f5046e14
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 "bctimer.h"
13 #include "bcwidgetgrid.h"
14 #include "bcwindowbase.h"
15 #include "bcwindowevents.h"
16 #include "colormodels.h"
17 #include "colors.h"
18 #include "condition.h"
19 #include "cursors.h"
20 #include "bchash.h"
21 #include "fonts.h"
22 #include "keys.h"
23 #include "language.h"
24 #include "mutex.h"
25 #include "sizes.h"
26 #include "vframe.h"
28 #ifdef HAVE_GL
29 #include <GL/gl.h>
30 #endif
31 #include <string.h>
32 #include <unistd.h>
34 #include <X11/extensions/Xvlib.h>
35 #include <X11/extensions/shape.h>
38 BC_ResizeCall::BC_ResizeCall(int w, int h)
40         this->w = w;
41         this->h = h;
53 Mutex BC_WindowBase::opengl_lock;
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                         // NOTE: since the value is itself a subwindow, the
92                         //       recursion removes the item from subwindows
93                         delete subwindows->values[0];
94                 }
95                 delete subwindows;
96         }
98         if(widgetgrids)
99         {
100                 while (widgetgrids->total) 
101                 {
102                         delete widgetgrids->last();
103                         widgetgrids->remove();
104                 }
105                 delete widgetgrids;
106         }
107                 
109                 delete pixmap;
111         XDestroyWindow(top_level->display, win);
113         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
114         if(icon_pixmap) delete icon_pixmap;
115         if(temp_bitmap) delete temp_bitmap;
121         if(window_type == MAIN_WINDOW) 
122         {
123                 XFreeGC(display, gc);
124 #ifdef HAVE_XFT
125                 if(largefont_xft) 
126                         XftFontClose (display, (XftFont*)largefont_xft);
127                 if(mediumfont_xft) 
128                         XftFontClose (display, (XftFont*)mediumfont_xft);
129                 if(smallfont_xft) 
130                         XftFontClose (display, (XftFont*)smallfont_xft);
131 #endif
132                 flush();
133 // Can't close display if another thread is waiting for events
134                 XCloseDisplay(display);
135 //              XCloseDisplay(event_display);
136                 clipboard->stop_clipboard();
137                 delete clipboard;
138         }
139         else
140         {
141                 flush();
142         }
144         resize_history.remove_all_objects();
145         common_events.remove_all_objects();
146         delete event_lock;
147         delete event_condition;
149         UNSET_ALL_LOCKS(this)
152 int BC_WindowBase::initialize()
154         test_keypress = 0;
155         is_deleting = 0;
156         window_lock = 0;
157         x = 0; 
158         y = 0; 
159         w = 0; 
160         h = 0;
161         bg_color = -1;
162         top_level = 0;
163         parent_window = 0;
164         subwindows = 0;
165         widgetgrids = 0;
166         xvideo_port_id = -1;
167         video_on = 0;
168         motion_events = 0;
169         resize_events = 0;
170         translation_events = 0;
171         ctrl_mask = shift_mask = alt_mask = 0;
172         cursor_x = cursor_y = button_number = 0;
173         button_down = 0;
174         button_pressed = 0;
175         button_time1 = button_time2 = 0;
176         double_click = 0;
177         last_motion_win = 0;
178         key_pressed = 0;
179         active_menubar = 0;
180         active_popup_menu = 0;
181         active_subwindow = 0;
182         pixmap = 0;
183         bg_pixmap = 0;
184         tooltip_text[0] = 0;
185         persistant_tooltip = 0;
186 //      next_repeat_id = 0;
187         tooltip_popup = 0;
188         tooltip_done = 0;
189         current_font = MEDIUMFONT;
190         current_color = BLACK;
191         current_cursor = ARROW_CURSOR;
192         hourglass_total = 0;
193         is_dragging = 0;
194         shared_bg_pixmap = 0;
195         icon_pixmap = 0;
196         window_type = MAIN_WINDOW;
197         translation_count = 0;
198         x_correction = y_correction = 0;
199         temp_bitmap = 0;
200         tooltip_on = 0;
201         temp_cursor = 0;
202         toggle_value = 0;
203         toggle_drag = 0;
204         has_focus = 0;
205         is_hourglass = 0;
206         is_transparent = 0;
207 #ifdef HAVE_LIBXXF86VM
208     vm_switched = 0;
209 #endif
210         xft_drawable = 0;
211         largefont_xft = 0;
212         mediumfont_xft = 0;
213         smallfont_xft = 0;
214 // Need these right away since put_event is called before run_window sometimes.
215         event_lock = new Mutex("BC_WindowBase::event_lock");
216         event_condition = new Condition(0, "BC_WindowBase::event_condition");
217         cursor_timer = new Timer;
218         event_thread = 0;
220         return 0;
223 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
224                         LeaveWindowMask | \
225                         ButtonPressMask | \
226                         ButtonReleaseMask | \
227                         PointerMotionMask | \
228                         FocusChangeMask
229                         
231 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
232                                 char *title, 
233                                 int x,
234                                 int y,
235                                 int w, 
236                                 int h, 
237                                 int minw, 
238                                 int minh, 
239                                 int allow_resize,
240                                 int private_color, 
241                                 int hide,
242                                 int bg_color,
243                                 char *display_name,
244                                 int window_type,
245                                 BC_Pixmap *bg_pixmap,
246                                 int group_it)
248         XSetWindowAttributes attr;
249         unsigned long mask;
250         XSizeHints size_hints;
251         int root_w;
252         int root_h;
253 #ifdef HAVE_LIBXXF86VM
254     int vm;
255 #endif
257     if(parent_window) top_level = parent_window->top_level;
259 #ifdef HAVE_LIBXXF86VM
260     if(window_type == VIDMODE_SCALED_WINDOW)
261             closest_vm(&vm,&w,&h);
262 #endif
264         this->x = x;
265         this->y = y;
266         this->w = w;
267         this->h = h;
268         this->bg_color = bg_color;
269         this->window_type = window_type;
270         this->hidden = hide;
271         this->private_color = private_color;
272         this->parent_window = parent_window;
273         this->bg_pixmap = bg_pixmap;
274         this->allow_resize = allow_resize;
275         strcpy(this->title, _(title));
276         if(bg_pixmap) shared_bg_pixmap = 1;
278         if(parent_window) top_level = parent_window->top_level;
280         subwindows = new BC_SubWindowList;
281         widgetgrids = new BC_WidgetGridList;
283 // Mandatory setup
284         if(window_type == MAIN_WINDOW)
285         {
286                 top_level = this;
287                 parent_window = this;
289 // This function must be the first Xlib
290 // function a multi-threaded program calls
291                 XInitThreads();
294 // get the display connection
295                 display = init_display(display_name);
296 //              event_display = init_display(display_name);
298 // Fudge window placement
299                 root_w = get_root_w(1, 0);
300                 root_h = get_root_h(0);
301                 if(this->x + this->w > root_w) this->x = root_w - this->w;
302                 if(this->y + this->h > root_h) this->y = root_h - this->h;
303                 if(this->x < 0) this->x = 0;
304                 if(this->y < 0) this->y = 0;
305                 screen = DefaultScreen(display);
306                 rootwin = RootWindow(display, screen);
309                 vis = DefaultVisual(display, screen);
310                 default_depth = DefaultDepth(display, screen);
312                 client_byte_order = (*(u_int32_t*)"a   ") & 0x00000001;
313                 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
316 // This must be done before fonts to know if antialiasing is available.
317                 init_colors();
318 // get the resources
319                 if(resources.use_shm < 0) resources.initialize_display(this);
320                 x_correction = get_resources()->get_left_border();
321                 y_correction = get_resources()->get_top_border();
323                 if(this->bg_color == -1)
324                         this->bg_color = resources.get_bg_color();
326 // printf("bcwindowbase 1 %s\n", title);
327 // if(window_type == MAIN_WINDOW) sleep(1);
328 // printf("bcwindowbase 10\n");
329                 init_fonts();
330                 init_gc();
331                 init_cursors();
333 // Create the window
334                 mask = CWEventMask | 
335                                 CWBackPixel | 
336                                 CWColormap | 
337                                 CWCursor;
339                 attr.event_mask = DEFAULT_EVENT_MASKS |
340                         StructureNotifyMask | 
341                         KeyPressMask;
343                 attr.background_pixel = get_color(this->bg_color);
344                 attr.colormap = cmap;
345                 attr.cursor = get_cursor_struct(ARROW_CURSOR);
347                 win = XCreateWindow(display, 
348                         rootwin, 
349                         this->x, 
350                         this->y, 
351                         this->w, 
352                         this->h, 
353                         0, 
354                         top_level->default_depth, 
355                         InputOutput, 
356                         vis, 
357                         mask, 
358                         &attr);
360                 XGetNormalHints(display, win, &size_hints);
362                 size_hints.flags = PSize | PMinSize | PMaxSize;
363                 size_hints.width = this->w;
364                 size_hints.height = this->h;
365                 size_hints.min_width = allow_resize ? minw : this->w;
366                 size_hints.max_width = allow_resize ? 32767 : this->w; 
367                 size_hints.min_height = allow_resize ? minh : this->h;
368                 size_hints.max_height = allow_resize ? 32767 : this->h; 
369                 if(x > -BC_INFINITY && x < BC_INFINITY)
370                 {
371                         size_hints.flags |= PPosition;
372                         size_hints.x = this->x;
373                         size_hints.y = this->y;
374                 }
376                 XSetStandardProperties(display, 
377                         win, 
378                         title, 
379                         title, 
380                         None, 
381                         0, 
382                         0, 
383                         &size_hints);
384                 get_atoms();
385                 
386                 clipboard = new BC_Clipboard(display_name);
387                 clipboard->start_clipboard();
389                 if (group_it)
390                 {
391                         Atom ClientLeaderXAtom;
392                         if (XGroupLeader == 0)
393                                 XGroupLeader = win;
394                         char *instance_name = "cinelerra";
395                         char *class_name = "Cinelerra";
396                         XClassHint *class_hints = XAllocClassHint(); 
397                         class_hints->res_name = instance_name;
398                         class_hints->res_class = class_name;
399                         XSetClassHint(top_level->display, win, class_hints);
400                         XFree(class_hints);
401                         ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
402                         XChangeProperty(display, 
403                                         win, 
404                                         ClientLeaderXAtom, 
405                                         XA_WINDOW, 
406                                         32, 
407                                         PropModeReplace, 
408                                         (unsigned char *)&XGroupLeader, 
409                                         true);
411                 }
412                 
413         }
415 #ifdef HAVE_LIBXXF86VM
416     if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
417     {
418             scale_vm (vm);
419             vm_switched = 1;
420     }
421 #endif
423 #ifdef HAVE_LIBXXF86VM
424     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
425 #else
426     if(window_type == POPUP_WINDOW)
427 #endif
428         {
429                 mask = CWEventMask | 
430                         CWBackPixel | 
431                         CWColormap | 
432                         CWOverrideRedirect | 
433                         CWSaveUnder | 
434                         CWCursor;
436                 attr.event_mask = DEFAULT_EVENT_MASKS |
437                         KeyPressMask;
439                 if(this->bg_color == -1)
440                         this->bg_color = resources.get_bg_color();
441                 attr.background_pixel = top_level->get_color(bg_color);
442                 attr.colormap = top_level->cmap;
443                 if(top_level->is_hourglass)
444                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
445                 else
446                 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
447                 attr.override_redirect = True;
448                 attr.save_under = True;
450                 win = XCreateWindow(top_level->display, 
451                         top_level->rootwin, 
452                         this->x, 
453                         this->y, 
454                         this->w, 
455                         this->h, 
456                         0, 
457                         top_level->default_depth, 
458                         InputOutput, 
459                         top_level->vis, 
460                         mask, 
461                         &attr);
462         }
464         if(window_type == SUB_WINDOW)
465         {
466                 mask = CWBackPixel | 
467                         CWEventMask | 
468                         CWCursor;
469                 attr.event_mask = DEFAULT_EVENT_MASKS;
470                 attr.background_pixel = top_level->get_color(this->bg_color);
471                 if(top_level->is_hourglass)
472                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
473                 else
474                         attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
475                 win = XCreateWindow(top_level->display, 
476                         parent_window->win, 
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                 init_window_shape();
488                 XMapWindow(top_level->display, win);
489         }
491 // Create pixmap for all windows
492         pixmap = new BC_Pixmap(this, this->w, this->h);
495 // Create truetype rendering surface
496 #ifdef HAVE_XFT
497         if(get_resources()->use_xft)
498         {
499 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n", 
500 // top_level->display,
501 // pixmap,
502 // top_level->vis,
503 // top_level->cmap);
504                 xft_drawable = XftDrawCreate(top_level->display,
505                        pixmap,
506                        top_level->vis,
507                        top_level->cmap);
508 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n", 
509 // xft_drawable, 
510 // top_level->display,
511 // pixmap,
512 // top_level->vis,
513 // top_level->cmap);
514         }
515 #endif
517 // Set up options for main window
518         if(window_type == MAIN_WINDOW)
519         {
520                 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
521                 {
522                         this->bg_pixmap = new BC_Pixmap(this, 
523                                 get_resources()->bg_image, 
524                                 PIXMAP_OPAQUE);
525                 }
527                 if(!hidden) show_window();
529         }
534         draw_background(0, 0, this->w, this->h);
535         flash();
537 // Set up options for popup window
538 #ifdef HAVE_LIBXXF86VM
539     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
540 #else
541     if(window_type == POPUP_WINDOW)
542 #endif
543         {
544                 init_window_shape();
545                 if(!hidden) show_window();
546         }
547         return 0;
550 Display* BC_WindowBase::init_display(char *display_name)
552         Display* display;
554         if(display_name && display_name[0] == 0) display_name = NULL;
555         if((display = XOpenDisplay(display_name)) == NULL)
556         {
557                 printf("BC_WindowBase::init_display: cannot connect to X server %s\n", 
558                         display_name);
559                 if(getenv("DISPLAY") == NULL)
560         {
561                         printf("'DISPLAY' environment variable not set.\n");
562                         exit(1);
563                 }
564                 else
565 // Try again with default display.
566                 {
567                         if((display = XOpenDisplay(0)) == NULL)
568                         {
569                                 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
570                                 exit(1);
571                         }
572                 }
573         }
574         return display;
577 int BC_WindowBase::run_window()
579         done = 0;
580         return_value = 0;
583 // Events may have been sent before run_window so can't initialize them here.
585 // Start tooltips
586         if(window_type == MAIN_WINDOW)
587         {
588 //              tooltip_id = get_repeat_id();
589                 set_repeat(get_resources()->tooltip_delay);
590         }
592 // Start X server events
593         event_thread = new BC_WindowEvents(this);
594         event_thread->start();
596 // Start common events
597         while(!done)
598         {
599                 dispatch_event();
600         }
602         unset_all_repeaters();
603         hide_tooltip();
604         delete event_thread;
605         event_thread = 0;
606         event_condition->reset();
607         common_events.remove_all_objects();
608         done = 0;
610         return return_value;
613 int BC_WindowBase::get_key_masks(XEvent *event)
615 // printf("BC_WindowBase::get_key_masks %llx\n", 
616 // event->xkey.state);
617 // ctrl key down
618         ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
619 // shift key down
620         shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
621         alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
622         return 0;
631 int BC_WindowBase::dispatch_event()
633         XEvent *event = 0;
634     Window tempwin;
635         KeySym keysym;
636         char keys_return[2];
637         int result;
638         XClientMessageEvent *ptr;
639         int temp;
640         int cancel_resize, cancel_translation;
642         key_pressed = 0;
644 // If an event is waiting get it, otherwise
645 // wait for next event only if there are no compressed events.
646         if(get_event_count() || 
647                 (!motion_events && !resize_events && !translation_events))
648         {
649 //              XNextEvent(display, event);
650                 event = get_event();
651 // Lock out window deletions
652                 lock_window("BC_WindowBase::dispatch_event 1");
653 //              get_key_masks(event);
654         }
655         else
656 // Handle compressed events
657         {
658                 lock_window("BC_WindowBase::dispatch_event 2");
659                 if(resize_events)
660                         dispatch_resize_event(last_resize_w, last_resize_h);
661                 else
662                 if(motion_events)
663                         dispatch_motion_event();
664                 else
665                 if(translation_events)
666                         dispatch_translation_event();
668                 unlock_window();
669                 return 0;
670         }
672 //printf("1 %s %p %d\n", title, event, event->type);
673         switch(event->type)
674         {
675                 case ClientMessage:
676                         get_key_masks(event);
677 // Clear the resize buffer
678                         if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
679 // Clear the motion buffer since this can clear the window
680                         if(motion_events)
681                         {
682                                 dispatch_motion_event();
683                         }
685                         ptr = (XClientMessageEvent*)event;
688                 if(ptr->message_type == ProtoXAtom && 
689                                 ptr->data.l[0] == DelWinXAtom)
690                 {
691                                 close_event();
692                         }
693                         else
694                         if(ptr->message_type == RepeaterXAtom)
695                         {
696                                 dispatch_repeat_event(ptr->data.l[0]);
697 // Make sure the repeater still exists.
698 //                              for(int i = 0; i < repeaters.total; i++)
699 //                              {
700 //                                      if(repeaters.values[i]->repeat_id == ptr->data.l[0])
701 //                                      {
702 //                                              dispatch_repeat_event_master(ptr->data.l[0]);
703 //                                              break;
704 //                                      }
705 //                              }
706                         }
707                         else
708                         if(ptr->message_type == SetDoneXAtom)
709                         {
710                                 done = 1;
711                         }
712                         break;
714                 case FocusIn:
715                         has_focus = 1;
716                         dispatch_focus_in();
717                         break;
719                 case FocusOut:
720                         has_focus = 0;
721                         dispatch_focus_out();
722                         break;
724 // Maximized
725                 case MapNotify:
726                         break;
728 // Minimized
729                 case UnmapNotify:
730                         break;
732                 case ButtonPress:
733                         get_key_masks(event);
734                         cursor_x = event->xbutton.x;
735                         cursor_y = event->xbutton.y;
736                         button_number = event->xbutton.button;
737                         event_win = event->xany.window;
738                         if (button_number != 4 && button_number != 5)
739                                 button_down = 1;
740                         button_pressed = event->xbutton.button;
741                         button_time1 = button_time2;
742                         button_time2 = event->xbutton.time;
743                         drag_x = cursor_x;
744                         drag_y = cursor_y;
745                         drag_win = event_win;
746                         drag_x1 = cursor_x - get_resources()->drag_radius;
747                         drag_x2 = cursor_x + get_resources()->drag_radius;
748                         drag_y1 = cursor_y - get_resources()->drag_radius;
749                         drag_y2 = cursor_y + get_resources()->drag_radius;
751                         if(button_time2 - button_time1 < resources.double_click)
752                         {
753 // Ignore triple clicks
754                                 double_click = 1; 
755                                 button_time2 = button_time1 = 0; 
756                         }
757                         else 
758                                 double_click = 0;
760                         dispatch_button_press();
761                         break;
763                 case ButtonRelease:
764                         get_key_masks(event);
765                         button_number = event->xbutton.button;
766                         event_win = event->xany.window;
767                         if (button_number != 4 && button_number != 5) 
768                                 button_down = 0;
770                         dispatch_button_release();
772                         break;
774                 case Expose:
775                         event_win = event->xany.window;
776                         dispatch_expose_event();
777                         break;
779                 case MotionNotify:
780                         get_key_masks(event);
781 // Dispatch previous motion event if this is a subsequent motion from a different window
782                         if(motion_events && last_motion_win != event->xany.window)
783                         {
784                                 dispatch_motion_event();
785                         }
787 // Buffer the current motion
788                         motion_events = 1;
789                         last_motion_x = event->xmotion.x;
790                         last_motion_y = event->xmotion.y;
791                         last_motion_win = event->xany.window;
792                         break;
794                 case ConfigureNotify:
795                         get_key_masks(event);
796                         XTranslateCoordinates(top_level->display, 
797                                 top_level->win, 
798                                 top_level->rootwin, 
799                                 0, 
800                                 0, 
801                                 &last_translate_x, 
802                                 &last_translate_y, 
803                                 &tempwin);
804                         last_resize_w = event->xconfigure.width;
805                         last_resize_h = event->xconfigure.height;
807                         cancel_resize = 0;
808                         cancel_translation = 0;
810 // Resize history prevents responses to recursive resize requests
811                         for(int i = 0; i < resize_history.total && !cancel_resize; i++)
812                         {
813                                 if(resize_history.values[i]->w == last_resize_w &&
814                                         resize_history.values[i]->h == last_resize_h)
815                                 {
816                                         delete resize_history.values[i];
817                                         resize_history.remove_number(i);
818                                         cancel_resize = 1;
819                                 }
820                         }
822                         if(last_resize_w == w && last_resize_h == h)
823                                 cancel_resize = 1;
825                         if(!cancel_resize)
826                         {
827                                 resize_events = 1;
828                         }
830                         if((last_translate_x == x && last_translate_y == y))
831                                 cancel_translation = 1;
833                         if(!cancel_translation)
834                         {
835                                 translation_events = 1;
836                         }
838                         translation_count++;
839                         break;
841                 case KeyPress:
842                         get_key_masks(event);
843                         keys_return[0] = 0;
844                         XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
846 // printf("BC_WindowBase::dispatch_event 2 %llx\n", 
847 // event->xkey.state);
848 // block out control keys
849                         if(keysym > 0xffe0 && keysym < 0xffff) break;
852                         if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
855                         switch(keysym)
856                         {
857 // block out extra keys
858                         case XK_Alt_L:      
859                         case XK_Alt_R:      
860                         case XK_Shift_L:    
861                         case XK_Shift_R:    
862                         case XK_Control_L:  
863                         case XK_Control_R:  
864                                         key_pressed = 0;         
865                                         break;
867 // Translate key codes
868                                 case XK_Return:     key_pressed = RETURN;    break;
869                         case XK_Up:         key_pressed = UP;        break;
870                                 case XK_Down:       key_pressed = DOWN;      break;
871                                 case XK_Left:       key_pressed = LEFT;      break;
872                         case XK_Right:      key_pressed = RIGHT;     break;
873                         case XK_Next:       key_pressed = PGDN;      break;
874                         case XK_Prior:      key_pressed = PGUP;      break;
875                         case XK_BackSpace:  key_pressed = BACKSPACE; break;
876                         case XK_Escape:     key_pressed = ESC;       break;
877                         case XK_Tab:
878                                         if(shift_down())
879                                                 key_pressed = LEFTTAB;
880                                         else
881                                                 key_pressed = TAB;       
882                                         break;
883                                 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
884                                 case XK_underscore: key_pressed = '_';       break;
885                         case XK_asciitilde: key_pressed = '~';       break;
886                                 case XK_Delete:     key_pressed = DELETE;    break;
887                                 case XK_Home:       key_pressed = HOME;      break;
888                                 case XK_End:        key_pressed = END;       break;
890 // number pad
891                                 case XK_KP_Enter:       key_pressed = KPENTER;   break;
892                                 case XK_KP_Add:         key_pressed = KPPLUS;    break;
893                                 case XK_KP_1:
894                                 case XK_KP_End:         key_pressed = KP1;       break;
895                                 case XK_KP_2:
896                                 case XK_KP_Down:        key_pressed = KP2;       break;
897                                 case XK_KP_3:
898                                 case XK_KP_Page_Down:   key_pressed = KP3;       break;
899                                 case XK_KP_4:
900                                 case XK_KP_Left:        key_pressed = KP4;       break;
901                                 case XK_KP_5:
902                                 case XK_KP_Begin:       key_pressed = KP5;       break;
903                                 case XK_KP_6:
904                                 case XK_KP_Right:       key_pressed = KP6;       break;
905                                 case XK_KP_0:
906                                 case XK_KP_Insert:      key_pressed = KPINS;     break;
907                                 case XK_KP_Decimal:
908                                 case XK_KP_Delete:      key_pressed = KPDEL;     break;
909                         default:           
910                                         //key_pressed = keys_return[0]; 
911                                         key_pressed = keysym & 0xff;
912                                         break;
913                         }
915 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
916                         result = dispatch_keypress_event();
917 // Handle some default keypresses
918                         if(!result)
919                         {
920                                 if(key_pressed == 'w' ||
921                                         key_pressed == 'W')
922                                 {
923                                         close_event();
924                                 }
925                         }
926                         break;
928                 case LeaveNotify:
929                         event_win = event->xany.window;
930                         dispatch_cursor_leave();
931                         break;
933                 case EnterNotify:
934                         event_win = event->xany.window;
935                         cursor_x = event->xcrossing.x;
936                         cursor_y = event->xcrossing.y;
937                         dispatch_cursor_enter();
938                         break;
939         }
940 //printf("100 %s %p %d\n", title, event, event->type);
942         unlock_window();
943         if(event) delete event;
944         return 0;
947 int BC_WindowBase::dispatch_expose_event()
949         int result = 0;
950         for(int i = 0; i < subwindows->total && !result; i++)
951         {
952                 result = subwindows->values[i]->dispatch_expose_event();
953         }
955 // Propagate to user
956         if(!result) expose_event();
957         return result;
960 int BC_WindowBase::dispatch_resize_event(int w, int h)
962 // Can't store new w and h until the event is handles 
963 // because bcfilebox depends on the old w and h to
964 // reposition widgets.
965         if(window_type == MAIN_WINDOW)
966         {
967                 resize_events = 0;
968                 delete pixmap;
969                 pixmap = new BC_Pixmap(this, w, h);
971                 clear_box(0, 0, w, h);
972         }
974 // Propagate to subwindows
975         for(int i = 0; i < subwindows->total; i++)
976         {
977                 subwindows->values[i]->dispatch_resize_event(w, h);
978         }
980 // Propagate to user
981         resize_event(w, h);
983         if(window_type == MAIN_WINDOW)
984         {
985                 this->w = w;
986                 this->h = h;
987         }
988         return 0;
991 int BC_WindowBase::dispatch_translation_event()
993         translation_events = 0;
994         if(window_type == MAIN_WINDOW)
995         {
996                 prev_x = x;
997                 prev_y = y;
998                 x = last_translate_x;
999                 y = last_translate_y;
1000 // Correct for window manager offsets
1001                 x -= x_correction;
1002                 y -= y_correction;
1003         }
1005         for(int i = 0; i < subwindows->total; i++)
1006         {
1007                 subwindows->values[i]->dispatch_translation_event();
1008         }
1010         translation_event();
1011         return 0;
1014 int BC_WindowBase::dispatch_motion_event()
1016         int result = 0;
1017         unhide_cursor();
1019         if(top_level == this)
1020         {
1021                 event_win = last_motion_win;
1022                 motion_events = 0;
1024 // Test for grab
1025                 if(get_button_down() && !active_menubar && !active_popup_menu)
1026                 {
1027                         if(!result)
1028                         {
1029                                 cursor_x = last_motion_x;
1030                                 cursor_y = last_motion_y;
1031                                 result = dispatch_drag_motion();
1032                         }
1034                         if(!result && 
1035                                 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 || 
1036                                 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1037                         {
1038                                 cursor_x = drag_x;
1039                                 cursor_y = drag_y;
1041                                 result = dispatch_drag_start();
1042                         }
1043                 }
1044                 cursor_x = last_motion_x;
1045                 cursor_y = last_motion_y;
1047                 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1048                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1049                 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1050         }
1052         for(int i = 0; i < subwindows->total && !result; i++)
1053         {
1054                 result = subwindows->values[i]->dispatch_motion_event();
1055         }
1058         if(!result) result = cursor_motion_event();    // give to user
1059         return result;
1062 int BC_WindowBase::dispatch_keypress_event()
1064         int result = 0;
1065         if(top_level == this)
1066         {
1067                 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1068         }
1070         for(int i = 0; i < subwindows->total && !result; i++)
1071         {
1072                 result = subwindows->values[i]->dispatch_keypress_event();
1073         }
1075         if(!result) result = keypress_event();
1077         return result;
1080 int BC_WindowBase::dispatch_focus_in()
1082         for(int i = 0; i < subwindows->total; i++)
1083         {
1084                 subwindows->values[i]->dispatch_focus_in();
1085         }
1087         focus_in_event();
1089         return 0;
1092 int BC_WindowBase::dispatch_focus_out()
1094         for(int i = 0; i < subwindows->total; i++)
1095         {
1096                 subwindows->values[i]->dispatch_focus_out();
1097         }
1099         focus_out_event();
1101         return 0;
1104 int BC_WindowBase::get_has_focus()
1106         return top_level->has_focus;
1109 int BC_WindowBase::get_deleting()
1111         if(is_deleting) return 1;
1112         if(parent_window && parent_window->get_deleting()) return 1;
1113         return 0;
1116 int BC_WindowBase::dispatch_button_press()
1118         int result = 0;
1119         if(top_level == this)
1120         {
1121                 if(active_menubar) result = active_menubar->dispatch_button_press();
1122                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1123                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1124         }
1126         for(int i = 0; i < subwindows->total && !result; i++)
1127         {
1128                 result = subwindows->values[i]->dispatch_button_press();
1129         }
1131         if(!result) result = button_press_event();
1133         return result;
1136 int BC_WindowBase::dispatch_button_release()
1138         int result = 0;
1139         if(top_level == this)
1140         {
1141                 if(active_menubar) result = active_menubar->dispatch_button_release();
1142                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1143                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1144                 if(!result && button_number != 4 && button_number != 5)
1145                         result = dispatch_drag_stop();
1146         }
1148         for(int i = 0; i < subwindows->total && !result; i++)
1149         {
1150                 result = subwindows->values[i]->dispatch_button_release();
1151         }
1153         if(!result)
1154         {
1155                 result = button_release_event();
1156         }
1158         return result;
1162 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1165 // all repeat event handlers get called and decide based on activity and duration
1166 // whether to respond
1167         for(int i = 0; i < subwindows->total; i++)
1168         {
1169                 subwindows->values[i]->dispatch_repeat_event(duration);
1170         }
1173         repeat_event(duration);
1177 // Unlock next repeat signal
1178         if(window_type == MAIN_WINDOW)
1179         {
1180                 for(int i = 0; i < repeaters.total; i++)
1181                 {
1182                         if(repeaters.values[i]->delay == duration)
1183                         {
1184                                 repeaters.values[i]->repeat_lock->unlock();
1185                         }
1186                 }
1187         }
1189         return 0;
1192 void BC_WindowBase::unhide_cursor()
1194         if(is_transparent)
1195         {
1196                 is_transparent = 0;
1197                 if(top_level->is_hourglass)
1198                         set_cursor(HOURGLASS_CURSOR, 1);
1199                 else
1200                         set_cursor(current_cursor, 1);
1201         }
1202         cursor_timer->update();
1206 void BC_WindowBase::update_video_cursor()
1208         if(video_on && !is_transparent)
1209         {
1210                 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1211                 {
1212                         is_transparent = 1;
1213                         set_cursor(TRANSPARENT_CURSOR, 1);
1214                         cursor_timer->update();
1215                 }
1216         }
1217         else
1218         {
1219                 cursor_timer->update();
1220         }
1224 int BC_WindowBase::dispatch_cursor_leave()
1226         unhide_cursor();
1228         for(int i = 0; i < subwindows->total; i++)
1229         {
1230                 subwindows->values[i]->dispatch_cursor_leave();
1231         }
1233         cursor_leave_event();
1234         return 0;
1237 int BC_WindowBase::dispatch_cursor_enter()
1239         int result = 0;
1241         unhide_cursor();
1243         if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1244         if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1245         if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1247         for(int i = 0; !result && i < subwindows->total; i++)
1248         {
1249                 result = subwindows->values[i]->dispatch_cursor_enter();
1250         }
1252         if(!result) result = cursor_enter_event();
1253         return result;
1256 int BC_WindowBase::cursor_enter_event()
1258         return 0;
1261 int BC_WindowBase::cursor_leave_event()
1263         return 0;
1266 int BC_WindowBase::close_event()
1268         set_done(1);
1269         return 1;
1272 int BC_WindowBase::dispatch_drag_start()
1274         int result = 0;
1275         if(active_menubar) result = active_menubar->dispatch_drag_start();
1276         if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1277         if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1278         
1279         for(int i = 0; i < subwindows->total && !result; i++)
1280         {
1281                 result = subwindows->values[i]->dispatch_drag_start();
1282         }
1284         if(!result) result = is_dragging = drag_start_event();
1285         return result;
1288 int BC_WindowBase::dispatch_drag_stop()
1290         int result = 0;
1292         for(int i = 0; i < subwindows->total && !result; i++)
1293         {
1294                 result = subwindows->values[i]->dispatch_drag_stop();
1295         }
1297         if(is_dragging && !result) 
1298         {
1299                 drag_stop_event();
1300                 is_dragging = 0;
1301                 result = 1;
1302         }
1304         return result;
1307 int BC_WindowBase::dispatch_drag_motion()
1309         int result = 0;
1310         for(int i = 0; i < subwindows->total && !result; i++)
1311         {
1312                 result = subwindows->values[i]->dispatch_drag_motion();
1313         }
1314         
1315         if(is_dragging && !result)
1316         {
1317                 drag_motion_event();
1318                 result = 1;
1319         }
1320         
1321         return result;
1328 int BC_WindowBase::show_tooltip(int w, int h)
1330         Window tempwin;
1332         if(!tooltip_on && get_resources()->tooltips_enabled)
1333         {
1334                 int i, j, x, y;
1335                 top_level->hide_tooltip();
1337                 tooltip_on = 1;
1338                 if(w < 0)
1339                         w = get_text_width(MEDIUMFONT, tooltip_text);
1341                 if(h < 0)
1342                         h = get_text_height(MEDIUMFONT, tooltip_text);
1344                 w += TOOLTIP_MARGIN * 2;
1345                 h += TOOLTIP_MARGIN * 2;
1347                 XTranslateCoordinates(top_level->display, 
1348                                 win, 
1349                                 top_level->rootwin, 
1350                                 get_w(), 
1351                                 get_h(), 
1352                                 &x, 
1353                                 &y, 
1354                                 &tempwin);
1355                 tooltip_popup = new BC_Popup(top_level, 
1356                                         x,
1357                                         y,
1358                                         w, 
1359                                         h, 
1360                                         get_resources()->tooltip_bg_color);
1362                 draw_tooltip();
1363                 tooltip_popup->set_font(MEDIUMFONT);
1364                 tooltip_popup->flash();
1365                 tooltip_popup->flush();
1366         }
1367         return 0;
1370 int BC_WindowBase::hide_tooltip()
1372         if(subwindows)
1373                 for(int i = 0; i < subwindows->total; i++)
1374                 {
1375                         subwindows->values[i]->hide_tooltip();
1376                 }
1378         if(tooltip_on)
1379         {
1380                 tooltip_on = 0;
1381                 delete tooltip_popup;
1382                 tooltip_popup = 0;
1383         }
1384         return 0;
1387 int BC_WindowBase::set_tooltip(char *text)
1389         strcpy(this->tooltip_text, text);
1390 // Update existing tooltip if it is visible
1391         if(tooltip_on)
1392         {
1393                 draw_tooltip();
1394                 tooltip_popup->flash();
1395         }
1396         return 0;
1399 // signal the event handler to repeat
1400 int BC_WindowBase::set_repeat(int64_t duration)
1402         if(duration <= 0)
1403         {
1404                 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1405                 return 0;
1406         }
1407         if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1409 // test repeater database for duplicates
1410         for(int i = 0; i < repeaters.total; i++)
1411         {
1412 // Already exists
1413                 if(repeaters.values[i]->delay == duration)
1414                 {
1415                         repeaters.values[i]->start_repeating();
1416                         return 0;
1417                 }
1418         }
1420         BC_Repeater *repeater = new BC_Repeater(this, duration);
1421         repeater->initialize();
1422         repeaters.append(repeater);
1423     repeater->start_repeating();
1424         return 0;
1427 int BC_WindowBase::unset_repeat(int64_t duration)
1429         if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1431         BC_Repeater *repeater = 0;
1432         for(int i = 0; i < repeaters.total; i++)
1433         {
1434                 if(repeaters.values[i]->delay == duration)
1435                 {
1436                         repeaters.values[i]->stop_repeating();
1437                 }
1438         }
1439         return 0;
1443 int BC_WindowBase::unset_all_repeaters()
1445         for(int i = 0; i < repeaters.total; i++)
1446         {
1447                 repeaters.values[i]->stop_repeating();
1448         }
1449         repeaters.remove_all_objects();
1450         return 0;
1453 // long BC_WindowBase::get_repeat_id()
1454 // {
1455 //      return top_level->next_repeat_id++;
1456 // }
1458 int BC_WindowBase::arm_repeat(int64_t duration)
1460         XEvent *event = new XEvent;
1461         XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1462         ptr->type = ClientMessage;
1463         ptr->message_type = RepeaterXAtom;
1464         ptr->format = 32;
1465         ptr->data.l[0] = duration;
1467 // Couldn't use XSendEvent since it locked up randomly.
1468         put_event(event);
1469 //      XSendEvent(top_level->event_display, 
1470 //              top_level->win, 
1471 //              0, 
1472 //              0, 
1473 //              event);
1474 //      flush();
1475         return 0;
1478 int BC_WindowBase::get_atoms()
1480         SetDoneXAtom =  XInternAtom(display, "BC_REPEAT_EVENT", False);
1481         RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1482         DelWinXAtom =   XInternAtom(display, "WM_DELETE_WINDOW", False);
1483         if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1484                 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1485         return 0;
1488 void BC_WindowBase::init_cursors()
1490         arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1491         cross_cursor = XCreateFontCursor(display, XC_crosshair);
1492         ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1493         vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1494         hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1495         move_cursor = XCreateFontCursor(display, XC_fleur);
1496         left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1497         right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1498         upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1499         upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1500         upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1501         downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1502         downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1503         hourglass_cursor = XCreateFontCursor(display, XC_watch);
1506         char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
1507         Colormap colormap = DefaultColormap(display, screen);
1508         Pixmap pixmap_bottom = XCreateBitmapFromData(display, 
1509                 rootwin,
1510                 cursor_data, 
1511                 8,
1512                 8);
1513         XColor black, dummy;
1514     XAllocNamedColor(display, colormap, "black", &black, &dummy);
1515         transparent_cursor = XCreatePixmapCursor(display,
1516                 pixmap_bottom,
1517                 pixmap_bottom,
1518                 &black,
1519                 &black,
1520                 0,
1521                 0);
1522 //      XDefineCursor(display, win, transparent_cursor);
1523         XFreePixmap(display, pixmap_bottom);
1526 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1528         int color_model;
1529         switch(depth)
1530         {
1531                 case 8:
1532                         color_model = BC_RGB8;
1533                         break;
1534                 case 16:
1535                         color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1536                         break;
1537                 case 24:
1538                         color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1539                         break;
1540                 case 32:
1541                         color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1542                         break;
1543         }
1544         return color_model;
1547 int BC_WindowBase::init_colors()
1549         total_colors = 0;
1550         current_color_value = current_color_pixel = 0;
1552 // Get the real depth
1553         char *data = 0;
1554         XImage *ximage;
1555         ximage = XCreateImage(top_level->display, 
1556                                         top_level->vis, 
1557                                         top_level->default_depth, 
1558                                         ZPixmap, 
1559                                         0, 
1560                                         data, 
1561                                         16, 
1562                                         16, 
1563                                         8, 
1564                                         0);
1565         bits_per_pixel = ximage->bits_per_pixel;
1566         XDestroyImage(ximage);
1568         color_model = evaluate_color_model(client_byte_order, 
1569                 server_byte_order, 
1570                 bits_per_pixel);
1571 // Get the color model
1572         switch(color_model)
1573         {
1574                 case BC_RGB8:
1575                         if(private_color)
1576                         {
1577                                 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1578                                 create_private_colors();
1579                         }
1580                         else
1581                         {
1582                                 cmap = DefaultColormap(display, screen);
1583                                 create_shared_colors();
1584                         }
1586                         allocate_color_table();
1587 // No antialiasing
1588                         get_resources()->use_xft = 0;
1589                         break;
1591                 default:
1592                         cmap = DefaultColormap(display, screen);
1593                         break;
1594         }
1595         return 0;
1598 int BC_WindowBase::create_private_colors()
1600         int color;
1601         total_colors = 256;
1603         for(int i = 0; i < 255; i++)
1604         {
1605                 color = (i & 0xc0) << 16;
1606                 color += (i & 0x38) << 10;
1607                 color += (i & 0x7) << 5;
1608                 color_table[i][0] = color;
1609         }
1610         create_shared_colors();        // overwrite the necessary colors on the table
1611         return 0;
1615 int BC_WindowBase::create_color(int color)
1617         if(total_colors == 256)
1618         {
1619 // replace the closest match with an exact match
1620                 color_table[get_color_rgb8(color)][0] = color;
1621         }
1622         else
1623         {
1624 // add the color to the table
1625                 color_table[total_colors][0] = color;
1626                 total_colors++;
1627         }
1628         return 0;
1631 int BC_WindowBase::create_shared_colors()
1633         create_color(BLACK);
1634         create_color(WHITE);   
1636         create_color(LTGREY);  
1637         create_color(MEGREY);  
1638         create_color(MDGREY);  
1639         create_color(DKGREY);                           
1641         create_color(LTCYAN);  
1642         create_color(MECYAN);  
1643         create_color(MDCYAN);  
1644         create_color(DKCYAN);  
1646         create_color(LTGREEN); 
1647         create_color(GREEN);   
1648         create_color(DKGREEN); 
1650         create_color(LTPINK);  
1651         create_color(PINK);
1652         create_color(RED);     
1654         create_color(LTBLUE);  
1655         create_color(BLUE);    
1656         create_color(DKBLUE);  
1658         create_color(LTYELLOW); 
1659         create_color(MEYELLOW); 
1660         create_color(MDYELLOW); 
1661         create_color(DKYELLOW); 
1663         create_color(LTPURPLE); 
1664         create_color(MEPURPLE); 
1665         create_color(MDPURPLE); 
1666         create_color(DKPURPLE); 
1668         create_color(FGGREY); 
1669         create_color(MNBLUE);
1670         create_color(ORANGE);
1671         create_color(FTGREY);
1673         return 0;
1676 int BC_WindowBase::allocate_color_table()
1678         int red, green, blue, color;
1679         int result;
1680         XColor col;
1682         for(int i = 0; i < total_colors; i++)
1683         {
1684                 color = color_table[i][0];
1685                 red = (color & 0xFF0000) >> 16;
1686                 green = (color & 0x00FF00) >> 8;
1687                 blue = color & 0xFF;
1689                 col.flags = DoRed | DoGreen | DoBlue;
1690                 col.red   = red<<8   | red;
1691                 col.green = green<<8 | green;
1692                 col.blue  = blue<<8  | blue;
1694                 XAllocColor(display, cmap, &col);
1695                 color_table[i][1] = col.pixel;
1696         }
1698         XInstallColormap(display, cmap);
1699         return 0;
1702 int BC_WindowBase::init_window_shape()
1704         if(bg_pixmap && bg_pixmap->use_alpha()) 
1705         {
1706                 XShapeCombineMask(top_level->display,
1707                 this->win,
1708                 ShapeBounding,
1709                 0,
1710                 0,
1711                 bg_pixmap->get_alpha(),
1712                 ShapeSet);
1713         }
1714         return 0;
1718 int BC_WindowBase::init_gc()
1720         unsigned long gcmask;
1721         gcmask = GCFont | GCGraphicsExposures;
1723         XGCValues gcvalues;
1724         gcvalues.font = mediumfont->fid;        // set the font
1725         gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
1726         gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1727         return 0;
1730 int BC_WindowBase::init_fonts()
1732         if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL)
1733                 if((largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1734                 largefont = XLoadQueryFont(display, "fixed"); 
1736         if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL)
1737                 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1738                 mediumfont = XLoadQueryFont(display, "fixed"); 
1740         if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL)
1741                 if((smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1742                 smallfont = XLoadQueryFont(display, "fixed");
1744 #ifdef HAVE_XFT
1745         if(get_resources()->use_xft)
1746         {
1749 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
1751                 if(!(largefont_xft = XftFontOpenXlfd(display,
1752                     screen,
1753                     resources.large_font_xft)))
1754                 {
1755                         largefont_xft = XftFontOpenXlfd(display,
1756                         screen,
1757                         "fixed");
1758                 }
1759 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
1760                 if(!(largefont_xft = XftFontOpenXlfd(display,
1761                     screen,
1762                     resources.large_font_xft)))
1763                 {
1764                         largefont_xft = XftFontOpenXlfd(display,
1765                         screen,
1766                         "fixed");
1767                 }
1768 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
1771                 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1772                       screen,
1773                       resources.medium_font_xft)))
1774                 {
1775                         mediumfont_xft = XftFontOpenXlfd(display,
1776                         screen,
1777                         "fixed");
1778                 }
1781                 if(!(smallfont_xft = XftFontOpenXlfd(display,
1782                       screen,
1783                       resources.small_font_xft)))
1784                 {
1785                           smallfont_xft = XftFontOpenXlfd(display,
1786                           screen,
1787                           "fixed");
1788                 }
1790 //printf("BC_WindowBase::init_fonts 100 %s %p\n", 
1791 //resources.medium_font, 
1792 //mediumfont_xft);
1794 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
1795         resources.large_font_xft,
1796         largefontset,
1797         resources.medium_font_xft,
1798         mediumfontset,
1799         resources.small_font_xft,
1800         smallfontset);
1802 // Extension failed to locate fonts
1803                 if(!largefontset || !mediumfontset || !smallfontset)
1804                 {
1805                         printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1806                                 resources.large_font_xft,
1807                                 largefontset,
1808                                 resources.medium_font_xft,
1809                                 mediumfontset,
1810                                 resources.small_font_xft,
1811                                 smallfontset);
1812                         get_resources()->use_xft = 0;
1813                 }
1814         }
1815         else
1816 #endif
1817         if(get_resources()->use_fontset)
1818         {
1819                 char **m, *d;
1820                 int n;
1822 // FIXME: should check the m,d,n values
1823                 if((largefontset = XCreateFontSet(display, 
1824                         resources.large_fontset,
1825             &m, 
1826                         &n, 
1827                         &d)) == 0)
1828             largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1829                 if((mediumfontset = XCreateFontSet(display, 
1830                         resources.medium_fontset,
1831             &m, 
1832                         &n, 
1833                         &d)) == 0)
1834             mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1835                 if((smallfontset = XCreateFontSet(display, 
1836                         resources.small_fontset,
1837             &m, 
1838                         &n, 
1839                         &d)) == 0)
1840             smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1842                 if(largefontset && mediumfontset && smallfontset)
1843                 {
1844                         curr_fontset = mediumfontset;
1845                         get_resources()->use_fontset = 1;
1846                 }
1847                 else
1848                 {
1849                         curr_fontset = 0;
1850                         get_resources()->use_fontset = 0;
1851                 }
1852         }
1854         return 0;
1859 int BC_WindowBase::get_color(int64_t color) 
1861 // return pixel of color
1862 // use this only for drawing subwindows not for bitmaps
1863          int i, test, difference, result;
1865         switch(color_model)
1866         {
1867                 case BC_RGB8:
1868                         if(private_color)
1869                         {
1870                                 return get_color_rgb8(color);
1871                         }
1872                         else
1873                         {
1874 // test last color looked up
1875                                 if(current_color_value == color) return current_color_pixel;
1877 // look up in table
1878                                 current_color_value = color;
1879                                 for(i = 0; i < total_colors; i++)
1880                                 {
1881                                         if(color_table[i][0] == color)
1882                                         {
1883                                                 current_color_pixel = color_table[i][1];
1884                                                 return current_color_pixel;
1885                                         }
1886                                 }
1888 // find nearest match
1889                                 difference = 0xFFFFFF;
1891                                 for(i = 0, result = 0; i < total_colors; i++)
1892                                 {
1893                                         test = abs((int)(color_table[i][0] - color));
1895                                         if(test < difference) 
1896                                         {
1897                                                 current_color_pixel = color_table[i][1]; 
1898                                                 difference = test;
1899                                         }
1900                                 }
1902                                 return current_color_pixel;
1903                         }
1904                         break;  
1906                 case BC_RGB565:
1907                         return get_color_rgb16(color);
1908                         break;
1910                 case BC_BGR565:
1911                         return get_color_bgr16(color);
1912                         break;
1914                 case BC_RGB888:
1915                 case BC_BGR888:
1916                         if(client_byte_order == server_byte_order)
1917                                 return color;
1918                         else
1919                                 get_color_bgr24(color);
1920                         break;
1922                 default:
1923                         return color;
1924                         break;  
1925         }
1926         return 0;
1929 int BC_WindowBase::get_color_rgb8(int color)
1931         int pixel;
1933         pixel = (color & 0xc00000) >> 16;
1934         pixel += (color & 0xe000) >> 10;
1935         pixel += (color & 0xe0) >> 5;
1936         return pixel;
1939 int64_t BC_WindowBase::get_color_rgb16(int color)
1941         int64_t result;
1942         result = (color & 0xf80000) >> 8;
1943         result += (color & 0xfc00) >> 5;
1944         result += (color & 0xf8) >> 3;
1945         
1946         return result;
1949 int64_t BC_WindowBase::get_color_bgr16(int color)
1951         int64_t result;
1952         result = (color & 0xf80000) >> 19;
1953         result += (color & 0xfc00) >> 5;
1954         result += (color & 0xf8) << 8;
1956         return result;
1959 int64_t BC_WindowBase::get_color_bgr24(int color)
1961         int64_t result;
1962         result = (color & 0xff) << 16;
1963         result += (color & 0xff00);
1964         result += (color & 0xff0000) >> 16;
1965         return result;
1968 void BC_WindowBase::start_video()
1970         cursor_timer->update();
1971         video_on = 1;
1972 //      set_color(BLACK);
1973 //      draw_box(0, 0, get_w(), get_h());
1974 //      flash();
1977 void BC_WindowBase::stop_video()
1979         video_on = 0;
1980         unhide_cursor();
1985 int64_t BC_WindowBase::get_color()
1987         return top_level->current_color;
1990 void BC_WindowBase::set_color(int64_t color)
1992         top_level->current_color = color;
1993         XSetForeground(top_level->display, 
1994                 top_level->gc, 
1995                 top_level->get_color(color));
1998 void BC_WindowBase::set_opaque()
2000         XSetFunction(top_level->display, top_level->gc, GXcopy);
2003 void BC_WindowBase::set_inverse() 
2005         XSetFunction(top_level->display, top_level->gc, GXxor);
2008 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2010         switch(cursor)
2011         {
2012                 case ARROW_CURSOR:         return top_level->arrow_cursor;                 break;
2013                 case CROSS_CURSOR:         return top_level->cross_cursor;
2014                 case IBEAM_CURSOR:         return top_level->ibeam_cursor;                 break;
2015                 case VSEPARATE_CURSOR:     return top_level->vseparate_cursor;             break;
2016                 case HSEPARATE_CURSOR:     return top_level->hseparate_cursor;             break;
2017                 case MOVE_CURSOR:              return top_level->move_cursor;                  break;
2018                 case LEFT_CURSOR:          return top_level->left_cursor;                  break;
2019                 case RIGHT_CURSOR:         return top_level->right_cursor;                 break;
2020                 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;         break;
2021                 case UPLEFT_RESIZE:        return top_level->upleft_resize_cursor;         break;
2022                 case UPRIGHT_RESIZE:       return top_level->upright_resize_cursor;        break;
2023                 case DOWNLEFT_RESIZE:      return top_level->downleft_resize_cursor;       break;
2024                 case DOWNRIGHT_RESIZE:     return top_level->downright_resize_cursor;      break;
2025                 case HOURGLASS_CURSOR:     return top_level->hourglass_cursor;                 break;
2026                 case TRANSPARENT_CURSOR:   return top_level->transparent_cursor;               break;
2027         }
2028         return 0;
2031 void BC_WindowBase::set_cursor(int cursor, int override)
2033 // don't change cursor if overridden
2034         if((!top_level->is_hourglass && !is_transparent) || 
2035                 override)
2036         {
2037                 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2038                 flush();
2039         }
2041         if(!override) current_cursor = cursor;
2044 void BC_WindowBase::set_x_cursor(int cursor)
2046         temp_cursor = XCreateFontCursor(top_level->display, cursor);
2047         XDefineCursor(top_level->display, win, temp_cursor);
2048         current_cursor = cursor;
2049         flush();
2052 int BC_WindowBase::get_cursor()
2054         return current_cursor;
2057 void BC_WindowBase::start_hourglass()
2059         top_level->start_hourglass_recursive();
2060         top_level->flush();
2063 void BC_WindowBase::stop_hourglass()
2065         top_level->stop_hourglass_recursive();
2066         top_level->flush();
2069 void BC_WindowBase::start_hourglass_recursive()
2071         if(this == top_level)
2072         {
2073                 hourglass_total++;
2074                 is_hourglass = 1;
2075         }
2077         if(!is_transparent)
2078         {
2079                 set_cursor(HOURGLASS_CURSOR, 1);
2080                 for(int i = 0; i < subwindows->total; i++)
2081                 {
2082                         subwindows->values[i]->start_hourglass_recursive();
2083                 }
2084         }
2087 void BC_WindowBase::stop_hourglass_recursive()
2089         if(this == top_level)
2090         {
2091                 if(hourglass_total == 0) return;
2092                 top_level->hourglass_total--;
2093         }
2095         if(!top_level->hourglass_total)
2096         {
2097                 top_level->is_hourglass = 0;
2099 // Cause set_cursor to perform change
2100                 if(!is_transparent)
2101                         set_cursor(current_cursor, 1);
2103                 for(int i = 0; i < subwindows->total; i++)
2104                 {
2105                         subwindows->values[i]->stop_hourglass_recursive();
2106                 }
2107         }
2115 XFontStruct* BC_WindowBase::get_font_struct(int font)
2117 // Clear out unrelated flags
2118         if(font & BOLDFACE) font ^= BOLDFACE;
2119         
2120         switch(font)
2121         {
2122                 case MEDIUMFONT: return top_level->mediumfont; break;
2123                 case SMALLFONT:  return top_level->smallfont;  break;
2124                 case LARGEFONT:  return top_level->largefont;  break;
2125         }
2126         return 0;
2129 XFontSet BC_WindowBase::get_fontset(int font)
2131         XFontSet fs = 0;
2133         if(get_resources()->use_fontset)
2134         {
2135                 switch(font)
2136                 {
2137                         case SMALLFONT:  fs = top_level->smallfontset; break;
2138                         case LARGEFONT:  fs = top_level->largefontset; break;
2139                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2140                 }
2141         }
2143         return fs;
2146 #ifdef HAVE_XFT
2147 XftFont* BC_WindowBase::get_xft_struct(int font)
2149 // Clear out unrelated flags
2150         if(font & BOLDFACE) font ^= BOLDFACE;
2152         switch(font)
2153         {
2154                 case MEDIUMFONT:   return (XftFont*)top_level->mediumfont_xft; break;
2155                 case SMALLFONT:    return (XftFont*)top_level->smallfont_xft;  break;
2156                 case LARGEFONT:    return (XftFont*)top_level->largefont_xft;  break;
2157         }
2159         return 0;
2161 #endif
2173 void BC_WindowBase::set_font(int font)
2175         top_level->current_font = font;
2178 #ifdef HAVE_XFT
2179         if(get_resources()->use_xft)
2180         {
2181                 ;
2182         }
2183         else
2184 #endif
2185         if(get_resources()->use_fontset)
2186         {
2187                 set_fontset(font);
2188         }
2190         if(get_font_struct(font))
2191         {
2192                 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2193         }
2195         return;
2198 void BC_WindowBase::set_fontset(int font)
2200         XFontSet fs = 0;
2202         if(get_resources()->use_fontset)
2203         {
2204                 switch(font)
2205                 {
2206                         case SMALLFONT:  fs = top_level->smallfontset; break;
2207                         case LARGEFONT:  fs = top_level->largefontset; break;
2208                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2209                 }
2210         }
2212         curr_fontset = fs;
2216 XFontSet BC_WindowBase::get_curr_fontset(void)
2218         if(get_resources()->use_fontset)
2219                 return curr_fontset;
2220         return 0;
2223 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2225 #ifdef HAVE_XFT
2226         if(get_resources()->use_xft && get_xft_struct(font))
2227         {
2228                 XGlyphInfo extents;
2229                 XftTextExtents8(top_level->display,
2230                         get_xft_struct(font),
2231                         (FcChar8*)text, 
2232                         length,
2233                         &extents);
2234                 return extents.xOff;
2235         }
2236         else
2237 #endif
2238         if(get_resources()->use_fontset && top_level->get_fontset(font))
2239                 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2240         else
2241         if(get_font_struct(font)) 
2242                 return XTextWidth(get_font_struct(font), text, length);
2243         else
2244         {
2245                 int w = 0;
2246                 switch(font)
2247                 {
2248                         case MEDIUM_7SEGMENT:
2249                                 return get_resources()->medium_7segment[0]->get_w() * length;
2250                                 break;
2252                         default:
2253                                 return 0;
2254                 }
2255                 return w;
2256         }
2259 int BC_WindowBase::get_text_width(int font, char *text, int length)
2261         int i, j, w = 0, line_w = 0;
2262         if(length < 0) length = strlen(text);
2264         for(i = 0, j = 0; i <= length; i++)
2265         {
2266                 line_w = 0;
2267                 if(text[i] == '\n')
2268                 {
2269                         line_w = get_single_text_width(font, &text[j], i - j);
2270                         j = i + 1;
2271                 }
2272                 else
2273                 if(text[i] == 0)
2274                 {
2275                         line_w = get_single_text_width(font, &text[j], length - j);
2276                 }
2277                 if(line_w > w) w = line_w;
2278         }
2280         if(i > length && w == 0)
2281         {
2282                 w = get_single_text_width(font, text, length);
2283         }
2285         return w;
2288 int BC_WindowBase::get_text_ascent(int font)
2290 #ifdef HAVE_XFT
2291         if(get_resources()->use_xft && get_xft_struct(font))
2292         {
2293                 XGlyphInfo extents;
2294                 XftTextExtents8(top_level->display,
2295                         get_xft_struct(font),
2296                         (FcChar8*)"O", 
2297                         1,
2298                         &extents);
2299                 return extents.y;
2300         }
2301         else
2302 #endif
2303         if(get_resources()->use_fontset && top_level->get_fontset(font))
2304         {
2305         XFontSetExtents *extents;
2307         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2308         return -extents->max_logical_extent.y;
2309         }
2310         else
2311         if(get_font_struct(font))
2312                 return top_level->get_font_struct(font)->ascent;
2313         else
2314         switch(font)
2315         {
2316                 case MEDIUM_7SEGMENT:
2317                         return get_resources()->medium_7segment[0]->get_h();
2318                         break;
2320                 default:
2321                         return 0;
2322         }
2325 int BC_WindowBase::get_text_descent(int font)
2327 #ifdef HAVE_XFT
2328         if(get_resources()->use_xft && get_xft_struct(font))
2329         {
2330                 XGlyphInfo extents;
2331                 XftTextExtents8(top_level->display,
2332                         get_xft_struct(font),
2333                         (FcChar8*)"j", 
2334                         1,
2335                         &extents);
2336                 return extents.height - extents.y;
2337         }
2338         else
2339 #endif
2340     if(get_resources()->use_fontset && top_level->get_fontset(font))
2341     {
2342         XFontSetExtents *extents;
2344         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2345         return (extents->max_logical_extent.height
2346                         + extents->max_logical_extent.y);
2347     }
2348     else
2349         if(get_font_struct(font))
2350                 return top_level->get_font_struct(font)->descent;
2351         else
2352         switch(font)
2353         {
2354                 default:
2355                         return 0;
2356         }
2359 int BC_WindowBase::get_text_height(int font, char *text)
2361         if(!text) return get_text_ascent(font) + get_text_descent(font);
2363 // Add height of lines
2364         int h = 0, i, length = strlen(text);
2365         for(i = 0; i <= length; i++)
2366         {
2367                 if(text[i] == '\n')
2368                         h++;
2369                 else
2370                 if(text[i] == 0)
2371                         h++;
2372         }
2373         return h * (get_text_ascent(font) + get_text_descent(font));
2376 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2378         if(color_model < 0) color_model = top_level->get_color_model();
2379         return new BC_Bitmap(top_level, w, h, color_model);
2382 int BC_WindowBase::accel_available(int color_model, int lock_it)
2384         if(window_type != MAIN_WINDOW) 
2385                 return top_level->accel_available(color_model, lock_it);
2387         int result = 0;
2389         if(lock_it) lock_window("BC_WindowBase::accel_available");
2390         switch(color_model)
2391         {
2392                 case BC_YUV420P:
2393                         result = grab_port_id(this, color_model);
2394                         if(result >= 0)
2395                         {
2396                                 xvideo_port_id = result;
2397                                 result = 1;
2398                         }
2399                         else
2400                                 result = 0;
2401                         break;
2403                 case BC_YUV422P:
2404                         result = 0;
2405                         break;
2407                 case BC_YUV422:
2408 //printf("BC_WindowBase::accel_available 1\n");
2409                         result = grab_port_id(this, color_model);
2410 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2411                         if(result >= 0)
2412                         {
2413                                 xvideo_port_id = result;
2414                                 result = 1;
2415                         }
2416                         else
2417                                 result = 0;
2418 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2419                         break;
2421                 default:
2422                         result = 0;
2423                         break;
2424         }
2426         if(lock_it) unlock_window();
2427 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2428         return result;
2432 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2434         int numFormats, i, j, k;
2435         unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2436         int port_id = -1;
2437     XvAdaptorInfo *info;
2438     XvImageFormatValues *formats;
2439         int x_color_model;
2441         if(!get_resources()->use_xvideo) return -1;
2443 // Translate from color_model to X color model
2444         x_color_model = cmodel_bc_to_x(color_model);
2446 // Only local server is fast enough.
2447         if(!resources.use_shm) return -1;
2449 // XV extension is available
2450     if(Success != XvQueryExtension(window->display, 
2451                                   &ver, 
2452                                   &rev, 
2453                                   &reqBase, 
2454                                   &eventBase, 
2455                                   &errorBase))
2456     {
2457                 return -1;
2458     }
2460 // XV adaptors are available
2461         XvQueryAdaptors(window->display, 
2462                 DefaultRootWindow(window->display), 
2463                 &numAdapt, 
2464                 &info);
2466         if(!numAdapt)
2467         {
2468                 return -1;
2469         }
2471 // Get adaptor with desired color model
2472     for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2473     {
2474 /* adaptor supports XvImages */
2475                 if(info[i].type & XvImageMask) 
2476                 {  
2477                 formats = XvListImageFormats(window->display, 
2478                                                         info[i].base_id, 
2479                                                         &numFormats);
2480 // for(j = 0; j < numFormats; j++)
2481 //      printf("%08x\n", formats[j].id);
2483                 for(j = 0; j < numFormats && xvideo_port_id < 0; j++) 
2484                 {
2485 /* this adaptor supports the desired format */
2486                                 if(formats[j].id == x_color_model)
2487                                 {
2488 /* Try to grab a port */
2489                                         for(k = 0; k < info[i].num_ports; k++)
2490                                         {
2491 /* Got a port */
2492                                                 if(Success == XvGrabPort(top_level->display, 
2493                                                         info[i].base_id + k, 
2494                                                         CurrentTime))
2495                                                 {
2496 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2497                                                         xvideo_port_id = info[i].base_id + k;
2498                                                         break;
2499                                                 }
2500                                         }
2501                                 }
2502                         }
2503                 if(formats) XFree(formats);
2504                 }
2505         }
2507     XvFreeAdaptorInfo(info);
2509         return xvideo_port_id;
2513 int BC_WindowBase::show_window(int flush) 
2515         XMapWindow(top_level->display, win); 
2516         if(flush) XFlush(top_level->display);
2517 //      XSync(top_level->display, 0);
2518         hidden = 0; 
2519         return 0;
2522 int BC_WindowBase::hide_window(int flush) 
2524         XUnmapWindow(top_level->display, win); 
2525         if(flush) XFlush(top_level->display);
2526         hidden = 1; 
2527         return 0;
2530 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2532         subwindows->append((BC_SubWindow*)menu_bar);
2534         menu_bar->parent_window = this;
2535         menu_bar->top_level = this->top_level;
2536         menu_bar->initialize();
2537         return menu_bar;
2540 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2542         subwindows->append(subwindow);
2544         if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2546 // parent window must be set before the subwindow initialization
2547         subwindow->parent_window = this;
2548         subwindow->top_level = this->top_level;
2550 // Execute derived initialization
2551         subwindow->initialize();
2552         return subwindow;
2556 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2558         return add_subwindow(subwindow);
2561 BC_WidgetGrid* BC_WindowBase::add_widgetgrid(BC_WidgetGrid *widgetgrid)
2563         widgetgrids->append(widgetgrid);
2564         return widgetgrid;
2568 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2570         set_opaque();
2571         XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
2572         if(x >= 0)
2573         {
2574                 XClearArea(top_level->display, win, x, y, w, h, 0);
2575         }
2576         else
2577         {
2578                 XClearWindow(top_level->display, win);
2579         }
2581         if(flush)
2582                 this->flush();
2583         return 0;
2586 int BC_WindowBase::flash(int flush)
2588         flash(-1, -1, -1, -1, flush);
2591 void BC_WindowBase::flush()
2593         XFlush(top_level->display);
2596 void BC_WindowBase::sync_display()
2598         XSync(top_level->display, False);
2601 int BC_WindowBase::get_window_lock()
2603         return top_level->window_lock;
2606 int BC_WindowBase::lock_window(char *location) 
2608         if(top_level && top_level != this)
2609         {
2610                 top_level->lock_window(location);
2611         }
2612         else
2613         if(top_level)
2614         {
2615                 SET_LOCK(this, title, location);
2616                 XLockDisplay(top_level->display);
2617                 SET_LOCK2
2618                 top_level->window_lock = 1;
2619         }
2620         else
2621         {
2622                 printf("BC_WindowBase::lock_window top_level NULL\n");
2623         }
2624         return 0;
2627 int BC_WindowBase::unlock_window() 
2629         if(top_level && top_level != this)
2630         {
2631                 top_level->unlock_window();
2632         }
2633         else
2634         if(top_level)
2635         {
2636                 UNSET_LOCK(this);
2637                 top_level->window_lock = 0;
2638                 XUnlockDisplay(top_level->display);
2639         }
2640         else
2641         {
2642                 printf("BC_WindowBase::unlock_window top_level NULL\n");
2643         }
2644         return 0;
2647 void BC_WindowBase::set_done(int return_value)
2649         if(window_type != MAIN_WINDOW)
2650                 top_level->set_done(return_value);
2651         else
2652         if(event_thread)
2653         {
2654                 XEvent *event = new XEvent;
2655                 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2657                 event->type = ClientMessage;
2658                 ptr->message_type = SetDoneXAtom;
2659                 ptr->format = 32;
2660                 this->return_value = return_value;
2662 // May lock up here because XSendEvent doesn't work too well 
2663 // asynchronous with XNextEvent.
2664 // This causes BC_WindowEvents to forward a copy of the event to run_window where 
2665 // it is deleted.
2666                 event_thread->done = 1;
2667                 XSendEvent(display, 
2668                         win, 
2669                         0, 
2670                         0, 
2671                         event);
2672                 flush();
2673                 put_event(event);
2674         }
2677 int BC_WindowBase::get_w()
2679         return w;
2682 int BC_WindowBase::get_h()
2684         return h;
2687 int BC_WindowBase::get_x()
2689         return x;
2692 int BC_WindowBase::get_y()
2694         return y;
2697 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2699         if(lock_display) lock_window("BC_WindowBase::get_root_w");
2700         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2701         int result = WidthOfScreen(screen_ptr);
2702 // Wider than 16:9, narrower than dual head
2703         if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2705         if(lock_display) unlock_window();
2706         return result;
2709 int BC_WindowBase::get_root_h(int lock_display)
2711         if(lock_display) lock_window("BC_WindowBase::get_root_h");
2712         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2713         int result = HeightOfScreen(screen_ptr);
2714         if(lock_display) unlock_window();
2715         return result;
2718 // Bottom right corner
2719 int BC_WindowBase::get_x2()
2721         return w + x;
2724 int BC_WindowBase::get_y2()
2726         return y + h;
2729 int BC_WindowBase::get_video_on()
2731         return video_on;
2734 int BC_WindowBase::get_hidden()
2736         return top_level->hidden;
2739 int BC_WindowBase::cursor_inside()
2741         return (top_level->cursor_x >= 0 && 
2742                         top_level->cursor_y >= 0 && 
2743                         top_level->cursor_x < w && 
2744                         top_level->cursor_y < h);
2747 BC_WindowBase* BC_WindowBase::get_top_level()
2749         return top_level;
2752 BC_WindowBase* BC_WindowBase::get_parent()
2754         return parent_window;
2757 int BC_WindowBase::get_color_model()
2759         return top_level->color_model;
2762 BC_Resources* BC_WindowBase::get_resources()
2764         return &BC_WindowBase::resources;
2767 int BC_WindowBase::get_bg_color()
2769         return bg_color;
2772 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2774         return bg_pixmap;
2777 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2779         top_level->active_subwindow = subwindow;
2782 int BC_WindowBase::activate()
2784         return 0;
2787 int BC_WindowBase::deactivate()
2789         if(window_type == MAIN_WINDOW)
2790         {
2791                 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2792                 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2793                 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2795                 top_level->active_menubar = 0;
2796                 top_level->active_popup_menu = 0;
2797                 top_level->active_subwindow = 0;
2798         }
2799         return 0;
2802 int BC_WindowBase::cycle_textboxes(int amount)
2804         int result = 0;
2805         BC_WindowBase *new_textbox = 0;
2807         if(amount > 0)
2808         {
2809                 BC_WindowBase *first_textbox = 0;
2810                 find_next_textbox(&first_textbox, &new_textbox, result);
2811                 if(!new_textbox) new_textbox = first_textbox;
2812                 
2813         }
2814         else
2815         if(amount < 0)
2816         {
2817                 BC_WindowBase *last_textbox = 0;
2818                 find_prev_textbox(&last_textbox, &new_textbox, result);
2819                 if(!new_textbox) new_textbox = last_textbox;
2820                 
2821         }
2823         if(new_textbox != active_subwindow)
2824         {
2825                 deactivate();
2826                 new_textbox->activate();
2827         }
2828         
2829         return 0;
2832 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2834 // Search subwindows for textbox
2835         for(int i = 0; i < subwindows->total && result < 2; i++)
2836         {
2837                 BC_WindowBase *test_subwindow = subwindows->values[i];
2838                 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2839         }
2841         if(result < 2)
2842         {
2843                 if(uses_text())
2844                 {
2845                         if(!*first_textbox) *first_textbox = this;
2847                         if(result < 1)
2848                         {
2849                                 if(top_level->active_subwindow == this)
2850                                         result++;
2851                         }
2852                         else
2853                         {
2854                                 result++;
2855                                 *next_textbox = this;
2856                         }
2857                 }
2858         }
2859         return 0;
2862 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2864         if(result < 2)
2865         {
2866                 if(uses_text())
2867                 {
2868                         if(!*last_textbox) *last_textbox = this;
2870                         if(result < 1)
2871                         {
2872                                 if(top_level->active_subwindow == this)
2873                                         result++;
2874                         }
2875                         else
2876                         {
2877                                 result++;
2878                                 *prev_textbox = this;
2879                         }
2880                 }
2881         }
2883 // Search subwindows for textbox
2884         for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2885         {
2886                 BC_WindowBase *test_subwindow = subwindows->values[i];
2887                 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2888         }
2889         return 0;
2892 BC_Clipboard* BC_WindowBase::get_clipboard()
2894         return top_level->clipboard;
2897 int BC_WindowBase::get_relative_cursor_x()
2899         int abs_x, abs_y, x, y, win_x, win_y;
2900         unsigned int temp_mask;
2901         Window temp_win;
2903         XQueryPointer(top_level->display, 
2904            top_level->win, 
2905            &temp_win, 
2906            &temp_win,
2907        &abs_x, 
2908            &abs_y, 
2909            &win_x, 
2910            &win_y, 
2911            &temp_mask);
2913         XTranslateCoordinates(top_level->display, 
2914                         top_level->rootwin, 
2915                         win, 
2916                         abs_x, 
2917                         abs_y, 
2918                         &x, 
2919                         &y, 
2920                         &temp_win);
2922         return x;
2925 int BC_WindowBase::get_relative_cursor_y()
2927         int abs_x, abs_y, x, y, win_x, win_y;
2928         unsigned int temp_mask;
2929         Window temp_win;
2931         XQueryPointer(top_level->display, 
2932            top_level->win, 
2933            &temp_win, 
2934            &temp_win,
2935        &abs_x, 
2936            &abs_y, 
2937            &win_x, 
2938            &win_y, 
2939            &temp_mask);
2941         XTranslateCoordinates(top_level->display, 
2942                         top_level->rootwin, 
2943                         win, 
2944                         abs_x, 
2945                         abs_y, 
2946                         &x, 
2947                         &y, 
2948                         &temp_win);
2950         return y;
2953 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2955         int abs_x, abs_y, win_x, win_y;
2956         unsigned int temp_mask;
2957         Window temp_win;
2959         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2960         XQueryPointer(top_level->display, 
2961                 top_level->win, 
2962                 &temp_win, 
2963                 &temp_win,
2964                 &abs_x, 
2965                 &abs_y, 
2966                 &win_x, 
2967                 &win_y, 
2968                 &temp_mask);
2969         if(lock_window) this->unlock_window();
2970         return abs_x;
2973 int BC_WindowBase::get_abs_cursor_y(int lock_window)
2975         int abs_x, abs_y, win_x, win_y;
2976         unsigned int temp_mask;
2977         Window temp_win;
2979         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
2980         XQueryPointer(top_level->display, 
2981                 top_level->win, 
2982                 &temp_win, 
2983                 &temp_win,
2984         &abs_x, 
2985                 &abs_y, 
2986                 &win_x, 
2987                 &win_y, 
2988                 &temp_mask);
2989         if(lock_window) this->unlock_window();
2990         return abs_y;
2993 int BC_WindowBase::match_window(Window win) 
2995         if (this->win == win) return 1;
2996         int result = 0;
2997         for(int i = 0; i < subwindows->total; i++)
2998         {
2999                 result = subwindows->values[i]->match_window(win);
3000                 if (result) return result;
3001         }
3002         return 0;
3006 int BC_WindowBase::get_cursor_over_window()
3008         if(top_level != this) return top_level->get_cursor_over_window();
3010         int abs_x, abs_y, win_x, win_y;
3011         unsigned int temp_mask;
3012         Window temp_win1, temp_win2;
3014         if (!XQueryPointer(display, 
3015                 win, 
3016                 &temp_win1, 
3017                 &temp_win2,
3018                 &abs_x, 
3019                 &abs_y, 
3020                 &win_x, 
3021                 &win_y, 
3022                 &temp_mask))
3023                 return 0;
3025         int result = match_window(temp_win2)    ;
3026         return result;
3029 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
3031         int x, y;
3032         Window tempwin;
3034         translate_coordinates(top_level->event_win, 
3035                 pov->win,
3036                 top_level->cursor_x,
3037                 top_level->cursor_y,
3038                 &x,
3039                 &y);
3040         return x;
3043 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
3045         int x, y;
3046         Window tempwin;
3048         translate_coordinates(top_level->event_win, 
3049                 pov->win,
3050                 top_level->cursor_x,
3051                 top_level->cursor_y,
3052                 &x,
3053                 &y);
3054         return y;
3057 int BC_WindowBase::get_drag_x()
3059         return top_level->drag_x;
3062 int BC_WindowBase::get_drag_y()
3064         return top_level->drag_y;
3067 int BC_WindowBase::get_cursor_x()
3069         return top_level->cursor_x;
3072 int BC_WindowBase::get_cursor_y()
3074         return top_level->cursor_y;
3077 int BC_WindowBase::is_event_win()
3079         return this->win == top_level->event_win;
3082 void BC_WindowBase::set_dragging(int value)
3084         is_dragging = value;
3087 int BC_WindowBase::get_dragging()
3089         return is_dragging;
3092 int BC_WindowBase::get_buttonpress()
3094         return top_level->button_number;
3097 int BC_WindowBase::get_button_down()
3099         return top_level->button_down;
3102 int BC_WindowBase::alt_down()
3104         return top_level->alt_mask;
3107 int BC_WindowBase::shift_down()
3109         return top_level->shift_mask;
3112 int BC_WindowBase::ctrl_down()
3114         return top_level->ctrl_mask;
3118 int BC_WindowBase::get_keypress()
3120         return top_level->key_pressed;
3123 int BC_WindowBase::get_double_click()
3125         return top_level->double_click;
3128 int BC_WindowBase::get_bgcolor()
3130         return bg_color;
3133 int BC_WindowBase::resize_window(int w, int h)
3135         if(window_type == MAIN_WINDOW && !allow_resize)
3136         {
3137                 XSizeHints size_hints;
3138                 size_hints.flags = PSize | PMinSize | PMaxSize;
3139                 size_hints.width = w;
3140                 size_hints.height = h;
3141                 size_hints.min_width = w;
3142                 size_hints.max_width = w; 
3143                 size_hints.min_height = h;
3144                 size_hints.max_height = h; 
3145                 XSetNormalHints(top_level->display, win, &size_hints);
3146         }
3147         XResizeWindow(top_level->display, win, w, h);
3149         this->w = w;
3150         this->h = h;
3151         delete pixmap;
3152         pixmap = new BC_Pixmap(this, w, h);
3154 // Propagate to menubar
3155         for(int i = 0; i < subwindows->total; i++)
3156         {
3157                 subwindows->values[i]->dispatch_resize_event(w, h);
3158         }
3160         draw_background(0, 0, w, h);
3161         if(top_level == this && get_resources()->recursive_resizing)
3162                 resize_history.append(new BC_ResizeCall(w, h));
3163         return 0;
3166 // The only way for resize events to be propagated is by updating the internal w and h
3167 int BC_WindowBase::resize_event(int w, int h)
3169         if(window_type == MAIN_WINDOW)
3170         {
3171                 this->w = w;
3172                 this->h = h;
3173         }
3174         return 0;
3177 int BC_WindowBase::reposition_widget(int x, int y, int w, int h) 
3179   return(reposition_window(x, y, w, h));
3182 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3184         int resize = 0;
3186 // Some tools set their own dimensions before calling this, causing the 
3187 // resize check to skip.
3188         this->x = x;
3189         this->y = y;
3191         if(w > 0 && w != this->w)
3192         {
3193                 resize = 1;
3194                 this->w = w;
3195         }
3197         if(h > 0 && h != this->h)
3198         {
3199                 resize = 1;
3200                 this->h = h;
3201         }
3203 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3205         if(this->w <= 0)
3206                 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3207         if(this->h <= 0)
3208                 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3210         if(translation_count && window_type == MAIN_WINDOW)
3211         {
3212 // KDE shifts window right and down.
3213 // FVWM leaves window alone and adds border around it.
3214                 XMoveResizeWindow(top_level->display, 
3215                         win, 
3216                         x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x, 
3217                         y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y, 
3218                         this->w,
3219                         this->h);
3220         }
3221         else
3222         {
3223                 XMoveResizeWindow(top_level->display, 
3224                         win, 
3225                         x, 
3226                         y, 
3227                         this->w, 
3228                         this->h);
3229         }
3231         if(resize)
3232         {
3233                 delete pixmap;
3234                 pixmap = new BC_Pixmap(this, this->w, this->h);
3235 // Propagate to menubar
3236                 for(int i = 0; i < subwindows->total; i++)
3237                 {
3238                         subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3239                 }
3241 //              draw_background(0, 0, w, h);
3242         }
3244         return 0;
3247 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3249         get_resources()->tooltips_enabled = tooltips_enabled;
3250         return 0;
3253 int BC_WindowBase::raise_window(int do_flush)
3255         XRaiseWindow(top_level->display, win);
3256         if(do_flush) XFlush(top_level->display);
3257         return 0;
3260 void BC_WindowBase::set_background(VFrame *bitmap)
3262         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3264         bg_pixmap = new BC_Pixmap(this, 
3265                         bitmap, 
3266                         PIXMAP_OPAQUE);
3267         shared_bg_pixmap = 0;
3268         draw_background(0, 0, w, h);
3271 void BC_WindowBase::set_title(char *text)
3273         XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0); 
3274         strcpy(this->title, _(text));
3275         flush();
3278 char* BC_WindowBase::get_title()
3280         return title;
3283 int BC_WindowBase::get_toggle_value()
3285         return toggle_value;
3288 int BC_WindowBase::get_toggle_drag()
3290         return toggle_drag;
3293 int BC_WindowBase::set_icon(VFrame *data)
3295         if(icon_pixmap) delete icon_pixmap;
3296         icon_pixmap = new BC_Pixmap(top_level, 
3297                 data, 
3298                 PIXMAP_ALPHA,
3299                 1);
3301         icon_window = new BC_Popup(this, 
3302                 (int)BC_INFINITY, 
3303                 (int)BC_INFINITY, 
3304                 icon_pixmap->get_w(), 
3305                 icon_pixmap->get_h(), 
3306                 -1, 
3307                 1, // All windows are hidden initially
3308                 icon_pixmap);
3310         XWMHints wm_hints;
3311         wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3312         wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3313         wm_hints.icon_mask = icon_pixmap->get_alpha();
3314         wm_hints.icon_window = icon_window->win;
3315         wm_hints.window_group = XGroupLeader;
3317 // for(int i = 0; i < 1000; i++)
3318 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3319 // printf("\n");
3321         XSetWMHints(top_level->display, top_level->win, &wm_hints);
3322         XSync(top_level->display, 0);
3323         return 0;
3326 int BC_WindowBase::set_w(int w)
3328         this->w = w;
3329         return 0;
3332 int BC_WindowBase::set_h(int h)
3334         this->h = h;
3335         return 0;
3338 int BC_WindowBase::load_defaults(BC_Hash *defaults)
3340         BC_Resources *resources = get_resources();
3341         char string[BCTEXTLEN];
3342         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3343         {
3344                 sprintf(string, "FILEBOX_HISTORY%d", i);
3345                 resources->filebox_history[i][0] = 0;
3346                 defaults->get(string, resources->filebox_history[i]);
3347         }
3348         resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3349         resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3350         resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3351         defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3352         return 0;
3355 int BC_WindowBase::save_defaults(BC_Hash *defaults)
3357         BC_Resources *resources = get_resources();
3358         char string[BCTEXTLEN];
3359         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3360         {
3361                 sprintf(string, "FILEBOX_HISTORY%d", i);
3362                 defaults->update(string, resources->filebox_history[i]);
3363         }
3364         defaults->update("FILEBOX_MODE", resources->filebox_mode);
3365         defaults->update("FILEBOX_W", resources->filebox_w);
3366         defaults->update("FILEBOX_H", resources->filebox_h);
3367         defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3368         return 0;
3373 // For some reason XTranslateCoordinates can take a long time to return.
3374 // We work around this by only calling it when the event windows are different.
3375 void BC_WindowBase::translate_coordinates(Window src_w, 
3376                 Window dest_w,
3377                 int src_x,
3378                 int src_y,
3379                 int *dest_x_return,
3380                 int *dest_y_return)
3382         Window tempwin = 0;
3383 //Timer timer;
3384 //timer.update();
3385         if(src_w == dest_w)
3386         {
3387                 *dest_x_return = src_x;
3388                 *dest_y_return = src_y;
3389         }
3390         else
3391         {
3392                 XTranslateCoordinates(top_level->display, 
3393                         src_w, 
3394                         dest_w, 
3395                         src_x, 
3396                         src_y, 
3397                         dest_x_return, 
3398                         dest_y_return,
3399                         &tempwin);
3400 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3401         }
3410 #ifdef HAVE_LIBXXF86VM
3411 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3413    int foo,bar;
3414    *vm = 0;
3415    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3416            int vm_count,i;
3417            XF86VidModeModeInfo **vm_modelines;
3418            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3419            for (i = 0; i < vm_count; i++) {
3420                    if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3421                            *vm = i;
3422            }
3423            display = top_level->display;
3424            if (vm_modelines[*vm]->hdisplay == *width)
3425                    *vm = -1;
3426            else
3427            {
3428                    *width = vm_modelines[*vm]->hdisplay;
3429                    *height = vm_modelines[*vm]->vdisplay;
3430            }
3431    }
3434 void BC_WindowBase::scale_vm(int vm)
3436    int foo,bar,dotclock;
3437    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3438    {
3439            int vm_count;
3440            XF86VidModeModeInfo **vm_modelines;
3441            XF86VidModeModeLine vml;
3442            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3443            XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3444            orig_modeline.dotclock = dotclock;
3445            orig_modeline.hdisplay = vml.hdisplay;
3446            orig_modeline.hsyncstart = vml.hsyncstart;
3447            orig_modeline.hsyncend = vml.hsyncend;
3448            orig_modeline.htotal = vml.htotal;
3449            orig_modeline.vdisplay = vml.vdisplay;
3450            orig_modeline.vsyncstart = vml.vsyncstart;
3451            orig_modeline.vsyncend = vml.vsyncend;
3452            orig_modeline.vtotal = vml.vtotal;
3453            orig_modeline.flags = vml.flags;
3454            orig_modeline.privsize = vml.privsize;
3455            // orig_modeline.private = vml.private;
3456            XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3457            XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3458            XFlush(top_level->display);
3459    }
3462 void BC_WindowBase::restore_vm()
3464    XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3465    XFlush(top_level->display);
3469 #endif
3472 #ifdef HAVE_GL
3474 extern "C"
3476         GLXContext glXCreateContext(Display *dpy,
3477                                XVisualInfo *vis,
3478                                GLXContext shareList,
3479                                int direct);
3480         
3481         int glXMakeCurrent(Display *dpy,
3482                        Drawable drawable,
3483                        GLXContext ctx);
3485         void glXSwapBuffers(Display *dpy,
3486                        Drawable drawable);
3491 void BC_WindowBase::enable_opengl()
3493         lock_window("BC_WindowBase::enable_opengl");
3494         opengl_lock.lock();
3496         XVisualInfo viproto;
3497         XVisualInfo *visinfo;
3498         int nvi;
3500         viproto.screen = top_level->screen;
3501         visinfo = XGetVisualInfo(top_level->display,
3502         VisualScreenMask,
3503         &viproto,
3504         &nvi);
3506         gl_context = glXCreateContext(top_level->display,
3507                 visinfo,
3508                 0,
3509                 1);
3511         glXMakeCurrent(top_level->display,
3512                 win,
3513                 gl_context);
3515 // Need expose events for 3D
3516         unsigned long valuemask = CWEventMask;
3517         XSetWindowAttributes attributes;
3518         attributes.event_mask = DEFAULT_EVENT_MASKS |
3519                         ExposureMask;
3520         XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3522         opengl_lock.unlock();
3523         unlock_window();
3526 void BC_WindowBase::disable_opengl()
3528         unsigned long valuemask = CWEventMask;
3529         XSetWindowAttributes attributes;
3530         attributes.event_mask = DEFAULT_EVENT_MASKS;
3531         XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3534 void BC_WindowBase::lock_opengl()
3536         lock_window("BC_WindowBase::lock_opengl");
3537         opengl_lock.lock();
3538         glXMakeCurrent(top_level->display,
3539                 win,
3540                 gl_context);
3543 void BC_WindowBase::unlock_opengl()
3545         opengl_lock.unlock();
3546         unlock_window();
3549 void BC_WindowBase::flip_opengl()
3551         glXSwapBuffers(top_level->display, win);
3553 #endif
3555 int BC_WindowBase::get_event_count()
3557         event_lock->lock("BC_WindowBase::get_event_count");
3558         int result = common_events.total;
3559         event_lock->unlock();
3560         return result;
3563 XEvent* BC_WindowBase::get_event()
3565         XEvent *result = 0;
3566         while(!done && !result)
3567         {
3568                 event_condition->lock("BC_WindowBase::get_event");
3569                 event_lock->lock("BC_WindowBase::get_event");
3571                 if(common_events.total && !done)
3572                 {
3573                         result = common_events.values[0];
3574                         common_events.remove_number(0);
3575                 }
3577                 event_lock->unlock();
3578         }
3579         return result;
3582 void BC_WindowBase::put_event(XEvent *event)
3584         event_lock->lock("BC_WindowBase::put_event");
3585         common_events.append(event);
3586         event_lock->unlock();
3587         event_condition->unlock();