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);
464 int mask = VisualDepthMask | VisualClassMask;
465 static XVisualInfo vinfo;
466 memset(&vinfo, 0, sizeof(vinfo));
468 vinfo.c_class = TrueColor;
470 XVisualInfo *vis_info = XGetVisualInfo(display, mask, &vinfo, &nitems);
471 vis = vis_info && nitems>0 ? vis_info[0].visual : 0;
472 if( vis_info ) XFree(vis_info);
475 vis = DefaultVisual(display, screen);
476 default_depth = DefaultDepth(display, screen);
478 client_byte_order = (*(const u_int32_t*)"a ") & 0x00000001;
479 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
482 // This must be done before fonts to know if antialiasing is available.
485 if(resources.use_shm < 0) resources.initialize_display(this);
486 x_correction = BC_DisplayInfo::get_left_border();
487 y_correction = BC_DisplayInfo::get_top_border();
489 // clamp window placement
490 if(this->x + this->w + x_correction > root_w)
491 this->x = root_w - this->w - x_correction;
492 if(this->y + this->h + y_correction > root_h)
493 this->y = root_h - this->h - y_correction;
494 if(this->x < 0) this->x = 0;
495 if(this->y < 0) this->y = 0;
497 if(this->bg_color == -1)
498 this->bg_color = resources.get_bg_color();
500 // printf("bcwindowbase 1 %s\n", title);
501 // if(window_type == MAIN_WINDOW) sleep(1);
502 // printf("bcwindowbase 10\n");
508 mask = CWEventMask | CWBackPixel | CWColormap | CWCursor;
510 attr.event_mask = DEFAULT_EVENT_MASKS |
511 StructureNotifyMask |
515 attr.background_pixel = get_color(this->bg_color);
516 attr.colormap = cmap;
517 attr.cursor = get_cursor_struct(ARROW_CURSOR);
519 win = XCreateWindow(display, rootwin,
520 this->x, this->y, this->w, this->h, 0,
521 top_level->default_depth, InputOutput,
523 XGetNormalHints(display, win, &size_hints);
525 size_hints.flags = PSize | PMinSize | PMaxSize;
526 size_hints.width = this->w;
527 size_hints.height = this->h;
528 size_hints.min_width = allow_resize ? minw : this->w;
529 size_hints.max_width = allow_resize ? 32767 : this->w;
530 size_hints.min_height = allow_resize ? minh : this->h;
531 size_hints.max_height = allow_resize ? 32767 : this->h;
532 if(x > -BC_INFINITY && x < BC_INFINITY)
534 size_hints.flags |= PPosition;
535 size_hints.x = this->x;
536 size_hints.y = this->y;
538 XSetWMProperties(display, win, 0, 0, 0, 0, &size_hints, 0, 0);
541 #ifndef SINGLE_THREAD
542 clipboard = new BC_Clipboard(this);
543 clipboard->start_clipboard();
549 Atom ClientLeaderXAtom;
550 if (XGroupLeader == 0)
552 const char *instance_name = "cinelerra";
553 const char *class_name = "Cinelerra";
554 XClassHint *class_hints = XAllocClassHint();
555 class_hints->res_name = (char*)instance_name;
556 class_hints->res_class = (char*)class_name;
557 XSetClassHint(top_level->display, win, class_hints);
559 ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
560 XChangeProperty(display, win, ClientLeaderXAtom, XA_WINDOW, 32,
561 PropModeReplace, (unsigned char *)&XGroupLeader, true);
564 set_icon(get_resources()->default_icon);
567 #ifdef HAVE_LIBXXF86VM
568 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
575 #ifdef HAVE_LIBXXF86VM
576 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
578 if(window_type == POPUP_WINDOW)
581 mask = CWEventMask | CWBackPixel | CWColormap |
582 CWOverrideRedirect | CWSaveUnder | CWCursor;
584 attr.event_mask = DEFAULT_EVENT_MASKS | ExposureMask |
585 KeyPressMask | KeyReleaseMask;
587 if(this->bg_color == -1)
588 this->bg_color = resources.get_bg_color();
589 attr.background_pixel = top_level->get_color(bg_color);
590 attr.colormap = top_level->cmap;
591 if(top_level->is_hourglass)
592 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
594 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
595 attr.override_redirect = True;
596 attr.save_under = True;
598 win = XCreateWindow(top_level->display,
599 top_level->rootwin, this->x, this->y, this->w, this->h, 0,
600 top_level->default_depth, InputOutput, top_level->vis, mask,
602 top_level->add_popup(this);
605 if(window_type == SUB_WINDOW)
607 mask = CWEventMask | CWBackPixel | CWCursor;
608 attr.event_mask = DEFAULT_EVENT_MASKS;
609 attr.background_pixel = top_level->get_color(this->bg_color);
610 if(top_level->is_hourglass)
611 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
613 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
614 win = XCreateWindow(top_level->display,
615 parent_window->win, this->x, this->y, this->w, this->h, 0,
616 top_level->default_depth, InputOutput, top_level->vis, mask,
619 if(!hidden) XMapWindow(top_level->display, win);
622 // Create pixmap for all windows
623 pixmap = new BC_Pixmap(this, this->w, this->h);
625 // Set up options for main window
626 if(window_type == MAIN_WINDOW)
628 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
630 this->bg_pixmap = new BC_Pixmap(this,
631 get_resources()->bg_image,
635 if(!hidden) show_window();
639 draw_background(0, 0, this->w, this->h);
641 flash(-1, -1, -1, -1, 0);
643 // Set up options for popup window
644 #ifdef HAVE_LIBXXF86VM
645 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
647 if(window_type == POPUP_WINDOW)
651 if(!hidden) show_window();
653 get_resources()->create_window_lock->unlock();
659 Display* BC_WindowBase::init_display(const char *display_name)
663 if(display_name && display_name[0] == 0) display_name = NULL;
664 if((display = XOpenDisplay(display_name)) == NULL) {
665 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
667 if(getenv("DISPLAY") == NULL) {
668 printf(_("'DISPLAY' environment variable not set.\n"));
671 // Try again with default display.
672 if((display = XOpenDisplay(0)) == NULL) {
673 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
678 static int xsynch = -1;
680 const char *cp = getenv("CIN_XSYNCH");
681 xsynch = !cp ? 0 : atoi(cp);
684 XSynchronize(display, True);
689 Display* BC_WindowBase::get_display()
691 return top_level->display;
694 int BC_WindowBase::get_screen()
696 return top_level->screen;
699 int BC_WindowBase::run_window()
705 // Events may have been sent before run_window so can't initialize them here.
708 set_repeat(get_resources()->tooltip_delay);
709 BC_Display::display_global->new_window(this);
711 // If the first window created, run the display loop in this thread.
712 if(BC_Display::display_global->is_first(this))
714 BC_Display::unlock_display();
715 BC_Display::display_global->loop();
719 BC_Display::unlock_display();
720 completion_lock->lock("BC_WindowBase::run_window");
723 BC_Display::lock_display("BC_WindowBase::run_window");
724 BC_Display::display_global->delete_window(this);
726 unset_all_repeaters();
728 BC_Display::unlock_display();
730 #else // SINGLE_THREAD
735 set_repeat(get_resources()->tooltip_delay);
737 // Start X server events
738 event_thread = new BC_WindowEvents(this);
739 event_thread->start();
745 // Handle common events
750 unset_all_repeaters();
754 event_condition->reset();
755 common_events.remove_all_objects();
759 #endif // SINGLE_THREAD
764 int BC_WindowBase::get_key_masks(unsigned int key_state)
766 // printf("BC_WindowBase::get_key_masks %llx\n",
767 // event->xkey.state);
768 ctrl_mask = (key_state & ControlMask) ? 1 : 0; // ctrl key down
769 shift_mask = (key_state & ShiftMask) ? 1 : 0; // shift key down
770 alt_mask = (key_state & Mod1Mask) ? 1 : 0; // alt key down
775 void BC_WindowBase::add_keyboard_listener(int(BC_WindowBase::*handler)(BC_WindowBase *))
777 BC_KeyboardHandlerLock set;
778 BC_KeyboardHandler::listeners.append(new BC_KeyboardHandler(handler, this));
781 void BC_WindowBase::del_keyboard_listener(int(BC_WindowBase::*handler)(BC_WindowBase *))
783 BC_KeyboardHandlerLock set;
784 int i = BC_KeyboardHandler::listeners.size();
785 while( --i >= 0 && BC_KeyboardHandler::listeners[i]->handler!=handler );
786 if( i >= 0 ) BC_KeyboardHandler::listeners.remove_object_number(i);
789 int BC_KeyboardHandler::run_event(BC_WindowBase *wp)
791 int result = (win->*handler)(wp);
795 int BC_KeyboardHandler::run_listeners(BC_WindowBase *wp)
798 BC_KeyboardHandlerLock set;
799 for( int i=0; !result && i<listeners.size(); ++i ) {
800 BC_KeyboardHandler *listener = listeners[i];
801 result = listener->run_event(wp);
806 void BC_KeyboardHandler::kill_grabs()
808 BC_KeyboardHandlerLock set;
809 for( int i=0; i<listeners.size(); ++i ) {
810 BC_WindowBase *win = listeners[i]->win;
811 if( win->get_window_type() != POPUP_WINDOW ) continue;
812 ((BC_Popup *)win)->ungrab_keyboard();
816 void BC_ActiveBitmaps::reque(XEvent *event)
818 XShmCompletionEvent *shm_ev = (XShmCompletionEvent *)event;
819 ShmSeg shmseg = shm_ev->shmseg;
820 Drawable drawable = shm_ev->drawable;
821 //printf("BC_BitmapImage::reque %08lx\n",shmseg);
822 active_lock.lock("BC_BitmapImage::reque");
823 BC_BitmapImage *bfr = first;
824 while( bfr && bfr->get_shmseg() != shmseg ) bfr = bfr->next;
825 if( bfr && bfr->drawable == drawable )
827 active_lock.unlock();
829 // sadly, X reports two drawable completions and creates false reporting, so no boobytrap
830 // printf("BC_BitmapImage::reque missed shmseg %08x, drawable %08x\n",
831 // (int)shmseg, (int)drawable);
834 if( bfr->drawable != drawable ) return;
835 if( bfr->is_zombie() ) { --BC_Bitmap::zombies; delete bfr; return; }
836 bfr->bitmap->reque(bfr);
839 void BC_ActiveBitmaps::insert(BC_BitmapImage *bfr, Drawable pixmap)
841 active_lock.lock("BC_BitmapImage::insert");
842 bfr->drawable = pixmap;
844 active_lock.unlock();
847 void BC_ActiveBitmaps::remove_buffers(BC_WindowBase *wdw)
849 active_lock.lock("BC_ActiveBitmaps::remove");
850 for( BC_BitmapImage *nxt=0, *bfr=first; bfr; bfr=nxt ) {
852 if( bfr->is_zombie() ) { --BC_Bitmap::zombies; delete bfr; continue; }
853 if( bfr->bitmap->parent_window == wdw ) remove_pointer(bfr);
855 active_lock.unlock();
858 BC_ActiveBitmaps::BC_ActiveBitmaps()
862 BC_ActiveBitmaps::~BC_ActiveBitmaps()
868 int BC_WindowBase::keysym_lookup(XEvent *event)
870 for( int i = 0; i < KEYPRESSLEN; ++i ) keys_return[i] = 0;
871 for( int i = 0; i < 4; ++i ) wkey_string[i] = 0;
873 if( event->xany.send_event && !event->xany.serial ) {
874 keysym = (KeySym) event->xkey.keycode;
875 keys_return[0] = keysym;
878 wkey_string_length = 0;
880 if( input_context ) {
881 wkey_string_length = XwcLookupString(input_context,
882 (XKeyEvent*)event, wkey_string, 4, &keysym, 0);
883 //printf("keysym_lookup 1 %d %d %lx %x %x %x %x\n", wkey_string_length, keysym,
884 // wkey_string[0], wkey_string[1], wkey_string[2], wkey_string[3]);
887 int ret = Xutf8LookupString(input_context, (XKeyEvent*)event,
888 keys_return, KEYPRESSLEN, &keysym, &stat);
889 //printf("keysym_lookup 2 %d %d %lx %x %x\n", ret, stat, keysym, keys_return[0], keys_return[1]);
890 if( stat == XLookupBoth ) return ret;
891 if( stat == XLookupKeySym ) return 0;
893 int ret = XLookupString((XKeyEvent*)event, keys_return, KEYPRESSLEN, &keysym, 0);
894 wkey_string_length = ret;
895 for( int i=0; i<ret; ++i ) wkey_string[i] = keys_return[i];
899 pthread_t locking_task = (pthread_t)-1L;
900 int locking_event = -1;
901 int locking_message = -1;
903 int BC_WindowBase::dispatch_event()
907 XClientMessageEvent *ptr;
908 int cancel_resize, cancel_translation;
909 volatile static int debug = 0;
914 #ifndef SINGLE_THREAD
915 // If an event is waiting get it, otherwise
916 // wait for next event only if there are no compressed events.
917 if(get_event_count() ||
918 (!motion_events && !resize_events && !translation_events))
921 // Lock out window deletions
922 lock_window("BC_WindowBase::dispatch_event 1");
923 locking_event = event->type;
924 locking_task = pthread_self();
925 locking_message = event->xclient.message_type;
928 // Handle compressed events
930 lock_window("BC_WindowBase::dispatch_event 2");
932 dispatch_resize_event(last_resize_w, last_resize_h);
934 dispatch_motion_event();
935 if(translation_events)
936 dispatch_translation_event();
947 if( debug && event->type != ClientMessage ) {
948 static const char *event_names[] = {
949 "Reply", "Error", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify",
950 "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose",
951 "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify",
952 "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
953 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear",
954 "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify",
955 "GenericEvent", "LASTEvent",
957 const int nevents = sizeof(event_names)/sizeof(event_names[0]);
959 printf("BC_WindowBase::dispatch_event %d %s %p %d (%s)\n", __LINE__,
960 title, event, event->type, event->type>=0 && event->type<nevents ?
961 event_names[event->type] : "Unknown");
966 active_grab->lock_window("BC_WindowBase::dispatch_event 3");
967 result = active_grab->grab_event(event);
968 active_grab->unlock_window();
969 if( result ) return result;
970 lock_window("BC_WindowBase::dispatch_event 4");
973 switch(event->type) {
975 // Clear the resize buffer
977 dispatch_resize_event(last_resize_w, last_resize_h);
978 // Clear the motion buffer since this can clear the window
980 dispatch_motion_event();
982 ptr = (XClientMessageEvent*)event;
983 if( ptr->message_type == ProtoXAtom &&
984 (Atom)ptr->data.l[0] == DelWinXAtom ) {
987 else if( ptr->message_type == RepeaterXAtom ) {
988 dispatch_repeat_event(ptr->data.l[0]);
990 else if( ptr->message_type == SetDoneXAtom ) {
994 receive_custom_xatoms((xatom_event *)ptr);
1000 dispatch_focus_in();
1005 dispatch_focus_out();
1019 dispatch_motion_event();
1021 get_key_masks(event->xbutton.state);
1022 cursor_x = event->xbutton.x;
1023 cursor_y = event->xbutton.y;
1024 button_number = event->xbutton.button;
1026 //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number);
1027 event_win = event->xany.window;
1028 if (button_number < 6) {
1029 if(button_number < 4)
1031 button_pressed = event->xbutton.button;
1032 button_time1 = button_time2;
1033 button_time2 = button_time3;
1034 button_time3 = event->xbutton.time;
1037 drag_win = event_win;
1038 drag_x1 = cursor_x - get_resources()->drag_radius;
1039 drag_x2 = cursor_x + get_resources()->drag_radius;
1040 drag_y1 = cursor_y - get_resources()->drag_radius;
1041 drag_y2 = cursor_y + get_resources()->drag_radius;
1043 if((long)(button_time3 - button_time1) < resources.double_click * 2)
1046 button_time3 = button_time2 = button_time1 = 0;
1048 if((long)(button_time3 - button_time2) < resources.double_click)
1051 // button_time3 = button_time2 = button_time1 = 0;
1059 dispatch_button_press();
1066 dispatch_motion_event();
1068 get_key_masks(event->xbutton.state);
1069 button_number = event->xbutton.button;
1070 event_win = event->xany.window;
1071 if (button_number < 6)
1073 if(button_number < 4)
1075 //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number);
1077 dispatch_button_release();
1082 event_win = event->xany.window;
1084 for( int i=0; !result && i<popups.size(); ++i ) { // popups take focus
1085 if( popups[i]->win == event_win )
1086 result = popups[i]->dispatch_expose_event();
1089 result = dispatch_expose_event();
1093 get_key_masks(event->xmotion.state);
1094 // Dispatch previous motion event if this is a subsequent motion from a different window
1095 if(motion_events && last_motion_win != event->xany.window)
1097 dispatch_motion_event();
1100 // Buffer the current motion
1102 last_motion_state = event->xmotion.state;
1103 last_motion_x = event->xmotion.x;
1104 last_motion_y = event->xmotion.y;
1105 last_motion_win = event->xany.window;
1108 case ConfigureNotify:
1109 // printf("BC_WindowBase::dispatch_event %d win=%p this->win=%p\n",
1111 // event->xany.window,
1114 XTranslateCoordinates(top_level->display,
1122 last_resize_w = event->xconfigure.width;
1123 last_resize_h = event->xconfigure.height;
1126 cancel_translation = 0;
1128 // Resize history prevents responses to recursive resize requests
1129 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
1131 if(resize_history.values[i]->w == last_resize_w &&
1132 resize_history.values[i]->h == last_resize_h)
1134 delete resize_history.values[i];
1135 resize_history.remove_number(i);
1140 if(last_resize_w == w && last_resize_h == h)
1148 if((last_translate_x == x && last_translate_y == y))
1149 cancel_translation = 1;
1151 if(!cancel_translation)
1153 translation_events = 1;
1156 translation_count++;
1160 get_key_masks(event->xkey.state);
1161 keys_return[0] = 0; keysym = -1;
1162 if(XFilterEvent(event, win)) {
1165 if( keysym_lookup(event) < 0 ) {
1166 printf("keysym %x\n", (uint32_t)keysym);
1170 //printf("BC_WindowBase::dispatch_event %d keysym=0x%x\n",
1174 // block out control keys
1175 if(keysym > 0xffe0 && keysym < 0xffff) break;
1176 // block out Alt_GR key
1177 if(keysym == 0xfe03) break;
1180 printf("BC_WindowBase::dispatch_event %x\n", (uint32_t)keysym);
1182 #ifdef X_HAVE_UTF8_STRING
1183 //It's Ascii or UTF8?
1184 // if (keysym != 0xffff && (keys_return[0] & 0xff) >= 0x7f )
1185 //printf("BC_WindowBase::dispatch_event %d %02x%02x\n", __LINE__, keys_return[0], keys_return[1]);
1187 if( ((keys_return[1] & 0xff) > 0x80) &&
1188 ((keys_return[0] & 0xff) > 0xC0) ) {
1189 //printf("BC_WindowBase::dispatch_event %d\n", __LINE__);
1190 key_pressed = keysym & 0xff;
1194 // shuttle speed codes
1195 if( keysym >= SKEY_MIN && keysym <= SKEY_MAX ) {
1196 key_pressed = keysym;
1198 else switch( keysym ) {
1199 // block out extra keys
1209 // Translate key codes
1210 case XK_Return: key_pressed = RETURN; break;
1211 case XK_Up: key_pressed = UP; break;
1212 case XK_Down: key_pressed = DOWN; break;
1213 case XK_Left: key_pressed = LEFT; break;
1214 case XK_Right: key_pressed = RIGHT; break;
1215 case XK_Next: key_pressed = PGDN; break;
1216 case XK_Prior: key_pressed = PGUP; break;
1217 case XK_BackSpace: key_pressed = BACKSPACE; break;
1218 case XK_Escape: key_pressed = ESC; break;
1221 key_pressed = LEFTTAB;
1225 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
1226 case XK_underscore: key_pressed = '_'; break;
1227 case XK_asciitilde: key_pressed = '~'; break;
1228 case XK_Delete: key_pressed = DELETE; break;
1229 case XK_Home: key_pressed = HOME; break;
1230 case XK_End: key_pressed = END; break;
1233 case XK_KP_Enter: key_pressed = KPENTER; break;
1234 case XK_KP_Add: key_pressed = KPPLUS; break;
1235 case XK_KP_Subtract: key_pressed = KPMINUS; break;
1236 case XK_KP_Multiply: key_pressed = KPSTAR; break;
1237 case XK_KP_Divide: key_pressed = KPSLASH; break;
1239 case XK_KP_End: key_pressed = KP1; break;
1241 case XK_KP_Down: key_pressed = KP2; break;
1243 case XK_KP_Page_Down: key_pressed = KP3; break;
1245 case XK_KP_Left: key_pressed = KP4; break;
1247 case XK_KP_Begin: key_pressed = KP5; break;
1249 case XK_KP_Right: key_pressed = KP6; break;
1251 case XK_KP_Home: key_pressed = KP7; break;
1253 case XK_KP_Up: key_pressed = KP8; break;
1255 case XK_KP_Page_Up: key_pressed = KP9; break;
1257 case XK_KP_Insert: key_pressed = KPINS; break;
1259 case XK_KP_Delete: key_pressed = KPDEL; break;
1261 case XK_F1: key_pressed = KEY_F1; break;
1262 case XK_F2: key_pressed = KEY_F2; break;
1263 case XK_F3: key_pressed = KEY_F3; break;
1264 case XK_F4: key_pressed = KEY_F4; break;
1265 case XK_F5: key_pressed = KEY_F5; break;
1266 case XK_F6: key_pressed = KEY_F6; break;
1267 case XK_F7: key_pressed = KEY_F7; break;
1268 case XK_F8: key_pressed = KEY_F8; break;
1269 case XK_F9: key_pressed = KEY_F9; break;
1270 case XK_F10: key_pressed = KEY_F10; break;
1271 case XK_F11: key_pressed = KEY_F11; break;
1272 case XK_F12: key_pressed = KEY_F12; break;
1274 case XK_Menu: key_pressed = KPMENU; break; /* menu */
1276 // above case XK_KP_Enter: key_pressed = KPENTER; break; /* check */
1277 case XF86XK_MenuKB: key_pressed = KPMENU; break; /* menu */
1278 // intercepted case XF86XK_PowerDown: key_pressed = KPPOWER; break; /* Power */
1279 case XF86XK_Launch1: key_pressed = KPTV; break; /* TV */
1280 case XF86XK_Launch2: key_pressed = KPDVD; break; /* DVD */
1281 // intercepted case XF86XK_WWW: key_pressed = KPWWEB; break; /* WEB */
1282 case XF86XK_Launch3: key_pressed = KPBOOK; break; /* book */
1283 case XF86XK_Launch4: key_pressed = KPHAND; break; /* hand */
1284 case XF86XK_Reply: key_pressed = KPTMR; break; /* timer */
1285 case SunXK_Front: key_pressed = KPMAXW; break; /* max */
1286 // above case XK_Left: key_pressed = LEFT; break; /* left */
1287 // above case XK_Right: key_pressed = RIGHT; break; /* right */
1288 // above case XK_Down: key_pressed = DOWN; break; /* down */
1289 // above case XK_Up: key_pressed = UP; break; /* up */
1290 // above case XK_SPACE: key_pressed = KPSPACE; break; /* ok */
1291 // intercepted case XF86XK_AudioRaiseVolume: key_pressed = KPVOLU; break; /* VOL + */
1292 // intercepted case XF86XK_AudioMute: key_pressed = KPMUTE; break; /* MUTE */
1293 // intercepted case XF86XK_AudioLowerVolume: key_pressed = KPVOLD; break; /* VOL - */
1294 case XF86XK_ScrollUp: key_pressed = KPCHUP; break; /* CH + */
1295 case XF86XK_ScrollDown: key_pressed = KPCHDN; break; /* CH - */
1296 case XF86XK_AudioRecord: key_pressed = KPRECD; break; /* ( o) red */
1297 case XF86XK_Forward: key_pressed = KPPLAY; break; /* ( >) */
1298 case XK_Redo: key_pressed = KPFWRD; break; /* (>>) */
1299 case XF86XK_Back: key_pressed = KPBACK; break; /* (<<) */
1300 case XK_Cancel: key_pressed = KPSTOP; break; /* ([]) */
1301 case XK_Pause: key_pressed = KPAUSE; break; /* ('') */
1304 key_pressed = keysym & 0xff;
1305 #ifdef X_HAVE_UTF8_STRING
1306 //printf("BC_WindowBase::dispatch_event %d\n", __LINE__);
1311 #ifdef X_HAVE_UTF8_STRING
1313 key_pressed_utf8 = keys_return;
1318 if( top_level == this )
1319 result = BC_KeyboardHandler::run_listeners(this);
1321 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
1323 result = dispatch_keypress_event();
1324 // Handle some default keypresses
1327 if(key_pressed == 'w' ||
1336 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
1337 dispatch_keyrelease_event();
1338 // printf("BC_WindowBase::dispatch_event KeyRelease keysym=0x%x keystate=0x%lld\n",
1339 // keysym, event->xkey.state);
1343 if( event->xcrossing.mode != NotifyNormal ) break;
1345 event_win = event->xany.window;
1346 dispatch_cursor_leave();
1350 if( event->xcrossing.mode != NotifyNormal ) break;
1352 if( !cursor_entered ) {
1353 for( int i=0; i<popups.size(); ++i ) { // popups always take focus
1354 if( popups[i]->win == event->xcrossing.window )
1357 if( !cursor_entered && get_resources()->grab_input_focus &&
1358 !event->xcrossing.focus && event->xcrossing.window == win ) {
1361 if( cursor_entered )
1364 event_win = event->xany.window;
1365 cursor_x = event->xcrossing.x;
1366 cursor_y = event->xcrossing.y;
1367 dispatch_cursor_enter();
1373 //printf("100 %s %p %d\n", title, event, event->type);
1374 //if(event->type != ClientMessage) dump();
1376 #ifndef SINGLE_THREAD
1379 if( resend_event_window ) {
1380 resend_event_window->put_event(event);
1381 resend_event_window = 0;
1387 // if(done) completion_lock->unlock();
1390 if(debug) printf("BC_WindowBase::dispatch_event this=%p %d\n", this, __LINE__);
1394 int BC_WindowBase::dispatch_expose_event()
1397 for(int i = 0; i < subwindows->total && !result; i++)
1399 result = subwindows->values[i]->dispatch_expose_event();
1402 // Propagate to user
1403 if(!result) expose_event();
1407 int BC_WindowBase::dispatch_resize_event(int w, int h)
1409 // Can't store new w and h until the event is handles
1410 // because bcfilebox depends on the old w and h to
1411 // reposition widgets.
1412 if( window_type == MAIN_WINDOW ) {
1417 pixmap = new BC_Pixmap(this, w, h);
1418 clear_box(0, 0, w, h);
1421 // Propagate to subwindows
1422 for(int i = 0; i < subwindows->total; i++) {
1423 subwindows->values[i]->dispatch_resize_event(w, h);
1426 // Propagate to user
1429 if( window_type == MAIN_WINDOW ) {
1438 int BC_WindowBase::dispatch_flash()
1441 for(int i = 0; i < subwindows->total; i++)
1442 subwindows->values[i]->dispatch_flash();
1446 int BC_WindowBase::dispatch_translation_event()
1448 translation_events = 0;
1449 if(window_type == MAIN_WINDOW)
1453 x = last_translate_x;
1454 y = last_translate_y;
1455 // Correct for window manager offsets
1460 for(int i = 0; i < subwindows->total; i++)
1462 subwindows->values[i]->dispatch_translation_event();
1465 translation_event();
1469 int BC_WindowBase::dispatch_motion_event()
1474 if(top_level == this)
1477 event_win = last_motion_win;
1478 get_key_masks(last_motion_state);
1481 if(get_button_down() && !active_menubar && !active_popup_menu)
1485 cursor_x = last_motion_x;
1486 cursor_y = last_motion_y;
1487 result = dispatch_drag_motion();
1491 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
1492 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1497 result = dispatch_drag_start();
1501 cursor_x = last_motion_x;
1502 cursor_y = last_motion_y;
1504 // printf("BC_WindowBase::dispatch_motion_event %d %p %p %p\n",
1507 // active_popup_menu,
1508 // active_subwindow);
1510 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1511 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1512 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1515 // Dispatch in stacking order
1516 for(int i = subwindows->size() - 1; i >= 0 && !result; i--)
1518 result = subwindows->values[i]->dispatch_motion_event();
1521 if(!result) result = cursor_motion_event(); // give to user
1525 int BC_WindowBase::dispatch_keypress_event()
1528 if(top_level == this)
1530 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1533 for(int i = 0; i < subwindows->total && !result; i++)
1535 result = subwindows->values[i]->dispatch_keypress_event();
1538 if(!result) result = keypress_event();
1543 int BC_WindowBase::dispatch_keyrelease_event()
1546 if(top_level == this)
1548 if(active_subwindow) result = active_subwindow->dispatch_keyrelease_event();
1551 for(int i = 0; i < subwindows->total && !result; i++)
1553 result = subwindows->values[i]->dispatch_keyrelease_event();
1556 if(!result) result = keyrelease_event();
1561 int BC_WindowBase::dispatch_focus_in()
1563 for(int i = 0; i < subwindows->total; i++)
1565 subwindows->values[i]->dispatch_focus_in();
1573 int BC_WindowBase::dispatch_focus_out()
1575 for(int i = 0; i < subwindows->total; i++)
1577 subwindows->values[i]->dispatch_focus_out();
1585 int BC_WindowBase::get_has_focus()
1587 return top_level->has_focus;
1590 int BC_WindowBase::get_deleting()
1592 if(is_deleting) return 1;
1593 if(parent_window && parent_window->get_deleting()) return 1;
1597 int BC_WindowBase::dispatch_button_press()
1602 if(top_level == this)
1604 if(active_menubar) result = active_menubar->dispatch_button_press();
1605 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1606 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1609 for(int i = 0; i < subwindows->total && !result; i++)
1611 result = subwindows->values[i]->dispatch_button_press();
1614 if(!result) result = button_press_event();
1620 int BC_WindowBase::dispatch_button_release()
1623 if(top_level == this)
1625 if(active_menubar) result = active_menubar->dispatch_button_release();
1626 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1627 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1628 if(!result && button_number != 4 && button_number != 5)
1629 result = dispatch_drag_stop();
1632 for(int i = 0; i < subwindows->total && !result; i++)
1634 result = subwindows->values[i]->dispatch_button_release();
1639 result = button_release_event();
1646 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1649 // all repeat event handlers get called and decide based on activity and duration
1650 // whether to respond
1651 for(int i = 0; i < subwindows->total; i++)
1653 subwindows->values[i]->dispatch_repeat_event(duration);
1657 repeat_event(duration);
1661 // Unlock next repeat signal
1662 if(window_type == MAIN_WINDOW)
1664 #ifdef SINGLE_THREAD
1665 BC_Display::display_global->unlock_repeaters(duration);
1667 for(int i = 0; i < repeaters.total; i++)
1669 if(repeaters.values[i]->delay == duration)
1671 repeaters.values[i]->repeat_lock->unlock();
1679 void BC_WindowBase::unhide_cursor()
1684 if(top_level->is_hourglass)
1685 set_cursor(HOURGLASS_CURSOR, 1, 0);
1687 set_cursor(current_cursor, 1, 0);
1689 cursor_timer->update();
1693 void BC_WindowBase::update_video_cursor()
1695 if(video_on && !is_transparent)
1697 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1700 set_cursor(TRANSPARENT_CURSOR, 1, 1);
1701 cursor_timer->update();
1706 cursor_timer->update();
1711 int BC_WindowBase::dispatch_cursor_leave()
1715 for(int i = 0; i < subwindows->total; i++)
1717 subwindows->values[i]->dispatch_cursor_leave();
1720 cursor_leave_event();
1724 int BC_WindowBase::dispatch_cursor_enter()
1730 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1731 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1732 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1734 for(int i = 0; !result && i < subwindows->total; i++)
1736 result = subwindows->values[i]->dispatch_cursor_enter();
1739 if(!result) result = cursor_enter_event();
1743 int BC_WindowBase::cursor_enter_event()
1748 int BC_WindowBase::cursor_leave_event()
1753 int BC_WindowBase::close_event()
1759 int BC_WindowBase::dispatch_drag_start()
1762 if(active_menubar) result = active_menubar->dispatch_drag_start();
1763 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1764 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1766 for(int i = 0; i < subwindows->total && !result; i++)
1768 result = subwindows->values[i]->dispatch_drag_start();
1771 if(!result) result = is_dragging = drag_start_event();
1775 int BC_WindowBase::dispatch_drag_stop()
1779 for(int i = 0; i < subwindows->total && !result; i++)
1781 result = subwindows->values[i]->dispatch_drag_stop();
1784 if(is_dragging && !result)
1794 int BC_WindowBase::dispatch_drag_motion()
1797 for(int i = 0; i < subwindows->total && !result; i++)
1799 result = subwindows->values[i]->dispatch_drag_motion();
1802 if(is_dragging && !result)
1804 drag_motion_event();
1812 int BC_WindowBase::show_tooltip(const char *text, int x, int y, int w, int h)
1815 int forced = !text ? force_tooltip : 1;
1816 if( !text ) text = tooltip_text;
1817 if( !text || (!forced && !get_resources()->tooltips_enabled) ) {
1818 top_level->hide_tooltip();
1822 if(w < 0) w = get_text_width(MEDIUMFONT, text) + TOOLTIP_MARGIN * 2;
1823 if(h < 0) h = get_text_height(MEDIUMFONT, text) + TOOLTIP_MARGIN * 2;
1824 // default x,y (win relative)
1825 if( x < 0 ) x = get_w();
1826 if( y < 0 ) y = get_h();
1828 get_root_coordinates(x, y, &wx, &wy);
1829 // keep the tip inside the window/display
1830 int x0 = top_level->get_x(), x1 = x0 + top_level->get_w();
1831 int x2 = top_level->get_screen_x(0, -1) + top_level->get_screen_w(0, -1);
1832 if( x1 > x2 ) x1 = x2;
1833 if( wx < x0 ) wx = x0;
1834 if( wx >= (x1-=w) ) wx = x1;
1835 int y0 = top_level->get_y(), y1 = y0 + top_level->get_h();
1836 int y2 = top_level->get_root_h(0);
1837 if( y1 > y2 ) y1 = y2;
1838 if( wy < y0 ) wy = y0;
1839 if( wy >= (y1-=h) ) wy = y1;
1840 // avoid tip under cursor (flickers)
1842 get_abs_cursor(abs_x,abs_y, 0);
1843 if( wx < abs_x && abs_x < wx+w && wy < abs_y && abs_y < wy+h ) {
1844 if( wx-abs_x < wy-abs_y )
1851 tooltip_popup = new BC_Popup(top_level, wx, wy, w, h,
1852 get_resources()->tooltip_bg_color);
1855 tooltip_popup->reposition_window(wx, wy, w, h);
1858 tooltip_popup->flash();
1859 tooltip_popup->flush();
1863 int BC_WindowBase::hide_tooltip()
1866 for(int i = 0; i < subwindows->total; i++)
1868 subwindows->values[i]->hide_tooltip();
1874 delete tooltip_popup;
1880 const char *BC_WindowBase::get_tooltip()
1882 return tooltip_text;
1885 int BC_WindowBase::set_tooltip(const char *text)
1887 tooltip_text = text;
1889 // Update existing tooltip if it is visible
1893 tooltip_popup->flash();
1897 // signal the event handler to repeat
1898 int BC_WindowBase::set_repeat(int64_t duration)
1902 printf("BC_WindowBase::set_repeat duration=%jd\n", duration);
1905 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1907 #ifdef SINGLE_THREAD
1908 BC_Display::display_global->set_repeat(this, duration);
1910 // test repeater database for duplicates
1911 for(int i = 0; i < repeaters.total; i++)
1914 if(repeaters.values[i]->delay == duration)
1916 repeaters.values[i]->start_repeating(this);
1921 BC_Repeater *repeater = new BC_Repeater(this, duration);
1922 repeater->initialize();
1923 repeaters.append(repeater);
1924 repeater->start_repeating();
1929 int BC_WindowBase::unset_repeat(int64_t duration)
1931 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1933 #ifdef SINGLE_THREAD
1934 BC_Display::display_global->unset_repeat(this, duration);
1936 for(int i = 0; i < repeaters.total; i++)
1938 if(repeaters.values[i]->delay == duration)
1940 repeaters.values[i]->stop_repeating();
1948 int BC_WindowBase::unset_all_repeaters()
1950 #ifdef SINGLE_THREAD
1951 BC_Display::display_global->unset_all_repeaters(this);
1953 for(int i = 0; i < repeaters.total; i++)
1955 repeaters.values[i]->stop_repeating();
1957 repeaters.remove_all_objects();
1962 // long BC_WindowBase::get_repeat_id()
1964 // return top_level->next_repeat_id++;
1967 XEvent *BC_WindowBase::new_xevent()
1969 XEvent *event = new XEvent;
1970 memset(event, 0, sizeof(*event));
1974 #ifndef SINGLE_THREAD
1975 int BC_WindowBase::arm_repeat(int64_t duration)
1977 XEvent *event = new_xevent();
1978 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1979 ptr->type = ClientMessage;
1980 ptr->message_type = RepeaterXAtom;
1982 ptr->data.l[0] = duration;
1984 // Couldn't use XSendEvent since it locked up randomly.
1990 int BC_WindowBase::receive_custom_xatoms(xatom_event *event)
1995 int BC_WindowBase::send_custom_xatom(xatom_event *event)
1997 #ifndef SINGLE_THREAD
1998 XEvent *myevent = new_xevent();
1999 XClientMessageEvent *ptr = (XClientMessageEvent*)myevent;
2000 ptr->type = ClientMessage;
2001 ptr->message_type = event->message_type;
2002 ptr->format = event->format;
2003 ptr->data.l[0] = event->data.l[0];
2004 ptr->data.l[1] = event->data.l[1];
2005 ptr->data.l[2] = event->data.l[2];
2006 ptr->data.l[3] = event->data.l[3];
2007 ptr->data.l[4] = event->data.l[4];
2016 Atom BC_WindowBase::create_xatom(const char *atom_name)
2018 return XInternAtom(display, atom_name, False);
2021 int BC_WindowBase::get_atoms()
2023 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
2024 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
2025 DestroyAtom = XInternAtom(display, "BC_DESTROY_WINDOW", False);
2026 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
2027 if( (ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False)) != 0 )
2028 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32,
2029 PropModeReplace, (unsigned char *)&DelWinXAtom, True);
2035 void BC_WindowBase::init_cursors()
2037 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
2038 cross_cursor = XCreateFontCursor(display, XC_crosshair);
2039 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
2040 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
2041 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
2042 move_cursor = XCreateFontCursor(display, XC_fleur);
2043 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
2044 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
2045 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
2046 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
2047 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
2048 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
2049 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
2050 hourglass_cursor = XCreateFontCursor(display, XC_watch);
2051 grabbed_cursor = create_grab_cursor();
2053 static char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
2054 Colormap colormap = DefaultColormap(display, screen);
2055 Pixmap pixmap_bottom = XCreateBitmapFromData(display,
2056 rootwin, cursor_data, 8, 8);
2057 XColor black, dummy;
2058 XAllocNamedColor(display, colormap, "black", &black, &dummy);
2059 transparent_cursor = XCreatePixmapCursor(display,
2060 pixmap_bottom, pixmap_bottom, &black, &black, 0, 0);
2061 // XDefineCursor(display, win, transparent_cursor);
2062 XFreePixmap(display, pixmap_bottom);
2065 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
2067 int color_model = BC_TRANSPARENCY;
2071 color_model = BC_RGB8;
2074 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
2077 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
2080 color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
2086 int BC_WindowBase::init_colors()
2089 current_color_value = current_color_pixel = 0;
2091 // Get the real depth
2094 ximage = XCreateImage(top_level->display,
2096 top_level->default_depth,
2104 bits_per_pixel = ximage->bits_per_pixel;
2105 XDestroyImage(ximage);
2107 color_model = evaluate_color_model(client_byte_order,
2110 // Get the color model
2115 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
2116 create_private_colors();
2119 cmap = DefaultColormap(display, screen);
2120 create_shared_colors();
2123 allocate_color_table();
2127 //cmap = DefaultColormap(display, screen);
2128 cmap = XCreateColormap(display, rootwin, vis, AllocNone );
2134 int BC_WindowBase::create_private_colors()
2139 for(int i = 0; i < 255; i++)
2141 color = (i & 0xc0) << 16;
2142 color += (i & 0x38) << 10;
2143 color += (i & 0x7) << 5;
2144 color_table[i][0] = color;
2146 create_shared_colors(); // overwrite the necessary colors on the table
2151 int BC_WindowBase::create_color(int color)
2153 if(total_colors == 256)
2155 // replace the closest match with an exact match
2156 color_table[get_color_rgb8(color)][0] = color;
2160 // add the color to the table
2161 color_table[total_colors][0] = color;
2167 int BC_WindowBase::create_shared_colors()
2169 create_color(BLACK);
2170 create_color(WHITE);
2172 create_color(LTGREY);
2173 create_color(MEGREY);
2174 create_color(MDGREY);
2175 create_color(DKGREY);
2177 create_color(LTCYAN);
2178 create_color(MECYAN);
2179 create_color(MDCYAN);
2180 create_color(DKCYAN);
2182 create_color(LTGREEN);
2183 create_color(GREEN);
2184 create_color(DKGREEN);
2186 create_color(LTPINK);
2190 create_color(LTBLUE);
2192 create_color(DKBLUE);
2194 create_color(LTYELLOW);
2195 create_color(MEYELLOW);
2196 create_color(MDYELLOW);
2197 create_color(DKYELLOW);
2199 create_color(LTPURPLE);
2200 create_color(MEPURPLE);
2201 create_color(MDPURPLE);
2202 create_color(DKPURPLE);
2204 create_color(FGGREY);
2205 create_color(MNBLUE);
2206 create_color(ORANGE);
2207 create_color(FTGREY);
2212 Cursor BC_WindowBase::create_grab_cursor()
2214 int iw = 23, iw1 = iw-1, iw2 = iw/2;
2215 int ih = 23, ih1 = ih-1, ih2 = ih/2;
2216 VFrame grab(iw,ih,BC_RGB888);
2218 grab.set_pixel_color(RED); // fg
2219 grab.draw_smooth(iw2,0, iw1,0, iw1,ih2);
2220 grab.draw_smooth(iw1,ih2, iw1,ih1, iw2,ih1);
2221 grab.draw_smooth(iw2,ih1, 0,ih1, 0,ih2);
2222 grab.draw_smooth(0,ih2, 0,0, iw2,0);
2223 grab.set_pixel_color(WHITE); // bg
2224 grab.draw_line(0,ih2, iw2-2,ih2);
2225 grab.draw_line(iw2+2,ih2, iw1,ih2);
2226 grab.draw_line(iw2,0, iw2,ih2-2);
2227 grab.draw_line(iw2,ih2+2, iw2,ih1);
2229 int bpl = (iw+7)/8, isz = bpl * ih;
2230 char img[isz]; memset(img, 0, isz);
2231 char msk[isz]; memset(msk, 0, isz);
2232 unsigned char **rows = grab.get_rows();
2233 for( int iy=0; iy<ih; ++iy ) {
2234 char *op = img + iy*bpl;
2235 char *mp = msk + iy*bpl;
2236 unsigned char *ip = rows[iy];
2237 for( int ix=0; ix<iw; ++ix,ip+=3 ) {
2238 if( ip[0] ) mp[ix>>3] |= (1<<(ix&7));
2239 if( !ip[1] ) op[ix>>3] |= (1<<(ix&7));
2242 unsigned long white_pix = WhitePixel(display, screen);
2243 unsigned long black_pix = BlackPixel(display, screen);
2244 Pixmap img_xpm = XCreatePixmapFromBitmapData(display, rootwin,
2245 img, iw,ih, white_pix,black_pix, 1);
2246 Pixmap msk_xpm = XCreatePixmapFromBitmapData(display, rootwin,
2247 msk, iw,ih, white_pix,black_pix, 1);
2250 fc.flags = bc.flags = DoRed | DoGreen | DoBlue;
2251 fc.red = 0xffff; fc.green = fc.blue = 0; // fg
2252 bc.red = 0xffff; bc.green = 0xffff; bc.blue = 0x0000; // bg
2253 Cursor cursor = XCreatePixmapCursor(display, img_xpm,msk_xpm, &fc,&bc, iw2,ih2);
2254 XFreePixmap(display, img_xpm);
2255 XFreePixmap(display, msk_xpm);
2259 int BC_WindowBase::allocate_color_table()
2261 int red, green, blue, color;
2264 for(int i = 0; i < total_colors; i++)
2266 color = color_table[i][0];
2267 red = (color & 0xFF0000) >> 16;
2268 green = (color & 0x00FF00) >> 8;
2269 blue = color & 0xFF;
2271 col.flags = DoRed | DoGreen | DoBlue;
2272 col.red = red<<8 | red;
2273 col.green = green<<8 | green;
2274 col.blue = blue<<8 | blue;
2276 XAllocColor(display, cmap, &col);
2277 color_table[i][1] = col.pixel;
2280 XInstallColormap(display, cmap);
2284 int BC_WindowBase::init_window_shape()
2286 if(bg_pixmap && bg_pixmap->use_alpha())
2288 XShapeCombineMask(top_level->display,
2289 this->win, ShapeBounding, 0, 0,
2290 bg_pixmap->get_alpha(), ShapeSet);
2296 int BC_WindowBase::init_gc()
2298 unsigned long gcmask;
2299 gcmask = GCFont | GCGraphicsExposures;
2302 gcvalues.font = mediumfont->fid; // set the font
2303 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
2304 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
2306 // gcmask = GCCapStyle | GCJoinStyle;
2307 // XGetGCValues(display, gc, gcmask, &gcvalues);
2308 // printf("BC_WindowBase::init_gc %d %d %d\n", __LINE__, gcvalues.cap_style, gcvalues.join_style);
2312 int BC_WindowBase::init_fonts()
2314 if( !(smallfont = XLoadQueryFont(display, _(resources.small_font))) )
2315 if( !(smallfont = XLoadQueryFont(display, _(resources.small_font2))) )
2316 smallfont = XLoadQueryFont(display, "fixed");
2317 if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font))) )
2318 if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) )
2319 mediumfont = XLoadQueryFont(display, "fixed");
2320 if( !(largefont = XLoadQueryFont(display, _(resources.large_font))) )
2321 if( !(largefont = XLoadQueryFont(display, _(resources.large_font2))) )
2322 largefont = XLoadQueryFont(display, "fixed");
2323 if( !(bigfont = XLoadQueryFont(display, _(resources.big_font))) )
2324 if( !(bigfont = XLoadQueryFont(display, _(resources.big_font2))) )
2325 bigfont = XLoadQueryFont(display, "fixed");
2327 if((clockfont = XLoadQueryFont(display, _(resources.clock_font))) == NULL)
2328 if((clockfont = XLoadQueryFont(display, _(resources.clock_font2))) == NULL)
2329 clockfont = XLoadQueryFont(display, "fixed");
2332 if(get_resources()->use_fontset)
2337 // FIXME: should check the m,d,n values
2338 smallfontset = XCreateFontSet(display, resources.small_fontset, &m, &n, &d);
2340 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2341 mediumfontset = XCreateFontSet(display, resources.medium_fontset, &m, &n, &d);
2342 if( !mediumfontset )
2343 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2344 largefontset = XCreateFontSet(display, resources.large_fontset, &m, &n, &d);
2346 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2347 bigfontset = XCreateFontSet(display, resources.big_fontset, &m, &n, &d);
2349 bigfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2350 clockfontset = XCreateFontSet(display, resources.clock_fontset, &m, &n, &d);
2352 clockfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2353 if(clockfontset && bigfontset && largefontset && mediumfontset && smallfontset) {
2354 curr_fontset = mediumfontset;
2355 get_resources()->use_fontset = 1;
2359 get_resources()->use_fontset = 0;
2366 void BC_WindowBase::init_xft()
2369 if( !get_resources()->use_xft ) return;
2370 // apparently, xft is not reentrant, more than this is needed
2371 static Mutex xft_init_lock("BC_WindowBase::xft_init_lock", 0);
2372 xft_init_lock.lock("BC_WindowBase::init_xft");
2373 if(!(smallfont_xft =
2374 (resources.small_font_xft[0] == '-' ?
2375 xftFontOpenXlfd(display, screen, resources.small_font_xft) :
2376 xftFontOpenName(display, screen, resources.small_font_xft))) )
2377 if(!(smallfont_xft =
2378 xftFontOpenXlfd(display, screen, resources.small_font_xft2)))
2379 smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2380 if(!(mediumfont_xft =
2381 (resources.medium_font_xft[0] == '-' ?
2382 xftFontOpenXlfd(display, screen, resources.medium_font_xft) :
2383 xftFontOpenName(display, screen, resources.medium_font_xft))) )
2384 if(!(mediumfont_xft =
2385 xftFontOpenXlfd(display, screen, resources.medium_font_xft2)))
2386 mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2387 if(!(largefont_xft =
2388 (resources.large_font_xft[0] == '-' ?
2389 xftFontOpenXlfd(display, screen, resources.large_font_xft) :
2390 xftFontOpenName(display, screen, resources.large_font_xft))) )
2391 if(!(largefont_xft =
2392 xftFontOpenXlfd(display, screen, resources.large_font_xft2)))
2393 largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
2395 (resources.big_font_xft[0] == '-' ?
2396 xftFontOpenXlfd(display, screen, resources.big_font_xft) :
2397 xftFontOpenName(display, screen, resources.big_font_xft))) )
2399 xftFontOpenXlfd(display, screen, resources.big_font_xft2)))
2400 bigfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2401 if(!(clockfont_xft =
2402 (resources.clock_font_xft[0] == '-' ?
2403 xftFontOpenXlfd(display, screen, resources.clock_font_xft) :
2404 xftFontOpenName(display, screen, resources.clock_font_xft))) )
2405 clockfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2408 if(!(bold_smallfont_xft =
2409 (resources.small_b_font_xft[0] == '-' ?
2410 xftFontOpenXlfd(display, screen, resources.small_b_font_xft) :
2411 xftFontOpenName(display, screen, resources.small_b_font_xft))) )
2412 bold_smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2413 if(!(bold_mediumfont_xft =
2414 (resources.medium_b_font_xft[0] == '-' ?
2415 xftFontOpenXlfd(display, screen, resources.medium_b_font_xft) :
2416 xftFontOpenName(display, screen, resources.medium_b_font_xft))) )
2417 bold_mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2418 if(!(bold_largefont_xft =
2419 (resources.large_b_font_xft[0] == '-' ?
2420 xftFontOpenXlfd(display, screen, resources.large_b_font_xft) :
2421 xftFontOpenName(display, screen, resources.large_b_font_xft))) )
2422 bold_largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
2424 if( !smallfont_xft || !mediumfont_xft || !largefont_xft || !bigfont_xft ||
2425 !bold_largefont_xft || !bold_mediumfont_xft || !bold_largefont_xft ||
2427 printf("BC_WindowBase::init_fonts: no xft fonts found:"
2428 " %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n",
2429 resources.small_font_xft, smallfont_xft,
2430 resources.medium_font_xft, mediumfont_xft,
2431 resources.large_font_xft, largefont_xft,
2432 resources.big_font_xft, bigfont_xft,
2433 resources.clock_font_xft, clockfont_xft,
2434 resources.small_b_font_xft, bold_smallfont_xft,
2435 resources.medium_b_font_xft, bold_mediumfont_xft,
2436 resources.large_b_font_xft, bold_largefont_xft);
2437 get_resources()->use_xft = 0;
2440 // _XftDisplayInfo needs a lock.
2441 xftDefaultHasRender(display);
2442 xft_init_lock.unlock();
2446 void BC_WindowBase::init_im()
2448 XIMStyles *xim_styles;
2451 if(!(input_method = XOpenIM(display, NULL, NULL, NULL)))
2453 printf("BC_WindowBase::init_im: Could not open input method.\n");
2456 if(XGetIMValues(input_method, XNQueryInputStyle, &xim_styles, NULL) ||
2459 printf("BC_WindowBase::init_im: Input method doesn't support any styles.\n");
2460 XCloseIM(input_method);
2465 for(int z = 0; z < xim_styles->count_styles; z++)
2467 if(xim_styles->supported_styles[z] == (XIMPreeditNothing | XIMStatusNothing))
2469 xim_style = xim_styles->supported_styles[z];
2477 printf("BC_WindowBase::init_im: Input method doesn't support the style we need.\n");
2478 XCloseIM(input_method);
2482 input_context = XCreateIC(input_method, XNInputStyle, xim_style,
2483 XNClientWindow, win, XNFocusWindow, win, NULL);
2486 printf("BC_WindowBase::init_im: Failed to create input context.\n");
2487 XCloseIM(input_method);
2492 void BC_WindowBase::finit_im()
2494 if( input_context ) {
2495 XDestroyIC(input_context);
2498 if( input_method ) {
2499 XCloseIM(input_method);
2505 int BC_WindowBase::get_color(int64_t color)
2507 // return pixel of color
2508 // use this only for drawing subwindows not for bitmaps
2509 int i, test, difference;
2515 return get_color_rgb8(color);
2516 // test last color looked up
2517 if(current_color_value == color)
2518 return current_color_pixel;
2521 current_color_value = color;
2522 for(i = 0; i < total_colors; i++)
2524 if(color_table[i][0] == color)
2526 current_color_pixel = color_table[i][1];
2527 return current_color_pixel;
2531 // find nearest match
2532 difference = 0xFFFFFF;
2534 for(i = 0; i < total_colors; i++)
2536 test = abs((int)(color_table[i][0] - color));
2538 if(test < difference)
2540 current_color_pixel = color_table[i][1];
2544 return current_color_pixel;
2547 return get_color_rgb16(color);
2550 return get_color_bgr16(color);
2554 return client_byte_order == server_byte_order ?
2555 color : get_color_bgr24(color);
2563 int BC_WindowBase::get_color_rgb8(int color)
2567 pixel = (color & 0xc00000) >> 16;
2568 pixel += (color & 0xe000) >> 10;
2569 pixel += (color & 0xe0) >> 5;
2573 int64_t BC_WindowBase::get_color_rgb16(int color)
2576 result = (color & 0xf80000) >> 8;
2577 result += (color & 0xfc00) >> 5;
2578 result += (color & 0xf8) >> 3;
2583 int64_t BC_WindowBase::get_color_bgr16(int color)
2586 result = (color & 0xf80000) >> 19;
2587 result += (color & 0xfc00) >> 5;
2588 result += (color & 0xf8) << 8;
2593 int64_t BC_WindowBase::get_color_bgr24(int color)
2596 result = (color & 0xff) << 16;
2597 result += (color & 0xff00);
2598 result += (color & 0xff0000) >> 16;
2602 void BC_WindowBase::start_video()
2604 cursor_timer->update();
2606 // set_color(BLACK);
2607 // draw_box(0, 0, get_w(), get_h());
2611 void BC_WindowBase::stop_video()
2619 int64_t BC_WindowBase::get_color()
2621 return top_level->current_color;
2624 void BC_WindowBase::set_color(int64_t color)
2626 top_level->current_color = color;
2627 XSetForeground(top_level->display,
2629 top_level->get_color(color));
2632 void BC_WindowBase::set_opaque()
2634 XSetFunction(top_level->display, top_level->gc, GXcopy);
2637 void BC_WindowBase::set_inverse()
2639 XSetFunction(top_level->display, top_level->gc, GXxor);
2642 void BC_WindowBase::set_line_width(int value)
2644 this->line_width = value;
2645 XSetLineAttributes(top_level->display, top_level->gc, value, /* line_width */
2646 line_dashes == 0 ? LineSolid : LineOnOffDash, /* line_style */
2647 line_dashes == 0 ? CapRound : CapNotLast, /* cap_style */
2648 JoinMiter); /* join_style */
2650 if(line_dashes > 0) {
2651 const char dashes = line_dashes;
2652 XSetDashes(top_level->display, top_level->gc, 0, &dashes, 1);
2655 // XGCValues gcvalues;
2656 // unsigned long gcmask;
2657 // gcmask = GCCapStyle | GCJoinStyle;
2658 // XGetGCValues(top_level->display, top_level->gc, gcmask, &gcvalues);
2659 // printf("BC_WindowBase::set_line_width %d %d %d\n", __LINE__, gcvalues.cap_style, gcvalues.join_style);
2662 void BC_WindowBase::set_line_dashes(int value)
2664 line_dashes = value;
2665 // call XSetLineAttributes
2666 set_line_width(line_width);
2670 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2674 case ARROW_CURSOR: return top_level->arrow_cursor;
2675 case CROSS_CURSOR: return top_level->cross_cursor;
2676 case IBEAM_CURSOR: return top_level->ibeam_cursor;
2677 case VSEPARATE_CURSOR: return top_level->vseparate_cursor;
2678 case HSEPARATE_CURSOR: return top_level->hseparate_cursor;
2679 case MOVE_CURSOR: return top_level->move_cursor;
2680 case LEFT_CURSOR: return top_level->left_cursor;
2681 case RIGHT_CURSOR: return top_level->right_cursor;
2682 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;
2683 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor;
2684 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor;
2685 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor;
2686 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor;
2687 case HOURGLASS_CURSOR: return top_level->hourglass_cursor;
2688 case TRANSPARENT_CURSOR: return top_level->transparent_cursor;
2689 case GRABBED_CURSOR: return top_level->grabbed_cursor;
2694 void BC_WindowBase::set_cursor(int cursor, int override, int flush)
2696 // inherit cursor from parent
2699 XUndefineCursor(top_level->display, win);
2700 current_cursor = cursor;
2703 // don't change cursor if overridden
2704 if((!top_level->is_hourglass && !is_transparent) ||
2707 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2708 if(flush) this->flush();
2711 if(!override) current_cursor = cursor;
2714 void BC_WindowBase::set_x_cursor(int cursor)
2716 temp_cursor = XCreateFontCursor(top_level->display, cursor);
2717 XDefineCursor(top_level->display, win, temp_cursor);
2718 current_cursor = cursor;
2722 int BC_WindowBase::get_cursor()
2724 return current_cursor;
2727 void BC_WindowBase::start_hourglass()
2729 top_level->start_hourglass_recursive();
2733 void BC_WindowBase::stop_hourglass()
2735 top_level->stop_hourglass_recursive();
2739 void BC_WindowBase::start_hourglass_recursive()
2741 if(this == top_level)
2749 set_cursor(HOURGLASS_CURSOR, 1, 0);
2750 for(int i = 0; i < subwindows->total; i++)
2752 subwindows->values[i]->start_hourglass_recursive();
2757 void BC_WindowBase::stop_hourglass_recursive()
2759 if(this == top_level)
2761 if(hourglass_total == 0) return;
2762 top_level->hourglass_total--;
2765 if(!top_level->hourglass_total)
2767 top_level->is_hourglass = 0;
2769 // Cause set_cursor to perform change
2771 set_cursor(current_cursor, 1, 0);
2773 for(int i = 0; i < subwindows->total; i++)
2775 subwindows->values[i]->stop_hourglass_recursive();
2783 XFontStruct* BC_WindowBase::get_font_struct(int font)
2785 // Clear out unrelated flags
2786 if(font & BOLDFACE) font ^= BOLDFACE;
2789 case SMALLFONT: return top_level->smallfont; break;
2790 case MEDIUMFONT: return top_level->mediumfont; break;
2791 case LARGEFONT: return top_level->largefont; break;
2792 case BIGFONT: return top_level->bigfont; break;
2793 case CLOCKFONT: return top_level->clockfont; break;
2798 XFontSet BC_WindowBase::get_fontset(int font)
2802 if(get_resources()->use_fontset)
2804 switch(font & 0xff) {
2805 case SMALLFONT: fs = top_level->smallfontset; break;
2806 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2807 case LARGEFONT: fs = top_level->largefontset; break;
2808 case BIGFONT: fs = top_level->bigfontset; break;
2809 case CLOCKFONT: fs = top_level->clockfontset; break;
2817 XftFont* BC_WindowBase::get_xft_struct(int font)
2820 case SMALLFONT: return (XftFont*)top_level->smallfont_xft;
2821 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft;
2822 case LARGEFONT: return (XftFont*)top_level->largefont_xft;
2823 case BIGFONT: return (XftFont*)top_level->bigfont_xft;
2824 case CLOCKFONT: return (XftFont*)top_level->clockfont_xft;
2825 case MEDIUMFONT_3D: return (XftFont*)top_level->bold_mediumfont_xft;
2826 case SMALLFONT_3D: return (XftFont*)top_level->bold_smallfont_xft;
2827 case LARGEFONT_3D: return (XftFont*)top_level->bold_largefont_xft;
2835 int BC_WindowBase::get_current_font()
2837 return top_level->current_font;
2840 void BC_WindowBase::set_font(int font)
2842 top_level->current_font = font;
2845 if(get_resources()->use_xft) {}
2848 if(get_resources()->use_fontset) {
2852 if(get_font_struct(font))
2854 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2860 void BC_WindowBase::set_fontset(int font)
2864 if(get_resources()->use_fontset) {
2866 case SMALLFONT: fs = top_level->smallfontset; break;
2867 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2868 case LARGEFONT: fs = top_level->largefontset; break;
2869 case BIGFONT: fs = top_level->bigfontset; break;
2870 case CLOCKFONT: fs = top_level->clockfontset; break;
2878 XFontSet BC_WindowBase::get_curr_fontset(void)
2880 if(get_resources()->use_fontset)
2881 return curr_fontset;
2885 int BC_WindowBase::get_single_text_width(int font, const char *text, int length)
2888 if(get_resources()->use_xft && get_xft_struct(font))
2891 #ifdef X_HAVE_UTF8_STRING
2892 if(get_resources()->locale_utf8)
2894 xftTextExtentsUtf8(top_level->display,
2895 get_xft_struct(font),
2896 (const XftChar8 *)text,
2903 xftTextExtents8(top_level->display,
2904 get_xft_struct(font),
2905 (const XftChar8 *)text,
2909 return extents.xOff;
2913 if(get_resources()->use_fontset && top_level->get_fontset(font))
2914 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2916 if(get_font_struct(font))
2917 return XTextWidth(get_font_struct(font), text, length);
2923 case MEDIUM_7SEGMENT:
2924 return get_resources()->medium_7segment[0]->get_w() * length;
2934 int BC_WindowBase::get_text_width(int font, const char *text, int length)
2936 int i, j, w = 0, line_w = 0;
2937 if(length < 0) length = strlen(text);
2939 for(i = 0, j = 0; i <= length; i++)
2944 line_w = get_single_text_width(font, &text[j], i - j);
2950 line_w = get_single_text_width(font, &text[j], length - j);
2952 if(line_w > w) w = line_w;
2955 if(i > length && w == 0)
2957 w = get_single_text_width(font, text, length);
2963 int BC_WindowBase::get_text_width(int font, const wchar_t *text, int length)
2966 if( length < 0 ) length = wcslen(text);
2968 for( i=j=0; i<length && text[i]; ++i ) {
2969 if( text[i] != '\n' ) continue;
2971 int lw = get_single_text_width(font, &text[j], i-j);
2972 if( w < lw ) w = lw;
2977 int lw = get_single_text_width(font, &text[j], length-j);
2978 if( w < lw ) w = lw;
2984 int BC_WindowBase::get_text_ascent(int font)
2988 if( (fstruct = get_xft_struct(font)) != 0 )
2989 return fstruct->ascent;
2991 if(get_resources()->use_fontset && top_level->get_fontset(font))
2993 XFontSetExtents *extents;
2995 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2996 return -extents->max_logical_extent.y;
2999 if(get_font_struct(font))
3000 return top_level->get_font_struct(font)->ascent;
3003 case MEDIUM_7SEGMENT:
3004 return get_resources()->medium_7segment[0]->get_h();
3009 int BC_WindowBase::get_text_descent(int font)
3013 if( (fstruct = get_xft_struct(font)) != 0 )
3014 return fstruct->descent;
3016 if(get_resources()->use_fontset && top_level->get_fontset(font)) {
3017 XFontSetExtents *extents;
3018 extents = XExtentsOfFontSet(top_level->get_fontset(font));
3019 return (extents->max_logical_extent.height
3020 + extents->max_logical_extent.y);
3023 if(get_font_struct(font))
3024 return top_level->get_font_struct(font)->descent;
3029 int BC_WindowBase::get_text_height(int font, const char *text)
3034 if( (fstruct = get_xft_struct(font)) != 0 )
3035 rowh = fstruct->height;
3038 rowh = get_text_ascent(font) + get_text_descent(font);
3040 if(!text) return rowh;
3042 // Add height of lines
3043 int h = 0, i, length = strlen(text);
3044 for(i = 0; i <= length; i++)
3055 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
3057 if(color_model < 0) color_model = top_level->get_color_model();
3058 return new BC_Bitmap(top_level, w, h, color_model);
3061 void BC_WindowBase::init_wait()
3063 #ifndef SINGLE_THREAD
3064 if(window_type != MAIN_WINDOW)
3065 top_level->init_wait();
3066 init_lock->lock("BC_WindowBase::init_wait");
3067 init_lock->unlock();
3071 int BC_WindowBase::accel_available(int color_model, int lock_it)
3073 if( window_type != MAIN_WINDOW )
3074 return top_level->accel_available(color_model, lock_it);
3076 lock_window("BC_WindowBase::accel_available");
3078 switch(color_model) {
3080 grab_port_id(color_model);
3084 grab_port_id(color_model);
3093 //printf("BC_WindowBase::accel_available %d %d\n", color_model, xvideo_port_id);
3094 return xvideo_port_id >= 0 ? 1 : 0;
3098 int BC_WindowBase::grab_port_id(int color_model)
3100 if( !get_resources()->use_xvideo || // disabled
3101 !get_resources()->use_shm ) // Only local server is fast enough.
3103 if( xvideo_port_id >= 0 )
3104 return xvideo_port_id;
3106 unsigned int ver, rev, reqBase, eventBase, errorBase;
3107 if( Success != XvQueryExtension(display, // XV extension is available
3108 &ver, &rev, &reqBase, &eventBase, &errorBase) )
3111 // XV adaptors are available
3112 unsigned int numAdapt = 0;
3113 XvAdaptorInfo *info = 0;
3114 XvQueryAdaptors(display, DefaultRootWindow(display), &numAdapt, &info);
3118 // Translate from color_model to X color model
3119 int x_color_model = BC_CModels::bc_to_x(color_model);
3121 // Get adaptor with desired color model
3122 for( int i = 0; i < (int)numAdapt && xvideo_port_id == -1; i++) {
3123 if( !(info[i].type & XvImageMask) || !info[i].num_ports ) continue;
3124 // adaptor supports XvImages
3125 int numFormats = 0, numPorts = info[i].num_ports;
3126 XvImageFormatValues *formats =
3127 XvListImageFormats(display, info[i].base_id, &numFormats);
3128 if( !formats ) continue;
3130 for( int j=0; j<numFormats && xvideo_port_id<0; ++j ) {
3131 if( formats[j].id != x_color_model ) continue;
3132 // this adaptor supports the desired format, grab a port
3133 for( int k=0; k<numPorts; ++k ) {
3134 if( Success == XvGrabPort(top_level->display,
3135 info[i].base_id+k, CurrentTime) ) {
3136 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
3137 xvideo_port_id = info[i].base_id + k;
3145 XvFreeAdaptorInfo(info);
3147 return xvideo_port_id;
3151 int BC_WindowBase::show_window(int flush)
3153 for(int i = 0; i < subwindows->size(); i++)
3155 subwindows->get(i)->show_window(0);
3158 XMapWindow(top_level->display, win);
3159 if(flush) XFlush(top_level->display);
3160 // XSync(top_level->display, 0);
3165 int BC_WindowBase::hide_window(int flush)
3167 for(int i = 0; i < subwindows->size(); i++)
3169 subwindows->get(i)->hide_window(0);
3172 XUnmapWindow(top_level->display, win);
3173 if(flush) this->flush();
3178 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
3180 subwindows->append((BC_SubWindow*)menu_bar);
3182 menu_bar->parent_window = this;
3183 menu_bar->top_level = this->top_level;
3184 menu_bar->initialize();
3188 BC_WindowBase* BC_WindowBase::add_popup(BC_WindowBase *window)
3190 //printf("BC_WindowBase::add_popup window=%p win=%p\n", window, window->win);
3191 if(this != top_level) return top_level->add_popup(window);
3192 popups.append(window);
3196 void BC_WindowBase::remove_popup(BC_WindowBase *window)
3198 //printf("BC_WindowBase::remove_popup %d size=%d window=%p win=%p\n", __LINE__, popups.size(), window, window->win);
3199 if(this != top_level)
3200 top_level->remove_popup(window);
3202 popups.remove(window);
3203 //printf("BC_WindowBase::remove_popup %d size=%d window=%p win=%p\n", __LINE__, popups.size(), window, window->win);
3207 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
3209 subwindows->append(subwindow);
3211 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
3213 // parent window must be set before the subwindow initialization
3214 subwindow->parent_window = this;
3215 subwindow->top_level = this->top_level;
3217 // Execute derived initialization
3218 subwindow->initialize();
3223 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
3225 return add_subwindow(subwindow);
3228 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
3230 if( !top_level->flash_enabled ) return 0;
3231 //printf("BC_WindowBase::flash %d %d %d %d %d\n", __LINE__, w, h, this->w, this->h);
3233 XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
3236 XClearArea(top_level->display, win, x, y, w, h, 0);
3240 XClearWindow(top_level->display, win);
3248 int BC_WindowBase::flash(int flush)
3250 flash(-1, -1, -1, -1, flush);
3254 void BC_WindowBase::flush()
3256 //if(!get_window_lock())
3257 // printf("BC_WindowBase::flush %s not locked\n", top_level->title);
3258 // X gets hosed if Flush/Sync are not user locked (at libX11-1.1.5 / libxcb-1.1.91)
3259 // _XReply deadlocks in condition_wait waiting for xlib lock when waiters!=-1
3260 int locked = get_window_lock();
3261 if( !locked ) lock_window("BC_WindowBase::flush");
3262 XFlush(top_level->display);
3263 if( !locked ) unlock_window();
3266 void BC_WindowBase::sync_display()
3268 int locked = get_window_lock();
3269 if( !locked ) lock_window("BC_WindowBase::sync_display");
3270 XSync(top_level->display, False);
3271 if( !locked ) unlock_window();
3274 int BC_WindowBase::get_window_lock()
3276 #ifdef SINGLE_THREAD
3277 return BC_Display::display_global->get_display_locked();
3279 return top_level->window_lock;
3283 int BC_WindowBase::lock_window(const char *location)
3285 if(top_level && top_level != this)
3287 top_level->lock_window(location);
3292 SET_LOCK(this, title, location);
3293 #ifdef SINGLE_THREAD
3294 BC_Display::lock_display(location);
3296 XLockDisplay(top_level->display);
3297 top_level->display_lock_owner = pthread_self();
3300 ++top_level->window_lock;
3304 printf("BC_WindowBase::lock_window top_level NULL\n");
3309 int BC_WindowBase::unlock_window()
3311 if(top_level && top_level != this)
3313 top_level->unlock_window();
3319 if( !top_level->window_lock ) {
3320 printf("BC_WindowBase::unlock_window %s not locked\n", title);
3323 if( top_level->window_lock > 0 )
3324 if( --top_level->window_lock == 0 )
3325 top_level->display_lock_owner = 0;
3326 #ifdef SINGLE_THREAD
3327 BC_Display::unlock_display();
3329 XUnlockDisplay(top_level->display);
3334 printf("BC_WindowBase::unlock_window top_level NULL\n");
3339 int BC_WindowBase::break_lock()
3341 if( !top_level ) return 0;
3342 if( top_level != this ) return top_level->break_lock();
3343 if( top_level->display_lock_owner != pthread_self() ) return 0;
3344 if( top_level->window_lock != 1 ) return 0;
3347 display_lock_owner = 0;
3348 #ifdef SINGLE_THREAD
3349 BC_Display::unlock_display();
3351 XUnlockDisplay(display);
3356 void BC_WindowBase::set_done(int return_value)
3358 if(done_set) return;
3360 if(window_type != MAIN_WINDOW)
3361 top_level->set_done(return_value);
3364 #ifdef SINGLE_THREAD
3365 this->return_value = return_value;
3366 BC_Display::display_global->arm_completion(this);
3367 completion_lock->unlock();
3368 #else // SINGLE_THREAD
3370 if( !event_thread ) return;
3371 XEvent *event = new_xevent();
3372 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
3373 event->type = ClientMessage;
3374 ptr->message_type = SetDoneXAtom;
3376 this->return_value = return_value;
3377 // May lock up here because XSendEvent doesn't work too well
3378 // asynchronous with XNextEvent.
3379 // This causes BC_WindowEvents to forward a copy of the event to run_window where
3381 // Deletion of event_thread is done at the end of BC_WindowBase::run_window() - by calling the destructor
3387 void BC_WindowBase::close(int return_value)
3389 hide_window(); flush();
3390 set_done(return_value);
3393 int BC_WindowBase::grab(BC_WindowBase *window)
3395 if( window->active_grab && this != window->active_grab ) return 0;
3396 window->active_grab = this;
3397 this->grab_active = window;
3400 int BC_WindowBase::ungrab(BC_WindowBase *window)
3402 if( window->active_grab && this != window->active_grab ) return 0;
3403 window->active_grab = 0;
3404 this->grab_active = 0;
3407 int BC_WindowBase::grab_event_count()
3410 #ifndef SINGLE_THREAD
3411 result = grab_active->get_event_count();
3415 int BC_WindowBase::grab_buttons()
3417 XSync(top_level->display, False);
3418 if( XGrabButton(top_level->display, AnyButton, AnyModifier,
3419 top_level->rootwin, True, ButtonPressMask | ButtonReleaseMask,
3420 GrabModeAsync, GrabModeSync, None, None) == GrabSuccess ) {
3421 set_active_subwindow(this);
3426 void BC_WindowBase::ungrab_buttons()
3428 XUngrabButton(top_level->display, AnyButton, AnyModifier, top_level->rootwin);
3429 set_active_subwindow(0);
3432 void BC_WindowBase::grab_cursor()
3434 Cursor cursor_grab = get_cursor_struct(GRABBED_CURSOR);
3435 XGrabPointer(top_level->display, top_level->rootwin, True,
3436 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
3437 GrabModeAsync, GrabModeAsync, None, cursor_grab, CurrentTime);
3439 void BC_WindowBase::ungrab_cursor()
3441 XUngrabPointer(top_level->display, CurrentTime);
3445 // WidthOfScreen/HeightOfScreen of XDefaultScreenOfDisplay
3446 // this is the bounding box of all the screens
3448 int BC_WindowBase::get_root_w(int lock_display)
3450 if(lock_display) lock_window("BC_WindowBase::get_root_w");
3451 Screen *def_screen = XDefaultScreenOfDisplay(top_level->display);
3452 int result = WidthOfScreen(def_screen);
3453 if(lock_display) unlock_window();
3457 int BC_WindowBase::get_root_h(int lock_display)
3459 if(lock_display) lock_window("BC_WindowBase::get_root_h");
3460 Screen *def_screen = XDefaultScreenOfDisplay(top_level->display);
3461 int result = HeightOfScreen(def_screen);
3462 if(lock_display) unlock_window();
3466 XineramaScreenInfo *
3467 BC_WindowBase::get_xinerama_info(int screen)
3469 if( !xinerama_info || !xinerama_screens ) return 0;
3471 for( int i=0; i<xinerama_screens; ++i )
3472 if( xinerama_info[i].screen_number == screen )
3473 return &xinerama_info[i];
3476 int top_x = get_x(), top_y = get_y();
3477 if( BC_DisplayInfo::left_border >= 0 ) top_x += BC_DisplayInfo::left_border;
3478 if( BC_DisplayInfo::top_border >= 0 ) top_y += BC_DisplayInfo::top_border;
3479 for( int i=0; i<xinerama_screens; ++i ) {
3480 int scr_y = top_y - xinerama_info[i].y_org;
3481 if( scr_y < 0 || scr_y >= xinerama_info[i].height ) continue;
3482 int scr_x = top_x - xinerama_info[i].x_org;
3483 if( scr_x >= 0 && scr_x < xinerama_info[i].width )
3484 return &xinerama_info[i];
3489 void BC_WindowBase::get_fullscreen_geometry(int &wx, int &wy, int &ww, int &wh)
3491 XineramaScreenInfo *info = top_level->get_xinerama_info(-1);
3493 wx = info->x_org; wy = info->y_org;
3494 ww = info->width; wh = info->height;
3497 wx = get_screen_x(0, -1);
3498 wy = get_screen_y(0, -1);
3499 int scr_w0 = get_screen_w(0, 0);
3500 int root_w = get_root_w(0);
3501 int root_h = get_root_h(0);
3502 if( root_w > scr_w0 ) { // multi-headed
3503 if( wx >= scr_w0 ) {
3504 // assumes right side is the big one
3505 ww = root_w - scr_w0;
3509 // use same aspect ratio to compute left height
3511 wh = (w*root_h) / (root_w-scr_w0);
3521 int BC_WindowBase::get_screen_x(int lock_display, int screen)
3524 if(lock_display) lock_window("BC_WindowBase::get_screen_x");
3525 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3528 int root_w = get_root_w(0);
3529 int root_h = get_root_h(0);
3530 // Shift X based on position of current window if dual head
3531 if( (float)root_w/root_h > 1.8 ) {
3532 root_w = get_screen_w(0, 0);
3533 if( top_level->get_x() >= root_w )
3538 result = info->x_org;
3539 if(lock_display) unlock_window();
3543 int BC_WindowBase::get_screen_y(int lock_display, int screen)
3545 if(lock_display) lock_window("BC_WindowBase::get_screen_y");
3546 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3547 int result = !info ? 0 : info->y_org;
3548 if(lock_display) unlock_window();
3552 int BC_WindowBase::get_screen_w(int lock_display, int screen)
3555 if(lock_display) lock_window("BC_WindowBase::get_screen_w");
3556 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3558 int width = get_root_w(0);
3559 int height = get_root_h(0);
3560 if( (float)width/height > 1.8 ) {
3561 // If dual head, the screen width is > 16x9
3562 // but we only want to fill one screen
3563 // this code assumes the "big" screen is on the right
3564 int scr_w0 = width / 2;
3566 case 600: scr_w0 = 800; break;
3567 case 720: scr_w0 = 1280; break;
3568 case 1024: scr_w0 = 1280; break;
3569 case 1200: scr_w0 = 1600; break;
3570 case 1080: scr_w0 = 1920; break;
3572 int scr_w1 = width - scr_w0;
3573 result = screen > 0 ? scr_w1 :
3574 screen == 0 ? scr_w0 :
3575 top_level->get_x() < scr_w0 ? scr_w0 : scr_w1;
3581 result = info->width;
3582 if(lock_display) unlock_window();
3586 int BC_WindowBase::get_screen_h(int lock_display, int screen)
3588 if(lock_display) lock_window("BC_WindowBase::get_screen_h");
3589 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3590 int result = info ? info->height : get_root_h(0);
3591 if(lock_display) unlock_window();
3595 // Bottom right corner
3596 int BC_WindowBase::get_x2()
3601 int BC_WindowBase::get_y2()
3606 int BC_WindowBase::get_video_on()
3611 int BC_WindowBase::get_hidden()
3613 return top_level->hidden;
3616 int BC_WindowBase::cursor_inside()
3618 return (top_level->cursor_x >= 0 &&
3619 top_level->cursor_y >= 0 &&
3620 top_level->cursor_x < w &&
3621 top_level->cursor_y < h);
3624 BC_WindowBase* BC_WindowBase::get_top_level()
3629 BC_WindowBase* BC_WindowBase::get_parent()
3631 return parent_window;
3634 int BC_WindowBase::get_color_model()
3636 return top_level->color_model;
3639 BC_Resources* BC_WindowBase::get_resources()
3641 return &BC_WindowBase::resources;
3644 BC_Synchronous* BC_WindowBase::get_synchronous()
3646 return BC_WindowBase::resources.get_synchronous();
3649 int BC_WindowBase::get_bg_color()
3654 void BC_WindowBase::set_bg_color(int color)
3656 this->bg_color = color;
3659 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
3664 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
3666 top_level->active_subwindow = subwindow;
3669 int BC_WindowBase::activate()
3674 int BC_WindowBase::deactivate()
3676 if(window_type == MAIN_WINDOW)
3678 if( top_level->active_menubar ) {
3679 top_level->active_menubar->deactivate();
3680 top_level->active_menubar = 0;
3682 if( top_level->active_popup_menu ) {
3683 top_level->active_popup_menu->deactivate();
3684 top_level->active_popup_menu = 0;
3686 if( top_level->active_subwindow ) {
3687 top_level->active_subwindow->deactivate();
3688 top_level->active_subwindow = 0;
3690 if( top_level->motion_events && top_level->last_motion_win == this->win )
3691 top_level->motion_events = 0;
3697 int BC_WindowBase::cycle_textboxes(int amount)
3700 BC_WindowBase *new_textbox = 0;
3704 BC_WindowBase *first_textbox = 0;
3705 find_next_textbox(&first_textbox, &new_textbox, result);
3706 if(!new_textbox) new_textbox = first_textbox;
3712 BC_WindowBase *last_textbox = 0;
3713 find_prev_textbox(&last_textbox, &new_textbox, result);
3714 if(!new_textbox) new_textbox = last_textbox;
3718 if(new_textbox != active_subwindow)
3721 new_textbox->activate();
3727 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
3729 // Search subwindows for textbox
3730 for(int i = 0; i < subwindows->total && result < 2; i++)
3732 BC_WindowBase *test_subwindow = subwindows->values[i];
3733 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
3740 if(!*first_textbox) *first_textbox = this;
3744 if(top_level->active_subwindow == this)
3750 *next_textbox = this;
3757 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
3763 if(!*last_textbox) *last_textbox = this;
3767 if(top_level->active_subwindow == this)
3773 *prev_textbox = this;
3778 // Search subwindows for textbox
3779 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
3781 BC_WindowBase *test_subwindow = subwindows->values[i];
3782 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
3787 BC_Clipboard* BC_WindowBase::get_clipboard()
3789 #ifdef SINGLE_THREAD
3790 return BC_Display::display_global->clipboard;
3792 return top_level->clipboard;
3796 Atom BC_WindowBase::to_clipboard(const char *data, long len, int clipboard_num)
3798 return get_clipboard()->to_clipboard(this, data, len, clipboard_num);
3801 long BC_WindowBase::from_clipboard(char *data, long maxlen, int clipboard_num)
3803 return get_clipboard()->from_clipboard(data, maxlen, clipboard_num);
3806 long BC_WindowBase::clipboard_len(int clipboard_num)
3808 return get_clipboard()->clipboard_len(clipboard_num);
3811 int BC_WindowBase::do_selection_clear(Window win)
3813 top_level->event_win = win;
3814 return dispatch_selection_clear();
3817 int BC_WindowBase::dispatch_selection_clear()
3820 for( int i=0; i<subwindows->total && !result; ++i )
3821 result = subwindows->values[i]->dispatch_selection_clear();
3823 result = selection_clear_event();
3828 void BC_WindowBase::get_relative_cursor(int &x, int &y, int lock_window)
3830 int abs_x, abs_y, win_x, win_y;
3831 unsigned int temp_mask;
3834 if(lock_window) this->lock_window("BC_WindowBase::get_relative_cursor");
3835 XQueryPointer(top_level->display, top_level->win,
3836 &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
3839 XTranslateCoordinates(top_level->display, top_level->rootwin,
3840 win, abs_x, abs_y, &x, &y, &temp_win);
3841 if(lock_window) this->unlock_window();
3843 int BC_WindowBase::get_relative_cursor_x(int lock_window)
3846 get_relative_cursor(x, y, lock_window);
3849 int BC_WindowBase::get_relative_cursor_y(int lock_window)
3852 get_relative_cursor(x, y, lock_window);
3856 void BC_WindowBase::get_abs_cursor(int &abs_x, int &abs_y, int lock_window)
3859 unsigned int temp_mask;
3862 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor");
3863 XQueryPointer(top_level->display, top_level->win,
3864 &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
3866 if(lock_window) this->unlock_window();
3868 int BC_WindowBase::get_abs_cursor_x(int lock_window)
3871 get_abs_cursor(abs_x, abs_y, lock_window);
3874 int BC_WindowBase::get_abs_cursor_y(int lock_window)
3877 get_abs_cursor(abs_x, abs_y, lock_window);
3881 void BC_WindowBase::get_pop_cursor(int &px, int &py, int lock_window)
3884 get_abs_cursor(px, py, lock_window);
3885 if( px < margin ) px = margin;
3886 if( py < margin ) py = margin;
3887 int wd = get_screen_w(lock_window,-1) - margin;
3888 if( px > wd ) px = wd;
3889 int ht = get_screen_h(lock_window,-1) - margin;
3890 if( py > ht ) py = ht;
3892 int BC_WindowBase::get_pop_cursor_x(int lock_window)
3895 get_pop_cursor(px, py, lock_window);
3898 int BC_WindowBase::get_pop_cursor_y(int lock_window)
3901 get_pop_cursor(px, py, lock_window);
3905 int BC_WindowBase::match_window(Window win)
3907 if (this->win == win) return 1;
3909 for(int i = 0; i < subwindows->total; i++) {
3910 result = subwindows->values[i]->match_window(win);
3911 if (result) return result;
3917 int BC_WindowBase::get_cursor_over_window()
3919 int abs_x, abs_y, win_x, win_y;
3920 unsigned int mask_return;
3921 Window root_return, child_return;
3923 int ret = XQueryPointer(top_level->display, top_level->rootwin,
3924 &root_return, &child_return, &abs_x, &abs_y,
3925 &win_x, &win_y, &mask_return);
3926 if( ret && child_return == None ) ret = 0;
3927 if( ret && win != child_return )
3928 ret = top_level->match_window(child_return);
3929 // query pointer can return a window manager window with this top_level as a child
3930 // for kde this can be two levels deep
3931 unsigned int nchildren_return = 0;
3932 Window parent_return, *children_return = 0;
3933 Window top_win = top_level->win;
3934 while( !ret && top_win != top_level->rootwin && top_win != root_return &&
3935 XQueryTree(top_level->display, top_win, &root_return,
3936 &parent_return, &children_return, &nchildren_return) ) {
3937 if( children_return ) XFree(children_return);
3938 if( (top_win=parent_return) == child_return ) ret = 1;
3943 int BC_WindowBase::cursor_above()
3946 get_relative_cursor(rx, ry);
3947 return rx < 0 || rx >= get_w() ||
3948 ry < 0 || ry >= get_h() ? 0 : 1;
3951 int BC_WindowBase::get_drag_x()
3953 return top_level->drag_x;
3956 int BC_WindowBase::get_drag_y()
3958 return top_level->drag_y;
3961 int BC_WindowBase::get_cursor_x()
3963 return top_level->cursor_x;
3966 int BC_WindowBase::get_cursor_y()
3968 return top_level->cursor_y;
3971 int BC_WindowBase::dump_windows()
3973 printf("\tBC_WindowBase::dump_windows window=%p win=%p '%s', %dx%d+%d+%d %s\n",
3974 this, (void*)this->win, title, w,h,x,y, typeid(*this).name());
3975 for(int i = 0; i < subwindows->size(); i++)
3976 subwindows->get(i)->dump_windows();
3977 for(int i = 0; i < popups.size(); i++) {
3978 BC_WindowBase *p = popups[i];
3979 printf("\tBC_WindowBase::dump_windows popup=%p win=%p '%s', %dx%d+%d+%d %s\n",
3980 p, (void*)p->win, p->title, p->w,p->h,p->x,p->y, typeid(*p).name());
3985 int BC_WindowBase::is_event_win()
3987 return this->win == top_level->event_win;
3990 void BC_WindowBase::set_dragging(int value)
3992 is_dragging = value;
3995 int BC_WindowBase::get_dragging()
4000 int BC_WindowBase::get_buttonpress()
4002 return top_level->button_number;
4005 int BC_WindowBase::get_button_down()
4007 return top_level->button_down;
4010 int BC_WindowBase::alt_down()
4012 return top_level->alt_mask;
4015 int BC_WindowBase::shift_down()
4017 return top_level->shift_mask;
4020 int BC_WindowBase::ctrl_down()
4022 return top_level->ctrl_mask;
4025 wchar_t* BC_WindowBase::get_wkeystring(int *length)
4028 *length = top_level->wkey_string_length;
4029 return top_level->wkey_string;
4032 #ifdef X_HAVE_UTF8_STRING
4033 char* BC_WindowBase::get_keypress_utf8()
4035 return top_level->key_pressed_utf8;
4040 int BC_WindowBase::get_keypress()
4042 return top_level->key_pressed;
4045 int BC_WindowBase::get_double_click()
4047 return top_level->double_click;
4050 int BC_WindowBase::get_triple_click()
4052 return top_level->triple_click;
4055 int BC_WindowBase::get_bgcolor()
4060 int BC_WindowBase::resize_window(int w, int h)
4062 if(this->w == w && this->h == h) return 0;
4064 if(window_type == MAIN_WINDOW && !allow_resize)
4066 XSizeHints size_hints;
4067 size_hints.flags = PSize | PMinSize | PMaxSize;
4068 size_hints.width = w;
4069 size_hints.height = h;
4070 size_hints.min_width = w;
4071 size_hints.max_width = w;
4072 size_hints.min_height = h;
4073 size_hints.max_height = h;
4074 if( this->x > -BC_INFINITY && this->x < BC_INFINITY ) {
4075 size_hints.flags |= PPosition;
4076 size_hints.x = this->x;
4077 size_hints.y = this->y;
4079 XSetNormalHints(top_level->display, win, &size_hints);
4081 XResizeWindow(top_level->display, win, w, h);
4086 pixmap = new BC_Pixmap(this, w, h);
4088 // Propagate to menubar
4089 for(int i = 0; i < subwindows->total; i++)
4091 subwindows->values[i]->dispatch_resize_event(w, h);
4094 draw_background(0, 0, w, h);
4095 if(top_level == this && get_resources()->recursive_resizing)
4096 resize_history.append(new BC_ResizeCall(w, h));
4100 // The only way for resize events to be propagated is by updating the internal w and h
4101 int BC_WindowBase::resize_event(int w, int h)
4103 if(window_type == MAIN_WINDOW)
4111 int BC_WindowBase::reposition_window(int x, int y)
4113 reposition_window(x, y, -1, -1);
4118 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
4122 // Some tools set their own dimensions before calling this, causing the
4123 // resize check to skip.
4127 if(w > 0 && w != this->w)
4133 if(h > 0 && h != this->h)
4139 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
4142 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
4144 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
4146 if(translation_count && window_type == MAIN_WINDOW)
4148 // KDE shifts window right and down.
4149 // FVWM leaves window alone and adds border around it.
4150 XMoveResizeWindow(top_level->display,
4152 x - BC_DisplayInfo::auto_reposition_x,
4153 y - BC_DisplayInfo::auto_reposition_y,
4159 XMoveResizeWindow(top_level->display,
4170 pixmap = new BC_Pixmap(this, this->w, this->h);
4171 clear_box(0,0, this->w, this->h);
4172 // Propagate to menubar
4173 for(int i = 0; i < subwindows->total; i++)
4175 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
4178 // draw_background(0, 0, w, h);
4184 int BC_WindowBase::reposition_window_relative(int dx, int dy, int w, int h)
4186 return reposition_window(get_x()+dx, get_y()+dy, w, h);
4189 int BC_WindowBase::reposition_window_relative(int dx, int dy)
4191 return reposition_window_relative(dx, dy, -1, -1);
4194 void BC_WindowBase::set_tooltips(int v)
4196 get_resources()->tooltips_enabled = v;
4199 void BC_WindowBase::set_force_tooltip(int v)
4204 int BC_WindowBase::raise_window(int do_flush)
4206 XRaiseWindow(top_level->display, win);
4207 if(do_flush) XFlush(top_level->display);
4211 int BC_WindowBase::lower_window(int do_flush)
4213 XLowerWindow(top_level->display, win);
4214 if(do_flush) XFlush(top_level->display);
4218 void BC_WindowBase::set_background(VFrame *bitmap)
4220 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
4222 bg_pixmap = new BC_Pixmap(this, bitmap, PIXMAP_OPAQUE);
4223 shared_bg_pixmap = 0;
4224 draw_background(0, 0, w, h);
4227 void BC_WindowBase::put_title(const char *text)
4229 char *cp = this->title, *ep = cp+sizeof(this->title)-1;
4230 for( const unsigned char *bp = (const unsigned char *)text; *bp && cp<ep; ++bp )
4231 *cp++ = *bp >= ' ' ? *bp : ' ';
4235 void BC_WindowBase::set_title(const char *text, int utf8)
4237 // utf8>0: wm + net_wm, utf8=0: wm only, utf<0: net_wm only
4239 const unsigned char *wm_title = (const unsigned char *)title;
4240 int title_len = strlen((const char *)title);
4242 Atom xa_wm_name = XA_WM_NAME;
4243 Atom xa_icon_name = XA_WM_ICON_NAME;
4244 Atom xa_string = XA_STRING;
4245 XChangeProperty(display, win, xa_wm_name, xa_string, 8,
4246 PropModeReplace, wm_title, title_len);
4247 XChangeProperty(display, win, xa_icon_name, xa_string, 8,
4248 PropModeReplace, wm_title, title_len);
4251 Atom xa_net_wm_name = XInternAtom(display, "_NET_WM_NAME", True);
4252 Atom xa_net_icon_name = XInternAtom(display, "_NET_WM_ICON_NAME", True);
4253 Atom xa_utf8_string = XInternAtom(display, "UTF8_STRING", True);
4254 XChangeProperty(display, win, xa_net_wm_name, xa_utf8_string, 8,
4255 PropModeReplace, wm_title, title_len);
4256 XChangeProperty(display, win, xa_net_icon_name, xa_utf8_string, 8,
4257 PropModeReplace, wm_title, title_len);
4262 const char *BC_WindowBase::get_title()
4267 int BC_WindowBase::get_toggle_value()
4269 return toggle_value;
4272 int BC_WindowBase::get_toggle_drag()
4277 int BC_WindowBase::set_icon(VFrame *data)
4279 if(icon_pixmap) delete icon_pixmap;
4280 icon_pixmap = new BC_Pixmap(top_level, data, PIXMAP_ALPHA, 1);
4282 if(icon_window) delete icon_window;
4283 icon_window = new BC_Popup(this,
4286 icon_pixmap->get_w(),
4287 icon_pixmap->get_h(),
4289 1, // All windows are hidden initially
4293 wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
4294 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
4295 wm_hints.icon_mask = icon_pixmap->get_alpha();
4296 wm_hints.icon_window = icon_window->win;
4297 wm_hints.window_group = XGroupLeader;
4299 // for(int i = 0; i < 1000; i++)
4300 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
4303 XSetWMHints(top_level->display, top_level->win, &wm_hints);
4304 XSync(top_level->display, 0);
4308 int BC_WindowBase::set_w(int w)
4314 int BC_WindowBase::set_h(int h)
4320 int BC_WindowBase::load_defaults(BC_Hash *defaults)
4322 BC_Resources *resources = get_resources();
4323 char string[BCTEXTLEN];
4324 int newest_id = - 1;
4325 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
4327 sprintf(string, "FILEBOX_HISTORY_PATH%d", i);
4328 resources->filebox_history[i].path[0] = 0;
4329 defaults->get(string, resources->filebox_history[i].path);
4330 sprintf(string, "FILEBOX_HISTORY_ID%d", i);
4331 resources->filebox_history[i].id = defaults->get(string, resources->get_id());
4332 if(resources->filebox_history[i].id > newest_id)
4333 newest_id = resources->filebox_history[i].id;
4336 resources->filebox_id = newest_id + 1;
4337 resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
4338 resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
4339 resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
4340 resources->filebox_columntype[0] = defaults->get("FILEBOX_TYPE0", resources->filebox_columntype[0]);
4341 resources->filebox_columntype[1] = defaults->get("FILEBOX_TYPE1", resources->filebox_columntype[1]);
4342 resources->filebox_columntype[2] = defaults->get("FILEBOX_TYPE2", resources->filebox_columntype[2]);
4343 resources->filebox_columntype[3] = defaults->get("FILEBOX_TYPE3", resources->filebox_columntype[3]);
4344 resources->filebox_columnwidth[0] = defaults->get("FILEBOX_WIDTH0", resources->filebox_columnwidth[0]);
4345 resources->filebox_columnwidth[1] = defaults->get("FILEBOX_WIDTH1", resources->filebox_columnwidth[1]);
4346 resources->filebox_columnwidth[2] = defaults->get("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
4347 resources->filebox_columnwidth[3] = defaults->get("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
4348 resources->filebox_size_format = defaults->get("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
4349 defaults->get("FILEBOX_FILTER", resources->filebox_filter);
4353 int BC_WindowBase::save_defaults(BC_Hash *defaults)
4355 BC_Resources *resources = get_resources();
4356 char string[BCTEXTLEN];
4357 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
4359 sprintf(string, "FILEBOX_HISTORY_PATH%d", i);
4360 defaults->update(string, resources->filebox_history[i].path);
4361 sprintf(string, "FILEBOX_HISTORY_ID%d", i);
4362 defaults->update(string, resources->filebox_history[i].id);
4364 defaults->update("FILEBOX_MODE", resources->filebox_mode);
4365 defaults->update("FILEBOX_W", resources->filebox_w);
4366 defaults->update("FILEBOX_H", resources->filebox_h);
4367 defaults->update("FILEBOX_TYPE0", resources->filebox_columntype[0]);
4368 defaults->update("FILEBOX_TYPE1", resources->filebox_columntype[1]);
4369 defaults->update("FILEBOX_TYPE2", resources->filebox_columntype[2]);
4370 defaults->update("FILEBOX_TYPE3", resources->filebox_columntype[3]);
4371 defaults->update("FILEBOX_WIDTH0", resources->filebox_columnwidth[0]);
4372 defaults->update("FILEBOX_WIDTH1", resources->filebox_columnwidth[1]);
4373 defaults->update("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
4374 defaults->update("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
4375 defaults->update("FILEBOX_FILTER", resources->filebox_filter);
4376 defaults->update("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
4382 // For some reason XTranslateCoordinates can take a long time to return.
4383 // We work around this by only calling it when the event windows are different.
4384 void BC_WindowBase::translate_coordinates(Window src_w,
4396 *dest_x_return = src_x;
4397 *dest_y_return = src_y;
4401 XTranslateCoordinates(top_level->display,
4409 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
4413 void BC_WindowBase::get_root_coordinates(int x, int y, int *abs_x, int *abs_y)
4415 translate_coordinates(win, top_level->rootwin, x, y, abs_x, abs_y);
4418 void BC_WindowBase::get_win_coordinates(int abs_x, int abs_y, int *x, int *y)
4420 translate_coordinates(top_level->rootwin, win, abs_x, abs_y, x, y);
4428 #ifdef HAVE_LIBXXF86VM
4429 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
4433 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
4435 XF86VidModeModeInfo **vm_modelines;
4436 XF86VidModeGetAllModeLines(top_level->display,
4437 XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
4438 for( i = 0; i < vm_count; i++ ) {
4439 if( vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay &&
4440 vm_modelines[i]->hdisplay >= *width )
4443 display = top_level->display;
4444 if( vm_modelines[*vm]->hdisplay == *width )
4447 *width = vm_modelines[*vm]->hdisplay;
4448 *height = vm_modelines[*vm]->vdisplay;
4453 void BC_WindowBase::scale_vm(int vm)
4455 int foo,bar,dotclock;
4456 if( XF86VidModeQueryExtension(top_level->display,&foo,&bar) ) {
4458 XF86VidModeModeInfo **vm_modelines;
4459 XF86VidModeModeLine vml;
4460 XF86VidModeGetAllModeLines(top_level->display,
4461 XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
4462 XF86VidModeGetModeLine(top_level->display,
4463 XDefaultScreen(top_level->display), &dotclock,&vml);
4464 orig_modeline.dotclock = dotclock;
4465 orig_modeline.hdisplay = vml.hdisplay;
4466 orig_modeline.hsyncstart = vml.hsyncstart;
4467 orig_modeline.hsyncend = vml.hsyncend;
4468 orig_modeline.htotal = vml.htotal;
4469 orig_modeline.vdisplay = vml.vdisplay;
4470 orig_modeline.vsyncstart = vml.vsyncstart;
4471 orig_modeline.vsyncend = vml.vsyncend;
4472 orig_modeline.vtotal = vml.vtotal;
4473 orig_modeline.flags = vml.flags;
4474 orig_modeline.privsize = vml.privsize;
4475 // orig_modeline.private = vml.private;
4476 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
4477 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
4478 XFlush(top_level->display);
4482 void BC_WindowBase::restore_vm()
4484 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
4485 XFlush(top_level->display);
4490 #ifndef SINGLE_THREAD
4491 int BC_WindowBase::get_event_count()
4493 event_lock->lock("BC_WindowBase::get_event_count");
4494 int result = common_events.total;
4495 event_lock->unlock();
4499 XEvent* BC_WindowBase::get_event()
4502 while(!done && !result)
4504 event_condition->lock("BC_WindowBase::get_event");
4505 event_lock->lock("BC_WindowBase::get_event");
4507 if(common_events.total && !done)
4509 result = common_events.values[0];
4510 common_events.remove_number(0);
4513 event_lock->unlock();
4518 void BC_WindowBase::put_event(XEvent *event)
4520 event_lock->lock("BC_WindowBase::put_event");
4521 common_events.append(event);
4522 event_lock->unlock();
4523 event_condition->unlock();
4526 void BC_WindowBase::dequeue_events(Window win)
4528 event_lock->lock("BC_WindowBase::dequeue_events");
4530 int out = 0, total = common_events.size();
4531 for( int in=0; in<total; ++in ) {
4532 if( common_events[in]->xany.window == win ) continue;
4533 common_events[out++] = common_events[in];
4535 common_events.total = out;
4537 event_lock->unlock();
4540 int BC_WindowBase::resend_event(BC_WindowBase *window)
4542 if( resend_event_window ) return 1;
4543 resend_event_window = window;
4549 int BC_WindowBase::resend_event(BC_WindowBase *window)
4554 #endif // SINGLE_THREAD
4556 int BC_WindowBase::get_id()
4562 BC_Pixmap *BC_WindowBase::create_pixmap(VFrame *vframe)
4564 int w = vframe->get_w(), h = vframe->get_h();
4565 BC_Pixmap *icon = new BC_Pixmap(this, w, h);
4566 icon->draw_vframe(vframe, 0,0, w,h, 0,0);
4571 void BC_WindowBase::flicker(int n, int ms)
4573 int color = get_bg_color();
4574 for( int i=2*n; --i>=0; ) {
4575 set_inverse(); set_bg_color(WHITE);
4576 clear_box(0,0, w,h); flash(1);
4577 sync_display(); Timer::delay(ms);
4579 set_bg_color(color);
4583 void BC_WindowBase::focus()
4585 XWindowAttributes xwa;
4586 XGetWindowAttributes(top_level->display, top_level->win, &xwa);
4587 if( xwa.map_state == IsViewable )
4588 XSetInputFocus(top_level->display, top_level->win, RevertToParent, CurrentTime);