• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files

hvirtual/guicast/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 "bcsynchronous.h"
00013 #include "bctimer.h"
00014 #include "bcwidgetgrid.h"
00015 #include "bcwindowbase.h"
00016 #include "bcwindowevents.h"
00017 #include "colormodels.h"
00018 #include "colors.h"
00019 #include "condition.h"
00020 #include "cursors.h"
00021 #include "bchash.h"
00022 #include "fonts.h"
00023 #include "keys.h"
00024 #include "language.h"
00025 #include "mutex.h"
00026 #include "sizes.h"
00027 #include "vframe.h"
00028 
00029 #ifdef HAVE_GL
00030 #include <GL/gl.h>
00031 #endif
00032 #include <string.h>
00033 #include <unistd.h>
00034 
00035 #include <X11/extensions/Xvlib.h>
00036 #include <X11/extensions/shape.h>
00037 
00038 
00039 BC_ResizeCall::BC_ResizeCall(int w, int h)
00040 {
00041         this->w = w;
00042         this->h = h;
00043 }
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 BC_Resources BC_WindowBase::resources;
00056 
00057 Window XGroupLeader = 0;
00058 
00059 BC_WindowBase::BC_WindowBase()
00060 {
00061 //printf("BC_WindowBase::BC_WindowBase 1\n");
00062         BC_WindowBase::initialize();
00063 }
00064 
00065 BC_WindowBase::~BC_WindowBase()
00066 {
00067 #ifdef HAVE_LIBXXF86VM
00068    if(window_type == VIDMODE_SCALED_WINDOW && vm_switched)
00069    {
00070            restore_vm();   
00071    }
00072 #endif
00073 
00074         hide_tooltip();
00075         if(window_type != MAIN_WINDOW)
00076         {
00077                 if(top_level->active_menubar == this) top_level->active_menubar = 0;
00078                 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
00079                 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
00080 // Remove pointer from parent window to this
00081                 parent_window->subwindows->remove(this);
00082         }
00083 
00084 
00085 // Delete the subwindows
00086         is_deleting = 1;
00087         if(subwindows)
00088         {
00089                 while(subwindows->total)
00090                 {
00091 // Subwindow removes its own pointer
00092                         delete subwindows->values[0];
00093                 }
00094                 delete subwindows;
00095         }
00096 
00097         if(widgetgrids)
00098         {
00099                 while (widgetgrids->total) 
00100                 {
00101                         delete widgetgrids->last();
00102                         widgetgrids->remove();
00103                 }
00104                 delete widgetgrids;
00105         }
00106                 
00107 
00108         delete pixmap;
00109 
00110 // Destroyed in synchronous thread if gl context exists.
00111 #ifdef HAVE_GL
00112         if(!gl_win_context || !get_resources()->get_synchronous())
00113 #endif
00114                 XDestroyWindow(top_level->display, win);
00115 
00116         if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
00117         if(icon_pixmap) delete icon_pixmap;
00118         if(temp_bitmap) delete temp_bitmap;
00119 
00120 
00121 
00122 
00123 
00124         if(window_type == MAIN_WINDOW) 
00125         {
00126                 XFreeGC(display, gc);
00127 #ifdef HAVE_XFT
00128                 if(largefont_xft) 
00129                         XftFontClose (display, (XftFont*)largefont_xft);
00130                 if(mediumfont_xft) 
00131                         XftFontClose (display, (XftFont*)mediumfont_xft);
00132                 if(smallfont_xft) 
00133                         XftFontClose (display, (XftFont*)smallfont_xft);
00134 #endif
00135                 flush();
00136 // Can't close display if another thread is waiting for events.
00137 // Synchronous thread must delete display if gl_context exists.
00138 #ifdef HAVE_GL
00139                 if(!gl_win_context || !get_resources()->get_synchronous())
00140 #endif
00141                         XCloseDisplay(display);
00142                 clipboard->stop_clipboard();
00143                 delete clipboard;
00144         }
00145         else
00146         {
00147                 flush();
00148         }
00149 
00150 // Must be last reference to display.
00151 // This only works if it's a MAIN_WINDOW since the display deletion for
00152 // a subwindow is not determined by the subwindow.
00153 #ifdef HAVE_GL
00154         if(gl_win_context && get_resources()->get_synchronous())
00155         {
00156                 printf("BC_WindowBase::~BC_WindowBase window deleted but opengl deletion is not\n"
00157                         "implemented for BC_Pixmap.\n");
00158                 get_resources()->get_synchronous()->delete_window(this);
00159         }
00160 #endif
00161 
00162         resize_history.remove_all_objects();
00163         common_events.remove_all_objects();
00164         delete event_lock;
00165         delete event_condition;
00166 
00167         UNSET_ALL_LOCKS(this)
00168 }
00169 
00170 int BC_WindowBase::initialize()
00171 {
00172         test_keypress = 0;
00173         is_deleting = 0;
00174         window_lock = 0;
00175         x = 0; 
00176         y = 0; 
00177         w = 0; 
00178         h = 0;
00179         bg_color = -1;
00180         top_level = 0;
00181         parent_window = 0;
00182         subwindows = 0;
00183         widgetgrids = 0;
00184         xvideo_port_id = -1;
00185         video_on = 0;
00186         motion_events = 0;
00187         resize_events = 0;
00188         translation_events = 0;
00189         ctrl_mask = shift_mask = alt_mask = 0;
00190         cursor_x = cursor_y = button_number = 0;
00191         button_down = 0;
00192         button_pressed = 0;
00193         button_time1 = button_time2 = 0;
00194         double_click = 0;
00195         last_motion_win = 0;
00196         key_pressed = 0;
00197         active_menubar = 0;
00198         active_popup_menu = 0;
00199         active_subwindow = 0;
00200         pixmap = 0;
00201         bg_pixmap = 0;
00202         tooltip_text[0] = 0;
00203         persistant_tooltip = 0;
00204 //      next_repeat_id = 0;
00205         tooltip_popup = 0;
00206         tooltip_done = 0;
00207         current_font = MEDIUMFONT;
00208         current_color = BLACK;
00209         current_cursor = ARROW_CURSOR;
00210         hourglass_total = 0;
00211         is_dragging = 0;
00212         shared_bg_pixmap = 0;
00213         icon_pixmap = 0;
00214         window_type = MAIN_WINDOW;
00215         translation_count = 0;
00216         x_correction = y_correction = 0;
00217         temp_bitmap = 0;
00218         tooltip_on = 0;
00219         temp_cursor = 0;
00220         toggle_value = 0;
00221         toggle_drag = 0;
00222         has_focus = 0;
00223         is_hourglass = 0;
00224         is_transparent = 0;
00225 #ifdef HAVE_LIBXXF86VM
00226     vm_switched = 0;
00227 #endif
00228         largefont_xft = 0;
00229         mediumfont_xft = 0;
00230         smallfont_xft = 0;
00231 // Need these right away since put_event is called before run_window sometimes.
00232         event_lock = new Mutex("BC_WindowBase::event_lock");
00233         event_condition = new Condition(0, "BC_WindowBase::event_condition");
00234         cursor_timer = new Timer;
00235         event_thread = 0;
00236 #ifdef HAVE_GL
00237         gl_win_context = 0;
00238 #endif
00239 
00240         return 0;
00241 }
00242 
00243 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
00244                         LeaveWindowMask | \
00245                         ButtonPressMask | \
00246                         ButtonReleaseMask | \
00247                         PointerMotionMask | \
00248                         FocusChangeMask
00249                         
00250 
00251 int BC_WindowBase::create_window(BC_WindowBase *parent_window,
00252                                 char *title, 
00253                                 int x,
00254                                 int y,
00255                                 int w, 
00256                                 int h, 
00257                                 int minw, 
00258                                 int minh, 
00259                                 int allow_resize,
00260                                 int private_color, 
00261                                 int hide,
00262                                 int bg_color,
00263                                 char *display_name,
00264                                 int window_type,
00265                                 BC_Pixmap *bg_pixmap,
00266                                 int group_it)
00267 {
00268         XSetWindowAttributes attr;
00269         unsigned long mask;
00270         XSizeHints size_hints;
00271         int root_w;
00272         int root_h;
00273 #ifdef HAVE_LIBXXF86VM
00274     int vm;
00275 #endif
00276 
00277         id = get_resources()->get_id();
00278 
00279 
00280         get_resources()->create_window_lock->lock("BC_WindowBase::create_window");
00281 
00282     if(parent_window) top_level = parent_window->top_level;
00283 
00284 #ifdef HAVE_LIBXXF86VM
00285     if(window_type == VIDMODE_SCALED_WINDOW)
00286             closest_vm(&vm,&w,&h);
00287 #endif
00288 
00289         this->x = x;
00290         this->y = y;
00291         this->w = w;
00292         this->h = h;
00293         this->bg_color = bg_color;
00294         this->window_type = window_type;
00295         this->hidden = hide;
00296         this->private_color = private_color;
00297         this->parent_window = parent_window;
00298         this->bg_pixmap = bg_pixmap;
00299         this->allow_resize = allow_resize;
00300         strcpy(this->title, _(title));
00301         if(bg_pixmap) shared_bg_pixmap = 1;
00302 
00303         if(parent_window) top_level = parent_window->top_level;
00304 
00305         subwindows = new BC_SubWindowList;
00306         widgetgrids = new BC_WidgetGridList;
00307 
00308 // Mandatory setup
00309         if(window_type == MAIN_WINDOW)
00310         {
00311                 top_level = this;
00312                 parent_window = this;
00313 
00314 // This function must be the first Xlib
00315 // function a multi-threaded program calls
00316                 XInitThreads();
00317 
00318 
00319 // get the display connection
00320                 display = init_display(display_name);
00321 //              event_display = init_display(display_name);
00322 
00323 // Fudge window placement
00324                 root_w = get_root_w(1, 0);
00325                 root_h = get_root_h(0);
00326                 if(this->x + this->w > root_w) this->x = root_w - this->w;
00327                 if(this->y + this->h > root_h) this->y = root_h - this->h;
00328                 if(this->x < 0) this->x = 0;
00329                 if(this->y < 0) this->y = 0;
00330                 screen = DefaultScreen(display);
00331                 rootwin = RootWindow(display, screen);
00332 
00333 
00334                 vis = DefaultVisual(display, screen);
00335                 default_depth = DefaultDepth(display, screen);
00336 
00337                 client_byte_order = (*(u_int32_t*)"a   ") & 0x00000001;
00338                 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
00339 
00340 
00341 // This must be done before fonts to know if antialiasing is available.
00342                 init_colors();
00343 // get the resources
00344                 if(resources.use_shm < 0) resources.initialize_display(this);
00345                 x_correction = get_resources()->get_left_border();
00346                 y_correction = get_resources()->get_top_border();
00347 
00348                 if(this->bg_color == -1)
00349                         this->bg_color = resources.get_bg_color();
00350 
00351 // printf("bcwindowbase 1 %s\n", title);
00352 // if(window_type == MAIN_WINDOW) sleep(1);
00353 // printf("bcwindowbase 10\n");
00354                 init_fonts();
00355                 init_gc();
00356                 init_cursors();
00357 
00358 // Create the window
00359                 mask = CWEventMask | 
00360                                 CWBackPixel | 
00361                                 CWColormap | 
00362                                 CWCursor;
00363 
00364                 attr.event_mask = DEFAULT_EVENT_MASKS |
00365                         StructureNotifyMask | 
00366                         KeyPressMask;
00367 
00368                 attr.background_pixel = get_color(this->bg_color);
00369                 attr.colormap = cmap;
00370                 attr.cursor = get_cursor_struct(ARROW_CURSOR);
00371 
00372                 win = XCreateWindow(display, 
00373                         rootwin, 
00374                         this->x, 
00375                         this->y, 
00376                         this->w, 
00377                         this->h, 
00378                         0, 
00379                         top_level->default_depth, 
00380                         InputOutput, 
00381                         vis, 
00382                         mask, 
00383                         &attr);
00384 
00385                 XGetNormalHints(display, win, &size_hints);
00386 
00387                 size_hints.flags = PSize | PMinSize | PMaxSize;
00388                 size_hints.width = this->w;
00389                 size_hints.height = this->h;
00390                 size_hints.min_width = allow_resize ? minw : this->w;
00391                 size_hints.max_width = allow_resize ? 32767 : this->w; 
00392                 size_hints.min_height = allow_resize ? minh : this->h;
00393                 size_hints.max_height = allow_resize ? 32767 : this->h; 
00394                 if(x > -BC_INFINITY && x < BC_INFINITY)
00395                 {
00396                         size_hints.flags |= PPosition;
00397                         size_hints.x = this->x;
00398                         size_hints.y = this->y;
00399                 }
00400 
00401                 XSetStandardProperties(display, 
00402                         win, 
00403                         title, 
00404                         title, 
00405                         None, 
00406                         0, 
00407                         0, 
00408                         &size_hints);
00409                 get_atoms();
00410                 
00411                 clipboard = new BC_Clipboard(display_name);
00412                 clipboard->start_clipboard();
00413 
00414                 if (group_it)
00415                 {
00416                         Atom ClientLeaderXAtom;
00417                         if (XGroupLeader == 0)
00418                                 XGroupLeader = win;
00419                         char *instance_name = "cinelerra";
00420                         char *class_name = "Cinelerra";
00421                         XClassHint *class_hints = XAllocClassHint(); 
00422                         class_hints->res_name = instance_name;
00423                         class_hints->res_class = class_name;
00424                         XSetClassHint(top_level->display, win, class_hints);
00425                         XFree(class_hints);
00426                         ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
00427                         XChangeProperty(display, 
00428                                         win, 
00429                                         ClientLeaderXAtom, 
00430                                         XA_WINDOW, 
00431                                         32, 
00432                                         PropModeReplace, 
00433                                         (unsigned char *)&XGroupLeader, 
00434                                         true);
00435 
00436                 }
00437                 
00438         }
00439 
00440 #ifdef HAVE_LIBXXF86VM
00441     if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
00442     {
00443             scale_vm (vm);
00444             vm_switched = 1;
00445     }
00446 #endif
00447 
00448 #ifdef HAVE_LIBXXF86VM
00449     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
00450 #else
00451     if(window_type == POPUP_WINDOW)
00452 #endif
00453         {
00454                 mask = CWEventMask | 
00455                         CWBackPixel | 
00456                         CWColormap | 
00457                         CWOverrideRedirect | 
00458                         CWSaveUnder | 
00459                         CWCursor;
00460 
00461                 attr.event_mask = DEFAULT_EVENT_MASKS |
00462                         KeyPressMask;
00463 
00464                 if(this->bg_color == -1)
00465                         this->bg_color = resources.get_bg_color();
00466                 attr.background_pixel = top_level->get_color(bg_color);
00467                 attr.colormap = top_level->cmap;
00468                 if(top_level->is_hourglass)
00469                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
00470                 else
00471                         attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
00472                 attr.override_redirect = True;
00473                 attr.save_under = True;
00474 
00475                 win = XCreateWindow(top_level->display, 
00476                         top_level->rootwin, 
00477                         this->x, 
00478                         this->y, 
00479                         this->w, 
00480                         this->h, 
00481                         0, 
00482                         top_level->default_depth, 
00483                         InputOutput, 
00484                         top_level->vis, 
00485                         mask, 
00486                         &attr);
00487         }
00488 
00489         if(window_type == SUB_WINDOW)
00490         {
00491                 mask = CWBackPixel | 
00492                         CWEventMask | 
00493                         CWCursor;
00494                 attr.event_mask = DEFAULT_EVENT_MASKS;
00495                 attr.background_pixel = top_level->get_color(this->bg_color);
00496                 if(top_level->is_hourglass)
00497                         attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
00498                 else
00499                         attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
00500                 win = XCreateWindow(top_level->display, 
00501                         parent_window->win, 
00502                         this->x, 
00503                         this->y, 
00504                         this->w, 
00505                         this->h, 
00506                         0, 
00507                         top_level->default_depth, 
00508                         InputOutput, 
00509                         top_level->vis, 
00510                         mask, 
00511                         &attr);
00512                 init_window_shape();
00513                 XMapWindow(top_level->display, win);
00514         }
00515 
00516 // Create pixmap for all windows
00517         pixmap = new BC_Pixmap(this, this->w, this->h);
00518 
00519 
00520 // Set up options for main window
00521         if(window_type == MAIN_WINDOW)
00522         {
00523                 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
00524                 {
00525                         this->bg_pixmap = new BC_Pixmap(this, 
00526                                 get_resources()->bg_image, 
00527                                 PIXMAP_OPAQUE);
00528                 }
00529 
00530                 if(!hidden) show_window();
00531 
00532         }
00533 
00534 
00535 
00536 
00537         draw_background(0, 0, this->w, this->h);
00538         flash();
00539 
00540 // Set up options for popup window
00541 #ifdef HAVE_LIBXXF86VM
00542     if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
00543 #else
00544     if(window_type == POPUP_WINDOW)
00545 #endif
00546         {
00547                 init_window_shape();
00548                 if(!hidden) show_window();
00549         }
00550         get_resources()->create_window_lock->unlock();
00551 
00552         return 0;
00553 }
00554 
00555 Display* BC_WindowBase::init_display(char *display_name)
00556 {
00557         Display* display;
00558 
00559         if(display_name && display_name[0] == 0) display_name = NULL;
00560         if((display = XOpenDisplay(display_name)) == NULL)
00561         {
00562                 printf("BC_WindowBase::init_display: cannot connect to X server %s\n", 
00563                         display_name);
00564                 if(getenv("DISPLAY") == NULL)
00565         {
00566                         printf("'DISPLAY' environment variable not set.\n");
00567                         exit(1);
00568                 }
00569                 else
00570 // Try again with default display.
00571                 {
00572                         if((display = XOpenDisplay(0)) == NULL)
00573                         {
00574                                 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
00575                                 exit(1);
00576                         }
00577                 }
00578         }
00579         return display;
00580 }
00581 
00582 Display* BC_WindowBase::get_display()
00583 {
00584         return top_level->display;
00585 }
00586 
00587 int BC_WindowBase::get_screen()
00588 {
00589         return top_level->screen;
00590 }
00591 
00592 int BC_WindowBase::run_window()
00593 {
00594         done = 0;
00595         return_value = 0;
00596 
00597 
00598 // Events may have been sent before run_window so can't initialize them here.
00599 
00600 // Start tooltips
00601         if(window_type == MAIN_WINDOW)
00602         {
00603 //              tooltip_id = get_repeat_id();
00604                 set_repeat(get_resources()->tooltip_delay);
00605         }
00606 
00607 // Start X server events
00608         event_thread = new BC_WindowEvents(this);
00609         event_thread->start();
00610 
00611 // Start common events
00612         while(!done)
00613         {
00614                 dispatch_event();
00615         }
00616 
00617         unset_all_repeaters();
00618         hide_tooltip();
00619         delete event_thread;
00620         event_thread = 0;
00621         event_condition->reset();
00622         common_events.remove_all_objects();
00623         done = 0;
00624 
00625         return return_value;
00626 }
00627 
00628 int BC_WindowBase::get_key_masks(XEvent *event)
00629 {
00630 // printf("BC_WindowBase::get_key_masks %llx\n", 
00631 // event->xkey.state);
00632 // ctrl key down
00633         ctrl_mask = (event->xkey.state & ControlMask) ? 1 : 0;
00634 // shift key down
00635         shift_mask = (event->xkey.state & ShiftMask) ? 1 : 0;
00636         alt_mask = (event->xkey.state & Mod1Mask) ? 1 : 0;
00637         return 0;
00638 }
00639 
00640 
00641 
00642 
00643 
00644 
00645 
00646 int BC_WindowBase::dispatch_event()
00647 {
00648         XEvent *event = 0;
00649     Window tempwin;
00650         KeySym keysym;
00651         char keys_return[2];
00652         int result;
00653         XClientMessageEvent *ptr;
00654         int temp;
00655         int cancel_resize, cancel_translation;
00656 
00657         key_pressed = 0;
00658 
00659 // If an event is waiting get it, otherwise
00660 // wait for next event only if there are no compressed events.
00661         if(get_event_count() || 
00662                 (!motion_events && !resize_events && !translation_events))
00663         {
00664 //              XNextEvent(display, event);
00665                 event = get_event();
00666 // Lock out window deletions
00667                 lock_window("BC_WindowBase::dispatch_event 1");
00668 //              get_key_masks(event);
00669         }
00670         else
00671 // Handle compressed events
00672         {
00673                 lock_window("BC_WindowBase::dispatch_event 2");
00674                 if(resize_events)
00675                         dispatch_resize_event(last_resize_w, last_resize_h);
00676                 else
00677                 if(motion_events)
00678                         dispatch_motion_event();
00679                 else
00680                 if(translation_events)
00681                         dispatch_translation_event();
00682 
00683                 unlock_window();
00684                 return 0;
00685         }
00686 
00687 //printf("1 %s %p %d\n", title, event, event->type);
00688         switch(event->type)
00689         {
00690                 case ClientMessage:
00691 // Clear the resize buffer
00692                         if(resize_events) dispatch_resize_event(last_resize_w, last_resize_h);
00693 // Clear the motion buffer since this can clear the window
00694                         if(motion_events)
00695                         {
00696                                 dispatch_motion_event();
00697                         }
00698 
00699                         ptr = (XClientMessageEvent*)event;
00700 
00701 
00702                 if(ptr->message_type == ProtoXAtom && 
00703                                 ptr->data.l[0] == DelWinXAtom)
00704                 {
00705                                 close_event();
00706                         }
00707                         else
00708                         if(ptr->message_type == RepeaterXAtom)
00709                         {
00710                                 dispatch_repeat_event(ptr->data.l[0]);
00711 // Make sure the repeater still exists.
00712 //                              for(int i = 0; i < repeaters.total; i++)
00713 //                              {
00714 //                                      if(repeaters.values[i]->repeat_id == ptr->data.l[0])
00715 //                                      {
00716 //                                              dispatch_repeat_event_master(ptr->data.l[0]);
00717 //                                              break;
00718 //                                      }
00719 //                              }
00720                         }
00721                         else
00722                         if(ptr->message_type == SetDoneXAtom)
00723                         {
00724                                 done = 1;
00725                         } else
00726                         { // We currently use X marshalling for xatom events, we can switch to something else later
00727                                 recieve_custom_xatoms((xatom_event *)ptr);
00728                         }
00729                         break;
00730 
00731                 case FocusIn:
00732                         has_focus = 1;
00733                         dispatch_focus_in();
00734                         break;
00735 
00736                 case FocusOut:
00737                         has_focus = 0;
00738                         dispatch_focus_out();
00739                         break;
00740 
00741 // Maximized
00742                 case MapNotify:
00743                         break;
00744 
00745 // Minimized
00746                 case UnmapNotify:
00747                         break;
00748 
00749                 case ButtonPress:
00750                         get_key_masks(event);
00751                         cursor_x = event->xbutton.x;
00752                         cursor_y = event->xbutton.y;
00753                         button_number = event->xbutton.button;
00754                         event_win = event->xany.window;
00755                         if (button_number != 4 && button_number != 5)
00756                                 button_down = 1;
00757                         button_pressed = event->xbutton.button;
00758                         button_time1 = button_time2;
00759                         button_time2 = event->xbutton.time;
00760                         drag_x = cursor_x;
00761                         drag_y = cursor_y;
00762                         drag_win = event_win;
00763                         drag_x1 = cursor_x - get_resources()->drag_radius;
00764                         drag_x2 = cursor_x + get_resources()->drag_radius;
00765                         drag_y1 = cursor_y - get_resources()->drag_radius;
00766                         drag_y2 = cursor_y + get_resources()->drag_radius;
00767 
00768                         if(button_time2 - button_time1 < resources.double_click)
00769                         {
00770 // Ignore triple clicks
00771                                 double_click = 1; 
00772                                 button_time2 = button_time1 = 0; 
00773                         }
00774                         else 
00775                                 double_click = 0;
00776 
00777                         dispatch_button_press();
00778                         break;
00779 
00780                 case ButtonRelease:
00781                         get_key_masks(event);
00782                         button_number = event->xbutton.button;
00783                         event_win = event->xany.window;
00784                         if (button_number != 4 && button_number != 5) 
00785                                 button_down = 0;
00786 
00787                         dispatch_button_release();
00788 
00789                         break;
00790 
00791                 case Expose:
00792                         event_win = event->xany.window;
00793                         dispatch_expose_event();
00794                         break;
00795 
00796                 case MotionNotify:
00797                         get_key_masks(event);
00798 // Dispatch previous motion event if this is a subsequent motion from a different window
00799                         if(motion_events && last_motion_win != event->xany.window)
00800                         {
00801                                 dispatch_motion_event();
00802                         }
00803 
00804 // Buffer the current motion
00805                         motion_events = 1;
00806                         last_motion_x = event->xmotion.x;
00807                         last_motion_y = event->xmotion.y;
00808                         last_motion_win = event->xany.window;
00809                         break;
00810 
00811                 case ConfigureNotify:
00812                         get_key_masks(event);
00813                         XTranslateCoordinates(top_level->display, 
00814                                 top_level->win, 
00815                                 top_level->rootwin, 
00816                                 0, 
00817                                 0, 
00818                                 &last_translate_x, 
00819                                 &last_translate_y, 
00820                                 &tempwin);
00821                         last_resize_w = event->xconfigure.width;
00822                         last_resize_h = event->xconfigure.height;
00823 
00824                         cancel_resize = 0;
00825                         cancel_translation = 0;
00826 
00827 // Resize history prevents responses to recursive resize requests
00828                         for(int i = 0; i < resize_history.total && !cancel_resize; i++)
00829                         {
00830                                 if(resize_history.values[i]->w == last_resize_w &&
00831                                         resize_history.values[i]->h == last_resize_h)
00832                                 {
00833                                         delete resize_history.values[i];
00834                                         resize_history.remove_number(i);
00835                                         cancel_resize = 1;
00836                                 }
00837                         }
00838 
00839                         if(last_resize_w == w && last_resize_h == h)
00840                                 cancel_resize = 1;
00841 
00842                         if(!cancel_resize)
00843                         {
00844                                 resize_events = 1;
00845                         }
00846 
00847                         if((last_translate_x == x && last_translate_y == y))
00848                                 cancel_translation = 1;
00849 
00850                         if(!cancel_translation)
00851                         {
00852                                 translation_events = 1;
00853                         }
00854 
00855                         translation_count++;
00856                         break;
00857 
00858                 case KeyPress:
00859                         get_key_masks(event);
00860                         keys_return[0] = 0;
00861                         XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
00862 
00863 // printf("BC_WindowBase::dispatch_event 2 %llx\n", 
00864 // event->xkey.state);
00865 // block out control keys
00866                         if(keysym > 0xffe0 && keysym < 0xffff) break;
00867 
00868 
00869                         if(test_keypress) printf("BC_WindowBase::dispatch_event %x\n", keysym);
00870 
00871 
00872                         switch(keysym)
00873                         {
00874 // block out extra keys
00875                         case XK_Alt_L:      
00876                         case XK_Alt_R:      
00877                         case XK_Shift_L:    
00878                         case XK_Shift_R:    
00879                         case XK_Control_L:  
00880                         case XK_Control_R:  
00881                                         key_pressed = 0;         
00882                                         break;
00883 
00884 // Translate key codes
00885                                 case XK_Return:     key_pressed = RETURN;    break;
00886                         case XK_Up:         key_pressed = UP;        break;
00887                                 case XK_Down:       key_pressed = DOWN;      break;
00888                                 case XK_Left:       key_pressed = LEFT;      break;
00889                         case XK_Right:      key_pressed = RIGHT;     break;
00890                         case XK_Next:       key_pressed = PGDN;      break;
00891                         case XK_Prior:      key_pressed = PGUP;      break;
00892                         case XK_BackSpace:  key_pressed = BACKSPACE; break;
00893                         case XK_Escape:     key_pressed = ESC;       break;
00894                         case XK_Tab:
00895                                         if(shift_down())
00896                                                 key_pressed = LEFTTAB;
00897                                         else
00898                                                 key_pressed = TAB;       
00899                                         break;
00900                                 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
00901                                 case XK_underscore: key_pressed = '_';       break;
00902                         case XK_asciitilde: key_pressed = '~';       break;
00903                                 case XK_Delete:     key_pressed = DELETE;    break;
00904                                 case XK_Home:       key_pressed = HOME;      break;
00905                                 case XK_End:        key_pressed = END;       break;
00906 
00907 // number pad
00908                                 case XK_KP_Enter:       key_pressed = KPENTER;   break;
00909                                 case XK_KP_Add:         key_pressed = KPPLUS;    break;
00910                                 case XK_KP_1:
00911                                 case XK_KP_End:         key_pressed = KP1;       break;
00912                                 case XK_KP_2:
00913                                 case XK_KP_Down:        key_pressed = KP2;       break;
00914                                 case XK_KP_3:
00915                                 case XK_KP_Page_Down:   key_pressed = KP3;       break;
00916                                 case XK_KP_4:
00917                                 case XK_KP_Left:        key_pressed = KP4;       break;
00918                                 case XK_KP_5:
00919                                 case XK_KP_Begin:       key_pressed = KP5;       break;
00920                                 case XK_KP_6:
00921                                 case XK_KP_Right:       key_pressed = KP6;       break;
00922                                 case XK_KP_0:
00923                                 case XK_KP_Insert:      key_pressed = KPINS;     break;
00924                                 case XK_KP_Decimal:
00925                                 case XK_KP_Delete:      key_pressed = KPDEL;     break;
00926                         default:           
00927                                         //key_pressed = keys_return[0]; 
00928                                         key_pressed = keysym & 0xff;
00929                                         break;
00930                         }
00931 
00932 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
00933                         result = dispatch_keypress_event();
00934 // Handle some default keypresses
00935                         if(!result)
00936                         {
00937                                 if(key_pressed == 'w' ||
00938                                         key_pressed == 'W')
00939                                 {
00940                                         close_event();
00941                                 }
00942                         }
00943                         break;
00944 
00945                 case LeaveNotify:
00946                         event_win = event->xany.window;
00947                         dispatch_cursor_leave();
00948                         break;
00949 
00950                 case EnterNotify:
00951                         event_win = event->xany.window;
00952                         cursor_x = event->xcrossing.x;
00953                         cursor_y = event->xcrossing.y;
00954                         dispatch_cursor_enter();
00955                         break;
00956         }
00957 //printf("100 %s %p %d\n", title, event, event->type);
00958 
00959         unlock_window();
00960         if(event) delete event;
00961         return 0;
00962 }
00963 
00964 int BC_WindowBase::dispatch_expose_event()
00965 {
00966         int result = 0;
00967         for(int i = 0; i < subwindows->total && !result; i++)
00968         {
00969                 result = subwindows->values[i]->dispatch_expose_event();
00970         }
00971 
00972 // Propagate to user
00973         if(!result) expose_event();
00974         return result;
00975 }
00976 
00977 int BC_WindowBase::dispatch_resize_event(int w, int h)
00978 {
00979 // Can't store new w and h until the event is handles 
00980 // because bcfilebox depends on the old w and h to
00981 // reposition widgets.
00982         if(window_type == MAIN_WINDOW)
00983         {
00984                 resize_events = 0;
00985                 delete pixmap;
00986                 pixmap = new BC_Pixmap(this, w, h);
00987 
00988                 clear_box(0, 0, w, h);
00989         }
00990 
00991 // Propagate to subwindows
00992         for(int i = 0; i < subwindows->total; i++)
00993         {
00994                 subwindows->values[i]->dispatch_resize_event(w, h);
00995         }
00996 
00997 // Propagate to user
00998         resize_event(w, h);
00999 
01000         if(window_type == MAIN_WINDOW)
01001         {
01002                 this->w = w;
01003                 this->h = h;
01004