r854: Merge 2.1:
[cinelerra_cv/ct.git] / guicast / bcwindowbase.C
blob50eb7923564f828f3123e46023d74bbb7ff14bc3
1 #include "bcbitmap.h"
2 #include "bcclipboard.h"
3 #include "bcdisplayinfo.h"
4 #include "bcmenubar.h"
5 #include "bcpixmap.h"
6 #include "bcpopup.h"
7 #include "bcpopupmenu.h"
8 #include "bcrepeater.h"
9 #include "bcresources.h"
10 #include "bcsignals.h"
11 #include "bcsubwindow.h"
12 #include "bcsynchronous.h"
13 #include "bctimer.h"
14 #include "bcwidgetgrid.h"
15 #include "bcwindowbase.h"
16 #include "bcwindowevents.h"
17 #include "colormodels.h"
18 #include "colors.h"
19 #include "condition.h"
20 #include "cursors.h"
21 #include "bchash.h"
22 #include "fonts.h"
23 #include "keys.h"
24 #include "language.h"
25 #include "mutex.h"
26 #include "sizes.h"
27 #include "vframe.h"
29 #ifdef HAVE_GL
30 #include <GL/gl.h>
31 #endif
32 #include <string.h>
33 #include <unistd.h>
35 #include <X11/extensions/Xvlib.h>
36 #include <X11/extensions/shape.h>
39 BC_ResizeCall::BC_ResizeCall(int w, int h)
41         this->w = w;
42         this->h = h;
55 BC_Resources BC_WindowBase::resources;
57 Window XGroupLeader = 0;
59 BC_WindowBase::BC_WindowBase()
61 //printf("BC_WindowBase::BC_WindowBase 1\n");
62         BC_WindowBase::initialize();
65 BC_WindowBase::~BC_WindowBase()
67 #ifdef HAVE_LIBXXF86VM
68    if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
69    {
70            restore_vm();   
71    }
72 #endif
74         hide_tooltip();
75         if(window_type != MAIN_WINDOW)
76         {
77                 if(top_level->active_menubar == this) top_level->active_menubar = 0;
78                 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
79                 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
80 // Remove pointer from parent window to this
81                 parent_window->subwindows->remove(this);
82         }
85 // Delete the subwindows
86         is_deleting = 1;
87         if(subwindows)
88         {
89                 while(subwindows->total)
90                 {
91 // Subwindow removes its own pointer
92                         delete subwindows->values[0];
93                 }
94                 delete subwindows;
95         }
97         if(widgetgrids)
98         {
99                 while (widgetgrids->total) 
100                 {
101                         delete widgetgrids->last();
102                         widgetgrids->remove();
103                 }
104                 delete widgetgrids;
105         }
106                 
108         delete pixmap;
110 // Destroyed in synchronous thread if gl context exists.
111 #ifdef HAVE_GL
112         if(!gl_win_context || !get_resources()->get_synchronous())
113 #endif
114                 XDestroyWindow(top_level->display, win);
116         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
117         if(icon_pixmap) delete icon_pixmap;
118         if(temp_bitmap) delete temp_bitmap;
124         if(window_type == MAIN_WINDOW) 
125         {
126                 XFreeGC(display, gc);
127 #ifdef HAVE_XFT
128                 if(largefont_xft) 
129                         XftFontClose (display, (XftFont*)largefont_xft);
130                 if(mediumfont_xft) 
131                         XftFontClose (display, (XftFont*)mediumfont_xft);
132                 if(smallfont_xft) 
133                         XftFontClose (display, (XftFont*)smallfont_xft);
134 #endif
135                 flush();
136 // Can't close display if another thread is waiting for events.
137 // Synchronous thread must delete display if gl_context exists.
138 #ifdef HAVE_GL
139                 if(!gl_win_context || !get_resources()->get_synchronous())
140 #endif
141                         XCloseDisplay(display);
142                 clipboard->stop_clipboard();
143                 delete clipboard;
144         }
145         else
146         {
147                 flush();
148         }
150 // Must be last reference to display.
151 // This only works if it's a MAIN_WINDOW since the display deletion for
152 // a subwindow is not determined by the subwindow.
153 #ifdef HAVE_GL
154         if(gl_win_context && get_resources()->get_synchronous())
155         {
156                 printf("BC_WindowBase::~BC_WindowBase window deleted but opengl deletion is not\n"
157                         "implemented for BC_Pixmap.\n");
158                 get_resources()->get_synchronous()->delete_window(this);
159         }
160 #endif
162         resize_history.remove_all_objects();
163         common_events.remove_all_objects();
164         delete event_lock;
165         delete event_condition;
167         UNSET_ALL_LOCKS(this)
170 int BC_WindowBase::initialize()
172         test_keypress = 0;
173         is_deleting = 0;
174         window_lock = 0;
175         x = 0; 
176         y = 0; 
177         w = 0; 
178         h = 0;
179         bg_color = -1;
180         top_level = 0;
181         parent_window = 0;
182         subwindows = 0;
183         widgetgrids = 0;
184         xvideo_port_id = -1;
185         video_on = 0;
186         motion_events = 0;
187         resize_events = 0;
188         translation_events = 0;
189         ctrl_mask = shift_mask = alt_mask = 0;
190         cursor_x = cursor_y = button_number = 0;
191         button_down = 0;
192         button_pressed = 0;
193         button_time1 = button_time2 = 0;
194         double_click = 0;
195         last_motion_win = 0;
196         key_pressed = 0;
197         active_menubar = 0;
198         active_popup_menu = 0;
199         active_subwindow = 0;
200         pixmap = 0;
201         bg_pixmap = 0;
202         tooltip_text[0] = 0;
203         persistant_tooltip = 0;
204 //      next_repeat_id = 0;
205         tooltip_popup = 0;
206         tooltip_done = 0;
207         current_font = MEDIUMFONT;
208         current_color = BLACK;
209         current_cursor = ARROW_CURSOR;
210         hourglass_total = 0;
211         is_dragging = 0;
212         shared_bg_pixmap = 0;
213         icon_pixmap = 0;
214         window_type = MAIN_WINDOW;
215         translation_count = 0;
216         x_correction = y_correction = 0;
217         temp_bitmap = 0;
218         tooltip_on = 0;
219         temp_cursor = 0;
220         toggle_value = 0;
221         toggle_drag = 0;
222         has_focus = 0;
223         is_hourglass = 0;
224         is_transparent = 0;
225 #ifdef HAVE_LIBXXF86VM
226     vm_switched = 0;
227 #endif
228         xft_drawable = 0;
229         largefont_xft = 0;
230         mediumfont_xft = 0;
231         smallfont_xft = 0;
232 // Need these right away since put_event is called before run_window sometimes.
233         event_lock = new Mutex("BC_WindowBase::event_lock");
234         event_condition = new Condition(0, "BC_WindowBase::event_condition");
235         cursor_timer = new Timer;
236         event_thread = 0;
237 #ifdef HAVE_GL
238         gl_win_context = 0;
239 #endif
241         return 0;
244 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
245                         LeaveWindowMask | \
246                         ButtonPressMask | \
247                         ButtonReleaseMask | \
248                         PointerMotionMask | \
249                         FocusChangeMask
250                         
252 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
253                                 char *title, 
254                                 int x,
255                                 int y,
256                                 int w, 
257                                 int h, 
258                                 int minw, 
259                                 int minh, 
260                                 int allow_resize,
261                                 int private_color, 
262                                 int hide,
263                                 int bg_color,
264                                 char *display_name,
265                                 int window_type,
266                                 BC_Pixmap *bg_pixmap,
267                                 int group_it)
269         XSetWindowAttributes attr;
270         unsigned long mask;
271         XSizeHints size_hints;
272         int root_w;
273         int root_h;
274 #ifdef HAVE_LIBXXF86VM
275     int vm;
276 #endif
278         id = get_resources()->get_id();
280     if(parent_window) top_level = parent_window->top_level;
282 #ifdef HAVE_LIBXXF86VM
283     if(window_type == VIDMODE_SCALED_WINDOW)
284             closest_vm(&vm,&w,&h);
285 #endif
287         this->x = x;
288         this->y = y;
289         this->w = w;
290         this->h = h;
291         this->bg_color = bg_color;
292         this->window_type = window_type;
293         this->hidden = hide;
294         this->private_color = private_color;
295         this->parent_window = parent_window;
296         this->bg_pixmap = bg_pixmap;
297         this->allow_resize = allow_resize;
298         strcpy(this->title, _(title));
299         if(bg_pixmap) shared_bg_pixmap = 1;
301         if(parent_window) top_level = parent_window->top_level;
303         subwindows = new BC_SubWindowList;
304         widgetgrids = new BC_WidgetGridList;
306 // Mandatory setup
307         if(window_type == MAIN_WINDOW)
308         {
309                 top_level = this;
310                 parent_window = this;
312 // This function must be the first Xlib
313 // function a multi-threaded program calls
314                 XInitThreads();
317 // get the display connection
318                 display = init_display(display_name);
319 //              event_display = init_display(display_name);
321 // Fudge window placement
322                 root_w = get_root_w(1, 0);
323                 root_h = get_root_h(0);
324                 if(this->x + this->w > root_w) this->x = root_w - this->w;
325                 if(this->y + this->h > root_h) this->y = root_h - this->h;
326                 if(this->x < 0) this->x = 0;
327                 if(this->y < 0) this->y = 0;
328                 screen = DefaultScreen(display);
329                 rootwin = RootWindow(display, screen);
332                 vis = DefaultVisual(display, screen);
333                 default_depth = DefaultDepth(display, screen);
335                 client_byte_order = (*(u_int32_t*)"a   ") & 0x00000001;
336                 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
339 // This must be done before fonts to know if antialiasing is available.
340                 init_colors();
341 // get the resources
342                 if(resources.use_shm < 0) resources.initialize_display(this);
343                 x_correction = get_resources()->get_left_border();
344                 y_correction = get_resources()->get_top_border();
346                 if(this->bg_color == -1)
347                         this->bg_color = resources.get_bg_color();
349 // printf("bcwindowbase 1 %s\n", title);
350 // if(window_type == MAIN_WINDOW) sleep(1);
351 // printf("bcwindowbase 10\n");
352                 init_fonts();
353                 init_gc();
354                 init_cursors();
356 // Create the window
357                 mask = CWEventMask | 
358                                 CWBackPixel | 
359                                 CWColormap | 
360                                 CWCursor;
362                 attr.event_mask = DEFAULT_EVENT_MASKS |
363                         StructureNotifyMask | 
364                         KeyPressMask;
366                 attr.background_pixel = get_color(this->bg_color);
367                 attr.colormap = cmap;
368                 attr.cursor = get_cursor_struct(ARROW_CURSOR);
370                 win = XCreateWindow(display, 
371                         rootwin, 
372                         this->x, 
373                         this->y, 
374                         this->w, 
375                         this->h, 
376                         0, 
377                         top_level->default_depth, 
378                         InputOutput, 
379                         vis, 
380                         mask, 
381                         &attr);
383                 XGetNormalHints(display, win, &size_hints);
385                 size_hints.flags = PSize | PMinSize | PMaxSize;
386                 size_hints.width = this->w;
387                 size_hints.height = this->h;
388                 size_hints.min_width = allow_resize ? minw : this->w;
389                 size_hints.max_width = allow_resize ? 32767 : this->w; 
390                 size_hints.min_height = allow_resize ? minh : this->h;
391                 size_hints.max_height = allow_resize ? 32767 : this->h; 
392                 if(x > -BC_INFINITY && x < BC_INFINITY)
393                 {
394                         size_hints.flags |= PPosition;
395                         size_hints.x = this->x;
396                         size_hints.y = this->y;
397                 }
399                 XSetStandardProperties(display, 
400                         win, 
401                         title, 
402                         title, 
403                         None, 
404                         0, 
405                         0, 
406                         &size_hints);
407                 get_atoms();
408                 
409                 clipboard = new BC_Clipboard(display_name);
410                 clipboard->start_clipboard();
412                 if (group_it)
413                 {
414                         Atom ClientLeaderXAtom;
415                         if (XGroupLeader == 0)
416                                 XGroupLeader = win;
417                         char *instance_name = "cinelerra";
418                         char *class_name = "Cinelerra";
419                         XClassHint *class_hints = XAllocClassHint(); 
420                         class_hints->res_name = instance_name;
421                         class_hints->res_class = class_name;
422                         XSetClassHint(top_level->display, win, class_hints);
423                         XFree(class_hints);
424                         ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
425                         XChangeProperty(display, 
426                                         win, 
427                                         ClientLeaderXAtom, 
428                                         XA_WINDOW, 
429                                         32, 
430                                         PropModeReplace, 
431                                         (unsigned char *)&XGroupLeader, 
432                                         true);
434                 }
435                 
436         }
438 #ifdef HAVE_LIBXXF86VM
439     if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
440     {
441             scale_vm (vm);
442             vm_switched = 1;
443     }
444 #endif
446 #ifdef HAVE_LIBXXF86VM
447     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
448 #else
449     if(window_type == POPUP_WINDOW)
450 #endif
451         {
452                 mask = CWEventMask | 
453                         CWBackPixel | 
454                         CWColormap | 
455                         CWOverrideRedirect | 
456                         CWSaveUnder | 
457                         CWCursor;
459                 attr.event_mask = DEFAULT_EVENT_MASKS |
460                         KeyPressMask;
462                 if(this->bg_color == -1)
463                         this->bg_color = resources.get_bg_color();
464                 attr.background_pixel = top_level->get_color(bg_color);
465                 attr.colormap = top_level->cmap;
466                 if(top_level->is_hourglass)
467                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
468                 else
469                         attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
470                 attr.override_redirect = True;
471                 attr.save_under = True;
473                 win = XCreateWindow(top_level->display, 
474                         top_level->rootwin, 
475                         this->x, 
476                         this->y, 
477                         this->w, 
478                         this->h, 
479                         0, 
480                         top_level->default_depth, 
481                         InputOutput, 
482                         top_level->vis, 
483                         mask, 
484                         &attr);
485         }
487         if(window_type == SUB_WINDOW)
488         {
489                 mask = CWBackPixel | 
490                         CWEventMask | 
491                         CWCursor;
492                 attr.event_mask = DEFAULT_EVENT_MASKS;
493                 attr.background_pixel = top_level->get_color(this->bg_color);
494                 if(top_level->is_hourglass)
495                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
496                 else
497                         attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
498                 win = XCreateWindow(top_level->display, 
499                         parent_window->win, 
500                         this->x, 
501                         this->y, 
502                         this->w, 
503                         this->h, 
504                         0, 
505                         top_level->default_depth, 
506                         InputOutput, 
507                         top_level->vis, 
508                         mask, 
509                         &attr);
510                 init_window_shape();
511                 XMapWindow(top_level->display, win);
512         }
514 // Create pixmap for all windows
515         pixmap = new BC_Pixmap(this, this->w, this->h);
518 // Create truetype rendering surface
519 #ifdef HAVE_XFT
520         if(get_resources()->use_xft)
521         {
522 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n", 
523 // top_level->display,
524 // pixmap,
525 // top_level->vis,
526 // top_level->cmap);
527                 xft_drawable = XftDrawCreate(top_level->display,
528                        pixmap,
529                        top_level->vis,
530                        top_level->cmap);
531 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n", 
532 // xft_drawable, 
533 // top_level->display,
534 // pixmap,
535 // top_level->vis,
536 // top_level->cmap);
537         }
538 #endif
540 // Set up options for main window
541         if(window_type == MAIN_WINDOW)
542         {
543                 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
544                 {
545                         this->bg_pixmap = new BC_Pixmap(this, 
546                                 get_resources()->bg_image, 
547                                 PIXMAP_OPAQUE);
548                 }
550                 if(!hidden) show_window();
552         }
557         draw_background(0, 0, this->w, this->h);
558         flash();
560 // Set up options for popup window
561 #ifdef HAVE_LIBXXF86VM
562     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
563 #else
564     if(window_type == POPUP_WINDOW)
565 #endif
566         {
567                 init_window_shape();
568                 if(!hidden) show_window();
569         }
570         return 0;
573 Display* BC_WindowBase::init_display(char *display_name)
575         Display* display;
577         if(display_name && display_name[0] == 0) display_name = NULL;
578         if((display = XOpenDisplay(display_name)) == NULL)
579         {
580                 printf("BC_WindowBase::init_display: cannot connect to X server %s\n", 
581                         display_name);
582                 if(getenv("DISPLAY") == NULL)
583         {
584                         printf("'DISPLAY' environment variable not set.\n");
585                         exit(1);
586                 }
587                 else
588 // Try again with default display.
589                 {
590                         if((display = XOpenDisplay(0)) == NULL)
591                         {
592                                 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
593                                 exit(1);
594                         }
595                 }
596         }
597         return display;
600 Display* BC_WindowBase::get_display()
602         return top_level->display;
605 int BC_WindowBase::get_screen()
607         return top_level->screen;
610 int BC_WindowBase::run_window()
612         done = 0;
613         return_value = 0;
616 // Events may have been sent before run_window so can't initialize them here.
618 // Start tooltips
619         if(window_type == MAIN_WINDOW)
620         {
621 //              tooltip_id = get_repeat_id();
622                 set_repeat(get_resources()->tooltip_delay);
623         }
625 // Start X server events
626         event_thread = new BC_WindowEvents(this);
627         event_thread->start();
629 // Start common events
630         while(!done)
631         {
632                 dispatch_event();
633         }
635         unset_all_repeaters();
636         hide_tooltip();
637         delete event_thread;
638         event_thread = 0;
639         event_condition->reset();
640         common_events.remove_all_objects();
641         done = 0;
643         return return_value;
646 int BC_WindowBase::get_key_masks(XEvent *event)
648 // printf("BC_WindowBase::get_key_masks %llx\n", 
649 // event->xkey.state);
650 // ctrl key down
651         ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
652 // shift key down
653         shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
654         alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
655         return 0;
664 int BC_WindowBase::dispatch_event()
666         XEvent *event = 0;
667     Window tempwin;
668         KeySym keysym;
669         char keys_return[2];
670         int result;
671         XClientMessageEvent *ptr;
672         int temp;
673         int cancel_resize, cancel_translation;
675         key_pressed = 0;
677 // If an event is waiting get it, otherwise
678 // wait for next event only if there are no compressed events.
679         if(get_event_count() || 
680                 (!motion_events && !resize_events && !translation_events))
681         {
682 //              XNextEvent(display, event);
683                 event = get_event();
684 // Lock out window deletions
685                 lock_window("BC_WindowBase::dispatch_event 1");
686 //              get_key_masks(event);
687         }
688         else
689 // Handle compressed events
690         {
691                 lock_window("BC_WindowBase::dispatch_event 2");
692                 if(resize_events)
693                         dispatch_resize_event(last_resize_w, last_resize_h);
694                 else
695                 if(motion_events)
696                         dispatch_motion_event();
697                 else
698                 if(translation_events)
699                         dispatch_translation_event();
701                 unlock_window();
702                 return 0;
703         }
705 //printf("1 %s %p %d\n", title, event, event->type);
706         switch(event->type)
707         {
708                 case ClientMessage:
709                         get_key_masks(event);
710 // Clear the resize buffer
711                         if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
712 // Clear the motion buffer since this can clear the window
713                         if(motion_events)
714                         {
715                                 dispatch_motion_event();
716                         }
718                         ptr = (XClientMessageEvent*)event;
721                 if(ptr->message_type == ProtoXAtom && 
722                                 ptr->data.l[0] == DelWinXAtom)
723                 {
724                                 close_event();
725                         }
726                         else
727                         if(ptr->message_type == RepeaterXAtom)
728                         {
729                                 dispatch_repeat_event(ptr->data.l[0]);
730 // Make sure the repeater still exists.
731 //                              for(int i = 0; i < repeaters.total; i++)
732 //                              {
733 //                                      if(repeaters.values[i]->repeat_id == ptr->data.l[0])
734 //                                      {
735 //                                              dispatch_repeat_event_master(ptr->data.l[0]);
736 //                                              break;
737 //                                      }
738 //                              }
739                         }
740                         else
741                         if(ptr->message_type == SetDoneXAtom)
742                         {
743                                 done = 1;
744                         }
745                         break;
747                 case FocusIn:
748                         has_focus = 1;
749                         dispatch_focus_in();
750                         break;
752                 case FocusOut:
753                         has_focus = 0;
754                         dispatch_focus_out();
755                         break;
757 // Maximized
758                 case MapNotify:
759                         break;
761 // Minimized
762                 case UnmapNotify:
763                         break;
765                 case ButtonPress:
766                         get_key_masks(event);
767                         cursor_x = event->xbutton.x;
768                         cursor_y = event->xbutton.y;
769                         button_number = event->xbutton.button;
770                         event_win = event->xany.window;
771                         if (button_number != 4 && button_number != 5)
772                                 button_down = 1;
773                         button_pressed = event->xbutton.button;
774                         button_time1 = button_time2;
775                         button_time2 = event->xbutton.time;
776                         drag_x = cursor_x;
777                         drag_y = cursor_y;
778                         drag_win = event_win;
779                         drag_x1 = cursor_x - get_resources()->drag_radius;
780                         drag_x2 = cursor_x + get_resources()->drag_radius;
781                         drag_y1 = cursor_y - get_resources()->drag_radius;
782                         drag_y2 = cursor_y + get_resources()->drag_radius;
784                         if(button_time2 - button_time1 < resources.double_click)
785                         {
786 // Ignore triple clicks
787                                 double_click = 1; 
788                                 button_time2 = button_time1 = 0; 
789                         }
790                         else 
791                                 double_click = 0;
793                         dispatch_button_press();
794                         break;
796                 case ButtonRelease:
797                         get_key_masks(event);
798                         button_number = event->xbutton.button;
799                         event_win = event->xany.window;
800                         if (button_number != 4 && button_number != 5) 
801                                 button_down = 0;
803                         dispatch_button_release();
805                         break;
807                 case Expose:
808                         event_win = event->xany.window;
809                         dispatch_expose_event();
810                         break;
812                 case MotionNotify:
813                         get_key_masks(event);
814 // Dispatch previous motion event if this is a subsequent motion from a different window
815                         if(motion_events && last_motion_win != event->xany.window)
816                         {
817                                 dispatch_motion_event();
818                         }
820 // Buffer the current motion
821                         motion_events = 1;
822                         last_motion_x = event->xmotion.x;
823                         last_motion_y = event->xmotion.y;
824                         last_motion_win = event->xany.window;
825                         break;
827                 case ConfigureNotify:
828                         get_key_masks(event);
829                         XTranslateCoordinates(top_level->display, 
830                                 top_level->win, 
831                                 top_level->rootwin, 
832                                 0, 
833                                 0, 
834                                 &last_translate_x, 
835                                 &last_translate_y, 
836                                 &tempwin);
837                         last_resize_w = event->xconfigure.width;
838                         last_resize_h = event->xconfigure.height;
840                         cancel_resize = 0;
841                         cancel_translation = 0;
843 // Resize history prevents responses to recursive resize requests
844                         for(int i = 0; i < resize_history.total && !cancel_resize; i++)
845                         {
846                                 if(resize_history.values[i]->w == last_resize_w &&
847                                         resize_history.values[i]->h == last_resize_h)
848                                 {
849                                         delete resize_history.values[i];
850                                         resize_history.remove_number(i);
851                                         cancel_resize = 1;
852                                 }
853                         }
855                         if(last_resize_w == w && last_resize_h == h)
856                                 cancel_resize = 1;
858                         if(!cancel_resize)
859                         {
860                                 resize_events = 1;
861                         }
863                         if((last_translate_x == x && last_translate_y == y))
864                                 cancel_translation = 1;
866                         if(!cancel_translation)
867                         {
868                                 translation_events = 1;
869                         }
871                         translation_count++;
872                         break;
874                 case KeyPress:
875                         get_key_masks(event);
876                         keys_return[0] = 0;
877                         XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
879 // printf("BC_WindowBase::dispatch_event 2 %llx\n", 
880 // event->xkey.state);
881 // block out control keys
882                         if(keysym > 0xffe0 && keysym < 0xffff) break;
885                         if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
888                         switch(keysym)
889                         {
890 // block out extra keys
891                         case XK_Alt_L:      
892                         case XK_Alt_R:      
893                         case XK_Shift_L:    
894                         case XK_Shift_R:    
895                         case XK_Control_L:  
896                         case XK_Control_R:  
897                                         key_pressed = 0;         
898                                         break;
900 // Translate key codes
901                                 case XK_Return:     key_pressed = RETURN;    break;
902                         case XK_Up:         key_pressed = UP;        break;
903                                 case XK_Down:       key_pressed = DOWN;      break;
904                                 case XK_Left:       key_pressed = LEFT;      break;
905                         case XK_Right:      key_pressed = RIGHT;     break;
906                         case XK_Next:       key_pressed = PGDN;      break;
907                         case XK_Prior:      key_pressed = PGUP;      break;
908                         case XK_BackSpace:  key_pressed = BACKSPACE; break;
909                         case XK_Escape:     key_pressed = ESC;       break;
910                         case XK_Tab:
911                                         if(shift_down())
912                                                 key_pressed = LEFTTAB;
913                                         else
914                                                 key_pressed = TAB;       
915                                         break;
916                                 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
917                                 case XK_underscore: key_pressed = '_';       break;
918                         case XK_asciitilde: key_pressed = '~';       break;
919                                 case XK_Delete:     key_pressed = DELETE;    break;
920                                 case XK_Home:       key_pressed = HOME;      break;
921                                 case XK_End:        key_pressed = END;       break;
923 // number pad
924                                 case XK_KP_Enter:       key_pressed = KPENTER;   break;
925                                 case XK_KP_Add:         key_pressed = KPPLUS;    break;
926                                 case XK_KP_1:
927                                 case XK_KP_End:         key_pressed = KP1;       break;
928                                 case XK_KP_2:
929                                 case XK_KP_Down:        key_pressed = KP2;       break;
930                                 case XK_KP_3:
931                                 case XK_KP_Page_Down:   key_pressed = KP3;       break;
932                                 case XK_KP_4:
933                                 case XK_KP_Left:        key_pressed = KP4;       break;
934                                 case XK_KP_5:
935                                 case XK_KP_Begin:       key_pressed = KP5;       break;
936                                 case XK_KP_6:
937                                 case XK_KP_Right:       key_pressed = KP6;       break;
938                                 case XK_KP_0:
939                                 case XK_KP_Insert:      key_pressed = KPINS;     break;
940                                 case XK_KP_Decimal:
941                                 case XK_KP_Delete:      key_pressed = KPDEL;     break;
942                         default:           
943                                         //key_pressed = keys_return[0]; 
944                                         key_pressed = keysym & 0xff;
945                                         break;
946                         }
948 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
949                         result = dispatch_keypress_event();
950 // Handle some default keypresses
951                         if(!result)
952                         {
953                                 if(key_pressed == 'w' ||
954                                         key_pressed == 'W')
955                                 {
956                                         close_event();
957                                 }
958                         }
959                         break;
961                 case LeaveNotify:
962                         event_win = event->xany.window;
963                         dispatch_cursor_leave();
964                         break;
966                 case EnterNotify:
967                         event_win = event->xany.window;
968                         cursor_x = event->xcrossing.x;
969                         cursor_y = event->xcrossing.y;
970                         dispatch_cursor_enter();
971                         break;
972         }
973 //printf("100 %s %p %d\n", title, event, event->type);
975         unlock_window();
976         if(event) delete event;
977         return 0;
980 int BC_WindowBase::dispatch_expose_event()
982         int result = 0;
983         for(int i = 0; i < subwindows->total && !result; i++)
984         {
985                 result = subwindows->values[i]->dispatch_expose_event();
986         }
988 // Propagate to user
989         if(!result) expose_event();
990         return result;
993 int BC_WindowBase::dispatch_resize_event(int w, int h)
995 // Can't store new w and h until the event is handles 
996 // because bcfilebox depends on the old w and h to
997 // reposition widgets.
998         if(window_type == MAIN_WINDOW)
999         {
1000                 resize_events = 0;
1001                 delete pixmap;
1002                 pixmap = new BC_Pixmap(this, w, h);
1004                 clear_box(0, 0, w, h);
1005         }
1007 // Propagate to subwindows
1008         for(int i = 0; i < subwindows->total; i++)
1009         {
1010                 subwindows->values[i]->dispatch_resize_event(w, h);
1011         }
1013 // Propagate to user
1014         resize_event(w, h);
1016         if(window_type == MAIN_WINDOW)
1017         {
1018                 this->w = w;
1019                 this->h = h;
1020         }
1021         return 0;
1024 int BC_WindowBase::dispatch_translation_event()
1026         translation_events = 0;
1027         if(window_type == MAIN_WINDOW)
1028         {
1029                 prev_x = x;
1030                 prev_y = y;
1031                 x = last_translate_x;
1032                 y = last_translate_y;
1033 // Correct for window manager offsets
1034                 x -= x_correction;
1035                 y -= y_correction;
1036         }
1038         for(int i = 0; i < subwindows->total; i++)
1039         {
1040                 subwindows->values[i]->dispatch_translation_event();
1041         }
1043         translation_event();
1044         return 0;
1047 int BC_WindowBase::dispatch_motion_event()
1049         int result = 0;
1050         unhide_cursor();
1052         if(top_level == this)
1053         {
1054                 event_win = last_motion_win;
1055                 motion_events = 0;
1057 // Test for grab
1058                 if(get_button_down() && !active_menubar && !active_popup_menu)
1059                 {
1060                         if(!result)
1061                         {
1062                                 cursor_x = last_motion_x;
1063                                 cursor_y = last_motion_y;
1064                                 result = dispatch_drag_motion();
1065                         }
1067                         if(!result && 
1068                                 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 || 
1069                                 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1070                         {
1071                                 cursor_x = drag_x;
1072                                 cursor_y = drag_y;
1074                                 result = dispatch_drag_start();
1075                         }
1076                 }
1077                 cursor_x = last_motion_x;
1078                 cursor_y = last_motion_y;
1080                 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1081                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1082                 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1083         }
1085         for(int i = 0; i < subwindows->total && !result; i++)
1086         {
1087                 result = subwindows->values[i]->dispatch_motion_event();
1088         }
1091         if(!result) result = cursor_motion_event();    // give to user
1092         return result;
1095 int BC_WindowBase::dispatch_keypress_event()
1097         int result = 0;
1098         if(top_level == this)
1099         {
1100                 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1101         }
1103         for(int i = 0; i < subwindows->total && !result; i++)
1104         {
1105                 result = subwindows->values[i]->dispatch_keypress_event();
1106         }
1108         if(!result) result = keypress_event();
1110         return result;
1113 int BC_WindowBase::dispatch_focus_in()
1115         for(int i = 0; i < subwindows->total; i++)
1116         {
1117                 subwindows->values[i]->dispatch_focus_in();
1118         }
1120         focus_in_event();
1122         return 0;
1125 int BC_WindowBase::dispatch_focus_out()
1127         for(int i = 0; i < subwindows->total; i++)
1128         {
1129                 subwindows->values[i]->dispatch_focus_out();
1130         }
1132         focus_out_event();
1134         return 0;
1137 int BC_WindowBase::get_has_focus()
1139         return top_level->has_focus;
1142 int BC_WindowBase::get_deleting()
1144         if(is_deleting) return 1;
1145         if(parent_window && parent_window->get_deleting()) return 1;
1146         return 0;
1149 int BC_WindowBase::dispatch_button_press()
1151         int result = 0;
1152         if(top_level == this)
1153         {
1154                 if(active_menubar) result = active_menubar->dispatch_button_press();
1155                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1156                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1157         }
1159         for(int i = 0; i < subwindows->total && !result; i++)
1160         {
1161                 result = subwindows->values[i]->dispatch_button_press();
1162         }
1164         if(!result) result = button_press_event();
1166         return result;
1169 int BC_WindowBase::dispatch_button_release()
1171         int result = 0;
1172         if(top_level == this)
1173         {
1174                 if(active_menubar) result = active_menubar->dispatch_button_release();
1175                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1176                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1177                 if(!result && button_number != 4 && button_number != 5)
1178                         result = dispatch_drag_stop();
1179         }
1181         for(int i = 0; i < subwindows->total && !result; i++)
1182         {
1183                 result = subwindows->values[i]->dispatch_button_release();
1184         }
1186         if(!result)
1187         {
1188                 result = button_release_event();
1189         }
1191         return result;
1195 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1198 // all repeat event handlers get called and decide based on activity and duration
1199 // whether to respond
1200         for(int i = 0; i < subwindows->total; i++)
1201         {
1202                 subwindows->values[i]->dispatch_repeat_event(duration);
1203         }
1206         repeat_event(duration);
1210 // Unlock next repeat signal
1211         if(window_type == MAIN_WINDOW)
1212         {
1213                 for(int i = 0; i < repeaters.total; i++)
1214                 {
1215                         if(repeaters.values[i]->delay == duration)
1216                         {
1217                                 repeaters.values[i]->repeat_lock->unlock();
1218                         }
1219                 }
1220         }
1222         return 0;
1225 void BC_WindowBase::unhide_cursor()
1227         if(is_transparent)
1228         {
1229                 is_transparent = 0;
1230                 if(top_level->is_hourglass)
1231                         set_cursor(HOURGLASS_CURSOR, 1);
1232                 else
1233                         set_cursor(current_cursor, 1);
1234         }
1235         cursor_timer->update();
1239 void BC_WindowBase::update_video_cursor()
1241         if(video_on && !is_transparent)
1242         {
1243                 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1244                 {
1245                         is_transparent = 1;
1246                         set_cursor(TRANSPARENT_CURSOR, 1);
1247                         cursor_timer->update();
1248                 }
1249         }
1250         else
1251         {
1252                 cursor_timer->update();
1253         }
1257 int BC_WindowBase::dispatch_cursor_leave()
1259         unhide_cursor();
1261         for(int i = 0; i < subwindows->total; i++)
1262         {
1263                 subwindows->values[i]->dispatch_cursor_leave();
1264         }
1266         cursor_leave_event();
1267         return 0;
1270 int BC_WindowBase::dispatch_cursor_enter()
1272         int result = 0;
1274         unhide_cursor();
1276         if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1277         if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1278         if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1280         for(int i = 0; !result && i < subwindows->total; i++)
1281         {
1282                 result = subwindows->values[i]->dispatch_cursor_enter();
1283         }
1285         if(!result) result = cursor_enter_event();
1286         return result;
1289 int BC_WindowBase::cursor_enter_event()
1291         return 0;
1294 int BC_WindowBase::cursor_leave_event()
1296         return 0;
1299 int BC_WindowBase::close_event()
1301         set_done(1);
1302         return 1;
1305 int BC_WindowBase::dispatch_drag_start()
1307         int result = 0;
1308         if(active_menubar) result = active_menubar->dispatch_drag_start();
1309         if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1310         if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1311         
1312         for(int i = 0; i < subwindows->total && !result; i++)
1313         {
1314                 result = subwindows->values[i]->dispatch_drag_start();
1315         }
1317         if(!result) result = is_dragging = drag_start_event();
1318         return result;
1321 int BC_WindowBase::dispatch_drag_stop()
1323         int result = 0;
1325         for(int i = 0; i < subwindows->total && !result; i++)
1326         {
1327                 result = subwindows->values[i]->dispatch_drag_stop();
1328         }
1330         if(is_dragging && !result) 
1331         {
1332                 drag_stop_event();
1333                 is_dragging = 0;
1334                 result = 1;
1335         }
1337         return result;
1340 int BC_WindowBase::dispatch_drag_motion()
1342         int result = 0;
1343         for(int i = 0; i < subwindows->total && !result; i++)
1344         {
1345                 result = subwindows->values[i]->dispatch_drag_motion();
1346         }
1347         
1348         if(is_dragging && !result)
1349         {
1350                 drag_motion_event();
1351                 result = 1;
1352         }
1353         
1354         return result;
1361 int BC_WindowBase::show_tooltip(int w, int h)
1363         Window tempwin;
1365         if(!tooltip_on && get_resources()->tooltips_enabled)
1366         {
1367                 int i, j, x, y;
1368                 top_level->hide_tooltip();
1370                 tooltip_on = 1;
1371                 if(w < 0)
1372                         w = get_text_width(MEDIUMFONT, tooltip_text);
1374                 if(h < 0)
1375                         h = get_text_height(MEDIUMFONT, tooltip_text);
1377                 w += TOOLTIP_MARGIN * 2;
1378                 h += TOOLTIP_MARGIN * 2;
1380                 XTranslateCoordinates(top_level->display, 
1381                                 win, 
1382                                 top_level->rootwin, 
1383                                 get_w(), 
1384                                 get_h(), 
1385                                 &x, 
1386                                 &y, 
1387                                 &tempwin);
1388                 tooltip_popup = new BC_Popup(top_level, 
1389                                         x,
1390                                         y,
1391                                         w, 
1392                                         h, 
1393                                         get_resources()->tooltip_bg_color);
1395                 draw_tooltip();
1396                 tooltip_popup->set_font(MEDIUMFONT);
1397                 tooltip_popup->flash();
1398                 tooltip_popup->flush();
1399         }
1400         return 0;
1403 int BC_WindowBase::hide_tooltip()
1405         if(subwindows)
1406                 for(int i = 0; i < subwindows->total; i++)
1407                 {
1408                         subwindows->values[i]->hide_tooltip();
1409                 }
1411         if(tooltip_on)
1412         {
1413                 tooltip_on = 0;
1414                 delete tooltip_popup;
1415                 tooltip_popup = 0;
1416         }
1417         return 0;
1420 int BC_WindowBase::set_tooltip(char *text)
1422         strcpy(this->tooltip_text, text);
1423 // Update existing tooltip if it is visible
1424         if(tooltip_on)
1425         {
1426                 draw_tooltip();
1427                 tooltip_popup->flash();
1428         }
1429         return 0;
1432 // signal the event handler to repeat
1433 int BC_WindowBase::set_repeat(int64_t duration)
1435         if(duration <= 0)
1436         {
1437                 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
1438                 return 0;
1439         }
1440         if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1442 // test repeater database for duplicates
1443         for(int i = 0; i < repeaters.total; i++)
1444         {
1445 // Already exists
1446                 if(repeaters.values[i]->delay == duration)
1447                 {
1448                         repeaters.values[i]->start_repeating();
1449                         return 0;
1450                 }
1451         }
1453         BC_Repeater *repeater = new BC_Repeater(this, duration);
1454         repeater->initialize();
1455         repeaters.append(repeater);
1456     repeater->start_repeating();
1457         return 0;
1460 int BC_WindowBase::unset_repeat(int64_t duration)
1462         if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1464         BC_Repeater *repeater = 0;
1465         for(int i = 0; i < repeaters.total; i++)
1466         {
1467                 if(repeaters.values[i]->delay == duration)
1468                 {
1469                         repeaters.values[i]->stop_repeating();
1470                 }
1471         }
1472         return 0;
1476 int BC_WindowBase::unset_all_repeaters()
1478         for(int i = 0; i < repeaters.total; i++)
1479         {
1480                 repeaters.values[i]->stop_repeating();
1481         }
1482         repeaters.remove_all_objects();
1483         return 0;
1486 // long BC_WindowBase::get_repeat_id()
1487 // {
1488 //      return top_level->next_repeat_id++;
1489 // }
1491 int BC_WindowBase::arm_repeat(int64_t duration)
1493         XEvent *event = new XEvent;
1494         XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1495         ptr->type = ClientMessage;
1496         ptr->message_type = RepeaterXAtom;
1497         ptr->format = 32;
1498         ptr->data.l[0] = duration;
1500 // Couldn't use XSendEvent since it locked up randomly.
1501         put_event(event);
1502 //      XSendEvent(top_level->event_display, 
1503 //              top_level->win, 
1504 //              0, 
1505 //              0, 
1506 //              event);
1507 //      flush();
1508         return 0;
1511 int BC_WindowBase::get_atoms()
1513         SetDoneXAtom =  XInternAtom(display, "BC_REPEAT_EVENT", False);
1514         RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
1515         DelWinXAtom =   XInternAtom(display, "WM_DELETE_WINDOW", False);
1516         if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
1517                 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
1518         return 0;
1521 void BC_WindowBase::init_cursors()
1523         arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
1524         cross_cursor = XCreateFontCursor(display, XC_crosshair);
1525         ibeam_cursor = XCreateFontCursor(display, XC_xterm);
1526         vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
1527         hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
1528         move_cursor = XCreateFontCursor(display, XC_fleur);
1529         left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
1530         right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
1531         upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
1532         upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
1533         upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
1534         downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
1535         downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
1536         hourglass_cursor = XCreateFontCursor(display, XC_watch);
1539         char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
1540         Colormap colormap = DefaultColormap(display, screen);
1541         Pixmap pixmap_bottom = XCreateBitmapFromData(display, 
1542                 rootwin,
1543                 cursor_data, 
1544                 8,
1545                 8);
1546         XColor black, dummy;
1547     XAllocNamedColor(display, colormap, "black", &black, &dummy);
1548         transparent_cursor = XCreatePixmapCursor(display,
1549                 pixmap_bottom,
1550                 pixmap_bottom,
1551                 &black,
1552                 &black,
1553                 0,
1554                 0);
1555 //      XDefineCursor(display, win, transparent_cursor);
1556         XFreePixmap(display, pixmap_bottom);
1559 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
1561         int color_model;
1562         switch(depth)
1563         {
1564                 case 8:
1565                         color_model = BC_RGB8;
1566                         break;
1567                 case 16:
1568                         color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
1569                         break;
1570                 case 24:
1571                         color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
1572                         break;
1573                 case 32:
1574                         color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
1575                         break;
1576         }
1577         return color_model;
1580 int BC_WindowBase::init_colors()
1582         total_colors = 0;
1583         current_color_value = current_color_pixel = 0;
1585 // Get the real depth
1586         char *data = 0;
1587         XImage *ximage;
1588         ximage = XCreateImage(top_level->display, 
1589                                         top_level->vis, 
1590                                         top_level->default_depth, 
1591                                         ZPixmap, 
1592                                         0, 
1593                                         data, 
1594                                         16, 
1595                                         16, 
1596                                         8, 
1597                                         0);
1598         bits_per_pixel = ximage->bits_per_pixel;
1599         XDestroyImage(ximage);
1601         color_model = evaluate_color_model(client_byte_order, 
1602                 server_byte_order, 
1603                 bits_per_pixel);
1604 // Get the color model
1605         switch(color_model)
1606         {
1607                 case BC_RGB8:
1608                         if(private_color)
1609                         {
1610                                 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
1611                                 create_private_colors();
1612                         }
1613                         else
1614                         {
1615                                 cmap = DefaultColormap(display, screen);
1616                                 create_shared_colors();
1617                         }
1619                         allocate_color_table();
1620 // No antialiasing
1621                         get_resources()->use_xft = 0;
1622                         break;
1624                 default:
1625                         cmap = DefaultColormap(display, screen);
1626                         break;
1627         }
1628         return 0;
1631 int BC_WindowBase::create_private_colors()
1633         int color;
1634         total_colors = 256;
1636         for(int i = 0; i < 255; i++)
1637         {
1638                 color = (i & 0xc0) << 16;
1639                 color += (i & 0x38) << 10;
1640                 color += (i & 0x7) << 5;
1641                 color_table[i][0] = color;
1642         }
1643         create_shared_colors();        // overwrite the necessary colors on the table
1644         return 0;
1648 int BC_WindowBase::create_color(int color)
1650         if(total_colors == 256)
1651         {
1652 // replace the closest match with an exact match
1653                 color_table[get_color_rgb8(color)][0] = color;
1654         }
1655         else
1656         {
1657 // add the color to the table
1658                 color_table[total_colors][0] = color;
1659                 total_colors++;
1660         }
1661         return 0;
1664 int BC_WindowBase::create_shared_colors()
1666         create_color(BLACK);
1667         create_color(WHITE);   
1669         create_color(LTGREY);  
1670         create_color(MEGREY);  
1671         create_color(MDGREY);  
1672         create_color(DKGREY);                           
1674         create_color(LTCYAN);  
1675         create_color(MECYAN);  
1676         create_color(MDCYAN);  
1677         create_color(DKCYAN);  
1679         create_color(LTGREEN); 
1680         create_color(GREEN);   
1681         create_color(DKGREEN); 
1683         create_color(LTPINK);  
1684         create_color(PINK);
1685         create_color(RED);     
1687         create_color(LTBLUE);  
1688         create_color(BLUE);    
1689         create_color(DKBLUE);  
1691         create_color(LTYELLOW); 
1692         create_color(MEYELLOW); 
1693         create_color(MDYELLOW); 
1694         create_color(DKYELLOW); 
1696         create_color(LTPURPLE); 
1697         create_color(MEPURPLE); 
1698         create_color(MDPURPLE); 
1699         create_color(DKPURPLE); 
1701         create_color(FGGREY); 
1702         create_color(MNBLUE);
1703         create_color(ORANGE);
1704         create_color(FTGREY);
1706         return 0;
1709 int BC_WindowBase::allocate_color_table()
1711         int red, green, blue, color;
1712         int result;
1713         XColor col;
1715         for(int i = 0; i < total_colors; i++)
1716         {
1717                 color = color_table[i][0];
1718                 red = (color & 0xFF0000) >> 16;
1719                 green = (color & 0x00FF00) >> 8;
1720                 blue = color & 0xFF;
1722                 col.flags = DoRed | DoGreen | DoBlue;
1723                 col.red   = red<<8   | red;
1724                 col.green = green<<8 | green;
1725                 col.blue  = blue<<8  | blue;
1727                 XAllocColor(display, cmap, &col);
1728                 color_table[i][1] = col.pixel;
1729         }
1731         XInstallColormap(display, cmap);
1732         return 0;
1735 int BC_WindowBase::init_window_shape()
1737         if(bg_pixmap && bg_pixmap->use_alpha()) 
1738         {
1739                 XShapeCombineMask(top_level->display,
1740                 this->win,
1741                 ShapeBounding,
1742                 0,
1743                 0,
1744                 bg_pixmap->get_alpha(),
1745                 ShapeSet);
1746         }
1747         return 0;
1751 int BC_WindowBase::init_gc()
1753         unsigned long gcmask;
1754         gcmask = GCFont | GCGraphicsExposures;
1756         XGCValues gcvalues;
1757         gcvalues.font = mediumfont->fid;        // set the font
1758         gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
1759         gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
1760         return 0;
1763 int BC_WindowBase::init_fonts()
1765         if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL)
1766                 if((largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL)
1767                         largefont = XLoadQueryFont(display, "fixed"); 
1769         if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL)
1770                 if((mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
1771                         mediumfont = XLoadQueryFont(display, "fixed"); 
1773         if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL)
1774                 if((smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
1775                         smallfont = XLoadQueryFont(display, "fixed");
1777 #ifdef HAVE_XFT
1778         if(get_resources()->use_xft)
1779         {
1782 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
1784                 if(!(largefont_xft = XftFontOpenXlfd(display,
1785                     screen,
1786                     resources.large_font_xft)))
1787                 {
1788                         largefont_xft = XftFontOpenXlfd(display,
1789                         screen,
1790                         "fixed");
1791                 }
1792 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
1793                 if(!(largefont_xft = XftFontOpenXlfd(display,
1794                     screen,
1795                     resources.large_font_xft)))
1796                 {
1797                         largefont_xft = XftFontOpenXlfd(display,
1798                         screen,
1799                         "fixed");
1800                 }
1801 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
1804                 if(!(mediumfont_xft = XftFontOpenXlfd(display,
1805                       screen,
1806                       resources.medium_font_xft)))
1807                 {
1808                         mediumfont_xft = XftFontOpenXlfd(display,
1809                         screen,
1810                         "fixed");
1811                 }
1814                 if(!(smallfont_xft = XftFontOpenXlfd(display,
1815                       screen,
1816                       resources.small_font_xft)))
1817                 {
1818                           smallfont_xft = XftFontOpenXlfd(display,
1819                           screen,
1820                           "fixed");
1821                 }
1823 //printf("BC_WindowBase::init_fonts 100 %s %p\n", 
1824 //resources.medium_font, 
1825 //mediumfont_xft);
1827 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
1828         resources.large_font_xft,
1829         largefontset,
1830         resources.medium_font_xft,
1831         mediumfontset,
1832         resources.small_font_xft,
1833         smallfontset);
1835 // Extension failed to locate fonts
1836                 if(!largefontset || !mediumfontset || !smallfontset)
1837                 {
1838                         printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
1839                                 resources.large_font_xft,
1840                                 largefontset,
1841                                 resources.medium_font_xft,
1842                                 mediumfontset,
1843                                 resources.small_font_xft,
1844                                 smallfontset);
1845                         get_resources()->use_xft = 0;
1846                 }
1847         }
1848         else
1849 #endif
1850         if(get_resources()->use_fontset)
1851         {
1852                 char **m, *d;
1853                 int n;
1855 // FIXME: should check the m,d,n values
1856                 if((largefontset = XCreateFontSet(display, 
1857                         resources.large_fontset,
1858             &m, 
1859                         &n, 
1860                         &d)) == 0)
1861             largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1862                 if((mediumfontset = XCreateFontSet(display, 
1863                         resources.medium_fontset,
1864             &m, 
1865                         &n, 
1866                         &d)) == 0)
1867             mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1868                 if((smallfontset = XCreateFontSet(display, 
1869                         resources.small_fontset,
1870             &m, 
1871                         &n, 
1872                         &d)) == 0)
1873             smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
1875                 if(largefontset && mediumfontset && smallfontset)
1876                 {
1877                         curr_fontset = mediumfontset;
1878                         get_resources()->use_fontset = 1;
1879                 }
1880                 else
1881                 {
1882                         curr_fontset = 0;
1883                         get_resources()->use_fontset = 0;
1884                 }
1885         }
1887         return 0;
1892 int BC_WindowBase::get_color(int64_t color) 
1894 // return pixel of color
1895 // use this only for drawing subwindows not for bitmaps
1896          int i, test, difference, result;
1898         switch(color_model)
1899         {
1900                 case BC_RGB8:
1901                         if(private_color)
1902                         {
1903                                 return get_color_rgb8(color);
1904                         }
1905                         else
1906                         {
1907 // test last color looked up
1908                                 if(current_color_value == color) return current_color_pixel;
1910 // look up in table
1911                                 current_color_value = color;
1912                                 for(i = 0; i < total_colors; i++)
1913                                 {
1914                                         if(color_table[i][0] == color)
1915                                         {
1916                                                 current_color_pixel = color_table[i][1];
1917                                                 return current_color_pixel;
1918                                         }
1919                                 }
1921 // find nearest match
1922                                 difference = 0xFFFFFF;
1924                                 for(i = 0, result = 0; i < total_colors; i++)
1925                                 {
1926                                         test = abs((int)(color_table[i][0] - color));
1928                                         if(test < difference) 
1929                                         {
1930                                                 current_color_pixel = color_table[i][1]; 
1931                                                 difference = test;
1932                                         }
1933                                 }
1935                                 return current_color_pixel;
1936                         }
1937                         break;  
1939                 case BC_RGB565:
1940                         return get_color_rgb16(color);
1941                         break;
1943                 case BC_BGR565:
1944                         return get_color_bgr16(color);
1945                         break;
1947                 case BC_RGB888:
1948                 case BC_BGR888:
1949                         if(client_byte_order == server_byte_order)
1950                                 return color;
1951                         else
1952                                 get_color_bgr24(color);
1953                         break;
1955                 default:
1956                         return color;
1957                         break;  
1958         }
1959         return 0;
1962 int BC_WindowBase::get_color_rgb8(int color)
1964         int pixel;
1966         pixel = (color & 0xc00000) >> 16;
1967         pixel += (color & 0xe000) >> 10;
1968         pixel += (color & 0xe0) >> 5;
1969         return pixel;
1972 int64_t BC_WindowBase::get_color_rgb16(int color)
1974         int64_t result;
1975         result = (color & 0xf80000) >> 8;
1976         result += (color & 0xfc00) >> 5;
1977         result += (color & 0xf8) >> 3;
1978         
1979         return result;
1982 int64_t BC_WindowBase::get_color_bgr16(int color)
1984         int64_t result;
1985         result = (color & 0xf80000) >> 19;
1986         result += (color & 0xfc00) >> 5;
1987         result += (color & 0xf8) << 8;
1989         return result;
1992 int64_t BC_WindowBase::get_color_bgr24(int color)
1994         int64_t result;
1995         result = (color & 0xff) << 16;
1996         result += (color & 0xff00);
1997         result += (color & 0xff0000) >> 16;
1998         return result;
2001 void BC_WindowBase::start_video()
2003         cursor_timer->update();
2004         video_on = 1;
2005 //      set_color(BLACK);
2006 //      draw_box(0, 0, get_w(), get_h());
2007 //      flash();
2010 void BC_WindowBase::stop_video()
2012         video_on = 0;
2013         unhide_cursor();
2018 int64_t BC_WindowBase::get_color()
2020         return top_level->current_color;
2023 void BC_WindowBase::set_color(int64_t color)
2025         top_level->current_color = color;
2026         XSetForeground(top_level->display, 
2027                 top_level->gc, 
2028                 top_level->get_color(color));
2031 void BC_WindowBase::set_opaque()
2033         XSetFunction(top_level->display, top_level->gc, GXcopy);
2036 void BC_WindowBase::set_inverse() 
2038         XSetFunction(top_level->display, top_level->gc, GXxor);
2041 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2043         switch(cursor)
2044         {
2045                 case ARROW_CURSOR:         return top_level->arrow_cursor;                 break;
2046                 case CROSS_CURSOR:         return top_level->cross_cursor;
2047                 case IBEAM_CURSOR:         return top_level->ibeam_cursor;                 break;
2048                 case VSEPARATE_CURSOR:     return top_level->vseparate_cursor;             break;
2049                 case HSEPARATE_CURSOR:     return top_level->hseparate_cursor;             break;
2050                 case MOVE_CURSOR:              return top_level->move_cursor;                  break;
2051                 case LEFT_CURSOR:          return top_level->left_cursor;                  break;
2052                 case RIGHT_CURSOR:         return top_level->right_cursor;                 break;
2053                 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;         break;
2054                 case UPLEFT_RESIZE:        return top_level->upleft_resize_cursor;         break;
2055                 case UPRIGHT_RESIZE:       return top_level->upright_resize_cursor;        break;
2056                 case DOWNLEFT_RESIZE:      return top_level->downleft_resize_cursor;       break;
2057                 case DOWNRIGHT_RESIZE:     return top_level->downright_resize_cursor;      break;
2058                 case HOURGLASS_CURSOR:     return top_level->hourglass_cursor;                 break;
2059                 case TRANSPARENT_CURSOR:   return top_level->transparent_cursor;               break;
2060         }
2061         return 0;
2064 void BC_WindowBase::set_cursor(int cursor, int override)
2066 // don't change cursor if overridden
2067         if((!top_level->is_hourglass && !is_transparent) || 
2068                 override)
2069         {
2070                 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2071                 flush();
2072         }
2074         if(!override) current_cursor = cursor;
2077 void BC_WindowBase::set_x_cursor(int cursor)
2079         temp_cursor = XCreateFontCursor(top_level->display, cursor);
2080         XDefineCursor(top_level->display, win, temp_cursor);
2081         current_cursor = cursor;
2082         flush();
2085 int BC_WindowBase::get_cursor()
2087         return current_cursor;
2090 void BC_WindowBase::start_hourglass()
2092         top_level->start_hourglass_recursive();
2093         top_level->flush();
2096 void BC_WindowBase::stop_hourglass()
2098         top_level->stop_hourglass_recursive();
2099         top_level->flush();
2102 void BC_WindowBase::start_hourglass_recursive()
2104         if(this == top_level)
2105         {
2106                 hourglass_total++;
2107                 is_hourglass = 1;
2108         }
2110         if(!is_transparent)
2111         {
2112                 set_cursor(HOURGLASS_CURSOR, 1);
2113                 for(int i = 0; i < subwindows->total; i++)
2114                 {
2115                         subwindows->values[i]->start_hourglass_recursive();
2116                 }
2117         }
2120 void BC_WindowBase::stop_hourglass_recursive()
2122         if(this == top_level)
2123         {
2124                 if(hourglass_total == 0) return;
2125                 top_level->hourglass_total--;
2126         }
2128         if(!top_level->hourglass_total)
2129         {
2130                 top_level->is_hourglass = 0;
2132 // Cause set_cursor to perform change
2133                 if(!is_transparent)
2134                         set_cursor(current_cursor, 1);
2136                 for(int i = 0; i < subwindows->total; i++)
2137                 {
2138                         subwindows->values[i]->stop_hourglass_recursive();
2139                 }
2140         }
2148 XFontStruct* BC_WindowBase::get_font_struct(int font)
2150 // Clear out unrelated flags
2151         if(font & BOLDFACE) font ^= BOLDFACE;
2152         
2153         switch(font)
2154         {
2155                 case MEDIUMFONT: return top_level->mediumfont; break;
2156                 case SMALLFONT:  return top_level->smallfont;  break;
2157                 case LARGEFONT:  return top_level->largefont;  break;
2158         }
2159         return 0;
2162 XFontSet BC_WindowBase::get_fontset(int font)
2164         XFontSet fs = 0;
2166         if(get_resources()->use_fontset)
2167         {
2168                 switch(font)
2169                 {
2170                         case SMALLFONT:  fs = top_level->smallfontset; break;
2171                         case LARGEFONT:  fs = top_level->largefontset; break;
2172                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2173                 }
2174         }
2176         return fs;
2179 #ifdef HAVE_XFT
2180 XftFont* BC_WindowBase::get_xft_struct(int font)
2182 // Clear out unrelated flags
2183         if(font & BOLDFACE) font ^= BOLDFACE;
2185         switch(font)
2186         {
2187                 case MEDIUMFONT:   return (XftFont*)top_level->mediumfont_xft; break;
2188                 case SMALLFONT:    return (XftFont*)top_level->smallfont_xft;  break;
2189                 case LARGEFONT:    return (XftFont*)top_level->largefont_xft;  break;
2190         }
2192         return 0;
2194 #endif
2206 void BC_WindowBase::set_font(int font)
2208         top_level->current_font = font;
2211 #ifdef HAVE_XFT
2212         if(get_resources()->use_xft)
2213         {
2214                 ;
2215         }
2216         else
2217 #endif
2218         if(get_resources()->use_fontset)
2219         {
2220                 set_fontset(font);
2221         }
2223         if(get_font_struct(font))
2224         {
2225                 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2226         }
2228         return;
2231 void BC_WindowBase::set_fontset(int font)
2233         XFontSet fs = 0;
2235         if(get_resources()->use_fontset)
2236         {
2237                 switch(font)
2238                 {
2239                         case SMALLFONT:  fs = top_level->smallfontset; break;
2240                         case LARGEFONT:  fs = top_level->largefontset; break;
2241                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
2242                 }
2243         }
2245         curr_fontset = fs;
2249 XFontSet BC_WindowBase::get_curr_fontset(void)
2251         if(get_resources()->use_fontset)
2252                 return curr_fontset;
2253         return 0;
2256 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
2258 #ifdef HAVE_XFT
2259         if(get_resources()->use_xft && get_xft_struct(font))
2260         {
2261                 XGlyphInfo extents;
2262                 XftTextExtents8(top_level->display,
2263                         get_xft_struct(font),
2264                         (FcChar8*)text, 
2265                         length,
2266                         &extents);
2267                 return extents.xOff;
2268         }
2269         else
2270 #endif
2271         if(get_resources()->use_fontset && top_level->get_fontset(font))
2272                 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2273         else
2274         if(get_font_struct(font)) 
2275                 return XTextWidth(get_font_struct(font), text, length);
2276         else
2277         {
2278                 int w = 0;
2279                 switch(font)
2280                 {
2281                         case MEDIUM_7SEGMENT:
2282                                 return get_resources()->medium_7segment[0]->get_w() * length;
2283                                 break;
2285                         default:
2286                                 return 0;
2287                 }
2288                 return w;
2289         }
2292 int BC_WindowBase::get_text_width(int font, char *text, int length)
2294         int i, j, w = 0, line_w = 0;
2295         if(length < 0) length = strlen(text);
2297         for(i = 0, j = 0; i <= length; i++)
2298         {
2299                 line_w = 0;
2300                 if(text[i] == '\n')
2301                 {
2302                         line_w = get_single_text_width(font, &text[j], i - j);
2303                         j = i + 1;
2304                 }
2305                 else
2306                 if(text[i] == 0)
2307                 {
2308                         line_w = get_single_text_width(font, &text[j], length - j);
2309                 }
2310                 if(line_w > w) w = line_w;
2311         }
2313         if(i > length && w == 0)
2314         {
2315                 w = get_single_text_width(font, text, length);
2316         }
2318         return w;
2321 int BC_WindowBase::get_text_ascent(int font)
2323 #ifdef HAVE_XFT
2324         if(get_resources()->use_xft && get_xft_struct(font))
2325         {
2326                 XGlyphInfo extents;
2327                 XftTextExtents8(top_level->display,
2328                         get_xft_struct(font),
2329                         (FcChar8*)"O", 
2330                         1,
2331                         &extents);
2332                 return extents.y + 2;
2333         }
2334         else
2335 #endif
2336         if(get_resources()->use_fontset && top_level->get_fontset(font))
2337         {
2338         XFontSetExtents *extents;
2340         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2341         return -extents->max_logical_extent.y;
2342         }
2343         else
2344         if(get_font_struct(font))
2345                 return top_level->get_font_struct(font)->ascent;
2346         else
2347         switch(font)
2348         {
2349                 case MEDIUM_7SEGMENT:
2350                         return get_resources()->medium_7segment[0]->get_h();
2351                         break;
2353                 default:
2354                         return 0;
2355         }
2358 int BC_WindowBase::get_text_descent(int font)
2360 #ifdef HAVE_XFT
2361         if(get_resources()->use_xft && get_xft_struct(font))
2362         {
2363                 XGlyphInfo extents;
2364                 XftTextExtents8(top_level->display,
2365                         get_xft_struct(font),
2366                         (FcChar8*)"j", 
2367                         1,
2368                         &extents);
2369                 return extents.height - extents.y;
2370         }
2371         else
2372 #endif
2373     if(get_resources()->use_fontset && top_level->get_fontset(font))
2374     {
2375         XFontSetExtents *extents;
2377         extents = XExtentsOfFontSet(top_level->get_fontset(font));
2378         return (extents->max_logical_extent.height
2379                         + extents->max_logical_extent.y);
2380     }
2381     else
2382         if(get_font_struct(font))
2383                 return top_level->get_font_struct(font)->descent;
2384         else
2385         switch(font)
2386         {
2387                 default:
2388                         return 0;
2389         }
2392 int BC_WindowBase::get_text_height(int font, char *text)
2394         if(!text) return get_text_ascent(font) + get_text_descent(font);
2396 // Add height of lines
2397         int h = 0, i, length = strlen(text);
2398         for(i = 0; i <= length; i++)
2399         {
2400                 if(text[i] == '\n')
2401                         h++;
2402                 else
2403                 if(text[i] == 0)
2404                         h++;
2405         }
2406         return h * (get_text_ascent(font) + get_text_descent(font));
2409 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
2411         if(color_model < 0) color_model = top_level->get_color_model();
2412         return new BC_Bitmap(top_level, w, h, color_model);
2415 int BC_WindowBase::accel_available(int color_model, int lock_it)
2417         if(window_type != MAIN_WINDOW) 
2418                 return top_level->accel_available(color_model, lock_it);
2420         int result = 0;
2422         if(lock_it) lock_window("BC_WindowBase::accel_available");
2423         switch(color_model)
2424         {
2425                 case BC_YUV420P:
2426                         result = grab_port_id(this, color_model);
2427                         if(result >= 0)
2428                         {
2429                                 xvideo_port_id = result;
2430                                 result = 1;
2431                         }
2432                         else
2433                                 result = 0;
2434                         break;
2436                 case BC_YUV422P:
2437                         result = 0;
2438                         break;
2440                 case BC_YUV422:
2441 //printf("BC_WindowBase::accel_available 1\n");
2442                         result = grab_port_id(this, color_model);
2443 //printf("BC_WindowBase::accel_available 2 %d\n", result);
2444                         if(result >= 0)
2445                         {
2446                                 xvideo_port_id = result;
2447                                 result = 1;
2448                         }
2449                         else
2450                                 result = 0;
2451 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
2452                         break;
2454                 default:
2455                         result = 0;
2456                         break;
2457         }
2459         if(lock_it) unlock_window();
2460 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
2461         return result;
2465 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
2467         int numFormats, i, j, k;
2468         unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
2469         int port_id = -1;
2470     XvAdaptorInfo *info;
2471     XvImageFormatValues *formats;
2472         int x_color_model;
2474         if(!get_resources()->use_xvideo) return -1;
2476 // Translate from color_model to X color model
2477         x_color_model = cmodel_bc_to_x(color_model);
2479 // Only local server is fast enough.
2480         if(!resources.use_shm) return -1;
2482 // XV extension is available
2483     if(Success != XvQueryExtension(window->display, 
2484                                   &ver, 
2485                                   &rev, 
2486                                   &reqBase, 
2487                                   &eventBase, 
2488                                   &errorBase))
2489     {
2490                 return -1;
2491     }
2493 // XV adaptors are available
2494         XvQueryAdaptors(window->display, 
2495                 DefaultRootWindow(window->display), 
2496                 &numAdapt, 
2497                 &info);
2499         if(!numAdapt)
2500         {
2501                 return -1;
2502         }
2504 // Get adaptor with desired color model
2505     for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
2506     {
2507 /* adaptor supports XvImages */
2508                 if(info[i].type & XvImageMask) 
2509                 {  
2510                 formats = XvListImageFormats(window->display, 
2511                                                         info[i].base_id, 
2512                                                         &numFormats);
2513 // for(j = 0; j < numFormats; j++)
2514 //      printf("%08x\n", formats[j].id);
2516                 for(j = 0; j < numFormats && xvideo_port_id < 0; j++) 
2517                 {
2518 /* this adaptor supports the desired format */
2519                                 if(formats[j].id == x_color_model)
2520                                 {
2521 /* Try to grab a port */
2522                                         for(k = 0; k < info[i].num_ports; k++)
2523                                         {
2524 /* Got a port */
2525                                                 if(Success == XvGrabPort(top_level->display, 
2526                                                         info[i].base_id + k, 
2527                                                         CurrentTime))
2528                                                 {
2529 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
2530                                                         xvideo_port_id = info[i].base_id + k;
2531                                                         break;
2532                                                 }
2533                                         }
2534                                 }
2535                         }
2536                 if(formats) XFree(formats);
2537                 }
2538         }
2540     XvFreeAdaptorInfo(info);
2542         return xvideo_port_id;
2546 int BC_WindowBase::show_window(int flush) 
2548         XMapWindow(top_level->display, win); 
2549         if(flush) XFlush(top_level->display);
2550 //      XSync(top_level->display, 0);
2551         hidden = 0; 
2552         return 0;
2555 int BC_WindowBase::hide_window(int flush) 
2557         XUnmapWindow(top_level->display, win); 
2558         if(flush) XFlush(top_level->display);
2559         hidden = 1; 
2560         return 0;
2563 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
2565         subwindows->append((BC_SubWindow*)menu_bar);
2567         menu_bar->parent_window = this;
2568         menu_bar->top_level = this->top_level;
2569         menu_bar->initialize();
2570         return menu_bar;
2573 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
2575         subwindows->append(subwindow);
2577         if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
2579 // parent window must be set before the subwindow initialization
2580         subwindow->parent_window = this;
2581         subwindow->top_level = this->top_level;
2583 // Execute derived initialization
2584         subwindow->initialize();
2585         return subwindow;
2589 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
2591         return add_subwindow(subwindow);
2594 BC_WidgetGrid* BC_WindowBase::add_widgetgrid(BC_WidgetGrid *widgetgrid)
2596         widgetgrids->append(widgetgrid);
2597         return widgetgrid;
2601 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
2603         set_opaque();
2604         XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
2605         if(x >= 0)
2606         {
2607                 XClearArea(top_level->display, win, x, y, w, h, 0);
2608         }
2609         else
2610         {
2611                 XClearWindow(top_level->display, win);
2612         }
2614         if(flush)
2615                 this->flush();
2616         return 0;
2619 int BC_WindowBase::flash(int flush)
2621         flash(-1, -1, -1, -1, flush);
2624 void BC_WindowBase::flush()
2626         XFlush(top_level->display);
2629 void BC_WindowBase::sync_display()
2631         XSync(top_level->display, False);
2634 int BC_WindowBase::get_window_lock()
2636         return top_level->window_lock;
2639 int BC_WindowBase::lock_window(char *location) 
2641         if(top_level && top_level != this)
2642         {
2643                 top_level->lock_window(location);
2644         }
2645         else
2646         if(top_level)
2647         {
2648                 SET_LOCK(this, title, location);
2649                 XLockDisplay(top_level->display);
2650                 SET_LOCK2
2651                 top_level->window_lock = 1;
2652         }
2653         else
2654         {
2655                 printf("BC_WindowBase::lock_window top_level NULL\n");
2656         }
2657         return 0;
2660 int BC_WindowBase::unlock_window() 
2662         if(top_level && top_level != this)
2663         {
2664                 top_level->unlock_window();
2665         }
2666         else
2667         if(top_level)
2668         {
2669                 UNSET_LOCK(this);
2670                 top_level->window_lock = 0;
2671                 XUnlockDisplay(top_level->display);
2672         }
2673         else
2674         {
2675                 printf("BC_WindowBase::unlock_window top_level NULL\n");
2676         }
2677         return 0;
2680 void BC_WindowBase::set_done(int return_value)
2682         if(window_type != MAIN_WINDOW)
2683                 top_level->set_done(return_value);
2684         else
2685         if(event_thread)
2686         {
2687                 XEvent *event = new XEvent;
2688                 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
2690                 event->type = ClientMessage;
2691                 ptr->message_type = SetDoneXAtom;
2692                 ptr->format = 32;
2693                 this->return_value = return_value;
2695 // May lock up here because XSendEvent doesn't work too well 
2696 // asynchronous with XNextEvent.
2697 // This causes BC_WindowEvents to forward a copy of the event to run_window where 
2698 // it is deleted.
2699                 event_thread->done = 1;
2700                 XSendEvent(display, 
2701                         win, 
2702                         0, 
2703                         0, 
2704                         event);
2705                 flush();
2706                 put_event(event);
2707         }
2710 int BC_WindowBase::get_w()
2712         return w;
2715 int BC_WindowBase::get_h()
2717         return h;
2720 int BC_WindowBase::get_x()
2722         return x;
2725 int BC_WindowBase::get_y()
2727         return y;
2730 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
2732         if(lock_display) lock_window("BC_WindowBase::get_root_w");
2733         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2734         int result = WidthOfScreen(screen_ptr);
2735 // Wider than 16:9, narrower than dual head
2736         if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
2738         if(lock_display) unlock_window();
2739         return result;
2742 int BC_WindowBase::get_root_h(int lock_display)
2744         if(lock_display) lock_window("BC_WindowBase::get_root_h");
2745         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
2746         int result = HeightOfScreen(screen_ptr);
2747         if(lock_display) unlock_window();
2748         return result;
2751 // Bottom right corner
2752 int BC_WindowBase::get_x2()
2754         return w + x;
2757 int BC_WindowBase::get_y2()
2759         return y + h;
2762 int BC_WindowBase::get_video_on()
2764         return video_on;
2767 int BC_WindowBase::get_hidden()
2769         return top_level->hidden;
2772 int BC_WindowBase::cursor_inside()
2774         return (top_level->cursor_x >= 0 && 
2775                         top_level->cursor_y >= 0 && 
2776                         top_level->cursor_x < w && 
2777                         top_level->cursor_y < h);
2780 BC_WindowBase* BC_WindowBase::get_top_level()
2782         return top_level;
2785 BC_WindowBase* BC_WindowBase::get_parent()
2787         return parent_window;
2790 int BC_WindowBase::get_color_model()
2792         return top_level->color_model;
2795 BC_Resources* BC_WindowBase::get_resources()
2797         return &BC_WindowBase::resources;
2800 BC_Synchronous* BC_WindowBase::get_synchronous()
2802         return BC_WindowBase::resources.get_synchronous();
2805 int BC_WindowBase::get_bg_color()
2807         return bg_color;
2810 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
2812         return bg_pixmap;
2815 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
2817         top_level->active_subwindow = subwindow;
2820 int BC_WindowBase::activate()
2822         return 0;
2825 int BC_WindowBase::deactivate()
2827         if(window_type == MAIN_WINDOW)
2828         {
2829                 if(top_level->active_menubar) top_level->active_menubar->deactivate();
2830                 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
2831                 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
2833                 top_level->active_menubar = 0;
2834                 top_level->active_popup_menu = 0;
2835                 top_level->active_subwindow = 0;
2836         }
2837         return 0;
2840 int BC_WindowBase::cycle_textboxes(int amount)
2842         int result = 0;
2843         BC_WindowBase *new_textbox = 0;
2845         if(amount > 0)
2846         {
2847                 BC_WindowBase *first_textbox = 0;
2848                 find_next_textbox(&first_textbox, &new_textbox, result);
2849                 if(!new_textbox) new_textbox = first_textbox;
2850                 
2851         }
2852         else
2853         if(amount < 0)
2854         {
2855                 BC_WindowBase *last_textbox = 0;
2856                 find_prev_textbox(&last_textbox, &new_textbox, result);
2857                 if(!new_textbox) new_textbox = last_textbox;
2858                 
2859         }
2861         if(new_textbox != active_subwindow)
2862         {
2863                 deactivate();
2864                 new_textbox->activate();
2865         }
2866         
2867         return 0;
2870 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
2872 // Search subwindows for textbox
2873         for(int i = 0; i < subwindows->total && result < 2; i++)
2874         {
2875                 BC_WindowBase *test_subwindow = subwindows->values[i];
2876                 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
2877         }
2879         if(result < 2)
2880         {
2881                 if(uses_text())
2882                 {
2883                         if(!*first_textbox) *first_textbox = this;
2885                         if(result < 1)
2886                         {
2887                                 if(top_level->active_subwindow == this)
2888                                         result++;
2889                         }
2890                         else
2891                         {
2892                                 result++;
2893                                 *next_textbox = this;
2894                         }
2895                 }
2896         }
2897         return 0;
2900 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
2902         if(result < 2)
2903         {
2904                 if(uses_text())
2905                 {
2906                         if(!*last_textbox) *last_textbox = this;
2908                         if(result < 1)
2909                         {
2910                                 if(top_level->active_subwindow == this)
2911                                         result++;
2912                         }
2913                         else
2914                         {
2915                                 result++;
2916                                 *prev_textbox = this;
2917                         }
2918                 }
2919         }
2921 // Search subwindows for textbox
2922         for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
2923         {
2924                 BC_WindowBase *test_subwindow = subwindows->values[i];
2925                 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
2926         }
2927         return 0;
2930 BC_Clipboard* BC_WindowBase::get_clipboard()
2932         return top_level->clipboard;
2935 int BC_WindowBase::get_relative_cursor_x()
2937         int abs_x, abs_y, x, y, win_x, win_y;
2938         unsigned int temp_mask;
2939         Window temp_win;
2941         XQueryPointer(top_level->display, 
2942            top_level->win, 
2943            &temp_win, 
2944            &temp_win,
2945        &abs_x, 
2946            &abs_y, 
2947            &win_x, 
2948            &win_y, 
2949            &temp_mask);
2951         XTranslateCoordinates(top_level->display, 
2952                         top_level->rootwin, 
2953                         win, 
2954                         abs_x, 
2955                         abs_y, 
2956                         &x, 
2957                         &y, 
2958                         &temp_win);
2960         return x;
2963 int BC_WindowBase::get_relative_cursor_y()
2965         int abs_x, abs_y, x, y, win_x, win_y;
2966         unsigned int temp_mask;
2967         Window temp_win;
2969         XQueryPointer(top_level->display, 
2970            top_level->win, 
2971            &temp_win, 
2972            &temp_win,
2973        &abs_x, 
2974            &abs_y, 
2975            &win_x, 
2976            &win_y, 
2977            &temp_mask);
2979         XTranslateCoordinates(top_level->display, 
2980                         top_level->rootwin, 
2981                         win, 
2982                         abs_x, 
2983                         abs_y, 
2984                         &x, 
2985                         &y, 
2986                         &temp_win);
2988         return y;
2991 int BC_WindowBase::get_abs_cursor_x(int lock_window)
2993         int abs_x, abs_y, win_x, win_y;
2994         unsigned int temp_mask;
2995         Window temp_win;
2997         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
2998         XQueryPointer(top_level->display, 
2999                 top_level->win, 
3000                 &temp_win, 
3001                 &temp_win,
3002                 &abs_x, 
3003                 &abs_y, 
3004                 &win_x, 
3005                 &win_y, 
3006                 &temp_mask);
3007         if(lock_window) this->unlock_window();
3008         return abs_x;
3011 int BC_WindowBase::get_abs_cursor_y(int lock_window)
3013         int abs_x, abs_y, win_x, win_y;
3014         unsigned int temp_mask;
3015         Window temp_win;
3017         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
3018         XQueryPointer(top_level->display, 
3019                 top_level->win, 
3020                 &temp_win, 
3021                 &temp_win,
3022         &abs_x, 
3023                 &abs_y, 
3024                 &win_x, 
3025                 &win_y, 
3026                 &temp_mask);
3027         if(lock_window) this->unlock_window();
3028         return abs_y;
3031 int BC_WindowBase::match_window(Window win) 
3033         if (this->win == win) return 1;
3034         int result = 0;
3035         for(int i = 0; i < subwindows->total; i++)
3036         {
3037                 result = subwindows->values[i]->match_window(win);
3038                 if (result) return result;
3039         }
3040         return 0;
3044 int BC_WindowBase::get_cursor_over_window()
3046         if(top_level != this) return top_level->get_cursor_over_window();
3048         int abs_x, abs_y, win_x, win_y;
3049         unsigned int temp_mask;
3050         Window temp_win1, temp_win2;
3052         if (!XQueryPointer(display, 
3053                 win, 
3054                 &temp_win1, 
3055                 &temp_win2,
3056                 &abs_x, 
3057                 &abs_y, 
3058                 &win_x, 
3059                 &win_y, 
3060                 &temp_mask))
3061                 return 0;
3063         int result = match_window(temp_win2)    ;
3064         return result;
3067 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
3069         int x, y;
3070         Window tempwin;
3072         translate_coordinates(top_level->event_win, 
3073                 pov->win,
3074                 top_level->cursor_x,
3075                 top_level->cursor_y,
3076                 &x,
3077                 &y);
3078         return x;
3081 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
3083         int x, y;
3084         Window tempwin;
3086         translate_coordinates(top_level->event_win, 
3087                 pov->win,
3088                 top_level->cursor_x,
3089                 top_level->cursor_y,
3090                 &x,
3091                 &y);
3092         return y;
3095 int BC_WindowBase::get_drag_x()
3097         return top_level->drag_x;
3100 int BC_WindowBase::get_drag_y()
3102         return top_level->drag_y;
3105 int BC_WindowBase::get_cursor_x()
3107         return top_level->cursor_x;
3110 int BC_WindowBase::get_cursor_y()
3112         return top_level->cursor_y;
3115 int BC_WindowBase::is_event_win()
3117         return this->win == top_level->event_win;
3120 void BC_WindowBase::set_dragging(int value)
3122         is_dragging = value;
3125 int BC_WindowBase::get_dragging()
3127         return is_dragging;
3130 int BC_WindowBase::get_buttonpress()
3132         return top_level->button_number;
3135 int BC_WindowBase::get_button_down()
3137         return top_level->button_down;
3140 int BC_WindowBase::alt_down()
3142         return top_level->alt_mask;
3145 int BC_WindowBase::shift_down()
3147         return top_level->shift_mask;
3150 int BC_WindowBase::ctrl_down()
3152         return top_level->ctrl_mask;
3156 int BC_WindowBase::get_keypress()
3158         return top_level->key_pressed;
3161 int BC_WindowBase::get_double_click()
3163         return top_level->double_click;
3166 int BC_WindowBase::get_bgcolor()
3168         return bg_color;
3171 int BC_WindowBase::resize_window(int w, int h)
3173         if(window_type == MAIN_WINDOW && !allow_resize)
3174         {
3175                 XSizeHints size_hints;
3176                 size_hints.flags = PSize | PMinSize | PMaxSize;
3177                 size_hints.width = w;
3178                 size_hints.height = h;
3179                 size_hints.min_width = w;
3180                 size_hints.max_width = w; 
3181                 size_hints.min_height = h;
3182                 size_hints.max_height = h; 
3183                 XSetNormalHints(top_level->display, win, &size_hints);
3184         }
3185         XResizeWindow(top_level->display, win, w, h);
3187         this->w = w;
3188         this->h = h;
3189         delete pixmap;
3190         pixmap = new BC_Pixmap(this, w, h);
3192 // Propagate to menubar
3193         for(int i = 0; i < subwindows->total; i++)
3194         {
3195                 subwindows->values[i]->dispatch_resize_event(w, h);
3196         }
3198         draw_background(0, 0, w, h);
3199         if(top_level == this && get_resources()->recursive_resizing)
3200                 resize_history.append(new BC_ResizeCall(w, h));
3201         return 0;
3204 // The only way for resize events to be propagated is by updating the internal w and h
3205 int BC_WindowBase::resize_event(int w, int h)
3207         if(window_type == MAIN_WINDOW)
3208         {
3209                 this->w = w;
3210                 this->h = h;
3211         }
3212         return 0;
3215 int BC_WindowBase::reposition_widget(int x, int y, int w, int h) 
3217   return(reposition_window(x, y, w, h));
3220 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
3222         int resize = 0;
3224 // Some tools set their own dimensions before calling this, causing the 
3225 // resize check to skip.
3226         this->x = x;
3227         this->y = y;
3229         if(w > 0 && w != this->w)
3230         {
3231                 resize = 1;
3232                 this->w = w;
3233         }
3235         if(h > 0 && h != this->h)
3236         {
3237                 resize = 1;
3238                 this->h = h;
3239         }
3241 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
3243         if(this->w <= 0)
3244                 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
3245         if(this->h <= 0)
3246                 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
3248         if(translation_count && window_type == MAIN_WINDOW)
3249         {
3250 // KDE shifts window right and down.
3251 // FVWM leaves window alone and adds border around it.
3252                 XMoveResizeWindow(top_level->display, 
3253                         win, 
3254                         x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x, 
3255                         y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y, 
3256                         this->w,
3257                         this->h);
3258         }
3259         else
3260         {
3261                 XMoveResizeWindow(top_level->display, 
3262                         win, 
3263                         x, 
3264                         y, 
3265                         this->w, 
3266                         this->h);
3267         }
3269         if(resize)
3270         {
3271                 delete pixmap;
3272                 pixmap = new BC_Pixmap(this, this->w, this->h);
3273 // Propagate to menubar
3274                 for(int i = 0; i < subwindows->total; i++)
3275                 {
3276                         subwindows->values[i]->dispatch_resize_event(this->w, this->h);
3277                 }
3279 //              draw_background(0, 0, w, h);
3280         }
3282         return 0;
3285 int BC_WindowBase::set_tooltips(int tooltips_enabled)
3287         get_resources()->tooltips_enabled = tooltips_enabled;
3288         return 0;
3291 int BC_WindowBase::raise_window(int do_flush)
3293         XRaiseWindow(top_level->display, win);
3294         if(do_flush) XFlush(top_level->display);
3295         return 0;
3298 void BC_WindowBase::set_background(VFrame *bitmap)
3300         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
3302         bg_pixmap = new BC_Pixmap(this, 
3303                         bitmap, 
3304                         PIXMAP_OPAQUE);
3305         shared_bg_pixmap = 0;
3306         draw_background(0, 0, w, h);
3309 void BC_WindowBase::set_title(char *text)
3311         XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0); 
3312         strcpy(this->title, _(text));
3313         flush();
3316 char* BC_WindowBase::get_title()
3318         return title;
3321 int BC_WindowBase::get_toggle_value()
3323         return toggle_value;
3326 int BC_WindowBase::get_toggle_drag()
3328         return toggle_drag;
3331 int BC_WindowBase::set_icon(VFrame *data)
3333         if(icon_pixmap) delete icon_pixmap;
3334         icon_pixmap = new BC_Pixmap(top_level, 
3335                 data, 
3336                 PIXMAP_ALPHA,
3337                 1);
3339         icon_window = new BC_Popup(this, 
3340                 (int)BC_INFINITY, 
3341                 (int)BC_INFINITY, 
3342                 icon_pixmap->get_w(), 
3343                 icon_pixmap->get_h(), 
3344                 -1, 
3345                 1, // All windows are hidden initially
3346                 icon_pixmap);
3348         XWMHints wm_hints;
3349         wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
3350         wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
3351         wm_hints.icon_mask = icon_pixmap->get_alpha();
3352         wm_hints.icon_window = icon_window->win;
3353         wm_hints.window_group = XGroupLeader;
3355 // for(int i = 0; i < 1000; i++)
3356 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
3357 // printf("\n");
3359         XSetWMHints(top_level->display, top_level->win, &wm_hints);
3360         XSync(top_level->display, 0);
3361         return 0;
3364 int BC_WindowBase::set_w(int w)
3366         this->w = w;
3367         return 0;
3370 int BC_WindowBase::set_h(int h)
3372         this->h = h;
3373         return 0;
3376 int BC_WindowBase::load_defaults(BC_Hash *defaults)
3378         BC_Resources *resources = get_resources();
3379         char string[BCTEXTLEN];
3380         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3381         {
3382                 sprintf(string, "FILEBOX_HISTORY%d", i);
3383                 resources->filebox_history[i][0] = 0;
3384                 defaults->get(string, resources->filebox_history[i]);
3385         }
3386         resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
3387         resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
3388         resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
3389         defaults->get("FILEBOX_FILTER", resources->filebox_filter);
3390         return 0;
3393 int BC_WindowBase::save_defaults(BC_Hash *defaults)
3395         BC_Resources *resources = get_resources();
3396         char string[BCTEXTLEN];
3397         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
3398         {
3399                 sprintf(string, "FILEBOX_HISTORY%d", i);
3400                 defaults->update(string, resources->filebox_history[i]);
3401         }
3402         defaults->update("FILEBOX_MODE", resources->filebox_mode);
3403         defaults->update("FILEBOX_W", resources->filebox_w);
3404         defaults->update("FILEBOX_H", resources->filebox_h);
3405         defaults->update("FILEBOX_FILTER", resources->filebox_filter);
3406         return 0;
3411 // For some reason XTranslateCoordinates can take a long time to return.
3412 // We work around this by only calling it when the event windows are different.
3413 void BC_WindowBase::translate_coordinates(Window src_w, 
3414                 Window dest_w,
3415                 int src_x,
3416                 int src_y,
3417                 int *dest_x_return,
3418                 int *dest_y_return)
3420         Window tempwin = 0;
3421 //Timer timer;
3422 //timer.update();
3423         if(src_w == dest_w)
3424         {
3425                 *dest_x_return = src_x;
3426                 *dest_y_return = src_y;
3427         }
3428         else
3429         {
3430                 XTranslateCoordinates(top_level->display, 
3431                         src_w, 
3432                         dest_w, 
3433                         src_x, 
3434                         src_y, 
3435                         dest_x_return, 
3436                         dest_y_return,
3437                         &tempwin);
3438 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
3439         }
3448 #ifdef HAVE_LIBXXF86VM
3449 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
3451    int foo,bar;
3452    *vm = 0;
3453    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
3454            int vm_count,i;
3455            XF86VidModeModeInfo **vm_modelines;
3456            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3457            for (i = 0; i < vm_count; i++) {
3458                    if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
3459                            *vm = i;
3460            }
3461            display = top_level->display;
3462            if (vm_modelines[*vm]->hdisplay == *width)
3463                    *vm = -1;
3464            else
3465            {
3466                    *width = vm_modelines[*vm]->hdisplay;
3467                    *height = vm_modelines[*vm]->vdisplay;
3468            }
3469    }
3472 void BC_WindowBase::scale_vm(int vm)
3474    int foo,bar,dotclock;
3475    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
3476    {
3477            int vm_count;
3478            XF86VidModeModeInfo **vm_modelines;
3479            XF86VidModeModeLine vml;
3480            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
3481            XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
3482            orig_modeline.dotclock = dotclock;
3483            orig_modeline.hdisplay = vml.hdisplay;
3484            orig_modeline.hsyncstart = vml.hsyncstart;
3485            orig_modeline.hsyncend = vml.hsyncend;
3486            orig_modeline.htotal = vml.htotal;
3487            orig_modeline.vdisplay = vml.vdisplay;
3488            orig_modeline.vsyncstart = vml.vsyncstart;
3489            orig_modeline.vsyncend = vml.vsyncend;
3490            orig_modeline.vtotal = vml.vtotal;
3491            orig_modeline.flags = vml.flags;
3492            orig_modeline.privsize = vml.privsize;
3493            // orig_modeline.private = vml.private;
3494            XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
3495            XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
3496            XFlush(top_level->display);
3497    }
3500 void BC_WindowBase::restore_vm()
3502    XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
3503    XFlush(top_level->display);
3507 #endif
3527 int BC_WindowBase::get_event_count()
3529         event_lock->lock("BC_WindowBase::get_event_count");
3530         int result = common_events.total;
3531         event_lock->unlock();
3532         return result;
3535 XEvent* BC_WindowBase::get_event()
3537         XEvent *result = 0;
3538         while(!done && !result)
3539         {
3540                 event_condition->lock("BC_WindowBase::get_event");
3541                 event_lock->lock("BC_WindowBase::get_event");
3543                 if(common_events.total && !done)
3544                 {
3545                         result = common_events.values[0];
3546                         common_events.remove_number(0);
3547                 }
3549                 event_lock->unlock();
3550         }
3551         return result;
3554 void BC_WindowBase::put_event(XEvent *event)
3556         event_lock->lock("BC_WindowBase::put_event");
3557         common_events.append(event);
3558         event_lock->unlock();
3559         event_condition->unlock();
3562 int BC_WindowBase::get_id()
3564         return id;