r819: When exporting properly set fourcc codes for DV video...
[cinelerra_cv/mob.git] / guicast / bcwindowbase.C
blob2625323f4ec4f87ffd9643025e3481bb2a6fc526
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 "bcwindowbase.h"
13 #include "bcwindowevents.h"
14 #include "colormodels.h"
15 #include "colors.h"
16 #include "condition.h"
17 #include "cursors.h"
18 #include "defaults.h"
19 #include "fonts.h"
20 #include "keys.h"
21 #include "language.h"
22 #include "sizes.h"
23 #include "vframe.h"
25 #ifdef HAVE_GL
26 #include <GL/gl.h>
27 #endif
28 #include <string.h>
29 #include <unistd.h>
31 #include <X11/extensions/Xvlib.h>
32 #include <X11/extensions/shape.h>
35 BC_ResizeCall::BC_ResizeCall(int w, int h)
37         this->w = w;
38         this->h = h;
50 Mutex BC_WindowBase::opengl_lock;
52 BC_Resources BC_WindowBase::resources;
54 Window XGroupLeader = 0;
56 BC_WindowBase::BC_WindowBase()
58 //printf("BC_WindowBase::BC_WindowBase 1\n");
59         BC_WindowBase::initialize();
62 BC_WindowBase::~BC_WindowBase()
65 #ifdef HAVE_LIBXXF86VM
66    if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
67    {
68            restore_vm();   
69    }
70 #endif
72         hide_tooltip();
73         if(window_type != MAIN_WINDOW)
74         {
75                 if(top_level->active_menubar == this) top_level->active_menubar = 0;
76                 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
77                 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
78                 parent_window->subwindows->remove(this);
79         }
82 // Delete the subwindows
83         is_deleting = 1;
84         if(subwindows)
85         {
86                 while (subwindows->total) 
87                 {
88                         // NOTE: since the value is itself a subwindow, the
89                         //       recursion removes the item from subwindows
90                         delete subwindows->values[0];
91                 }
92                 delete subwindows;
93         }
95         XFreePixmap(top_level->display, pixmap);
96         XDestroyWindow(top_level->display, win);
98         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
99         if(icon_pixmap) delete icon_pixmap;
100         if(temp_bitmap) delete temp_bitmap;
103         if(window_type == MAIN_WINDOW) 
104         {
105                 
106                 XFreeGC(display, gc);
107 #ifdef HAVE_XFT
108                 if(largefont_xft) 
109                         XftFontClose (display, (XftFont*)largefont_xft);
110                 if(mediumfont_xft) 
111                         XftFontClose (display, (XftFont*)mediumfont_xft);
112                 if(smallfont_xft) 
113                         XftFontClose (display, (XftFont*)smallfont_xft);
114 #endif
115                 flush();
116 // Can't close display if another thread is waiting for events
117                 XCloseDisplay(display);
118 //              XCloseDisplay(event_display);
119                 clipboard->stop_clipboard();
120                 delete clipboard;
121         }
122         else
123         {
124                 flush();
125         }
127         resize_history.remove_all_objects();
128         common_events.remove_all_objects();
129         delete event_lock;
130         delete event_condition;
131         UNSET_ALL_LOCKS(this)
134 int BC_WindowBase::initialize()
136         test_keypress = 0;
137         is_deleting = 0;
138         window_lock = 0;
139         x = 0; 
140         y = 0; 
141         w = 0; 
142         h = 0;
143         bg_color = -1;
144         top_level = 0;
145         parent_window = 0;
146         subwindows = 0;
147         xvideo_port_id = -1;
148         video_on = 0;
149         motion_events = 0;
150         resize_events = 0;
151         translation_events = 0;
152         ctrl_mask = shift_mask = alt_mask = 0;
153         cursor_x = cursor_y = button_number = 0;
154         button_down = 0;
155         button_pressed = 0;
156         button_time1 = button_time2 = 0;
157         double_click = 0;
158         last_motion_win = 0;
159         key_pressed = 0;
160         active_menubar = 0;
161         active_popup_menu = 0;
162         active_subwindow = 0;
163         bg_pixmap = 0;
164         tooltip_text[0] = 0;
165         persistant_tooltip = 0;
166 //      next_repeat_id = 0;
167         tooltip_popup = 0;
168         tooltip_done = 0;
169         current_font = MEDIUMFONT;
170         current_color = BLACK;
171         prev_cursor = current_cursor = ARROW_CURSOR;
172         hourglass_total = 0;
173         is_dragging = 0;
174         shared_bg_pixmap = 0;
175         icon_pixmap = 0;
176         window_type = MAIN_WINDOW;
177         translation_count = 0;
178         x_correction = y_correction = 0;
179         temp_bitmap = 0;
180         tooltip_on = 0;
181         temp_cursor = 0;
182         toggle_value = 0;
183         toggle_drag = 0;
184         has_focus = 0;
185 #ifdef HAVE_LIBXXF86VM
186     vm_switched = 0;
187 #endif
188         xft_drawable = 0;
189         largefont_xft = 0;
190         mediumfont_xft = 0;
191         smallfont_xft = 0;
192 // Need these right away since put_event is called before run_window sometimes.
193         event_lock = new Mutex("BC_WindowBase::event_lock");
194         event_condition = new Condition(0, "BC_WindowBase::event_condition");
195         event_thread = 0;
197         return 0;
200 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
201                         LeaveWindowMask | \
202                         ButtonPressMask | \
203                         ButtonReleaseMask | \
204                         PointerMotionMask | \
205                         FocusChangeMask
206                         
208 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
209                                 char *title, 
210                                 int x,
211                                 int y,
212                                 int w, 
213                                 int h, 
214                                 int minw, 
215                                 int minh, 
216                                 int allow_resize,
217                                 int private_color, 
218                                 int hide,
219                                 int bg_color,
220                                 char *display_name,
221                                 int window_type,
222                                 BC_Pixmap *bg_pixmap,
223                                 int group_it)
225         XSetWindowAttributes attr;
226         unsigned long mask;
227         XSizeHints size_hints;
228         int root_w;
229         int root_h;
230 #ifdef HAVE_LIBXXF86VM
231     int vm;
232 #endif
234     if(parent_window) top_level = parent_window->top_level;
236 #ifdef HAVE_LIBXXF86VM
237     if(window_type == VIDMODE_SCALED_WINDOW)
238             closest_vm(&vm,&w,&h);
239 #endif
241         this->x = x;
242         this->y = y;
243         this->w = w;
244         this->h = h;
245         this->bg_color = bg_color;
246         this->window_type = window_type;
247         this->hidden = hide;
248         this->private_color = private_color;
249         this->parent_window = parent_window;
250         this->bg_pixmap = bg_pixmap;
251         this->allow_resize = allow_resize;
252         strcpy(this->title, _(title));
253         if(bg_pixmap) shared_bg_pixmap = 1;
255         if(parent_window) top_level = parent_window->top_level;
257         subwindows = new BC_SubWindowList;
259 // Mandatory setup
260         if(window_type == MAIN_WINDOW)
261         {
262                 top_level = this;
263                 parent_window = this;
265 // This function must be the first Xlib
266 // function a multi-threaded program calls
267                 XInitThreads();
270 // get the display connection
271                 display = init_display(display_name);
272 //              event_display = init_display(display_name);
274 // Fudge window placement
275                 root_w = get_root_w(1, 0);
276                 root_h = get_root_h(0);
277                 if(this->x + this->w > root_w) this->x = root_w - this->w;
278                 if(this->y + this->h > root_h) this->y = root_h - this->h;
279                 if(this->x < 0) this->x = 0;
280                 if(this->y < 0) this->y = 0;
281                 screen = DefaultScreen(display);
283                 rootwin = RootWindow(display, screen);
284                 vis = DefaultVisual(display, screen);
285                 default_depth = DefaultDepth(display, screen);
286                 client_byte_order = (*(u_int32_t*)"a   ") & 0x00000001;
287                 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
291 // This must be done before fonts to know if antialiasing is available.
292                 init_colors();
293 // get the resources
294                 if(resources.use_shm < 0) resources.initialize_display(this);
295                 x_correction = get_resources()->get_left_border();
296                 y_correction = get_resources()->get_top_border();
298                 if(this->bg_color == -1)
299                         this->bg_color = resources.get_bg_color();
300                 init_fonts();
301                 init_gc();
302                 init_cursors();
304 // Create the window
305                 mask = CWEventMask | 
306                                 CWBackPixel | 
307                                 CWColormap | 
308                                 CWCursor;
310                 attr.event_mask = DEFAULT_EVENT_MASKS |
311                         StructureNotifyMask | 
312                         KeyPressMask;
314                 attr.background_pixel = get_color(this->bg_color);
315                 attr.colormap = cmap;
316                 attr.cursor = get_cursor_struct(ARROW_CURSOR);
318                 win = XCreateWindow(display, 
319                         rootwin, 
320                         this->x, 
321                         this->y, 
322                         this->w, 
323                         this->h, 
324                         0, 
325                         top_level->default_depth, 
326                         InputOutput, 
327                         vis, 
328                         mask, 
329                         &attr);
331                 XGetNormalHints(display, win, &size_hints);
333                 size_hints.flags = PSize | PMinSize | PMaxSize;
334                 size_hints.width = this->w;
335                 size_hints.height = this->h;
336                 size_hints.min_width = allow_resize ? minw : this->w;
337                 size_hints.max_width = allow_resize ? 32767 : this->w; 
338                 size_hints.min_height = allow_resize ? minh : this->h;
339                 size_hints.max_height = allow_resize ? 32767 : this->h; 
340                 if(x > -BC_INFINITY && x < BC_INFINITY)
341                 {
342                         size_hints.flags |= PPosition;
343                         size_hints.x = this->x;
344                         size_hints.y = this->y;
345                 }
347                 XSetStandardProperties(display, 
348                         win, 
349                         title, 
350                         title, 
351                         None, 
352                         0, 
353                         0, 
354                         &size_hints);
355                 get_atoms();
356                 
357                 clipboard = new BC_Clipboard(display_name);
358                 clipboard->start_clipboard();
360                 if (group_it)
361                 {
362                         Atom ClientLeaderXAtom;
363                         if (XGroupLeader == 0)
364                                 XGroupLeader = win;
365                         char *instance_name = "cinelerra";
366                         char *class_name = "Cinelerra";
367                         XClassHint *class_hints = XAllocClassHint(); 
368                         class_hints->res_name = instance_name;
369                         class_hints->res_class = class_name;
370                         XSetClassHint(top_level->display, win, class_hints);
371                         XFree(class_hints);
372                         ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
373                         XChangeProperty(display, 
374                                         win, 
375                                         ClientLeaderXAtom, 
376                                         XA_WINDOW, 
377                                         32, 
378                                         PropModeReplace, 
379                                         (unsigned char *)&XGroupLeader, 
380                                         true);
382                 }
383                 
384         }
386 #ifdef HAVE_LIBXXF86VM
387     if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
388     {
389             scale_vm (vm);
390             vm_switched = 1;
391     }
392 #endif
394 #ifdef HAVE_LIBXXF86VM
395     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
396 #else
397     if(window_type == POPUP_WINDOW)
398 #endif
399         {
400                 mask = CWEventMask | 
401                         CWBackPixel | 
402                         CWColormap | 
403                         CWOverrideRedirect | 
404                         CWSaveUnder | 
405                         CWCursor;
407                 attr.event_mask = DEFAULT_EVENT_MASKS |
408                         KeyPressMask;
410                 if(this->bg_color == -1)
411                         this->bg_color = resources.get_bg_color();
412                 attr.background_pixel = top_level->get_color(bg_color);
413                 attr.colormap = top_level->cmap;
414                 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
415                 attr.override_redirect = True;
416                 attr.save_under = True;
418                 win = XCreateWindow(top_level->display, 
419                         top_level->rootwin, 
420                         this->x, 
421                         this->y, 
422                         this->w, 
423                         this->h, 
424                         0, 
425                         top_level->default_depth, 
426                         InputOutput, 
427                         top_level->vis, 
428                         mask, 
429                         &attr);
430         }
432         if(window_type == SUB_WINDOW)
433         {
434                 mask = CWBackPixel | CWEventMask;
435                 attr.event_mask = DEFAULT_EVENT_MASKS;
436                 attr.background_pixel = top_level->get_color(this->bg_color);
437                 win = XCreateWindow(top_level->display, 
438                         parent_window->win, 
439                         this->x, 
440                         this->y, 
441                         this->w, 
442                         this->h, 
443                         0, 
444                         top_level->default_depth, 
445                         InputOutput, 
446                         top_level->vis, 
447                         mask, 
448                         &attr);
449                 init_window_shape();
450                 XMapWindow(top_level->display, win);
451         }
453 // Create pixmap for all windows
454         pixmap = XCreatePixmap(top_level->display, 
455                 win, 
456                 this->w, 
457                 this->h, 
458                 top_level->default_depth);
460 // Create truetype rendering surface
461 #ifdef HAVE_XFT
462         if(get_resources()->use_xft)
463         {
464 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n", 
465 // top_level->display,
466 // pixmap,
467 // top_level->vis,
468 // top_level->cmap);
469                 xft_drawable = XftDrawCreate(top_level->display,
470                        pixmap,
471                        top_level->vis,
472                        top_level->cmap);
473 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n", 
474 // xft_drawable, 
475 // top_level->display,
476 // pixmap,
477 // top_level->vis,
478 // top_level->cmap);
479         }
480 #endif
482 // Set up options for main window
483         if(window_type == MAIN_WINDOW)
484         {
485                 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
486                 {
487                         this->bg_pixmap = new BC_Pixmap(this, 
488                                 get_resources()->bg_image, 
489                                 PIXMAP_OPAQUE);
490                 }
492                 if(!hidden) show_window();
494         }
499         draw_background(0, 0, this->w, this->h);
500         flash();
502 // Set up options for popup window
503 #ifdef HAVE_LIBXXF86VM
504     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
505 #else
506     if(window_type == POPUP_WINDOW)
507 #endif
508         {
509                 init_window_shape();
510                 if(!hidden) show_window();
511         }
512         return 0;
515 Display* BC_WindowBase::init_display(char *display_name)
517         Display* display;
519         if(display_name && display_name[0] == 0) display_name = NULL;
520         if((display = XOpenDisplay(display_name)) == NULL)
521         {
522                 printf("BC_WindowBase::init_display: cannot connect to X server %s\n", 
523                         display_name);
524                 if(getenv("DISPLAY") == NULL)
525         {
526                         printf("'DISPLAY' environment variable not set.\n");
527                         exit(1);
528                 }
529                 else
530 // Try again with default display.
531                 {
532                         if((display = XOpenDisplay(0)) == NULL)
533                         {
534                                 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
535                                 exit(1);
536                         }
537                 }
538         }
539         return display;
542 int BC_WindowBase::run_window()
544         done = 0;
545         return_value = 0;
548 // Events may have been sent before run_window so can't initialize them here.
550 // Start tooltips
551         if(window_type == MAIN_WINDOW)
552         {
553 //              tooltip_id = get_repeat_id();
554                 set_repeat(get_resources()->tooltip_delay);
555         }
557 // Start X server events
558         event_thread = new BC_WindowEvents(this);
559         event_thread->start();
561 // Start common events
562         while(!done)
563         {
564                 dispatch_event();
565         }
567         unset_all_repeaters();
568         hide_tooltip();
569         delete event_thread;
570         event_thread = 0;
571         event_condition->reset();
572         common_events.remove_all_objects();
573         done = 0;
575         return return_value;
578 int BC_WindowBase::get_key_masks(XEvent *event)
580 // printf("BC_WindowBase::get_key_masks %llx\n", 
581 // event->xkey.state);
582 // ctrl key down
583         ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
584 // shift key down
585         shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
586         alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
587         return 0;
596 int BC_WindowBase::dispatch_event()
598         XEvent *event = 0;
599     Window tempwin;
600         KeySym keysym;
601         char keys_return[2];
602         int result;
603         XClientMessageEvent *ptr;
604         int temp;
605         int cancel_resize, cancel_translation;
607         key_pressed = 0;
609 // If an event is waiting get it, otherwise
610 // wait for next event only if there are no compressed events.
611         if(get_event_count() || 
612                 (!motion_events && !resize_events && !translation_events))
613         {
614 //              XNextEvent(display, event);
615                 event = get_event();
616 // Lock out window deletions
617                 lock_window("BC_WindowBase::dispatch_event 1");
618 //              get_key_masks(event);
619         }
620         else
621 // Handle compressed events
622         {
623                 lock_window("BC_WindowBase::dispatch_event 2");
624                 if(resize_events)
625                         dispatch_resize_event(last_resize_w, last_resize_h);
626                 else
627                 if(motion_events)
628                         dispatch_motion_event();
629                 else
630                 if(translation_events)
631                         dispatch_translation_event();
633                 unlock_window();
634                 return 0;
635         }
637 //printf("1 %s %p %d\n", title, event, event->type);
638         switch(event->type)
639         {
640                 case ClientMessage:
641                         get_key_masks(event);
642 // Clear the resize buffer
643                         if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
644 // Clear the motion buffer since this can clear the window
645                         if(motion_events)
646                         {
647                                 dispatch_motion_event();
648                         }
650                         ptr = (XClientMessageEvent*)event;
653                 if(ptr->message_type == ProtoXAtom && 
654                                 ptr->data.l[0] == DelWinXAtom)
655                 {
656                                 close_event();
657                         }
658                         else
659                         if(ptr->message_type == RepeaterXAtom)
660                         {
661                                 dispatch_repeat_event(ptr->data.l[0]);
662 // Make sure the repeater still exists.
663 //                              for(int i = 0; i < repeaters.total; i++)
664 //                              {
665 //                                      if(repeaters.values[i]->repeat_id == ptr->data.l[0])
666 //                                      {
667 //                                              dispatch_repeat_event_master(ptr->data.l[0]);
668 //                                              break;
669 //                                      }
670 //                              }
671                         }
672                         else
673                         if(ptr->message_type == SetDoneXAtom)
674                         {
675                                 done = 1;
676                         }
677                         break;
679                 case FocusIn:
680                         has_focus = 1;
681                         dispatch_focus_in();
682                         break;
684                 case FocusOut:
685                         has_focus = 0;
686                         dispatch_focus_out();
687                         break;
689 // Maximized
690                 case MapNotify:
691                         break;
693 // Minimized
694                 case UnmapNotify:
695                         break;
697                 case ButtonPress:
698                         get_key_masks(event);
699                         cursor_x = event->xbutton.x;
700                         cursor_y = event->xbutton.y;
701                         button_number = event->xbutton.button;
702                         event_win = event->xany.window;
703                         if (button_number != 4 && button_number != 5)
704                                 button_down = 1;
705                         button_pressed = event->xbutton.button;
706                         button_time1 = button_time2;
707                         button_time2 = event->xbutton.time;
708                         drag_x = cursor_x;
709                         drag_y = cursor_y;
710                         drag_win = event_win;
711                         drag_x1 = cursor_x - get_resources()->drag_radius;
712                         drag_x2 = cursor_x + get_resources()->drag_radius;
713                         drag_y1 = cursor_y - get_resources()->drag_radius;
714                         drag_y2 = cursor_y + get_resources()->drag_radius;
716                         if(button_time2 - button_time1 < resources.double_click)
717                         {
718 // Ignore triple clicks
719                                 double_click = 1; 
720                                 button_time2 = button_time1 = 0; 
721                         }
722                         else 
723                                 double_click = 0;
725                         dispatch_button_press();
726                         break;
728                 case ButtonRelease:
729                         get_key_masks(event);
730                         button_number = event->xbutton.button;
731                         event_win = event->xany.window;
732                         if (button_number != 4 && button_number != 5) 
733                                 button_down = 0;
735                         dispatch_button_release();
737                         break;
739                 case Expose:
740                         event_win = event->xany.window;
741                         dispatch_expose_event();
742                         break;
744                 case MotionNotify:
745                         get_key_masks(event);
746 // Dispatch previous motion event if this is a subsequent motion from a different window
747                         if(motion_events && last_motion_win != event->xany.window)
748                         {
749                                 dispatch_motion_event();
750                         }
752 // Buffer the current motion
753                         motion_events = 1;
754                         last_motion_x = event->xmotion.x;
755                         last_motion_y = event->xmotion.y;
756                         last_motion_win = event->xany.window;
757                         break;
759                 case ConfigureNotify:
760                         get_key_masks(event);
761                         XTranslateCoordinates(top_level->display, 
762                                 top_level->win, 
763                                 top_level->rootwin, 
764                                 0, 
765                                 0, 
766                                 &last_translate_x, 
767                                 &last_translate_y, 
768                                 &tempwin);
769                         last_resize_w = event->xconfigure.width;
770                         last_resize_h = event->xconfigure.height;
772                         cancel_resize = 0;
773                         cancel_translation = 0;
775 // Resize history prevents responses to recursive resize requests
776                         for(int i = 0; i < resize_history.total && !cancel_resize; i++)
777                         {
778                                 if(resize_history.values[i]->w == last_resize_w &&
779                                         resize_history.values[i]->h == last_resize_h)
780                                 {
781                                         delete resize_history.values[i];
782                                         resize_history.remove_number(i);
783                                         cancel_resize = 1;
784                                 }
785                         }
787                         if(last_resize_w == w && last_resize_h == h)
788                                 cancel_resize = 1;
790                         if(!cancel_resize)
791                         {
792                                 resize_events = 1;
793                         }
795                         if((last_translate_x == x && last_translate_y == y))
796                                 cancel_translation = 1;
798                         if(!cancel_translation)
799                         {
800                                 translation_events = 1;
801                         }
803                         translation_count++;
804                         break;
806                 case KeyPress:
807                         get_key_masks(event);
808                         keys_return[0] = 0;
809                         XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
811 // printf("BC_WindowBase::dispatch_event 2 %llx\n", 
812 // event->xkey.state);
813 // block out control keys
814                         if(keysym > 0xffe0 && keysym < 0xffff) break;
817                         if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
820                         switch(keysym)
821                         {
822 // block out extra keys
823                         case XK_Alt_L:      
824                         case XK_Alt_R:      
825                         case XK_Shift_L:    
826                         case XK_Shift_R:    
827                         case XK_Control_L:  
828                         case XK_Control_R:  
829                                         key_pressed = 0;         
830                                         break;
832 // Translate key codes
833                                 case XK_Return:     key_pressed = RETURN;    break;
834                         case XK_Up:         key_pressed = UP;        break;
835                                 case XK_Down:       key_pressed = DOWN;      break;
836                                 case XK_Left:       key_pressed = LEFT;      break;
837                         case XK_Right:      key_pressed = RIGHT;     break;
838                         case XK_Next:       key_pressed = PGDN;      break;
839                         case XK_Prior:      key_pressed = PGUP;      break;
840                         case XK_BackSpace:  key_pressed = BACKSPACE; break;
841                         case XK_Escape:     key_pressed = ESC;       break;
842                         case XK_Tab:
843                                         if(shift_down())
844                                                 key_pressed = LEFTTAB;
845                                         else
846                                                 key_pressed = TAB;       
847                                         break;
848                                 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
849                                 case XK_underscore: key_pressed = '_';       break;
850                         case XK_asciitilde: key_pressed = '~';       break;
851                                 case XK_Delete:     key_pressed = DELETE;    break;
852                                 case XK_Home:       key_pressed = HOME;      break;
853                                 case XK_End:        key_pressed = END;       break;
855 // number pad
856                                 case XK_KP_Enter:       key_pressed = KPENTER;   break;
857                                 case XK_KP_Add:         key_pressed = KPPLUS;    break;
858                                 case XK_KP_1:
859                                 case XK_KP_End:         key_pressed = KP1;       break;
860                                 case XK_KP_2:
861                                 case XK_KP_Down:        key_pressed = KP2;       break;
862                                 case XK_KP_3:
863                                 case XK_KP_Page_Down:   key_pressed = KP3;       break;
864                                 case XK_KP_4:
865                                 case XK_KP_Left:        key_pressed = KP4;       break;
866                                 case XK_KP_5:
867                                 case XK_KP_Begin:       key_pressed = KP5;       break;
868                                 case XK_KP_6:
869                                 case XK_KP_Right:       key_pressed = KP6;       break;
870                                 case XK_KP_0:
871                                 case XK_KP_Insert:      key_pressed = KPINS;     break;
872                                 case XK_KP_Decimal:
873                                 case XK_KP_Delete:      key_pressed = KPDEL;     break;
874                         default:           
875                                         //key_pressed = keys_return[0]; 
876                                         key_pressed = keysym & 0xff;
877                                         break;
878                         }
880 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
881                         result = dispatch_keypress_event();
882 // Handle some default keypresses
883                         if(!result)
884                         {
885                                 if(key_pressed == 'w' ||
886                                         key_pressed == 'W')
887                                 {
888                                         close_event();
889                                 }
890                         }
891                         break;
893                 case LeaveNotify:
894                         event_win = event->xany.window;
895                         dispatch_cursor_leave();
896                         break;
898                 case EnterNotify:
899                         event_win = event->xany.window;
900                         cursor_x = event->xcrossing.x;
901                         cursor_y = event->xcrossing.y;
902                         dispatch_cursor_enter();
903                         break;
904         }
905 //printf("100 %s %p %d\n", title, event, event->type);
907         unlock_window();
908         if(event) delete event;
909         return 0;
912 int BC_WindowBase::dispatch_expose_event()
914         int result = 0;
915         for(int i = 0; i < subwindows->total && !result; i++)
916         {
917                 result = subwindows->values[i]->dispatch_expose_event();
918         }
920 // Propagate to user
921         if(!result) expose_event();
922         return result;
925 int BC_WindowBase::dispatch_resize_event(int w, int h)
927         if(window_type == MAIN_WINDOW)
928         {
929                 resize_events = 0;
930 // Can't store w and h here because bcfilebox depends on the old w and h to
931 // reposition widgets.
932                 XFreePixmap(top_level->display, pixmap);
933                 pixmap = XCreatePixmap(top_level->display, 
934                         win, 
935                         w, 
936                         h, 
937                         top_level->default_depth);
938                 clear_box(0, 0, w, h);
939         }
941 // Propagate to subwindows
942         for(int i = 0; i < subwindows->total; i++)
943         {
944                 subwindows->values[i]->dispatch_resize_event(w, h);
945         }
947 // Propagate to user
948         resize_event(w, h);
950         if(window_type == MAIN_WINDOW)
951         {
952                 this->w = w;
953                 this->h = h;
954         }
955         return 0;
958 int BC_WindowBase::dispatch_translation_event()
960         translation_events = 0;
961         if(window_type == MAIN_WINDOW)
962         {
963                 prev_x = x;
964                 prev_y = y;
965                 x = last_translate_x;
966                 y = last_translate_y;
967 // Correct for window manager offsets
968                 x -= x_correction;
969                 y -= y_correction;
970         }
972         for(int i = 0; i < subwindows->total; i++)
973         {
974                 subwindows->values[i]->dispatch_translation_event();
975         }
977         translation_event();
978         return 0;
981 int BC_WindowBase::dispatch_motion_event()
983         int result = 0;
985         if(top_level == this)
986         {
987                 event_win = last_motion_win;
988                 motion_events = 0;
990 // Test for grab
991                 if(get_button_down() && !active_menubar && !active_popup_menu)
992                 {
993                         if(!result)
994                         {
995                                 cursor_x = last_motion_x;
996                                 cursor_y = last_motion_y;
997                                 result = dispatch_drag_motion();
998                         }
1000                         if(!result && 
1001                                 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 || 
1002                                 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1003                         {
1004                                 cursor_x = drag_x;
1005                                 cursor_y = drag_y;
1007                                 result = dispatch_drag_start();
1008                         }
1009                 }
1010                 cursor_x = last_motion_x;
1011                 cursor_y = last_motion_y;
1013                 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1014                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1015                 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1016         }
1018         for(int i = 0; i < subwindows->total && !result; i++)
1019         {
1020                 result = subwindows->values[i]->dispatch_motion_event();
1021         }
1023         if(!result) result = cursor_motion_event();    // give to user
1024         return result;
1027 int BC_WindowBase::dispatch_keypress_event()
1029         int result = 0;
1030         if(top_level == this)
1031         {
1032                 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1033         }
1035         for(int i = 0; i < subwindows->total && !result; i++)
1036         {
1037                 result = subwindows->values[i]->dispatch_keypress_event();
1038         }
1040         if(!result) result = keypress_event();
1042         return result;
1045 int BC_WindowBase::dispatch_focus_in()
1047         for(int i = 0; i < subwindows->total; i++)
1048         {
1049                 subwindows->values[i]->dispatch_focus_in();
1050         }
1052         focus_in_event();
1054         return 0;
1057 int BC_WindowBase::dispatch_focus_out()
1059         for(int i = 0; i < subwindows->total; i++)
1060         {
1061                 subwindows->values[i]->dispatch_focus_out();
1062         }
1064         focus_out_event();
1066         return 0;
1069 int BC_WindowBase::get_has_focus()
1071         return top_level->has_focus;
1074 int BC_WindowBase::get_deleting()
1076         if(is_deleting) return 1;
1077         if(parent_window && parent_window->get_deleting()) return 1;
1078         return 0;
1081 int BC_WindowBase::dispatch_button_press()
1083         int result = 0;
1084         if(top_level == this)
1085         {
1086                 if(active_menubar) result = active_menubar->dispatch_button_press();
1087                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1088                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1089         }
1091         for(int i = 0; i < subwindows->total && !result; i++)
1092         {
1093                 result = subwindows->values[i]->dispatch_button_press();
1094         }
1096         if(!result) result = button_press_event();
1098         return result;
1101 int BC_WindowBase::dispatch_button_release()
1103         int result = 0;
1104         if(top_level == this)
1105         {
1106                 if(active_menubar) result = active_menubar->dispatch_button_release();
1107 //printf("BC_WindowBase::dispatch_button_release 1 %d\n", result);
1108                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1109 //printf("BC_WindowBase::dispatch_button_release 2 %p %d\n", active_subwindow, result);
1110                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1111 //printf("BC_WindowBase::dispatch_button_release 3 %d\n", result);
1112                 if(!result && button_number != 4 && button_number != 5)
1113                         result = dispatch_drag_stop();
1114         }
1115 //printf("BC_WindowBase::dispatch_button_release 4 %d\n", result);
1117         for(int i = 0; i < subwindows->total && !result; i++)
1118         {
1119                 result = subwindows->values[i]->dispatch_button_release();
1120         }
1121 //printf("BC_WindowBase::dispatch_button_release 5 %d\n", result);
1123         if(!result)
1124         {
1125                 result = button_release_event();
1126         }
1127 //printf("BC_WindowBase::dispatch_button_release 6 %d\n", result);
1129         return result;
1133 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1136 // all repeat event handlers get called and decide based on activity and duration
1137 // whether to respond
1138         for(int i = 0; i < subwindows->total; i++)
1139         {
1140                 subwindows->values[i]->dispatch_repeat_event(duration);
1141         }
1142         repeat_event(duration);
1144 // Unlock next signal
1145         if(window_type == MAIN_WINDOW)
1146         {
1147                 for(int i = 0; i < repeaters.total; i++)
1148                 {
1149                         if(repeaters.values[i]->delay == duration)
1150                         {
1151                                 repeaters.values[i]->repeat_lock->unlock();
1152                         }
1153                 }
1154         }
1156         return 0;
1159 int BC_WindowBase::dispatch_cursor_leave()
1161         for(int i = 0; i < subwindows->total; i++)
1162         {
1163                 subwindows->values[i]->dispatch_cursor_leave();
1164         }
1166         cursor_leave_event();
1167         return 0;
1170 int BC_WindowBase::dispatch_cursor_enter()
1172         int result = 0;
1174         if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1175         if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1176         if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1178         for(int i = 0; !result && i < subwindows->total; i++)
1179         {
1180                 result = subwindows->values[i]->dispatch_cursor_enter();
1181         }
1183         if(!result) result = cursor_enter_event();
1184         return result;
1187 int BC_WindowBase::cursor_enter_event()
1189         return 0;
1192 int BC_WindowBase::cursor_leave_event()
1194         return 0;
1197 int BC_WindowBase::close_event()
1199         set_done(1);
1200         return 1;
1203 int BC_WindowBase::dispatch_drag_start()
1205         int result = 0;
1206         if(active_menubar) result = active_menubar->dispatch_drag_start();
1207         if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1208         if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1209         
1210         for(int i = 0; i < subwindows->total && !result; i++)
1211         {
1212                 result = subwindows->values[i]->dispatch_drag_start();
1213         }
1215         if(!result) result = is_dragging = drag_start_event();
1216         return result;
1219 int BC_WindowBase::dispatch_drag_stop()
1221         int result = 0;
1223         for(int i = 0; i < subwindows->total && !result; i++)
1224         {
1225                 result = subwindows->values[i]->dispatch_drag_stop();
1226         }
1228         if(is_dragging && !result) 
1229         {
1230                 drag_stop_event();
1231                 is_dragging = 0;
1232                 result = 1;
1233         }
1235         return result;
1238 int BC_WindowBase::dispatch_drag_motion()
1240         int result = 0;
1241         for(int i = 0; i < subwindows->total && !result; i++)
1242         {
1243                 result = subwindows->values[i]->dispatch_drag_motion();
1244         }
1245         
1246         if(is_dragging && !result)
1247         {
1248                 drag_motion_event();
1249                 result = 1;
1250         }
1251         
1252         return result;
1259 int BC_WindowBase::show_tooltip(int w, int h)
1261         Window tempwin;
1263         if(!tooltip_on && get_resources()->tooltips_enabled)
1264         {
1265                 int i, j, x, y;
1266                 top_level->hide_tooltip();
1268                 tooltip_on = 1;
1269                 if(w < 0)
1270                         w = get_text_width(MEDIUMFONT, tooltip_text);
1272                 if(h < 0)
1273                         h = get_text_height(MEDIUMFONT, tooltip_text);
1275                 w += TOOLTIP_MARGIN * 2;
1276                 h += TOOLTIP_MARGIN * 2;
1278                 XTranslateCoordinates(top_level->display, 
1279                                 win, 
1280                                 top_level->rootwin, 
1281                                 get_w(), 
1282                                 get_h(), 
1283                                 &x, 
1284                                 &y, 
1285                                 &tempwin);
1286                 tooltip_popup = new BC_Popup(top_level, 
1287                                         x,
1288                                         y,
1289                                         w, 
1290                                         h, 
1291                                         get_resources()->tooltip_bg_color);
1293                 draw_tooltip();
1294                 tooltip_popup->set_font(MEDIUMFONT);
1295                 tooltip_popup->flash();
1296                 tooltip_popup->flush();
1297         }
1298         return 0;
1301 int BC_WindowBase::hide_tooltip()
1303         if(subwindows)
1304                 for(int i = 0; i < subwindows->total; i++)
1305                 {
1306                         subwindows->values[i]->hide_tooltip();
1307                 }
1309         if(tooltip_on)
1310         {
1311                 tooltip_on = 0;
1312                 delete tooltip_popup;
1313                 tooltip_popup = 0;
1314         }
1315         return 0;
1318 int BC_WindowBase::set_tooltip(char *text)
1320         strcpy(this->tooltip_text, text);
1321 // Update existing tooltip if it is visible
1322         if(tooltip_on)
1323         {
1324                 draw_tooltip();
1325                 tooltip_popup->flash();
1326         }
1327         return 0;
1330 // signal the event handler to repeat
1331 int BC_WindowBase::set_repeat(int64_t duration)
1333         if(duration <= 0)
1334         {
1335                 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1336                 return 0;
1337         }
1338         if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1340 // test repeater database for duplicates
1341         for(int i = 0; i < repeaters.total; i++)
1342         {
1343 // Already exists
1344                 if(repeaters.values[i]->delay == duration)
1345                 {
1346                         repeaters.values[i]->start_repeating();
1347                         return 0;
1348                 }
1349         }
1351         BC_Repeater *repeater = new BC_Repeater(this, duration);
1352         repeater->initialize();
1353         repeaters.append(repeater);
1354     repeater->start_repeating();
1355         return 0;
1358 int BC_WindowBase::unset_repeat(int64_t duration)
1360         if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1362         BC_Repeater *repeater = 0;
1363         for(int i = 0; i < repeaters.total; i++)
1364         {
1365                 if(repeaters.values[i]->delay == duration)
1366                 {
1367                         repeaters.values[i]->stop_repeating();
1368                 }
1369         }
1370         return 0;
1374 int BC_WindowBase::unset_all_repeaters()
1376         for(int i = 0; i < repeaters.total; i++)
1377         {
1378                 repeaters.values[i]->stop_repeating();
1379         }
1380         repeaters.remove_all_objects();
1381         return 0;
1384 // long BC_WindowBase::get_repeat_id()
1385 // {
1386 //      return top_level->next_repeat_id++;
1387 // }
1389 int BC_WindowBase::arm_repeat(int64_t duration)
1391         XEvent *event = new XEvent;
1392         XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1393         ptr->type = ClientMessage;
1394         ptr->message_type = RepeaterXAtom;
1395         ptr->format = 32;
1396         ptr->data.l[0] = duration;
1398 // Couldn't use XSendEvent since it locked up randomly.
1399         put_event(event);
1400 //      XSendEvent(top_level->event_display, 
1401 //              top_level->win, 
1402 //              0, 
1403 //              0, 
1404 //              event);
1405 //      flush();
1406         return 0;
1409 int BC_WindowBase::get_atoms()
1411         SetDoneXAtom =  XInternAtom(display, "BC_REPEAT_EVENT", False);
1412         RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1413         DelWinXAtom =   XInternAtom(display, "WM_DELETE_WINDOW", False);
1414         if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1415                 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1416         return 0;
1419 void BC_WindowBase::init_cursors()
1421         arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1422         cross_cursor = XCreateFontCursor(display, XC_crosshair);
1423         ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1424         vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1425         hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1426         move_cursor = XCreateFontCursor(display, XC_fleur);
1427         left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1428         right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1429         upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1430         upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1431         upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1432         downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1433         downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1434         hourglass_cursor = XCreateFontCursor(display, XC_watch);
1437 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1439         int color_model;
1440         switch(depth)
1441         {
1442                 case 8:
1443                         color_model = BC_RGB8;
1444                         break;
1445                 case 16:
1446                         color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1447                         break;
1448                 case 24:
1449                         color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1450                         break;
1451                 case 32:
1452                         color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1453                         break;
1454         }
1455         return color_model;
1458 int BC_WindowBase::init_colors()
1460         total_colors = 0;
1461         current_color_value = current_color_pixel = 0;
1463 // Get the real depth
1464         char *data = 0;
1465         XImage *ximage;
1466         ximage = XCreateImage(top_level->display, 
1467                                         top_level->vis, 
1468                                         top_level->default_depth, 
1469                                         ZPixmap, 
1470                                         0, 
1471                                         data, 
1472                                         16, 
1473                                         16, 
1474                                         8, 
1475                                         0);
1476         bits_per_pixel = ximage->bits_per_pixel;
1477         XDestroyImage(ximage);
1479         color_model = evaluate_color_model(client_byte_order, 
1480                 server_byte_order, 
1481                 bits_per_pixel);
1482 // Get the color model
1483         switch(color_model)
1484         {
1485                 case BC_RGB8:
1486                         if(private_color)
1487                         {
1488                                 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1489                                 create_private_colors();
1490                         }
1491                         else
1492                         {
1493                                 cmap = DefaultColormap(display, screen);
1494                                 create_shared_colors();
1495                         }
1497                         allocate_color_table();
1498 // No antialiasing
1499                         get_resources()->use_xft = 0;
1500                         break;
1502                 default:
1503                         cmap = DefaultColormap(display, screen);
1504                         break;
1505         }
1506         return 0;
1509 int BC_WindowBase::create_private_colors()
1511         int color;
1512         total_colors = 256;
1514         for(int i = 0; i < 255; i++)
1515         {
1516                 color = (i & 0xc0) << 16;
1517                 color += (i & 0x38) << 10;
1518                 color += (i & 0x7) << 5;
1519                 color_table[i][0] = color;
1520         }
1521         create_shared_colors();        // overwrite the necessary colors on the table
1522         return 0;
1526 int BC_WindowBase::create_color(int color)
1528         if(total_colors == 256)
1529         {
1530 // replace the closest match with an exact match
1531                 color_table[get_color_rgb8(color)][0] = color;
1532         }
1533         else
1534         {
1535 // add the color to the table
1536                 color_table[total_colors][0] = color;
1537                 total_colors++;
1538         }
1539         return 0;
1542 int BC_WindowBase::create_shared_colors()
1544         create_color(BLACK);
1545         create_color(WHITE);   
1547         create_color(LTGREY);  
1548         create_color(MEGREY);  
1549         create_color(MDGREY);  
1550         create_color(DKGREY);                           
1552         create_color(LTCYAN);  
1553         create_color(MECYAN);  
1554         create_color(MDCYAN);  
1555         create_color(DKCYAN);  
1557         create_color(LTGREEN); 
1558         create_color(GREEN);   
1559         create_color(DKGREEN); 
1561         create_color(LTPINK);  
1562         create_color(PINK);
1563         create_color(RED);     
1565         create_color(LTBLUE);  
1566         create_color(BLUE);    
1567         create_color(DKBLUE);  
1569         create_color(LTYELLOW); 
1570         create_color(MEYELLOW); 
1571         create_color(MDYELLOW); 
1572         create_color(DKYELLOW); 
1574         create_color(LTPURPLE); 
1575         create_color(MEPURPLE); 
1576         create_color(MDPURPLE); 
1577         create_color(DKPURPLE); 
1579         create_color(FGGREY); 
1580         create_color(MNBLUE);
1581         create_color(ORANGE);
1582         create_color(FTGREY);
1584         return 0;
1587 int BC_WindowBase::allocate_color_table()
1589         int red, green, blue, color;
1590         int result;
1591         XColor col;
1593         for(int i = 0; i < total_colors; i++)
1594         {
1595                 color = color_table[i][0];
1596                 red = (color & 0xFF0000) >> 16;
1597                 green = (color & 0x00FF00) >> 8;
1598                 blue = color & 0xFF;
1600                 col.flags = DoRed | DoGreen | DoBlue;
1601                 col.red   = red<<8   | red;
1602                 col.green = green<<8 | green;
1603                 col.blue  = blue<<8  | blue;
1605                 XAllocColor(display, cmap, &col);
1606                 color_table[i][1] = col.pixel;
1607         }
1609         XInstallColormap(display, cmap);
1610         return 0;
1613 int BC_WindowBase::init_window_shape()
1615         if(bg_pixmap && bg_pixmap->use_alpha()) 
1616         {
1617                 XShapeCombineMask(top_level->display,
1618                 this->win,
1619                 ShapeBounding,
1620                 0,
1621                 0,
1622                 bg_pixmap->get_alpha(),
1623                 ShapeSet);
1624         }
1625         return 0;
1629 int BC_WindowBase::init_gc()
1631         unsigned long gcmask;
1632         gcmask = GCFont | GCGraphicsExposures;
1634         XGCValues gcvalues;
1635         gcvalues.font = mediumfont->fid;        // set the font
1636         gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
1637         gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1638         return 0;
1641 int BC_WindowBase::init_fonts()
1643         if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL &&
1644                 (largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL) 
1645                 largefont = XLoadQueryFont(display, "fixed"); 
1647         if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL &&
1648                 (mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1649                 mediumfont = XLoadQueryFont(display, "fixed"); 
1651         if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL &&
1652                 (smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1653                 smallfont = XLoadQueryFont(display, "fixed");
1655 #ifdef HAVE_XFT
1656         if(get_resources()->use_xft)
1657         {
1660 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
1662                 if(!(largefont_xft = XftFontOpenXlfd(display,
1663                     screen,
1664                     resources.large_font_xft)))
1665                 {
1666                         largefont_xft = XftFontOpenXlfd(display,
1667                         screen,
1668                         "fixed");
1669                 }
1670 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
1671                 if(!(largefont_xft = XftFontOpenXlfd(display,
1672                     screen,
1673                     resources.large_font_xft)))
1674                 {
1675                         largefont_xft = XftFontOpenXlfd(display,
1676                         screen,
1677                         "fixed");
1678                 }
1679 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
1682                 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1683                       screen,
1684                       resources.medium_font_xft)))
1685                 {
1686                         mediumfont_xft = XftFontOpenXlfd(display,
1687                         screen,
1688                         "fixed");
1689                 }
1692                 if(!(smallfont_xft = XftFontOpenXlfd(display,
1693                       screen,
1694                       resources.small_font_xft)))
1695                 {
1696                           smallfont_xft = XftFontOpenXlfd(display,
1697                           screen,
1698                           "fixed");
1699                 }
1701 //printf("BC_WindowBase::init_fonts 100 %s %p\n", 
1702 //resources.medium_font, 
1703 //mediumfont_xft);
1705 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
1706         resources.large_font_xft,
1707         largefontset,
1708         resources.medium_font_xft,
1709         mediumfontset,
1710         resources.small_font_xft,
1711         smallfontset);
1713 // Extension failed to locate fonts
1714                 if(!largefontset || !mediumfontset || !smallfontset)
1715                 {
1716                         printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1717                                 resources.large_font_xft,
1718                                 largefontset,
1719                                 resources.medium_font_xft,
1720                                 mediumfontset,
1721                                 resources.small_font_xft,
1722                                 smallfontset);
1723                         get_resources()->use_xft = 0;
1724                 }
1725         }
1726         else
1727 #endif
1728         if(get_resources()->use_fontset)
1729         {
1730                 char **m, *d;
1731                 int n;
1733 // FIXME: should check the m,d,n values
1734                 if((largefontset = XCreateFontSet(display, 
1735                         resources.large_fontset,
1736             &m, 
1737                         &n, 
1738                         &d)) == 0)
1739             largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1740                 if((mediumfontset = XCreateFontSet(display, 
1741                         resources.medium_fontset,
1742             &m, 
1743                         &n, 
1744                         &d)) == 0)
1745             mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1746                 if((smallfontset = XCreateFontSet(display, 
1747                         resources.small_fontset,
1748             &m, 
1749                         &n, 
1750                         &d)) == 0)
1751             smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1753                 if(largefontset && mediumfontset && smallfontset)
1754                 {
1755                         curr_fontset = mediumfontset;
1756                         get_resources()->use_fontset = 1;
1757                 }
1758                 else
1759                 {
1760                         curr_fontset = 0;
1761                         get_resources()->use_fontset = 0;
1762                 }
1763         }
1765         return 0;
1768 int BC_WindowBase::get_color(int64_t color) 
1770 // return pixel of color
1771 // use this only for drawing subwindows not for bitmaps
1772          int i, test, difference, result;
1774         switch(color_model)
1775         {
1776                 case BC_RGB8:
1777                         if(private_color)
1778                         {
1779                                 return get_color_rgb8(color);
1780                         }
1781                         else
1782                         {
1783 // test last color looked up
1784                                 if(current_color_value == color) return current_color_pixel;
1786 // look up in table
1787                                 current_color_value = color;
1788                                 for(i = 0; i < total_colors; i++)
1789                                 {
1790                                         if(color_table[i][0] == color)
1791                                         {
1792                                                 current_color_pixel = color_table[i][1];
1793                                                 return current_color_pixel;
1794                                         }
1795                                 }
1797 // find nearest match
1798                                 difference = 0xFFFFFF;
1800                                 for(i = 0, result = 0; i < total_colors; i++)
1801                                 {
1802                                         test = abs((int)(color_table[i][0] - color));
1804                                         if(test < difference) 
1805                                         {
1806                                                 current_color_pixel = color_table[i][1]; 
1807                                                 difference = test;
1808                                         }
1809                                 }
1811                                 return current_color_pixel;
1812                         }
1813                         break;  
1815                 case BC_RGB565:
1816                         return get_color_rgb16(color);
1817                         break;
1819                 case BC_BGR565:
1820                         return get_color_bgr16(color);
1821                         break;
1823                 case BC_RGB888:
1824                 case BC_BGR888:
1825                         if(client_byte_order == server_byte_order)
1826                                 return color;
1827                         else
1828                                 get_color_bgr24(color);
1829                         break;
1831                 default:
1832                         return color;
1833                         break;  
1834         }
1835         return 0;
1838 int BC_WindowBase::get_color_rgb8(int color)
1840         int pixel;
1842         pixel = (color & 0xc00000) >> 16;
1843         pixel += (color & 0xe000) >> 10;
1844         pixel += (color & 0xe0) >> 5;
1845         return pixel;
1848 int64_t BC_WindowBase::get_color_rgb16(int color)
1850         int64_t result;
1851         result = (color & 0xf80000) >> 8;
1852         result += (color & 0xfc00) >> 5;
1853         result += (color & 0xf8) >> 3;
1854         
1855         return result;
1858 int64_t BC_WindowBase::get_color_bgr16(int color)
1860         int64_t result;
1861         result = (color & 0xf80000) >> 19;
1862         result += (color & 0xfc00) >> 5;
1863         result += (color & 0xf8) << 8;
1865         return result;
1868 int64_t BC_WindowBase::get_color_bgr24(int color)
1870         int64_t result;
1871         result = (color & 0xff) << 16;
1872         result += (color & 0xff00);
1873         result += (color & 0xff0000) >> 16;
1874         return result;
1877 int BC_WindowBase::video_is_on()
1879         return video_on;
1882 void BC_WindowBase::start_video()
1884         video_on = 1;
1885 //      set_color(BLACK);
1886 //      draw_box(0, 0, get_w(), get_h());
1887 //      flash();
1890 void BC_WindowBase::stop_video()
1892         video_on = 0;
1897 int64_t BC_WindowBase::get_color()
1899         return top_level->current_color;
1902 void BC_WindowBase::set_color(int64_t color)
1904         top_level->current_color = color;
1905         XSetForeground(top_level->display, 
1906                 top_level->gc, 
1907                 top_level->get_color(color));
1910 void BC_WindowBase::set_opaque()
1912         XSetFunction(top_level->display, top_level->gc, GXcopy);
1915 void BC_WindowBase::set_inverse() 
1917         XSetFunction(top_level->display, top_level->gc, GXxor);
1920 Cursor BC_WindowBase::get_cursor_struct(int cursor)
1922         switch(cursor)
1923         {
1924                 case ARROW_CURSOR:         return top_level->arrow_cursor;                 break;
1925                 case CROSS_CURSOR:         return top_level->cross_cursor;
1926                 case IBEAM_CURSOR:         return top_level->ibeam_cursor;                 break;
1927                 case VSEPARATE_CURSOR:     return top_level->vseparate_cursor;             break;
1928                 case HSEPARATE_CURSOR:     return top_level->hseparate_cursor;             break;
1929                 case MOVE_CURSOR:              return top_level->move_cursor;                  break;
1930                 case LEFT_CURSOR:          return top_level->left_cursor;                  break;
1931                 case RIGHT_CURSOR:         return top_level->right_cursor;                 break;
1932                 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;         break;
1933                 case UPLEFT_RESIZE:        return top_level->upleft_resize_cursor;         break;
1934                 case UPRIGHT_RESIZE:       return top_level->upright_resize_cursor;        break;
1935                 case DOWNLEFT_RESIZE:      return top_level->downleft_resize_cursor;       break;
1936                 case DOWNRIGHT_RESIZE:     return top_level->downright_resize_cursor;      break;
1937                 case HOURGLASS_CURSOR:     return top_level->hourglass_cursor;             break;
1938         }
1939         return 0;
1942 void BC_WindowBase::set_cursor(int cursor, int is_hourglass)
1944 // don't change cursor if hourglass mode unless the caller is the hourglass routine.
1945         if(is_hourglass || current_cursor != HOURGLASS_CURSOR)
1946         {
1947                 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
1948                 current_cursor = cursor;
1949                 flush();
1950         }
1951         else
1952 // save new cursor for later
1953         {
1954                 prev_cursor = cursor;
1955         }
1958 void BC_WindowBase::set_x_cursor(int cursor)
1960         temp_cursor = XCreateFontCursor(top_level->display, cursor);
1961         XDefineCursor(top_level->display, win, temp_cursor);
1962         current_cursor = cursor;
1963         flush();
1966 int BC_WindowBase::get_cursor()
1968         return current_cursor;
1971 void BC_WindowBase::start_hourglass()
1973         top_level->start_hourglass_recursive();
1974         top_level->flush();
1977 void BC_WindowBase::stop_hourglass()
1979         top_level->stop_hourglass_recursive();
1980         top_level->flush();
1983 void BC_WindowBase::start_hourglass_recursive()
1985         if(this == top_level)
1986         {
1987                 hourglass_total++;
1988                 if(current_cursor == HOURGLASS_CURSOR) return;
1989         }
1991         prev_cursor = current_cursor;
1992         set_cursor(HOURGLASS_CURSOR, 1);
1993         for(int i = 0; i < subwindows->total; i++)
1994         {
1995                 subwindows->values[i]->start_hourglass_recursive();
1996         }
1999 void BC_WindowBase::stop_hourglass_recursive()
2001         if(this == top_level)
2002         {
2003                 if(hourglass_total == 0) return;
2004                 hourglass_total--;
2005         }
2007 // Cause set_cursor to perform change
2008         set_cursor(prev_cursor, 1);
2009         for(int i = 0; i < subwindows->total; i++)
2010         {
2011                 subwindows->values[i]->stop_hourglass_recursive();
2012         }
2020 XFontStruct* BC_WindowBase::get_font_struct(int font)
2022 // Clear out unrelated flags
2023         if(font & BOLDFACE) font ^= BOLDFACE;
2024         
2025         switch(font)
2026         {
2027                 case MEDIUMFONT: return top_level->mediumfont; break;
2028                 case SMALLFONT:  return top_level->smallfont;  break;
2029                 case LARGEFONT:  return top_level->largefont;  break;
2030         }
2031         return 0;
2034 XFontSet BC_WindowBase::get_fontset(int font)
2036         XFontSet fs = 0;
2038         if(get_resources()->use_fontset)
2039         {
2040                 switch(font)
2041                 {
2042                         case SMALLFONT:  fs = top_level->smallfontset; break;
2043                         case LARGEFONT:  fs = top_level->largefontset; break;
2044                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2045                 }
2046         }
2048         return fs;
2051 #ifdef HAVE_XFT
2052 XftFont* BC_WindowBase::get_xft_struct(int font)
2054 // Clear out unrelated flags
2055         if(font & BOLDFACE) font ^= BOLDFACE;
2057         switch(font)
2058         {
2059                 case MEDIUMFONT:   return (XftFont*)top_level->mediumfont_xft; break;
2060                 case SMALLFONT:    return (XftFont*)top_level->smallfont_xft;  break;
2061                 case LARGEFONT:    return (XftFont*)top_level->largefont_xft;  break;
2062         }
2064         return 0;
2066 #endif
2078 void BC_WindowBase::set_font(int font)
2080         top_level->current_font = font;
2083 #ifdef HAVE_XFT
2084         if(get_resources()->use_xft)
2085         {
2086                 ;
2087         }
2088         else
2089 #endif
2090         if(get_resources()->use_fontset)
2091         {
2092                 set_fontset(font);
2093         }
2095         if(get_font_struct(font))
2096         {
2097                 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2098         }
2100         return;
2103 void BC_WindowBase::set_fontset(int font)
2105         XFontSet fs = 0;
2107         if(get_resources()->use_fontset)
2108         {
2109                 switch(font)
2110                 {
2111                         case SMALLFONT:  fs = top_level->smallfontset; break;
2112                         case LARGEFONT:  fs = top_level->largefontset; break;
2113                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2114                 }
2115         }
2117         curr_fontset = fs;
2121 XFontSet BC_WindowBase::get_curr_fontset(void)
2123         if(get_resources()->use_fontset)
2124                 return curr_fontset;
2125         return 0;
2128 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2130 #ifdef HAVE_XFT
2131         if(get_resources()->use_xft && get_xft_struct(font))
2132         {
2133                 XGlyphInfo extents;
2134                 XftTextExtents8(top_level->display,
2135                         get_xft_struct(font),
2136                         (FcChar8*)text, 
2137                         length,
2138                         &extents);
2139                 return extents.xOff;
2140         }
2141         else
2142 #endif
2143         if(get_resources()->use_fontset && top_level->get_fontset(font))
2144                 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2145         else
2146         if(get_font_struct(font)) 
2147                 return XTextWidth(get_font_struct(font), text, length);
2148         else
2149         {
2150                 int w = 0;
2151                 switch(font)
2152                 {
2153                         case MEDIUM_7SEGMENT:
2154                                 return get_resources()->medium_7segment[0]->get_w() * length;
2155                                 break;
2157                         default:
2158                                 return 0;
2159                 }
2160                 return w;
2161         }
2164 int BC_WindowBase::get_text_width(int font, char *text, int length)
2166         int i, j, w = 0, line_w = 0;
2167         if(length < 0) length = strlen(text);
2169         for(i = 0, j = 0; i <= length; i++)
2170         {
2171                 line_w = 0;
2172                 if(text[i] == '\n')
2173                 {
2174                         line_w = get_single_text_width(font, &text[j], i - j);
2175                         j = i + 1;
2176                 }
2177                 else
2178                 if(text[i] == 0)
2179                 {
2180                         line_w = get_single_text_width(font, &text[j], length - j);
2181                 }
2182                 if(line_w > w) w = line_w;
2183         }
2185         if(i > length && w == 0)
2186         {
2187                 w = get_single_text_width(font, text, length);
2188         }
2190         return w;
2193 int BC_WindowBase::get_text_ascent(int font)
2195 #ifdef HAVE_XFT
2196         if(get_resources()->use_xft && get_xft_struct(font))
2197         {
2198                 XGlyphInfo extents;
2199                 XftTextExtents8(top_level->display,
2200                         get_xft_struct(font),
2201                         (FcChar8*)"O", 
2202                         1,
2203                         &extents);
2204                 return extents.y;
2205         }
2206         else
2207 #endif
2208         if(get_resources()->use_fontset && top_level->get_fontset(font))
2209         {
2210         XFontSetExtents *extents;
2212         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2213         return -extents->max_logical_extent.y;
2214         }
2215         else
2216         if(get_font_struct(font))
2217                 return top_level->get_font_struct(font)->ascent;
2218         else
2219         switch(font)
2220         {
2221                 case MEDIUM_7SEGMENT:
2222                         return get_resources()->medium_7segment[0]->get_h();
2223                         break;
2225                 default:
2226                         return 0;
2227         }
2230 int BC_WindowBase::get_text_descent(int font)
2232 #ifdef HAVE_XFT
2233         if(get_resources()->use_xft && get_xft_struct(font))
2234         {
2235                 XGlyphInfo extents;
2236                 XftTextExtents8(top_level->display,
2237                         get_xft_struct(font),
2238                         (FcChar8*)"j", 
2239                         1,
2240                         &extents);
2241                 return extents.height - extents.y;
2242         }
2243         else
2244 #endif
2245     if(get_resources()->use_fontset && top_level->get_fontset(font))
2246     {
2247         XFontSetExtents *extents;
2249         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2250         return (extents->max_logical_extent.height
2251                         + extents->max_logical_extent.y);
2252     }
2253     else
2254         if(get_font_struct(font))
2255                 return top_level->get_font_struct(font)->descent;
2256         else
2257         switch(font)
2258         {
2259                 default:
2260                         return 0;
2261         }
2264 int BC_WindowBase::get_text_height(int font, char *text)
2266         if(!text) return get_text_ascent(font) + get_text_descent(font);
2268 // Add height of lines
2269         int h = 0, i, length = strlen(text);
2270         for(i = 0; i <= length; i++)
2271         {
2272                 if(text[i] == '\n')
2273                         h++;
2274                 else
2275                 if(text[i] == 0)
2276                         h++;
2277         }
2278         return h * (get_text_ascent(font) + get_text_descent(font));
2281 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2283         if(color_model < 0) color_model = top_level->get_color_model();
2284         return new BC_Bitmap(top_level, w, h, color_model);
2287 int BC_WindowBase::accel_available(int color_model, int lock_it)
2289         if(window_type != MAIN_WINDOW) 
2290                 return top_level->accel_available(color_model, lock_it);
2292         int result = 0;
2294         if(lock_it) lock_window("BC_WindowBase::accel_available");
2295         switch(color_model)
2296         {
2297                 case BC_YUV420P:
2298                         result = grab_port_id(this, color_model);
2299                         if(result >= 0)
2300                         {
2301                                 xvideo_port_id = result;
2302                                 result = 1;
2303                         }
2304                         else
2305                                 result = 0;
2306                         break;
2308                 case BC_YUV422P:
2309                         result = 0;
2310                         break;
2312                 case BC_YUV422:
2313 //printf("BC_WindowBase::accel_available 1\n");
2314                         result = grab_port_id(this, color_model);
2315 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2316                         if(result >= 0)
2317                         {
2318                                 xvideo_port_id = result;
2319                                 result = 1;
2320                         }
2321                         else
2322                                 result = 0;
2323 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2324                         break;
2326                 default:
2327                         result = 0;
2328                         break;
2329         }
2331         if(lock_it) unlock_window();
2332 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2333         return result;
2337 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2339         int numFormats, i, j, k;
2340         unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2341         int port_id = -1;
2342     XvAdaptorInfo *info;
2343     XvImageFormatValues *formats;
2344         int x_color_model;
2346         if(!get_resources()->use_xvideo) return -1;
2348 // Translate from color_model to X color model
2349         x_color_model = cmodel_bc_to_x(color_model);
2351 // Only local server is fast enough.
2352         if(!resources.use_shm) return -1;
2354 // XV extension is available
2355     if(Success != XvQueryExtension(window->display, 
2356                                   &ver, 
2357                                   &rev, 
2358                                   &reqBase, 
2359                                   &eventBase, 
2360                                   &errorBase))
2361     {
2362                 return -1;
2363     }
2365 // XV adaptors are available
2366         XvQueryAdaptors(window->display, 
2367                 DefaultRootWindow(window->display), 
2368                 &numAdapt, 
2369                 &info);
2371         if(!numAdapt)
2372         {
2373                 return -1;
2374         }
2376 // Get adaptor with desired color model
2377     for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2378     {
2379 /* adaptor supports XvImages */
2380                 if(info[i].type & XvImageMask) 
2381                 {  
2382                 formats = XvListImageFormats(window->display, 
2383                                                         info[i].base_id, 
2384                                                         &numFormats);
2385 // for(j = 0; j < numFormats; j++)
2386 //      printf("%08x\n", formats[j].id);
2388                 for(j = 0; j < numFormats && xvideo_port_id < 0; j++) 
2389                 {
2390 /* this adaptor supports the desired format */
2391                                 if(formats[j].id == x_color_model)
2392                                 {
2393 /* Try to grab a port */
2394                                         for(k = 0; k < info[i].num_ports; k++)
2395                                         {
2396 /* Got a port */
2397                                                 if(Success == XvGrabPort(top_level->display, 
2398                                                         info[i].base_id + k, 
2399                                                         CurrentTime))
2400                                                 {
2401 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2402                                                         xvideo_port_id = info[i].base_id + k;
2403                                                         break;
2404                                                 }
2405                                         }
2406                                 }
2407                         }
2408                 if(formats) XFree(formats);
2409                 }
2410         }
2412     XvFreeAdaptorInfo(info);
2414         return xvideo_port_id;
2418 int BC_WindowBase::show_window(int flush) 
2420         XMapWindow(top_level->display, win); 
2421         if(flush) XFlush(top_level->display);
2422 //      XSync(top_level->display, 0);
2423         hidden = 0; 
2424         return 0;
2427 int BC_WindowBase::hide_window(int flush) 
2429         XUnmapWindow(top_level->display, win); 
2430         if(flush) XFlush(top_level->display);
2431         hidden = 1; 
2432         return 0;
2435 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2437         subwindows->append((BC_SubWindow*)menu_bar);
2439         menu_bar->parent_window = this;
2440         menu_bar->top_level = this->top_level;
2441         menu_bar->initialize();
2442         return menu_bar;
2445 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2447         subwindows->append(subwindow);
2449         if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2451 // parent window must be set before the subwindow initialization
2452         subwindow->parent_window = this;
2453         subwindow->top_level = this->top_level;
2455 // Execute derived initialization
2456         subwindow->initialize();
2457         return subwindow;
2461 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2463         return add_subwindow(subwindow);
2466 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2468         set_opaque();
2469         XSetWindowBackgroundPixmap(top_level->display, win, pixmap);
2470         if(x >= 0)
2471         {
2472                 XClearArea(top_level->display, win, x, y, w, h, 0);
2473         }
2474         else
2475         {
2476                 XClearWindow(top_level->display, win);
2477         }
2479         if(flush)
2480                 this->flush();
2481         return 0;
2484 int BC_WindowBase::flash(int flush)
2486         flash(-1, -1, -1, -1, flush);
2489 void BC_WindowBase::flush()
2491         XFlush(top_level->display);
2494 void BC_WindowBase::sync_display()
2496         XSync(top_level->display, False);
2499 int BC_WindowBase::get_window_lock()
2501         return top_level->window_lock;
2504 int BC_WindowBase::lock_window(char *location) 
2506         if(top_level && top_level != this)
2507         {
2508                 top_level->lock_window(location);
2509         }
2510         else
2511         if(top_level)
2512         {
2513                 SET_LOCK(this, title, location);
2514                 XLockDisplay(top_level->display);
2515                 SET_LOCK2
2516                 top_level->window_lock = 1;
2517         }
2518         else
2519         {
2520                 printf("BC_WindowBase::lock_window top_level NULL\n");
2521         }
2522         return 0;
2525 int BC_WindowBase::unlock_window() 
2527         if(top_level && top_level != this)
2528         {
2529                 top_level->unlock_window();
2530         }
2531         else
2532         if(top_level)
2533         {
2534                 UNSET_LOCK(this);
2535                 top_level->window_lock = 0;
2536                 XUnlockDisplay(top_level->display);
2537         }
2538         else
2539         {
2540                 printf("BC_WindowBase::unlock_window top_level NULL\n");
2541         }
2542         return 0;
2545 void BC_WindowBase::set_done(int return_value)
2547         if(window_type != MAIN_WINDOW)
2548                 top_level->set_done(return_value);
2549         else
2550         if(event_thread)
2551         {
2552                 XEvent *event = new XEvent;
2553                 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2555                 event->type = ClientMessage;
2556                 ptr->message_type = SetDoneXAtom;
2557                 ptr->format = 32;
2558                 this->return_value = return_value;
2560 // May lock up here because XSendEvent doesn't work too well 
2561 // asynchronous with XNextEvent.
2562 // This causes BC_WindowEvents to forward a copy of the event to run_window where 
2563 // it is deleted.
2564                 event_thread->done = 1;
2565                 XSendEvent(display, 
2566                         win, 
2567                         0, 
2568                         0, 
2569                         event);
2570                 flush();
2571                 put_event(event);
2572         }
2575 int BC_WindowBase::get_w()
2577         return w;
2580 int BC_WindowBase::get_h()
2582         return h;
2585 int BC_WindowBase::get_x()
2587         return x;
2590 int BC_WindowBase::get_y()
2592         return y;
2595 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2597         if(lock_display) lock_window("BC_WindowBase::get_root_w");
2598         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2599         int result = WidthOfScreen(screen_ptr);
2600 // Wider than 16:9, narrower than dual head
2601         if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2603         if(lock_display) unlock_window();
2604         return result;
2607 int BC_WindowBase::get_root_h(int lock_display)
2609         if(lock_display) lock_window("BC_WindowBase::get_root_h");
2610         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2611         int result = HeightOfScreen(screen_ptr);
2612         if(lock_display) unlock_window();
2613         return result;
2616 // Bottom right corner
2617 int BC_WindowBase::get_x2()
2619         return w + x;
2622 int BC_WindowBase::get_y2()
2624         return y + h;
2627 int BC_WindowBase::get_video_on()
2629         return video_on;
2632 int BC_WindowBase::get_hidden()
2634         return top_level->hidden;
2637 int BC_WindowBase::cursor_inside()
2639         return (top_level->cursor_x >= 0 && 
2640                         top_level->cursor_y >= 0 && 
2641                         top_level->cursor_x < w && 
2642                         top_level->cursor_y < h);
2645 BC_WindowBase* BC_WindowBase::get_top_level()
2647         return top_level;
2650 BC_WindowBase* BC_WindowBase::get_parent()
2652         return parent_window;
2655 int BC_WindowBase::get_color_model()
2657         return top_level->color_model;
2660 BC_Resources* BC_WindowBase::get_resources()
2662         return &BC_WindowBase::resources;
2665 int BC_WindowBase::get_bg_color()
2667         return bg_color;
2670 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2672         return bg_pixmap;
2675 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2677         top_level->active_subwindow = subwindow;
2680 int BC_WindowBase::activate()
2682         return 0;
2685 int BC_WindowBase::deactivate()
2687         if(window_type == MAIN_WINDOW)
2688         {
2689                 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2690                 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2691                 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2693                 top_level->active_menubar = 0;
2694                 top_level->active_popup_menu = 0;
2695                 top_level->active_subwindow = 0;
2696         }
2697         return 0;
2700 int BC_WindowBase::cycle_textboxes(int amount)
2702         int result = 0;
2703         BC_WindowBase *new_textbox = 0;
2705         if(amount > 0)
2706         {
2707                 BC_WindowBase *first_textbox = 0;
2708                 find_next_textbox(&first_textbox, &new_textbox, result);
2709                 if(!new_textbox) new_textbox = first_textbox;
2710                 
2711         }
2712         else
2713         if(amount < 0)
2714         {
2715                 BC_WindowBase *last_textbox = 0;
2716                 find_prev_textbox(&last_textbox, &new_textbox, result);
2717                 if(!new_textbox) new_textbox = last_textbox;
2718                 
2719         }
2721         if(new_textbox != active_subwindow)
2722         {
2723                 deactivate();
2724                 new_textbox->activate();
2725         }
2726         
2727         return 0;
2730 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2732 // Search subwindows for textbox
2733         for(int i = 0; i < subwindows->total && result < 2; i++)
2734         {
2735                 BC_WindowBase *test_subwindow = subwindows->values[i];
2736                 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2737         }
2739         if(result < 2)
2740         {
2741                 if(uses_text())
2742                 {
2743                         if(!*first_textbox) *first_textbox = this;
2745                         if(result < 1)
2746                         {
2747                                 if(top_level->active_subwindow == this)
2748                                         result++;
2749                         }
2750                         else
2751                         {
2752                                 result++;
2753                                 *next_textbox = this;
2754                         }
2755                 }
2756         }
2757         return 0;
2760 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2762         if(result < 2)
2763         {
2764                 if(uses_text())
2765                 {
2766                         if(!*last_textbox) *last_textbox = this;
2768                         if(result < 1)
2769                         {
2770                                 if(top_level->active_subwindow == this)
2771                                         result++;
2772                         }
2773                         else
2774                         {
2775                                 result++;
2776                                 *prev_textbox = this;
2777                         }
2778                 }
2779         }
2781 // Search subwindows for textbox
2782         for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2783         {
2784                 BC_WindowBase *test_subwindow = subwindows->values[i];
2785                 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2786         }
2787         return 0;
2790 BC_Clipboard* BC_WindowBase::get_clipboard()
2792         return top_level->clipboard;
2795 int BC_WindowBase::get_relative_cursor_x()
2797         int abs_x, abs_y, x, y, win_x, win_y;
2798         unsigned int temp_mask;
2799         Window temp_win;
2801         XQueryPointer(top_level->display, 
2802            top_level->win, 
2803            &temp_win, 
2804            &temp_win,
2805        &abs_x, 
2806            &abs_y, 
2807            &win_x, 
2808            &win_y, 
2809            &temp_mask);
2811         XTranslateCoordinates(top_level->display, 
2812                         top_level->rootwin, 
2813                         win, 
2814                         abs_x, 
2815                         abs_y, 
2816                         &x, 
2817                         &y, 
2818                         &temp_win);
2820         return x;
2823 int BC_WindowBase::get_relative_cursor_y()
2825         int abs_x, abs_y, x, y, win_x, win_y;
2826         unsigned int temp_mask;
2827         Window temp_win;
2829         XQueryPointer(top_level->display, 
2830            top_level->win, 
2831            &temp_win, 
2832            &temp_win,
2833        &abs_x, 
2834            &abs_y, 
2835            &win_x, 
2836            &win_y, 
2837            &temp_mask);
2839         XTranslateCoordinates(top_level->display, 
2840                         top_level->rootwin, 
2841                         win, 
2842                         abs_x, 
2843                         abs_y, 
2844                         &x, 
2845                         &y, 
2846                         &temp_win);
2848         return y;
2851 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2853         int abs_x, abs_y, win_x, win_y;
2854         unsigned int temp_mask;
2855         Window temp_win;
2857 SET_TRACE
2858         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2859 SET_TRACE
2860         XQueryPointer(top_level->display, 
2861                 top_level->win, 
2862                 &temp_win, 
2863                 &temp_win,
2864                 &abs_x, 
2865                 &abs_y, 
2866                 &win_x, 
2867                 &win_y, 
2868                 &temp_mask);
2869 SET_TRACE
2870         if(lock_window) this->unlock_window();
2871 SET_TRACE
2872         return abs_x;
2875 int BC_WindowBase::get_abs_cursor_y(int lock_window)
2877         int abs_x, abs_y, win_x, win_y;
2878         unsigned int temp_mask;
2879         Window temp_win;
2881         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
2882         XQueryPointer(top_level->display, 
2883                 top_level->win, 
2884                 &temp_win, 
2885                 &temp_win,
2886         &abs_x, 
2887                 &abs_y, 
2888                 &win_x, 
2889                 &win_y, 
2890                 &temp_mask);
2891         if(lock_window) this->unlock_window();
2892         return abs_y;
2895 int BC_WindowBase::match_window(Window win) 
2897         if (this->win == win) return 1;
2898         int result = 0;
2899         for(int i = 0; i < subwindows->total; i++)
2900         {
2901                 result = subwindows->values[i]->match_window(win);
2902                 if (result) return result;
2903         }
2904         return 0;
2908 int BC_WindowBase::get_cursor_over_window()
2910         if(top_level != this) return top_level->get_cursor_over_window();
2912         int abs_x, abs_y, win_x, win_y;
2913         unsigned int temp_mask;
2914         Window temp_win1, temp_win2;
2916         if (!XQueryPointer(display, 
2917                 win, 
2918                 &temp_win1, 
2919                 &temp_win2,
2920                 &abs_x, 
2921                 &abs_y, 
2922                 &win_x, 
2923                 &win_y, 
2924                 &temp_mask))
2925                 return 0;
2927         int result = match_window(temp_win2)    ;
2928         return result;
2931 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
2933         int x, y;
2934         Window tempwin;
2936         translate_coordinates(top_level->event_win, 
2937                 pov->win,
2938                 top_level->cursor_x,
2939                 top_level->cursor_y,
2940                 &x,
2941                 &y);
2942         return x;
2945 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
2947         int x, y;
2948         Window tempwin;
2950         translate_coordinates(top_level->event_win, 
2951                 pov->win,
2952                 top_level->cursor_x,
2953                 top_level->cursor_y,
2954                 &x,
2955                 &y);
2956         return y;
2959 int BC_WindowBase::get_drag_x()
2961         return top_level->drag_x;
2964 int BC_WindowBase::get_drag_y()
2966         return top_level->drag_y;
2969 int BC_WindowBase::get_cursor_x()
2971         return top_level->cursor_x;
2974 int BC_WindowBase::get_cursor_y()
2976         return top_level->cursor_y;
2979 int BC_WindowBase::is_event_win()
2981         return this->win == top_level->event_win;
2984 void BC_WindowBase::set_dragging(int value)
2986         is_dragging = value;
2989 int BC_WindowBase::get_dragging()
2991         return is_dragging;
2994 int BC_WindowBase::get_buttonpress()
2996         return top_level->button_number;
2999 int BC_WindowBase::get_button_down()
3001         return top_level->button_down;
3004 int BC_WindowBase::alt_down()
3006         return top_level->alt_mask;
3009 int BC_WindowBase::shift_down()
3011         return top_level->shift_mask;
3014 int BC_WindowBase::ctrl_down()
3016         return top_level->ctrl_mask;
3020 int BC_WindowBase::get_keypress()
3022         return top_level->key_pressed;
3025 int BC_WindowBase::get_double_click()
3027         return top_level->double_click;
3030 int BC_WindowBase::get_bgcolor()
3032         return bg_color;
3035 int BC_WindowBase::resize_window(int w, int h)
3037         if(window_type == MAIN_WINDOW && !allow_resize)
3038         {
3039                 XSizeHints size_hints;
3040                 size_hints.flags = PSize | PMinSize | PMaxSize;
3041                 size_hints.width = w;
3042                 size_hints.height = h;
3043                 size_hints.min_width = w;
3044                 size_hints.max_width = w; 
3045                 size_hints.min_height = h;
3046                 size_hints.max_height = h; 
3047                 XSetNormalHints(top_level->display, win, &size_hints);
3048         }
3049         XResizeWindow(top_level->display, win, w, h);
3051         this->w = w;
3052         this->h = h;
3053         XFreePixmap(top_level->display, pixmap);
3054         pixmap = XCreatePixmap(top_level->display, win, w, h, top_level->default_depth);
3056 // Propagate to menubar
3057         for(int i = 0; i < subwindows->total; i++)
3058         {
3059                 subwindows->values[i]->dispatch_resize_event(w, h);
3060         }
3062         draw_background(0, 0, w, h);
3063         if(top_level == this && get_resources()->recursive_resizing)
3064                 resize_history.append(new BC_ResizeCall(w, h));
3065         return 0;
3068 // The only way for resize events to be propagated is by updating the internal w and h
3069 int BC_WindowBase::resize_event(int w, int h)
3071         if(window_type == MAIN_WINDOW)
3072         {
3073                 this->w = w;
3074                 this->h = h;
3075         }
3076         return 0;
3079 int BC_WindowBase::reposition_widget(int x, int y, int w, int h) 
3081   return(reposition_window(x, y, w, h));
3084 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3086         int resize = 0;
3088 // Some tools set their own dimensions before calling this, causing the 
3089 // resize check to skip.
3090         this->x = x;
3091         this->y = y;
3093         if(w > 0 && w != this->w)
3094         {
3095                 resize = 1;
3096                 this->w = w;
3097         }
3099         if(h > 0 && h != this->h)
3100         {
3101                 resize = 1;
3102                 this->h = h;
3103         }
3105 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3107         if(this->w <= 0)
3108                 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3109         if(this->h <= 0)
3110                 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3112         if(translation_count && window_type == MAIN_WINDOW)
3113         {
3114 // KDE shifts window right and down.
3115 // FVWM leaves window alone and adds border around it.
3116                 XMoveResizeWindow(top_level->display, 
3117                         win, 
3118                         x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x, 
3119                         y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y, 
3120                         this->w,
3121                         this->h);
3122         }
3123         else
3124         {
3125                 XMoveResizeWindow(top_level->display, 
3126                         win, 
3127                         x, 
3128                         y, 
3129                         this->w, 
3130                         this->h);
3131         }
3133         if(resize)
3134         {
3135                 XFreePixmap(top_level->display, pixmap);
3136                 pixmap = XCreatePixmap(top_level->display, 
3137                         win, 
3138                         this->w, 
3139                         this->h, 
3140                         top_level->default_depth);
3142 // Propagate to menubar
3143                 for(int i = 0; i < subwindows->total; i++)
3144                 {
3145                         subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3146                 }
3148 //              draw_background(0, 0, w, h);
3149         }
3151         return 0;
3154 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3156         get_resources()->tooltips_enabled = tooltips_enabled;
3157         return 0;
3160 int BC_WindowBase::raise_window(int do_flush)
3162         XRaiseWindow(top_level->display, win);
3163         if(do_flush) XFlush(top_level->display);
3164         return 0;
3167 void BC_WindowBase::set_background(VFrame *bitmap)
3169         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3171         bg_pixmap = new BC_Pixmap(this, 
3172                         bitmap, 
3173                         PIXMAP_OPAQUE);
3174         shared_bg_pixmap = 0;
3175         draw_background(0, 0, w, h);
3178 void BC_WindowBase::set_title(char *text)
3180         XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0); 
3181         strcpy(this->title, _(text));
3182         flush();
3185 char* BC_WindowBase::get_title()
3187         return title;
3190 int BC_WindowBase::get_toggle_value()
3192         return toggle_value;
3195 int BC_WindowBase::get_toggle_drag()
3197         return toggle_drag;
3200 int BC_WindowBase::set_icon(VFrame *data)
3202         if(icon_pixmap) delete icon_pixmap;
3203         icon_pixmap = new BC_Pixmap(top_level, 
3204                 data, 
3205                 PIXMAP_ALPHA,
3206                 1);
3208         icon_window = new BC_Popup(this, 
3209                 (int)BC_INFINITY, 
3210                 (int)BC_INFINITY, 
3211                 icon_pixmap->get_w(), 
3212                 icon_pixmap->get_h(), 
3213                 -1, 
3214                 1, // All windows are hidden initially
3215                 icon_pixmap);
3217         XWMHints wm_hints;
3218         wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3219         wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3220         wm_hints.icon_mask = icon_pixmap->get_alpha();
3221         wm_hints.icon_window = icon_window->win;
3222         wm_hints.window_group = XGroupLeader;
3224 // for(int i = 0; i < 1000; i++)
3225 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3226 // printf("\n");
3228         XSetWMHints(top_level->display, top_level->win, &wm_hints);
3229         XSync(top_level->display, 0);
3230         return 0;
3233 int BC_WindowBase::set_w(int w)
3235         this->w = w;
3236         return 0;
3239 int BC_WindowBase::set_h(int h)
3241         this->h = h;
3242         return 0;
3245 int BC_WindowBase::load_defaults(Defaults *defaults)
3247         BC_Resources *resources = get_resources();
3248         char string[BCTEXTLEN];
3249         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3250         {
3251                 sprintf(string, "FILEBOX_HISTORY%d", i);
3252                 resources->filebox_history[i][0] = 0;
3253                 defaults->get(string, resources->filebox_history[i]);
3254         }
3255         resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3256         resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3257         resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3258         defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3259         return 0;
3262 int BC_WindowBase::save_defaults(Defaults *defaults)
3264         BC_Resources *resources = get_resources();
3265         char string[BCTEXTLEN];
3266         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3267         {
3268                 sprintf(string, "FILEBOX_HISTORY%d", i);
3269                 defaults->update(string, resources->filebox_history[i]);
3270         }
3271         defaults->update("FILEBOX_MODE", resources->filebox_mode);
3272         defaults->update("FILEBOX_W", resources->filebox_w);
3273         defaults->update("FILEBOX_H", resources->filebox_h);
3274         defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3275         return 0;
3280 // For some reason XTranslateCoordinates can take a long time to return.
3281 // We work around this by only calling it when the event windows are different.
3282 void BC_WindowBase::translate_coordinates(Window src_w, 
3283                 Window dest_w,
3284                 int src_x,
3285                 int src_y,
3286                 int *dest_x_return,
3287                 int *dest_y_return)
3289         Window tempwin = 0;
3290 //Timer timer;
3291 //timer.update();
3292         if(src_w == dest_w)
3293         {
3294                 *dest_x_return = src_x;
3295                 *dest_y_return = src_y;
3296         }
3297         else
3298         {
3299                 XTranslateCoordinates(top_level->display, 
3300                         src_w, 
3301                         dest_w, 
3302                         src_x, 
3303                         src_y, 
3304                         dest_x_return, 
3305                         dest_y_return,
3306                         &tempwin);
3307 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3308         }
3317 #ifdef HAVE_LIBXXF86VM
3318 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3320    int foo,bar;
3321    *vm = 0;
3322    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3323            int vm_count,i;
3324            XF86VidModeModeInfo **vm_modelines;
3325            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3326            for (i = 0; i < vm_count; i++) {
3327                    if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3328                            *vm = i;
3329            }
3330            display = top_level->display;
3331            if (vm_modelines[*vm]->hdisplay == *width)
3332                    *vm = -1;
3333            else
3334            {
3335                    *width = vm_modelines[*vm]->hdisplay;
3336                    *height = vm_modelines[*vm]->vdisplay;
3337            }
3338    }
3341 void BC_WindowBase::scale_vm(int vm)
3343    int foo,bar,dotclock;
3344    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3345    {
3346            int vm_count;
3347            XF86VidModeModeInfo **vm_modelines;
3348            XF86VidModeModeLine vml;
3349            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3350            XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3351            orig_modeline.dotclock = dotclock;
3352            orig_modeline.hdisplay = vml.hdisplay;
3353            orig_modeline.hsyncstart = vml.hsyncstart;
3354            orig_modeline.hsyncend = vml.hsyncend;
3355            orig_modeline.htotal = vml.htotal;
3356            orig_modeline.vdisplay = vml.vdisplay;
3357            orig_modeline.vsyncstart = vml.vsyncstart;
3358            orig_modeline.vsyncend = vml.vsyncend;
3359            orig_modeline.vtotal = vml.vtotal;
3360            orig_modeline.flags = vml.flags;
3361            orig_modeline.privsize = vml.privsize;
3362            // orig_modeline.private = vml.private;
3363            XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3364            XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3365            XFlush(top_level->display);
3366    }
3369 void BC_WindowBase::restore_vm()
3371    XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3372    XFlush(top_level->display);
3376 #endif
3379 #ifdef HAVE_GL
3381 extern "C"
3383         GLXContext glXCreateContext(Display *dpy,
3384                                XVisualInfo *vis,
3385                                GLXContext shareList,
3386                                int direct);
3387         
3388         int glXMakeCurrent(Display *dpy,
3389                        Drawable drawable,
3390                        GLXContext ctx);
3392         void glXSwapBuffers(Display *dpy,
3393                        Drawable drawable);
3398 void BC_WindowBase::enable_opengl()
3400         lock_window("BC_WindowBase::enable_opengl");
3401         opengl_lock.lock();
3403         XVisualInfo viproto;
3404         XVisualInfo *visinfo;
3405         int nvi;
3407         viproto.screen = top_level->screen;
3408         visinfo = XGetVisualInfo(top_level->display,
3409         VisualScreenMask,
3410         &viproto,
3411         &nvi);
3413         gl_context = glXCreateContext(top_level->display,
3414                 visinfo,
3415                 0,
3416                 1);
3418         glXMakeCurrent(top_level->display,
3419                 win,
3420                 gl_context);
3422 // Need expose events for 3D
3423         unsigned long valuemask = CWEventMask;
3424         XSetWindowAttributes attributes;
3425         attributes.event_mask = DEFAULT_EVENT_MASKS |
3426                         ExposureMask;
3427         XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3429         opengl_lock.unlock();
3430         unlock_window();
3433 void BC_WindowBase::disable_opengl()
3435         unsigned long valuemask = CWEventMask;
3436         XSetWindowAttributes attributes;
3437         attributes.event_mask = DEFAULT_EVENT_MASKS;
3438         XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
3441 void BC_WindowBase::lock_opengl()
3443         lock_window("BC_WindowBase::lock_opengl");
3444         opengl_lock.lock();
3445         glXMakeCurrent(top_level->display,
3446                 win,
3447                 gl_context);
3450 void BC_WindowBase::unlock_opengl()
3452         opengl_lock.unlock();
3453         unlock_window();
3456 void BC_WindowBase::flip_opengl()
3458         glXSwapBuffers(top_level->display, win);
3460 #endif
3462 int BC_WindowBase::get_event_count()
3464         event_lock->lock("BC_WindowBase::get_event_count");
3465         int result = common_events.total;
3466         event_lock->unlock();
3467         return result;
3470 XEvent* BC_WindowBase::get_event()
3472         XEvent *result = 0;
3473         while(!done && !result)
3474         {
3475                 event_condition->lock("BC_WindowBase::get_event");
3476                 event_lock->lock("BC_WindowBase::get_event");
3478                 if(common_events.total && !done)
3479                 {
3480                         result = common_events.values[0];
3481                         common_events.remove_number(0);
3482                 }
3484                 event_lock->unlock();
3485         }
3486         return result;
3489 void BC_WindowBase::put_event(XEvent *event)
3491         event_lock->lock("BC_WindowBase::put_event");
3492         common_events.append(event);
3493         event_lock->unlock();
3494         event_condition->unlock();