X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/065722d7b13d2dde15f536591f80567c489c561a..b5a8b32f50f7a5550dc9602236b9c7b49ba5e02c:/src/x11/app.cpp diff --git a/src/x11/app.cpp b/src/x11/app.cpp index 431e76420f..dfdb222158 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -30,6 +30,8 @@ #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 @@ -103,6 +105,10 @@ 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 @@ -149,7 +155,7 @@ void wxApp::CleanUp() wxTheColourDatabase = NULL; wxDeleteStockObjects(); - + wxDeleteStockLists(); delete wxTheApp; @@ -264,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()) @@ -396,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() @@ -432,22 +454,22 @@ struct wxExposeInfo 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 @@ -463,14 +485,16 @@ bool wxApp::ProcessXEvent(WXEvent* _event) wxWindow* win = NULL; 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 // Window and wxWindow, so if it's not in the table, // it must have been destroyed. - + win = wxGetWindowFromTable(window); if (!win) { @@ -484,13 +508,13 @@ bool wxApp::ProcessXEvent(WXEvent* _event) #ifdef __WXDEBUG__ wxString windowClass = win->GetClassInfo()->GetClassName(); #endif - + switch (event->type) { case Expose: { -#if wxUSE_TWO_WINDOWS - if (event->xexpose.window != (Window)win->GetClientWindow()) +#if wxUSE_TWO_WINDOWS && !wxUSE_NANOX + if (event->xexpose.window != (Window)win->GetClientAreaWindow()) { XEvent tmp_event; wxExposeInfo info; @@ -507,7 +531,6 @@ bool wxApp::ProcessXEvent(WXEvent* _event) { win->GetUpdateRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), XExposeEventGetWidth(event), XExposeEventGetHeight(event)); - win->GetClearRegion().Union( XExposeEventGetX(event), XExposeEventGetY(event), XExposeEventGetWidth(event), XExposeEventGetHeight(event)); @@ -520,12 +543,20 @@ bool wxApp::ProcessXEvent(WXEvent* _event) { win->GetUpdateRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, tmp_event.xexpose.width, tmp_event.xexpose.height ); - + win->GetClearRegion().Union( tmp_event.xexpose.x, tmp_event.xexpose.y, tmp_event.xexpose.width, tmp_event.xexpose.height ); } #endif - if (win->GetMainWindow() == win->GetClientWindow()) + + // 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. @@ -535,25 +566,27 @@ bool wxApp::ProcessXEvent(WXEvent* _event) return TRUE; } - + #if !wxUSE_NANOX case GraphicsExpose: { - // wxLogDebug( "GraphicsExpose from %s", win->GetName().c_str(), - // event->xgraphicsexpose.x, event->xgraphicsexpose.y, - // event->xgraphicsexpose.width, event->xgraphicsexpose.height); - + printf( "GraphicExpose event\n" ); + + 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) { // Only erase background, paint in idle time. win->SendEraseEvents(); - //win->Update(); + // win->Update(); } return TRUE; @@ -567,17 +600,17 @@ bool wxApp::ProcessXEvent(WXEvent* _event) 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)) ) { @@ -600,7 +633,7 @@ bool wxApp::ProcessXEvent(WXEvent* _event) wxKeyEvent keyEvent(wxEVT_KEY_UP); wxTranslateKeyEvent(keyEvent, win, window, event); - + return win->GetEventHandler()->ProcessEvent( keyEvent ); } case ConfigureNotify: @@ -609,6 +642,13 @@ bool wxApp::ProcessXEvent(WXEvent* _event) if (event->update.utype == GR_UPDATE_SIZE) #endif { + 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; @@ -618,7 +658,7 @@ bool wxApp::ProcessXEvent(WXEvent* _event) { wxSizeEvent sizeEvent( wxSize(XConfigureEventGetWidth(event), XConfigureEventGetHeight(event)), win->GetId() ); sizeEvent.SetEventObject( win ); - + return win->GetEventHandler()->ProcessEvent( sizeEvent ); } } @@ -668,14 +708,14 @@ bool wxApp::ProcessXEvent(WXEvent* _event) case ResizeRequest: { 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)); - + wxSize sz = win->GetSize(); wxSizeEvent sizeEvent(sz, win->GetId()); sizeEvent.SetEventObject(win); @@ -712,7 +752,7 @@ bool wxApp::ProcessXEvent(WXEvent* _event) tlw = tlw->GetParent(); if (tlw && !tlw->IsEnabled()) return FALSE; - + if (event->type == ButtonPress) { if ((win != wxWindow::FindFocus()) && win->AcceptsFocus()) @@ -721,11 +761,20 @@ bool wxApp::ProcessXEvent(WXEvent* _event) // 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(); } } - + #if !wxUSE_NANOX if (event->type == LeaveNotify || event->type == EnterNotify) { @@ -745,14 +794,26 @@ bool wxApp::ProcessXEvent(WXEvent* _event) (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); - focusEvent.SetWindow( g_prevFocus ); - g_prevFocus = NULL; + wxLogTrace( _T("focus"), _T("FocusIn from %s of type %s"), win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); - return 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; @@ -764,8 +825,8 @@ bool wxApp::ProcessXEvent(WXEvent* _event) (event->xfocus.mode == NotifyNormal)) #endif { - // wxLogDebug( "FocusOut from %s of type %s", win->GetName().c_str(), win->GetClassInfo()->GetClassName() ); - + 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); focusEvent.SetWindow( g_nextFocus ); @@ -888,8 +949,6 @@ bool wxApp::SendIdleEvents(wxWindow* win) win->GetEventHandler()->ProcessEvent(event); - win->OnInternalIdle(); - if (event.MoreRequested()) needMore = TRUE; @@ -902,7 +961,9 @@ bool wxApp::SendIdleEvents(wxWindow* win) node = node->Next(); } - + + win->OnInternalIdle(); + return needMore; } @@ -924,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() { @@ -931,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; } @@ -961,7 +1136,7 @@ WXColormap wxApp::GetMainColormap(WXDisplay* display) Window wxGetWindowParent(Window window) { wxASSERT_MSG( window, "invalid window" ); - + return (Window) 0; Window parent, root = 0; @@ -1048,12 +1223,14 @@ bool wxApp::Yield(bool onlyIfNeeded) return TRUE; } -void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg) +#ifdef __WXDEBUG__ + +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); @@ -1061,3 +1238,5 @@ void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg) #endif } +#endif // __WXDEBUG__ +