Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

bcwindowbase.C

Go to the documentation of this file.
00001 #include "bcbitmap.h"
00002 #include "bcclipboard.h"
00003 #include "bcdisplayinfo.h"
00004 #include "bcmenubar.h"
00005 #include "bcpixmap.h"
00006 #include "bcpopup.h"
00007 #include "bcpopupmenu.h"
00008 #include "bcrepeater.h"
00009 #include "bcresources.h"
00010 #include "bcsignals.h"
00011 #include "bcsubwindow.h"
00012 #include "bcwindowbase.h"
00013 #include "bcwindowevents.h"
00014 #include "colormodels.h"
00015 #include "colors.h"
00016 #include "condition.h"
00017 #include "cursors.h"
00018 #include "defaults.h"
00019 #include "fonts.h"
00020 #include "keys.h"
00021 #include "language.h"
00022 #include "sizes.h"
00023 #include "vframe.h"
00024 
00025 #ifdef HAVE_GL
00026 #include <GL/gl.h>
00027 #endif
00028 #include <string.h>
00029 #include <unistd.h>
00030 
00031 #include <X11/extensions/Xvlib.h>
00032 #include <X11/extensions/shape.h>
00033 
00034 
00035 BC_ResizeCall::BC_ResizeCall(int w, int h)
00036 {
00037         this->w = w;
00038         this->h = h;
00039 }
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 Mutex BC_WindowBase::opengl_lock;
00051 
00052 BC_Resources BC_WindowBase::resources;
00053 
00054 Window XGroupLeader = 0;
00055 
00056 BC_WindowBase::BC_WindowBase()
00057 {
00058 //printf("BC_WindowBase::BC_WindowBase 1\n");
00059         BC_WindowBase::initialize();
00060 }
00061 
00062 BC_WindowBase::~BC_WindowBase()
00063 {
00064 
00065 #ifdef HAVE_LIBXXF86VM
00066    if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
00067    {
00068            restore_vm();   
00069    }
00070 #endif
00071 
00072         hide_tooltip();
00073         if(window_type != MAIN_WINDOW)
00074         {
00075                 if(top_level->active_menubar == this) top_level->active_menubar = 0;
00076                 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
00077                 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
00078                 parent_window->subwindows->remove(this);
00079         }
00080 
00081 
00082 // Delete the subwindows
00083         is_deleting = 1;
00084         if(subwindows)
00085         {
00086                 while (subwindows->total) 
00087                 {
00088                         // NOTE: since the value is itself a subwindow, the
00089                         //       recursion removes the item from subwindows
00090                         delete subwindows->values[0];
00091                 }
00092                 delete subwindows;
00093         }
00094 
00095         XFreePixmap(top_level->display, pixmap);
00096         XDestroyWindow(top_level->display, win);
00097 
00098         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
00099         if(icon_pixmap) delete icon_pixmap;
00100         if(temp_bitmap) delete temp_bitmap;
00101 
00102 
00103         if(window_type == MAIN_WINDOW) 
00104         {
00105                 
00106                 XFreeGC(display, gc);
00107 #ifdef HAVE_XFT
00108                 if(largefont_xft) 
00109                         XftFontClose (display, (XftFont*)largefont_xft);
00110                 if(mediumfont_xft) 
00111                         XftFontClose (display, (XftFont*)mediumfont_xft);
00112                 if(smallfont_xft) 
00113                         XftFontClose (display, (XftFont*)smallfont_xft);
00114 #endif
00115                 flush();
00116 // Can't close display if another thread is waiting for events
00117                 XCloseDisplay(display);
00118 //              XCloseDisplay(event_display);
00119                 clipboard->stop_clipboard();
00120                 delete clipboard;
00121         }
00122         else
00123         {
00124                 flush();
00125         }
00126 
00127         resize_history.remove_all_objects();
00128         common_events.remove_all_objects();
00129         delete event_lock;
00130         delete event_condition;
00131         UNSET_ALL_LOCKS(this)
00132 }
00133 
00134 int BC_WindowBase::initialize()
00135 {
00136         test_keypress = 0;
00137         is_deleting = 0;
00138         window_lock = 0;
00139         x = 0; 
00140         y = 0; 
00141         w = 0; 
00142         h = 0;
00143         bg_color = -1;
00144         top_level = 0;
00145         parent_window = 0;
00146         subwindows = 0;
00147         xvideo_port_id = -1;
00148         video_on = 0;
00149         motion_events = 0;
00150         resize_events = 0;
00151         translation_events = 0;
00152         ctrl_mask = shift_mask = alt_mask = 0;
00153         cursor_x = cursor_y = button_number = 0;
00154         button_down = 0;
00155         button_pressed = 0;
00156         button_time1 = button_time2 = 0;
00157         double_click = 0;
00158         last_motion_win = 0;
00159         key_pressed = 0;
00160         active_menubar = 0;
00161         active_popup_menu = 0;
00162         active_subwindow = 0;
00163         bg_pixmap = 0;
00164         tooltip_text[0] = 0;
00165         persistant_tooltip = 0;
00166 //      next_repeat_id = 0;
00167         tooltip_popup = 0;
00168         tooltip_done = 0;
00169         current_font = MEDIUMFONT;
00170         current_color = BLACK;
00171         prev_cursor = current_cursor = ARROW_CURSOR;
00172         hourglass_total = 0;
00173         is_dragging = 0;
00174         shared_bg_pixmap = 0;
00175         icon_pixmap = 0;
00176         window_type = MAIN_WINDOW;
00177         translation_count = 0;
00178         x_correction = y_correction = 0;
00179         temp_bitmap = 0;
00180         tooltip_on = 0;
00181         temp_cursor = 0;
00182         toggle_value = 0;
00183         toggle_drag = 0;
00184         has_focus = 0;
00185 #ifdef HAVE_LIBXXF86VM
00186     vm_switched = 0;
00187 #endif
00188         xft_drawable = 0;
00189         largefont_xft = 0;
00190         mediumfont_xft = 0;
00191         smallfont_xft = 0;
00192 // Need these right away since put_event is called before run_window sometimes.
00193         event_lock = new Mutex("BC_WindowBase::event_lock");
00194         event_condition = new Condition(0, "BC_WindowBase::event_condition");
00195         event_thread = 0;
00196 
00197         return 0;
00198 }
00199 
00200 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
00201                         LeaveWindowMask | \
00202                         ButtonPressMask | \
00203                         ButtonReleaseMask | \
00204                         PointerMotionMask | \
00205                         FocusChangeMask
00206                         
00207 
00208 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
00209                                 char *title, 
00210                                 int x,
00211                                 int y,
00212                                 int w, 
00213                                 int h, 
00214                                 int minw, 
00215                                 int minh, 
00216                                 int allow_resize,
00217                                 int private_color, 
00218                                 int hide,
00219                                 int bg_color,
00220                                 char *display_name,
00221                                 int window_type,
00222                                 BC_Pixmap *bg_pixmap,
00223                                 int group_it)
00224 {
00225         XSetWindowAttributes attr;
00226         unsigned long mask;
00227         XSizeHints size_hints;
00228         int root_w;
00229         int root_h;
00230 #ifdef HAVE_LIBXXF86VM
00231     int vm;
00232 #endif
00233 
00234     if(parent_window) top_level = parent_window->top_level;
00235 
00236 #ifdef HAVE_LIBXXF86VM
00237     if(window_type == VIDMODE_SCALED_WINDOW)
00238             closest_vm(&vm,&w,&h);
00239 #endif
00240 
00241         this->x = x;
00242         this->y = y;
00243         this->w = w;
00244         this->h = h;
00245         this->bg_color = bg_color;
00246         this->window_type = window_type;
00247         this->hidden = hide;
00248         this->private_color = private_color;
00249         this->parent_window = parent_window;
00250         this->bg_pixmap = bg_pixmap;
00251         this->allow_resize = allow_resize;
00252         strcpy(this->title, _(title));
00253         if(bg_pixmap) shared_bg_pixmap = 1;
00254 
00255         if(parent_window) top_level = parent_window->top_level;
00256 
00257         subwindows = new BC_SubWindowList;
00258 
00259 // Mandatory setup
00260         if(window_type == MAIN_WINDOW)
00261         {
00262                 top_level = this;
00263                 parent_window = this;
00264 
00265 // This function must be the first Xlib
00266 // function a multi-threaded program calls
00267                 XInitThreads();
00268 
00269 
00270 // get the display connection
00271                 display = init_display(display_name);
00272 //              event_display = init_display(display_name);
00273 
00274 // Fudge window placement
00275                 root_w = get_root_w(1, 0);
00276                 root_h = get_root_h(0);
00277                 if(this->x + this->w > root_w) this->x = root_w - this->w;
00278                 if(this->y + this->h > root_h) this->y = root_h - this->h;
00279                 if(this->x < 0) this->x = 0;
00280                 if(this->y < 0) this->y = 0;
00281                 screen = DefaultScreen(display);
00282 
00283                 rootwin = RootWindow(display, screen);
00284                 vis = DefaultVisual(display, screen);
00285                 default_depth = DefaultDepth(display, screen);
00286                 client_byte_order = (*(u_int32_t*)"a   ") & 0x00000001;
00287                 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
00288 
00289 
00290 
00291 // This must be done before fonts to know if antialiasing is available.
00292                 init_colors();
00293 // get the resources
00294                 if(resources.use_shm < 0) resources.initialize_display(this);
00295                 x_correction = get_resources()->get_left_border();
00296                 y_correction = get_resources()->get_top_border();
00297 
00298                 if(this->bg_color == -1)
00299                         this->bg_color = resources.get_bg_color();
00300                 init_fonts();
00301                 init_gc();
00302                 init_cursors();
00303 
00304 // Create the window
00305                 mask = CWEventMask | 
00306                                 CWBackPixel | 
00307                                 CWColormap | 
00308                                 CWCursor;
00309 
00310                 attr.event_mask = DEFAULT_EVENT_MASKS |
00311                         StructureNotifyMask | 
00312                         KeyPressMask;
00313 
00314                 attr.background_pixel = get_color(this->bg_color);
00315                 attr.colormap = cmap;
00316                 attr.cursor = get_cursor_struct(ARROW_CURSOR);
00317 
00318                 win = XCreateWindow(display, 
00319                         rootwin, 
00320                         this->x, 
00321                         this->y, 
00322                         this->w, 
00323                         this->h, 
00324                         0, 
00325                         top_level->default_depth, 
00326                         InputOutput, 
00327                         vis, 
00328                         mask, 
00329                         &attr);
00330 
00331                 XGetNormalHints(display, win, &size_hints);
00332 
00333                 size_hints.flags = PSize | PMinSize | PMaxSize;
00334                 size_hints.width = this->w;
00335                 size_hints.height = this->h;
00336                 size_hints.min_width = allow_resize ? minw : this->w;
00337                 size_hints.max_width = allow_resize ? 32767 : this->w; 
00338                 size_hints.min_height = allow_resize ? minh : this->h;
00339                 size_hints.max_height = allow_resize ? 32767 : this->h; 
00340                 if(x > -BC_INFINITY && x < BC_INFINITY)
00341                 {
00342                         size_hints.flags |= PPosition;
00343                         size_hints.x = this->x;
00344                         size_hints.y = this->y;
00345                 }
00346 
00347                 XSetStandardProperties(display, 
00348                         win, 
00349                         title, 
00350                         title, 
00351                         None, 
00352                         0, 
00353                         0, 
00354                         &size_hints);
00355                 get_atoms();
00356                 
00357                 clipboard = new BC_Clipboard(display_name);
00358                 clipboard->start_clipboard();
00359 
00360                 if (group_it)
00361                 {
00362                         Atom ClientLeaderXAtom;
00363                         if (XGroupLeader == 0)
00364                                 XGroupLeader = win;
00365                         char *instance_name = "cinelerra";
00366                         char *class_name = "Cinelerra";
00367                         XClassHint *class_hints = XAllocClassHint(); 
00368                         class_hints->res_name = instance_name;
00369                         class_hints->res_class = class_name;
00370                         XSetClassHint(top_level->display, win, class_hints);
00371                         XFree(class_hints);
00372                         ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
00373                         XChangeProperty(display, 
00374                                         win, 
00375                                         ClientLeaderXAtom, 
00376                                         XA_WINDOW, 
00377                                         32, 
00378                                         PropModeReplace, 
00379                                         (unsigned char *)&XGroupLeader, 
00380                                         true);
00381 
00382                 }
00383                 
00384         }
00385 
00386 #ifdef HAVE_LIBXXF86VM
00387     if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
00388     {
00389             scale_vm (vm);
00390             vm_switched = 1;
00391     }
00392 #endif
00393 
00394 #ifdef HAVE_LIBXXF86VM
00395     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
00396 #else
00397     if(window_type == POPUP_WINDOW)
00398 #endif
00399         {
00400                 mask = CWEventMask | 
00401                         CWBackPixel | 
00402                         CWColormap | 
00403                         CWOverrideRedirect | 
00404                         CWSaveUnder | 
00405                         CWCursor;
00406 
00407                 attr.event_mask = DEFAULT_EVENT_MASKS |
00408                         KeyPressMask;
00409 
00410                 if(this->bg_color == -1)
00411                         this->bg_color = resources.get_bg_color();
00412                 attr.background_pixel = top_level->get_color(bg_color);
00413                 attr.colormap = top_level->cmap;
00414                 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
00415                 attr.override_redirect = True;
00416                 attr.save_under = True;
00417 
00418                 win = XCreateWindow(top_level->display, 
00419                         top_level->rootwin, 
00420                         this->x, 
00421                         this->y, 
00422                         this->w, 
00423                         this->h, 
00424                         0, 
00425                         top_level->default_depth, 
00426                         InputOutput, 
00427                         top_level->vis, 
00428                         mask, 
00429                         &attr);
00430         }
00431 
00432         if(window_type == SUB_WINDOW)
00433         {
00434                 mask = CWBackPixel | CWEventMask;
00435                 attr.event_mask = DEFAULT_EVENT_MASKS;
00436                 attr.background_pixel = top_level->get_color(this->bg_color);
00437                 win = XCreateWindow(top_level->display, 
00438                         parent_window->win, 
00439                         this->x, 
00440                         this->y, 
00441                         this->w, 
00442                         this->h, 
00443                         0, 
00444                         top_level->default_depth, 
00445                         InputOutput, 
00446                         top_level->vis, 
00447                         mask, 
00448                         &attr);
00449                 init_window_shape();
00450                 XMapWindow(top_level->display, win);
00451         }
00452 
00453 // Create pixmap for all windows
00454         pixmap = XCreatePixmap(top_level->display, 
00455                 win, 
00456                 this->w, 
00457                 this->h, 
00458                 top_level->default_depth);
00459 
00460 // Create truetype rendering surface
00461 #ifdef HAVE_XFT
00462         if(get_resources()->use_xft)
00463         {
00464 // printf("BC_WindowBase::create_window 1 %p %p %p %p\n", 
00465 // top_level->display,
00466 // pixmap,
00467 // top_level->vis,
00468 // top_level->cmap);
00469                 xft_drawable = XftDrawCreate(top_level->display,
00470                        pixmap,
00471                        top_level->vis,
00472                        top_level->cmap);
00473 // printf("BC_WindowBase::create_window 10 %p %p %p %p %p\n", 
00474 // xft_drawable, 
00475 // top_level->display,
00476 // pixmap,
00477 // top_level->vis,
00478 // top_level->cmap);
00479         }
00480 #endif
00481 
00482 // Set up options for main window
00483         if(window_type == MAIN_WINDOW)
00484         {
00485                 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
00486                 {
00487                         this->bg_pixmap = new BC_Pixmap(this, 
00488                                 get_resources()->bg_image, 
00489                                 PIXMAP_OPAQUE);
00490                 }
00491 
00492                 if(!hidden) show_window();
00493 
00494         }
00495 
00496 
00497 
00498 
00499         draw_background(0, 0, this->w, this->h);
00500         flash();
00501 
00502 // Set up options for popup window
00503 #ifdef HAVE_LIBXXF86VM
00504     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
00505 #else
00506     if(window_type == POPUP_WINDOW)
00507 #endif
00508         {
00509                 init_window_shape();
00510                 if(!hidden) show_window();
00511         }
00512         return 0;
00513 }
00514 
00515 Display* BC_WindowBase::init_display(char *display_name)
00516 {
00517         Display* display;
00518 
00519         if(display_name && display_name[0] == 0) display_name = NULL;
00520         if((display = XOpenDisplay(display_name)) == NULL)
00521         {
00522                 printf("BC_WindowBase::init_display: cannot connect to X server %s\n", 
00523                         display_name);
00524                 if(getenv("DISPLAY") == NULL)
00525         {
00526                         printf("'DISPLAY' environment variable not set.\n");
00527                         exit(1);
00528                 }
00529                 else
00530 // Try again with default display.
00531                 {
00532                         if((display = XOpenDisplay(0)) == NULL)
00533                         {
00534                                 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
00535                                 exit(1);
00536                         }
00537                 }
00538         }
00539         return display;
00540 }
00541 
00542 int BC_WindowBase::run_window()
00543 {
00544         done = 0;
00545         return_value = 0;
00546 
00547 
00548 // Events may have been sent before run_window so can't initialize them here.
00549 
00550 // Start tooltips
00551         if(window_type == MAIN_WINDOW)
00552         {
00553 //              tooltip_id = get_repeat_id();
00554                 set_repeat(get_resources()->tooltip_delay);
00555         }
00556 
00557 // Start X server events
00558         event_thread = new BC_WindowEvents(this);
00559         event_thread->start();
00560 
00561 // Start common events
00562         while(!done)
00563         {
00564                 dispatch_event();
00565         }
00566 
00567         unset_all_repeaters();
00568         hide_tooltip();
00569         delete event_thread;
00570         event_thread = 0;
00571         event_condition->reset();
00572         common_events.remove_all_objects();
00573         done = 0;
00574 
00575         return return_value;
00576 }
00577 
00578 int BC_WindowBase::get_key_masks(XEvent *event)
00579 {
00580 // printf("BC_WindowBase::get_key_masks %llx\n", 
00581 // event->xkey.state);
00582 // ctrl key down
00583         ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
00584 // shift key down
00585         shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
00586         alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
00587         return 0;
00588 }
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 int BC_WindowBase::dispatch_event()
00597 {
00598         XEvent *event = 0;
00599     Window tempwin;
00600         KeySym keysym;
00601         char keys_return[2];
00602         int result;
00603         XClientMessageEvent *ptr;
00604         int temp;
00605         int cancel_resize, cancel_translation;
00606 
00607         key_pressed = 0;
00608 
00609 // If an event is waiting get it, otherwise
00610 // wait for next event only if there are no compressed events.
00611         if(get_event_count() || 
00612                 (!motion_events && !resize_events && !translation_events))
00613         {
00614 //              XNextEvent(display, event);
00615                 event = get_event();
00616 // Lock out window deletions
00617                 lock_window("BC_WindowBase::dispatch_event 1");
00618 //              get_key_masks(event);
00619         }
00620         else
00621 // Handle compressed events
00622         {
00623                 lock_window("BC_WindowBase::dispatch_event 2");
00624                 if(resize_events)
00625                         dispatch_resize_event(last_resize_w, last_resize_h);
00626                 else
00627                 if(motion_events)
00628                         dispatch_motion_event();
00629                 else
00630                 if(translation_events)
00631                         dispatch_translation_event();
00632 
00633                 unlock_window();
00634                 return 0;
00635         }
00636 
00637 //printf("1 %s %p %d\n", title, event, event->type);
00638         switch(event->type)
00639         {
00640                 case ClientMessage:
00641                         get_key_masks(event);
00642 // Clear the resize buffer
00643                         if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
00644 // Clear the motion buffer since this can clear the window
00645                         if(motion_events)
00646                         {
00647                                 dispatch_motion_event();
00648                         }
00649 
00650                         ptr = (XClientMessageEvent*)event;
00651 
00652 
00653                 if(ptr->message_type == ProtoXAtom && 
00654                                 ptr->data.l[0] == DelWinXAtom)
00655                 {
00656                                 close_event();
00657                         }
00658                         else
00659                         if(ptr->message_type == RepeaterXAtom)
00660                         {
00661                                 dispatch_repeat_event(ptr->data.l[0]);
00662 // Make sure the repeater still exists.
00663 //                              for(int i = 0; i < repeaters.total; i++)
00664 //                              {
00665 //                                      if(repeaters.values[i]->repeat_id == ptr->data.l[0])
00666 //                                      {
00667 //                                              dispatch_repeat_event_master(ptr->data.l[0]);
00668 //                                              break;
00669 //                                      }
00670 //                              }
00671                         }
00672                         else
00673                         if(ptr->message_type == SetDoneXAtom)
00674                         {
00675                                 done = 1;
00676                         }
00677                         break;
00678 
00679                 case FocusIn:
00680                         has_focus = 1;
00681                         dispatch_focus_in();
00682                         break;
00683 
00684                 case FocusOut:
00685                         has_focus = 0;
00686                         dispatch_focus_out();
00687                         break;
00688 
00689 // Maximized
00690                 case MapNotify:
00691                         break;
00692 
00693 // Minimized
00694                 case UnmapNotify:
00695                         break;
00696 
00697                 case ButtonPress:
00698                         get_key_masks(event);
00699                         cursor_x = event->xbutton.x;
00700                         cursor_y = event->xbutton.y;
00701                         button_number = event->xbutton.button;
00702                         event_win = event->xany.window;
00703                         if (button_number != 4 && button_number != 5)
00704                                 button_down = 1;
00705                         button_pressed = event->xbutton.button;
00706                         button_time1 = button_time2;
00707                         button_time2 = event->xbutton.time;
00708                         drag_x = cursor_x;
00709                         drag_y = cursor_y;
00710                         drag_win = event_win;
00711                         drag_x1 = cursor_x - get_resources()->drag_radius;
00712                         drag_x2 = cursor_x + get_resources()->drag_radius;
00713                         drag_y1 = cursor_y - get_resources()->drag_radius;
00714                         drag_y2 = cursor_y + get_resources()->drag_radius;
00715 
00716                         if(button_time2 - button_time1 < resources.double_click)
00717                         {
00718 // Ignore triple clicks
00719                                 double_click = 1; 
00720                                 button_time2 = button_time1 = 0; 
00721                         }
00722                         else 
00723                                 double_click = 0;
00724 
00725                         dispatch_button_press();
00726                         break;
00727 
00728                 case ButtonRelease:
00729                         get_key_masks(event);
00730                         button_number = event->xbutton.button;
00731                         event_win = event->xany.window;
00732                         if (button_number != 4 && button_number != 5) 
00733                                 button_down = 0;
00734 
00735                         dispatch_button_release();
00736 
00737                         break;
00738 
00739                 case Expose:
00740                         event_win = event->xany.window;
00741                         dispatch_expose_event();
00742                         break;
00743 
00744                 case MotionNotify:
00745                         get_key_masks(event);
00746 // Dispatch previous motion event if this is a subsequent motion from a different window
00747                         if(motion_events && last_motion_win != event->xany.window)
00748                         {
00749                                 dispatch_motion_event();
00750                         }
00751 
00752 // Buffer the current motion
00753                         motion_events = 1;
00754                         last_motion_x = event->xmotion.x;
00755                         last_motion_y = event->xmotion.y;
00756                         last_motion_win = event->xany.window;
00757                         break;
00758 
00759                 case ConfigureNotify:
00760                         get_key_masks(event);
00761                         XTranslateCoordinates(top_level->display, 
00762                                 top_level->win, 
00763                                 top_level->rootwin, 
00764                                 0, 
00765                                 0, 
00766                                 &last_translate_x, 
00767                                 &last_translate_y, 
00768                                 &tempwin);
00769                         last_resize_w = event->xconfigure.width;
00770                         last_resize_h = event->xconfigure.height;
00771 
00772                         cancel_resize = 0;
00773                         cancel_translation = 0;
00774 
00775 // Resize history prevents responses to recursive resize requests
00776                         for(int i = 0; i < resize_history.total && !cancel_resize; i++)
00777                         {
00778                                 if(resize_history.values[i]->w == last_resize_w &&
00779                                         resize_history.values[i]->h == last_resize_h)
00780                                 {
00781                                         delete resize_history.values[i];
00782                                         resize_history.remove_number(i);
00783                                         cancel_resize = 1;
00784                                 }
00785                         }
00786 
00787                         if(last_resize_w == w && last_resize_h == h)
00788                                 cancel_resize = 1;
00789 
00790                         if(!cancel_resize)
00791                         {
00792                                 resize_events = 1;
00793                         }
00794 
00795                         if((last_translate_x == x && last_translate_y == y))
00796                                 cancel_translation = 1;
00797 
00798                         if(!cancel_translation)
00799                         {
00800                                 translation_events = 1;
00801                         }
00802 
00803                         translation_count++;
00804                         break;
00805 
00806                 case KeyPress:
00807                         get_key_masks(event);
00808                         keys_return[0] = 0;
00809                         XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
00810 
00811 // printf("BC_WindowBase::dispatch_event 2 %llx\n", 
00812 // event->xkey.state);
00813 // block out control keys
00814                         if(keysym > 0xffe0 && keysym < 0xffff) break;
00815 
00816 
00817                         if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
00818 
00819 
00820                         switch(keysym)
00821                         {
00822 // block out extra keys
00823                         case XK_Alt_L:      
00824                         case XK_Alt_R:      
00825                         case XK_Shift_L:    
00826                         case XK_Shift_R:    
00827                         case XK_Control_L:  
00828                         case XK_Control_R:  
00829                                         key_pressed = 0;         
00830                                         break;
00831 
00832 // Translate key codes
00833                                 case XK_Return:     key_pressed = RETURN;    break;
00834                         case XK_Up:         key_pressed = UP;        break;
00835                                 case XK_Down:       key_pressed = DOWN;      break;
00836                                 case XK_Left:       key_pressed = LEFT;      break;
00837                         case XK_Right:      key_pressed = RIGHT;     break;
00838                         case XK_Next:       key_pressed = PGDN;      break;
00839                         case XK_Prior:      key_pressed = PGUP;      break;
00840                         case XK_BackSpace:  key_pressed = BACKSPACE; break;
00841                         case XK_Escape:     key_pressed = ESC;       break;
00842                         case XK_Tab:
00843                                         if(shift_down())
00844                                                 key_pressed = LEFTTAB;
00845                                         else
00846                                                 key_pressed = TAB;       
00847                                         break;
00848                                 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
00849                                 case XK_underscore: key_pressed = '_';       break;
00850                         case XK_asciitilde: key_pressed = '~';       break;
00851                                 case XK_Delete:     key_pressed = DELETE;    break;
00852                                 case XK_Home:       key_pressed = HOME;      break;
00853                                 case XK_End:        key_pressed = END;       break;
00854 
00855 // number pad
00856                                 case XK_KP_Enter:       key_pressed = KPENTER;   break;
00857                                 case XK_KP_Add:         key_pressed = KPPLUS;    break;
00858                                 case XK_KP_1:
00859                                 case XK_KP_End:         key_pressed = KP1;       break;
00860                                 case XK_KP_2:
00861                                 case XK_KP_Down:        key_pressed = KP2;       break;
00862                                 case XK_KP_3:
00863                                 case XK_KP_Page_Down:   key_pressed = KP3;       break;
00864                                 case XK_KP_4:
00865                                 case XK_KP_Left:        key_pressed = KP4;       break;
00866                                 case XK_KP_5:
00867                                 case XK_KP_Begin:       key_pressed = KP5;       break;
00868                                 case XK_KP_6:
00869                                 case XK_KP_Right:       key_pressed = KP6;       break;
00870                                 case XK_KP_0:
00871                                 case XK_KP_Insert:      key_pressed = KPINS;     break;
00872                                 case XK_KP_Decimal:
00873                                 case XK_KP_Delete:      key_pressed = KPDEL;     break;
00874                         default:           
00875                                         //key_pressed = keys_return[0]; 
00876                                         key_pressed = keysym & 0xff;
00877                                         break;
00878                         }
00879 
00880 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
00881                         result = dispatch_keypress_event();
00882 // Handle some default keypresses
00883                         if(!result)
00884                         {
00885                                 if(key_pressed == 'w' ||
00886                                         key_pressed == 'W')
00887                                 {
00888                                         close_event();
00889                                 }
00890                         }
00891                         break;
00892 
00893                 case LeaveNotify:
00894                         event_win = event->xany.window;
00895                         dispatch_cursor_leave();
00896                         break;
00897 
00898                 case EnterNotify:
00899                         event_win = event->xany.window;
00900                         cursor_x = event->xcrossing.x;
00901                         cursor_y = event->xcrossing.y;
00902                         dispatch_cursor_enter();
00903                         break;
00904         }
00905 //printf("100 %s %p %d\n", title, event, event->type);
00906 
00907         unlock_window();
00908         if(event) delete event;
00909         return 0;
00910 }
00911 
00912 int BC_WindowBase::dispatch_expose_event()
00913 {
00914         int result = 0;
00915         for(int i = 0; i < subwindows->total && !result; i++)
00916         {
00917                 result = subwindows->values[i]->dispatch_expose_event();
00918         }
00919 
00920 // Propagate to user
00921         if(!result) expose_event();
00922         return result;
00923 }
00924 
00925 int BC_WindowBase::dispatch_resize_event(int w, int h)
00926 {
00927         if(window_type == MAIN_WINDOW)
00928         {
00929                 resize_events = 0;
00930 // Can't store w and h here because bcfilebox depends on the old w and h to
00931 // reposition widgets.
00932                 XFreePixmap(top_level->display, pixmap);
00933                 pixmap = XCreatePixmap(top_level->display, 
00934                         win, 
00935                         w, 
00936                         h, 
00937                         top_level->default_depth);
00938                 clear_box(0, 0, w, h);
00939         }
00940 
00941 // Propagate to subwindows
00942         for(int i = 0; i < subwindows->total; i++)
00943         {
00944                 subwindows->values[i]->dispatch_resize_event(w, h);
00945         }
00946 
00947 // Propagate to user
00948         resize_event(w, h);
00949 
00950         if(window_type == MAIN_WINDOW)
00951         {
00952                 this->w = w;
00953                 this->h = h;
00954         }
00955         return 0;
00956 }
00957 
00958 int BC_WindowBase::dispatch_translation_event()
00959 {
00960         translation_events = 0;
00961         if(window_type == MAIN_WINDOW)
00962         {
00963                 prev_x = x;
00964                 prev_y = y;
00965                 x = last_translate_x;
00966                 y = last_translate_y;
00967 // Correct for window manager offsets
00968                 x -= x_correction;
00969                 y -= y_correction;
00970         }
00971 
00972         for(int i = 0; i < subwindows->total; i++)
00973         {
00974                 subwindows->values[i]->dispatch_translation_event();
00975         }
00976 
00977         translation_event();
00978         return 0;
00979 }
00980 
00981 int BC_WindowBase::dispatch_motion_event()
00982 {
00983         int result = 0;
00984 
00985         if(top_level == this)
00986         {
00987                 event_win = last_motion_win;
00988                 motion_events = 0;
00989 
00990 // Test for grab
00991                 if(get_button_down() && !active_menubar && !active_popup_menu)
00992                 {
00993                         if(!result)
00994                         {
00995                                 cursor_x = last_motion_x;
00996                                 cursor_y = last_motion_y;
00997                                 result = dispatch_drag_motion();
00998                         }
00999 
01000                         if(!result && 
01001                                 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 || 
01002                                 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
01003                         {
01004                                 cursor_x = drag_x;
01005                                 cursor_y = drag_y;
01006 
01007                                 result = dispatch_drag_start();
01008                         }
01009                 }
01010                 cursor_x = last_motion_x;
01011                 cursor_y = last_motion_y;
01012 
01013                 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
01014                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
01015                 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
01016         }
01017 
01018         for(int i = 0; i < subwindows->total && !result; i++)
01019         {
01020                 result = subwindows->values[i]->dispatch_motion_event();
01021         }
01022 
01023         if(!result) result = cursor_motion_event();    // give to user
01024         return result;
01025 }
01026 
01027 int BC_WindowBase::dispatch_keypress_event()
01028 {
01029         int result = 0;
01030         if(top_level == this)
01031         {
01032                 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
01033         }
01034 
01035         for(int i = 0; i < subwindows->total && !result; i++)
01036         {
01037                 result = subwindows->values[i]->dispatch_keypress_event();
01038         }
01039 
01040         if(!result) result = keypress_event();
01041 
01042         return result;
01043 }
01044 
01045 int BC_WindowBase::dispatch_focus_in()
01046 {
01047         for(int i = 0; i < subwindows->total; i++)
01048         {
01049                 subwindows->values[i]->dispatch_focus_in();
01050         }
01051 
01052         focus_in_event();
01053 
01054         return 0;
01055 }
01056 
01057 int BC_WindowBase::dispatch_focus_out()
01058 {
01059         for(int i = 0; i < subwindows->total; i++)
01060         {
01061                 subwindows->values[i]->dispatch_focus_out();
01062         }
01063 
01064         focus_out_event();
01065 
01066         return 0;
01067 }
01068 
01069 int BC_WindowBase::get_has_focus()
01070 {
01071         return top_level->has_focus;
01072 }
01073 
01074 int BC_WindowBase::get_deleting()
01075 {
01076         if(is_deleting) return 1;
01077         if(parent_window && parent_window->get_deleting()) return 1;
01078         return 0;
01079 }
01080 
01081 int BC_WindowBase::dispatch_button_press()
01082 {
01083         int result = 0;
01084         if(top_level == this)
01085         {
01086                 if(active_menubar) result = active_menubar->dispatch_button_press();
01087                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
01088                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
01089         }
01090 
01091         for(int i = 0; i < subwindows->total && !result; i++)
01092         {
01093                 result = subwindows->values[i]->dispatch_button_press();
01094         }
01095 
01096         if(!result) result = button_press_event();
01097 
01098         return result;
01099 }
01100 
01101 int BC_WindowBase::dispatch_button_release()
01102 {
01103         int result = 0;
01104         if(top_level == this)
01105         {
01106                 if(active_menubar) result = active_menubar->dispatch_button_release();
01107 //printf("BC_WindowBase::dispatch_button_release 1 %d\n", result);
01108                 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
01109 //printf("BC_WindowBase::dispatch_button_release 2 %p %d\n", active_subwindow, result);
01110                 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
01111 //printf("BC_WindowBase::dispatch_button_release 3 %d\n", result);
01112                 if(!result && button_number != 4 && button_number != 5)
01113                         result = dispatch_drag_stop();
01114         }
01115 //printf("BC_WindowBase::dispatch_button_release 4 %d\n", result);
01116 
01117         for(int i = 0; i < subwindows->total && !result; i++)
01118         {
01119                 result = subwindows->values[i]->dispatch_button_release();
01120         }
01121 //printf("BC_WindowBase::dispatch_button_release 5 %d\n", result);
01122 
01123         if(!result)
01124         {
01125                 result = button_release_event();
01126         }
01127 //printf("BC_WindowBase::dispatch_button_release 6 %d\n", result);
01128 
01129         return result;
01130 }
01131 
01132 
01133 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
01134 {
01135 
01136 // all repeat event handlers get called and decide based on activity and duration
01137 // whether to respond
01138         for(int i = 0; i < subwindows->total; i++)
01139         {
01140                 subwindows->values[i]->dispatch_repeat_event(duration);
01141         }
01142         repeat_event(duration);
01143 
01144 // Unlock next signal
01145         if(window_type == MAIN_WINDOW)
01146         {
01147                 for(int i = 0; i < repeaters.total; i++)
01148                 {
01149                         if(repeaters.values[i]->delay == duration)
01150                         {
01151                                 repeaters.values[i]->repeat_lock->unlock();
01152                         }
01153                 }
01154         }
01155 
01156         return 0;
01157 }
01158 
01159 int BC_WindowBase::dispatch_cursor_leave()
01160 {
01161         for(int i = 0; i < subwindows->total; i++)
01162         {
01163                 subwindows->values[i]->dispatch_cursor_leave();
01164         }
01165 
01166         cursor_leave_event();
01167         return 0;
01168 }
01169 
01170 int BC_WindowBase::dispatch_cursor_enter()
01171 {
01172         int result = 0;
01173 
01174         if(active_menubar) result = active_menubar->dispatch_cursor_enter();
01175         if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
01176         if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
01177 
01178         for(int i = 0; !result && i < subwindows->total; i++)
01179         {
01180                 result = subwindows->values[i]->dispatch_cursor_enter();
01181         }
01182 
01183         if(!result) result = cursor_enter_event();
01184         return result;
01185 }
01186 
01187 int BC_WindowBase::cursor_enter_event()
01188 {
01189         return 0;
01190 }
01191 
01192 int BC_WindowBase::cursor_leave_event()
01193 {
01194         return 0;
01195 }
01196 
01197 int BC_WindowBase::close_event()
01198 {
01199         set_done(1);
01200         return 1;
01201 }
01202 
01203 int BC_WindowBase::dispatch_drag_start()
01204 {
01205         int result = 0;
01206         if(active_menubar) result = active_menubar->dispatch_drag_start();
01207         if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
01208         if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
01209         
01210         for(int i = 0; i < subwindows->total && !result; i++)
01211         {
01212                 result = subwindows->values[i]->dispatch_drag_start();
01213         }
01214 
01215         if(!result) result = is_dragging = drag_start_event();
01216         return result;
01217 }
01218 
01219 int BC_WindowBase::dispatch_drag_stop()
01220 {
01221         int result = 0;
01222 
01223         for(int i = 0; i < subwindows->total && !result; i++)
01224         {
01225                 result = subwindows->values[i]->dispatch_drag_stop();
01226         }
01227 
01228         if(is_dragging && !result) 
01229         {
01230                 drag_stop_event();
01231                 is_dragging = 0;
01232                 result = 1;
01233         }
01234 
01235         return result;
01236 }
01237 
01238 int BC_WindowBase::dispatch_drag_motion()
01239 {
01240         int result = 0;
01241         for(int i = 0; i < subwindows->total && !result; i++)
01242         {
01243                 result = subwindows->values[i]->dispatch_drag_motion();
01244         }
01245         
01246         if(is_dragging && !result)
01247         {
01248                 drag_motion_event();
01249                 result = 1;
01250         }
01251         
01252         return result;
01253 }
01254 
01255 
01256 
01257 
01258 
01259 int BC_WindowBase::show_tooltip(int w, int h)
01260 {
01261         Window tempwin;
01262 
01263         if(!tooltip_on && get_resources()->tooltips_enabled)
01264         {
01265                 int i, j, x, y;
01266                 top_level->hide_tooltip();
01267 
01268                 tooltip_on = 1;
01269                 if(w < 0)
01270                         w = get_text_width(MEDIUMFONT, tooltip_text);
01271 
01272                 if(h < 0)
01273                         h = get_text_height(MEDIUMFONT, tooltip_text);
01274 
01275                 w += TOOLTIP_MARGIN * 2;
01276                 h += TOOLTIP_MARGIN * 2;
01277 
01278                 XTranslateCoordinates(top_level->display, 
01279                                 win, 
01280                                 top_level->rootwin, 
01281                                 get_w(), 
01282                                 get_h(), 
01283                                 &x, 
01284                                 &y, 
01285                                 &tempwin);
01286                 tooltip_popup = new BC_Popup(top_level, 
01287                                         x,
01288                                         y,
01289                                         w, 
01290                                         h, 
01291                                         get_resources()->tooltip_bg_color);
01292 
01293                 draw_tooltip();
01294                 tooltip_popup->set_font(MEDIUMFONT);
01295                 tooltip_popup->flash();
01296                 tooltip_popup->flush();
01297         }
01298         return 0;
01299 }
01300 
01301 int BC_WindowBase::hide_tooltip()
01302 {
01303         if(subwindows)
01304                 for(int i = 0; i < subwindows->total; i++)
01305                 {
01306                         subwindows->values[i]->hide_tooltip();
01307                 }
01308 
01309         if(tooltip_on)
01310         {
01311                 tooltip_on = 0;
01312                 delete tooltip_popup;
01313                 tooltip_popup = 0;
01314         }
01315         return 0;
01316 }
01317 
01318 int BC_WindowBase::set_tooltip(char *text)
01319 {
01320         strcpy(this->tooltip_text, text);
01321 // Update existing tooltip if it is visible
01322         if(tooltip_on)
01323         {
01324                 draw_tooltip();
01325                 tooltip_popup->flash();
01326         }
01327         return 0;
01328 }
01329 
01330 // signal the event handler to repeat
01331 int BC_WindowBase::set_repeat(int64_t duration)
01332 {
01333         if(duration <= 0)
01334         {
01335                 printf("BC_WindowBase::set_repeat duration=%d\n", duration);
01336                 return 0;
01337         }
01338         if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
01339 
01340 // test repeater database for duplicates
01341         for(int i = 0; i < repeaters.total; i++)
01342         {
01343 // Already exists
01344                 if(repeaters.values[i]->delay == duration)
01345                 {
01346                         repeaters.values[i]->start_repeating();
01347                         return 0;
01348                 }
01349         }
01350 
01351         BC_Repeater *repeater = new BC_Repeater(this, duration);
01352         repeater->initialize();
01353         repeaters.append(repeater);
01354     repeater->start_repeating();
01355         return 0;
01356 }
01357 
01358 int BC_WindowBase::unset_repeat(int64_t duration)
01359 {
01360         if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
01361 
01362         BC_Repeater *repeater = 0;
01363         for(int i = 0; i < repeaters.total; i++)
01364         {
01365                 if(repeaters.values[i]->delay == duration)
01366                 {
01367                         repeaters.values[i]->stop_repeating();
01368                 }
01369         }
01370         return 0;
01371 }
01372 
01373 
01374 int BC_WindowBase::unset_all_repeaters()
01375 {
01376         for(int i = 0; i < repeaters.total; i++)
01377         {
01378                 repeaters.values[i]->stop_repeating();
01379         }
01380         repeaters.remove_all_objects();
01381         return 0;
01382 }
01383 
01384 // long BC_WindowBase::get_repeat_id()
01385 // {
01386 //      return top_level->next_repeat_id++;
01387 // }
01388 
01389 int BC_WindowBase::arm_repeat(int64_t duration)
01390 {
01391         XEvent *event = new XEvent;
01392         XClientMessageEvent *ptr = (XClientMessageEvent*)event;
01393         ptr->type = ClientMessage;
01394         ptr->message_type = RepeaterXAtom;
01395         ptr->format = 32;
01396         ptr->data.l[0] = duration;
01397 
01398 // Couldn't use XSendEvent since it locked up randomly.
01399         put_event(event);
01400 //      XSendEvent(top_level->event_display, 
01401 //              top_level->win, 
01402 //              0, 
01403 //              0, 
01404 //              event);
01405 //      flush();
01406         return 0;
01407 }
01408 
01409 int BC_WindowBase::get_atoms()
01410 {
01411         SetDoneXAtom =  XInternAtom(display, "BC_REPEAT_EVENT", False);
01412         RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
01413         DelWinXAtom =   XInternAtom(display, "WM_DELETE_WINDOW", False);
01414         if(ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False))
01415                 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32, PropModeReplace, (unsigned char *)&DelWinXAtom, True);
01416         return 0;
01417 }
01418 
01419 void BC_WindowBase::init_cursors()
01420 {
01421         arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
01422         cross_cursor = XCreateFontCursor(display, XC_crosshair);
01423         ibeam_cursor = XCreateFontCursor(display, XC_xterm);
01424         vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
01425         hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
01426         move_cursor = XCreateFontCursor(display, XC_fleur);
01427         left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
01428         right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
01429         upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
01430         upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
01431         upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
01432         downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
01433         downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
01434         hourglass_cursor = XCreateFontCursor(display, XC_watch);
01435 }
01436 
01437 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
01438 {
01439         int color_model;
01440         switch(depth)
01441         {
01442                 case 8:
01443                         color_model = BC_RGB8;
01444                         break;
01445                 case 16:
01446                         color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
01447                         break;
01448                 case 24:
01449                         color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
01450                         break;
01451                 case 32:
01452                         color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
01453                         break;
01454         }
01455         return color_model;
01456 }
01457 
01458 int BC_WindowBase::init_colors()
01459 {
01460         total_colors = 0;
01461         current_color_value = current_color_pixel = 0;
01462 
01463 // Get the real depth
01464         char *data = 0;
01465         XImage *ximage;
01466         ximage = XCreateImage(top_level->display, 
01467                                         top_level->vis, 
01468                                         top_level->default_depth, 
01469                                         ZPixmap, 
01470                                         0, 
01471                                         data, 
01472                                         16, 
01473                                         16, 
01474                                         8, 
01475                                         0);
01476         bits_per_pixel = ximage->bits_per_pixel;
01477         XDestroyImage(ximage);
01478 
01479         color_model = evaluate_color_model(client_byte_order, 
01480                 server_byte_order, 
01481                 bits_per_pixel);
01482 // Get the color model
01483         switch(color_model)
01484         {
01485                 case BC_RGB8:
01486                         if(private_color)
01487                         {
01488                                 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
01489                                 create_private_colors();
01490                         }
01491                         else
01492                         {
01493                                 cmap = DefaultColormap(display, screen);
01494                                 create_shared_colors();
01495                         }
01496 
01497                         allocate_color_table();
01498 // No antialiasing
01499                         get_resources()->use_xft = 0;
01500                         break;
01501 
01502                 default:
01503                         cmap = DefaultColormap(display, screen);
01504                         break;
01505         }
01506         return 0;
01507 }
01508 
01509 int BC_WindowBase::create_private_colors()
01510 {
01511         int color;
01512         total_colors = 256;
01513 
01514         for(int i = 0; i < 255; i++)
01515         {
01516                 color = (i & 0xc0) << 16;
01517                 color += (i & 0x38) << 10;
01518                 color += (i & 0x7) << 5;
01519                 color_table[i][0] = color;
01520         }
01521         create_shared_colors();        // overwrite the necessary colors on the table
01522         return 0;
01523 }
01524 
01525 
01526 int BC_WindowBase::create_color(int color)
01527 {
01528         if(total_colors == 256)
01529         {
01530 // replace the closest match with an exact match
01531                 color_table[get_color_rgb8(color)][0] = color;
01532         }
01533         else
01534         {
01535 // add the color to the table
01536                 color_table[total_colors][0] = color;
01537                 total_colors++;
01538         }
01539         return 0;
01540 }
01541 
01542 int BC_WindowBase::create_shared_colors()
01543 {
01544         create_color(BLACK);
01545         create_color(WHITE);   
01546 
01547         create_color(LTGREY);  
01548         create_color(MEGREY);  
01549         create_color(MDGREY);  
01550         create_color(DKGREY);                           
01551 
01552         create_color(LTCYAN);  
01553         create_color(MECYAN);  
01554         create_color(MDCYAN);  
01555         create_color(DKCYAN);  
01556 
01557         create_color(LTGREEN); 
01558         create_color(GREEN);   
01559         create_color(DKGREEN); 
01560 
01561         create_color(LTPINK);  
01562         create_color(PINK);
01563         create_color(RED);     
01564 
01565         create_color(LTBLUE);  
01566         create_color(BLUE);    
01567         create_color(DKBLUE);  
01568 
01569         create_color(LTYELLOW); 
01570         create_color(MEYELLOW); 
01571         create_color(MDYELLOW); 
01572         create_color(DKYELLOW); 
01573 
01574         create_color(LTPURPLE); 
01575         create_color(MEPURPLE); 
01576         create_color(MDPURPLE); 
01577         create_color(DKPURPLE); 
01578 
01579         create_color(FGGREY); 
01580         create_color(MNBLUE);
01581         create_color(ORANGE);
01582         create_color(FTGREY);
01583 
01584         return 0;
01585 }
01586 
01587 int BC_WindowBase::allocate_color_table()
01588 {
01589         int red, green, blue, color;
01590         int result;
01591         XColor col;
01592 
01593         for(int i = 0; i < total_colors; i++)
01594         {
01595                 color = color_table[i][0];
01596                 red = (color & 0xFF0000) >> 16;
01597                 green = (color & 0x00FF00) >> 8;
01598                 blue = color & 0xFF;
01599 
01600                 col.flags = DoRed | DoGreen | DoBlue;
01601                 col.red   = red<<8   | red;
01602                 col.green = green<<8 | green;
01603                 col.blue  = blue<<8  | blue;
01604 
01605                 XAllocColor(display, cmap, &col);
01606                 color_table[i][1] = col.pixel;
01607         }
01608 
01609         XInstallColormap(display, cmap);
01610         return 0;
01611 }
01612 
01613 int BC_WindowBase::init_window_shape()
01614 {
01615         if(bg_pixmap && bg_pixmap->use_alpha()) 
01616         {
01617                 XShapeCombineMask(top_level->display,
01618                 this->win,
01619                 ShapeBounding,
01620                 0,
01621                 0,
01622                 bg_pixmap->get_alpha(),
01623                 ShapeSet);
01624         }
01625         return 0;
01626 }
01627 
01628 
01629 int BC_WindowBase::init_gc()
01630 {
01631         unsigned long gcmask;
01632         gcmask = GCFont | GCGraphicsExposures;
01633 
01634         XGCValues gcvalues;
01635         gcvalues.font = mediumfont->fid;        // set the font
01636         gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
01637         gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
01638         return 0;
01639 }
01640 
01641 int BC_WindowBase::init_fonts()
01642 {
01643         if((largefont = XLoadQueryFont(display, _(resources.large_font))) == NULL &&
01644                 (largefont = XLoadQueryFont(display, _(resources.large_font2))) == NULL) 
01645                 largefont = XLoadQueryFont(display, "fixed"); 
01646 
01647         if((mediumfont = XLoadQueryFont(display, _(resources.medium_font))) == NULL &&
01648                 (mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) == NULL)
01649                 mediumfont = XLoadQueryFont(display, "fixed"); 
01650 
01651         if((smallfont = XLoadQueryFont(display, _(resources.small_font))) == NULL &&
01652                 (smallfont = XLoadQueryFont(display, _(resources.small_font2))) == NULL)
01653                 smallfont = XLoadQueryFont(display, "fixed");
01654 
01655 #ifdef HAVE_XFT
01656         if(get_resources()->use_xft)
01657         {
01658 
01659 
01660 //printf("BC_WindowBase::init_fonts 1 %p %p %s\n", display, screen, resources.large_font_xft);
01661 
01662                 if(!(largefont_xft = XftFontOpenXlfd(display,
01663                     screen,
01664                     resources.large_font_xft)))
01665                 {
01666                         largefont_xft = XftFontOpenXlfd(display,
01667                         screen,
01668                         "fixed");
01669                 }
01670 //printf("BC_WindowBase::init_fonts 1 %p\n", largefont_xft);
01671                 if(!(largefont_xft = XftFontOpenXlfd(display,
01672                     screen,
01673                     resources.large_font_xft)))
01674                 {
01675                         largefont_xft = XftFontOpenXlfd(display,
01676                         screen,
01677                         "fixed");
01678                 }
01679 //printf("BC_WindowBase::init_fonts 2 %p\n", largefont_xft);
01680 
01681 
01682                 if(!(mediumfont_xft = XftFontOpenXlfd(display,
01683                       screen,
01684                       resources.medium_font_xft)))
01685                 {
01686                         mediumfont_xft = XftFontOpenXlfd(display,
01687                         screen,
01688                         "fixed");
01689                 }
01690 
01691 
01692                 if(!(smallfont_xft = XftFontOpenXlfd(display,
01693                       screen,
01694                       resources.small_font_xft)))
01695                 {
01696                           smallfont_xft = XftFontOpenXlfd(display,
01697                           screen,
01698                           "fixed");
01699                 }
01700 
01701 //printf("BC_WindowBase::init_fonts 100 %s %p\n", 
01702 //resources.medium_font, 
01703 //mediumfont_xft);
01704 
01705 printf("BC_WindowBase::init_fonts: %s=%p %s=%p %s=%p\n",
01706         resources.large_font_xft,
01707         largefontset,
01708         resources.medium_font_xft,
01709         mediumfontset,
01710         resources.small_font_xft,
01711         smallfontset);
01712 
01713 // Extension failed to locate fonts
01714                 if(!largefontset || !mediumfontset || !smallfontset)
01715                 {
01716                         printf("BC_WindowBase::init_fonts: no xft fonts found %s=%p %s=%p %s=%p\n",
01717                                 resources.large_font_xft,
01718                                 largefontset,
01719                                 resources.medium_font_xft,
01720                                 mediumfontset,
01721                                 resources.small_font_xft,
01722                                 smallfontset);
01723                         get_resources()->use_xft = 0;
01724                 }
01725         }
01726         else
01727 #endif
01728         if(get_resources()->use_fontset)
01729         {
01730                 char **m, *d;
01731                 int n;
01732 
01733 // FIXME: should check the m,d,n values
01734                 if((largefontset = XCreateFontSet(display, 
01735                         resources.large_fontset,
01736             &m, 
01737                         &n, 
01738                         &d)) == 0)
01739             largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
01740                 if((mediumfontset = XCreateFontSet(display, 
01741                         resources.medium_fontset,
01742             &m, 
01743                         &n, 
01744                         &d)) == 0)
01745             mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
01746                 if((smallfontset = XCreateFontSet(display, 
01747                         resources.small_fontset,
01748             &m, 
01749                         &n, 
01750                         &d)) == 0)
01751             smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
01752 
01753                 if(largefontset && mediumfontset && smallfontset)
01754                 {
01755                         curr_fontset = mediumfontset;
01756                         get_resources()->use_fontset = 1;
01757                 }
01758                 else
01759                 {
01760                         curr_fontset = 0;
01761                         get_resources()->use_fontset = 0;
01762                 }
01763         }
01764 
01765         return 0;
01766 }
01767 
01768 int BC_WindowBase::get_color(int64_t color) 
01769 {
01770 // return pixel of color
01771 // use this only for drawing subwindows not for bitmaps
01772          int i, test, difference, result;
01773 
01774         switch(color_model)
01775         {
01776                 case BC_RGB8:
01777                         if(private_color)
01778                         {
01779                                 return get_color_rgb8(color);
01780                         }
01781                         else
01782                         {
01783 // test last color looked up
01784                                 if(current_color_value == color) return current_color_pixel;
01785 
01786 // look up in table
01787                                 current_color_value = color;
01788                                 for(i = 0; i < total_colors; i++)
01789                                 {
01790                                         if(color_table[i][0] == color)
01791                                         {
01792                                                 current_color_pixel = color_table[i][1];
01793                                                 return current_color_pixel;
01794                                         }
01795                                 }
01796 
01797 // find nearest match
01798                                 difference = 0xFFFFFF;
01799 
01800                                 for(i = 0, result = 0; i < total_colors; i++)
01801                                 {
01802                                         test = abs((int)(color_table[i][0] - color));
01803 
01804                                         if(test < difference) 
01805                                         {
01806                                                 current_color_pixel = color_table[i][1]; 
01807                                                 difference = test;
01808                                         }
01809                                 }
01810 
01811                                 return current_color_pixel;
01812                         }
01813                         break;  
01814 
01815                 case BC_RGB565:
01816                         return get_color_rgb16(color);
01817                         break;
01818 
01819                 case BC_BGR565:
01820                         return get_color_bgr16(color);
01821                         break;
01822 
01823                 case BC_RGB888:
01824                 case BC_BGR888:
01825                         if(client_byte_order == server_byte_order)
01826                                 return color;
01827                         else
01828                                 get_color_bgr24(color);
01829                         break;
01830 
01831                 default:
01832                         return color;
01833                         break;  
01834         }
01835         return 0;
01836 }
01837 
01838 int BC_WindowBase::get_color_rgb8(int color)
01839 {
01840         int pixel;
01841 
01842         pixel = (color & 0xc00000) >> 16;
01843         pixel += (color & 0xe000) >> 10;
01844         pixel += (color & 0xe0) >> 5;
01845         return pixel;
01846 }
01847 
01848 int64_t BC_WindowBase::get_color_rgb16(int color)
01849 {
01850         int64_t result;
01851         result = (color & 0xf80000) >> 8;
01852         result += (color & 0xfc00) >> 5;
01853         result += (color & 0xf8) >> 3;
01854         
01855         return result;
01856 }
01857 
01858 int64_t BC_WindowBase::get_color_bgr16(int color)
01859 {
01860         int64_t result;
01861         result = (color & 0xf80000) >> 19;
01862         result += (color & 0xfc00) >> 5;
01863         result += (color & 0xf8) << 8;
01864 
01865         return result;
01866 }
01867 
01868 int64_t BC_WindowBase::get_color_bgr24(int color)
01869 {
01870         int64_t result;
01871         result = (color & 0xff) << 16;
01872         result += (color & 0xff00);
01873         result += (color & 0xff0000) >> 16;
01874         return result;
01875 }
01876 
01877 int BC_WindowBase::video_is_on()
01878 {
01879         return video_on;
01880 }
01881 
01882 void BC_WindowBase::start_video()
01883 {
01884         video_on = 1;
01885 //      set_color(BLACK);
01886 //      draw_box(0, 0, get_w(), get_h());
01887 //      flash();
01888 }
01889 
01890 void BC_WindowBase::stop_video()
01891 {
01892         video_on = 0;
01893 }
01894 
01895 
01896 
01897 int64_t BC_WindowBase::get_color()
01898 {
01899         return top_level->current_color;
01900 }
01901 
01902 void BC_WindowBase::set_color(int64_t color)
01903 {
01904         top_level->current_color = color;
01905         XSetForeground(top_level->display, 
01906                 top_level->gc, 
01907                 top_level->get_color(color));
01908 }
01909 
01910 void BC_WindowBase::set_opaque()
01911 {
01912         XSetFunction(top_level->display, top_level->gc, GXcopy);
01913 }
01914 
01915 void BC_WindowBase::set_inverse() 
01916 {
01917         XSetFunction(top_level->display, top_level->gc, GXxor);
01918 }
01919 
01920 Cursor BC_WindowBase::get_cursor_struct(int cursor)
01921 {
01922         switch(cursor)
01923         {
01924                 case ARROW_CURSOR:         return top_level->arrow_cursor;                 break;
01925                 case CROSS_CURSOR:         return top_level->cross_cursor;
01926                 case IBEAM_CURSOR:         return top_level->ibeam_cursor;                 break;
01927                 case VSEPARATE_CURSOR:     return top_level->vseparate_cursor;             break;
01928                 case HSEPARATE_CURSOR:     return top_level->hseparate_cursor;             break;
01929                 case MOVE_CURSOR:              return top_level->move_cursor;                  break;
01930                 case LEFT_CURSOR:          return top_level->left_cursor;                  break;
01931                 case RIGHT_CURSOR:         return top_level->right_cursor;                 break;
01932                 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;         break;
01933                 case UPLEFT_RESIZE:        return top_level->upleft_resize_cursor;         break;
01934                 case UPRIGHT_RESIZE:       return top_level->upright_resize_cursor;        break;
01935                 case DOWNLEFT_RESIZE:      return top_level->downleft_resize_cursor;       break;
01936                 case DOWNRIGHT_RESIZE:     return top_level->downright_resize_cursor;      break;
01937                 case HOURGLASS_CURSOR:     return top_level->hourglass_cursor;             break;
01938         }
01939         return 0;
01940 }
01941 
01942 void BC_WindowBase::set_cursor(int cursor, int is_hourglass)
01943 {
01944 // don't change cursor if hourglass mode unless the caller is the hourglass routine.
01945         if(is_hourglass || current_cursor != HOURGLASS_CURSOR)
01946         {
01947                 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
01948                 current_cursor = cursor;
01949                 flush();
01950         }
01951         else
01952 // save new cursor for later
01953         {
01954                 prev_cursor = cursor;
01955         }
01956 }
01957 
01958 void BC_WindowBase::set_x_cursor(int cursor)
01959 {
01960         temp_cursor = XCreateFontCursor(top_level->display, cursor);
01961         XDefineCursor(top_level->display, win, temp_cursor);
01962         current_cursor = cursor;
01963         flush();
01964 }
01965 
01966 int BC_WindowBase::get_cursor()
01967 {
01968         return current_cursor;
01969 }
01970 
01971 void BC_WindowBase::start_hourglass()
01972 {
01973         top_level->start_hourglass_recursive();
01974         top_level->flush();
01975 }
01976 
01977 void BC_WindowBase::stop_hourglass()
01978 {
01979         top_level->stop_hourglass_recursive();
01980         top_level->flush();
01981 }
01982 
01983 void BC_WindowBase::start_hourglass_recursive()
01984 {
01985         if(this == top_level)
01986         {
01987                 hourglass_total++;
01988                 if(current_cursor == HOURGLASS_CURSOR) return;
01989         }
01990 
01991         prev_cursor = current_cursor;
01992         set_cursor(HOURGLASS_CURSOR, 1);
01993         for(int i = 0; i < subwindows->total; i++)
01994         {
01995                 subwindows->values[i]->start_hourglass_recursive();
01996         }
01997 }
01998 
01999 void BC_WindowBase::stop_hourglass_recursive()
02000 {
02001         if(this == top_level)
02002         {
02003                 if(hourglass_total == 0) return;
02004                 hourglass_total--;
02005         }
02006 
02007 // Cause set_cursor to perform change
02008         set_cursor(prev_cursor, 1);
02009         for(int i = 0; i < subwindows->total; i++)
02010         {
02011                 subwindows->values[i]->stop_hourglass_recursive();
02012         }
02013 }
02014 
02015 
02016 
02017 
02018 
02019 
02020 XFontStruct* BC_WindowBase::get_font_struct(int font)
02021 {
02022 // Clear out unrelated flags
02023         if(font & BOLDFACE) font ^= BOLDFACE;
02024         
02025         switch(font)
02026         {
02027                 case MEDIUMFONT: return top_level->mediumfont; break;
02028                 case SMALLFONT:  return top_level->smallfont;  break;
02029                 case LARGEFONT:  return top_level->largefont;  break;
02030         }
02031         return 0;
02032 }
02033 
02034 XFontSet BC_WindowBase::get_fontset(int font)
02035 {
02036         XFontSet fs = 0;
02037 
02038         if(get_resources()->use_fontset)
02039         {
02040                 switch(font)
02041                 {
02042                         case SMALLFONT:  fs = top_level->smallfontset; break;
02043                         case LARGEFONT:  fs = top_level->largefontset; break;
02044                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
02045                 }
02046         }
02047 
02048         return fs;
02049 }
02050 
02051 #ifdef HAVE_XFT
02052 XftFont* BC_WindowBase::get_xft_struct(int font)
02053 {
02054 // Clear out unrelated flags
02055         if(font & BOLDFACE) font ^= BOLDFACE;
02056 
02057         switch(font)
02058         {
02059                 case MEDIUMFONT:   return (XftFont*)top_level->mediumfont_xft; break;
02060                 case SMALLFONT:    return (XftFont*)top_level->smallfont_xft;  break;
02061                 case LARGEFONT:    return (XftFont*)top_level->largefont_xft;  break;
02062         }
02063 
02064         return 0;
02065 }
02066 #endif
02067 
02068 
02069 
02070 
02071 
02072 
02073 
02074 
02075 
02076 
02077 
02078 void BC_WindowBase::set_font(int font)
02079 {
02080         top_level->current_font = font;
02081 
02082 
02083 #ifdef HAVE_XFT
02084         if(get_resources()->use_xft)
02085         {
02086                 ;
02087         }
02088         else
02089 #endif
02090         if(get_resources()->use_fontset)
02091         {
02092                 set_fontset(font);
02093         }
02094 
02095         if(get_font_struct(font))
02096         {
02097                 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
02098         }
02099 
02100         return;
02101 }
02102 
02103 void BC_WindowBase::set_fontset(int font)
02104 {
02105         XFontSet fs = 0;
02106 
02107         if(get_resources()->use_fontset)
02108         {
02109                 switch(font)
02110                 {
02111                         case SMALLFONT:  fs = top_level->smallfontset; break;
02112                         case LARGEFONT:  fs = top_level->largefontset; break;
02113                         case MEDIUMFONT: fs = top_level->mediumfontset; break;
02114                 }
02115         }
02116 
02117         curr_fontset = fs;
02118 }
02119 
02120 
02121 XFontSet BC_WindowBase::get_curr_fontset(void)
02122 {
02123         if(get_resources()->use_fontset)
02124                 return curr_fontset;
02125         return 0;
02126 }
02127 
02128 int BC_WindowBase::get_single_text_width(int font, char *text, int length)
02129 {
02130 #ifdef HAVE_XFT
02131         if(get_resources()->use_xft && get_xft_struct(font))
02132         {
02133                 XGlyphInfo extents;
02134                 XftTextExtents8(top_level->display,
02135                         get_xft_struct(font),
02136                         (FcChar8*)text, 
02137                         length,
02138                         &extents);
02139                 return extents.xOff;
02140         }
02141         else
02142 #endif
02143         if(get_resources()->use_fontset && top_level->get_fontset(font))
02144                 return XmbTextEscapement(top_level->get_fontset(font), text, length);
02145         else
02146         if(get_font_struct(font)) 
02147                 return XTextWidth(get_font_struct(font), text, length);
02148         else
02149         {
02150                 int w = 0;
02151                 switch(font)
02152                 {
02153                         case MEDIUM_7SEGMENT:
02154                                 return get_resources()->medium_7segment[0]->get_w() * length;
02155                                 break;
02156 
02157                         default:
02158                                 return 0;
02159                 }
02160                 return w;
02161         }
02162 }
02163 
02164 int BC_WindowBase::get_text_width(int font, char *text, int length)
02165 {
02166         int i, j, w = 0, line_w = 0;
02167         if(length < 0) length = strlen(text);
02168 
02169         for(i = 0, j = 0; i <= length; i++)
02170         {
02171                 line_w = 0;
02172                 if(text[i] == '\n')
02173                 {
02174                         line_w = get_single_text_width(font, &text[j], i - j);
02175                         j = i + 1;
02176                 }
02177                 else
02178                 if(text[i] == 0)
02179                 {
02180                         line_w = get_single_text_width(font, &text[j], length - j);
02181                 }
02182                 if(line_w > w) w = line_w;
02183         }
02184 
02185         if(i > length && w == 0)
02186         {
02187                 w = get_single_text_width(font, text, length);
02188         }
02189 
02190         return w;
02191 }
02192 
02193 int BC_WindowBase::get_text_ascent(int font)
02194 {
02195 #ifdef HAVE_XFT
02196         if(get_resources()->use_xft && get_xft_struct(font))
02197         {
02198                 XGlyphInfo extents;
02199                 XftTextExtents8(top_level->display,
02200                         get_xft_struct(font),
02201                         (FcChar8*)"O", 
02202                         1,
02203                         &extents);
02204                 return extents.y;
02205         }
02206         else
02207 #endif
02208         if(get_resources()->use_fontset && top_level->get_fontset(font))
02209         {
02210         XFontSetExtents *extents;
02211 
02212         extents = XExtentsOfFontSet(top_level->get_fontset(font));
02213         return -extents->max_logical_extent.y;
02214         }
02215         else
02216         if(get_font_struct(font))
02217                 return top_level->get_font_struct(font)->ascent;
02218         else
02219         switch(font)
02220         {
02221                 case MEDIUM_7SEGMENT:
02222                         return get_resources()->medium_7segment[0]->get_h();
02223                         break;
02224 
02225                 default:
02226                         return 0;
02227         }
02228 }
02229 
02230 int BC_WindowBase::get_text_descent(int font)
02231 {
02232 #ifdef HAVE_XFT
02233         if(get_resources()->use_xft && get_xft_struct(font))
02234         {
02235                 XGlyphInfo extents;
02236                 XftTextExtents8(top_level->display,
02237                         get_xft_struct(font),
02238                         (FcChar8*)"j", 
02239                         1,
02240                         &extents);
02241                 return extents.height - extents.y;
02242         }
02243         else
02244 #endif
02245     if(get_resources()->use_fontset && top_level->get_fontset(font))
02246     {
02247         XFontSetExtents *extents;
02248 
02249         extents = XExtentsOfFontSet(top_level->get_fontset(font));
02250         return (extents->max_logical_extent.height
02251                         + extents->max_logical_extent.y);
02252     }
02253     else
02254         if(get_font_struct(font))
02255                 return top_level->get_font_struct(font)->descent;
02256         else
02257         switch(font)
02258         {
02259                 default:
02260                         return 0;
02261         }
02262 }
02263 
02264 int BC_WindowBase::get_text_height(int font, char *text)
02265 {
02266         if(!text) return get_text_ascent(font) + get_text_descent(font);
02267 
02268 // Add height of lines
02269         int h = 0, i, length = strlen(text);
02270         for(i = 0; i <= length; i++)
02271         {
02272                 if(text[i] == '\n')
02273                         h++;
02274                 else
02275                 if(text[i] == 0)
02276                         h++;
02277         }
02278         return h * (get_text_ascent(font) + get_text_descent(font));
02279 }
02280 
02281 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
02282 {
02283         if(color_model < 0) color_model = top_level->get_color_model();
02284         return new BC_Bitmap(top_level, w, h, color_model);
02285 }
02286 
02287 int BC_WindowBase::accel_available(int color_model, int lock_it)
02288 {
02289         if(window_type != MAIN_WINDOW) 
02290                 return top_level->accel_available(color_model, lock_it);
02291 
02292         int result = 0;
02293 
02294         if(lock_it) lock_window("BC_WindowBase::accel_available");
02295         switch(color_model)
02296         {
02297                 case BC_YUV420P:
02298                         result = grab_port_id(this, color_model);
02299                         if(result >= 0)
02300                         {
02301                                 xvideo_port_id = result;
02302                                 result = 1;
02303                         }
02304                         else
02305                                 result = 0;
02306                         break;
02307 
02308                 case BC_YUV422P:
02309                         result = 0;
02310                         break;
02311 
02312                 case BC_YUV422:
02313 //printf("BC_WindowBase::accel_available 1\n");
02314                         result = grab_port_id(this, color_model);
02315 //printf("BC_WindowBase::accel_available 2 %d\n", result);
02316                         if(result >= 0)
02317                         {
02318                                 xvideo_port_id = result;
02319                                 result = 1;
02320                         }
02321                         else
02322                                 result = 0;
02323 //printf("BC_WindowBase::accel_available 3 %d\n", xvideo_port_id);
02324                         break;
02325 
02326                 default:
02327                         result = 0;
02328                         break;
02329         }
02330 
02331         if(lock_it) unlock_window();
02332 //printf("BC_WindowBase::accel_available %d %d\n", color_model, result);
02333         return result;
02334 }
02335 
02336 
02337 int BC_WindowBase::grab_port_id(BC_WindowBase *window, int color_model)
02338 {
02339         int numFormats, i, j, k;
02340         unsigned int ver, rev, numAdapt, reqBase, eventBase, errorBase;
02341         int port_id = -1;
02342     XvAdaptorInfo *info;
02343     XvImageFormatValues *formats;
02344         int x_color_model;
02345 
02346         if(!get_resources()->use_xvideo) return -1;
02347 
02348 // Translate from color_model to X color model
02349         x_color_model = cmodel_bc_to_x(color_model);
02350 
02351 // Only local server is fast enough.
02352         if(!resources.use_shm) return -1;
02353 
02354 // XV extension is available
02355     if(Success != XvQueryExtension(window->display, 
02356                                   &ver, 
02357                                   &rev, 
02358                                   &reqBase, 
02359                                   &eventBase, 
02360                                   &errorBase))
02361     {
02362                 return -1;
02363     }
02364 
02365 // XV adaptors are available
02366         XvQueryAdaptors(window->display, 
02367                 DefaultRootWindow(window->display), 
02368                 &numAdapt, 
02369                 &info);
02370 
02371         if(!numAdapt)
02372         {
02373                 return -1;
02374         }
02375 
02376 // Get adaptor with desired color model
02377     for(i = 0; i < numAdapt && xvideo_port_id == -1; i++)
02378     {
02379 /* adaptor supports XvImages */
02380                 if(info[i].type & XvImageMask) 
02381                 {  
02382                 formats = XvListImageFormats(window->display, 
02383                                                         info[i].base_id, 
02384                                                         &numFormats);
02385 // for(j = 0; j < numFormats; j++)
02386 //      printf("%08x\n", formats[j].id);
02387 
02388                 for(j = 0; j < numFormats && xvideo_port_id < 0; j++) 
02389                 {
02390 /* this adaptor supports the desired format */
02391                                 if(formats[j].id == x_color_model)
02392                                 {
02393 /* Try to grab a port */
02394                                         for(k = 0; k < info[i].num_ports; k++)
02395                                         {
02396 /* Got a port */
02397                                                 if(Success == XvGrabPort(top_level->display, 
02398                                                         info[i].base_id + k, 
02399                                                         CurrentTime))
02400                                                 {
02401 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
02402                                                         xvideo_port_id = info[i].base_id + k;
02403                                                         break;
02404                                                 }
02405                                         }
02406                                 }
02407                         }
02408                 if(formats) XFree(formats);
02409                 }
02410         }
02411 
02412     XvFreeAdaptorInfo(info);
02413 
02414         return xvideo_port_id;
02415 }
02416 
02417 
02418 int BC_WindowBase::show_window(int flush) 
02419 {
02420         XMapWindow(top_level->display, win); 
02421         if(flush) XFlush(top_level->display);
02422 //      XSync(top_level->display, 0);
02423         hidden = 0; 
02424         return 0;
02425 }
02426 
02427 int BC_WindowBase::hide_window(int flush) 
02428 { 
02429         XUnmapWindow(top_level->display, win); 
02430         if(flush) XFlush(top_level->display);
02431         hidden = 1; 
02432         return 0;
02433 }
02434 
02435 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
02436 {
02437         subwindows->append((BC_SubWindow*)menu_bar);
02438 
02439         menu_bar->parent_window = this;
02440         menu_bar->top_level = this->top_level;
02441         menu_bar->initialize();
02442         return menu_bar;
02443 }
02444 
02445 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
02446 {
02447         subwindows->append(subwindow);
02448 
02449         if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
02450 
02451 // parent window must be set before the subwindow initialization
02452         subwindow->parent_window = this;
02453         subwindow->top_level = this->top_level;
02454 
02455 // Execute derived initialization
02456         subwindow->initialize();
02457         return subwindow;
02458 }
02459 
02460 
02461 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
02462 {
02463         return add_subwindow(subwindow);
02464 }
02465 
02466 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
02467 {
02468         set_opaque();
02469         XSetWindowBackgroundPixmap(top_level->display, win, pixmap);
02470         if(x >= 0)
02471         {
02472                 XClearArea(top_level->display, win, x, y, w, h, 0);
02473         }
02474         else
02475         {
02476                 XClearWindow(top_level->display, win);
02477         }
02478 
02479         if(flush)
02480                 this->flush();
02481         return 0;
02482 }
02483 
02484 int BC_WindowBase::flash(int flush)
02485 {
02486         flash(-1, -1, -1, -1, flush);
02487 }
02488 
02489 void BC_WindowBase::flush()
02490 {
02491         XFlush(top_level->display);
02492 }
02493 
02494 void BC_WindowBase::sync_display()
02495 {
02496         XSync(top_level->display, False);
02497 }
02498 
02499 int BC_WindowBase::get_window_lock()
02500 {
02501         return top_level->window_lock;
02502 }
02503 
02504 int BC_WindowBase::lock_window(char *location) 
02505 {
02506         if(top_level && top_level != this)
02507         {
02508                 top_level->lock_window(location);
02509         }
02510         else
02511         if(top_level)
02512         {
02513                 SET_LOCK(this, title, location);
02514                 XLockDisplay(top_level->display);
02515                 SET_LOCK2
02516                 top_level->window_lock = 1;
02517         }
02518         else
02519         {
02520                 printf("BC_WindowBase::lock_window top_level NULL\n");
02521         }
02522         return 0;
02523 }
02524 
02525 int BC_WindowBase::unlock_window() 
02526 {
02527         if(top_level && top_level != this)
02528         {
02529                 top_level->unlock_window();
02530         }
02531         else
02532         if(top_level)
02533         {
02534                 UNSET_LOCK(this);
02535                 top_level->window_lock = 0;
02536                 XUnlockDisplay(top_level->display);
02537         }
02538         else
02539         {
02540                 printf("BC_WindowBase::unlock_window top_level NULL\n");
02541         }
02542         return 0;
02543 }
02544 
02545 void BC_WindowBase::set_done(int return_value)
02546 {
02547         if(window_type != MAIN_WINDOW)
02548                 top_level->set_done(return_value);
02549         else
02550         if(event_thread)
02551         {
02552                 XEvent *event = new XEvent;
02553                 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
02554 
02555                 event->type = ClientMessage;
02556                 ptr->message_type = SetDoneXAtom;
02557                 ptr->format = 32;
02558                 this->return_value = return_value;
02559 
02560 // May lock up here because XSendEvent doesn't work too well 
02561 // asynchronous with XNextEvent.
02562 // This causes BC_WindowEvents to forward a copy of the event to run_window where 
02563 // it is deleted.
02564                 event_thread->done = 1;
02565                 XSendEvent(display, 
02566                         win, 
02567                         0, 
02568                         0, 
02569                         event);
02570                 flush();
02571                 put_event(event);
02572         }
02573 }
02574 
02575 int BC_WindowBase::get_w()
02576 {
02577         return w;
02578 }
02579 
02580 int BC_WindowBase::get_h()
02581 {
02582         return h;
02583 }
02584 
02585 int BC_WindowBase::get_x()
02586 {
02587         return x;
02588 }
02589 
02590 int BC_WindowBase::get_y()
02591 {
02592         return y;
02593 }
02594 
02595 int BC_WindowBase::get_root_w(int ignore_dualhead, int lock_display)
02596 {
02597         if(lock_display) lock_window("BC_WindowBase::get_root_w");
02598         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
02599         int result = WidthOfScreen(screen_ptr);
02600 // Wider than 16:9, narrower than dual head
02601         if(!ignore_dualhead) if((float)result / HeightOfScreen(screen_ptr) > 1.8) result /= 2;
02602 
02603         if(lock_display) unlock_window();
02604         return result;
02605 }
02606 
02607 int BC_WindowBase::get_root_h(int lock_display)
02608 {
02609         if(lock_display) lock_window("BC_WindowBase::get_root_h");
02610         Screen *screen_ptr = XDefaultScreenOfDisplay(display);
02611         int result = HeightOfScreen(screen_ptr);
02612         if(lock_display) unlock_window();
02613         return result;
02614 }
02615 
02616 // Bottom right corner
02617 int BC_WindowBase::get_x2()
02618 {
02619         return w + x;
02620 }
02621 
02622 int BC_WindowBase::get_y2()
02623 {
02624         return y + h;
02625 }
02626 
02627 int BC_WindowBase::get_video_on()
02628 {
02629         return video_on;
02630 }
02631 
02632 int BC_WindowBase::get_hidden()
02633 {
02634         return top_level->hidden;
02635 }
02636 
02637 int BC_WindowBase::cursor_inside()
02638 {
02639         return (top_level->cursor_x >= 0 && 
02640                         top_level->cursor_y >= 0 && 
02641                         top_level->cursor_x < w && 
02642                         top_level->cursor_y < h);
02643 }
02644 
02645 BC_WindowBase* BC_WindowBase::get_top_level()
02646 {
02647         return top_level;
02648 }
02649 
02650 BC_WindowBase* BC_WindowBase::get_parent()
02651 {
02652         return parent_window;
02653 }
02654 
02655 int BC_WindowBase::get_color_model()
02656 {
02657         return top_level->color_model;
02658 }
02659 
02660 BC_Resources* BC_WindowBase::get_resources()
02661 {
02662         return &BC_WindowBase::resources;
02663 }
02664 
02665 int BC_WindowBase::get_bg_color()
02666 {
02667         return bg_color;
02668 }
02669 
02670 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
02671 {
02672         return bg_pixmap;
02673 }
02674 
02675 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
02676 {
02677         top_level->active_subwindow = subwindow;
02678 }
02679 
02680 int BC_WindowBase::activate()
02681 {
02682         return 0;
02683 }
02684 
02685 int BC_WindowBase::deactivate()
02686 {
02687         if(window_type == MAIN_WINDOW)
02688         {
02689                 if(top_level->active_menubar) top_level->active_menubar->deactivate();
02690                 if(top_level->active_popup_menu) top_level->active_popup_menu->deactivate();
02691                 if(top_level->active_subwindow) top_level->active_subwindow->deactivate();
02692 
02693                 top_level->active_menubar = 0;
02694                 top_level->active_popup_menu = 0;
02695                 top_level->active_subwindow = 0;
02696         }
02697         return 0;
02698 }
02699 
02700 int BC_WindowBase::cycle_textboxes(int amount)
02701 {
02702         int result = 0;
02703         BC_WindowBase *new_textbox = 0;
02704 
02705         if(amount > 0)
02706         {
02707                 BC_WindowBase *first_textbox = 0;
02708                 find_next_textbox(&first_textbox, &new_textbox, result);
02709                 if(!new_textbox) new_textbox = first_textbox;
02710                 
02711         }
02712         else
02713         if(amount < 0)
02714         {
02715                 BC_WindowBase *last_textbox = 0;
02716                 find_prev_textbox(&last_textbox, &new_textbox, result);
02717                 if(!new_textbox) new_textbox = last_textbox;
02718                 
02719         }
02720 
02721         if(new_textbox != active_subwindow)
02722         {
02723                 deactivate();
02724                 new_textbox->activate();
02725         }
02726         
02727         return 0;
02728 }
02729 
02730 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
02731 {
02732 // Search subwindows for textbox
02733         for(int i = 0; i < subwindows->total && result < 2; i++)
02734         {
02735                 BC_WindowBase *test_subwindow = subwindows->values[i];
02736                 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
02737         }
02738 
02739         if(result < 2)
02740         {
02741                 if(uses_text())
02742                 {
02743                         if(!*first_textbox) *first_textbox = this;
02744 
02745                         if(result < 1)
02746                         {
02747                                 if(top_level->active_subwindow == this)
02748                                         result++;
02749                         }
02750                         else
02751                         {
02752                                 result++;
02753                                 *next_textbox = this;
02754                         }
02755                 }
02756         }
02757         return 0;
02758 }
02759 
02760 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
02761 {
02762         if(result < 2)
02763         {
02764                 if(uses_text())
02765                 {
02766                         if(!*last_textbox) *last_textbox = this;
02767 
02768                         if(result < 1)
02769                         {
02770                                 if(top_level->active_subwindow == this)
02771                                         result++;
02772                         }
02773                         else
02774                         {
02775                                 result++;
02776                                 *prev_textbox = this;
02777                         }
02778                 }
02779         }
02780 
02781 // Search subwindows for textbox
02782         for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
02783         {
02784                 BC_WindowBase *test_subwindow = subwindows->values[i];
02785                 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
02786         }
02787         return 0;
02788 }
02789 
02790 BC_Clipboard* BC_WindowBase::get_clipboard()
02791 {
02792         return top_level->clipboard;
02793 }
02794 
02795 int BC_WindowBase::get_relative_cursor_x()
02796 {
02797         int abs_x, abs_y, x, y, win_x, win_y;
02798         unsigned int temp_mask;
02799         Window temp_win;
02800 
02801         XQueryPointer(top_level->display, 
02802            top_level->win, 
02803            &temp_win, 
02804            &temp_win,
02805        &abs_x, 
02806            &abs_y, 
02807            &win_x, 
02808            &win_y, 
02809            &temp_mask);
02810 
02811         XTranslateCoordinates(top_level->display, 
02812                         top_level->rootwin, 
02813                         win, 
02814                         abs_x, 
02815                         abs_y, 
02816                         &x, 
02817                         &y, 
02818                         &temp_win);
02819 
02820         return x;
02821 }
02822 
02823 int BC_WindowBase::get_relative_cursor_y()
02824 {
02825         int abs_x, abs_y, x, y, win_x, win_y;
02826         unsigned int temp_mask;
02827         Window temp_win;
02828 
02829         XQueryPointer(top_level->display, 
02830            top_level->win, 
02831            &temp_win, 
02832            &temp_win,
02833        &abs_x, 
02834            &abs_y, 
02835            &win_x, 
02836            &win_y, 
02837            &temp_mask);
02838 
02839         XTranslateCoordinates(top_level->display, 
02840                         top_level->rootwin, 
02841                         win, 
02842                         abs_x, 
02843                         abs_y, 
02844                         &x, 
02845                         &y, 
02846                         &temp_win);
02847 
02848         return y;
02849 }
02850 
02851 int BC_WindowBase::get_abs_cursor_x(int lock_window)
02852 {
02853         int abs_x, abs_y, win_x, win_y;
02854         unsigned int temp_mask;
02855         Window temp_win;
02856 
02857 SET_TRACE
02858         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_x");
02859 SET_TRACE
02860         XQueryPointer(top_level->display, 
02861                 top_level->win, 
02862                 &temp_win, 
02863                 &temp_win,
02864                 &abs_x, 
02865                 &abs_y, 
02866                 &win_x, 
02867                 &win_y, 
02868                 &temp_mask);
02869 SET_TRACE
02870         if(lock_window) this->unlock_window();
02871 SET_TRACE
02872         return abs_x;
02873 }
02874 
02875 int BC_WindowBase::get_abs_cursor_y(int lock_window)
02876 {
02877         int abs_x, abs_y, win_x, win_y;
02878         unsigned int temp_mask;
02879         Window temp_win;
02880 
02881         if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor_y");
02882         XQueryPointer(top_level->display, 
02883                 top_level->win, 
02884                 &temp_win, 
02885                 &temp_win,
02886         &abs_x, 
02887                 &abs_y, 
02888                 &win_x, 
02889                 &win_y, 
02890                 &temp_mask);
02891         if(lock_window) this->unlock_window();
02892         return abs_y;
02893 }
02894 
02895 int BC_WindowBase::match_window(Window win) 
02896 {
02897         if (this->win == win) return 1;
02898         int result = 0;
02899         for(int i = 0; i < subwindows->total; i++)
02900         {
02901                 result = subwindows->values[i]->match_window(win);
02902                 if (result) return result;
02903         }
02904         return 0;
02905 
02906 }
02907 
02908 int BC_WindowBase::get_cursor_over_window()
02909 {
02910         if(top_level != this) return top_level->get_cursor_over_window();
02911 
02912         int abs_x, abs_y, win_x, win_y;
02913         unsigned int temp_mask;
02914         Window temp_win1, temp_win2;
02915 
02916         if (!XQueryPointer(display, 
02917                 win, 
02918                 &temp_win1, 
02919                 &temp_win2,
02920                 &abs_x, 
02921                 &abs_y, 
02922                 &win_x, 
02923                 &win_y, 
02924                 &temp_mask))
02925                 return 0;
02926 
02927         int result = match_window(temp_win2)    ;
02928         return result;
02929 }
02930 
02931 int BC_WindowBase::relative_cursor_x(BC_WindowBase *pov)
02932 {
02933         int x, y;
02934         Window tempwin;
02935 
02936         translate_coordinates(top_level->event_win, 
02937                 pov->win,
02938                 top_level->cursor_x,
02939                 top_level->cursor_y,
02940                 &x,
02941                 &y);
02942         return x;
02943 }
02944 
02945 int BC_WindowBase::relative_cursor_y(BC_WindowBase *pov)
02946 {
02947         int x, y;
02948         Window tempwin;
02949 
02950         translate_coordinates(top_level->event_win, 
02951                 pov->win,
02952                 top_level->cursor_x,
02953                 top_level->cursor_y,
02954                 &x,
02955                 &y);
02956         return y;
02957 }
02958 
02959 int BC_WindowBase::get_drag_x()
02960 {
02961         return top_level->drag_x;
02962 }
02963 
02964 int BC_WindowBase::get_drag_y()
02965 {
02966         return top_level->drag_y;
02967 }
02968 
02969 int BC_WindowBase::get_cursor_x()
02970 {
02971         return top_level->cursor_x;
02972 }
02973 
02974 int BC_WindowBase::get_cursor_y()
02975 {
02976         return top_level->cursor_y;
02977 }
02978 
02979 int BC_WindowBase::is_event_win()
02980 {
02981         return this->win == top_level->event_win;
02982 }
02983 
02984 void BC_WindowBase::set_dragging(int value)
02985 {
02986         is_dragging = value;
02987 }
02988 
02989 int BC_WindowBase::get_dragging()
02990 {
02991         return is_dragging;
02992 }
02993 
02994 int BC_WindowBase::get_buttonpress()
02995 {
02996         return top_level->button_number;
02997 }
02998 
02999 int BC_WindowBase::get_button_down()
03000 {
03001         return top_level->button_down;
03002 }
03003 
03004 int BC_WindowBase::alt_down()
03005 {
03006         return top_level->alt_mask;
03007 }
03008 
03009 int BC_WindowBase::shift_down()
03010 {
03011         return top_level->shift_mask;
03012 }
03013 
03014 int BC_WindowBase::ctrl_down()
03015 {
03016         return top_level->ctrl_mask;
03017 }
03018 
03019 
03020 int BC_WindowBase::get_keypress()
03021 {
03022         return top_level->key_pressed;
03023 }
03024 
03025 int BC_WindowBase::get_double_click()
03026 {
03027         return top_level->double_click;
03028 }
03029 
03030 int BC_WindowBase::get_bgcolor()
03031 {
03032         return bg_color;
03033 }
03034 
03035 int BC_WindowBase::resize_window(int w, int h)
03036 {
03037         if(window_type == MAIN_WINDOW && !allow_resize)
03038         {
03039                 XSizeHints size_hints;
03040                 size_hints.flags = PSize | PMinSize | PMaxSize;
03041                 size_hints.width = w;
03042                 size_hints.height = h;
03043                 size_hints.min_width = w;
03044                 size_hints.max_width = w; 
03045                 size_hints.min_height = h;
03046                 size_hints.max_height = h; 
03047                 XSetNormalHints(top_level->display, win, &size_hints);
03048         }
03049         XResizeWindow(top_level->display, win, w, h);
03050 
03051         this->w = w;
03052         this->h = h;
03053         XFreePixmap(top_level->display, pixmap);
03054         pixmap = XCreatePixmap(top_level->display, win, w, h, top_level->default_depth);
03055 
03056 // Propagate to menubar
03057         for(int i = 0; i < subwindows->total; i++)
03058         {
03059                 subwindows->values[i]->dispatch_resize_event(w, h);
03060         }
03061 
03062         draw_background(0, 0, w, h);
03063         if(top_level == this && get_resources()->recursive_resizing)
03064                 resize_history.append(new BC_ResizeCall(w, h));
03065         return 0;
03066 }
03067 
03068 // The only way for resize events to be propagated is by updating the internal w and h
03069 int BC_WindowBase::resize_event(int w, int h)
03070 {
03071         if(window_type == MAIN_WINDOW)
03072         {
03073                 this->w = w;
03074                 this->h = h;
03075         }
03076         return 0;
03077 }
03078 
03079 int BC_WindowBase::reposition_widget(int x, int y, int w, int h) 
03080 {
03081   return(reposition_window(x, y, w, h));
03082 }
03083 
03084 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
03085 {
03086         int resize = 0;
03087 
03088 // Some tools set their own dimensions before calling this, causing the 
03089 // resize check to skip.
03090         this->x = x;
03091         this->y = y;
03092 
03093         if(w > 0 && w != this->w)
03094         {
03095                 resize = 1;
03096                 this->w = w;
03097         }
03098 
03099         if(h > 0 && h != this->h)
03100         {
03101                 resize = 1;
03102                 this->h = h;
03103         }
03104 
03105 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
03106 
03107         if(this->w <= 0)
03108                 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
03109         if(this->h <= 0)
03110                 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
03111 
03112         if(translation_count && window_type == MAIN_WINDOW)
03113         {
03114 // KDE shifts window right and down.
03115 // FVWM leaves window alone and adds border around it.
03116                 XMoveResizeWindow(top_level->display, 
03117                         win, 
03118                         x + BC_DisplayInfo::left_border - BC_DisplayInfo::auto_reposition_x, 
03119                         y + BC_DisplayInfo::top_border - BC_DisplayInfo::auto_reposition_y, 
03120                         this->w,
03121                         this->h);
03122         }
03123         else
03124         {
03125                 XMoveResizeWindow(top_level->display, 
03126                         win, 
03127                         x, 
03128                         y, 
03129                         this->w, 
03130                         this->h);
03131         }
03132 
03133         if(resize)
03134         {
03135                 XFreePixmap(top_level->display, pixmap);
03136                 pixmap = XCreatePixmap(top_level->display, 
03137                         win, 
03138                         this->w, 
03139                         this->h, 
03140                         top_level->default_depth);
03141 
03142 // Propagate to menubar
03143                 for(int i = 0; i < subwindows->total; i++)
03144                 {
03145                         subwindows->values[i]->dispatch_resize_event(this->w, this->h);
03146                 }
03147 
03148 //              draw_background(0, 0, w, h);
03149         }
03150 
03151         return 0;
03152 }
03153 
03154 int BC_WindowBase::set_tooltips(int tooltips_enabled)
03155 {
03156         get_resources()->tooltips_enabled = tooltips_enabled;
03157         return 0;
03158 }
03159 
03160 int BC_WindowBase::raise_window(int do_flush)
03161 {
03162         XRaiseWindow(top_level->display, win);
03163         if(do_flush) XFlush(top_level->display);
03164         return 0;
03165 }
03166 
03167 void BC_WindowBase::set_background(VFrame *bitmap)
03168 {
03169         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
03170 
03171         bg_pixmap = new BC_Pixmap(this, 
03172                         bitmap, 
03173                         PIXMAP_OPAQUE);
03174         shared_bg_pixmap = 0;
03175         draw_background(0, 0, w, h);
03176 }
03177 
03178 void BC_WindowBase::set_title(char *text)
03179 {
03180         XSetStandardProperties(top_level->display, top_level->win, text, text, None, 0, 0, 0); 
03181         strcpy(this->title, _(text));
03182         flush();
03183 }
03184 
03185 char* BC_WindowBase::get_title()
03186 {
03187         return title;
03188 }
03189 
03190 int BC_WindowBase::get_toggle_value()
03191 {
03192         return toggle_value;
03193 }
03194 
03195 int BC_WindowBase::get_toggle_drag()
03196 {
03197         return toggle_drag;
03198 }
03199 
03200 int BC_WindowBase::set_icon(VFrame *data)
03201 {
03202         if(icon_pixmap) delete icon_pixmap;
03203         icon_pixmap = new BC_Pixmap(top_level, 
03204                 data, 
03205                 PIXMAP_ALPHA,
03206                 1);
03207 
03208         icon_window = new BC_Popup(this, 
03209                 (int)BC_INFINITY, 
03210                 (int)BC_INFINITY, 
03211                 icon_pixmap->get_w(), 
03212                 icon_pixmap->get_h(), 
03213                 -1, 
03214                 1, // All windows are hidden initially
03215                 icon_pixmap);
03216 
03217         XWMHints wm_hints;
03218         wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
03219         wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
03220         wm_hints.icon_mask = icon_pixmap->get_alpha();
03221         wm_hints.icon_window = icon_window->win;
03222         wm_hints.window_group = XGroupLeader;
03223 
03224 // for(int i = 0; i < 1000; i++)
03225 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
03226 // printf("\n");
03227 
03228         XSetWMHints(top_level->display, top_level->win, &wm_hints);
03229         XSync(top_level->display, 0);
03230         return 0;
03231 }
03232 
03233 int BC_WindowBase::set_w(int w)
03234 {
03235         this->w = w;
03236         return 0;
03237 }
03238 
03239 int BC_WindowBase::set_h(int h)
03240 {
03241         this->h = h;
03242         return 0;
03243 }
03244 
03245 int BC_WindowBase::load_defaults(Defaults *defaults)
03246 {
03247         BC_Resources *resources = get_resources();
03248         char string[BCTEXTLEN];
03249         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
03250         {
03251                 sprintf(string, "FILEBOX_HISTORY%d", i);
03252                 resources->filebox_history[i][0] = 0;
03253                 defaults->get(string, resources->filebox_history[i]);
03254         }
03255         resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
03256         resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
03257         resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
03258         defaults->get("FILEBOX_FILTER", resources->filebox_filter);
03259         return 0;
03260 }
03261 
03262 int BC_WindowBase::save_defaults(Defaults *defaults)
03263 {
03264         BC_Resources *resources = get_resources();
03265         char string[BCTEXTLEN];
03266         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
03267         {
03268                 sprintf(string, "FILEBOX_HISTORY%d", i);
03269                 defaults->update(string, resources->filebox_history[i]);
03270         }
03271         defaults->update("FILEBOX_MODE", resources->filebox_mode);
03272         defaults->update("FILEBOX_W", resources->filebox_w);
03273         defaults->update("FILEBOX_H", resources->filebox_h);
03274         defaults->update("FILEBOX_FILTER", resources->filebox_filter);
03275         return 0;
03276 }
03277 
03278 
03279 
03280 // For some reason XTranslateCoordinates can take a long time to return.
03281 // We work around this by only calling it when the event windows are different.
03282 void BC_WindowBase::translate_coordinates(Window src_w, 
03283                 Window dest_w,
03284                 int src_x,
03285                 int src_y,
03286                 int *dest_x_return,
03287                 int *dest_y_return)
03288 {
03289         Window tempwin = 0;
03290 //Timer timer;
03291 //timer.update();
03292         if(src_w == dest_w)
03293         {
03294                 *dest_x_return = src_x;
03295                 *dest_y_return = src_y;
03296         }
03297         else
03298         {
03299                 XTranslateCoordinates(top_level->display, 
03300                         src_w, 
03301                         dest_w, 
03302                         src_x, 
03303                         src_y, 
03304                         dest_x_return, 
03305                         dest_y_return,
03306                         &tempwin);
03307 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
03308         }
03309 }
03310 
03311 
03312 
03313 
03314 
03315 
03316 
03317 #ifdef HAVE_LIBXXF86VM
03318 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
03319 {
03320    int foo,bar;
03321    *vm = 0;
03322    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
03323            int vm_count,i;
03324            XF86VidModeModeInfo **vm_modelines;
03325            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
03326            for (i = 0; i < vm_count; i++) {
03327                    if (vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay && vm_modelines[i]->hdisplay >= *width)
03328                            *vm = i;
03329            }
03330            display = top_level->display;
03331            if (vm_modelines[*vm]->hdisplay == *width)
03332                    *vm = -1;
03333            else
03334            {
03335                    *width = vm_modelines[*vm]->hdisplay;
03336                    *height = vm_modelines[*vm]->vdisplay;
03337            }
03338    }
03339 }
03340 
03341 void BC_WindowBase::scale_vm(int vm)
03342 {
03343    int foo,bar,dotclock;
03344    if(XF86VidModeQueryExtension(top_level->display,&foo,&bar))
03345    {
03346            int vm_count;
03347            XF86VidModeModeInfo **vm_modelines;
03348            XF86VidModeModeLine vml;
03349            XF86VidModeGetAllModeLines(top_level->display,XDefaultScreen(top_level->display),&vm_count,&vm_modelines);
03350            XF86VidModeGetModeLine(top_level->display,XDefaultScreen(top_level->display),&dotclock,&vml);
03351            orig_modeline.dotclock = dotclock;
03352            orig_modeline.hdisplay = vml.hdisplay;
03353            orig_modeline.hsyncstart = vml.hsyncstart;
03354            orig_modeline.hsyncend = vml.hsyncend;
03355            orig_modeline.htotal = vml.htotal;
03356            orig_modeline.vdisplay = vml.vdisplay;
03357            orig_modeline.vsyncstart = vml.vsyncstart;
03358            orig_modeline.vsyncend = vml.vsyncend;
03359            orig_modeline.vtotal = vml.vtotal;
03360            orig_modeline.flags = vml.flags;
03361            orig_modeline.privsize = vml.privsize;
03362            // orig_modeline.private = vml.private;
03363            XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
03364            XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
03365            XFlush(top_level->display);
03366    }
03367 }
03368 
03369 void BC_WindowBase::restore_vm()
03370 {
03371    XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
03372    XFlush(top_level->display);
03373 }
03374 
03375 
03376 #endif
03377 
03378 
03379 #ifdef HAVE_GL
03380 
03381 extern "C"
03382 {
03383         GLXContext glXCreateContext(Display *dpy,
03384                                XVisualInfo *vis,
03385                                GLXContext shareList,
03386                                int direct);
03387         
03388         int glXMakeCurrent(Display *dpy,
03389                        Drawable drawable,
03390                        GLXContext ctx);
03391 
03392         void glXSwapBuffers(Display *dpy,
03393                        Drawable drawable);
03394 };
03395 
03396 
03397 
03398 void BC_WindowBase::enable_opengl()
03399 {
03400         lock_window("BC_WindowBase::enable_opengl");
03401         opengl_lock.lock();
03402 
03403         XVisualInfo viproto;
03404         XVisualInfo *visinfo;
03405         int nvi;
03406 
03407         viproto.screen = top_level->screen;
03408         visinfo = XGetVisualInfo(top_level->display,
03409         VisualScreenMask,
03410         &viproto,
03411         &nvi);
03412 
03413         gl_context = glXCreateContext(top_level->display,
03414                 visinfo,
03415                 0,
03416                 1);
03417 
03418         glXMakeCurrent(top_level->display,
03419                 win,
03420                 gl_context);
03421 
03422 // Need expose events for 3D
03423         unsigned long valuemask = CWEventMask;
03424         XSetWindowAttributes attributes;
03425         attributes.event_mask = DEFAULT_EVENT_MASKS |
03426                         ExposureMask;
03427         XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
03428 
03429         opengl_lock.unlock();
03430         unlock_window();
03431 }
03432 
03433 void BC_WindowBase::disable_opengl()
03434 {
03435         unsigned long valuemask = CWEventMask;
03436         XSetWindowAttributes attributes;
03437         attributes.event_mask = DEFAULT_EVENT_MASKS;
03438         XChangeWindowAttributes(top_level->display, win, valuemask, &attributes);
03439 }
03440 
03441 void BC_WindowBase::lock_opengl()
03442 {
03443         lock_window("BC_WindowBase::lock_opengl");
03444         opengl_lock.lock();
03445         glXMakeCurrent(top_level->display,
03446                 win,
03447                 gl_context);
03448 }
03449 
03450 void BC_WindowBase::unlock_opengl()
03451 {
03452         opengl_lock.unlock();
03453         unlock_window();
03454 }
03455 
03456 void BC_WindowBase::flip_opengl()
03457 {
03458         glXSwapBuffers(top_level->display, win);
03459 }
03460 #endif
03461 
03462 int BC_WindowBase::get_event_count()
03463 {
03464         event_lock->lock("BC_WindowBase::get_event_count");
03465         int result = common_events.total;
03466         event_lock->unlock();
03467         return result;
03468 }
03469 
03470 XEvent* BC_WindowBase::get_event()
03471 {
03472         XEvent *result = 0;
03473         while(!done && !result)
03474         {
03475                 event_condition->lock("BC_WindowBase::get_event");
03476                 event_lock->lock("BC_WindowBase::get_event");
03477 
03478                 if(common_events.total && !done)
03479                 {
03480                         result = common_events.values[0];
03481                         common_events.remove_number(0);
03482                 }
03483 
03484                 event_lock->unlock();
03485         }
03486         return result;
03487 }
03488 
03489 void BC_WindowBase::put_event(XEvent *event)
03490 {
03491         event_lock->lock("BC_WindowBase::put_event");
03492         common_events.append(event);
03493         event_lock->unlock();
03494         event_condition->unlock();
03495 }
03496 
03497 
03498 
03499 
03500 
03501 
03502 

Generated on Sun Jan 8 13:26:34 2006 for Guicast-svn by  doxygen 1.4.4