X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/45ff6421e6d0327584bb85aeb5bda8be48b6ca5e..02a1dfbae942c883d8651e34dcfbc5153aabc56e:/src/x11/app.cpp diff --git a/src/x11/app.cpp b/src/x11/app.cpp index a4d0c28487..1ca16bb8e2 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -17,19 +17,20 @@ #include "wx/app.h" #include "wx/utils.h" #include "wx/gdicmn.h" -#include "wx/pen.h" -#include "wx/brush.h" -#include "wx/cursor.h" #include "wx/icon.h" #include "wx/dialog.h" -#include "wx/msgdlg.h" #include "wx/log.h" #include "wx/module.h" #include "wx/memory.h" #include "wx/log.h" #include "wx/intl.h" #include "wx/evtloop.h" -#include "wx/cmdline.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" @@ -39,40 +40,38 @@ #include "wx/resource.h" #endif -#ifdef __VMS__ -#pragma message disable nosimpint -#endif -#include -#include -#include -#include -#ifdef __VMS__ -#pragma message enable nosimpint -#endif - #include "wx/x11/private.h" #include -extern wxList wxPendingDelete; +//------------------------------------------------------------------------ +// global data +//------------------------------------------------------------------------ -wxApp *wxTheApp = NULL; +extern wxList wxPendingDelete; wxHashTable *wxWidgetHashTable = NULL; +wxHashTable *wxClientWidgetHashTable = NULL; -IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) +wxApp *wxTheApp = NULL; -BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) - EVT_IDLE(wxApp::OnIdle) -END_EVENT_TABLE() +// 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; -static const wxCmdLineEntryDesc g_cmdLineDesc[] = -{ - { wxCMD_LINE_SWITCH, "sync", "sync", "synchronize the display" }, - { wxCMD_LINE_OPTION, "display", "display", "use the given display", wxCMD_LINE_VAL_STRING }, +// 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; - { wxCMD_LINE_NONE } -}; +//------------------------------------------------------------------------ +// X11 error handling +//------------------------------------------------------------------------ #ifdef __WXDEBUG__ typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *); @@ -82,13 +81,26 @@ 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; +IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) + +BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) + EVT_IDLE(wxApp::OnIdle) +END_EVENT_TABLE() + bool wxApp::Initialize() { wxClassInfo::InitializeClasses(); @@ -110,6 +122,7 @@ bool wxApp::Initialize() #endif wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER); + wxClientWidgetHashTable = new wxHashTable(wxKEY_INTEGER); wxModule::RegisterModules(); if (!wxModule::InitializeModules()) return FALSE; @@ -119,8 +132,14 @@ bool wxApp::Initialize() void wxApp::CleanUp() { + if (g_newArgv) + delete[] g_newArgv; + g_newArgv = NULL; + delete wxWidgetHashTable; wxWidgetHashTable = NULL; + delete wxClientWidgetHashTable; + wxClientWidgetHashTable = NULL; wxModule::CleanUpModules(); @@ -132,7 +151,7 @@ void wxApp::CleanUp() wxTheColourDatabase = NULL; wxDeleteStockObjects(); - + wxDeleteStockLists(); delete wxTheApp; @@ -152,7 +171,7 @@ void wxApp::CleanUp() // wxDebugContext, too. if (wxDebugContext::CountObjectsLeft(TRUE) > 0) { - wxLogDebug("There were memory leaks.\n"); + wxLogDebug("There were memory leaks."); wxDebugContext::Dump(); wxDebugContext::PrintStatistics(); } @@ -164,39 +183,95 @@ void wxApp::CleanUp() delete wxLog::SetActiveTarget(NULL); } -// This is set within wxEntryStart -- too early on -// to put these in wxTheApp -static int g_newArgc = 0; -static wxChar** g_newArgv = NULL; - // NB: argc and argv may be changed here, pass by reference! int wxEntryStart( int& argc, char *argv[] ) { #ifdef __WXDEBUG__ +#if !wxUSE_NANOX // install the X error handler gs_pfnXErrorHandler = XSetErrorHandler( wxXErrorHandler ); +#endif #endif // __WXDEBUG__ - /// TODO -#if 0 - // Parse the arguments. Is it OK to use the command line - // parser before calling Initialize? - wxCmdLineParser cmdLine(argv, argv); -#endif + wxString displayName; + bool syncDisplay = FALSE; + + // Parse the arguments. + // We can't use wxCmdLineParser or OnInitCmdLine and friends because + // we have to create the Display earlier. If we can find a way to + // use the wxAppBase API then I'll be quite happy to change it. + g_newArgv = new wxChar*[argc]; + g_newArgc = 0; + int i; + for (i = 0; i < argc; i++) + { + wxString arg(argv[i]); + if (arg == wxT("-display")) + { + if (i < (argc - 1)) + { + i ++; + displayName = argv[i]; + continue; + } + } + else if (arg == wxT("-geometry")) + { + if (i < (argc - 1)) + { + i ++; + wxString windowGeometry = argv[i]; + int w, h; + if (wxSscanf(windowGeometry.c_str(), _T("%dx%d"), &w, &h) != 2) + { + wxLogError(_("Invalid geometry specification '%s'"), windowGeometry.c_str()); + } + else + { + g_initialSize = wxSize(w, h); + } + continue; + } + } + else if (arg == wxT("-sync")) + { + syncDisplay = TRUE; + continue; + } + else if (arg == wxT("-iconic")) + { + g_showIconic = TRUE; - Display* xdisplay = XOpenDisplay(NULL); + continue; + } + + // Not eaten by wxWindows, so pass through + g_newArgv[g_newArgc] = argv[i]; + g_newArgc ++; + } + + Display* xdisplay = NULL; + if (displayName.IsEmpty()) + xdisplay = XOpenDisplay(NULL); + else + xdisplay = XOpenDisplay((char*) displayName.c_str()); if (!xdisplay) { wxLogError( _("wxWindows could not open display. Exiting.") ); return -1; } - + + if (syncDisplay) + { + XSynchronize(xdisplay, True); + } + wxApp::ms_display = (WXDisplay*) xdisplay; - + XSelectInput( xdisplay, XDefaultRootWindow(xdisplay), PropertyChangeMask); - -// wxSetDetectableAutoRepeat( TRUE ); + + wxSetDetectableAutoRepeat( TRUE ); if (!wxApp::Initialize()) return -1; @@ -204,7 +279,6 @@ int wxEntryStart( int& argc, char *argv[] ) return 0; } - int wxEntryInitGui() { int retValue = 0; @@ -263,6 +337,8 @@ int wxEntry( int argc, char *argv[] ) wxTheApp->argc = argc; wxTheApp->argv = argv; } + wxTheApp->m_showIconic = g_showIconic; + wxTheApp->m_initialSize = g_initialSize; int retValue; retValue = wxEntryInitGui(); @@ -320,6 +396,24 @@ wxApp::wxApp() m_topLevelWidget = (WXWindow) NULL; m_maxRequestSize = 0; 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() @@ -332,7 +426,7 @@ bool wxApp::Initialized() int wxApp::MainLoop() { - int rt; + int rt; m_mainLoop = new wxEventLoop; rt = m_mainLoop->Run(); @@ -342,21 +436,56 @@ 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 - // TODO: may need to translate coordinates from actualWindow - // to window, if the receiving window != wxWindow window - // while (window && !(win = wxGetWindowFromTable(window))) - // window = wxGetWindowParent(window); - // Because we're receiving events after a window // has been destroyed, assume a 1:1 match between // Window and wxWindow, so if it's not in the table, @@ -364,161 +493,322 @@ 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->GetClientWindow()) { - 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); - - // 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->GetClientWindow()) + win->NeedUpdateNcAreaInIdle(); + + // Only erase background, paint in idle time. + win->SendEraseEvents(); + // win->Update(); + } + + return TRUE; + } + +#if !wxUSE_NANOX + case GraphicsExpose: + { + printf( "GraphicExpose event\n" ); + + // 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) + { + // Only erase background, paint in idle time. + win->SendEraseEvents(); + // win->Update(); + } + + 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; + + return FALSE; } case KeyRelease: { - if (win && !win->IsEnabled()) - return; + if (!win->IsEnabled()) + return FALSE; - if (win) + wxKeyEvent keyEvent(wxEVT_KEY_UP); + wxTranslateKeyEvent(keyEvent, win, window, event); + + return win->GetEventHandler()->ProcessEvent( keyEvent ); + } + case ConfigureNotify: + { +#if wxUSE_NANOX + if (event->update.utype == GR_UPDATE_SIZE) +#endif { - wxKeyEvent keyEvent(wxEVT_KEY_UP); - wxTranslateKeyEvent(keyEvent, win, window, event); - - win->GetEventHandler()->ProcessEvent( keyEvent ); + 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; + return FALSE; + break; } +#if !wxUSE_NANOX case PropertyNotify: { - HandlePropertyChange(_event); - return; + //wxLogDebug("PropertyNotify: %s", windowClass.c_str()); + return HandlePropertyChange(_event); } case ClientMessage: - { - Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True);; - Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True);; + { + if (!win->IsEnabled()) + return FALSE; + + Atom wm_delete_window = XInternAtom(wxGlobalDisplay(), "WM_DELETE_WINDOW", True); + Atom wm_protocols = XInternAtom(wxGlobalDisplay(), "WM_PROTOCOLS", True); if (event->xclient.message_type == wm_protocols) { if ((Atom) (event->xclient.data.l[0]) == wm_delete_window) { - if (win) - { - win->Close(FALSE); - } + win->Close(FALSE); + return TRUE; } } - return; + return FALSE; } - case ConfigureNotify: +#if 0 + case DestroyNotify: { - if (win) - { - wxSizeEvent sizeEvent( wxSize(event->xconfigure.width,event->xconfigure.height), win->GetId() ); - sizeEvent.SetEventObject( win ); - - win->GetEventHandler()->ProcessEvent( sizeEvent ); - } + 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: { - /* Terry Gitnick - 1/21/98 - * 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)); - - // TODO: when implementing refresh optimization, we can use - // XtAddExposureToRegion to expand the window's paint region. - if (win) - { - wxSize sz = win->GetSize(); - wxSizeEvent sizeEvent(sz, win->GetId()); - sizeEvent.SetEventObject(win); + wxSize sz = win->GetSize(); + wxSizeEvent sizeEvent(sz, win->GetId()); + sizeEvent.SetEventObject(win); - win->GetEventHandler()->ProcessEvent( sizeEvent ); - } - - return; + return win->GetEventHandler()->ProcessEvent( sizeEvent ); } - case Expose: +#endif +#endif +#if wxUSE_NANOX + case GR_EVENT_TYPE_CLOSE_REQ: { if (win) { - // Schedule update for later - win->GetUpdateRegion().Union( event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); + win->Close(FALSE); + return TRUE; } - - return; + return FALSE; + break; } +#endif case EnterNotify: case LeaveNotify: case ButtonPress: case ButtonRelease: case MotionNotify: { - if (win && !win->IsEnabled()) - return; + if (!win->IsEnabled()) + 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()) + { + // This might actually be done in wxWindow::SetFocus() + // and not here. TODO. + g_prevFocus = wxWindow::FindFocus(); + g_nextFocus = win; - if (win) + win->SetFocus(); + } + } + +#if !wxUSE_NANOX + if (event->type == LeaveNotify || event->type == EnterNotify) { - wxMouseEvent wxevent; - wxTranslateMouseEvent(wxevent, win, window, event); - win->GetEventHandler()->ProcessEvent( wxevent ); + // Throw out NotifyGrab and NotifyUngrab + if (event->xcrossing.mode != NotifyNormal) + return FALSE; } - return; +#endif + wxMouseEvent wxevent; + wxTranslateMouseEvent(wxevent, win, window, event); + return win->GetEventHandler()->ProcessEvent( wxevent ); } case FocusIn: { - if (win && event->xfocus.detail != NotifyPointer) +#if !wxUSE_NANOX + if ((event->xfocus.detail != NotifyPointer) && + (event->xfocus.mode == NotifyNormal)) +#endif { + // wxLogDebug( "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); + focusEvent.SetWindow( g_prevFocus ); + g_prevFocus = NULL; + + return win->GetEventHandler()->ProcessEvent(focusEvent); } + return FALSE; break; } case FocusOut: { - if (win && event->xfocus.detail != NotifyPointer) +#if !wxUSE_NANOX + if ((event->xfocus.detail != NotifyPointer) && + (event->xfocus.mode == NotifyNormal)) +#endif { + // wxLogDebug( "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: @@ -527,9 +817,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. @@ -564,11 +856,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); /* let Motif do the work */ + // XtDispatchEvent((XEvent*) event); + return FALSE; } void wxApp::OnIdle(wxIdleEvent& event) @@ -631,8 +924,6 @@ bool wxApp::SendIdleEvents(wxWindow* win) win->GetEventHandler()->ProcessEvent(event); - win->OnInternalIdle(); - if (event.MoreRequested()) needMore = TRUE; @@ -645,7 +936,9 @@ bool wxApp::SendIdleEvents(wxWindow* win) node = node->Next(); } - + + win->OnInternalIdle(); + return needMore; } @@ -667,21 +960,135 @@ void wxApp::DeletePendingObjects() } } -// Create an application context +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() { // Eventually this line will be removed, but for // 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; } @@ -703,11 +1110,25 @@ 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) @@ -748,54 +1169,40 @@ 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(); - s_inYield = FALSE; - - return TRUE; -} - -// TODO use XmGetPixmap (?) to get the really standard icons! - -// XPM hack: make the arrays const -#define static static const - -#include "wx/generic/info.xpm" -#include "wx/generic/error.xpm" -#include "wx/generic/question.xpm" -#include "wx/generic/warning.xpm" - -#undef static +#if wxUSE_TIMER + wxTimer::NotifyTimers(); +#endif + ProcessIdle(); -wxIcon -wxApp::GetStdIcon(int which) const -{ - switch(which) + if (newEventLoop) { - case wxICON_INFORMATION: - return wxIcon(info_xpm); - - case wxICON_QUESTION: - return wxIcon(question_xpm); - - case wxICON_EXCLAMATION: - return wxIcon(warning_xpm); + wxEventLoop::SetActive(NULL); + delete newEventLoop; + } - default: - wxFAIL_MSG("requested non existent standard icon"); - // still fall through + s_inYield = FALSE; - case wxICON_HAND: - return wxIcon(error_xpm); - } + return TRUE; } void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg) { // While the GUI isn't working that well, just print out the // message. -#if 0 +#if 1 wxAppBase::OnAssert(file, line, msg); #else wxString msg2;