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 }