4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "bcclipboard.h"
24 #include "bcdisplay.h"
25 #include "bcdisplayinfo.h"
26 #include "bcmenubar.h"
29 #include "bcpopupmenu.h"
30 #include "bcrepeater.h"
31 #include "bcresources.h"
32 #include "bcsignals.h"
33 #include "bcsubwindow.h"
34 #include "bcsynchronous.h"
36 #include "bcwindowbase.h"
37 #include "bcwindowevents.h"
38 #include "bccmodels.h"
40 #include "condition.h"
49 #include "workarounds.h"
59 #include <X11/extensions/Xinerama.h>
60 #include <X11/extensions/Xvlib.h>
61 #include <X11/extensions/shape.h>
62 #include <X11/XF86keysym.h>
63 #include <X11/Sunkeysym.h>
65 BC_ResizeCall::BC_ResizeCall(int w, int h)
77 int BC_WindowBase::shm_completion_event = -1;
81 BC_Resources BC_WindowBase::resources;
83 Window XGroupLeader = 0;
85 Mutex BC_KeyboardHandlerLock::keyboard_listener_mutex("keyboard_listener",0);
86 ArrayList<BC_KeyboardHandler*> BC_KeyboardHandler::listeners;
88 BC_WindowBase::BC_WindowBase()
90 //printf("BC_WindowBase::BC_WindowBase 1\n");
91 BC_WindowBase::initialize();
94 BC_WindowBase::~BC_WindowBase()
97 BC_Display::lock_display("BC_WindowBase::~BC_WindowBase");
99 if(window_type == MAIN_WINDOW)
100 lock_window("BC_WindowBase::~BC_WindowBase");
103 #ifdef HAVE_LIBXXF86VM
104 if(window_type == VIDMODE_SCALED_WINDOW && vm_switched) {
111 if(window_type != MAIN_WINDOW)
114 XSelectInput(top_level->display, this->win, 0);
115 XSync(top_level->display,0);
116 #ifndef SINGLE_THREAD
117 top_level->dequeue_events(win);
119 // drop active window refs to this
120 if(top_level->active_menubar == this) top_level->active_menubar = 0;
121 if(top_level->active_popup_menu == this) top_level->active_popup_menu = 0;
122 if(top_level->active_subwindow == this) top_level->active_subwindow = 0;
123 // drop motion window refs to this
124 if(top_level->motion_events && top_level->last_motion_win == this->win)
125 top_level->motion_events = 0;
127 // Remove pointer from parent window to this
128 parent_window->subwindows->remove(this);
131 if(grab_active) grab_active->active_grab = 0;
132 if(icon_window) delete icon_window;
133 if(window_type == POPUP_WINDOW)
134 parent_window->remove_popup(this);
136 // Delete the subwindows
139 while(subwindows->total)
141 // Subwindow removes its own pointer
142 delete subwindows->values[0];
149 //printf("delete glx=%08x, win=%08x %s\n", (unsigned)glx_win, (unsigned)win, title);
151 if( get_resources()->get_synchronous() && glx_win != 0 ) {
152 if( window_type == MAIN_WINDOW )
154 get_resources()->get_synchronous()->delete_window(this);
155 if( window_type == MAIN_WINDOW )
156 lock_window("BC_WindowBase::delete_window");
159 XDestroyWindow(top_level->display, win);
161 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
162 if(icon_pixmap) delete icon_pixmap;
163 if(temp_bitmap) delete temp_bitmap;
164 top_level->active_bitmaps.remove_buffers(this);
165 if(_7segment_pixmaps)
167 for(int i = 0; i < TOTAL_7SEGMENT; i++)
168 delete _7segment_pixmaps[i];
170 delete [] _7segment_pixmaps;
175 if(window_type == MAIN_WINDOW)
177 XFreeGC(display, gc);
178 static XFontStruct *BC_WindowBase::*xfont[] = {
179 &BC_WindowBase::smallfont,
180 &BC_WindowBase::mediumfont,
181 &BC_WindowBase::largefont,
182 &BC_WindowBase::bigfont,
183 &BC_WindowBase::clockfont,
185 for( int i=sizeof(xfont)/sizeof(xfont[0]); --i>=0; )
186 XFreeFont(display, this->*xfont[i]);
189 // prevents a bug when Xft closes with unrefd fonts
190 FcPattern *defaults = FcPatternCreate();
191 FcPatternAddInteger(defaults, "maxunreffonts", 0);
192 XftDefaultSet(display, defaults);
194 static void *BC_WindowBase::*xft_font[] = {
195 &BC_WindowBase::smallfont_xft,
196 &BC_WindowBase::mediumfont_xft,
197 &BC_WindowBase::largefont_xft,
198 &BC_WindowBase::bigfont_xft,
199 &BC_WindowBase::bold_smallfont_xft,
200 &BC_WindowBase::bold_mediumfont_xft,
201 &BC_WindowBase::bold_largefont_xft,
202 &BC_WindowBase::clockfont_xft,
204 for( int i=sizeof(xft_font)/sizeof(xft_font[0]); --i>=0; ) {
205 XftFont *xft = (XftFont *)(this->*xft_font[i]);
206 if( xft ) xftFontClose (display, xft);
214 XFree(xinerama_info);
215 xinerama_screens = 0;
217 if( xvideo_port_id >= 0 )
218 XvUngrabPort(display, xvideo_port_id, CurrentTime);
221 // Must be last reference to display.
222 // _XftDisplayInfo needs a lock.
223 get_resources()->create_window_lock->lock("BC_WindowBase::~BC_WindowBase");
224 XCloseDisplay(display);
225 get_resources()->create_window_lock->unlock();
227 // clipboard uses a different display connection
228 clipboard->stop_clipboard();
232 resize_history.remove_all_objects();
234 #ifndef SINGLE_THREAD
235 common_events.remove_all_objects();
237 delete event_condition;
240 top_level->window_lock = 0;
241 BC_Display::unlock_display();
246 if( glx_fbcfgs_window ) XFree(glx_fbcfgs_window);
247 if( glx_fbcfgs_pbuffer) XFree(glx_fbcfgs_pbuffer);
248 if( glx_fbcfgs_pixmap ) XFree(glx_fbcfgs_pixmap);
251 UNSET_ALL_LOCKS(this)
254 int BC_WindowBase::initialize()
259 display_lock_owner = 0;
264 resend_event_window = 0;
276 xinerama_screens = 0;
281 translation_events = 0;
282 ctrl_mask = shift_mask = alt_mask = 0;
283 cursor_x = cursor_y = button_number = 0;
297 active_popup_menu = 0;
298 active_subwindow = 0;
302 _7segment_pixmaps = 0;
305 // next_repeat_id = 0;
307 current_font = MEDIUMFONT;
308 current_color = BLACK;
309 current_cursor = ARROW_CURSOR;
312 shared_bg_pixmap = 0;
315 window_type = MAIN_WINDOW;
316 translation_count = 0;
317 x_correction = y_correction = 0;
326 #ifdef HAVE_LIBXXF86VM
344 bold_smallfont_xft = 0;
345 bold_mediumfont_xft = 0;
346 bold_largefont_xft = 0;
348 completion_lock = new Condition(0, "BC_WindowBase::completion_lock");
350 // Need these right away since put_event is called before run_window sometimes.
351 event_lock = new Mutex("BC_WindowBase::event_lock");
352 event_condition = new Condition(0, "BC_WindowBase::event_condition");
353 init_lock = new Condition(0, "BC_WindowBase::init_lock");
356 cursor_timer = new Timer;
359 glx_fbcfgs_window = 0; n_fbcfgs_window = 0;
360 glx_fbcfgs_pbuffer = 0; n_fbcfgs_pbuffer = 0;
361 glx_fbcfgs_pixmap = 0; n_fbcfgs_pixmap = 0;
375 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
378 ButtonReleaseMask | \
379 PointerMotionMask | \
383 int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title,
384 int x, int y, int w, int h, int minw, int minh, int allow_resize,
385 int private_color, int hide, int bg_color, const char *display_name,
386 int window_type, BC_Pixmap *bg_pixmap, int group_it)
388 XSetWindowAttributes attr;
390 XSizeHints size_hints;
393 #ifdef HAVE_LIBXXF86VM
397 id = get_resources()->get_id();
398 if(parent_window) top_level = parent_window->top_level;
399 if( top_level ) lock_window("BC_WindowBase::create_window");
400 get_resources()->create_window_lock->lock("BC_WindowBase::create_window");
402 #ifdef HAVE_LIBXXF86VM
403 if(window_type == VIDMODE_SCALED_WINDOW)
404 closest_vm(&vm,&w,&h);
411 this->bg_color = bg_color;
412 this->window_type = window_type;
414 this->private_color = private_color;
415 this->parent_window = parent_window;
416 this->bg_pixmap = bg_pixmap;
417 this->allow_resize = allow_resize;
419 strcpy(this->display_name, display_name);
421 this->display_name[0] = 0;
424 if(bg_pixmap) shared_bg_pixmap = 1;
426 subwindows = new BC_SubWindowList;
428 if(window_type == MAIN_WINDOW)
431 parent_window = this;
435 display = BC_Display::get_display(display_name);
436 BC_Display::lock_display("BC_WindowBase::create_window");
437 // BC_Display::display_global->new_window(this);
440 // get the display connection
442 // This function must be the first Xlib
443 // function a multi-threaded program calls
445 display = init_display(display_name);
446 if( shm_completion_event < 0 ) shm_completion_event =
447 ShmCompletion + XShmGetEventBase(display);
449 lock_window("BC_WindowBase::create_window 1");
451 screen = DefaultScreen(display);
452 rootwin = RootWindow(display, screen);
453 // window placement boundaries
454 if( !xinerama_screens && XineramaIsActive(display) )
455 xinerama_info = XineramaQueryScreens(display, &xinerama_screens);
456 root_w = get_root_w(0);
457 root_h = get_root_h(0);
460 vis = get_glx_visual(display);
463 vis = DefaultVisual(display, screen);
465 default_depth = DefaultDepth(display, screen);
467 client_byte_order = (*(const u_int32_t*)"a ") & 0x00000001;
468 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
471 // This must be done before fonts to know if antialiasing is available.
474 if(resources.use_shm < 0) resources.initialize_display(this);
475 x_correction = BC_DisplayInfo::get_left_border();
476 y_correction = BC_DisplayInfo::get_top_border();
478 // clamp window placement
479 if(this->x + this->w + x_correction > root_w)
480 this->x = root_w - this->w - x_correction;
481 if(this->y + this->h + y_correction > root_h)
482 this->y = root_h - this->h - y_correction;
483 if(this->x < 0) this->x = 0;
484 if(this->y < 0) this->y = 0;
486 if(this->bg_color == -1)
487 this->bg_color = resources.get_bg_color();
489 // printf("bcwindowbase 1 %s\n", title);
490 // if(window_type == MAIN_WINDOW) sleep(1);
491 // printf("bcwindowbase 10\n");
497 mask = CWEventMask | CWBackPixel | CWColormap | CWCursor;
499 attr.event_mask = DEFAULT_EVENT_MASKS |
500 StructureNotifyMask |
504 attr.background_pixel = get_color(this->bg_color);
505 attr.colormap = cmap;
506 attr.cursor = get_cursor_struct(ARROW_CURSOR);
508 win = XCreateWindow(display, rootwin,
509 this->x, this->y, this->w, this->h, 0,
510 top_level->default_depth, InputOutput,
512 XGetNormalHints(display, win, &size_hints);
514 size_hints.flags = PSize | PMinSize | PMaxSize;
515 size_hints.width = this->w;
516 size_hints.height = this->h;
517 size_hints.min_width = allow_resize ? minw : this->w;
518 size_hints.max_width = allow_resize ? 32767 : this->w;
519 size_hints.min_height = allow_resize ? minh : this->h;
520 size_hints.max_height = allow_resize ? 32767 : this->h;
521 if(x > -BC_INFINITY && x < BC_INFINITY)
523 size_hints.flags |= PPosition;
524 size_hints.x = this->x;
525 size_hints.y = this->y;
527 XSetWMProperties(display, win, 0, 0, 0, 0, &size_hints, 0, 0);
530 #ifndef SINGLE_THREAD
531 clipboard = new BC_Clipboard(this);
532 clipboard->start_clipboard();
538 Atom ClientLeaderXAtom;
539 if (XGroupLeader == 0)
541 const char *instance_name = "cinelerra";
542 const char *class_name = "Cinelerra";
543 XClassHint *class_hints = XAllocClassHint();
544 class_hints->res_name = (char*)instance_name;
545 class_hints->res_class = (char*)class_name;
546 XSetClassHint(top_level->display, win, class_hints);
548 ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
549 XChangeProperty(display, win, ClientLeaderXAtom, XA_WINDOW, 32,
550 PropModeReplace, (unsigned char *)&XGroupLeader, true);
553 set_icon(get_resources()->default_icon);
556 #ifdef HAVE_LIBXXF86VM
557 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
564 #ifdef HAVE_LIBXXF86VM
565 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
567 if(window_type == POPUP_WINDOW)
570 mask = CWEventMask | CWBackPixel | CWColormap |
571 CWOverrideRedirect | CWSaveUnder | CWCursor;
573 attr.event_mask = DEFAULT_EVENT_MASKS | ExposureMask |
574 KeyPressMask | KeyReleaseMask;
576 if(this->bg_color == -1)
577 this->bg_color = resources.get_bg_color();
578 attr.background_pixel = top_level->get_color(bg_color);
579 attr.colormap = top_level->cmap;
580 if(top_level->is_hourglass)
581 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
583 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
584 attr.override_redirect = True;
585 attr.save_under = True;
587 win = XCreateWindow(top_level->display,
588 top_level->rootwin, this->x, this->y, this->w, this->h, 0,
589 top_level->default_depth, InputOutput, top_level->vis, mask,
591 top_level->add_popup(this);
594 if(window_type == SUB_WINDOW)
596 mask = CWEventMask | CWBackPixel | CWCursor;
597 attr.event_mask = DEFAULT_EVENT_MASKS;
598 attr.background_pixel = top_level->get_color(this->bg_color);
599 if(top_level->is_hourglass)
600 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
602 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
603 win = XCreateWindow(top_level->display,
604 parent_window->win, this->x, this->y, this->w, this->h, 0,
605 top_level->default_depth, InputOutput, top_level->vis, mask,
608 if(!hidden) XMapWindow(top_level->display, win);
611 // Create pixmap for all windows
612 pixmap = new BC_Pixmap(this, this->w, this->h);
614 // Set up options for main window
615 if(window_type == MAIN_WINDOW)
617 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
619 this->bg_pixmap = new BC_Pixmap(this,
620 get_resources()->bg_image,
624 if(!hidden) show_window();
628 draw_background(0, 0, this->w, this->h);
630 flash(-1, -1, -1, -1, 0);
632 // Set up options for popup window
633 #ifdef HAVE_LIBXXF86VM
634 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
636 if(window_type == POPUP_WINDOW)
640 if(!hidden) show_window();
642 get_resources()->create_window_lock->unlock();
648 Display* BC_WindowBase::init_display(const char *display_name)
652 if(display_name && display_name[0] == 0) display_name = NULL;
653 if((display = XOpenDisplay(display_name)) == NULL) {
654 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
656 if(getenv("DISPLAY") == NULL) {
657 printf(_("'DISPLAY' environment variable not set.\n"));
660 // Try again with default display.
661 if((display = XOpenDisplay(0)) == NULL) {
662 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
667 static int xsynch = -1;
669 const char *cp = getenv("CIN_XSYNCH");
670 xsynch = !cp ? 0 : atoi(cp);
673 XSynchronize(display, True);
678 Display* BC_WindowBase::get_display()
680 return top_level->display;
683 int BC_WindowBase::get_screen()
685 return top_level->screen;
688 int BC_WindowBase::run_window()
694 // Events may have been sent before run_window so can't initialize them here.
697 set_repeat(get_resources()->tooltip_delay);
698 BC_Display::display_global->new_window(this);
700 // If the first window created, run the display loop in this thread.
701 if(BC_Display::display_global->is_first(this))
703 BC_Display::unlock_display();
704 BC_Display::display_global->loop();
708 BC_Display::unlock_display();
709 completion_lock->lock("BC_WindowBase::run_window");
712 BC_Display::lock_display("BC_WindowBase::run_window");
713 BC_Display::display_global->delete_window(this);
715 unset_all_repeaters();
717 BC_Display::unlock_display();
719 #else // SINGLE_THREAD
724 set_repeat(get_resources()->tooltip_delay);
726 // Start X server events
727 event_thread = new BC_WindowEvents(this);
728 event_thread->start();
734 // Handle common events
739 unset_all_repeaters();
743 event_condition->reset();
744 common_events.remove_all_objects();
748 #endif // SINGLE_THREAD
753 int BC_WindowBase::get_key_masks(unsigned int key_state)
755 // printf("BC_WindowBase::get_key_masks %llx\n",
756 // event->xkey.state);
757 ctrl_mask = (key_state & ControlMask) ? 1 : 0; // ctrl key down
758 shift_mask = (key_state & ShiftMask) ? 1 : 0; // shift key down
759 alt_mask = (key_state & Mod1Mask) ? 1 : 0; // alt key down
764 void BC_WindowBase::add_keyboard_listener(int(BC_WindowBase::*handler)(BC_WindowBase *))
766 BC_KeyboardHandlerLock set;
767 BC_KeyboardHandler::listeners.append(new BC_KeyboardHandler(handler, this));
770 void BC_WindowBase::del_keyboard_listener(int(BC_WindowBase::*handler)(BC_WindowBase *))
772 BC_KeyboardHandlerLock set;
773 int i = BC_KeyboardHandler::listeners.size();
774 while( --i >= 0 && BC_KeyboardHandler::listeners[i]->handler!=handler );
775 if( i >= 0 ) BC_KeyboardHandler::listeners.remove_object_number(i);
778 int BC_KeyboardHandler::run_event(BC_WindowBase *wp)
780 int result = (win->*handler)(wp);
784 int BC_KeyboardHandler::run_listeners(BC_WindowBase *wp)
787 BC_KeyboardHandlerLock set;
788 for( int i=0; !result && i<listeners.size(); ++i ) {
789 BC_KeyboardHandler *listener = listeners[i];
790 result = listener->run_event(wp);
795 void BC_KeyboardHandler::kill_grabs()
797 BC_KeyboardHandlerLock set;
798 for( int i=0; i<listeners.size(); ++i ) {
799 BC_WindowBase *win = listeners[i]->win;
800 if( win->get_window_type() != POPUP_WINDOW ) continue;
801 ((BC_Popup *)win)->ungrab_keyboard();
805 void BC_ActiveBitmaps::reque(XEvent *event)
807 XShmCompletionEvent *shm_ev = (XShmCompletionEvent *)event;
808 ShmSeg shmseg = shm_ev->shmseg;
809 Drawable drawable = shm_ev->drawable;
810 //printf("BC_BitmapImage::reque %08lx\n",shmseg);
811 active_lock.lock("BC_BitmapImage::reque");
812 BC_BitmapImage *bfr = first;
813 while( bfr && bfr->get_shmseg() != shmseg ) bfr = bfr->next;
814 if( bfr && bfr->drawable == drawable )
816 active_lock.unlock();
818 // sadly, X reports two drawable completions and creates false reporting, so no boobytrap
819 // printf("BC_BitmapImage::reque missed shmseg %08x, drawable %08x\n",
820 // (int)shmseg, (int)drawable);
823 if( bfr->drawable != drawable ) return;
824 if( bfr->is_zombie() ) { --BC_Bitmap::zombies; delete bfr; return; }
825 bfr->bitmap->reque(bfr);
828 void BC_ActiveBitmaps::insert(BC_BitmapImage *bfr, Drawable pixmap)
830 active_lock.lock("BC_BitmapImage::insert");
831 bfr->drawable = pixmap;
833 active_lock.unlock();
836 void BC_ActiveBitmaps::remove_buffers(BC_WindowBase *wdw)
838 active_lock.lock("BC_ActiveBitmaps::remove");
839 for( BC_BitmapImage *nxt=0, *bfr=first; bfr; bfr=nxt ) {
841 if( bfr->is_zombie() ) { --BC_Bitmap::zombies; delete bfr; continue; }
842 if( bfr->bitmap->parent_window == wdw ) remove_pointer(bfr);
844 active_lock.unlock();
847 BC_ActiveBitmaps::BC_ActiveBitmaps()
851 BC_ActiveBitmaps::~BC_ActiveBitmaps()
857 int BC_WindowBase::keysym_lookup(XEvent *event)
859 for( int i = 0; i < KEYPRESSLEN; ++i ) keys_return[i] = 0;
860 for( int i = 0; i < 4; ++i ) wkey_string[i] = 0;
862 if( event->xany.send_event && !event->xany.serial ) {
863 keysym = (KeySym) event->xkey.keycode;
864 keys_return[0] = keysym;
867 wkey_string_length = 0;
869 if( input_context ) {
870 wkey_string_length = XwcLookupString(input_context,
871 (XKeyEvent*)event, wkey_string, 4, &keysym, 0);
872 //printf("keysym_lookup 1 %d %d %lx %x %x %x %x\n", wkey_string_length, keysym,
873 // wkey_string[0], wkey_string[1], wkey_string[2], wkey_string[3]);
876 int ret = Xutf8LookupString(input_context, (XKeyEvent*)event,
877 keys_return, KEYPRESSLEN, &keysym, &stat);
878 //printf("keysym_lookup 2 %d %d %lx %x %x\n", ret, stat, keysym, keys_return[0], keys_return[1]);
879 if( stat == XLookupBoth ) return ret;
880 if( stat == XLookupKeySym ) return 0;
882 int ret = XLookupString((XKeyEvent*)event, keys_return, KEYPRESSLEN, &keysym, 0);
883 wkey_string_length = ret;
884 for( int i=0; i<ret; ++i ) wkey_string[i] = keys_return[i];
888 pthread_t locking_task = (pthread_t)-1L;
889 int locking_event = -1;
890 int locking_message = -1;
892 int BC_WindowBase::dispatch_event()
896 XClientMessageEvent *ptr;
897 int cancel_resize, cancel_translation;
898 volatile static int debug = 0;
903 #ifndef SINGLE_THREAD
904 // If an event is waiting get it, otherwise
905 // wait for next event only if there are no compressed events.
906 if(get_event_count() ||
907 (!motion_events && !resize_events && !translation_events))
910 // Lock out window deletions
911 lock_window("BC_WindowBase::dispatch_event 1");
912 locking_event = event->type;
913 locking_task = pthread_self();
914 locking_message = event->xclient.message_type;
917 // Handle compressed events
919 lock_window("BC_WindowBase::dispatch_event 2");
921 dispatch_resize_event(last_resize_w, last_resize_h);
923 dispatch_motion_event();
924 if(translation_events)
925 dispatch_translation_event();
936 if( debug && event->type != ClientMessage ) {
937 static const char *event_names[] = {
938 "Reply", "Error", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify",
939 "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose",
940 "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify",
941 "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
942 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear",
943 "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify",
944 "GenericEvent", "LASTEvent",
946 const int nevents = sizeof(event_names)/sizeof(event_names[0]);
948 printf("BC_WindowBase::dispatch_event %d %s %p %d (%s)\n", __LINE__,
949 title, event, event->type, event->type>=0 && event->type<nevents ?
950 event_names[event->type] : "Unknown");
955 active_grab->lock_window("BC_WindowBase::dispatch_event 3");
956 result = active_grab->grab_event(event);
957 active_grab->unlock_window();
958 if( result ) return result;
959 lock_window("BC_WindowBase::dispatch_event 4");
962 switch(event->type) {
964 // Clear the resize buffer
966 dispatch_resize_event(last_resize_w, last_resize_h);
967 // Clear the motion buffer since this can clear the window
969 dispatch_motion_event();
971 ptr = (XClientMessageEvent*)event;
972 if( ptr->message_type == ProtoXAtom &&
973 (Atom)ptr->data.l[0] == DelWinXAtom ) {
976 else if( ptr->message_type == RepeaterXAtom ) {
977 dispatch_repeat_event(ptr->data.l[0]);
979 else if( ptr->message_type == SetDoneXAtom ) {
983 receive_custom_xatoms((xatom_event *)ptr);
994 dispatch_focus_out();
1008 dispatch_motion_event();
1010 get_key_masks(event->xbutton.state);
1011 cursor_x = event->xbutton.x;
1012 cursor_y = event->xbutton.y;
1013 button_number = event->xbutton.button;
1015 //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number);
1016 event_win = event->xany.window;
1017 if (button_number < 6) {
1018 if(button_number < 4)
1020 button_pressed = event->xbutton.button;
1021 button_time1 = button_time2;
1022 button_time2 = button_time3;
1023 button_time3 = event->xbutton.time;
1026 drag_win = event_win;
1027 drag_x1 = cursor_x - get_resources()->drag_radius;
1028 drag_x2 = cursor_x + get_resources()->drag_radius;
1029 drag_y1 = cursor_y - get_resources()->drag_radius;
1030 drag_y2 = cursor_y + get_resources()->drag_radius;
1032 if((long)(button_time3 - button_time1) < resources.double_click * 2)
1035 button_time3 = button_time2 = button_time1 = 0;
1037 if((long)(button_time3 - button_time2) < resources.double_click)
1040 // button_time3 = button_time2 = button_time1 = 0;
1048 dispatch_button_press();
1055 dispatch_motion_event();
1057 get_key_masks(event->xbutton.state);
1058 button_number = event->xbutton.button;
1059 event_win = event->xany.window;
1060 if (button_number < 6)
1062 if(button_number < 4)
1064 //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number);
1066 dispatch_button_release();
1071 event_win = event->xany.window;
1073 for( int i=0; !result && i<popups.size(); ++i ) { // popups take focus
1074 if( popups[i]->win == event_win )
1075 result = popups[i]->dispatch_expose_event();
1078 result = dispatch_expose_event();
1082 get_key_masks(event->xmotion.state);
1083 // Dispatch previous motion event if this is a subsequent motion from a different window
1084 if(motion_events && last_motion_win != event->xany.window)
1086 dispatch_motion_event();
1089 // Buffer the current motion
1091 last_motion_state = event->xmotion.state;
1092 last_motion_x = event->xmotion.x;
1093 last_motion_y = event->xmotion.y;
1094 last_motion_win = event->xany.window;
1097 case ConfigureNotify:
1098 // printf("BC_WindowBase::dispatch_event %d win=%p this->win=%p\n",
1100 // event->xany.window,
1103 XTranslateCoordinates(top_level->display,
1111 last_resize_w = event->xconfigure.width;
1112 last_resize_h = event->xconfigure.height;
1115 cancel_translation = 0;
1117 // Resize history prevents responses to recursive resize requests
1118 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
1120 if(resize_history.values[i]->w == last_resize_w &&
1121 resize_history.values[i]->h == last_resize_h)
1123 delete resize_history.values[i];
1124 resize_history.remove_number(i);
1129 if(last_resize_w == w && last_resize_h == h)
1137 if((last_translate_x == x && last_translate_y == y))
1138 cancel_translation = 1;
1140 if(!cancel_translation)
1142 translation_events = 1;
1145 translation_count++;
1149 get_key_masks(event->xkey.state);
1150 keys_return[0] = 0; keysym = -1;
1151 if(XFilterEvent(event, win)) {
1154 if( keysym_lookup(event) < 0 ) {
1155 printf("keysym %x\n", (uint32_t)keysym);
1159 //printf("BC_WindowBase::dispatch_event %d keysym=0x%x\n",
1163 // block out control keys
1164 if(keysym > 0xffe0 && keysym < 0xffff) break;
1165 // block out Alt_GR key
1166 if(keysym == 0xfe03) break;
1169 printf("BC_WindowBase::dispatch_event %x\n", (uint32_t)keysym);
1171 #ifdef X_HAVE_UTF8_STRING
1172 //It's Ascii or UTF8?
1173 // if (keysym != 0xffff && (keys_return[0] & 0xff) >= 0x7f )
1174 //printf("BC_WindowBase::dispatch_event %d %02x%02x\n", __LINE__, keys_return[0], keys_return[1]);
1176 if( ((keys_return[1] & 0xff) > 0x80) &&
1177 ((keys_return[0] & 0xff) > 0xC0) ) {
1178 //printf("BC_WindowBase::dispatch_event %d\n", __LINE__);
1179 key_pressed = keysym & 0xff;
1183 // shuttle speed codes
1184 if( keysym >= SKEY_MIN && keysym <= SKEY_MAX ) {
1185 key_pressed = keysym;
1187 else switch( keysym ) {
1188 // block out extra keys
1198 // Translate key codes
1199 case XK_Return: key_pressed = RETURN; break;
1200 case XK_Up: key_pressed = UP; break;
1201 case XK_Down: key_pressed = DOWN; break;
1202 case XK_Left: key_pressed = LEFT; break;
1203 case XK_Right: key_pressed = RIGHT; break;
1204 case XK_Next: key_pressed = PGDN; break;
1205 case XK_Prior: key_pressed = PGUP; break;
1206 case XK_BackSpace: key_pressed = BACKSPACE; break;
1207 case XK_Escape: key_pressed = ESC; break;
1210 key_pressed = LEFTTAB;
1214 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
1215 case XK_underscore: key_pressed = '_'; break;
1216 case XK_asciitilde: key_pressed = '~'; break;
1217 case XK_Delete: key_pressed = DELETE; break;
1218 case XK_Home: key_pressed = HOME; break;
1219 case XK_End: key_pressed = END; break;
1222 case XK_KP_Enter: key_pressed = KPENTER; break;
1223 case XK_KP_Add: key_pressed = KPPLUS; break;
1224 case XK_KP_Subtract: key_pressed = KPMINUS; break;
1225 case XK_KP_Multiply: key_pressed = KPSTAR; break;
1226 case XK_KP_Divide: key_pressed = KPSLASH; break;
1228 case XK_KP_End: key_pressed = KP1; break;
1230 case XK_KP_Down: key_pressed = KP2; break;
1232 case XK_KP_Page_Down: key_pressed = KP3; break;
1234 case XK_KP_Left: key_pressed = KP4; break;
1236 case XK_KP_Begin: key_pressed = KP5; break;
1238 case XK_KP_Right: key_pressed = KP6; break;
1240 case XK_KP_Home: key_pressed = KP7; break;
1242 case XK_KP_Up: key_pressed = KP8; break;
1244 case XK_KP_Page_Up: key_pressed = KP9; break;
1246 case XK_KP_Insert: key_pressed = KPINS; break;
1248 case XK_KP_Delete: key_pressed = KPDEL; break;
1250 case XK_F1: key_pressed = KEY_F1; break;
1251 case XK_F2: key_pressed = KEY_F2; break;
1252 case XK_F3: key_pressed = KEY_F3; break;
1253 case XK_F4: key_pressed = KEY_F4; break;
1254 case XK_F5: key_pressed = KEY_F5; break;
1255 case XK_F6: key_pressed = KEY_F6; break;
1256 case XK_F7: key_pressed = KEY_F7; break;
1257 case XK_F8: key_pressed = KEY_F8; break;
1258 case XK_F9: key_pressed = KEY_F9; break;
1259 case XK_F10: key_pressed = KEY_F10; break;
1260 case XK_F11: key_pressed = KEY_F11; break;
1261 case XK_F12: key_pressed = KEY_F12; break;
1263 case XK_Menu: key_pressed = KPMENU; break; /* menu */
1265 // above case XK_KP_Enter: key_pressed = KPENTER; break; /* check */
1266 case XF86XK_MenuKB: key_pressed = KPMENU; break; /* menu */
1267 // intercepted case XF86XK_PowerDown: key_pressed = KPPOWER; break; /* Power */
1268 case XF86XK_Launch1: key_pressed = KPTV; break; /* TV */
1269 case XF86XK_Launch2: key_pressed = KPDVD; break; /* DVD */
1270 // intercepted case XF86XK_WWW: key_pressed = KPWWEB; break; /* WEB */
1271 case XF86XK_Launch3: key_pressed = KPBOOK; break; /* book */
1272 case XF86XK_Launch4: key_pressed = KPHAND; break; /* hand */
1273 case XF86XK_Reply: key_pressed = KPTMR; break; /* timer */
1274 case SunXK_Front: key_pressed = KPMAXW; break; /* max */
1275 // above case XK_Left: key_pressed = LEFT; break; /* left */
1276 // above case XK_Right: key_pressed = RIGHT; break; /* right */
1277 // above case XK_Down: key_pressed = DOWN; break; /* down */
1278 // above case XK_Up: key_pressed = UP; break; /* up */
1279 // above case XK_SPACE: key_pressed = KPSPACE; break; /* ok */
1280 // intercepted case XF86XK_AudioRaiseVolume: key_pressed = KPVOLU; break; /* VOL + */
1281 // intercepted case XF86XK_AudioMute: key_pressed = KPMUTE; break; /* MUTE */
1282 // intercepted case XF86XK_AudioLowerVolume: key_pressed = KPVOLD; break; /* VOL - */
1283 case XF86XK_ScrollUp: key_pressed = KPCHUP; break; /* CH + */
1284 case XF86XK_ScrollDown: key_pressed = KPCHDN; break; /* CH - */
1285 case XF86XK_AudioRecord: key_pressed = KPRECD; break; /* ( o) red */
1286 case XF86XK_Forward: key_pressed = KPPLAY; break; /* ( >) */
1287 case XK_Redo: key_pressed = KPFWRD; break; /* (>>) */
1288 case XF86XK_Back: key_pressed = KPBACK; break; /* (<<) */
1289 case XK_Cancel: key_pressed = KPSTOP; break; /* ([]) */
1290 case XK_Pause: key_pressed = KPAUSE; break; /* ('') */
1293 key_pressed = keysym & 0xff;
1294 #ifdef X_HAVE_UTF8_STRING
1295 //printf("BC_WindowBase::dispatch_event %d\n", __LINE__);
1300 #ifdef X_HAVE_UTF8_STRING
1302 key_pressed_utf8 = keys_return;
1307 if( top_level == this )
1308 result = BC_KeyboardHandler::run_listeners(this);
1310 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
1312 result = dispatch_keypress_event();
1313 // Handle some default keypresses
1316 if(key_pressed == 'w' ||
1325 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
1326 dispatch_keyrelease_event();
1327 // printf("BC_WindowBase::dispatch_event KeyRelease keysym=0x%x keystate=0x%lld\n",
1328 // keysym, event->xkey.state);
1332 if( event->xcrossing.mode != NotifyNormal ) break;
1334 event_win = event->xany.window;
1335 dispatch_cursor_leave();
1339 if( event->xcrossing.mode != NotifyNormal ) break;
1341 if( !cursor_entered ) {
1342 for( int i=0; i<popups.size(); ++i ) { // popups always take focus
1343 if( popups[i]->win == event->xcrossing.window )
1346 if( !cursor_entered && get_resources()->grab_input_focus &&
1347 !event->xcrossing.focus && event->xcrossing.window == win ) {
1350 if( cursor_entered )
1353 event_win = event->xany.window;
1354 cursor_x = event->xcrossing.x;
1355 cursor_y = event->xcrossing.y;
1356 dispatch_cursor_enter();
1362 //printf("100 %s %p %d\n", title, event, event->type);
1363 //if(event->type != ClientMessage) dump();
1365 #ifndef SINGLE_THREAD
1368 if( resend_event_window ) {
1369 resend_event_window->put_event(event);
1370 resend_event_window = 0;
1376 // if(done) completion_lock->unlock();
1379 if(debug) printf("BC_WindowBase::dispatch_event this=%p %d\n", this, __LINE__);
1383 int BC_WindowBase::dispatch_expose_event()
1386 for(int i = 0; i < subwindows->total && !result; i++)
1388 result = subwindows->values[i]->dispatch_expose_event();
1391 // Propagate to user
1392 if(!result) expose_event();
1396 int BC_WindowBase::dispatch_resize_event(int w, int h)
1398 // Can't store new w and h until the event is handles
1399 // because bcfilebox depends on the old w and h to
1400 // reposition widgets.
1401 if( window_type == MAIN_WINDOW ) {
1406 pixmap = new BC_Pixmap(this, w, h);
1407 clear_box(0, 0, w, h);
1410 // Propagate to subwindows
1411 for(int i = 0; i < subwindows->total; i++) {
1412 subwindows->values[i]->dispatch_resize_event(w, h);
1415 // Propagate to user
1418 if( window_type == MAIN_WINDOW ) {
1427 int BC_WindowBase::dispatch_flash()
1430 for(int i = 0; i < subwindows->total; i++)
1431 subwindows->values[i]->dispatch_flash();
1435 int BC_WindowBase::dispatch_translation_event()
1437 translation_events = 0;
1438 if(window_type == MAIN_WINDOW)
1442 x = last_translate_x;
1443 y = last_translate_y;
1444 // Correct for window manager offsets
1449 for(int i = 0; i < subwindows->total; i++)
1451 subwindows->values[i]->dispatch_translation_event();
1454 translation_event();
1458 int BC_WindowBase::dispatch_motion_event()
1463 if(top_level == this)
1466 event_win = last_motion_win;
1467 get_key_masks(last_motion_state);
1470 if(get_button_down() && !active_menubar && !active_popup_menu)
1474 cursor_x = last_motion_x;
1475 cursor_y = last_motion_y;
1476 result = dispatch_drag_motion();
1480 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
1481 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1486 result = dispatch_drag_start();
1490 cursor_x = last_motion_x;
1491 cursor_y = last_motion_y;
1493 // printf("BC_WindowBase::dispatch_motion_event %d %p %p %p\n",
1496 // active_popup_menu,
1497 // active_subwindow);
1499 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1500 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1501 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1504 // Dispatch in stacking order
1505 for(int i = subwindows->size() - 1; i >= 0 && !result; i--)
1507 result = subwindows->values[i]->dispatch_motion_event();
1510 if(!result) result = cursor_motion_event(); // give to user
1514 int BC_WindowBase::dispatch_keypress_event()
1517 if(top_level == this)
1519 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1522 for(int i = 0; i < subwindows->total && !result; i++)
1524 result = subwindows->values[i]->dispatch_keypress_event();
1527 if(!result) result = keypress_event();
1532 int BC_WindowBase::dispatch_keyrelease_event()
1535 if(top_level == this)
1537 if(active_subwindow) result = active_subwindow->dispatch_keyrelease_event();
1540 for(int i = 0; i < subwindows->total && !result; i++)
1542 result = subwindows->values[i]->dispatch_keyrelease_event();
1545 if(!result) result = keyrelease_event();
1550 int BC_WindowBase::dispatch_focus_in()
1552 for(int i = 0; i < subwindows->total; i++)
1554 subwindows->values[i]->dispatch_focus_in();
1562 int BC_WindowBase::dispatch_focus_out()
1564 for(int i = 0; i < subwindows->total; i++)
1566 subwindows->values[i]->dispatch_focus_out();
1574 int BC_WindowBase::get_has_focus()
1576 return top_level->has_focus;
1579 int BC_WindowBase::get_deleting()
1581 if(is_deleting) return 1;
1582 if(parent_window && parent_window->get_deleting()) return 1;
1586 int BC_WindowBase::dispatch_button_press()
1591 if(top_level == this)
1593 if(active_menubar) result = active_menubar->dispatch_button_press();
1594 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1595 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1598 for(int i = 0; i < subwindows->total && !result; i++)
1600 result = subwindows->values[i]->dispatch_button_press();
1603 if(!result) result = button_press_event();
1609 int BC_WindowBase::dispatch_button_release()
1612 if(top_level == this)
1614 if(active_menubar) result = active_menubar->dispatch_button_release();
1615 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1616 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1617 if(!result && button_number != 4 && button_number != 5)
1618 result = dispatch_drag_stop();
1621 for(int i = 0; i < subwindows->total && !result; i++)
1623 result = subwindows->values[i]->dispatch_button_release();
1628 result = button_release_event();
1635 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1638 // all repeat event handlers get called and decide based on activity and duration
1639 // whether to respond
1640 for(int i = 0; i < subwindows->total; i++)
1642 subwindows->values[i]->dispatch_repeat_event(duration);
1646 repeat_event(duration);
1650 // Unlock next repeat signal
1651 if(window_type == MAIN_WINDOW)
1653 #ifdef SINGLE_THREAD
1654 BC_Display::display_global->unlock_repeaters(duration);
1656 for(int i = 0; i < repeaters.total; i++)
1658 if(repeaters.values[i]->delay == duration)
1660 repeaters.values[i]->repeat_lock->unlock();
1668 void BC_WindowBase::unhide_cursor()
1673 if(top_level->is_hourglass)
1674 set_cursor(HOURGLASS_CURSOR, 1, 0);
1676 set_cursor(current_cursor, 1, 0);
1678 cursor_timer->update();
1682 void BC_WindowBase::update_video_cursor()
1684 if(video_on && !is_transparent)
1686 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1689 set_cursor(TRANSPARENT_CURSOR, 1, 1);
1690 cursor_timer->update();
1695 cursor_timer->update();
1700 int BC_WindowBase::dispatch_cursor_leave()
1704 for(int i = 0; i < subwindows->total; i++)
1706 subwindows->values[i]->dispatch_cursor_leave();
1709 cursor_leave_event();
1713 int BC_WindowBase::dispatch_cursor_enter()
1719 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1720 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1721 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1723 for(int i = 0; !result && i < subwindows->total; i++)
1725 result = subwindows->values[i]->dispatch_cursor_enter();
1728 if(!result) result = cursor_enter_event();
1732 int BC_WindowBase::cursor_enter_event()
1737 int BC_WindowBase::cursor_leave_event()
1742 int BC_WindowBase::close_event()
1748 int BC_WindowBase::dispatch_drag_start()
1751 if(active_menubar) result = active_menubar->dispatch_drag_start();
1752 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1753 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1755 for(int i = 0; i < subwindows->total && !result; i++)
1757 result = subwindows->values[i]->dispatch_drag_start();
1760 if(!result) result = is_dragging = drag_start_event();
1764 int BC_WindowBase::dispatch_drag_stop()
1768 for(int i = 0; i < subwindows->total && !result; i++)
1770 result = subwindows->values[i]->dispatch_drag_stop();
1773 if(is_dragging && !result)
1783 int BC_WindowBase::dispatch_drag_motion()
1786 for(int i = 0; i < subwindows->total && !result; i++)
1788 result = subwindows->values[i]->dispatch_drag_motion();
1791 if(is_dragging && !result)
1793 drag_motion_event();
1801 int BC_WindowBase::show_tooltip(const char *text, int x, int y, int w, int h)
1804 int forced = !text ? force_tooltip : 1;
1805 if( !text ) text = tooltip_text;
1806 if( !text || (!forced && !get_resources()->tooltips_enabled) ) {
1807 top_level->hide_tooltip();
1811 if(w < 0) w = get_text_width(MEDIUMFONT, text) + TOOLTIP_MARGIN * 2;
1812 if(h < 0) h = get_text_height(MEDIUMFONT, text) + TOOLTIP_MARGIN * 2;
1813 // default x,y (win relative)
1814 if( x < 0 ) x = get_w();
1815 if( y < 0 ) y = get_h();
1817 get_root_coordinates(x, y, &wx, &wy);
1818 // keep the tip inside the window/display
1819 int x0 = top_level->get_x(), x1 = x0 + top_level->get_w();
1820 int x2 = top_level->get_screen_x(0, -1) + top_level->get_screen_w(0, -1);
1821 if( x1 > x2 ) x1 = x2;
1822 if( wx < x0 ) wx = x0;
1823 if( wx >= (x1-=w) ) wx = x1;
1824 int y0 = top_level->get_y(), y1 = y0 + top_level->get_h();
1825 int y2 = top_level->get_root_h(0);
1826 if( y1 > y2 ) y1 = y2;
1827 if( wy < y0 ) wy = y0;
1828 if( wy >= (y1-=h) ) wy = y1;
1829 // avoid tip under cursor (flickers)
1831 get_abs_cursor(abs_x,abs_y, 0);
1832 if( wx < abs_x && abs_x < wx+w && wy < abs_y && abs_y < wy+h ) {
1833 if( wx-abs_x < wy-abs_y )
1840 tooltip_popup = new BC_Popup(top_level, wx, wy, w, h,
1841 get_resources()->tooltip_bg_color);
1844 tooltip_popup->reposition_window(wx, wy, w, h);
1847 tooltip_popup->flash();
1848 tooltip_popup->flush();
1852 int BC_WindowBase::hide_tooltip()
1855 for(int i = 0; i < subwindows->total; i++)
1857 subwindows->values[i]->hide_tooltip();
1863 delete tooltip_popup;
1869 const char *BC_WindowBase::get_tooltip()
1871 return tooltip_text;
1874 int BC_WindowBase::set_tooltip(const char *text)
1876 tooltip_text = text;
1878 // Update existing tooltip if it is visible
1882 tooltip_popup->flash();
1886 // signal the event handler to repeat
1887 int BC_WindowBase::set_repeat(int64_t duration)
1891 printf("BC_WindowBase::set_repeat duration=%jd\n", duration);
1894 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1896 #ifdef SINGLE_THREAD
1897 BC_Display::display_global->set_repeat(this, duration);
1899 // test repeater database for duplicates
1900 for(int i = 0; i < repeaters.total; i++)
1903 if(repeaters.values[i]->delay == duration)
1905 repeaters.values[i]->start_repeating(this);
1910 BC_Repeater *repeater = new BC_Repeater(this, duration);
1911 repeater->initialize();
1912 repeaters.append(repeater);
1913 repeater->start_repeating();
1918 int BC_WindowBase::unset_repeat(int64_t duration)
1920 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1922 #ifdef SINGLE_THREAD
1923 BC_Display::display_global->unset_repeat(this, duration);
1925 for(int i = 0; i < repeaters.total; i++)
1927 if(repeaters.values[i]->delay == duration)
1929 repeaters.values[i]->stop_repeating();
1937 int BC_WindowBase::unset_all_repeaters()
1939 #ifdef SINGLE_THREAD
1940 BC_Display::display_global->unset_all_repeaters(this);
1942 for(int i = 0; i < repeaters.total; i++)
1944 repeaters.values[i]->stop_repeating();
1946 repeaters.remove_all_objects();
1951 // long BC_WindowBase::get_repeat_id()
1953 // return top_level->next_repeat_id++;
1956 XEvent *BC_WindowBase::new_xevent()
1958 XEvent *event = new XEvent;
1959 memset(event, 0, sizeof(*event));
1963 #ifndef SINGLE_THREAD
1964 int BC_WindowBase::arm_repeat(int64_t duration)
1966 XEvent *event = new_xevent();
1967 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1968 ptr->type = ClientMessage;
1969 ptr->message_type = RepeaterXAtom;
1971 ptr->data.l[0] = duration;
1973 // Couldn't use XSendEvent since it locked up randomly.
1979 int BC_WindowBase::receive_custom_xatoms(xatom_event *event)
1984 int BC_WindowBase::send_custom_xatom(xatom_event *event)
1986 #ifndef SINGLE_THREAD
1987 XEvent *myevent = new_xevent();
1988 XClientMessageEvent *ptr = (XClientMessageEvent*)myevent;
1989 ptr->type = ClientMessage;
1990 ptr->message_type = event->message_type;
1991 ptr->format = event->format;
1992 ptr->data.l[0] = event->data.l[0];
1993 ptr->data.l[1] = event->data.l[1];
1994 ptr->data.l[2] = event->data.l[2];
1995 ptr->data.l[3] = event->data.l[3];
1996 ptr->data.l[4] = event->data.l[4];
2005 Atom BC_WindowBase::create_xatom(const char *atom_name)
2007 return XInternAtom(display, atom_name, False);
2010 int BC_WindowBase::get_atoms()
2012 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
2013 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
2014 DestroyAtom = XInternAtom(display, "BC_DESTROY_WINDOW", False);
2015 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
2016 if( (ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False)) != 0 )
2017 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32,
2018 PropModeReplace, (unsigned char *)&DelWinXAtom, True);
2024 void BC_WindowBase::init_cursors()
2026 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
2027 cross_cursor = XCreateFontCursor(display, XC_crosshair);
2028 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
2029 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
2030 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
2031 move_cursor = XCreateFontCursor(display, XC_fleur);
2032 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
2033 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
2034 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
2035 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
2036 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
2037 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
2038 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
2039 hourglass_cursor = XCreateFontCursor(display, XC_watch);
2040 grabbed_cursor = create_grab_cursor();
2042 static char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
2043 Colormap colormap = DefaultColormap(display, screen);
2044 Pixmap pixmap_bottom = XCreateBitmapFromData(display,
2045 rootwin, cursor_data, 8, 8);
2046 XColor black, dummy;
2047 XAllocNamedColor(display, colormap, "black", &black, &dummy);
2048 transparent_cursor = XCreatePixmapCursor(display,
2049 pixmap_bottom, pixmap_bottom, &black, &black, 0, 0);
2050 // XDefineCursor(display, win, transparent_cursor);
2051 XFreePixmap(display, pixmap_bottom);
2054 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
2056 int color_model = BC_TRANSPARENCY;
2060 color_model = BC_RGB8;
2063 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
2066 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
2069 color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
2075 int BC_WindowBase::init_colors()
2078 current_color_value = current_color_pixel = 0;
2080 // Get the real depth
2083 ximage = XCreateImage(top_level->display,
2085 top_level->default_depth,
2093 bits_per_pixel = ximage->bits_per_pixel;
2094 XDestroyImage(ximage);
2096 color_model = evaluate_color_model(client_byte_order,
2099 // Get the color model
2104 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
2105 create_private_colors();
2108 cmap = DefaultColormap(display, screen);
2109 create_shared_colors();
2112 allocate_color_table();
2116 //cmap = DefaultColormap(display, screen);
2117 cmap = XCreateColormap(display, rootwin, vis, AllocNone );
2123 int BC_WindowBase::create_private_colors()
2128 for(int i = 0; i < 255; i++)
2130 color = (i & 0xc0) << 16;
2131 color += (i & 0x38) << 10;
2132 color += (i & 0x7) << 5;
2133 color_table[i][0] = color;
2135 create_shared_colors(); // overwrite the necessary colors on the table
2140 int BC_WindowBase::create_color(int color)
2142 if(total_colors == 256)
2144 // replace the closest match with an exact match
2145 color_table[get_color_rgb8(color)][0] = color;
2149 // add the color to the table
2150 color_table[total_colors][0] = color;
2156 int BC_WindowBase::create_shared_colors()
2158 create_color(BLACK);
2159 create_color(WHITE);
2161 create_color(LTGREY);
2162 create_color(MEGREY);
2163 create_color(MDGREY);
2164 create_color(DKGREY);
2166 create_color(LTCYAN);
2167 create_color(MECYAN);
2168 create_color(MDCYAN);
2169 create_color(DKCYAN);
2171 create_color(LTGREEN);
2172 create_color(GREEN);
2173 create_color(DKGREEN);
2175 create_color(LTPINK);
2179 create_color(LTBLUE);
2181 create_color(DKBLUE);
2183 create_color(LTYELLOW);
2184 create_color(MEYELLOW);
2185 create_color(MDYELLOW);
2186 create_color(DKYELLOW);
2188 create_color(LTPURPLE);
2189 create_color(MEPURPLE);
2190 create_color(MDPURPLE);
2191 create_color(DKPURPLE);
2193 create_color(FGGREY);
2194 create_color(MNBLUE);
2195 create_color(ORANGE);
2196 create_color(FTGREY);
2201 Cursor BC_WindowBase::create_grab_cursor()
2203 int iw = 23, iw1 = iw-1, iw2 = iw/2;
2204 int ih = 23, ih1 = ih-1, ih2 = ih/2;
2205 VFrame grab(iw,ih,BC_RGB888);
2207 grab.set_pixel_color(RED); // fg
2208 grab.draw_smooth(iw2,0, iw1,0, iw1,ih2);
2209 grab.draw_smooth(iw1,ih2, iw1,ih1, iw2,ih1);
2210 grab.draw_smooth(iw2,ih1, 0,ih1, 0,ih2);
2211 grab.draw_smooth(0,ih2, 0,0, iw2,0);
2212 grab.set_pixel_color(WHITE); // bg
2213 grab.draw_line(0,ih2, iw2-2,ih2);
2214 grab.draw_line(iw2+2,ih2, iw1,ih2);
2215 grab.draw_line(iw2,0, iw2,ih2-2);
2216 grab.draw_line(iw2,ih2+2, iw2,ih1);
2218 int bpl = (iw+7)/8, isz = bpl * ih;
2219 char img[isz]; memset(img, 0, isz);
2220 char msk[isz]; memset(msk, 0, isz);
2221 unsigned char **rows = grab.get_rows();
2222 for( int iy=0; iy<ih; ++iy ) {
2223 char *op = img + iy*bpl;
2224 char *mp = msk + iy*bpl;
2225 unsigned char *ip = rows[iy];
2226 for( int ix=0; ix<iw; ++ix,ip+=3 ) {
2227 if( ip[0] ) mp[ix>>3] |= (1<<(ix&7));
2228 if( !ip[1] ) op[ix>>3] |= (1<<(ix&7));
2231 unsigned long white_pix = WhitePixel(display, screen);
2232 unsigned long black_pix = BlackPixel(display, screen);
2233 Pixmap img_xpm = XCreatePixmapFromBitmapData(display, rootwin,
2234 img, iw,ih, white_pix,black_pix, 1);
2235 Pixmap msk_xpm = XCreatePixmapFromBitmapData(display, rootwin,
2236 msk, iw,ih, white_pix,black_pix, 1);
2239 fc.flags = bc.flags = DoRed | DoGreen | DoBlue;
2240 fc.red = 0xffff; fc.green = fc.blue = 0; // fg
2241 bc.red = 0xffff; bc.green = 0xffff; bc.blue = 0x0000; // bg
2242 Cursor cursor = XCreatePixmapCursor(display, img_xpm,msk_xpm, &fc,&bc, iw2,ih2);
2243 XFreePixmap(display, img_xpm);
2244 XFreePixmap(display, msk_xpm);
2248 int BC_WindowBase::allocate_color_table()
2250 int red, green, blue, color;
2253 for(int i = 0; i < total_colors; i++)
2255 color = color_table[i][0];
2256 red = (color & 0xFF0000) >> 16;
2257 green = (color & 0x00FF00) >> 8;
2258 blue = color & 0xFF;
2260 col.flags = DoRed | DoGreen | DoBlue;
2261 col.red = red<<8 | red;
2262 col.green = green<<8 | green;
2263 col.blue = blue<<8 | blue;
2265 XAllocColor(display, cmap, &col);
2266 color_table[i][1] = col.pixel;
2269 XInstallColormap(display, cmap);
2273 int BC_WindowBase::init_window_shape()
2275 if(bg_pixmap && bg_pixmap->use_alpha())
2277 XShapeCombineMask(top_level->display,
2278 this->win, ShapeBounding, 0, 0,
2279 bg_pixmap->get_alpha(), ShapeSet);
2285 int BC_WindowBase::init_gc()
2287 unsigned long gcmask;
2288 gcmask = GCFont | GCGraphicsExposures;
2291 gcvalues.font = mediumfont->fid; // set the font
2292 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
2293 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
2295 // gcmask = GCCapStyle | GCJoinStyle;
2296 // XGetGCValues(display, gc, gcmask, &gcvalues);
2297 // printf("BC_WindowBase::init_gc %d %d %d\n", __LINE__, gcvalues.cap_style, gcvalues.join_style);
2301 int BC_WindowBase::init_fonts()
2303 if( !(smallfont = XLoadQueryFont(display, _(resources.small_font))) )
2304 if( !(smallfont = XLoadQueryFont(display, _(resources.small_font2))) )
2305 smallfont = XLoadQueryFont(display, "fixed");
2306 if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font))) )
2307 if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) )
2308 mediumfont = XLoadQueryFont(display, "fixed");
2309 if( !(largefont = XLoadQueryFont(display, _(resources.large_font))) )
2310 if( !(largefont = XLoadQueryFont(display, _(resources.large_font2))) )
2311 largefont = XLoadQueryFont(display, "fixed");
2312 if( !(bigfont = XLoadQueryFont(display, _(resources.big_font))) )
2313 if( !(bigfont = XLoadQueryFont(display, _(resources.big_font2))) )
2314 bigfont = XLoadQueryFont(display, "fixed");
2316 if((clockfont = XLoadQueryFont(display, _(resources.clock_font))) == NULL)
2317 if((clockfont = XLoadQueryFont(display, _(resources.clock_font2))) == NULL)
2318 clockfont = XLoadQueryFont(display, "fixed");
2321 if(get_resources()->use_fontset)
2326 // FIXME: should check the m,d,n values
2327 smallfontset = XCreateFontSet(display, resources.small_fontset, &m, &n, &d);
2329 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2330 mediumfontset = XCreateFontSet(display, resources.medium_fontset, &m, &n, &d);
2331 if( !mediumfontset )
2332 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2333 largefontset = XCreateFontSet(display, resources.large_fontset, &m, &n, &d);
2335 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2336 bigfontset = XCreateFontSet(display, resources.big_fontset, &m, &n, &d);
2338 bigfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2339 clockfontset = XCreateFontSet(display, resources.clock_fontset, &m, &n, &d);
2341 clockfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2342 if(clockfontset && bigfontset && largefontset && mediumfontset && smallfontset) {
2343 curr_fontset = mediumfontset;
2344 get_resources()->use_fontset = 1;
2348 get_resources()->use_fontset = 0;
2355 void BC_WindowBase::init_xft()
2358 if( !get_resources()->use_xft ) return;
2359 // apparently, xft is not reentrant, more than this is needed
2360 static Mutex xft_init_lock("BC_WindowBase::xft_init_lock", 0);
2361 xft_init_lock.lock("BC_WindowBase::init_xft");
2362 if(!(smallfont_xft =
2363 (resources.small_font_xft[0] == '-' ?
2364 xftFontOpenXlfd(display, screen, resources.small_font_xft) :
2365 xftFontOpenName(display, screen, resources.small_font_xft))) )
2366 if(!(smallfont_xft =
2367 xftFontOpenXlfd(display, screen, resources.small_font_xft2)))
2368 smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2369 if(!(mediumfont_xft =
2370 (resources.medium_font_xft[0] == '-' ?
2371 xftFontOpenXlfd(display, screen, resources.medium_font_xft) :
2372 xftFontOpenName(display, screen, resources.medium_font_xft))) )
2373 if(!(mediumfont_xft =
2374 xftFontOpenXlfd(display, screen, resources.medium_font_xft2)))
2375 mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2376 if(!(largefont_xft =
2377 (resources.large_font_xft[0] == '-' ?
2378 xftFontOpenXlfd(display, screen, resources.large_font_xft) :
2379 xftFontOpenName(display, screen, resources.large_font_xft))) )
2380 if(!(largefont_xft =
2381 xftFontOpenXlfd(display, screen, resources.large_font_xft2)))
2382 largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
2384 (resources.big_font_xft[0] == '-' ?
2385 xftFontOpenXlfd(display, screen, resources.big_font_xft) :
2386 xftFontOpenName(display, screen, resources.big_font_xft))) )
2388 xftFontOpenXlfd(display, screen, resources.big_font_xft2)))
2389 bigfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2390 if(!(clockfont_xft =
2391 (resources.clock_font_xft[0] == '-' ?
2392 xftFontOpenXlfd(display, screen, resources.clock_font_xft) :
2393 xftFontOpenName(display, screen, resources.clock_font_xft))) )
2394 clockfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2397 if(!(bold_smallfont_xft =
2398 (resources.small_b_font_xft[0] == '-' ?
2399 xftFontOpenXlfd(display, screen, resources.small_b_font_xft) :
2400 xftFontOpenName(display, screen, resources.small_b_font_xft))) )
2401 bold_smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2402 if(!(bold_mediumfont_xft =
2403 (resources.medium_b_font_xft[0] == '-' ?
2404 xftFontOpenXlfd(display, screen, resources.medium_b_font_xft) :
2405 xftFontOpenName(display, screen, resources.medium_b_font_xft))) )
2406 bold_mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2407 if(!(bold_largefont_xft =
2408 (resources.large_b_font_xft[0] == '-' ?
2409 xftFontOpenXlfd(display, screen, resources.large_b_font_xft) :
2410 xftFontOpenName(display, screen, resources.large_b_font_xft))) )
2411 bold_largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
2413 if( !smallfont_xft || !mediumfont_xft || !largefont_xft || !bigfont_xft ||
2414 !bold_largefont_xft || !bold_mediumfont_xft || !bold_largefont_xft ||
2416 printf("BC_WindowBase::init_fonts: no xft fonts found:"
2417 " %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n",
2418 resources.small_font_xft, smallfont_xft,
2419 resources.medium_font_xft, mediumfont_xft,
2420 resources.large_font_xft, largefont_xft,
2421 resources.big_font_xft, bigfont_xft,
2422 resources.clock_font_xft, clockfont_xft,
2423 resources.small_b_font_xft, bold_smallfont_xft,
2424 resources.medium_b_font_xft, bold_mediumfont_xft,
2425 resources.large_b_font_xft, bold_largefont_xft);
2426 get_resources()->use_xft = 0;
2429 // _XftDisplayInfo needs a lock.
2430 xftDefaultHasRender(display);
2431 xft_init_lock.unlock();
2435 void BC_WindowBase::init_im()
2437 XIMStyles *xim_styles;
2440 if(!(input_method = XOpenIM(display, NULL, NULL, NULL)))
2442 printf("BC_WindowBase::init_im: Could not open input method.\n");
2445 if(XGetIMValues(input_method, XNQueryInputStyle, &xim_styles, NULL) ||
2448 printf("BC_WindowBase::init_im: Input method doesn't support any styles.\n");
2449 XCloseIM(input_method);
2454 for(int z = 0; z < xim_styles->count_styles; z++)
2456 if(xim_styles->supported_styles[z] == (XIMPreeditNothing | XIMStatusNothing))
2458 xim_style = xim_styles->supported_styles[z];
2466 printf("BC_WindowBase::init_im: Input method doesn't support the style we need.\n");
2467 XCloseIM(input_method);
2471 input_context = XCreateIC(input_method, XNInputStyle, xim_style,
2472 XNClientWindow, win, XNFocusWindow, win, NULL);
2475 printf("BC_WindowBase::init_im: Failed to create input context.\n");
2476 XCloseIM(input_method);
2481 void BC_WindowBase::finit_im()
2483 if( input_context ) {
2484 XDestroyIC(input_context);
2487 if( input_method ) {
2488 XCloseIM(input_method);
2494 int BC_WindowBase::get_color(int64_t color)
2496 // return pixel of color
2497 // use this only for drawing subwindows not for bitmaps
2498 int i, test, difference;
2504 return get_color_rgb8(color);
2505 // test last color looked up
2506 if(current_color_value == color)
2507 return current_color_pixel;
2510 current_color_value = color;
2511 for(i = 0; i < total_colors; i++)
2513 if(color_table[i][0] == color)
2515 current_color_pixel = color_table[i][1];
2516 return current_color_pixel;
2520 // find nearest match
2521 difference = 0xFFFFFF;
2523 for(i = 0; i < total_colors; i++)
2525 test = abs((int)(color_table[i][0] - color));
2527 if(test < difference)
2529 current_color_pixel = color_table[i][1];
2533 return current_color_pixel;
2536 return get_color_rgb16(color);
2539 return get_color_bgr16(color);
2543 return client_byte_order == server_byte_order ?
2544 color : get_color_bgr24(color);
2552 int BC_WindowBase::get_color_rgb8(int color)
2556 pixel = (color & 0xc00000) >> 16;
2557 pixel += (color & 0xe000) >> 10;
2558 pixel += (color & 0xe0) >> 5;
2562 int64_t BC_WindowBase::get_color_rgb16(int color)
2565 result = (color & 0xf80000) >> 8;
2566 result += (color & 0xfc00) >> 5;
2567 result += (color & 0xf8) >> 3;
2572 int64_t BC_WindowBase::get_color_bgr16(int color)
2575 result = (color & 0xf80000) >> 19;
2576 result += (color & 0xfc00) >> 5;
2577 result += (color & 0xf8) << 8;
2582 int64_t BC_WindowBase::get_color_bgr24(int color)
2585 result = (color & 0xff) << 16;
2586 result += (color & 0xff00);
2587 result += (color & 0xff0000) >> 16;
2591 void BC_WindowBase::start_video()
2593 cursor_timer->update();
2595 // set_color(BLACK);
2596 // draw_box(0, 0, get_w(), get_h());
2600 void BC_WindowBase::stop_video()
2608 int64_t BC_WindowBase::get_color()
2610 return top_level->current_color;
2613 void BC_WindowBase::set_color(int64_t color)
2615 top_level->current_color = color;
2616 XSetForeground(top_level->display,
2618 top_level->get_color(color));
2621 void BC_WindowBase::set_opaque()
2623 XSetFunction(top_level->display, top_level->gc, GXcopy);
2626 void BC_WindowBase::set_inverse()
2628 XSetFunction(top_level->display, top_level->gc, GXxor);
2631 void BC_WindowBase::set_line_width(int value)
2633 this->line_width = value;
2634 XSetLineAttributes(top_level->display, top_level->gc, value, /* line_width */
2635 line_dashes == 0 ? LineSolid : LineOnOffDash, /* line_style */
2636 line_dashes == 0 ? CapRound : CapNotLast, /* cap_style */
2637 JoinMiter); /* join_style */
2639 if(line_dashes > 0) {
2640 const char dashes = line_dashes;
2641 XSetDashes(top_level->display, top_level->gc, 0, &dashes, 1);
2644 // XGCValues gcvalues;
2645 // unsigned long gcmask;
2646 // gcmask = GCCapStyle | GCJoinStyle;
2647 // XGetGCValues(top_level->display, top_level->gc, gcmask, &gcvalues);
2648 // printf("BC_WindowBase::set_line_width %d %d %d\n", __LINE__, gcvalues.cap_style, gcvalues.join_style);
2651 void BC_WindowBase::set_line_dashes(int value)
2653 line_dashes = value;
2654 // call XSetLineAttributes
2655 set_line_width(line_width);
2659 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2663 case ARROW_CURSOR: return top_level->arrow_cursor;
2664 case CROSS_CURSOR: return top_level->cross_cursor;
2665 case IBEAM_CURSOR: return top_level->ibeam_cursor;
2666 case VSEPARATE_CURSOR: return top_level->vseparate_cursor;
2667 case HSEPARATE_CURSOR: return top_level->hseparate_cursor;
2668 case MOVE_CURSOR: return top_level->move_cursor;
2669 case LEFT_CURSOR: return top_level->left_cursor;
2670 case RIGHT_CURSOR: return top_level->right_cursor;
2671 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;
2672 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor;
2673 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor;
2674 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor;
2675 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor;
2676 case HOURGLASS_CURSOR: return top_level->hourglass_cursor;
2677 case TRANSPARENT_CURSOR: return top_level->transparent_cursor;
2678 case GRABBED_CURSOR: return top_level->grabbed_cursor;
2683 void BC_WindowBase::set_cursor(int cursor, int override, int flush)
2685 // inherit cursor from parent
2688 XUndefineCursor(top_level->display, win);
2689 current_cursor = cursor;
2692 // don't change cursor if overridden
2693 if((!top_level->is_hourglass && !is_transparent) ||
2696 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2697 if(flush) this->flush();
2700 if(!override) current_cursor = cursor;
2703 void BC_WindowBase::set_x_cursor(int cursor)
2705 temp_cursor = XCreateFontCursor(top_level->display, cursor);
2706 XDefineCursor(top_level->display, win, temp_cursor);
2707 current_cursor = cursor;
2711 int BC_WindowBase::get_cursor()
2713 return current_cursor;
2716 void BC_WindowBase::start_hourglass()
2718 top_level->start_hourglass_recursive();
2722 void BC_WindowBase::stop_hourglass()
2724 top_level->stop_hourglass_recursive();
2728 void BC_WindowBase::start_hourglass_recursive()
2730 if(this == top_level)
2738 set_cursor(HOURGLASS_CURSOR, 1, 0);
2739 for(int i = 0; i < subwindows->total; i++)
2741 subwindows->values[i]->start_hourglass_recursive();
2746 void BC_WindowBase::stop_hourglass_recursive()
2748 if(this == top_level)
2750 if(hourglass_total == 0) return;
2751 top_level->hourglass_total--;
2754 if(!top_level->hourglass_total)
2756 top_level->is_hourglass = 0;
2758 // Cause set_cursor to perform change
2760 set_cursor(current_cursor, 1, 0);
2762 for(int i = 0; i < subwindows->total; i++)
2764 subwindows->values[i]->stop_hourglass_recursive();
2772 XFontStruct* BC_WindowBase::get_font_struct(int font)
2774 // Clear out unrelated flags
2775 if(font & BOLDFACE) font ^= BOLDFACE;
2778 case SMALLFONT: return top_level->smallfont; break;
2779 case MEDIUMFONT: return top_level->mediumfont; break;
2780 case LARGEFONT: return top_level->largefont; break;
2781 case BIGFONT: return top_level->bigfont; break;
2782 case CLOCKFONT: return top_level->clockfont; break;
2787 XFontSet BC_WindowBase::get_fontset(int font)
2791 if(get_resources()->use_fontset)
2793 switch(font & 0xff) {
2794 case SMALLFONT: fs = top_level->smallfontset; break;
2795 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2796 case LARGEFONT: fs = top_level->largefontset; break;
2797 case BIGFONT: fs = top_level->bigfontset; break;
2798 case CLOCKFONT: fs = top_level->clockfontset; break;
2806 XftFont* BC_WindowBase::get_xft_struct(int font)
2809 case SMALLFONT: return (XftFont*)top_level->smallfont_xft;
2810 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft;
2811 case LARGEFONT: return (XftFont*)top_level->largefont_xft;
2812 case BIGFONT: return (XftFont*)top_level->bigfont_xft;
2813 case CLOCKFONT: return (XftFont*)top_level->clockfont_xft;
2814 case MEDIUMFONT_3D: return (XftFont*)top_level->bold_mediumfont_xft;
2815 case SMALLFONT_3D: return (XftFont*)top_level->bold_smallfont_xft;
2816 case LARGEFONT_3D: return (XftFont*)top_level->bold_largefont_xft;
2824 int BC_WindowBase::get_current_font()
2826 return top_level->current_font;
2829 void BC_WindowBase::set_font(int font)
2831 top_level->current_font = font;
2834 if(get_resources()->use_xft) {}
2837 if(get_resources()->use_fontset) {
2841 if(get_font_struct(font))
2843 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2849 void BC_WindowBase::set_fontset(int font)
2853 if(get_resources()->use_fontset) {
2855 case SMALLFONT: fs = top_level->smallfontset; break;
2856 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2857 case LARGEFONT: fs = top_level->largefontset; break;
2858 case BIGFONT: fs = top_level->bigfontset; break;
2859 case CLOCKFONT: fs = top_level->clockfontset; break;
2867 XFontSet BC_WindowBase::get_curr_fontset(void)
2869 if(get_resources()->use_fontset)
2870 return curr_fontset;
2874 int BC_WindowBase::get_single_text_width(int font, const char *text, int length)
2877 if(get_resources()->use_xft && get_xft_struct(font))
2880 #ifdef X_HAVE_UTF8_STRING
2881 if(get_resources()->locale_utf8)
2883 xftTextExtentsUtf8(top_level->display,
2884 get_xft_struct(font),
2885 (const XftChar8 *)text,
2892 xftTextExtents8(top_level->display,
2893 get_xft_struct(font),
2894 (const XftChar8 *)text,
2898 return extents.xOff;
2902 if(get_resources()->use_fontset && top_level->get_fontset(font))
2903 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2905 if(get_font_struct(font))
2906 return XTextWidth(get_font_struct(font), text, length);
2912 case MEDIUM_7SEGMENT:
2913 return get_resources()->medium_7segment[0]->get_w() * length;
2923 int BC_WindowBase::get_text_width(int font, const char *text, int length)
2925 int i, j, w = 0, line_w = 0;
2926 if(length < 0) length = strlen(text);
2928 for(i = 0, j = 0; i <= length; i++)
2933 line_w = get_single_text_width(font, &text[j], i - j);
2939 line_w = get_single_text_width(font, &text[j], length - j);
2941 if(line_w > w) w = line_w;
2944 if(i > length && w == 0)
2946 w = get_single_text_width(font, text, length);
2952 int BC_WindowBase::get_text_width(int font, const wchar_t *text, int length)
2955 if( length < 0 ) length = wcslen(text);
2957 for( i=j=0; i<length && text[i]; ++i ) {
2958 if( text[i] != '\n' ) continue;
2960 int lw = get_single_text_width(font, &text[j], i-j);
2961 if( w < lw ) w = lw;
2966 int lw = get_single_text_width(font, &text[j], length-j);
2967 if( w < lw ) w = lw;
2973 int BC_WindowBase::get_text_ascent(int font)
2977 if( (fstruct = get_xft_struct(font)) != 0 )
2978 return fstruct->ascent;
2980 if(get_resources()->use_fontset && top_level->get_fontset(font))
2982 XFontSetExtents *extents;
2984 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2985 return -extents->max_logical_extent.y;
2988 if(get_font_struct(font))
2989 return top_level->get_font_struct(font)->ascent;
2992 case MEDIUM_7SEGMENT:
2993 return get_resources()->medium_7segment[0]->get_h();
2998 int BC_WindowBase::get_text_descent(int font)
3002 if( (fstruct = get_xft_struct(font)) != 0 )
3003 return fstruct->descent;
3005 if(get_resources()->use_fontset && top_level->get_fontset(font)) {
3006 XFontSetExtents *extents;
3007 extents = XExtentsOfFontSet(top_level->get_fontset(font));
3008 return (extents->max_logical_extent.height
3009 + extents->max_logical_extent.y);
3012 if(get_font_struct(font))
3013 return top_level->get_font_struct(font)->descent;
3018 int BC_WindowBase::get_text_height(int font, const char *text)
3023 if( (fstruct = get_xft_struct(font)) != 0 )
3024 rowh = fstruct->height;
3027 rowh = get_text_ascent(font) + get_text_descent(font);
3029 if(!text) return rowh;
3031 // Add height of lines
3032 int h = 0, i, length = strlen(text);
3033 for(i = 0; i <= length; i++)
3044 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
3046 if(color_model < 0) color_model = top_level->get_color_model();
3047 return new BC_Bitmap(top_level, w, h, color_model);
3050 void BC_WindowBase::init_wait()
3052 #ifndef SINGLE_THREAD
3053 if(window_type != MAIN_WINDOW)
3054 top_level->init_wait();
3055 init_lock->lock("BC_WindowBase::init_wait");
3056 init_lock->unlock();
3060 int BC_WindowBase::accel_available(int color_model, int lock_it)
3062 if( window_type != MAIN_WINDOW )
3063 return top_level->accel_available(color_model, lock_it);
3065 lock_window("BC_WindowBase::accel_available");
3067 switch(color_model) {
3069 grab_port_id(color_model);
3073 grab_port_id(color_model);
3082 //printf("BC_WindowBase::accel_available %d %d\n", color_model, xvideo_port_id);
3083 return xvideo_port_id >= 0 ? 1 : 0;
3087 int BC_WindowBase::grab_port_id(int color_model)
3089 if( !get_resources()->use_xvideo || // disabled
3090 !get_resources()->use_shm ) // Only local server is fast enough.
3092 if( xvideo_port_id >= 0 )
3093 return xvideo_port_id;
3095 unsigned int ver, rev, reqBase, eventBase, errorBase;
3096 if( Success != XvQueryExtension(display, // XV extension is available
3097 &ver, &rev, &reqBase, &eventBase, &errorBase) )
3100 // XV adaptors are available
3101 unsigned int numAdapt = 0;
3102 XvAdaptorInfo *info = 0;
3103 XvQueryAdaptors(display, DefaultRootWindow(display), &numAdapt, &info);
3107 // Translate from color_model to X color model
3108 int x_color_model = BC_CModels::bc_to_x(color_model);
3110 // Get adaptor with desired color model
3111 for( int i = 0; i < (int)numAdapt && xvideo_port_id == -1; i++) {
3112 if( !(info[i].type & XvImageMask) || !info[i].num_ports ) continue;
3113 // adaptor supports XvImages
3114 int numFormats = 0, numPorts = info[i].num_ports;
3115 XvImageFormatValues *formats =
3116 XvListImageFormats(display, info[i].base_id, &numFormats);
3117 if( !formats ) continue;
3119 for( int j=0; j<numFormats && xvideo_port_id<0; ++j ) {
3120 if( formats[j].id != x_color_model ) continue;
3121 // this adaptor supports the desired format, grab a port
3122 for( int k=0; k<numPorts; ++k ) {
3123 if( Success == XvGrabPort(top_level->display,
3124 info[i].base_id+k, CurrentTime) ) {
3125 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
3126 xvideo_port_id = info[i].base_id + k;
3134 XvFreeAdaptorInfo(info);
3136 return xvideo_port_id;
3140 int BC_WindowBase::show_window(int flush)
3142 for(int i = 0; i < subwindows->size(); i++)
3144 subwindows->get(i)->show_window(0);
3147 XMapWindow(top_level->display, win);
3148 if(flush) XFlush(top_level->display);
3149 // XSync(top_level->display, 0);
3154 int BC_WindowBase::hide_window(int flush)
3156 for(int i = 0; i < subwindows->size(); i++)
3158 subwindows->get(i)->hide_window(0);
3161 XUnmapWindow(top_level->display, win);
3162 if(flush) this->flush();
3167 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
3169 subwindows->append((BC_SubWindow*)menu_bar);
3171 menu_bar->parent_window = this;
3172 menu_bar->top_level = this->top_level;
3173 menu_bar->initialize();
3177 BC_WindowBase* BC_WindowBase::add_popup(BC_WindowBase *window)
3179 //printf("BC_WindowBase::add_popup window=%p win=%p\n", window, window->win);
3180 if(this != top_level) return top_level->add_popup(window);
3181 popups.append(window);
3185 void BC_WindowBase::remove_popup(BC_WindowBase *window)
3187 //printf("BC_WindowBase::remove_popup %d size=%d window=%p win=%p\n", __LINE__, popups.size(), window, window->win);
3188 if(this != top_level)
3189 top_level->remove_popup(window);
3191 popups.remove(window);
3192 //printf("BC_WindowBase::remove_popup %d size=%d window=%p win=%p\n", __LINE__, popups.size(), window, window->win);
3196 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
3198 subwindows->append(subwindow);
3200 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
3202 // parent window must be set before the subwindow initialization
3203 subwindow->parent_window = this;
3204 subwindow->top_level = this->top_level;
3206 // Execute derived initialization
3207 subwindow->initialize();
3212 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
3214 return add_subwindow(subwindow);
3217 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
3219 if( !top_level->flash_enabled ) return 0;
3220 //printf("BC_WindowBase::flash %d %d %d %d %d\n", __LINE__, w, h, this->w, this->h);
3222 XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
3225 XClearArea(top_level->display, win, x, y, w, h, 0);
3229 XClearWindow(top_level->display, win);
3237 int BC_WindowBase::flash(int flush)
3239 flash(-1, -1, -1, -1, flush);
3243 void BC_WindowBase::flush()
3245 //if(!get_window_lock())
3246 // printf("BC_WindowBase::flush %s not locked\n", top_level->title);
3247 // X gets hosed if Flush/Sync are not user locked (at libX11-1.1.5 / libxcb-1.1.91)
3248 // _XReply deadlocks in condition_wait waiting for xlib lock when waiters!=-1
3249 int locked = get_window_lock();
3250 if( !locked ) lock_window("BC_WindowBase::flush");
3251 XFlush(top_level->display);
3252 if( !locked ) unlock_window();
3255 void BC_WindowBase::sync_display()
3257 int locked = get_window_lock();
3258 if( !locked ) lock_window("BC_WindowBase::sync_display");
3259 XSync(top_level->display, False);
3260 if( !locked ) unlock_window();
3263 int BC_WindowBase::get_window_lock()
3265 #ifdef SINGLE_THREAD
3266 return BC_Display::display_global->get_display_locked();
3268 return top_level->window_lock;
3272 int BC_WindowBase::lock_window(const char *location)
3274 if(top_level && top_level != this)
3276 top_level->lock_window(location);
3281 SET_LOCK(this, title, location);
3282 #ifdef SINGLE_THREAD
3283 BC_Display::lock_display(location);
3285 XLockDisplay(top_level->display);
3286 top_level->display_lock_owner = pthread_self();
3289 ++top_level->window_lock;
3293 printf("BC_WindowBase::lock_window top_level NULL\n");
3298 int BC_WindowBase::unlock_window()
3300 if(top_level && top_level != this)
3302 top_level->unlock_window();
3308 if( !top_level->window_lock ) {
3309 printf("BC_WindowBase::unlock_window %s not locked\n", title);
3312 if( top_level->window_lock > 0 )
3313 if( --top_level->window_lock == 0 )
3314 top_level->display_lock_owner = 0;
3315 #ifdef SINGLE_THREAD
3316 BC_Display::unlock_display();
3318 XUnlockDisplay(top_level->display);
3323 printf("BC_WindowBase::unlock_window top_level NULL\n");
3328 int BC_WindowBase::break_lock()
3330 if( !top_level ) return 0;
3331 if( top_level != this ) return top_level->break_lock();
3332 if( top_level->display_lock_owner != pthread_self() ) return 0;
3333 if( top_level->window_lock != 1 ) return 0;
3336 display_lock_owner = 0;
3337 #ifdef SINGLE_THREAD
3338 BC_Display::unlock_display();
3340 XUnlockDisplay(display);
3345 void BC_WindowBase::set_done(int return_value)
3347 if(done_set) return;
3349 if(window_type != MAIN_WINDOW)
3350 top_level->set_done(return_value);
3353 #ifdef SINGLE_THREAD
3354 this->return_value = return_value;
3355 BC_Display::display_global->arm_completion(this);
3356 completion_lock->unlock();
3357 #else // SINGLE_THREAD
3359 if( !event_thread ) return;
3360 XEvent *event = new_xevent();
3361 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
3362 event->type = ClientMessage;
3363 ptr->message_type = SetDoneXAtom;
3365 this->return_value = return_value;
3366 // May lock up here because XSendEvent doesn't work too well
3367 // asynchronous with XNextEvent.
3368 // This causes BC_WindowEvents to forward a copy of the event to run_window where
3370 // Deletion of event_thread is done at the end of BC_WindowBase::run_window() - by calling the destructor
3376 void BC_WindowBase::close(int return_value)
3378 hide_window(); flush();
3379 set_done(return_value);
3382 int BC_WindowBase::grab(BC_WindowBase *window)
3384 if( window->active_grab && this != window->active_grab ) return 0;
3385 window->active_grab = this;
3386 this->grab_active = window;
3389 int BC_WindowBase::ungrab(BC_WindowBase *window)
3391 if( window->active_grab && this != window->active_grab ) return 0;
3392 window->active_grab = 0;
3393 this->grab_active = 0;
3396 int BC_WindowBase::grab_event_count()
3399 #ifndef SINGLE_THREAD
3400 result = grab_active->get_event_count();
3404 int BC_WindowBase::grab_buttons()
3406 XSync(top_level->display, False);
3407 if( XGrabButton(top_level->display, AnyButton, AnyModifier,
3408 top_level->rootwin, True, ButtonPressMask | ButtonReleaseMask,
3409 GrabModeAsync, GrabModeSync, None, None) == GrabSuccess ) {
3410 set_active_subwindow(this);
3415 void BC_WindowBase::ungrab_buttons()
3417 XUngrabButton(top_level->display, AnyButton, AnyModifier, top_level->rootwin);
3418 set_active_subwindow(0);
3421 void BC_WindowBase::grab_cursor()
3423 Cursor cursor_grab = get_cursor_struct(GRABBED_CURSOR);
3424 XGrabPointer(top_level->display, top_level->rootwin, True,
3425 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
3426 GrabModeAsync, GrabModeAsync, None, cursor_grab, CurrentTime);
3428 void BC_WindowBase::ungrab_cursor()
3430 XUngrabPointer(top_level->display, CurrentTime);
3434 // WidthOfScreen/HeightOfScreen of XDefaultScreenOfDisplay
3435 // this is the bounding box of all the screens
3437 int BC_WindowBase::get_root_w(int lock_display)
3439 if(lock_display) lock_window("BC_WindowBase::get_root_w");
3440 Screen *def_screen = XDefaultScreenOfDisplay(top_level->display);
3441 int result = WidthOfScreen(def_screen);
3442 if(lock_display) unlock_window();
3446 int BC_WindowBase::get_root_h(int lock_display)
3448 if(lock_display) lock_window("BC_WindowBase::get_root_h");
3449 Screen *def_screen = XDefaultScreenOfDisplay(top_level->display);
3450 int result = HeightOfScreen(def_screen);
3451 if(lock_display) unlock_window();
3455 XineramaScreenInfo *
3456 BC_WindowBase::get_xinerama_info(int screen)
3458 if( !xinerama_info || !xinerama_screens ) return 0;
3460 for( int i=0; i<xinerama_screens; ++i )
3461 if( xinerama_info[i].screen_number == screen )
3462 return &xinerama_info[i];
3465 int top_x = get_x(), top_y = get_y();
3466 if( BC_DisplayInfo::left_border >= 0 ) top_x += BC_DisplayInfo::left_border;
3467 if( BC_DisplayInfo::top_border >= 0 ) top_y += BC_DisplayInfo::top_border;
3468 for( int i=0; i<xinerama_screens; ++i ) {
3469 int scr_y = top_y - xinerama_info[i].y_org;
3470 if( scr_y < 0 || scr_y >= xinerama_info[i].height ) continue;
3471 int scr_x = top_x - xinerama_info[i].x_org;
3472 if( scr_x >= 0 && scr_x < xinerama_info[i].width )
3473 return &xinerama_info[i];
3478 void BC_WindowBase::get_fullscreen_geometry(int &wx, int &wy, int &ww, int &wh)
3480 XineramaScreenInfo *info = top_level->get_xinerama_info(-1);
3482 wx = info->x_org; wy = info->y_org;
3483 ww = info->width; wh = info->height;
3486 wx = get_screen_x(0, -1);
3487 wy = get_screen_y(0, -1);
3488 int scr_w0 = get_screen_w(0, 0);
3489 int root_w = get_root_w(0);
3490 int root_h = get_root_h(0);
3491 if( root_w > scr_w0 ) { // multi-headed
3492 if( wx >= scr_w0 ) {
3493 // assumes right side is the big one
3494 ww = root_w - scr_w0;
3498 // use same aspect ratio to compute left height
3500 wh = (w*root_h) / (root_w-scr_w0);
3510 int BC_WindowBase::get_screen_x(int lock_display, int screen)
3513 if(lock_display) lock_window("BC_WindowBase::get_screen_x");
3514 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3517 int root_w = get_root_w(0);
3518 int root_h = get_root_h(0);
3519 // Shift X based on position of current window if dual head
3520 if( (float)root_w/root_h > 1.8 ) {
3521 root_w = get_screen_w(0, 0);
3522 if( top_level->get_x() >= root_w )
3527 result = info->x_org;
3528 if(lock_display) unlock_window();
3532 int BC_WindowBase::get_screen_y(int lock_display, int screen)
3534 if(lock_display) lock_window("BC_WindowBase::get_screen_y");
3535 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3536 int result = !info ? 0 : info->y_org;
3537 if(lock_display) unlock_window();
3541 int BC_WindowBase::get_screen_w(int lock_display, int screen)
3544 if(lock_display) lock_window("BC_WindowBase::get_screen_w");
3545 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3547 int width = get_root_w(0);
3548 int height = get_root_h(0);
3549 if( (float)width/height > 1.8 ) {
3550 // If dual head, the screen width is > 16x9
3551 // but we only want to fill one screen
3552 // this code assumes the "big" screen is on the right
3553 int scr_w0 = width / 2;
3555 case 600: scr_w0 = 800; break;
3556 case 720: scr_w0 = 1280; break;
3557 case 1024: scr_w0 = 1280; break;
3558 case 1200: scr_w0 = 1600; break;
3559 case 1080: scr_w0 = 1920; break;
3561 int scr_w1 = width - scr_w0;
3562 result = screen > 0 ? scr_w1 :
3563 screen == 0 ? scr_w0 :
3564 top_level->get_x() < scr_w0 ? scr_w0 : scr_w1;
3570 result = info->width;
3571 if(lock_display) unlock_window();
3575 int BC_WindowBase::get_screen_h(int lock_display, int screen)
3577 if(lock_display) lock_window("BC_WindowBase::get_screen_h");
3578 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3579 int result = info ? info->height : get_root_h(0);
3580 if(lock_display) unlock_window();
3584 // Bottom right corner
3585 int BC_WindowBase::get_x2()
3590 int BC_WindowBase::get_y2()
3595 int BC_WindowBase::get_video_on()
3600 int BC_WindowBase::get_hidden()
3602 return top_level->hidden;
3605 int BC_WindowBase::cursor_inside()
3607 return (top_level->cursor_x >= 0 &&
3608 top_level->cursor_y >= 0 &&
3609 top_level->cursor_x < w &&
3610 top_level->cursor_y < h);
3613 BC_WindowBase* BC_WindowBase::get_top_level()
3618 BC_WindowBase* BC_WindowBase::get_parent()
3620 return parent_window;
3623 int BC_WindowBase::get_color_model()
3625 return top_level->color_model;
3628 BC_Resources* BC_WindowBase::get_resources()
3630 return &BC_WindowBase::resources;
3633 BC_Synchronous* BC_WindowBase::get_synchronous()
3635 return BC_WindowBase::resources.get_synchronous();
3638 int BC_WindowBase::get_bg_color()
3643 void BC_WindowBase::set_bg_color(int color)
3645 this->bg_color = color;
3648 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
3653 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
3655 top_level->active_subwindow = subwindow;
3658 int BC_WindowBase::activate()
3663 int BC_WindowBase::deactivate()
3665 if(window_type == MAIN_WINDOW)
3667 if( top_level->active_menubar ) {
3668 top_level->active_menubar->deactivate();
3669 top_level->active_menubar = 0;
3671 if( top_level->active_popup_menu ) {
3672 top_level->active_popup_menu->deactivate();
3673 top_level->active_popup_menu = 0;
3675 if( top_level->active_subwindow ) {
3676 top_level->active_subwindow->deactivate();
3677 top_level->active_subwindow = 0;
3679 if( top_level->motion_events && top_level->last_motion_win == this->win )
3680 top_level->motion_events = 0;
3686 int BC_WindowBase::cycle_textboxes(int amount)
3689 BC_WindowBase *new_textbox = 0;
3693 BC_WindowBase *first_textbox = 0;
3694 find_next_textbox(&first_textbox, &new_textbox, result);
3695 if(!new_textbox) new_textbox = first_textbox;
3701 BC_WindowBase *last_textbox = 0;
3702 find_prev_textbox(&last_textbox, &new_textbox, result);
3703 if(!new_textbox) new_textbox = last_textbox;
3707 if(new_textbox != active_subwindow)
3710 new_textbox->activate();
3716 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
3718 // Search subwindows for textbox
3719 for(int i = 0; i < subwindows->total && result < 2; i++)
3721 BC_WindowBase *test_subwindow = subwindows->values[i];
3722 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
3729 if(!*first_textbox) *first_textbox = this;
3733 if(top_level->active_subwindow == this)
3739 *next_textbox = this;
3746 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
3752 if(!*last_textbox) *last_textbox = this;
3756 if(top_level->active_subwindow == this)
3762 *prev_textbox = this;
3767 // Search subwindows for textbox
3768 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
3770 BC_WindowBase *test_subwindow = subwindows->values[i];
3771 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
3776 BC_Clipboard* BC_WindowBase::get_clipboard()
3778 #ifdef SINGLE_THREAD
3779 return BC_Display::display_global->clipboard;
3781 return top_level->clipboard;
3785 Atom BC_WindowBase::to_clipboard(const char *data, long len, int clipboard_num)
3787 return get_clipboard()->to_clipboard(this, data, len, clipboard_num);
3790 long BC_WindowBase::from_clipboard(char *data, long maxlen, int clipboard_num)
3792 return get_clipboard()->from_clipboard(data, maxlen, clipboard_num);
3795 long BC_WindowBase::clipboard_len(int clipboard_num)
3797 return get_clipboard()->clipboard_len(clipboard_num);
3800 int BC_WindowBase::do_selection_clear(Window win)
3802 top_level->event_win = win;
3803 return dispatch_selection_clear();
3806 int BC_WindowBase::dispatch_selection_clear()
3809 for( int i=0; i<subwindows->total && !result; ++i )
3810 result = subwindows->values[i]->dispatch_selection_clear();
3812 result = selection_clear_event();
3817 void BC_WindowBase::get_relative_cursor(int &x, int &y, int lock_window)
3819 int abs_x, abs_y, win_x, win_y;
3820 unsigned int temp_mask;
3823 if(lock_window) this->lock_window("BC_WindowBase::get_relative_cursor");
3824 XQueryPointer(top_level->display, top_level->win,
3825 &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
3828 XTranslateCoordinates(top_level->display, top_level->rootwin,
3829 win, abs_x, abs_y, &x, &y, &temp_win);
3830 if(lock_window) this->unlock_window();
3832 int BC_WindowBase::get_relative_cursor_x(int lock_window)
3835 get_relative_cursor(x, y, lock_window);
3838 int BC_WindowBase::get_relative_cursor_y(int lock_window)
3841 get_relative_cursor(x, y, lock_window);
3845 void BC_WindowBase::get_abs_cursor(int &abs_x, int &abs_y, int lock_window)
3848 unsigned int temp_mask;
3851 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor");
3852 XQueryPointer(top_level->display, top_level->win,
3853 &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
3855 if(lock_window) this->unlock_window();
3857 int BC_WindowBase::get_abs_cursor_x(int lock_window)
3860 get_abs_cursor(abs_x, abs_y, lock_window);
3863 int BC_WindowBase::get_abs_cursor_y(int lock_window)
3866 get_abs_cursor(abs_x, abs_y, lock_window);
3870 void BC_WindowBase::get_pop_cursor(int &px, int &py, int lock_window)
3873 get_abs_cursor(px, py, lock_window);
3874 if( px < margin ) px = margin;
3875 if( py < margin ) py = margin;
3876 int wd = get_screen_w(lock_window,-1) - margin;
3877 if( px > wd ) px = wd;
3878 int ht = get_screen_h(lock_window,-1) - margin;
3879 if( py > ht ) py = ht;
3881 int BC_WindowBase::get_pop_cursor_x(int lock_window)
3884 get_pop_cursor(px, py, lock_window);
3887 int BC_WindowBase::get_pop_cursor_y(int lock_window)
3890 get_pop_cursor(px, py, lock_window);
3894 int BC_WindowBase::match_window(Window win)
3896 if (this->win == win) return 1;
3898 for(int i = 0; i < subwindows->total; i++) {
3899 result = subwindows->values[i]->match_window(win);
3900 if (result) return result;
3906 int BC_WindowBase::get_cursor_over_window()
3908 int abs_x, abs_y, win_x, win_y;
3909 unsigned int mask_return;
3910 Window root_return, child_return;
3912 int ret = XQueryPointer(top_level->display, top_level->rootwin,
3913 &root_return, &child_return, &abs_x, &abs_y,
3914 &win_x, &win_y, &mask_return);
3915 if( ret && child_return == None ) ret = 0;
3916 if( ret && win != child_return )
3917 ret = top_level->match_window(child_return);
3918 // query pointer can return a window manager window with this top_level as a child
3919 // for kde this can be two levels deep
3920 unsigned int nchildren_return = 0;
3921 Window parent_return, *children_return = 0;
3922 Window top_win = top_level->win;
3923 while( !ret && top_win != top_level->rootwin && top_win != root_return &&
3924 XQueryTree(top_level->display, top_win, &root_return,
3925 &parent_return, &children_return, &nchildren_return) ) {
3926 if( children_return ) XFree(children_return);
3927 if( (top_win=parent_return) == child_return ) ret = 1;
3932 int BC_WindowBase::cursor_above()
3935 get_relative_cursor(rx, ry);
3936 return rx < 0 || rx >= get_w() ||
3937 ry < 0 || ry >= get_h() ? 0 : 1;
3940 int BC_WindowBase::get_drag_x()
3942 return top_level->drag_x;
3945 int BC_WindowBase::get_drag_y()
3947 return top_level->drag_y;
3950 int BC_WindowBase::get_cursor_x()
3952 return top_level->cursor_x;
3955 int BC_WindowBase::get_cursor_y()
3957 return top_level->cursor_y;
3960 int BC_WindowBase::dump_windows()
3962 printf("\tBC_WindowBase::dump_windows window=%p win=%p '%s', %dx%d+%d+%d %s\n",
3963 this, (void*)this->win, title, w,h,x,y, typeid(*this).name());
3964 for(int i = 0; i < subwindows->size(); i++)
3965 subwindows->get(i)->dump_windows();
3966 for(int i = 0; i < popups.size(); i++) {
3967 BC_WindowBase *p = popups[i];
3968 printf("\tBC_WindowBase::dump_windows popup=%p win=%p '%s', %dx%d+%d+%d %s\n",
3969 p, (void*)p->win, p->title, p->w,p->h,p->x,p->y, typeid(*p).name());
3974 int BC_WindowBase::is_event_win()
3976 return this->win == top_level->event_win;
3979 void BC_WindowBase::set_dragging(int value)
3981 is_dragging = value;
3984 int BC_WindowBase::get_dragging()
3989 int BC_WindowBase::get_buttonpress()
3991 return top_level->button_number;
3994 int BC_WindowBase::get_button_down()
3996 return top_level->button_down;
3999 int BC_WindowBase::alt_down()
4001 return top_level->alt_mask;
4004 int BC_WindowBase::shift_down()
4006 return top_level->shift_mask;
4009 int BC_WindowBase::ctrl_down()
4011 return top_level->ctrl_mask;
4014 wchar_t* BC_WindowBase::get_wkeystring(int *length)
4017 *length = top_level->wkey_string_length;
4018 return top_level->wkey_string;
4021 #ifdef X_HAVE_UTF8_STRING
4022 char* BC_WindowBase::get_keypress_utf8()
4024 return top_level->key_pressed_utf8;
4029 int BC_WindowBase::get_keypress()
4031 return top_level->key_pressed;
4034 int BC_WindowBase::get_double_click()
4036 return top_level->double_click;
4039 int BC_WindowBase::get_triple_click()
4041 return top_level->triple_click;
4044 int BC_WindowBase::get_bgcolor()
4049 int BC_WindowBase::resize_window(int w, int h)
4051 if(this->w == w && this->h == h) return 0;
4053 if(window_type == MAIN_WINDOW && !allow_resize)
4055 XSizeHints size_hints;
4056 size_hints.flags = PSize | PMinSize | PMaxSize;
4057 size_hints.width = w;
4058 size_hints.height = h;
4059 size_hints.min_width = w;
4060 size_hints.max_width = w;
4061 size_hints.min_height = h;
4062 size_hints.max_height = h;
4063 if( this->x > -BC_INFINITY && this->x < BC_INFINITY ) {
4064 size_hints.flags |= PPosition;
4065 size_hints.x = this->x;
4066 size_hints.y = this->y;
4068 XSetNormalHints(top_level->display, win, &size_hints);
4070 XResizeWindow(top_level->display, win, w, h);
4075 pixmap = new BC_Pixmap(this, w, h);
4077 // Propagate to menubar
4078 for(int i = 0; i < subwindows->total; i++)
4080 subwindows->values[i]->dispatch_resize_event(w, h);
4083 draw_background(0, 0, w, h);
4084 if(top_level == this && get_resources()->recursive_resizing)
4085 resize_history.append(new BC_ResizeCall(w, h));
4089 // The only way for resize events to be propagated is by updating the internal w and h
4090 int BC_WindowBase::resize_event(int w, int h)
4092 if(window_type == MAIN_WINDOW)
4100 int BC_WindowBase::reposition_window(int x, int y)
4102 reposition_window(x, y, -1, -1);
4107 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
4111 // Some tools set their own dimensions before calling this, causing the
4112 // resize check to skip.
4116 if(w > 0 && w != this->w)
4122 if(h > 0 && h != this->h)
4128 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
4131 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
4133 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
4135 if(translation_count && window_type == MAIN_WINDOW)
4137 // KDE shifts window right and down.
4138 // FVWM leaves window alone and adds border around it.
4139 XMoveResizeWindow(top_level->display,
4141 x - BC_DisplayInfo::auto_reposition_x,
4142 y - BC_DisplayInfo::auto_reposition_y,
4148 XMoveResizeWindow(top_level->display,
4159 pixmap = new BC_Pixmap(this, this->w, this->h);
4160 clear_box(0,0, this->w, this->h);
4161 // Propagate to menubar
4162 for(int i = 0; i < subwindows->total; i++)
4164 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
4167 // draw_background(0, 0, w, h);
4173 int BC_WindowBase::reposition_window_relative(int dx, int dy, int w, int h)
4175 return reposition_window(get_x()+dx, get_y()+dy, w, h);
4178 int BC_WindowBase::reposition_window_relative(int dx, int dy)
4180 return reposition_window_relative(dx, dy, -1, -1);
4183 void BC_WindowBase::set_tooltips(int v)
4185 get_resources()->tooltips_enabled = v;
4188 void BC_WindowBase::set_force_tooltip(int v)
4193 int BC_WindowBase::raise_window(int do_flush)
4195 XRaiseWindow(top_level->display, win);
4196 if(do_flush) XFlush(top_level->display);
4200 int BC_WindowBase::lower_window(int do_flush)
4202 XLowerWindow(top_level->display, win);
4203 if(do_flush) XFlush(top_level->display);
4207 void BC_WindowBase::set_background(VFrame *bitmap)
4209 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
4211 bg_pixmap = new BC_Pixmap(this, bitmap, PIXMAP_OPAQUE);
4212 shared_bg_pixmap = 0;
4213 draw_background(0, 0, w, h);
4216 void BC_WindowBase::put_title(const char *text)
4218 char *cp = this->title, *ep = cp+sizeof(this->title)-1;
4219 for( const unsigned char *bp = (const unsigned char *)text; *bp && cp<ep; ++bp )
4220 *cp++ = *bp >= ' ' ? *bp : ' ';
4224 void BC_WindowBase::set_title(const char *text, int utf8)
4226 // utf8>0: wm + net_wm, utf8=0: wm only, utf<0: net_wm only
4228 const unsigned char *wm_title = (const unsigned char *)title;
4229 int title_len = strlen((const char *)title);
4231 Atom xa_wm_name = XA_WM_NAME;
4232 Atom xa_icon_name = XA_WM_ICON_NAME;
4233 Atom xa_string = XA_STRING;
4234 XChangeProperty(display, win, xa_wm_name, xa_string, 8,
4235 PropModeReplace, wm_title, title_len);
4236 XChangeProperty(display, win, xa_icon_name, xa_string, 8,
4237 PropModeReplace, wm_title, title_len);
4240 Atom xa_net_wm_name = XInternAtom(display, "_NET_WM_NAME", True);
4241 Atom xa_net_icon_name = XInternAtom(display, "_NET_WM_ICON_NAME", True);
4242 Atom xa_utf8_string = XInternAtom(display, "UTF8_STRING", True);
4243 XChangeProperty(display, win, xa_net_wm_name, xa_utf8_string, 8,
4244 PropModeReplace, wm_title, title_len);
4245 XChangeProperty(display, win, xa_net_icon_name, xa_utf8_string, 8,
4246 PropModeReplace, wm_title, title_len);
4251 const char *BC_WindowBase::get_title()
4256 int BC_WindowBase::get_toggle_value()
4258 return toggle_value;
4261 int BC_WindowBase::get_toggle_drag()
4266 int BC_WindowBase::set_icon(VFrame *data)
4268 if(icon_pixmap) delete icon_pixmap;
4269 icon_pixmap = new BC_Pixmap(top_level, data, PIXMAP_ALPHA, 1);
4271 if(icon_window) delete icon_window;
4272 icon_window = new BC_Popup(this,
4275 icon_pixmap->get_w(),
4276 icon_pixmap->get_h(),
4278 1, // All windows are hidden initially
4282 wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
4283 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
4284 wm_hints.icon_mask = icon_pixmap->get_alpha();
4285 wm_hints.icon_window = icon_window->win;
4286 wm_hints.window_group = XGroupLeader;
4288 // for(int i = 0; i < 1000; i++)
4289 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
4292 XSetWMHints(top_level->display, top_level->win, &wm_hints);
4293 XSync(top_level->display, 0);
4297 int BC_WindowBase::set_w(int w)
4303 int BC_WindowBase::set_h(int h)
4309 int BC_WindowBase::load_defaults(BC_Hash *defaults)
4311 BC_Resources *resources = get_resources();
4312 char string[BCTEXTLEN];
4313 int newest_id = - 1;
4314 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
4316 sprintf(string, "FILEBOX_HISTORY_PATH%d", i);
4317 resources->filebox_history[i].path[0] = 0;
4318 defaults->get(string, resources->filebox_history[i].path);
4319 sprintf(string, "FILEBOX_HISTORY_ID%d", i);
4320 resources->filebox_history[i].id = defaults->get(string, resources->get_id());
4321 if(resources->filebox_history[i].id > newest_id)
4322 newest_id = resources->filebox_history[i].id;
4325 resources->filebox_id = newest_id + 1;
4326 resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
4327 resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
4328 resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
4329 resources->filebox_columntype[0] = defaults->get("FILEBOX_TYPE0", resources->filebox_columntype[0]);
4330 resources->filebox_columntype[1] = defaults->get("FILEBOX_TYPE1", resources->filebox_columntype[1]);
4331 resources->filebox_columntype[2] = defaults->get("FILEBOX_TYPE2", resources->filebox_columntype[2]);
4332 resources->filebox_columntype[3] = defaults->get("FILEBOX_TYPE3", resources->filebox_columntype[3]);
4333 resources->filebox_columnwidth[0] = defaults->get("FILEBOX_WIDTH0", resources->filebox_columnwidth[0]);
4334 resources->filebox_columnwidth[1] = defaults->get("FILEBOX_WIDTH1", resources->filebox_columnwidth[1]);
4335 resources->filebox_columnwidth[2] = defaults->get("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
4336 resources->filebox_columnwidth[3] = defaults->get("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
4337 resources->filebox_size_format = defaults->get("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
4338 defaults->get("FILEBOX_FILTER", resources->filebox_filter);
4342 int BC_WindowBase::save_defaults(BC_Hash *defaults)
4344 BC_Resources *resources = get_resources();
4345 char string[BCTEXTLEN];
4346 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
4348 sprintf(string, "FILEBOX_HISTORY_PATH%d", i);
4349 defaults->update(string, resources->filebox_history[i].path);
4350 sprintf(string, "FILEBOX_HISTORY_ID%d", i);
4351 defaults->update(string, resources->filebox_history[i].id);
4353 defaults->update("FILEBOX_MODE", resources->filebox_mode);
4354 defaults->update("FILEBOX_W", resources->filebox_w);
4355 defaults->update("FILEBOX_H", resources->filebox_h);
4356 defaults->update("FILEBOX_TYPE0", resources->filebox_columntype[0]);
4357 defaults->update("FILEBOX_TYPE1", resources->filebox_columntype[1]);
4358 defaults->update("FILEBOX_TYPE2", resources->filebox_columntype[2]);
4359 defaults->update("FILEBOX_TYPE3", resources->filebox_columntype[3]);
4360 defaults->update("FILEBOX_WIDTH0", resources->filebox_columnwidth[0]);
4361 defaults->update("FILEBOX_WIDTH1", resources->filebox_columnwidth[1]);
4362 defaults->update("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
4363 defaults->update("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
4364 defaults->update("FILEBOX_FILTER", resources->filebox_filter);
4365 defaults->update("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
4371 // For some reason XTranslateCoordinates can take a long time to return.
4372 // We work around this by only calling it when the event windows are different.
4373 void BC_WindowBase::translate_coordinates(Window src_w,
4385 *dest_x_return = src_x;
4386 *dest_y_return = src_y;
4390 XTranslateCoordinates(top_level->display,
4398 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
4402 void BC_WindowBase::get_root_coordinates(int x, int y, int *abs_x, int *abs_y)
4404 translate_coordinates(win, top_level->rootwin, x, y, abs_x, abs_y);
4407 void BC_WindowBase::get_win_coordinates(int abs_x, int abs_y, int *x, int *y)
4409 translate_coordinates(top_level->rootwin, win, abs_x, abs_y, x, y);
4417 #ifdef HAVE_LIBXXF86VM
4418 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
4422 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
4424 XF86VidModeModeInfo **vm_modelines;
4425 XF86VidModeGetAllModeLines(top_level->display,
4426 XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
4427 for( i = 0; i < vm_count; i++ ) {
4428 if( vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay &&
4429 vm_modelines[i]->hdisplay >= *width )
4432 display = top_level->display;
4433 if( vm_modelines[*vm]->hdisplay == *width )
4436 *width = vm_modelines[*vm]->hdisplay;
4437 *height = vm_modelines[*vm]->vdisplay;
4442 void BC_WindowBase::scale_vm(int vm)
4444 int foo,bar,dotclock;
4445 if( XF86VidModeQueryExtension(top_level->display,&foo,&bar) ) {
4447 XF86VidModeModeInfo **vm_modelines;
4448 XF86VidModeModeLine vml;
4449 XF86VidModeGetAllModeLines(top_level->display,
4450 XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
4451 XF86VidModeGetModeLine(top_level->display,
4452 XDefaultScreen(top_level->display), &dotclock,&vml);
4453 orig_modeline.dotclock = dotclock;
4454 orig_modeline.hdisplay = vml.hdisplay;
4455 orig_modeline.hsyncstart = vml.hsyncstart;
4456 orig_modeline.hsyncend = vml.hsyncend;
4457 orig_modeline.htotal = vml.htotal;
4458 orig_modeline.vdisplay = vml.vdisplay;
4459 orig_modeline.vsyncstart = vml.vsyncstart;
4460 orig_modeline.vsyncend = vml.vsyncend;
4461 orig_modeline.vtotal = vml.vtotal;
4462 orig_modeline.flags = vml.flags;
4463 orig_modeline.privsize = vml.privsize;
4464 // orig_modeline.private = vml.private;
4465 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
4466 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
4467 XFlush(top_level->display);
4471 void BC_WindowBase::restore_vm()
4473 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
4474 XFlush(top_level->display);
4479 #ifndef SINGLE_THREAD
4480 int BC_WindowBase::get_event_count()
4482 event_lock->lock("BC_WindowBase::get_event_count");
4483 int result = common_events.total;
4484 event_lock->unlock();
4488 XEvent* BC_WindowBase::get_event()
4491 while(!done && !result)
4493 event_condition->lock("BC_WindowBase::get_event");
4494 event_lock->lock("BC_WindowBase::get_event");
4496 if(common_events.total && !done)
4498 result = common_events.values[0];
4499 common_events.remove_number(0);
4502 event_lock->unlock();
4507 void BC_WindowBase::put_event(XEvent *event)
4509 event_lock->lock("BC_WindowBase::put_event");
4510 common_events.append(event);
4511 event_lock->unlock();
4512 event_condition->unlock();
4515 void BC_WindowBase::dequeue_events(Window win)
4517 event_lock->lock("BC_WindowBase::dequeue_events");
4519 int out = 0, total = common_events.size();
4520 for( int in=0; in<total; ++in ) {
4521 if( common_events[in]->xany.window == win ) continue;
4522 common_events[out++] = common_events[in];
4524 common_events.total = out;
4526 event_lock->unlock();
4529 int BC_WindowBase::resend_event(BC_WindowBase *window)
4531 if( resend_event_window ) return 1;
4532 resend_event_window = window;
4538 int BC_WindowBase::resend_event(BC_WindowBase *window)
4543 #endif // SINGLE_THREAD
4545 int BC_WindowBase::get_id()
4551 BC_Pixmap *BC_WindowBase::create_pixmap(VFrame *vframe)
4553 int w = vframe->get_w(), h = vframe->get_h();
4554 BC_Pixmap *icon = new BC_Pixmap(this, w, h);
4555 icon->draw_vframe(vframe, 0,0, w,h, 0,0);
4560 void BC_WindowBase::flicker(int n, int ms)
4562 int color = get_bg_color();
4563 for( int i=2*n; --i>=0; ) {
4564 set_inverse(); set_bg_color(WHITE);
4565 clear_box(0,0, w,h); flash(1);
4566 sync_display(); Timer::delay(ms);
4568 set_bg_color(color);
4572 void BC_WindowBase::focus()
4574 XWindowAttributes xwa;
4575 XGetWindowAttributes(top_level->display, top_level->win, &xwa);
4576 if( xwa.map_state == IsViewable )
4577 XSetInputFocus(top_level->display, top_level->win, RevertToParent, CurrentTime);