X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7e4501ee3cc88ee8dd2b75e2964118e2897ec4a2..b5a8b32f50f7a5550dc9602236b9c7b49ba5e02c:/src/x11/app.cpp diff --git a/src/x11/app.cpp b/src/x11/app.cpp index 511b5fb034..dfdb222158 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -25,10 +25,13 @@ #include "wx/log.h" #include "wx/intl.h" #include "wx/evtloop.h" +#include "wx/timer.h" #include "wx/univ/theme.h" #include "wx/univ/renderer.h" +#define ABS(a) (((a) < 0) ? -(a) : (a)) + #if wxUSE_THREADS #include "wx/thread.h" #endif @@ -37,32 +40,38 @@ #include "wx/resource.h" #endif -#ifdef __VMS__ -#pragma message disable nosimpint -#endif -#include -#include -#include - -#ifdef __VMS__ -#pragma message enable nosimpint -#endif - #include "wx/x11/private.h" #include +//------------------------------------------------------------------------ +// global data +//------------------------------------------------------------------------ + extern wxList wxPendingDelete; +wxHashTable *wxWidgetHashTable = NULL; +wxHashTable *wxClientWidgetHashTable = NULL; + wxApp *wxTheApp = NULL; -wxHashTable *wxWidgetHashTable = NULL; +// This is set within wxEntryStart -- too early on +// to put these in wxTheApp +static int g_newArgc = 0; +static wxChar** g_newArgv = NULL; +static bool g_showIconic = FALSE; +static wxSize g_initialSize = wxDefaultSize; -IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) +// This is required for wxFocusEvent::SetWindow(). It will only +// work for focus events which we provoke ourselves (by calling +// SetFocus()). It will not work for those events, which X11 +// generates itself. +static wxWindow *g_nextFocus = NULL; +static wxWindow *g_prevFocus = NULL; -BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) - EVT_IDLE(wxApp::OnIdle) -END_EVENT_TABLE() +//------------------------------------------------------------------------ +// X11 error handling +//------------------------------------------------------------------------ #ifdef __WXDEBUG__ typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *); @@ -72,24 +81,34 @@ XErrorHandlerFunc gs_pfnXErrorHandler = 0; static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent) { // just forward to the default handler for now - return gs_pfnXErrorHandler(dpy, xevent); + if (gs_pfnXErrorHandler) + return gs_pfnXErrorHandler(dpy, xevent); + else + return 0; } #endif // __WXDEBUG__ +//------------------------------------------------------------------------ +// wxApp +//------------------------------------------------------------------------ + long wxApp::sm_lastMessageTime = 0; WXDisplay *wxApp::ms_display = NULL; -// This is set within wxEntryStart -- too early on -// to put these in wxTheApp -static int g_newArgc = 0; -static wxChar** g_newArgv = NULL; -static bool g_showIconic = FALSE; -static wxSize g_initialSize = wxDefaultSize; +IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) + +BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) + EVT_IDLE(wxApp::OnIdle) +END_EVENT_TABLE() bool wxApp::Initialize() { wxClassInfo::InitializeClasses(); +#if wxUSE_INTL + wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); +#endif + // GL: I'm annoyed ... I don't know where to put this and I don't want to // create a module for that as it's part of the core. #if wxUSE_THREADS @@ -107,6 +126,7 @@ bool wxApp::Initialize() #endif wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER); + wxClientWidgetHashTable = new wxHashTable(wxKEY_INTEGER); wxModule::RegisterModules(); if (!wxModule::InitializeModules()) return FALSE; @@ -122,6 +142,8 @@ void wxApp::CleanUp() delete wxWidgetHashTable; wxWidgetHashTable = NULL; + delete wxClientWidgetHashTable; + wxClientWidgetHashTable = NULL; wxModule::CleanUpModules(); @@ -133,7 +155,7 @@ void wxApp::CleanUp() wxTheColourDatabase = NULL; wxDeleteStockObjects(); - + wxDeleteStockLists(); delete wxTheApp; @@ -169,8 +191,10 @@ void wxApp::CleanUp() int wxEntryStart( int& argc, char *argv[] ) { #ifdef __WXDEBUG__ +#if !wxUSE_NANOX // install the X error handler gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler ); +#endif #endif // __WXDEBUG__ wxString displayName; @@ -230,11 +254,11 @@ int wxEntryStart( int& argc, char *argv[] ) g_newArgc ++; } - Display* xdisplay; + Display* xdisplay = NULL; if (displayName.IsEmpty()) xdisplay = XOpenDisplay(NULL); else - xdisplay = XOpenDisplay(displayName); + xdisplay = XOpenDisplay((char*) displayName.c_str()); if (!xdisplay) { @@ -246,11 +270,11 @@ int wxEntryStart( int& argc, char *argv[] ) { XSynchronize(xdisplay, True); } - + wxApp::ms_display = (WXDisplay*) xdisplay; - + XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask); - + wxSetDetectableAutoRepeat( TRUE ); if (!wxApp::Initialize()) @@ -378,6 +402,22 @@ wxApp::wxApp() m_mainLoop = NULL; m_showIconic = FALSE; m_initialSize = wxDefaultSize; + +#if !wxUSE_NANOX + m_visualColormap = NULL; + m_colorCube = NULL; +#endif +} + +wxApp::~wxApp() +{ +#if !wxUSE_NANOX + if (m_colorCube) + free( m_colorCube ); + + if (m_visualColormap) + delete [] (XColor*)m_visualColormap; +#endif } bool wxApp::Initialized() @@ -390,7 +430,7 @@ bool wxApp::Initialized() int wxApp::MainLoop() { - int rt; + int rt; m_mainLoop = new wxEventLoop; rt = m_mainLoop->Run(); @@ -400,15 +440,55 @@ int wxApp::MainLoop() return rt; } -// Processes an X event. -void wxApp::ProcessXEvent(WXEvent* _event) +#if !wxUSE_NANOX +//----------------------------------------------------------------------- +// X11 predicate function for exposure compression +//----------------------------------------------------------------------- + +struct wxExposeInfo +{ + Window window; + Bool found_non_matching; +}; + +static Bool expose_predicate (Display *display, XEvent *xevent, XPointer arg) +{ + wxExposeInfo *info = (wxExposeInfo*) arg; + + if (info->found_non_matching) + return FALSE; + + if (xevent->xany.type != Expose) + { + info->found_non_matching = TRUE; + return FALSE; + } + + if (xevent->xexpose.window != info->window) + { + info->found_non_matching = TRUE; + return FALSE; + } + + return TRUE; +} +#endif + // wxUSE_NANOX + +//----------------------------------------------------------------------- +// Processes an X event, returning TRUE if the event was processed. +//----------------------------------------------------------------------- + +bool wxApp::ProcessXEvent(WXEvent* _event) { XEvent* event = (XEvent*) _event; wxWindow* win = NULL; - Window window = event->xany.window; + Window window = XEventGetWindow(event); +#if 0 Window actualWindow = window; - +#endif + // Find the first wxWindow that corresponds to this event window // Because we're receiving events after a window // has been destroyed, assume a 1:1 match between @@ -417,72 +497,184 @@ void wxApp::ProcessXEvent(WXEvent* _event) win = wxGetWindowFromTable(window); if (!win) - return; + { +#if wxUSE_TWO_WINDOWS + win = wxGetClientWindowFromTable(window); + if (!win) +#endif + return FALSE; + } + +#ifdef __WXDEBUG__ + wxString windowClass = win->GetClassInfo()->GetClassName(); +#endif switch (event->type) { - case KeyPress: + case Expose: { - if (win && !win->IsEnabled()) - return; - +#if wxUSE_TWO_WINDOWS && !wxUSE_NANOX + if (event->xexpose.window != (Window)win->GetClientAreaWindow()) { - if (win) + XEvent tmp_event; + wxExposeInfo info; + info.window = event->xexpose.window; + info.found_non_matching = FALSE; + while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info )) { - wxKeyEvent keyEvent(wxEVT_KEY_DOWN); - wxTranslateKeyEvent(keyEvent, win, window, event); - - wxLogDebug( "OnKey from %s", win->GetName().c_str() ); - - // We didn't process wxEVT_KEY_DOWN, so send - // wxEVT_CHAR - if (!win->GetEventHandler()->ProcessEvent( keyEvent )) - { - keyEvent.SetEventType(wxEVT_CHAR); - win->GetEventHandler()->ProcessEvent( keyEvent ); - } + // Don't worry about optimizing redrawing the border etc. + } + win->NeedUpdateNcAreaInIdle(); + } + else +#endif + { + win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), + XExposeEventGetWidth(event), XExposeEventGetHeight(event)); + win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), + XExposeEventGetWidth(event), XExposeEventGetHeight(event)); + +#if !wxUSE_NANOX + XEvent tmp_event; + wxExposeInfo info; + info.window = event->xexpose.window; + info.found_non_matching = FALSE; + while (XCheckIfEvent( wxGlobalDisplay(), &tmp_event, expose_predicate, (XPointer) &info )) + { + win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, + tmp_event.xexpose.width, tmp_event.xexpose.height ); - // We intercepted and processed the key down event - return; + win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, + tmp_event.xexpose.width, tmp_event.xexpose.height ); } +#endif + + // This simplifies the expose and clear areas to simple + // rectangles. + win->GetUpdateRegion() = win->GetUpdateRegion().GetBox(); + win->GetClearRegion() = win->GetClearRegion().GetBox(); + + // If we only have one X11 window, always indicate + // that borders might have to be redrawn. + if (win->GetMainWindow() == win->GetClientAreaWindow()) + win->NeedUpdateNcAreaInIdle(); + + // Only erase background, paint in idle time. + win->SendEraseEvents(); + // win->Update(); } - return; + + return TRUE; } - case KeyRelease: + +#if !wxUSE_NANOX + case GraphicsExpose: { - if (win && !win->IsEnabled()) - return; + printf( "GraphicExpose event\n" ); - if (win) + wxLogTrace( _T("expose"), _T("GraphicsExpose from %s"), win->GetName().c_str(), + event->xgraphicsexpose.x, event->xgraphicsexpose.y, + event->xgraphicsexpose.width, event->xgraphicsexpose.height); + + win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, + event->xgraphicsexpose.width, event->xgraphicsexpose.height); + + win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, + event->xgraphicsexpose.width, event->xgraphicsexpose.height); + + if (event->xgraphicsexpose.count == 0) { - wxKeyEvent keyEvent(wxEVT_KEY_UP); - wxTranslateKeyEvent(keyEvent, win, window, event); - - win->GetEventHandler()->ProcessEvent( keyEvent ); + // Only erase background, paint in idle time. + win->SendEraseEvents(); + // win->Update(); } - return; + + return TRUE; + } +#endif + + case KeyPress: + { + if (!win->IsEnabled()) + return FALSE; + + wxKeyEvent keyEvent(wxEVT_KEY_DOWN); + wxTranslateKeyEvent(keyEvent, win, window, event); + + // wxLogDebug( "OnKey from %s", win->GetName().c_str() ); + + // We didn't process wxEVT_KEY_DOWN, so send wxEVT_CHAR + if (win->GetEventHandler()->ProcessEvent( keyEvent )) + return TRUE; + + keyEvent.SetEventType(wxEVT_CHAR); + if (win->GetEventHandler()->ProcessEvent( keyEvent )) + return TRUE; + + if ( (keyEvent.m_keyCode == WXK_TAB) && + win->GetParent() && (win->GetParent()->HasFlag( wxTAB_TRAVERSAL)) ) + { + wxNavigationKeyEvent new_event; + new_event.SetEventObject( win->GetParent() ); + /* GDK reports GDK_ISO_Left_Tab for SHIFT-TAB */ + new_event.SetDirection( (keyEvent.m_keyCode == WXK_TAB) ); + /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */ + new_event.SetWindowChange( keyEvent.ControlDown() ); + new_event.SetCurrentFocus( win ); + return win->GetParent()->GetEventHandler()->ProcessEvent( new_event ); + } + + return FALSE; + } + case KeyRelease: + { + if (!win->IsEnabled()) + return FALSE; + + wxKeyEvent keyEvent(wxEVT_KEY_UP); + wxTranslateKeyEvent(keyEvent, win, window, event); + + return win->GetEventHandler()->ProcessEvent( keyEvent ); } case ConfigureNotify: { - // Not clear if this is the same in NanoX - if (win) +#if wxUSE_NANOX + if (event->update.utype == GR_UPDATE_SIZE) +#endif { - wxSizeEvent sizeEvent( wxSize(event->xconfigure.width,event->xconfigure.height), win->GetId() ); - sizeEvent.SetEventObject( win ); - - win->GetEventHandler()->ProcessEvent( sizeEvent ); + if (win->IsTopLevel()) + { + wxTopLevelWindow *tlw = (wxTopLevelWindow*) win; + tlw->SetConfigureGeometry( XConfigureEventGetX(event), XConfigureEventGetY(event), + XConfigureEventGetWidth(event), XConfigureEventGetHeight(event) ); + } + + if (win->IsTopLevel() && win->IsShown()) + { + wxTopLevelWindowX11 *tlw = (wxTopLevelWindowX11 *) win; + tlw->SetNeedResizeInIdle(); + } + else + { + wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() ); + sizeEvent.SetEventObject( win ); + + return win->GetEventHandler()->ProcessEvent( sizeEvent ); + } } + return FALSE; + break; } #if !wxUSE_NANOX case PropertyNotify: { - HandlePropertyChange(_event); - return; + //wxLogDebug("PropertyNotify: %s", windowClass.c_str()); + return HandlePropertyChange(_event); } case ClientMessage: { - if (win && !win->IsEnabled()) - return; + if (!win->IsEnabled()) + return FALSE; Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True); Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True); @@ -491,143 +683,157 @@ void wxApp::ProcessXEvent(WXEvent* _event) { if ((Atom) (event->xclient.data.l[0]) == wm_delete_window) { - if (win) - { - win->Close(FALSE); - } + win->Close(FALSE); + return TRUE; } } - return; + return FALSE; + } +#if 0 + case DestroyNotify: + { + printf( "destroy from %s\n", win->GetName().c_str() ); + break; + } + case CreateNotify: + { + printf( "create from %s\n", win->GetName().c_str() ); + break; + } + case MapRequest: + { + printf( "map request from %s\n", win->GetName().c_str() ); + break; } case ResizeRequest: { - /* - * If resize event, don't resize until the last resize event for this - * window is recieved. Prevents flicker as windows are resized. - */ - + printf( "resize request from %s\n", win->GetName().c_str() ); + Display *disp = (Display*) wxGetDisplay(); XEvent report; - + // to avoid flicker report = * event; while( XCheckTypedWindowEvent (disp, actualWindow, ResizeRequest, &report)); - - if (win) - { - wxSize sz = win->GetSize(); - wxSizeEvent sizeEvent(sz, win->GetId()); - sizeEvent.SetEventObject(win); - win->GetEventHandler()->ProcessEvent( sizeEvent ); - } + wxSize sz = win->GetSize(); + wxSizeEvent sizeEvent(sz, win->GetId()); + sizeEvent.SetEventObject(win); - return; + return win->GetEventHandler()->ProcessEvent( sizeEvent ); } #endif +#endif #if wxUSE_NANOX case GR_EVENT_TYPE_CLOSE_REQ: { if (win) { win->Close(FALSE); + return TRUE; } + return FALSE; break; } #endif - case Expose: - { - if (win) - { - win->GetUpdateRegion().Union( event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); - - win->GetClearRegion().Union( event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); - - // if (event->xexpose.count == 0) - // win->Update(); - } - - return; - } - case GraphicsExpose: - { - if (win) - { - // wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(), - // event->xgraphicsexpose.x, event->xgraphicsexpose.y, - // event->xgraphicsexpose.width, event->xgraphicsexpose.height); - - win->GetUpdateRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, - event->xgraphicsexpose.width, event->xgraphicsexpose.height); - - win->GetClearRegion().Union( event->xgraphicsexpose.x, event->xgraphicsexpose.y, - event->xgraphicsexpose.width, event->xgraphicsexpose.height); - - // if (event->xgraphicsexpose.count == 0) - // win->Update(); - } - - return; - } case EnterNotify: case LeaveNotify: case ButtonPress: case ButtonRelease: case MotionNotify: { - if (!win) - return; - if (!win->IsEnabled()) - return; - -#if 1 + return FALSE; + + // Here we check if the top level window is + // disabled, which is one aspect of modality. + wxWindow *tlw = win; + while (tlw && !tlw->IsTopLevel()) + tlw = tlw->GetParent(); + if (tlw && !tlw->IsEnabled()) + return FALSE; + if (event->type == ButtonPress) { if ((win != wxWindow::FindFocus()) && win->AcceptsFocus()) - win->SetFocus(); + { + // This might actually be done in wxWindow::SetFocus() + // and not here. TODO. + g_prevFocus = wxWindow::FindFocus(); + g_nextFocus = win; + + wxLogTrace( _T("focus"), _T("About to call SetFocus on %s of type %s due to button press"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); + + // Record the fact that this window is + // getting the focus, because we'll need to + // check if its parent is getting a bogus + // focus and duly ignore it. + // TODO: may need to have this code in SetFocus, too. + extern wxWindow* g_GettingFocus; + g_GettingFocus = win; + win->SetFocus(); + } } -#endif +#if !wxUSE_NANOX + if (event->type == LeaveNotify || event->type == EnterNotify) + { + // Throw out NotifyGrab and NotifyUngrab + if (event->xcrossing.mode != NotifyNormal) + return FALSE; + } +#endif wxMouseEvent wxevent; wxTranslateMouseEvent(wxevent, win, window, event); - win->GetEventHandler()->ProcessEvent( wxevent ); - return; + return win->GetEventHandler()->ProcessEvent( wxevent ); } case FocusIn: { #if !wxUSE_NANOX - if (win && event->xfocus.detail != NotifyPointer) + if ((event->xfocus.detail != NotifyPointer) && + (event->xfocus.mode == NotifyNormal)) #endif { - wxLogDebug( "FocusIn from %s", win->GetName().c_str() ); + wxLogTrace( _T("focus"), _T("FocusIn from %s of type %s"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); - wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId()); - focusEvent.SetEventObject(win); - win->GetEventHandler()->ProcessEvent(focusEvent); + extern wxWindow* g_GettingFocus; + if (g_GettingFocus && g_GettingFocus->GetParent() == win) + { + // Ignore this, this can be a spurious FocusIn + // caused by a child having its focus set. + g_GettingFocus = NULL; + wxLogTrace( _T("focus"), _T("FocusIn from %s of type %s being deliberately ignored"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); + return TRUE; + } + else + { + wxFocusEvent focusEvent(wxEVT_SET_FOCUS, win->GetId()); + focusEvent.SetEventObject(win); + focusEvent.SetWindow( g_prevFocus ); + g_prevFocus = NULL; + + return win->GetEventHandler()->ProcessEvent(focusEvent); + } } + return FALSE; break; } case FocusOut: { #if !wxUSE_NANOX - if (win && event->xfocus.detail != NotifyPointer) + if ((event->xfocus.detail != NotifyPointer) && + (event->xfocus.mode == NotifyNormal)) #endif { - wxLogDebug( "FocusOut from %s", win->GetName().c_str() ); - + wxLogTrace( _T("focus"), _T("FocusOut from %s of type %s"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); + wxFocusEvent focusEvent(wxEVT_KILL_FOCUS, win->GetId()); focusEvent.SetEventObject(win); - win->GetEventHandler()->ProcessEvent(focusEvent); + focusEvent.SetWindow( g_nextFocus ); + g_nextFocus = NULL; + return win->GetEventHandler()->ProcessEvent(focusEvent); } - break; - } - case DestroyNotify: - { - // Do we want to process this (for top-level windows)? - // But we want to be able to veto closes, anyway + return FALSE; break; } default: @@ -636,9 +842,11 @@ void wxApp::ProcessXEvent(WXEvent* _event) //wxString eventName = wxGetXEventName(XEvent& event); //wxLogDebug(wxT("Event %s not handled"), eventName.c_str()); #endif + return FALSE; break; } } + return FALSE; } // Returns TRUE if more time is needed. @@ -673,11 +881,12 @@ void wxApp::Dispatch() // This should be redefined in a derived class for // handling property change events for XAtom IPC. -void wxApp::HandlePropertyChange(WXEvent *event) +bool wxApp::HandlePropertyChange(WXEvent *event) { // by default do nothing special // TODO: what to do for X11 // XtDispatchEvent((XEvent*) event); + return FALSE; } void wxApp::OnIdle(wxIdleEvent& event) @@ -740,8 +949,6 @@ bool wxApp::SendIdleEvents(wxWindow* win) win->GetEventHandler()->ProcessEvent(event); - win->OnInternalIdle(); - if (event.MoreRequested()) needMore = TRUE; @@ -754,7 +961,9 @@ bool wxApp::SendIdleEvents(wxWindow* win) node = node->Next(); } - + + win->OnInternalIdle(); + return needMore; } @@ -776,6 +985,24 @@ void wxApp::DeletePendingObjects() } } +static void wxCalcPrecAndShift( unsigned long mask, int *shift, int *prec ) +{ + *shift = 0; + *prec = 0; + + while (!(mask & 0x1)) + { + (*shift)++; + mask >>= 1; + } + + while (mask & 0x1) + { + (*prec)++; + mask >>= 1; + } +} + // Create display, and other initialization bool wxApp::OnInitGui() { @@ -783,14 +1010,110 @@ bool wxApp::OnInitGui() // now we don't want to try popping up a dialog // for error messages. delete wxLog::SetActiveTarget(new wxLogStderr); - + if (!wxAppBase::OnInitGui()) - return FALSE; - + return FALSE; + GetMainColormap( wxApp::GetDisplay() ); m_maxRequestSize = XMaxRequestSize( (Display*) wxApp::GetDisplay() ); +#if !wxUSE_NANOX + // Get info about the current visual. It is enough + // to do this once here unless we support different + // visuals, displays and screens. Given that wxX11 + // mostly for embedded things, that is no real + // limitation. + Display *xdisplay = (Display*) wxApp::GetDisplay(); + int xscreen = DefaultScreen(xdisplay); + Visual* xvisual = DefaultVisual(xdisplay,xscreen); + int xdepth = DefaultDepth(xdisplay, xscreen); + + XVisualInfo vinfo_template; + vinfo_template.visual = xvisual; + vinfo_template.visualid = XVisualIDFromVisual( xvisual ); + vinfo_template.depth = xdepth; + + int nitem = 0; + XVisualInfo *vi = XGetVisualInfo( xdisplay, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem ); + wxASSERT_MSG( vi, wxT("No visual info") ); + + m_visualType = vi->visual->c_class; + m_visualScreen = vi->screen; + + m_visualRedMask = vi->red_mask; + m_visualGreenMask = vi->green_mask; + m_visualBlueMask = vi->blue_mask; + + if (m_visualType != GrayScale && m_visualType != PseudoColor) + { + wxCalcPrecAndShift( m_visualRedMask, &m_visualRedShift, &m_visualRedPrec ); + wxCalcPrecAndShift( m_visualGreenMask, &m_visualGreenShift, &m_visualGreenPrec ); + wxCalcPrecAndShift( m_visualBlueMask, &m_visualBlueShift, &m_visualBluePrec ); + } + + m_visualDepth = xdepth; + if (xdepth == 16) + xdepth = m_visualRedPrec + m_visualGreenPrec + m_visualBluePrec; + + m_visualColormapSize = vi->colormap_size; + + XFree( vi ); + + if (m_visualDepth > 8) + return TRUE; + + m_visualColormap = new XColor[m_visualColormapSize]; + XColor* colors = (XColor*) m_visualColormap; + + for (int i = 0; i < m_visualColormapSize; i++) + colors[i].pixel = i; + + XQueryColors( xdisplay, DefaultColormap(xdisplay,xscreen), colors, m_visualColormapSize ); + + m_colorCube = (unsigned char*)malloc(32 * 32 * 32); + + for (int r = 0; r < 32; r++) + { + for (int g = 0; g < 32; g++) + { + for (int b = 0; b < 32; b++) + { + int rr = (r << 3) | (r >> 2); + int gg = (g << 3) | (g >> 2); + int bb = (b << 3) | (b >> 2); + + int index = -1; + + if (colors) + { + int max = 3 * 65536; + + for (int i = 0; i < m_visualColormapSize; i++) + { + int rdiff = ((rr << 8) - colors[i].red); + int gdiff = ((gg << 8) - colors[i].green); + int bdiff = ((bb << 8) - colors[i].blue); + int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff); + if (sum < max) + { + index = i; max = sum; + } + } + } + else + { + // assume 8-bit true or static colors. this really exists + index = (r >> (5 - m_visualRedPrec)) << m_visualRedShift; + index |= (g >> (5 - m_visualGreenPrec)) << m_visualGreenShift; + index |= (b >> (5 - m_visualBluePrec)) << m_visualBlueShift; + } + m_colorCube[ (r*1024) + (g*32) + b ] = index; + } + } + } +#endif + return TRUE; } @@ -813,14 +1136,24 @@ WXColormap wxApp::GetMainColormap(WXDisplay* display) Window wxGetWindowParent(Window window) { wxASSERT_MSG( window, "invalid window" ); - + return (Window) 0; Window parent, root = 0; +#if wxUSE_NANOX + int noChildren = 0; +#else unsigned int noChildren = 0; +#endif Window* children = NULL; - int res = XQueryTree((Display*) wxGetDisplay(), window, & root, & parent, - & children, & noChildren); + + // #define XQueryTree(d,w,r,p,c,nc) GrQueryTree(w,p,c,nc) + int res = 1; +#if !wxUSE_NANOX + res = +#endif + XQueryTree((Display*) wxGetDisplay(), window, & root, & parent, + & children, & noChildren); if (children) XFree(children); if (res) @@ -861,25 +1194,43 @@ bool wxApp::Yield(bool onlyIfNeeded) s_inYield = TRUE; + // Make sure we have an event loop object, + // or Pending/Dispatch will fail + wxEventLoop* eventLoop = wxEventLoop::GetActive(); + wxEventLoop* newEventLoop = NULL; + if (!eventLoop) + { + newEventLoop = new wxEventLoop; + wxEventLoop::SetActive(newEventLoop); + } + while (wxTheApp && wxTheApp->Pending()) wxTheApp->Dispatch(); +#if wxUSE_TIMER + wxTimer::NotifyTimers(); +#endif + ProcessIdle(); + + if (newEventLoop) + { + wxEventLoop::SetActive(NULL); + delete newEventLoop; + } + s_inYield = FALSE; return TRUE; } -wxIcon wxApp::GetStdIcon(int which) const -{ - return wxTheme::Get()->GetRenderer()->GetStdIcon(which); -} +#ifdef __WXDEBUG__ -void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg) +void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg) { // While the GUI isn't working that well, just print out the // message. -#if 0 - wxAppBase::OnAssert(file, line, msg); +#if 1 + wxAppBase::OnAssert(file, line, cond, msg); #else wxString msg2; msg2.Printf("At file %s:%d: %s", file, line, msg); @@ -887,3 +1238,5 @@ void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg) #endif } +#endif // __WXDEBUG__ +