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 get_resources()->get_synchronous()->delete_window(this);
155 XDestroyWindow(top_level->display, win);
157 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
158 if(icon_pixmap) delete icon_pixmap;
159 if(temp_bitmap) delete temp_bitmap;
160 top_level->active_bitmaps.remove_buffers(this);
161 if(_7segment_pixmaps)
163 for(int i = 0; i < TOTAL_7SEGMENT; i++)
164 delete _7segment_pixmaps[i];
166 delete [] _7segment_pixmaps;
171 if(window_type == MAIN_WINDOW)
173 XFreeGC(display, gc);
174 static XFontStruct *BC_WindowBase::*xfont[] = {
175 &BC_WindowBase::smallfont,
176 &BC_WindowBase::mediumfont,
177 &BC_WindowBase::largefont,
178 &BC_WindowBase::bigfont,
179 &BC_WindowBase::clockfont,
181 for( int i=sizeof(xfont)/sizeof(xfont[0]); --i>=0; )
182 XFreeFont(display, this->*xfont[i]);
185 // prevents a bug when Xft closes with unrefd fonts
186 FcPattern *defaults = FcPatternCreate();
187 FcPatternAddInteger(defaults, "maxunreffonts", 0);
188 XftDefaultSet(display, defaults);
190 static void *BC_WindowBase::*xft_font[] = {
191 &BC_WindowBase::smallfont_xft,
192 &BC_WindowBase::mediumfont_xft,
193 &BC_WindowBase::largefont_xft,
194 &BC_WindowBase::bigfont_xft,
195 &BC_WindowBase::bold_smallfont_xft,
196 &BC_WindowBase::bold_mediumfont_xft,
197 &BC_WindowBase::bold_largefont_xft,
198 &BC_WindowBase::clockfont_xft,
200 for( int i=sizeof(xft_font)/sizeof(xft_font[0]); --i>=0; ) {
201 XftFont *xft = (XftFont *)(this->*xft_font[i]);
202 if( xft ) xftFontClose (display, xft);
210 XFree(xinerama_info);
211 xinerama_screens = 0;
213 if( xvideo_port_id >= 0 )
214 XvUngrabPort(display, xvideo_port_id, CurrentTime);
217 // Must be last reference to display.
218 // _XftDisplayInfo needs a lock.
219 get_resources()->create_window_lock->lock("BC_WindowBase::~BC_WindowBase");
220 XCloseDisplay(display);
221 get_resources()->create_window_lock->unlock();
223 // clipboard uses a different display connection
224 clipboard->stop_clipboard();
228 resize_history.remove_all_objects();
230 #ifndef SINGLE_THREAD
231 common_events.remove_all_objects();
233 delete event_condition;
236 top_level->window_lock = 0;
237 BC_Display::unlock_display();
242 if( glx_fbcfgs_window ) XFree(glx_fbcfgs_window);
243 if( glx_fbcfgs_pbuffer) XFree(glx_fbcfgs_pbuffer);
244 if( glx_fbcfgs_pixmap ) XFree(glx_fbcfgs_pixmap);
247 UNSET_ALL_LOCKS(this)
250 int BC_WindowBase::initialize()
255 display_lock_owner = 0;
260 resend_event_window = 0;
272 xinerama_screens = 0;
277 translation_events = 0;
278 ctrl_mask = shift_mask = alt_mask = 0;
279 cursor_x = cursor_y = button_number = 0;
293 active_popup_menu = 0;
294 active_subwindow = 0;
298 _7segment_pixmaps = 0;
301 // next_repeat_id = 0;
303 current_font = MEDIUMFONT;
304 current_color = BLACK;
305 current_cursor = ARROW_CURSOR;
308 shared_bg_pixmap = 0;
311 window_type = MAIN_WINDOW;
312 translation_count = 0;
313 x_correction = y_correction = 0;
322 #ifdef HAVE_LIBXXF86VM
340 bold_smallfont_xft = 0;
341 bold_mediumfont_xft = 0;
342 bold_largefont_xft = 0;
344 completion_lock = new Condition(0, "BC_WindowBase::completion_lock");
346 // Need these right away since put_event is called before run_window sometimes.
347 event_lock = new Mutex("BC_WindowBase::event_lock");
348 event_condition = new Condition(0, "BC_WindowBase::event_condition");
349 init_lock = new Condition(0, "BC_WindowBase::init_lock");
352 cursor_timer = new Timer;
355 glx_fbcfgs_window = 0; n_fbcfgs_window = 0;
356 glx_fbcfgs_pbuffer = 0; n_fbcfgs_pbuffer = 0;
357 glx_fbcfgs_pixmap = 0; n_fbcfgs_pixmap = 0;
371 #define DEFAULT_EVENT_MASKS EnterWindowMask | \
374 ButtonReleaseMask | \
375 PointerMotionMask | \
379 int BC_WindowBase::create_window(BC_WindowBase *parent_window, const char *title,
380 int x, int y, int w, int h, int minw, int minh, int allow_resize,
381 int private_color, int hide, int bg_color, const char *display_name,
382 int window_type, BC_Pixmap *bg_pixmap, int group_it)
384 XSetWindowAttributes attr;
386 XSizeHints size_hints;
389 #ifdef HAVE_LIBXXF86VM
393 id = get_resources()->get_id();
394 if(parent_window) top_level = parent_window->top_level;
395 if( top_level ) lock_window("BC_WindowBase::create_window");
396 get_resources()->create_window_lock->lock("BC_WindowBase::create_window");
398 #ifdef HAVE_LIBXXF86VM
399 if(window_type == VIDMODE_SCALED_WINDOW)
400 closest_vm(&vm,&w,&h);
407 this->bg_color = bg_color;
408 this->window_type = window_type;
410 this->private_color = private_color;
411 this->parent_window = parent_window;
412 this->bg_pixmap = bg_pixmap;
413 this->allow_resize = allow_resize;
415 strcpy(this->display_name, display_name);
417 this->display_name[0] = 0;
420 if(bg_pixmap) shared_bg_pixmap = 1;
422 subwindows = new BC_SubWindowList;
424 if(window_type == MAIN_WINDOW)
427 parent_window = this;
431 display = BC_Display::get_display(display_name);
432 BC_Display::lock_display("BC_WindowBase::create_window");
433 // BC_Display::display_global->new_window(this);
436 // get the display connection
438 // This function must be the first Xlib
439 // function a multi-threaded program calls
441 display = init_display(display_name);
442 if( shm_completion_event < 0 ) shm_completion_event =
443 ShmCompletion + XShmGetEventBase(display);
445 lock_window("BC_WindowBase::create_window 1");
447 screen = DefaultScreen(display);
448 rootwin = RootWindow(display, screen);
449 // window placement boundaries
450 if( !xinerama_screens && XineramaIsActive(display) )
451 xinerama_info = XineramaQueryScreens(display, &xinerama_screens);
452 root_w = get_root_w(0);
453 root_h = get_root_h(0);
456 vis = get_glx_visual(display);
459 vis = DefaultVisual(display, screen);
461 default_depth = DefaultDepth(display, screen);
463 client_byte_order = (*(const u_int32_t*)"a ") & 0x00000001;
464 server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
467 // This must be done before fonts to know if antialiasing is available.
470 if(resources.use_shm < 0) resources.initialize_display(this);
471 x_correction = BC_DisplayInfo::get_left_border();
472 y_correction = BC_DisplayInfo::get_top_border();
474 // clamp window placement
475 if(this->x + this->w + x_correction > root_w)
476 this->x = root_w - this->w - x_correction;
477 if(this->y + this->h + y_correction > root_h)
478 this->y = root_h - this->h - y_correction;
479 if(this->x < 0) this->x = 0;
480 if(this->y < 0) this->y = 0;
482 if(this->bg_color == -1)
483 this->bg_color = resources.get_bg_color();
485 // printf("bcwindowbase 1 %s\n", title);
486 // if(window_type == MAIN_WINDOW) sleep(1);
487 // printf("bcwindowbase 10\n");
493 mask = CWEventMask | CWBackPixel | CWColormap | CWCursor;
495 attr.event_mask = DEFAULT_EVENT_MASKS |
496 StructureNotifyMask |
500 attr.background_pixel = get_color(this->bg_color);
501 attr.colormap = cmap;
502 attr.cursor = get_cursor_struct(ARROW_CURSOR);
504 win = XCreateWindow(display, rootwin,
505 this->x, this->y, this->w, this->h, 0,
506 top_level->default_depth, InputOutput,
508 XGetNormalHints(display, win, &size_hints);
510 size_hints.flags = PSize | PMinSize | PMaxSize;
511 size_hints.width = this->w;
512 size_hints.height = this->h;
513 size_hints.min_width = allow_resize ? minw : this->w;
514 size_hints.max_width = allow_resize ? 32767 : this->w;
515 size_hints.min_height = allow_resize ? minh : this->h;
516 size_hints.max_height = allow_resize ? 32767 : this->h;
517 if(x > -BC_INFINITY && x < BC_INFINITY)
519 size_hints.flags |= PPosition;
520 size_hints.x = this->x;
521 size_hints.y = this->y;
523 XSetWMProperties(display, win, 0, 0, 0, 0, &size_hints, 0, 0);
526 #ifndef SINGLE_THREAD
527 clipboard = new BC_Clipboard(this);
528 clipboard->start_clipboard();
534 Atom ClientLeaderXAtom;
535 if (XGroupLeader == 0)
537 const char *instance_name = "cinelerra";
538 const char *class_name = "Cinelerra";
539 XClassHint *class_hints = XAllocClassHint();
540 class_hints->res_name = (char*)instance_name;
541 class_hints->res_class = (char*)class_name;
542 XSetClassHint(top_level->display, win, class_hints);
544 ClientLeaderXAtom = XInternAtom(display, "WM_CLIENT_LEADER", True);
545 XChangeProperty(display, win, ClientLeaderXAtom, XA_WINDOW, 32,
546 PropModeReplace, (unsigned char *)&XGroupLeader, true);
549 set_icon(get_resources()->default_icon);
552 #ifdef HAVE_LIBXXF86VM
553 if(window_type == VIDMODE_SCALED_WINDOW && vm != -1)
560 #ifdef HAVE_LIBXXF86VM
561 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
563 if(window_type == POPUP_WINDOW)
566 mask = CWEventMask | CWBackPixel | CWColormap |
567 CWOverrideRedirect | CWSaveUnder | CWCursor;
569 attr.event_mask = DEFAULT_EVENT_MASKS | ExposureMask |
570 KeyPressMask | KeyReleaseMask;
572 if(this->bg_color == -1)
573 this->bg_color = resources.get_bg_color();
574 attr.background_pixel = top_level->get_color(bg_color);
575 attr.colormap = top_level->cmap;
576 if(top_level->is_hourglass)
577 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
579 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
580 attr.override_redirect = True;
581 attr.save_under = True;
583 win = XCreateWindow(top_level->display,
584 top_level->rootwin, this->x, this->y, this->w, this->h, 0,
585 top_level->default_depth, InputOutput, top_level->vis, mask,
587 top_level->add_popup(this);
590 if(window_type == SUB_WINDOW)
592 mask = CWEventMask | CWBackPixel | CWCursor;
593 attr.event_mask = DEFAULT_EVENT_MASKS;
594 attr.background_pixel = top_level->get_color(this->bg_color);
595 if(top_level->is_hourglass)
596 attr.cursor = top_level->get_cursor_struct(HOURGLASS_CURSOR);
598 attr.cursor = top_level->get_cursor_struct(ARROW_CURSOR);
599 win = XCreateWindow(top_level->display,
600 parent_window->win, this->x, this->y, this->w, this->h, 0,
601 top_level->default_depth, InputOutput, top_level->vis, mask,
604 if(!hidden) XMapWindow(top_level->display, win);
607 // Create pixmap for all windows
608 pixmap = new BC_Pixmap(this, this->w, this->h);
610 // Set up options for main window
611 if(window_type == MAIN_WINDOW)
613 if(get_resources()->bg_image && !bg_pixmap && bg_color < 0)
615 this->bg_pixmap = new BC_Pixmap(this,
616 get_resources()->bg_image,
620 if(!hidden) show_window();
624 draw_background(0, 0, this->w, this->h);
626 flash(-1, -1, -1, -1, 0);
628 // Set up options for popup window
629 #ifdef HAVE_LIBXXF86VM
630 if(window_type == POPUP_WINDOW || window_type == VIDMODE_SCALED_WINDOW)
632 if(window_type == POPUP_WINDOW)
636 if(!hidden) show_window();
638 get_resources()->create_window_lock->unlock();
644 Display* BC_WindowBase::init_display(const char *display_name)
648 if(display_name && display_name[0] == 0) display_name = NULL;
649 if((display = XOpenDisplay(display_name)) == NULL) {
650 printf("BC_WindowBase::init_display: cannot connect to X server %s\n",
652 if(getenv("DISPLAY") == NULL) {
653 printf(_("'DISPLAY' environment variable not set.\n"));
656 // Try again with default display.
657 if((display = XOpenDisplay(0)) == NULL) {
658 printf("BC_WindowBase::init_display: cannot connect to default X server.\n");
663 static int xsynch = -1;
665 const char *cp = getenv("CIN_XSYNCH");
666 xsynch = !cp ? 0 : atoi(cp);
669 XSynchronize(display, True);
674 Display* BC_WindowBase::get_display()
676 return top_level->display;
679 int BC_WindowBase::get_screen()
681 return top_level->screen;
684 int BC_WindowBase::run_window()
690 // Events may have been sent before run_window so can't initialize them here.
693 set_repeat(get_resources()->tooltip_delay);
694 BC_Display::display_global->new_window(this);
696 // If the first window created, run the display loop in this thread.
697 if(BC_Display::display_global->is_first(this))
699 BC_Display::unlock_display();
700 BC_Display::display_global->loop();
704 BC_Display::unlock_display();
705 completion_lock->lock("BC_WindowBase::run_window");
708 BC_Display::lock_display("BC_WindowBase::run_window");
709 BC_Display::display_global->delete_window(this);
711 unset_all_repeaters();
713 BC_Display::unlock_display();
715 #else // SINGLE_THREAD
720 set_repeat(get_resources()->tooltip_delay);
722 // Start X server events
723 event_thread = new BC_WindowEvents(this);
724 event_thread->start();
730 // Handle common events
735 unset_all_repeaters();
739 event_condition->reset();
740 common_events.remove_all_objects();
744 #endif // SINGLE_THREAD
749 int BC_WindowBase::get_key_masks(unsigned int key_state)
751 // printf("BC_WindowBase::get_key_masks %llx\n",
752 // event->xkey.state);
753 ctrl_mask = (key_state & ControlMask) ? 1 : 0; // ctrl key down
754 shift_mask = (key_state & ShiftMask) ? 1 : 0; // shift key down
755 alt_mask = (key_state & Mod1Mask) ? 1 : 0; // alt key down
760 void BC_WindowBase::add_keyboard_listener(int(BC_WindowBase::*handler)(BC_WindowBase *))
762 BC_KeyboardHandlerLock set;
763 BC_KeyboardHandler::listeners.append(new BC_KeyboardHandler(handler, this));
766 void BC_WindowBase::del_keyboard_listener(int(BC_WindowBase::*handler)(BC_WindowBase *))
768 BC_KeyboardHandlerLock set;
769 int i = BC_KeyboardHandler::listeners.size();
770 while( --i >= 0 && BC_KeyboardHandler::listeners[i]->handler!=handler );
771 if( i >= 0 ) BC_KeyboardHandler::listeners.remove_object_number(i);
774 int BC_KeyboardHandler::run_event(BC_WindowBase *wp)
776 int result = (win->*handler)(wp);
780 int BC_KeyboardHandler::run_listeners(BC_WindowBase *wp)
783 BC_KeyboardHandlerLock set;
784 for( int i=0; !result && i<listeners.size(); ++i ) {
785 BC_KeyboardHandler *listener = listeners[i];
786 result = listener->run_event(wp);
791 void BC_KeyboardHandler::kill_grabs()
793 BC_KeyboardHandlerLock set;
794 for( int i=0; i<listeners.size(); ++i ) {
795 BC_WindowBase *win = listeners[i]->win;
796 if( win->get_window_type() != POPUP_WINDOW ) continue;
797 ((BC_Popup *)win)->ungrab_keyboard();
801 void BC_ActiveBitmaps::reque(XEvent *event)
803 XShmCompletionEvent *shm_ev = (XShmCompletionEvent *)event;
804 ShmSeg shmseg = shm_ev->shmseg;
805 Drawable drawable = shm_ev->drawable;
806 //printf("BC_BitmapImage::reque %08lx\n",shmseg);
807 active_lock.lock("BC_BitmapImage::reque");
808 BC_BitmapImage *bfr = first;
809 while( bfr && bfr->get_shmseg() != shmseg ) bfr = bfr->next;
810 if( bfr && bfr->drawable == drawable )
812 active_lock.unlock();
814 // sadly, X reports two drawable completions and creates false reporting, so no boobytrap
815 // printf("BC_BitmapImage::reque missed shmseg %08x, drawable %08x\n",
816 // (int)shmseg, (int)drawable);
819 if( bfr->drawable != drawable ) return;
820 if( bfr->is_zombie() ) { --BC_Bitmap::zombies; delete bfr; return; }
821 bfr->bitmap->reque(bfr);
824 void BC_ActiveBitmaps::insert(BC_BitmapImage *bfr, Drawable pixmap)
826 active_lock.lock("BC_BitmapImage::insert");
827 bfr->drawable = pixmap;
829 active_lock.unlock();
832 void BC_ActiveBitmaps::remove_buffers(BC_WindowBase *wdw)
834 active_lock.lock("BC_ActiveBitmaps::remove");
835 for( BC_BitmapImage *nxt=0, *bfr=first; bfr; bfr=nxt ) {
837 if( bfr->is_zombie() ) { --BC_Bitmap::zombies; delete bfr; continue; }
838 if( bfr->bitmap->parent_window == wdw ) remove_pointer(bfr);
840 active_lock.unlock();
843 BC_ActiveBitmaps::BC_ActiveBitmaps()
847 BC_ActiveBitmaps::~BC_ActiveBitmaps()
853 int BC_WindowBase::keysym_lookup(XEvent *event)
855 for( int i = 0; i < KEYPRESSLEN; ++i ) keys_return[i] = 0;
856 for( int i = 0; i < 4; ++i ) wkey_string[i] = 0;
858 if( event->xany.send_event && !event->xany.serial ) {
859 keysym = (KeySym) event->xkey.keycode;
860 keys_return[0] = keysym;
863 wkey_string_length = 0;
865 if( input_context ) {
866 wkey_string_length = XwcLookupString(input_context,
867 (XKeyEvent*)event, wkey_string, 4, &keysym, 0);
868 //printf("keysym_lookup 1 %d %d %lx %x %x %x %x\n", wkey_string_length, keysym,
869 // wkey_string[0], wkey_string[1], wkey_string[2], wkey_string[3]);
872 int ret = Xutf8LookupString(input_context, (XKeyEvent*)event,
873 keys_return, KEYPRESSLEN, &keysym, &stat);
874 //printf("keysym_lookup 2 %d %d %lx %x %x\n", ret, stat, keysym, keys_return[0], keys_return[1]);
875 if( stat == XLookupBoth ) return ret;
876 if( stat == XLookupKeySym ) return 0;
878 int ret = XLookupString((XKeyEvent*)event, keys_return, KEYPRESSLEN, &keysym, 0);
879 wkey_string_length = ret;
880 for( int i=0; i<ret; ++i ) wkey_string[i] = keys_return[i];
884 pthread_t locking_task = (pthread_t)-1L;
885 int locking_event = -1;
886 int locking_message = -1;
888 int BC_WindowBase::dispatch_event()
892 XClientMessageEvent *ptr;
893 int cancel_resize, cancel_translation;
894 volatile static int debug = 0;
899 #ifndef SINGLE_THREAD
900 // If an event is waiting get it, otherwise
901 // wait for next event only if there are no compressed events.
902 if(get_event_count() ||
903 (!motion_events && !resize_events && !translation_events))
906 // Lock out window deletions
907 lock_window("BC_WindowBase::dispatch_event 1");
908 locking_event = event->type;
909 locking_task = pthread_self();
910 locking_message = event->xclient.message_type;
913 // Handle compressed events
915 lock_window("BC_WindowBase::dispatch_event 2");
917 dispatch_resize_event(last_resize_w, last_resize_h);
919 dispatch_motion_event();
920 if(translation_events)
921 dispatch_translation_event();
932 if( debug && event->type != ClientMessage ) {
933 static const char *event_names[] = {
934 "Reply", "Error", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify",
935 "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose",
936 "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify",
937 "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
938 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear",
939 "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify",
940 "GenericEvent", "LASTEvent",
942 const int nevents = sizeof(event_names)/sizeof(event_names[0]);
944 printf("BC_WindowBase::dispatch_event %d %s %p %d (%s)\n", __LINE__,
945 title, event, event->type, event->type>=0 && event->type<nevents ?
946 event_names[event->type] : "Unknown");
951 active_grab->lock_window("BC_WindowBase::dispatch_event 3");
952 result = active_grab->grab_event(event);
953 active_grab->unlock_window();
954 if( result ) return result;
955 lock_window("BC_WindowBase::dispatch_event 4");
958 switch(event->type) {
960 // Clear the resize buffer
962 dispatch_resize_event(last_resize_w, last_resize_h);
963 // Clear the motion buffer since this can clear the window
965 dispatch_motion_event();
967 ptr = (XClientMessageEvent*)event;
968 if( ptr->message_type == ProtoXAtom &&
969 (Atom)ptr->data.l[0] == DelWinXAtom ) {
972 else if( ptr->message_type == RepeaterXAtom ) {
973 dispatch_repeat_event(ptr->data.l[0]);
975 else if( ptr->message_type == SetDoneXAtom ) {
979 receive_custom_xatoms((xatom_event *)ptr);
990 dispatch_focus_out();
1004 dispatch_motion_event();
1006 get_key_masks(event->xbutton.state);
1007 cursor_x = event->xbutton.x;
1008 cursor_y = event->xbutton.y;
1009 button_number = event->xbutton.button;
1011 //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number);
1012 event_win = event->xany.window;
1013 if (button_number < 6) {
1014 if(button_number < 4)
1016 button_pressed = event->xbutton.button;
1017 button_time1 = button_time2;
1018 button_time2 = button_time3;
1019 button_time3 = event->xbutton.time;
1022 drag_win = event_win;
1023 drag_x1 = cursor_x - get_resources()->drag_radius;
1024 drag_x2 = cursor_x + get_resources()->drag_radius;
1025 drag_y1 = cursor_y - get_resources()->drag_radius;
1026 drag_y2 = cursor_y + get_resources()->drag_radius;
1028 if((long)(button_time3 - button_time1) < resources.double_click * 2)
1031 button_time3 = button_time2 = button_time1 = 0;
1033 if((long)(button_time3 - button_time2) < resources.double_click)
1036 // button_time3 = button_time2 = button_time1 = 0;
1044 dispatch_button_press();
1051 dispatch_motion_event();
1053 get_key_masks(event->xbutton.state);
1054 button_number = event->xbutton.button;
1055 event_win = event->xany.window;
1056 if (button_number < 6)
1058 if(button_number < 4)
1060 //printf("BC_WindowBase::dispatch_event %d %d\n", __LINE__, button_number);
1062 dispatch_button_release();
1067 event_win = event->xany.window;
1069 for( int i=0; !result && i<popups.size(); ++i ) { // popups take focus
1070 if( popups[i]->win == event_win )
1071 result = popups[i]->dispatch_expose_event();
1074 result = dispatch_expose_event();
1078 get_key_masks(event->xmotion.state);
1079 // Dispatch previous motion event if this is a subsequent motion from a different window
1080 if(motion_events && last_motion_win != event->xany.window)
1082 dispatch_motion_event();
1085 // Buffer the current motion
1087 last_motion_state = event->xmotion.state;
1088 last_motion_x = event->xmotion.x;
1089 last_motion_y = event->xmotion.y;
1090 last_motion_win = event->xany.window;
1093 case ConfigureNotify:
1094 // printf("BC_WindowBase::dispatch_event %d win=%p this->win=%p\n",
1096 // event->xany.window,
1099 XTranslateCoordinates(top_level->display,
1107 last_resize_w = event->xconfigure.width;
1108 last_resize_h = event->xconfigure.height;
1111 cancel_translation = 0;
1113 // Resize history prevents responses to recursive resize requests
1114 for(int i = 0; i < resize_history.total && !cancel_resize; i++)
1116 if(resize_history.values[i]->w == last_resize_w &&
1117 resize_history.values[i]->h == last_resize_h)
1119 delete resize_history.values[i];
1120 resize_history.remove_number(i);
1125 if(last_resize_w == w && last_resize_h == h)
1133 if((last_translate_x == x && last_translate_y == y))
1134 cancel_translation = 1;
1136 if(!cancel_translation)
1138 translation_events = 1;
1141 translation_count++;
1145 get_key_masks(event->xkey.state);
1146 keys_return[0] = 0; keysym = -1;
1147 if(XFilterEvent(event, win)) {
1150 if( keysym_lookup(event) < 0 ) {
1151 printf("keysym %x\n", (uint32_t)keysym);
1155 //printf("BC_WindowBase::dispatch_event %d keysym=0x%x\n",
1159 // block out control keys
1160 if(keysym > 0xffe0 && keysym < 0xffff) break;
1161 // block out Alt_GR key
1162 if(keysym == 0xfe03) break;
1165 printf("BC_WindowBase::dispatch_event %x\n", (uint32_t)keysym);
1167 #ifdef X_HAVE_UTF8_STRING
1168 //It's Ascii or UTF8?
1169 // if (keysym != 0xffff && (keys_return[0] & 0xff) >= 0x7f )
1170 //printf("BC_WindowBase::dispatch_event %d %02x%02x\n", __LINE__, keys_return[0], keys_return[1]);
1172 if( ((keys_return[1] & 0xff) > 0x80) &&
1173 ((keys_return[0] & 0xff) > 0xC0) ) {
1174 //printf("BC_WindowBase::dispatch_event %d\n", __LINE__);
1175 key_pressed = keysym & 0xff;
1179 // shuttle speed codes
1180 if( keysym >= SKEY_MIN && keysym <= SKEY_MAX ) {
1181 key_pressed = keysym;
1183 else switch( keysym ) {
1184 // block out extra keys
1194 // Translate key codes
1195 case XK_Return: key_pressed = RETURN; break;
1196 case XK_Up: key_pressed = UP; break;
1197 case XK_Down: key_pressed = DOWN; break;
1198 case XK_Left: key_pressed = LEFT; break;
1199 case XK_Right: key_pressed = RIGHT; break;
1200 case XK_Next: key_pressed = PGDN; break;
1201 case XK_Prior: key_pressed = PGUP; break;
1202 case XK_BackSpace: key_pressed = BACKSPACE; break;
1203 case XK_Escape: key_pressed = ESC; break;
1206 key_pressed = LEFTTAB;
1210 case XK_ISO_Left_Tab: key_pressed = LEFTTAB; break;
1211 case XK_underscore: key_pressed = '_'; break;
1212 case XK_asciitilde: key_pressed = '~'; break;
1213 case XK_Delete: key_pressed = DELETE; break;
1214 case XK_Home: key_pressed = HOME; break;
1215 case XK_End: key_pressed = END; break;
1218 case XK_KP_Enter: key_pressed = KPENTER; break;
1219 case XK_KP_Add: key_pressed = KPPLUS; break;
1220 case XK_KP_Subtract: key_pressed = KPMINUS; break;
1221 case XK_KP_Multiply: key_pressed = KPSTAR; break;
1222 case XK_KP_Divide: key_pressed = KPSLASH; break;
1224 case XK_KP_End: key_pressed = KP1; break;
1226 case XK_KP_Down: key_pressed = KP2; break;
1228 case XK_KP_Page_Down: key_pressed = KP3; break;
1230 case XK_KP_Left: key_pressed = KP4; break;
1232 case XK_KP_Begin: key_pressed = KP5; break;
1234 case XK_KP_Right: key_pressed = KP6; break;
1236 case XK_KP_Home: key_pressed = KP7; break;
1238 case XK_KP_Up: key_pressed = KP8; break;
1240 case XK_KP_Page_Up: key_pressed = KP9; break;
1242 case XK_KP_Insert: key_pressed = KPINS; break;
1244 case XK_KP_Delete: key_pressed = KPDEL; break;
1246 case XK_F1: key_pressed = KEY_F1; break;
1247 case XK_F2: key_pressed = KEY_F2; break;
1248 case XK_F3: key_pressed = KEY_F3; break;
1249 case XK_F4: key_pressed = KEY_F4; break;
1250 case XK_F5: key_pressed = KEY_F5; break;
1251 case XK_F6: key_pressed = KEY_F6; break;
1252 case XK_F7: key_pressed = KEY_F7; break;
1253 case XK_F8: key_pressed = KEY_F8; break;
1254 case XK_F9: key_pressed = KEY_F9; break;
1255 case XK_F10: key_pressed = KEY_F10; break;
1256 case XK_F11: key_pressed = KEY_F11; break;
1257 case XK_F12: key_pressed = KEY_F12; break;
1259 case XK_Menu: key_pressed = KPMENU; break; /* menu */
1261 // above case XK_KP_Enter: key_pressed = KPENTER; break; /* check */
1262 case XF86XK_MenuKB: key_pressed = KPMENU; break; /* menu */
1263 // intercepted case XF86XK_PowerDown: key_pressed = KPPOWER; break; /* Power */
1264 case XF86XK_Launch1: key_pressed = KPTV; break; /* TV */
1265 case XF86XK_Launch2: key_pressed = KPDVD; break; /* DVD */
1266 // intercepted case XF86XK_WWW: key_pressed = KPWWEB; break; /* WEB */
1267 case XF86XK_Launch3: key_pressed = KPBOOK; break; /* book */
1268 case XF86XK_Launch4: key_pressed = KPHAND; break; /* hand */
1269 case XF86XK_Reply: key_pressed = KPTMR; break; /* timer */
1270 case SunXK_Front: key_pressed = KPMAXW; break; /* max */
1271 // above case XK_Left: key_pressed = LEFT; break; /* left */
1272 // above case XK_Right: key_pressed = RIGHT; break; /* right */
1273 // above case XK_Down: key_pressed = DOWN; break; /* down */
1274 // above case XK_Up: key_pressed = UP; break; /* up */
1275 // above case XK_SPACE: key_pressed = KPSPACE; break; /* ok */
1276 // intercepted case XF86XK_AudioRaiseVolume: key_pressed = KPVOLU; break; /* VOL + */
1277 // intercepted case XF86XK_AudioMute: key_pressed = KPMUTE; break; /* MUTE */
1278 // intercepted case XF86XK_AudioLowerVolume: key_pressed = KPVOLD; break; /* VOL - */
1279 case XF86XK_ScrollUp: key_pressed = KPCHUP; break; /* CH + */
1280 case XF86XK_ScrollDown: key_pressed = KPCHDN; break; /* CH - */
1281 case XF86XK_AudioRecord: key_pressed = KPRECD; break; /* ( o) red */
1282 case XF86XK_Forward: key_pressed = KPPLAY; break; /* ( >) */
1283 case XK_Redo: key_pressed = KPFWRD; break; /* (>>) */
1284 case XF86XK_Back: key_pressed = KPBACK; break; /* (<<) */
1285 case XK_Cancel: key_pressed = KPSTOP; break; /* ([]) */
1286 case XK_Pause: key_pressed = KPAUSE; break; /* ('') */
1289 key_pressed = keysym & 0xff;
1290 #ifdef X_HAVE_UTF8_STRING
1291 //printf("BC_WindowBase::dispatch_event %d\n", __LINE__);
1296 #ifdef X_HAVE_UTF8_STRING
1298 key_pressed_utf8 = keys_return;
1303 if( top_level == this )
1304 result = BC_KeyboardHandler::run_listeners(this);
1306 //printf("BC_WindowBase::dispatch_event %d %d %x\n", shift_down(), alt_down(), key_pressed);
1308 result = dispatch_keypress_event();
1309 // Handle some default keypresses
1312 if(key_pressed == 'w' ||
1321 XLookupString((XKeyEvent*)event, keys_return, 1, &keysym, 0);
1322 dispatch_keyrelease_event();
1323 // printf("BC_WindowBase::dispatch_event KeyRelease keysym=0x%x keystate=0x%lld\n",
1324 // keysym, event->xkey.state);
1328 if( event->xcrossing.mode != NotifyNormal ) break;
1330 event_win = event->xany.window;
1331 dispatch_cursor_leave();
1335 if( event->xcrossing.mode != NotifyNormal ) break;
1337 if( !cursor_entered ) {
1338 for( int i=0; i<popups.size(); ++i ) { // popups always take focus
1339 if( popups[i]->win == event->xcrossing.window )
1342 if( !cursor_entered && get_resources()->grab_input_focus &&
1343 !event->xcrossing.focus && event->xcrossing.window == win ) {
1346 if( cursor_entered )
1349 event_win = event->xany.window;
1350 cursor_x = event->xcrossing.x;
1351 cursor_y = event->xcrossing.y;
1352 dispatch_cursor_enter();
1358 //printf("100 %s %p %d\n", title, event, event->type);
1359 //if(event->type != ClientMessage) dump();
1361 #ifndef SINGLE_THREAD
1364 if( resend_event_window ) {
1365 resend_event_window->put_event(event);
1366 resend_event_window = 0;
1372 // if(done) completion_lock->unlock();
1375 if(debug) printf("BC_WindowBase::dispatch_event this=%p %d\n", this, __LINE__);
1379 int BC_WindowBase::dispatch_expose_event()
1382 for(int i = 0; i < subwindows->total && !result; i++)
1384 result = subwindows->values[i]->dispatch_expose_event();
1387 // Propagate to user
1388 if(!result) expose_event();
1392 int BC_WindowBase::dispatch_resize_event(int w, int h)
1394 // Can't store new w and h until the event is handles
1395 // because bcfilebox depends on the old w and h to
1396 // reposition widgets.
1397 if( window_type == MAIN_WINDOW ) {
1402 pixmap = new BC_Pixmap(this, w, h);
1403 clear_box(0, 0, w, h);
1406 // Propagate to subwindows
1407 for(int i = 0; i < subwindows->total; i++) {
1408 subwindows->values[i]->dispatch_resize_event(w, h);
1411 // Propagate to user
1414 if( window_type == MAIN_WINDOW ) {
1423 int BC_WindowBase::dispatch_flash()
1426 for(int i = 0; i < subwindows->total; i++)
1427 subwindows->values[i]->dispatch_flash();
1431 int BC_WindowBase::dispatch_translation_event()
1433 translation_events = 0;
1434 if(window_type == MAIN_WINDOW)
1438 x = last_translate_x;
1439 y = last_translate_y;
1440 // Correct for window manager offsets
1445 for(int i = 0; i < subwindows->total; i++)
1447 subwindows->values[i]->dispatch_translation_event();
1450 translation_event();
1454 int BC_WindowBase::dispatch_motion_event()
1459 if(top_level == this)
1462 event_win = last_motion_win;
1463 get_key_masks(last_motion_state);
1466 if(get_button_down() && !active_menubar && !active_popup_menu)
1470 cursor_x = last_motion_x;
1471 cursor_y = last_motion_y;
1472 result = dispatch_drag_motion();
1476 (last_motion_x < drag_x1 || last_motion_x >= drag_x2 ||
1477 last_motion_y < drag_y1 || last_motion_y >= drag_y2))
1482 result = dispatch_drag_start();
1486 cursor_x = last_motion_x;
1487 cursor_y = last_motion_y;
1489 // printf("BC_WindowBase::dispatch_motion_event %d %p %p %p\n",
1492 // active_popup_menu,
1493 // active_subwindow);
1495 if(active_menubar && !result) result = active_menubar->dispatch_motion_event();
1496 if(active_popup_menu && !result) result = active_popup_menu->dispatch_motion_event();
1497 if(active_subwindow && !result) result = active_subwindow->dispatch_motion_event();
1500 // Dispatch in stacking order
1501 for(int i = subwindows->size() - 1; i >= 0 && !result; i--)
1503 result = subwindows->values[i]->dispatch_motion_event();
1506 if(!result) result = cursor_motion_event(); // give to user
1510 int BC_WindowBase::dispatch_keypress_event()
1513 if(top_level == this)
1515 if(active_subwindow) result = active_subwindow->dispatch_keypress_event();
1518 for(int i = 0; i < subwindows->total && !result; i++)
1520 result = subwindows->values[i]->dispatch_keypress_event();
1523 if(!result) result = keypress_event();
1528 int BC_WindowBase::dispatch_keyrelease_event()
1531 if(top_level == this)
1533 if(active_subwindow) result = active_subwindow->dispatch_keyrelease_event();
1536 for(int i = 0; i < subwindows->total && !result; i++)
1538 result = subwindows->values[i]->dispatch_keyrelease_event();
1541 if(!result) result = keyrelease_event();
1546 int BC_WindowBase::dispatch_focus_in()
1548 for(int i = 0; i < subwindows->total; i++)
1550 subwindows->values[i]->dispatch_focus_in();
1558 int BC_WindowBase::dispatch_focus_out()
1560 for(int i = 0; i < subwindows->total; i++)
1562 subwindows->values[i]->dispatch_focus_out();
1570 int BC_WindowBase::get_has_focus()
1572 return top_level->has_focus;
1575 int BC_WindowBase::get_deleting()
1577 if(is_deleting) return 1;
1578 if(parent_window && parent_window->get_deleting()) return 1;
1582 int BC_WindowBase::dispatch_button_press()
1587 if(top_level == this)
1589 if(active_menubar) result = active_menubar->dispatch_button_press();
1590 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_press();
1591 if(active_subwindow && !result) result = active_subwindow->dispatch_button_press();
1594 for(int i = 0; i < subwindows->total && !result; i++)
1596 result = subwindows->values[i]->dispatch_button_press();
1599 if(!result) result = button_press_event();
1605 int BC_WindowBase::dispatch_button_release()
1608 if(top_level == this)
1610 if(active_menubar) result = active_menubar->dispatch_button_release();
1611 if(active_popup_menu && !result) result = active_popup_menu->dispatch_button_release();
1612 if(active_subwindow && !result) result = active_subwindow->dispatch_button_release();
1613 if(!result && button_number != 4 && button_number != 5)
1614 result = dispatch_drag_stop();
1617 for(int i = 0; i < subwindows->total && !result; i++)
1619 result = subwindows->values[i]->dispatch_button_release();
1624 result = button_release_event();
1631 int BC_WindowBase::dispatch_repeat_event(int64_t duration)
1634 // all repeat event handlers get called and decide based on activity and duration
1635 // whether to respond
1636 for(int i = 0; i < subwindows->total; i++)
1638 subwindows->values[i]->dispatch_repeat_event(duration);
1642 repeat_event(duration);
1646 // Unlock next repeat signal
1647 if(window_type == MAIN_WINDOW)
1649 #ifdef SINGLE_THREAD
1650 BC_Display::display_global->unlock_repeaters(duration);
1652 for(int i = 0; i < repeaters.total; i++)
1654 if(repeaters.values[i]->delay == duration)
1656 repeaters.values[i]->repeat_lock->unlock();
1664 void BC_WindowBase::unhide_cursor()
1669 if(top_level->is_hourglass)
1670 set_cursor(HOURGLASS_CURSOR, 1, 0);
1672 set_cursor(current_cursor, 1, 0);
1674 cursor_timer->update();
1678 void BC_WindowBase::update_video_cursor()
1680 if(video_on && !is_transparent)
1682 if(cursor_timer->get_difference() > VIDEO_CURSOR_TIMEOUT && !is_transparent)
1685 set_cursor(TRANSPARENT_CURSOR, 1, 1);
1686 cursor_timer->update();
1691 cursor_timer->update();
1696 int BC_WindowBase::dispatch_cursor_leave()
1700 for(int i = 0; i < subwindows->total; i++)
1702 subwindows->values[i]->dispatch_cursor_leave();
1705 cursor_leave_event();
1709 int BC_WindowBase::dispatch_cursor_enter()
1715 if(active_menubar) result = active_menubar->dispatch_cursor_enter();
1716 if(!result && active_popup_menu) result = active_popup_menu->dispatch_cursor_enter();
1717 if(!result && active_subwindow) result = active_subwindow->dispatch_cursor_enter();
1719 for(int i = 0; !result && i < subwindows->total; i++)
1721 result = subwindows->values[i]->dispatch_cursor_enter();
1724 if(!result) result = cursor_enter_event();
1728 int BC_WindowBase::cursor_enter_event()
1733 int BC_WindowBase::cursor_leave_event()
1738 int BC_WindowBase::close_event()
1744 int BC_WindowBase::dispatch_drag_start()
1747 if(active_menubar) result = active_menubar->dispatch_drag_start();
1748 if(!result && active_popup_menu) result = active_popup_menu->dispatch_drag_start();
1749 if(!result && active_subwindow) result = active_subwindow->dispatch_drag_start();
1751 for(int i = 0; i < subwindows->total && !result; i++)
1753 result = subwindows->values[i]->dispatch_drag_start();
1756 if(!result) result = is_dragging = drag_start_event();
1760 int BC_WindowBase::dispatch_drag_stop()
1764 for(int i = 0; i < subwindows->total && !result; i++)
1766 result = subwindows->values[i]->dispatch_drag_stop();
1769 if(is_dragging && !result)
1779 int BC_WindowBase::dispatch_drag_motion()
1782 for(int i = 0; i < subwindows->total && !result; i++)
1784 result = subwindows->values[i]->dispatch_drag_motion();
1787 if(is_dragging && !result)
1789 drag_motion_event();
1797 int BC_WindowBase::show_tooltip(const char *text, int x, int y, int w, int h)
1800 int forced = !text ? force_tooltip : 1;
1801 if( !text ) text = tooltip_text;
1802 if( !text || (!forced && !get_resources()->tooltips_enabled) ) {
1803 top_level->hide_tooltip();
1807 if(w < 0) w = get_text_width(MEDIUMFONT, text) + TOOLTIP_MARGIN * 2;
1808 if(h < 0) h = get_text_height(MEDIUMFONT, text) + TOOLTIP_MARGIN * 2;
1809 // default x,y (win relative)
1810 if( x < 0 ) x = get_w();
1811 if( y < 0 ) y = get_h();
1813 get_root_coordinates(x, y, &wx, &wy);
1814 // keep the tip inside the window/display
1815 int x0 = top_level->get_x(), x1 = x0 + top_level->get_w();
1816 int x2 = top_level->get_screen_x(0, -1) + top_level->get_screen_w(0, -1);
1817 if( x1 > x2 ) x1 = x2;
1818 if( wx < x0 ) wx = x0;
1819 if( wx >= (x1-=w) ) wx = x1;
1820 int y0 = top_level->get_y(), y1 = y0 + top_level->get_h();
1821 int y2 = top_level->get_root_h(0);
1822 if( y1 > y2 ) y1 = y2;
1823 if( wy < y0 ) wy = y0;
1824 if( wy >= (y1-=h) ) wy = y1;
1825 // avoid tip under cursor (flickers)
1827 get_abs_cursor(abs_x,abs_y, 0);
1828 if( wx < abs_x && abs_x < wx+w && wy < abs_y && abs_y < wy+h ) {
1829 if( wx-abs_x < wy-abs_y )
1836 tooltip_popup = new BC_Popup(top_level, wx, wy, w, h,
1837 get_resources()->tooltip_bg_color);
1840 tooltip_popup->reposition_window(wx, wy, w, h);
1843 tooltip_popup->flash();
1844 tooltip_popup->flush();
1848 int BC_WindowBase::hide_tooltip()
1851 for(int i = 0; i < subwindows->total; i++)
1853 subwindows->values[i]->hide_tooltip();
1859 delete tooltip_popup;
1865 const char *BC_WindowBase::get_tooltip()
1867 return tooltip_text;
1870 int BC_WindowBase::set_tooltip(const char *text)
1872 tooltip_text = text;
1874 // Update existing tooltip if it is visible
1878 tooltip_popup->flash();
1882 // signal the event handler to repeat
1883 int BC_WindowBase::set_repeat(int64_t duration)
1887 printf("BC_WindowBase::set_repeat duration=%jd\n", duration);
1890 if(window_type != MAIN_WINDOW) return top_level->set_repeat(duration);
1892 #ifdef SINGLE_THREAD
1893 BC_Display::display_global->set_repeat(this, duration);
1895 // test repeater database for duplicates
1896 for(int i = 0; i < repeaters.total; i++)
1899 if(repeaters.values[i]->delay == duration)
1901 repeaters.values[i]->start_repeating(this);
1906 BC_Repeater *repeater = new BC_Repeater(this, duration);
1907 repeater->initialize();
1908 repeaters.append(repeater);
1909 repeater->start_repeating();
1914 int BC_WindowBase::unset_repeat(int64_t duration)
1916 if(window_type != MAIN_WINDOW) return top_level->unset_repeat(duration);
1918 #ifdef SINGLE_THREAD
1919 BC_Display::display_global->unset_repeat(this, duration);
1921 for(int i = 0; i < repeaters.total; i++)
1923 if(repeaters.values[i]->delay == duration)
1925 repeaters.values[i]->stop_repeating();
1933 int BC_WindowBase::unset_all_repeaters()
1935 #ifdef SINGLE_THREAD
1936 BC_Display::display_global->unset_all_repeaters(this);
1938 for(int i = 0; i < repeaters.total; i++)
1940 repeaters.values[i]->stop_repeating();
1942 repeaters.remove_all_objects();
1947 // long BC_WindowBase::get_repeat_id()
1949 // return top_level->next_repeat_id++;
1952 XEvent *BC_WindowBase::new_xevent()
1954 XEvent *event = new XEvent;
1955 memset(event, 0, sizeof(*event));
1959 #ifndef SINGLE_THREAD
1960 int BC_WindowBase::arm_repeat(int64_t duration)
1962 XEvent *event = new_xevent();
1963 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
1964 ptr->type = ClientMessage;
1965 ptr->message_type = RepeaterXAtom;
1967 ptr->data.l[0] = duration;
1969 // Couldn't use XSendEvent since it locked up randomly.
1975 int BC_WindowBase::receive_custom_xatoms(xatom_event *event)
1980 int BC_WindowBase::send_custom_xatom(xatom_event *event)
1982 #ifndef SINGLE_THREAD
1983 XEvent *myevent = new_xevent();
1984 XClientMessageEvent *ptr = (XClientMessageEvent*)myevent;
1985 ptr->type = ClientMessage;
1986 ptr->message_type = event->message_type;
1987 ptr->format = event->format;
1988 ptr->data.l[0] = event->data.l[0];
1989 ptr->data.l[1] = event->data.l[1];
1990 ptr->data.l[2] = event->data.l[2];
1991 ptr->data.l[3] = event->data.l[3];
1992 ptr->data.l[4] = event->data.l[4];
2001 Atom BC_WindowBase::create_xatom(const char *atom_name)
2003 return XInternAtom(display, atom_name, False);
2006 int BC_WindowBase::get_atoms()
2008 SetDoneXAtom = XInternAtom(display, "BC_REPEAT_EVENT", False);
2009 RepeaterXAtom = XInternAtom(display, "BC_CLOSE_EVENT", False);
2010 DestroyAtom = XInternAtom(display, "BC_DESTROY_WINDOW", False);
2011 DelWinXAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
2012 if( (ProtoXAtom = XInternAtom(display, "WM_PROTOCOLS", False)) != 0 )
2013 XChangeProperty(display, win, ProtoXAtom, XA_ATOM, 32,
2014 PropModeReplace, (unsigned char *)&DelWinXAtom, True);
2020 void BC_WindowBase::init_cursors()
2022 arrow_cursor = XCreateFontCursor(display, XC_top_left_arrow);
2023 cross_cursor = XCreateFontCursor(display, XC_crosshair);
2024 ibeam_cursor = XCreateFontCursor(display, XC_xterm);
2025 vseparate_cursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
2026 hseparate_cursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
2027 move_cursor = XCreateFontCursor(display, XC_fleur);
2028 left_cursor = XCreateFontCursor(display, XC_sb_left_arrow);
2029 right_cursor = XCreateFontCursor(display, XC_sb_right_arrow);
2030 upright_arrow_cursor = XCreateFontCursor(display, XC_arrow);
2031 upleft_resize_cursor = XCreateFontCursor(display, XC_top_left_corner);
2032 upright_resize_cursor = XCreateFontCursor(display, XC_top_right_corner);
2033 downleft_resize_cursor = XCreateFontCursor(display, XC_bottom_left_corner);
2034 downright_resize_cursor = XCreateFontCursor(display, XC_bottom_right_corner);
2035 hourglass_cursor = XCreateFontCursor(display, XC_watch);
2036 grabbed_cursor = create_grab_cursor();
2038 static char cursor_data[] = { 0,0,0,0, 0,0,0,0 };
2039 Colormap colormap = DefaultColormap(display, screen);
2040 Pixmap pixmap_bottom = XCreateBitmapFromData(display,
2041 rootwin, cursor_data, 8, 8);
2042 XColor black, dummy;
2043 XAllocNamedColor(display, colormap, "black", &black, &dummy);
2044 transparent_cursor = XCreatePixmapCursor(display,
2045 pixmap_bottom, pixmap_bottom, &black, &black, 0, 0);
2046 // XDefineCursor(display, win, transparent_cursor);
2047 XFreePixmap(display, pixmap_bottom);
2050 int BC_WindowBase::evaluate_color_model(int client_byte_order, int server_byte_order, int depth)
2052 int color_model = BC_TRANSPARENCY;
2056 color_model = BC_RGB8;
2059 color_model = (server_byte_order == client_byte_order) ? BC_RGB565 : BC_BGR565;
2062 color_model = server_byte_order ? BC_BGR888 : BC_RGB888;
2065 color_model = server_byte_order ? BC_BGR8888 : BC_ARGB8888;
2071 int BC_WindowBase::init_colors()
2074 current_color_value = current_color_pixel = 0;
2076 // Get the real depth
2079 ximage = XCreateImage(top_level->display,
2081 top_level->default_depth,
2089 bits_per_pixel = ximage->bits_per_pixel;
2090 XDestroyImage(ximage);
2092 color_model = evaluate_color_model(client_byte_order,
2095 // Get the color model
2100 cmap = XCreateColormap(display, rootwin, vis, AllocNone);
2101 create_private_colors();
2104 cmap = DefaultColormap(display, screen);
2105 create_shared_colors();
2108 allocate_color_table();
2112 //cmap = DefaultColormap(display, screen);
2113 cmap = XCreateColormap(display, rootwin, vis, AllocNone );
2119 int BC_WindowBase::create_private_colors()
2124 for(int i = 0; i < 255; i++)
2126 color = (i & 0xc0) << 16;
2127 color += (i & 0x38) << 10;
2128 color += (i & 0x7) << 5;
2129 color_table[i][0] = color;
2131 create_shared_colors(); // overwrite the necessary colors on the table
2136 int BC_WindowBase::create_color(int color)
2138 if(total_colors == 256)
2140 // replace the closest match with an exact match
2141 color_table[get_color_rgb8(color)][0] = color;
2145 // add the color to the table
2146 color_table[total_colors][0] = color;
2152 int BC_WindowBase::create_shared_colors()
2154 create_color(BLACK);
2155 create_color(WHITE);
2157 create_color(LTGREY);
2158 create_color(MEGREY);
2159 create_color(MDGREY);
2160 create_color(DKGREY);
2162 create_color(LTCYAN);
2163 create_color(MECYAN);
2164 create_color(MDCYAN);
2165 create_color(DKCYAN);
2167 create_color(LTGREEN);
2168 create_color(GREEN);
2169 create_color(DKGREEN);
2171 create_color(LTPINK);
2175 create_color(LTBLUE);
2177 create_color(DKBLUE);
2179 create_color(LTYELLOW);
2180 create_color(MEYELLOW);
2181 create_color(MDYELLOW);
2182 create_color(DKYELLOW);
2184 create_color(LTPURPLE);
2185 create_color(MEPURPLE);
2186 create_color(MDPURPLE);
2187 create_color(DKPURPLE);
2189 create_color(FGGREY);
2190 create_color(MNBLUE);
2191 create_color(ORANGE);
2192 create_color(FTGREY);
2197 Cursor BC_WindowBase::create_grab_cursor()
2199 int iw = 23, iw1 = iw-1, iw2 = iw/2;
2200 int ih = 23, ih1 = ih-1, ih2 = ih/2;
2201 VFrame grab(iw,ih,BC_RGB888);
2203 grab.set_pixel_color(RED); // fg
2204 grab.draw_smooth(iw2,0, iw1,0, iw1,ih2);
2205 grab.draw_smooth(iw1,ih2, iw1,ih1, iw2,ih1);
2206 grab.draw_smooth(iw2,ih1, 0,ih1, 0,ih2);
2207 grab.draw_smooth(0,ih2, 0,0, iw2,0);
2208 grab.set_pixel_color(WHITE); // bg
2209 grab.draw_line(0,ih2, iw2-2,ih2);
2210 grab.draw_line(iw2+2,ih2, iw1,ih2);
2211 grab.draw_line(iw2,0, iw2,ih2-2);
2212 grab.draw_line(iw2,ih2+2, iw2,ih1);
2214 int bpl = (iw+7)/8, isz = bpl * ih;
2215 char img[isz]; memset(img, 0, isz);
2216 char msk[isz]; memset(msk, 0, isz);
2217 unsigned char **rows = grab.get_rows();
2218 for( int iy=0; iy<ih; ++iy ) {
2219 char *op = img + iy*bpl;
2220 char *mp = msk + iy*bpl;
2221 unsigned char *ip = rows[iy];
2222 for( int ix=0; ix<iw; ++ix,ip+=3 ) {
2223 if( ip[0] ) mp[ix>>3] |= (1<<(ix&7));
2224 if( !ip[1] ) op[ix>>3] |= (1<<(ix&7));
2227 unsigned long white_pix = WhitePixel(display, screen);
2228 unsigned long black_pix = BlackPixel(display, screen);
2229 Pixmap img_xpm = XCreatePixmapFromBitmapData(display, rootwin,
2230 img, iw,ih, white_pix,black_pix, 1);
2231 Pixmap msk_xpm = XCreatePixmapFromBitmapData(display, rootwin,
2232 msk, iw,ih, white_pix,black_pix, 1);
2235 fc.flags = bc.flags = DoRed | DoGreen | DoBlue;
2236 fc.red = 0xffff; fc.green = fc.blue = 0; // fg
2237 bc.red = 0xffff; bc.green = 0xffff; bc.blue = 0x0000; // bg
2238 Cursor cursor = XCreatePixmapCursor(display, img_xpm,msk_xpm, &fc,&bc, iw2,ih2);
2239 XFreePixmap(display, img_xpm);
2240 XFreePixmap(display, msk_xpm);
2244 int BC_WindowBase::allocate_color_table()
2246 int red, green, blue, color;
2249 for(int i = 0; i < total_colors; i++)
2251 color = color_table[i][0];
2252 red = (color & 0xFF0000) >> 16;
2253 green = (color & 0x00FF00) >> 8;
2254 blue = color & 0xFF;
2256 col.flags = DoRed | DoGreen | DoBlue;
2257 col.red = red<<8 | red;
2258 col.green = green<<8 | green;
2259 col.blue = blue<<8 | blue;
2261 XAllocColor(display, cmap, &col);
2262 color_table[i][1] = col.pixel;
2265 XInstallColormap(display, cmap);
2269 int BC_WindowBase::init_window_shape()
2271 if(bg_pixmap && bg_pixmap->use_alpha())
2273 XShapeCombineMask(top_level->display,
2274 this->win, ShapeBounding, 0, 0,
2275 bg_pixmap->get_alpha(), ShapeSet);
2281 int BC_WindowBase::init_gc()
2283 unsigned long gcmask;
2284 gcmask = GCFont | GCGraphicsExposures;
2287 gcvalues.font = mediumfont->fid; // set the font
2288 gcvalues.graphics_exposures = 0; // prevent expose events for every redraw
2289 gc = XCreateGC(display, rootwin, gcmask, &gcvalues);
2291 // gcmask = GCCapStyle | GCJoinStyle;
2292 // XGetGCValues(display, gc, gcmask, &gcvalues);
2293 // printf("BC_WindowBase::init_gc %d %d %d\n", __LINE__, gcvalues.cap_style, gcvalues.join_style);
2297 int BC_WindowBase::init_fonts()
2299 if( !(smallfont = XLoadQueryFont(display, _(resources.small_font))) )
2300 if( !(smallfont = XLoadQueryFont(display, _(resources.small_font2))) )
2301 smallfont = XLoadQueryFont(display, "fixed");
2302 if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font))) )
2303 if( !(mediumfont = XLoadQueryFont(display, _(resources.medium_font2))) )
2304 mediumfont = XLoadQueryFont(display, "fixed");
2305 if( !(largefont = XLoadQueryFont(display, _(resources.large_font))) )
2306 if( !(largefont = XLoadQueryFont(display, _(resources.large_font2))) )
2307 largefont = XLoadQueryFont(display, "fixed");
2308 if( !(bigfont = XLoadQueryFont(display, _(resources.big_font))) )
2309 if( !(bigfont = XLoadQueryFont(display, _(resources.big_font2))) )
2310 bigfont = XLoadQueryFont(display, "fixed");
2312 if((clockfont = XLoadQueryFont(display, _(resources.clock_font))) == NULL)
2313 if((clockfont = XLoadQueryFont(display, _(resources.clock_font2))) == NULL)
2314 clockfont = XLoadQueryFont(display, "fixed");
2317 if(get_resources()->use_fontset)
2322 // FIXME: should check the m,d,n values
2323 smallfontset = XCreateFontSet(display, resources.small_fontset, &m, &n, &d);
2325 smallfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2326 mediumfontset = XCreateFontSet(display, resources.medium_fontset, &m, &n, &d);
2327 if( !mediumfontset )
2328 mediumfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2329 largefontset = XCreateFontSet(display, resources.large_fontset, &m, &n, &d);
2331 largefontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2332 bigfontset = XCreateFontSet(display, resources.big_fontset, &m, &n, &d);
2334 bigfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2335 clockfontset = XCreateFontSet(display, resources.clock_fontset, &m, &n, &d);
2337 clockfontset = XCreateFontSet(display, "fixed,*", &m, &n, &d);
2338 if(clockfontset && bigfontset && largefontset && mediumfontset && smallfontset) {
2339 curr_fontset = mediumfontset;
2340 get_resources()->use_fontset = 1;
2344 get_resources()->use_fontset = 0;
2351 void BC_WindowBase::init_xft()
2354 if( !get_resources()->use_xft ) return;
2355 // apparently, xft is not reentrant, more than this is needed
2356 static Mutex xft_init_lock("BC_WindowBase::xft_init_lock", 0);
2357 xft_init_lock.lock("BC_WindowBase::init_xft");
2358 if(!(smallfont_xft =
2359 (resources.small_font_xft[0] == '-' ?
2360 xftFontOpenXlfd(display, screen, resources.small_font_xft) :
2361 xftFontOpenName(display, screen, resources.small_font_xft))) )
2362 if(!(smallfont_xft =
2363 xftFontOpenXlfd(display, screen, resources.small_font_xft2)))
2364 smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2365 if(!(mediumfont_xft =
2366 (resources.medium_font_xft[0] == '-' ?
2367 xftFontOpenXlfd(display, screen, resources.medium_font_xft) :
2368 xftFontOpenName(display, screen, resources.medium_font_xft))) )
2369 if(!(mediumfont_xft =
2370 xftFontOpenXlfd(display, screen, resources.medium_font_xft2)))
2371 mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2372 if(!(largefont_xft =
2373 (resources.large_font_xft[0] == '-' ?
2374 xftFontOpenXlfd(display, screen, resources.large_font_xft) :
2375 xftFontOpenName(display, screen, resources.large_font_xft))) )
2376 if(!(largefont_xft =
2377 xftFontOpenXlfd(display, screen, resources.large_font_xft2)))
2378 largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
2380 (resources.big_font_xft[0] == '-' ?
2381 xftFontOpenXlfd(display, screen, resources.big_font_xft) :
2382 xftFontOpenName(display, screen, resources.big_font_xft))) )
2384 xftFontOpenXlfd(display, screen, resources.big_font_xft2)))
2385 bigfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2386 if(!(clockfont_xft =
2387 (resources.clock_font_xft[0] == '-' ?
2388 xftFontOpenXlfd(display, screen, resources.clock_font_xft) :
2389 xftFontOpenName(display, screen, resources.clock_font_xft))) )
2390 clockfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2393 if(!(bold_smallfont_xft =
2394 (resources.small_b_font_xft[0] == '-' ?
2395 xftFontOpenXlfd(display, screen, resources.small_b_font_xft) :
2396 xftFontOpenName(display, screen, resources.small_b_font_xft))) )
2397 bold_smallfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2398 if(!(bold_mediumfont_xft =
2399 (resources.medium_b_font_xft[0] == '-' ?
2400 xftFontOpenXlfd(display, screen, resources.medium_b_font_xft) :
2401 xftFontOpenName(display, screen, resources.medium_b_font_xft))) )
2402 bold_mediumfont_xft = xftFontOpenXlfd(display, screen, "fixed");
2403 if(!(bold_largefont_xft =
2404 (resources.large_b_font_xft[0] == '-' ?
2405 xftFontOpenXlfd(display, screen, resources.large_b_font_xft) :
2406 xftFontOpenName(display, screen, resources.large_b_font_xft))) )
2407 bold_largefont_xft = xftFontOpenXlfd(display, screen, "fixed");
2409 if( !smallfont_xft || !mediumfont_xft || !largefont_xft || !bigfont_xft ||
2410 !bold_largefont_xft || !bold_mediumfont_xft || !bold_largefont_xft ||
2412 printf("BC_WindowBase::init_fonts: no xft fonts found:"
2413 " %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n %s=%p\n",
2414 resources.small_font_xft, smallfont_xft,
2415 resources.medium_font_xft, mediumfont_xft,
2416 resources.large_font_xft, largefont_xft,
2417 resources.big_font_xft, bigfont_xft,
2418 resources.clock_font_xft, clockfont_xft,
2419 resources.small_b_font_xft, bold_smallfont_xft,
2420 resources.medium_b_font_xft, bold_mediumfont_xft,
2421 resources.large_b_font_xft, bold_largefont_xft);
2422 get_resources()->use_xft = 0;
2425 // _XftDisplayInfo needs a lock.
2426 xftDefaultHasRender(display);
2427 xft_init_lock.unlock();
2431 void BC_WindowBase::init_im()
2433 XIMStyles *xim_styles;
2436 if(!(input_method = XOpenIM(display, NULL, NULL, NULL)))
2438 printf("BC_WindowBase::init_im: Could not open input method.\n");
2441 if(XGetIMValues(input_method, XNQueryInputStyle, &xim_styles, NULL) ||
2444 printf("BC_WindowBase::init_im: Input method doesn't support any styles.\n");
2445 XCloseIM(input_method);
2450 for(int z = 0; z < xim_styles->count_styles; z++)
2452 if(xim_styles->supported_styles[z] == (XIMPreeditNothing | XIMStatusNothing))
2454 xim_style = xim_styles->supported_styles[z];
2462 printf("BC_WindowBase::init_im: Input method doesn't support the style we need.\n");
2463 XCloseIM(input_method);
2467 input_context = XCreateIC(input_method, XNInputStyle, xim_style,
2468 XNClientWindow, win, XNFocusWindow, win, NULL);
2471 printf("BC_WindowBase::init_im: Failed to create input context.\n");
2472 XCloseIM(input_method);
2477 void BC_WindowBase::finit_im()
2479 if( input_context ) {
2480 XDestroyIC(input_context);
2483 if( input_method ) {
2484 XCloseIM(input_method);
2490 int BC_WindowBase::get_color(int64_t color)
2492 // return pixel of color
2493 // use this only for drawing subwindows not for bitmaps
2494 int i, test, difference;
2500 return get_color_rgb8(color);
2501 // test last color looked up
2502 if(current_color_value == color)
2503 return current_color_pixel;
2506 current_color_value = color;
2507 for(i = 0; i < total_colors; i++)
2509 if(color_table[i][0] == color)
2511 current_color_pixel = color_table[i][1];
2512 return current_color_pixel;
2516 // find nearest match
2517 difference = 0xFFFFFF;
2519 for(i = 0; i < total_colors; i++)
2521 test = abs((int)(color_table[i][0] - color));
2523 if(test < difference)
2525 current_color_pixel = color_table[i][1];
2529 return current_color_pixel;
2532 return get_color_rgb16(color);
2535 return get_color_bgr16(color);
2539 return client_byte_order == server_byte_order ?
2540 color : get_color_bgr24(color);
2548 int BC_WindowBase::get_color_rgb8(int color)
2552 pixel = (color & 0xc00000) >> 16;
2553 pixel += (color & 0xe000) >> 10;
2554 pixel += (color & 0xe0) >> 5;
2558 int64_t BC_WindowBase::get_color_rgb16(int color)
2561 result = (color & 0xf80000) >> 8;
2562 result += (color & 0xfc00) >> 5;
2563 result += (color & 0xf8) >> 3;
2568 int64_t BC_WindowBase::get_color_bgr16(int color)
2571 result = (color & 0xf80000) >> 19;
2572 result += (color & 0xfc00) >> 5;
2573 result += (color & 0xf8) << 8;
2578 int64_t BC_WindowBase::get_color_bgr24(int color)
2581 result = (color & 0xff) << 16;
2582 result += (color & 0xff00);
2583 result += (color & 0xff0000) >> 16;
2587 void BC_WindowBase::start_video()
2589 cursor_timer->update();
2591 // set_color(BLACK);
2592 // draw_box(0, 0, get_w(), get_h());
2596 void BC_WindowBase::stop_video()
2604 int64_t BC_WindowBase::get_color()
2606 return top_level->current_color;
2609 void BC_WindowBase::set_color(int64_t color)
2611 top_level->current_color = color;
2612 XSetForeground(top_level->display,
2614 top_level->get_color(color));
2617 void BC_WindowBase::set_opaque()
2619 XSetFunction(top_level->display, top_level->gc, GXcopy);
2622 void BC_WindowBase::set_inverse()
2624 XSetFunction(top_level->display, top_level->gc, GXxor);
2627 void BC_WindowBase::set_line_width(int value)
2629 this->line_width = value;
2630 XSetLineAttributes(top_level->display, top_level->gc, value, /* line_width */
2631 line_dashes == 0 ? LineSolid : LineOnOffDash, /* line_style */
2632 line_dashes == 0 ? CapRound : CapNotLast, /* cap_style */
2633 JoinMiter); /* join_style */
2635 if(line_dashes > 0) {
2636 const char dashes = line_dashes;
2637 XSetDashes(top_level->display, top_level->gc, 0, &dashes, 1);
2640 // XGCValues gcvalues;
2641 // unsigned long gcmask;
2642 // gcmask = GCCapStyle | GCJoinStyle;
2643 // XGetGCValues(top_level->display, top_level->gc, gcmask, &gcvalues);
2644 // printf("BC_WindowBase::set_line_width %d %d %d\n", __LINE__, gcvalues.cap_style, gcvalues.join_style);
2647 void BC_WindowBase::set_line_dashes(int value)
2649 line_dashes = value;
2650 // call XSetLineAttributes
2651 set_line_width(line_width);
2655 Cursor BC_WindowBase::get_cursor_struct(int cursor)
2659 case ARROW_CURSOR: return top_level->arrow_cursor;
2660 case CROSS_CURSOR: return top_level->cross_cursor;
2661 case IBEAM_CURSOR: return top_level->ibeam_cursor;
2662 case VSEPARATE_CURSOR: return top_level->vseparate_cursor;
2663 case HSEPARATE_CURSOR: return top_level->hseparate_cursor;
2664 case MOVE_CURSOR: return top_level->move_cursor;
2665 case LEFT_CURSOR: return top_level->left_cursor;
2666 case RIGHT_CURSOR: return top_level->right_cursor;
2667 case UPRIGHT_ARROW_CURSOR: return top_level->upright_arrow_cursor;
2668 case UPLEFT_RESIZE: return top_level->upleft_resize_cursor;
2669 case UPRIGHT_RESIZE: return top_level->upright_resize_cursor;
2670 case DOWNLEFT_RESIZE: return top_level->downleft_resize_cursor;
2671 case DOWNRIGHT_RESIZE: return top_level->downright_resize_cursor;
2672 case HOURGLASS_CURSOR: return top_level->hourglass_cursor;
2673 case TRANSPARENT_CURSOR: return top_level->transparent_cursor;
2674 case GRABBED_CURSOR: return top_level->grabbed_cursor;
2679 void BC_WindowBase::set_cursor(int cursor, int override, int flush)
2681 // inherit cursor from parent
2684 XUndefineCursor(top_level->display, win);
2685 current_cursor = cursor;
2688 // don't change cursor if overridden
2689 if((!top_level->is_hourglass && !is_transparent) ||
2692 XDefineCursor(top_level->display, win, get_cursor_struct(cursor));
2693 if(flush) this->flush();
2696 if(!override) current_cursor = cursor;
2699 void BC_WindowBase::set_x_cursor(int cursor)
2701 temp_cursor = XCreateFontCursor(top_level->display, cursor);
2702 XDefineCursor(top_level->display, win, temp_cursor);
2703 current_cursor = cursor;
2707 int BC_WindowBase::get_cursor()
2709 return current_cursor;
2712 void BC_WindowBase::start_hourglass()
2714 top_level->start_hourglass_recursive();
2718 void BC_WindowBase::stop_hourglass()
2720 top_level->stop_hourglass_recursive();
2724 void BC_WindowBase::start_hourglass_recursive()
2726 if(this == top_level)
2734 set_cursor(HOURGLASS_CURSOR, 1, 0);
2735 for(int i = 0; i < subwindows->total; i++)
2737 subwindows->values[i]->start_hourglass_recursive();
2742 void BC_WindowBase::stop_hourglass_recursive()
2744 if(this == top_level)
2746 if(hourglass_total == 0) return;
2747 top_level->hourglass_total--;
2750 if(!top_level->hourglass_total)
2752 top_level->is_hourglass = 0;
2754 // Cause set_cursor to perform change
2756 set_cursor(current_cursor, 1, 0);
2758 for(int i = 0; i < subwindows->total; i++)
2760 subwindows->values[i]->stop_hourglass_recursive();
2768 XFontStruct* BC_WindowBase::get_font_struct(int font)
2770 // Clear out unrelated flags
2771 if(font & BOLDFACE) font ^= BOLDFACE;
2774 case SMALLFONT: return top_level->smallfont; break;
2775 case MEDIUMFONT: return top_level->mediumfont; break;
2776 case LARGEFONT: return top_level->largefont; break;
2777 case BIGFONT: return top_level->bigfont; break;
2778 case CLOCKFONT: return top_level->clockfont; break;
2783 XFontSet BC_WindowBase::get_fontset(int font)
2787 if(get_resources()->use_fontset)
2789 switch(font & 0xff) {
2790 case SMALLFONT: fs = top_level->smallfontset; break;
2791 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2792 case LARGEFONT: fs = top_level->largefontset; break;
2793 case BIGFONT: fs = top_level->bigfontset; break;
2794 case CLOCKFONT: fs = top_level->clockfontset; break;
2802 XftFont* BC_WindowBase::get_xft_struct(int font)
2805 case SMALLFONT: return (XftFont*)top_level->smallfont_xft;
2806 case MEDIUMFONT: return (XftFont*)top_level->mediumfont_xft;
2807 case LARGEFONT: return (XftFont*)top_level->largefont_xft;
2808 case BIGFONT: return (XftFont*)top_level->bigfont_xft;
2809 case CLOCKFONT: return (XftFont*)top_level->clockfont_xft;
2810 case MEDIUMFONT_3D: return (XftFont*)top_level->bold_mediumfont_xft;
2811 case SMALLFONT_3D: return (XftFont*)top_level->bold_smallfont_xft;
2812 case LARGEFONT_3D: return (XftFont*)top_level->bold_largefont_xft;
2820 int BC_WindowBase::get_current_font()
2822 return top_level->current_font;
2825 void BC_WindowBase::set_font(int font)
2827 top_level->current_font = font;
2830 if(get_resources()->use_xft) {}
2833 if(get_resources()->use_fontset) {
2837 if(get_font_struct(font))
2839 XSetFont(top_level->display, top_level->gc, get_font_struct(font)->fid);
2845 void BC_WindowBase::set_fontset(int font)
2849 if(get_resources()->use_fontset) {
2851 case SMALLFONT: fs = top_level->smallfontset; break;
2852 case MEDIUMFONT: fs = top_level->mediumfontset; break;
2853 case LARGEFONT: fs = top_level->largefontset; break;
2854 case BIGFONT: fs = top_level->bigfontset; break;
2855 case CLOCKFONT: fs = top_level->clockfontset; break;
2863 XFontSet BC_WindowBase::get_curr_fontset(void)
2865 if(get_resources()->use_fontset)
2866 return curr_fontset;
2870 int BC_WindowBase::get_single_text_width(int font, const char *text, int length)
2873 if(get_resources()->use_xft && get_xft_struct(font))
2876 #ifdef X_HAVE_UTF8_STRING
2877 if(get_resources()->locale_utf8)
2879 xftTextExtentsUtf8(top_level->display,
2880 get_xft_struct(font),
2881 (const XftChar8 *)text,
2888 xftTextExtents8(top_level->display,
2889 get_xft_struct(font),
2890 (const XftChar8 *)text,
2894 return extents.xOff;
2898 if(get_resources()->use_fontset && top_level->get_fontset(font))
2899 return XmbTextEscapement(top_level->get_fontset(font), text, length);
2901 if(get_font_struct(font))
2902 return XTextWidth(get_font_struct(font), text, length);
2908 case MEDIUM_7SEGMENT:
2909 return get_resources()->medium_7segment[0]->get_w() * length;
2919 int BC_WindowBase::get_text_width(int font, const char *text, int length)
2921 int i, j, w = 0, line_w = 0;
2922 if(length < 0) length = strlen(text);
2924 for(i = 0, j = 0; i <= length; i++)
2929 line_w = get_single_text_width(font, &text[j], i - j);
2935 line_w = get_single_text_width(font, &text[j], length - j);
2937 if(line_w > w) w = line_w;
2940 if(i > length && w == 0)
2942 w = get_single_text_width(font, text, length);
2948 int BC_WindowBase::get_text_width(int font, const wchar_t *text, int length)
2951 if( length < 0 ) length = wcslen(text);
2953 for( i=j=0; i<length && text[i]; ++i ) {
2954 if( text[i] != '\n' ) continue;
2956 int lw = get_single_text_width(font, &text[j], i-j);
2957 if( w < lw ) w = lw;
2962 int lw = get_single_text_width(font, &text[j], length-j);
2963 if( w < lw ) w = lw;
2969 int BC_WindowBase::get_text_ascent(int font)
2973 if( (fstruct = get_xft_struct(font)) != 0 )
2974 return fstruct->ascent;
2976 if(get_resources()->use_fontset && top_level->get_fontset(font))
2978 XFontSetExtents *extents;
2980 extents = XExtentsOfFontSet(top_level->get_fontset(font));
2981 return -extents->max_logical_extent.y;
2984 if(get_font_struct(font))
2985 return top_level->get_font_struct(font)->ascent;
2988 case MEDIUM_7SEGMENT:
2989 return get_resources()->medium_7segment[0]->get_h();
2994 int BC_WindowBase::get_text_descent(int font)
2998 if( (fstruct = get_xft_struct(font)) != 0 )
2999 return fstruct->descent;
3001 if(get_resources()->use_fontset && top_level->get_fontset(font)) {
3002 XFontSetExtents *extents;
3003 extents = XExtentsOfFontSet(top_level->get_fontset(font));
3004 return (extents->max_logical_extent.height
3005 + extents->max_logical_extent.y);
3008 if(get_font_struct(font))
3009 return top_level->get_font_struct(font)->descent;
3014 int BC_WindowBase::get_text_height(int font, const char *text)
3019 if( (fstruct = get_xft_struct(font)) != 0 )
3020 rowh = fstruct->height;
3023 rowh = get_text_ascent(font) + get_text_descent(font);
3025 if(!text) return rowh;
3027 // Add height of lines
3028 int h = 0, i, length = strlen(text);
3029 for(i = 0; i <= length; i++)
3040 BC_Bitmap* BC_WindowBase::new_bitmap(int w, int h, int color_model)
3042 if(color_model < 0) color_model = top_level->get_color_model();
3043 return new BC_Bitmap(top_level, w, h, color_model);
3046 void BC_WindowBase::init_wait()
3048 #ifndef SINGLE_THREAD
3049 if(window_type != MAIN_WINDOW)
3050 top_level->init_wait();
3051 init_lock->lock("BC_WindowBase::init_wait");
3052 init_lock->unlock();
3056 int BC_WindowBase::accel_available(int color_model, int lock_it)
3058 if( window_type != MAIN_WINDOW )
3059 return top_level->accel_available(color_model, lock_it);
3061 lock_window("BC_WindowBase::accel_available");
3063 switch(color_model) {
3065 grab_port_id(color_model);
3069 grab_port_id(color_model);
3078 //printf("BC_WindowBase::accel_available %d %d\n", color_model, xvideo_port_id);
3079 return xvideo_port_id >= 0 ? 1 : 0;
3083 int BC_WindowBase::grab_port_id(int color_model)
3085 if( !get_resources()->use_xvideo || // disabled
3086 !get_resources()->use_shm ) // Only local server is fast enough.
3088 if( xvideo_port_id >= 0 )
3089 return xvideo_port_id;
3091 unsigned int ver, rev, reqBase, eventBase, errorBase;
3092 if( Success != XvQueryExtension(display, // XV extension is available
3093 &ver, &rev, &reqBase, &eventBase, &errorBase) )
3096 // XV adaptors are available
3097 unsigned int numAdapt = 0;
3098 XvAdaptorInfo *info = 0;
3099 XvQueryAdaptors(display, DefaultRootWindow(display), &numAdapt, &info);
3103 // Translate from color_model to X color model
3104 int x_color_model = BC_CModels::bc_to_x(color_model);
3106 // Get adaptor with desired color model
3107 for( int i = 0; i < (int)numAdapt && xvideo_port_id == -1; i++) {
3108 if( !(info[i].type & XvImageMask) || !info[i].num_ports ) continue;
3109 // adaptor supports XvImages
3110 int numFormats = 0, numPorts = info[i].num_ports;
3111 XvImageFormatValues *formats =
3112 XvListImageFormats(display, info[i].base_id, &numFormats);
3113 if( !formats ) continue;
3115 for( int j=0; j<numFormats && xvideo_port_id<0; ++j ) {
3116 if( formats[j].id != x_color_model ) continue;
3117 // this adaptor supports the desired format, grab a port
3118 for( int k=0; k<numPorts; ++k ) {
3119 if( Success == XvGrabPort(top_level->display,
3120 info[i].base_id+k, CurrentTime) ) {
3121 //printf("BC_WindowBase::grab_port_id %llx\n", info[i].base_id);
3122 xvideo_port_id = info[i].base_id + k;
3130 XvFreeAdaptorInfo(info);
3132 return xvideo_port_id;
3136 int BC_WindowBase::show_window(int flush)
3138 for(int i = 0; i < subwindows->size(); i++)
3140 subwindows->get(i)->show_window(0);
3143 XMapWindow(top_level->display, win);
3144 if(flush) XFlush(top_level->display);
3145 // XSync(top_level->display, 0);
3150 int BC_WindowBase::hide_window(int flush)
3152 for(int i = 0; i < subwindows->size(); i++)
3154 subwindows->get(i)->hide_window(0);
3157 XUnmapWindow(top_level->display, win);
3158 if(flush) this->flush();
3163 BC_MenuBar* BC_WindowBase::add_menubar(BC_MenuBar *menu_bar)
3165 subwindows->append((BC_SubWindow*)menu_bar);
3167 menu_bar->parent_window = this;
3168 menu_bar->top_level = this->top_level;
3169 menu_bar->initialize();
3173 BC_WindowBase* BC_WindowBase::add_popup(BC_WindowBase *window)
3175 //printf("BC_WindowBase::add_popup window=%p win=%p\n", window, window->win);
3176 if(this != top_level) return top_level->add_popup(window);
3177 popups.append(window);
3181 void BC_WindowBase::remove_popup(BC_WindowBase *window)
3183 //printf("BC_WindowBase::remove_popup %d size=%d window=%p win=%p\n", __LINE__, popups.size(), window, window->win);
3184 if(this != top_level)
3185 top_level->remove_popup(window);
3187 popups.remove(window);
3188 //printf("BC_WindowBase::remove_popup %d size=%d window=%p win=%p\n", __LINE__, popups.size(), window, window->win);
3192 BC_WindowBase* BC_WindowBase::add_subwindow(BC_WindowBase *subwindow)
3194 subwindows->append(subwindow);
3196 if(subwindow->bg_color == -1) subwindow->bg_color = this->bg_color;
3198 // parent window must be set before the subwindow initialization
3199 subwindow->parent_window = this;
3200 subwindow->top_level = this->top_level;
3202 // Execute derived initialization
3203 subwindow->initialize();
3208 BC_WindowBase* BC_WindowBase::add_tool(BC_WindowBase *subwindow)
3210 return add_subwindow(subwindow);
3213 int BC_WindowBase::flash(int x, int y, int w, int h, int flush)
3215 if( !top_level->flash_enabled ) return 0;
3216 //printf("BC_WindowBase::flash %d %d %d %d %d\n", __LINE__, w, h, this->w, this->h);
3218 XSetWindowBackgroundPixmap(top_level->display, win, pixmap->opaque_pixmap);
3221 XClearArea(top_level->display, win, x, y, w, h, 0);
3225 XClearWindow(top_level->display, win);
3233 int BC_WindowBase::flash(int flush)
3235 flash(-1, -1, -1, -1, flush);
3239 void BC_WindowBase::flush()
3241 //if(!get_window_lock())
3242 // printf("BC_WindowBase::flush %s not locked\n", top_level->title);
3243 // X gets hosed if Flush/Sync are not user locked (at libX11-1.1.5 / libxcb-1.1.91)
3244 // _XReply deadlocks in condition_wait waiting for xlib lock when waiters!=-1
3245 int locked = get_window_lock();
3246 if( !locked ) lock_window("BC_WindowBase::flush");
3247 XFlush(top_level->display);
3248 if( !locked ) unlock_window();
3251 void BC_WindowBase::sync_display()
3253 int locked = get_window_lock();
3254 if( !locked ) lock_window("BC_WindowBase::sync_display");
3255 XSync(top_level->display, False);
3256 if( !locked ) unlock_window();
3259 int BC_WindowBase::get_window_lock()
3261 #ifdef SINGLE_THREAD
3262 return BC_Display::display_global->get_display_locked();
3264 return top_level->window_lock;
3268 int BC_WindowBase::lock_window(const char *location)
3270 if(top_level && top_level != this)
3272 top_level->lock_window(location);
3277 SET_LOCK(this, title, location);
3278 #ifdef SINGLE_THREAD
3279 BC_Display::lock_display(location);
3281 XLockDisplay(top_level->display);
3282 top_level->display_lock_owner = pthread_self();
3285 ++top_level->window_lock;
3289 printf("BC_WindowBase::lock_window top_level NULL\n");
3294 int BC_WindowBase::unlock_window()
3296 if(top_level && top_level != this)
3298 top_level->unlock_window();
3304 if( !top_level->window_lock ) {
3305 printf("BC_WindowBase::unlock_window %s not locked\n", title);
3308 if( top_level->window_lock > 0 )
3309 if( --top_level->window_lock == 0 )
3310 top_level->display_lock_owner = 0;
3311 #ifdef SINGLE_THREAD
3312 BC_Display::unlock_display();
3314 XUnlockDisplay(top_level->display);
3319 printf("BC_WindowBase::unlock_window top_level NULL\n");
3324 int BC_WindowBase::break_lock()
3326 if( !top_level ) return 0;
3327 if( top_level != this ) return top_level->break_lock();
3328 if( top_level->display_lock_owner != pthread_self() ) return 0;
3329 if( top_level->window_lock != 1 ) return 0;
3332 display_lock_owner = 0;
3333 #ifdef SINGLE_THREAD
3334 BC_Display::unlock_display();
3336 XUnlockDisplay(display);
3341 void BC_WindowBase::set_done(int return_value)
3343 if(done_set) return;
3345 if(window_type != MAIN_WINDOW)
3346 top_level->set_done(return_value);
3349 #ifdef SINGLE_THREAD
3350 this->return_value = return_value;
3351 BC_Display::display_global->arm_completion(this);
3352 completion_lock->unlock();
3353 #else // SINGLE_THREAD
3355 if( !event_thread ) return;
3356 XEvent *event = new_xevent();
3357 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
3358 event->type = ClientMessage;
3359 ptr->message_type = SetDoneXAtom;
3361 this->return_value = return_value;
3362 // May lock up here because XSendEvent doesn't work too well
3363 // asynchronous with XNextEvent.
3364 // This causes BC_WindowEvents to forward a copy of the event to run_window where
3366 // Deletion of event_thread is done at the end of BC_WindowBase::run_window() - by calling the destructor
3372 void BC_WindowBase::close(int return_value)
3374 hide_window(); flush();
3375 set_done(return_value);
3378 int BC_WindowBase::grab(BC_WindowBase *window)
3380 if( window->active_grab && this != window->active_grab ) return 0;
3381 window->active_grab = this;
3382 this->grab_active = window;
3385 int BC_WindowBase::ungrab(BC_WindowBase *window)
3387 if( window->active_grab && this != window->active_grab ) return 0;
3388 window->active_grab = 0;
3389 this->grab_active = 0;
3392 int BC_WindowBase::grab_event_count()
3395 #ifndef SINGLE_THREAD
3396 result = grab_active->get_event_count();
3400 int BC_WindowBase::grab_buttons()
3402 XSync(top_level->display, False);
3403 if( XGrabButton(top_level->display, AnyButton, AnyModifier,
3404 top_level->rootwin, True, ButtonPressMask | ButtonReleaseMask,
3405 GrabModeAsync, GrabModeSync, None, None) == GrabSuccess ) {
3406 set_active_subwindow(this);
3411 void BC_WindowBase::ungrab_buttons()
3413 XUngrabButton(top_level->display, AnyButton, AnyModifier, top_level->rootwin);
3414 set_active_subwindow(0);
3417 void BC_WindowBase::grab_cursor()
3419 Cursor cursor_grab = get_cursor_struct(GRABBED_CURSOR);
3420 XGrabPointer(top_level->display, top_level->rootwin, True,
3421 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
3422 GrabModeAsync, GrabModeAsync, None, cursor_grab, CurrentTime);
3424 void BC_WindowBase::ungrab_cursor()
3426 XUngrabPointer(top_level->display, CurrentTime);
3430 // WidthOfScreen/HeightOfScreen of XDefaultScreenOfDisplay
3431 // this is the bounding box of all the screens
3433 int BC_WindowBase::get_root_w(int lock_display)
3435 if(lock_display) lock_window("BC_WindowBase::get_root_w");
3436 Screen *def_screen = XDefaultScreenOfDisplay(top_level->display);
3437 int result = WidthOfScreen(def_screen);
3438 if(lock_display) unlock_window();
3442 int BC_WindowBase::get_root_h(int lock_display)
3444 if(lock_display) lock_window("BC_WindowBase::get_root_h");
3445 Screen *def_screen = XDefaultScreenOfDisplay(top_level->display);
3446 int result = HeightOfScreen(def_screen);
3447 if(lock_display) unlock_window();
3451 XineramaScreenInfo *
3452 BC_WindowBase::get_xinerama_info(int screen)
3454 if( !xinerama_info || !xinerama_screens ) return 0;
3456 for( int i=0; i<xinerama_screens; ++i )
3457 if( xinerama_info[i].screen_number == screen )
3458 return &xinerama_info[i];
3461 int top_x = get_x(), top_y = get_y();
3462 if( BC_DisplayInfo::left_border >= 0 ) top_x += BC_DisplayInfo::left_border;
3463 if( BC_DisplayInfo::top_border >= 0 ) top_y += BC_DisplayInfo::top_border;
3464 for( int i=0; i<xinerama_screens; ++i ) {
3465 int scr_y = top_y - xinerama_info[i].y_org;
3466 if( scr_y < 0 || scr_y >= xinerama_info[i].height ) continue;
3467 int scr_x = top_x - xinerama_info[i].x_org;
3468 if( scr_x >= 0 && scr_x < xinerama_info[i].width )
3469 return &xinerama_info[i];
3474 void BC_WindowBase::get_fullscreen_geometry(int &wx, int &wy, int &ww, int &wh)
3476 XineramaScreenInfo *info = top_level->get_xinerama_info(-1);
3478 wx = info->x_org; wy = info->y_org;
3479 ww = info->width; wh = info->height;
3482 wx = get_screen_x(0, -1);
3483 wy = get_screen_y(0, -1);
3484 int scr_w0 = get_screen_w(0, 0);
3485 int root_w = get_root_w(0);
3486 int root_h = get_root_h(0);
3487 if( root_w > scr_w0 ) { // multi-headed
3488 if( wx >= scr_w0 ) {
3489 // assumes right side is the big one
3490 ww = root_w - scr_w0;
3494 // use same aspect ratio to compute left height
3496 wh = (w*root_h) / (root_w-scr_w0);
3506 int BC_WindowBase::get_screen_x(int lock_display, int screen)
3509 if(lock_display) lock_window("BC_WindowBase::get_screen_x");
3510 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3513 int root_w = get_root_w(0);
3514 int root_h = get_root_h(0);
3515 // Shift X based on position of current window if dual head
3516 if( (float)root_w/root_h > 1.8 ) {
3517 root_w = get_screen_w(0, 0);
3518 if( top_level->get_x() >= root_w )
3523 result = info->x_org;
3524 if(lock_display) unlock_window();
3528 int BC_WindowBase::get_screen_y(int lock_display, int screen)
3530 if(lock_display) lock_window("BC_WindowBase::get_screen_y");
3531 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3532 int result = !info ? 0 : info->y_org;
3533 if(lock_display) unlock_window();
3537 int BC_WindowBase::get_screen_w(int lock_display, int screen)
3540 if(lock_display) lock_window("BC_WindowBase::get_screen_w");
3541 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3543 int width = get_root_w(0);
3544 int height = get_root_h(0);
3545 if( (float)width/height > 1.8 ) {
3546 // If dual head, the screen width is > 16x9
3547 // but we only want to fill one screen
3548 // this code assumes the "big" screen is on the right
3549 int scr_w0 = width / 2;
3551 case 600: scr_w0 = 800; break;
3552 case 720: scr_w0 = 1280; break;
3553 case 1024: scr_w0 = 1280; break;
3554 case 1200: scr_w0 = 1600; break;
3555 case 1080: scr_w0 = 1920; break;
3557 int scr_w1 = width - scr_w0;
3558 result = screen > 0 ? scr_w1 :
3559 screen == 0 ? scr_w0 :
3560 top_level->get_x() < scr_w0 ? scr_w0 : scr_w1;
3566 result = info->width;
3567 if(lock_display) unlock_window();
3571 int BC_WindowBase::get_screen_h(int lock_display, int screen)
3573 if(lock_display) lock_window("BC_WindowBase::get_screen_h");
3574 XineramaScreenInfo *info = top_level->get_xinerama_info(screen);
3575 int result = info ? info->height : get_root_h(0);
3576 if(lock_display) unlock_window();
3580 // Bottom right corner
3581 int BC_WindowBase::get_x2()
3586 int BC_WindowBase::get_y2()
3591 int BC_WindowBase::get_video_on()
3596 int BC_WindowBase::get_hidden()
3598 return top_level->hidden;
3601 int BC_WindowBase::cursor_inside()
3603 return (top_level->cursor_x >= 0 &&
3604 top_level->cursor_y >= 0 &&
3605 top_level->cursor_x < w &&
3606 top_level->cursor_y < h);
3609 BC_WindowBase* BC_WindowBase::get_top_level()
3614 BC_WindowBase* BC_WindowBase::get_parent()
3616 return parent_window;
3619 int BC_WindowBase::get_color_model()
3621 return top_level->color_model;
3624 BC_Resources* BC_WindowBase::get_resources()
3626 return &BC_WindowBase::resources;
3629 BC_Synchronous* BC_WindowBase::get_synchronous()
3631 return BC_WindowBase::resources.get_synchronous();
3634 int BC_WindowBase::get_bg_color()
3639 void BC_WindowBase::set_bg_color(int color)
3641 this->bg_color = color;
3644 BC_Pixmap* BC_WindowBase::get_bg_pixmap()
3649 void BC_WindowBase::set_active_subwindow(BC_WindowBase *subwindow)
3651 top_level->active_subwindow = subwindow;
3654 int BC_WindowBase::activate()
3659 int BC_WindowBase::deactivate()
3661 if(window_type == MAIN_WINDOW)
3663 if( top_level->active_menubar ) {
3664 top_level->active_menubar->deactivate();
3665 top_level->active_menubar = 0;
3667 if( top_level->active_popup_menu ) {
3668 top_level->active_popup_menu->deactivate();
3669 top_level->active_popup_menu = 0;
3671 if( top_level->active_subwindow ) {
3672 top_level->active_subwindow->deactivate();
3673 top_level->active_subwindow = 0;
3675 if( top_level->motion_events && top_level->last_motion_win == this->win )
3676 top_level->motion_events = 0;
3682 int BC_WindowBase::cycle_textboxes(int amount)
3685 BC_WindowBase *new_textbox = 0;
3689 BC_WindowBase *first_textbox = 0;
3690 find_next_textbox(&first_textbox, &new_textbox, result);
3691 if(!new_textbox) new_textbox = first_textbox;
3697 BC_WindowBase *last_textbox = 0;
3698 find_prev_textbox(&last_textbox, &new_textbox, result);
3699 if(!new_textbox) new_textbox = last_textbox;
3703 if(new_textbox != active_subwindow)
3706 new_textbox->activate();
3712 int BC_WindowBase::find_next_textbox(BC_WindowBase **first_textbox, BC_WindowBase **next_textbox, int &result)
3714 // Search subwindows for textbox
3715 for(int i = 0; i < subwindows->total && result < 2; i++)
3717 BC_WindowBase *test_subwindow = subwindows->values[i];
3718 test_subwindow->find_next_textbox(first_textbox, next_textbox, result);
3725 if(!*first_textbox) *first_textbox = this;
3729 if(top_level->active_subwindow == this)
3735 *next_textbox = this;
3742 int BC_WindowBase::find_prev_textbox(BC_WindowBase **last_textbox, BC_WindowBase **prev_textbox, int &result)
3748 if(!*last_textbox) *last_textbox = this;
3752 if(top_level->active_subwindow == this)
3758 *prev_textbox = this;
3763 // Search subwindows for textbox
3764 for(int i = subwindows->total - 1; i >= 0 && result < 2; i--)
3766 BC_WindowBase *test_subwindow = subwindows->values[i];
3767 test_subwindow->find_prev_textbox(last_textbox, prev_textbox, result);
3772 BC_Clipboard* BC_WindowBase::get_clipboard()
3774 #ifdef SINGLE_THREAD
3775 return BC_Display::display_global->clipboard;
3777 return top_level->clipboard;
3781 Atom BC_WindowBase::to_clipboard(const char *data, long len, int clipboard_num)
3783 return get_clipboard()->to_clipboard(this, data, len, clipboard_num);
3786 long BC_WindowBase::from_clipboard(char *data, long maxlen, int clipboard_num)
3788 return get_clipboard()->from_clipboard(data, maxlen, clipboard_num);
3791 long BC_WindowBase::clipboard_len(int clipboard_num)
3793 return get_clipboard()->clipboard_len(clipboard_num);
3796 int BC_WindowBase::do_selection_clear(Window win)
3798 top_level->event_win = win;
3799 return dispatch_selection_clear();
3802 int BC_WindowBase::dispatch_selection_clear()
3805 for( int i=0; i<subwindows->total && !result; ++i )
3806 result = subwindows->values[i]->dispatch_selection_clear();
3808 result = selection_clear_event();
3813 void BC_WindowBase::get_relative_cursor(int &x, int &y, int lock_window)
3815 int abs_x, abs_y, win_x, win_y;
3816 unsigned int temp_mask;
3819 if(lock_window) this->lock_window("BC_WindowBase::get_relative_cursor");
3820 XQueryPointer(top_level->display, top_level->win,
3821 &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
3824 XTranslateCoordinates(top_level->display, top_level->rootwin,
3825 win, abs_x, abs_y, &x, &y, &temp_win);
3826 if(lock_window) this->unlock_window();
3828 int BC_WindowBase::get_relative_cursor_x(int lock_window)
3831 get_relative_cursor(x, y, lock_window);
3834 int BC_WindowBase::get_relative_cursor_y(int lock_window)
3837 get_relative_cursor(x, y, lock_window);
3841 void BC_WindowBase::get_abs_cursor(int &abs_x, int &abs_y, int lock_window)
3844 unsigned int temp_mask;
3847 if(lock_window) this->lock_window("BC_WindowBase::get_abs_cursor");
3848 XQueryPointer(top_level->display, top_level->win,
3849 &temp_win, &temp_win, &abs_x, &abs_y, &win_x, &win_y,
3851 if(lock_window) this->unlock_window();
3853 int BC_WindowBase::get_abs_cursor_x(int lock_window)
3856 get_abs_cursor(abs_x, abs_y, lock_window);
3859 int BC_WindowBase::get_abs_cursor_y(int lock_window)
3862 get_abs_cursor(abs_x, abs_y, lock_window);
3866 void BC_WindowBase::get_pop_cursor(int &px, int &py, int lock_window)
3869 get_abs_cursor(px, py, lock_window);
3870 if( px < margin ) px = margin;
3871 if( py < margin ) py = margin;
3872 int wd = get_screen_w(lock_window,-1) - margin;
3873 if( px > wd ) px = wd;
3874 int ht = get_screen_h(lock_window,-1) - margin;
3875 if( py > ht ) py = ht;
3877 int BC_WindowBase::get_pop_cursor_x(int lock_window)
3880 get_pop_cursor(px, py, lock_window);
3883 int BC_WindowBase::get_pop_cursor_y(int lock_window)
3886 get_pop_cursor(px, py, lock_window);
3890 int BC_WindowBase::match_window(Window win)
3892 if (this->win == win) return 1;
3894 for(int i = 0; i < subwindows->total; i++) {
3895 result = subwindows->values[i]->match_window(win);
3896 if (result) return result;
3902 int BC_WindowBase::get_cursor_over_window()
3904 int abs_x, abs_y, win_x, win_y;
3905 unsigned int mask_return;
3906 Window root_return, child_return;
3908 int ret = XQueryPointer(top_level->display, top_level->rootwin,
3909 &root_return, &child_return, &abs_x, &abs_y,
3910 &win_x, &win_y, &mask_return);
3911 if( ret && child_return == None ) ret = 0;
3912 if( ret && win != child_return )
3913 ret = top_level->match_window(child_return);
3914 // query pointer can return a window manager window with this top_level as a child
3915 // for kde this can be two levels deep
3916 unsigned int nchildren_return = 0;
3917 Window parent_return, *children_return = 0;
3918 Window top_win = top_level->win;
3919 while( !ret && top_win != top_level->rootwin && top_win != root_return &&
3920 XQueryTree(top_level->display, top_win, &root_return,
3921 &parent_return, &children_return, &nchildren_return) ) {
3922 if( children_return ) XFree(children_return);
3923 if( (top_win=parent_return) == child_return ) ret = 1;
3928 int BC_WindowBase::cursor_above()
3931 get_relative_cursor(rx, ry);
3932 return rx < 0 || rx >= get_w() ||
3933 ry < 0 || ry >= get_h() ? 0 : 1;
3936 int BC_WindowBase::get_drag_x()
3938 return top_level->drag_x;
3941 int BC_WindowBase::get_drag_y()
3943 return top_level->drag_y;
3946 int BC_WindowBase::get_cursor_x()
3948 return top_level->cursor_x;
3951 int BC_WindowBase::get_cursor_y()
3953 return top_level->cursor_y;
3956 int BC_WindowBase::dump_windows()
3958 printf("\tBC_WindowBase::dump_windows window=%p win=%p '%s', %dx%d+%d+%d %s\n",
3959 this, (void*)this->win, title, w,h,x,y, typeid(*this).name());
3960 for(int i = 0; i < subwindows->size(); i++)
3961 subwindows->get(i)->dump_windows();
3962 for(int i = 0; i < popups.size(); i++) {
3963 BC_WindowBase *p = popups[i];
3964 printf("\tBC_WindowBase::dump_windows popup=%p win=%p '%s', %dx%d+%d+%d %s\n",
3965 p, (void*)p->win, p->title, p->w,p->h,p->x,p->y, typeid(*p).name());
3970 int BC_WindowBase::is_event_win()
3972 return this->win == top_level->event_win;
3975 void BC_WindowBase::set_dragging(int value)
3977 is_dragging = value;
3980 int BC_WindowBase::get_dragging()
3985 int BC_WindowBase::get_buttonpress()
3987 return top_level->button_number;
3990 int BC_WindowBase::get_button_down()
3992 return top_level->button_down;
3995 int BC_WindowBase::alt_down()
3997 return top_level->alt_mask;
4000 int BC_WindowBase::shift_down()
4002 return top_level->shift_mask;
4005 int BC_WindowBase::ctrl_down()
4007 return top_level->ctrl_mask;
4010 wchar_t* BC_WindowBase::get_wkeystring(int *length)
4013 *length = top_level->wkey_string_length;
4014 return top_level->wkey_string;
4017 #ifdef X_HAVE_UTF8_STRING
4018 char* BC_WindowBase::get_keypress_utf8()
4020 return top_level->key_pressed_utf8;
4025 int BC_WindowBase::get_keypress()
4027 return top_level->key_pressed;
4030 int BC_WindowBase::get_double_click()
4032 return top_level->double_click;
4035 int BC_WindowBase::get_triple_click()
4037 return top_level->triple_click;
4040 int BC_WindowBase::get_bgcolor()
4045 int BC_WindowBase::resize_window(int w, int h)
4047 if(this->w == w && this->h == h) return 0;
4049 if(window_type == MAIN_WINDOW && !allow_resize)
4051 XSizeHints size_hints;
4052 size_hints.flags = PSize | PMinSize | PMaxSize;
4053 size_hints.width = w;
4054 size_hints.height = h;
4055 size_hints.min_width = w;
4056 size_hints.max_width = w;
4057 size_hints.min_height = h;
4058 size_hints.max_height = h;
4059 XSetNormalHints(top_level->display, win, &size_hints);
4061 XResizeWindow(top_level->display, win, w, h);
4066 pixmap = new BC_Pixmap(this, w, h);
4068 // Propagate to menubar
4069 for(int i = 0; i < subwindows->total; i++)
4071 subwindows->values[i]->dispatch_resize_event(w, h);
4074 draw_background(0, 0, w, h);
4075 if(top_level == this && get_resources()->recursive_resizing)
4076 resize_history.append(new BC_ResizeCall(w, h));
4080 // The only way for resize events to be propagated is by updating the internal w and h
4081 int BC_WindowBase::resize_event(int w, int h)
4083 if(window_type == MAIN_WINDOW)
4091 int BC_WindowBase::reposition_window(int x, int y)
4093 reposition_window(x, y, -1, -1);
4098 int BC_WindowBase::reposition_window(int x, int y, int w, int h)
4102 // Some tools set their own dimensions before calling this, causing the
4103 // resize check to skip.
4107 if(w > 0 && w != this->w)
4113 if(h > 0 && h != this->h)
4119 //printf("BC_WindowBase::reposition_window %d %d %d\n", translation_count, x_correction, y_correction);
4122 printf("BC_WindowBase::reposition_window this->w == %d\n", this->w);
4124 printf("BC_WindowBase::reposition_window this->h == %d\n", this->h);
4126 if(translation_count && window_type == MAIN_WINDOW)
4128 // KDE shifts window right and down.
4129 // FVWM leaves window alone and adds border around it.
4130 XMoveResizeWindow(top_level->display,
4132 x - BC_DisplayInfo::auto_reposition_x,
4133 y - BC_DisplayInfo::auto_reposition_y,
4139 XMoveResizeWindow(top_level->display,
4150 pixmap = new BC_Pixmap(this, this->w, this->h);
4151 clear_box(0,0, this->w, this->h);
4152 // Propagate to menubar
4153 for(int i = 0; i < subwindows->total; i++)
4155 subwindows->values[i]->dispatch_resize_event(this->w, this->h);
4158 // draw_background(0, 0, w, h);
4164 int BC_WindowBase::reposition_window_relative(int dx, int dy, int w, int h)
4166 return reposition_window(get_x()+dx, get_y()+dy, w, h);
4169 int BC_WindowBase::reposition_window_relative(int dx, int dy)
4171 return reposition_window_relative(dx, dy, -1, -1);
4174 void BC_WindowBase::set_tooltips(int v)
4176 get_resources()->tooltips_enabled = v;
4179 void BC_WindowBase::set_force_tooltip(int v)
4184 int BC_WindowBase::raise_window(int do_flush)
4186 XRaiseWindow(top_level->display, win);
4187 if(do_flush) XFlush(top_level->display);
4191 int BC_WindowBase::lower_window(int do_flush)
4193 XLowerWindow(top_level->display, win);
4194 if(do_flush) XFlush(top_level->display);
4198 void BC_WindowBase::set_background(VFrame *bitmap)
4200 if(bg_pixmap && !shared_bg_pixmap) delete bg_pixmap;
4202 bg_pixmap = new BC_Pixmap(this, bitmap, PIXMAP_OPAQUE);
4203 shared_bg_pixmap = 0;
4204 draw_background(0, 0, w, h);
4207 void BC_WindowBase::put_title(const char *text)
4209 char *cp = this->title, *ep = cp+sizeof(this->title)-1;
4210 for( const unsigned char *bp = (const unsigned char *)text; *bp && cp<ep; ++bp )
4211 *cp++ = *bp >= ' ' ? *bp : ' ';
4215 void BC_WindowBase::set_title(const char *text, int utf8)
4217 // utf8>0: wm + net_wm, utf8=0: wm only, utf<0: net_wm only
4219 const unsigned char *wm_title = (const unsigned char *)title;
4220 int title_len = strlen((const char *)title);
4222 Atom xa_wm_name = XA_WM_NAME;
4223 Atom xa_icon_name = XA_WM_ICON_NAME;
4224 Atom xa_string = XA_STRING;
4225 XChangeProperty(display, win, xa_wm_name, xa_string, 8,
4226 PropModeReplace, wm_title, title_len);
4227 XChangeProperty(display, win, xa_icon_name, xa_string, 8,
4228 PropModeReplace, wm_title, title_len);
4231 Atom xa_net_wm_name = XInternAtom(display, "_NET_WM_NAME", True);
4232 Atom xa_net_icon_name = XInternAtom(display, "_NET_WM_ICON_NAME", True);
4233 Atom xa_utf8_string = XInternAtom(display, "UTF8_STRING", True);
4234 XChangeProperty(display, win, xa_net_wm_name, xa_utf8_string, 8,
4235 PropModeReplace, wm_title, title_len);
4236 XChangeProperty(display, win, xa_net_icon_name, xa_utf8_string, 8,
4237 PropModeReplace, wm_title, title_len);
4242 const char *BC_WindowBase::get_title()
4247 int BC_WindowBase::get_toggle_value()
4249 return toggle_value;
4252 int BC_WindowBase::get_toggle_drag()
4257 int BC_WindowBase::set_icon(VFrame *data)
4259 if(icon_pixmap) delete icon_pixmap;
4260 icon_pixmap = new BC_Pixmap(top_level, data, PIXMAP_ALPHA, 1);
4262 if(icon_window) delete icon_window;
4263 icon_window = new BC_Popup(this,
4266 icon_pixmap->get_w(),
4267 icon_pixmap->get_h(),
4269 1, // All windows are hidden initially
4273 wm_hints.flags = WindowGroupHint | IconPixmapHint | IconMaskHint | IconWindowHint;
4274 wm_hints.icon_pixmap = icon_pixmap->get_pixmap();
4275 wm_hints.icon_mask = icon_pixmap->get_alpha();
4276 wm_hints.icon_window = icon_window->win;
4277 wm_hints.window_group = XGroupLeader;
4279 // for(int i = 0; i < 1000; i++)
4280 // printf("02x ", icon_pixmap->get_alpha()->get_row_pointers()[0][i]);
4283 XSetWMHints(top_level->display, top_level->win, &wm_hints);
4284 XSync(top_level->display, 0);
4288 int BC_WindowBase::set_w(int w)
4294 int BC_WindowBase::set_h(int h)
4300 int BC_WindowBase::load_defaults(BC_Hash *defaults)
4302 BC_Resources *resources = get_resources();
4303 char string[BCTEXTLEN];
4304 int newest_id = - 1;
4305 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
4307 sprintf(string, "FILEBOX_HISTORY_PATH%d", i);
4308 resources->filebox_history[i].path[0] = 0;
4309 defaults->get(string, resources->filebox_history[i].path);
4310 sprintf(string, "FILEBOX_HISTORY_ID%d", i);
4311 resources->filebox_history[i].id = defaults->get(string, resources->get_id());
4312 if(resources->filebox_history[i].id > newest_id)
4313 newest_id = resources->filebox_history[i].id;
4316 resources->filebox_id = newest_id + 1;
4317 resources->filebox_mode = defaults->get("FILEBOX_MODE", get_resources()->filebox_mode);
4318 resources->filebox_w = defaults->get("FILEBOX_W", get_resources()->filebox_w);
4319 resources->filebox_h = defaults->get("FILEBOX_H", get_resources()->filebox_h);
4320 resources->filebox_columntype[0] = defaults->get("FILEBOX_TYPE0", resources->filebox_columntype[0]);
4321 resources->filebox_columntype[1] = defaults->get("FILEBOX_TYPE1", resources->filebox_columntype[1]);
4322 resources->filebox_columntype[2] = defaults->get("FILEBOX_TYPE2", resources->filebox_columntype[2]);
4323 resources->filebox_columntype[3] = defaults->get("FILEBOX_TYPE3", resources->filebox_columntype[3]);
4324 resources->filebox_columnwidth[0] = defaults->get("FILEBOX_WIDTH0", resources->filebox_columnwidth[0]);
4325 resources->filebox_columnwidth[1] = defaults->get("FILEBOX_WIDTH1", resources->filebox_columnwidth[1]);
4326 resources->filebox_columnwidth[2] = defaults->get("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
4327 resources->filebox_columnwidth[3] = defaults->get("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
4328 resources->filebox_size_format = defaults->get("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
4329 defaults->get("FILEBOX_FILTER", resources->filebox_filter);
4333 int BC_WindowBase::save_defaults(BC_Hash *defaults)
4335 BC_Resources *resources = get_resources();
4336 char string[BCTEXTLEN];
4337 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
4339 sprintf(string, "FILEBOX_HISTORY_PATH%d", i);
4340 defaults->update(string, resources->filebox_history[i].path);
4341 sprintf(string, "FILEBOX_HISTORY_ID%d", i);
4342 defaults->update(string, resources->filebox_history[i].id);
4344 defaults->update("FILEBOX_MODE", resources->filebox_mode);
4345 defaults->update("FILEBOX_W", resources->filebox_w);
4346 defaults->update("FILEBOX_H", resources->filebox_h);
4347 defaults->update("FILEBOX_TYPE0", resources->filebox_columntype[0]);
4348 defaults->update("FILEBOX_TYPE1", resources->filebox_columntype[1]);
4349 defaults->update("FILEBOX_TYPE2", resources->filebox_columntype[2]);
4350 defaults->update("FILEBOX_TYPE3", resources->filebox_columntype[3]);
4351 defaults->update("FILEBOX_WIDTH0", resources->filebox_columnwidth[0]);
4352 defaults->update("FILEBOX_WIDTH1", resources->filebox_columnwidth[1]);
4353 defaults->update("FILEBOX_WIDTH2", resources->filebox_columnwidth[2]);
4354 defaults->update("FILEBOX_WIDTH3", resources->filebox_columnwidth[3]);
4355 defaults->update("FILEBOX_FILTER", resources->filebox_filter);
4356 defaults->update("FILEBOX_SIZE_FORMAT", get_resources()->filebox_size_format);
4362 // For some reason XTranslateCoordinates can take a long time to return.
4363 // We work around this by only calling it when the event windows are different.
4364 void BC_WindowBase::translate_coordinates(Window src_w,
4376 *dest_x_return = src_x;
4377 *dest_y_return = src_y;
4381 XTranslateCoordinates(top_level->display,
4389 //printf("BC_WindowBase::translate_coordinates 1 %lld\n", timer.get_difference());
4393 void BC_WindowBase::get_root_coordinates(int x, int y, int *abs_x, int *abs_y)
4395 translate_coordinates(win, top_level->rootwin, x, y, abs_x, abs_y);
4398 void BC_WindowBase::get_win_coordinates(int abs_x, int abs_y, int *x, int *y)
4400 translate_coordinates(top_level->rootwin, win, abs_x, abs_y, x, y);
4408 #ifdef HAVE_LIBXXF86VM
4409 void BC_WindowBase::closest_vm(int *vm, int *width, int *height)
4413 if(XF86VidModeQueryExtension(top_level->display,&foo,&bar)) {
4415 XF86VidModeModeInfo **vm_modelines;
4416 XF86VidModeGetAllModeLines(top_level->display,
4417 XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
4418 for( i = 0; i < vm_count; i++ ) {
4419 if( vm_modelines[i]->hdisplay < vm_modelines[*vm]->hdisplay &&
4420 vm_modelines[i]->hdisplay >= *width )
4423 display = top_level->display;
4424 if( vm_modelines[*vm]->hdisplay == *width )
4427 *width = vm_modelines[*vm]->hdisplay;
4428 *height = vm_modelines[*vm]->vdisplay;
4433 void BC_WindowBase::scale_vm(int vm)
4435 int foo,bar,dotclock;
4436 if( XF86VidModeQueryExtension(top_level->display,&foo,&bar) ) {
4438 XF86VidModeModeInfo **vm_modelines;
4439 XF86VidModeModeLine vml;
4440 XF86VidModeGetAllModeLines(top_level->display,
4441 XDefaultScreen(top_level->display), &vm_count,&vm_modelines);
4442 XF86VidModeGetModeLine(top_level->display,
4443 XDefaultScreen(top_level->display), &dotclock,&vml);
4444 orig_modeline.dotclock = dotclock;
4445 orig_modeline.hdisplay = vml.hdisplay;
4446 orig_modeline.hsyncstart = vml.hsyncstart;
4447 orig_modeline.hsyncend = vml.hsyncend;
4448 orig_modeline.htotal = vml.htotal;
4449 orig_modeline.vdisplay = vml.vdisplay;
4450 orig_modeline.vsyncstart = vml.vsyncstart;
4451 orig_modeline.vsyncend = vml.vsyncend;
4452 orig_modeline.vtotal = vml.vtotal;
4453 orig_modeline.flags = vml.flags;
4454 orig_modeline.privsize = vml.privsize;
4455 // orig_modeline.private = vml.private;
4456 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),vm_modelines[vm]);
4457 XF86VidModeSetViewPort(top_level->display,XDefaultScreen(top_level->display),0,0);
4458 XFlush(top_level->display);
4462 void BC_WindowBase::restore_vm()
4464 XF86VidModeSwitchToMode(top_level->display,XDefaultScreen(top_level->display),&orig_modeline);
4465 XFlush(top_level->display);
4470 #ifndef SINGLE_THREAD
4471 int BC_WindowBase::get_event_count()
4473 event_lock->lock("BC_WindowBase::get_event_count");
4474 int result = common_events.total;
4475 event_lock->unlock();
4479 XEvent* BC_WindowBase::get_event()
4482 while(!done && !result)
4484 event_condition->lock("BC_WindowBase::get_event");
4485 event_lock->lock("BC_WindowBase::get_event");
4487 if(common_events.total && !done)
4489 result = common_events.values[0];
4490 common_events.remove_number(0);
4493 event_lock->unlock();
4498 void BC_WindowBase::put_event(XEvent *event)
4500 event_lock->lock("BC_WindowBase::put_event");
4501 common_events.append(event);
4502 event_lock->unlock();
4503 event_condition->unlock();
4506 void BC_WindowBase::dequeue_events(Window win)
4508 event_lock->lock("BC_WindowBase::dequeue_events");
4510 int out = 0, total = common_events.size();
4511 for( int in=0; in<total; ++in ) {
4512 if( common_events[in]->xany.window == win ) continue;
4513 common_events[out++] = common_events[in];
4515 common_events.total = out;
4517 event_lock->unlock();
4520 int BC_WindowBase::resend_event(BC_WindowBase *window)
4522 if( resend_event_window ) return 1;
4523 resend_event_window = window;
4529 int BC_WindowBase::resend_event(BC_WindowBase *window)
4534 #endif // SINGLE_THREAD
4536 int BC_WindowBase::get_id()
4542 BC_Pixmap *BC_WindowBase::create_pixmap(VFrame *vframe)
4544 int w = vframe->get_w(), h = vframe->get_h();
4545 BC_Pixmap *icon = new BC_Pixmap(this, w, h);
4546 icon->draw_vframe(vframe, 0,0, w,h, 0,0);
4551 void BC_WindowBase::flicker(int n, int ms)
4553 int color = get_bg_color();
4554 for( int i=2*n; --i>=0; ) {
4555 set_inverse(); set_bg_color(WHITE);
4556 clear_box(0,0, w,h); flash(1);
4557 sync_display(); Timer::delay(ms);
4559 set_bg_color(color);
4563 void BC_WindowBase::focus()
4565 XWindowAttributes xwa;
4566 XGetWindowAttributes(top_level->display, top_level->win, &xwa);
4567 if( xwa.map_state == IsViewable )
4568 XSetInputFocus(top_level->display, top_level->win, RevertToParent, CurrentTime);