+bool wxWindow::ProcessAccelerator(wxKeyEvent& event)
+{
+ if (!m_acceleratorTable.Ok())
+ return FALSE;
+
+ int count = m_acceleratorTable.GetCount();
+ wxAcceleratorEntry* entries = m_acceleratorTable.GetEntries();
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ wxAcceleratorEntry* entry = & (entries[i]);
+ if (entry->MatchesEvent(event))
+ {
+ // Bingo, we have a match. Now find a control that matches the
+ // entry command id.
+
+ // Need to go up to the top of the window hierarchy, since it might
+ // be e.g. a menu item
+ wxWindow* parent = this;
+ while ( parent && !parent->IsTopLevel() )
+ parent = parent->GetParent();
+
+ if (!parent)
+ return FALSE;
+
+ wxFrame* frame = wxDynamicCast(parent, wxFrame);
+ if ( frame )
+ {
+ // Try for a menu command
+ if (frame->GetMenuBar())
+ {
+ wxMenuItem* item = frame->GetMenuBar()->FindItem(entry->GetCommand());
+ if (item)
+ {
+ wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, entry->GetCommand());
+ commandEvent.SetEventObject(frame);
+
+ // If ProcessEvent returns TRUE (it was handled), then
+ // the calling code will skip the event handling.
+ return frame->GetEventHandler()->ProcessEvent(commandEvent);
+ }
+ }
+ }
+
+ // Find a child matching the command id
+ wxWindow* child = parent->FindWindow(entry->GetCommand());
+
+ // No such child
+ if (!child)
+ return FALSE;
+
+ // Now we process those kinds of windows that we can.
+ // For now, only buttons.
+ if ( wxDynamicCast(child, wxButton) )
+ {
+ wxCommandEvent commandEvent (wxEVT_COMMAND_BUTTON_CLICKED, child->GetId());
+ commandEvent.SetEventObject(child);
+ return child->GetEventHandler()->ProcessEvent(commandEvent);
+ }
+
+ return FALSE;
+ } // matches event
+ }// for
+
+ // We didn't match the key event against an accelerator.
+ return FALSE;
+}
+
+// ============================================================================
+// Motif-specific stuff from here on
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// function which maintain the global hash table mapping Widgets to wxWindows
+// ----------------------------------------------------------------------------
+
+bool wxAddWindowToTable(Widget w, wxWindow *win)
+{
+ wxWindow *oldItem = NULL;
+ if ((oldItem = (wxWindow *)wxWidgetHashTable->Get ((long) w)))
+ {
+ wxLogDebug("Widget table clash: new widget is %ld, %s",
+ (long)w, win->GetClassInfo()->GetClassName());
+ return FALSE;
+ }
+
+ wxWidgetHashTable->Put((long) w, win);
+
+ wxLogTrace("widget", "Widget 0x%08x <-> window %p (%s)",
+ w, win, win->GetClassInfo()->GetClassName());
+
+ return TRUE;
+}
+
+wxWindow *wxGetWindowFromTable(Widget w)
+{
+ return (wxWindow *)wxWidgetHashTable->Get((long) w);
+}
+
+void wxDeleteWindowFromTable(Widget w)
+{
+ wxWidgetHashTable->Delete((long)w);
+}
+
+// ----------------------------------------------------------------------------
+// add/remove window from the table
+// ----------------------------------------------------------------------------
+
+// Add to hash table, add event handler
+bool wxWindow::AttachWidget (wxWindow* WXUNUSED(parent), WXWidget mainWidget,
+ WXWidget formWidget, int x, int y, int width, int height)
+{
+ wxAddWindowToTable((Widget) mainWidget, this);
+ if (CanAddEventHandler())
+ {
+ XtAddEventHandler((Widget) mainWidget,
+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
+ False,
+ wxPanelItemEventHandler,
+ (XtPointer) this);
+ }
+
+ if (!formWidget)
+ {
+ XtTranslations ptr;
+ XtOverrideTranslations ((Widget) mainWidget,
+ ptr = XtParseTranslationTable ("<Configure>: resize()"));
+ XtFree ((char *) ptr);
+ }
+
+ // Some widgets have a parent form widget, e.g. wxRadioBox
+ if (formWidget)
+ {
+ if (!wxAddWindowToTable((Widget) formWidget, this))
+ return FALSE;
+
+ XtTranslations ptr;
+ XtOverrideTranslations ((Widget) formWidget,
+ ptr = XtParseTranslationTable ("<Configure>: resize()"));
+ XtFree ((char *) ptr);
+ }
+
+ if (x == -1)
+ x = 0;
+ if (y == -1)
+ y = 0;
+ SetSize (x, y, width, height);
+
+ return TRUE;
+}
+
+// Remove event handler, remove from hash table
+bool wxWindow::DetachWidget(WXWidget widget)
+{
+ if (CanAddEventHandler())
+ {
+ XtRemoveEventHandler((Widget) widget,
+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask, // | KeyPressMask,
+ False,
+ wxPanelItemEventHandler,
+ (XtPointer)this);
+ }
+
+ wxDeleteWindowFromTable((Widget) widget);
+ return TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// Motif-specific accessors
+// ----------------------------------------------------------------------------
+
+// Get the underlying X window
+WXWindow wxWindow::GetXWindow() const
+{
+ Widget wMain = (Widget)GetMainWidget();
+ if ( wMain )
+ return (WXWindow) XtWindow(wMain);
+ else
+ return (WXWindow) 0;
+}
+
+// Get the underlying X display
+WXDisplay *wxWindow::GetXDisplay() const
+{
+ Widget wMain = (Widget)GetMainWidget();
+ if ( wMain )
+ return (WXDisplay*) XtDisplay(wMain);
+ else
+ return (WXDisplay*) NULL;
+}
+
+WXWidget wxWindow::GetMainWidget() const
+{
+ if (m_drawingArea)
+ return m_drawingArea;
+ else
+ return m_mainWidget;
+}
+
+WXWidget wxWindow::GetClientWidget() const
+{
+ if (m_drawingArea != (WXWidget) 0)
+ return m_drawingArea;
+ else
+ return GetMainWidget();
+}
+
+WXWidget wxWindow::GetTopWidget() const
+{
+ return GetMainWidget();
+}
+
+WXWidget wxWindow::GetLabelWidget() const
+{
+ return GetMainWidget();
+}
+
+// ----------------------------------------------------------------------------
+// Motif callbacks
+// ----------------------------------------------------------------------------
+
+// All widgets should have this as their resize proc.
+// OnSize sent to wxWindow via client data.
+void wxWidgetResizeProc(Widget w, XConfigureEvent *WXUNUSED(event), String WXUNUSED(args)[], int *WXUNUSED(num_args))
+{
+ wxWindow *win = wxGetWindowFromTable(w);
+ if (!win)
+ return;
+
+ if (win->PreResize())
+ {
+ int width, height;
+ win->GetSize(&width, &height);
+ wxSizeEvent sizeEvent(wxSize(width, height), win->GetId());
+ sizeEvent.SetEventObject(win);
+ win->GetEventHandler()->ProcessEvent(sizeEvent);
+ }
+}
+
+static void wxCanvasRepaintProc(Widget drawingArea,
+ XtPointer clientData,
+ XmDrawingAreaCallbackStruct * cbs)
+{
+ if (!wxGetWindowFromTable(drawingArea))
+ return;
+
+ XEvent * event = cbs->event;
+ wxWindow * win = (wxWindow *) clientData;
+
+ switch (event->type)
+ {
+ case Expose:
+ {
+ win->AddUpdateRect(event->xexpose.x, event->xexpose.y,
+ event->xexpose.width, event->xexpose.height);
+
+ if (event -> xexpose.count == 0)
+ {
+ win->DoPaint();
+ win->ClearUpdateRects();
+ }
+ break;
+ }
+ }
+}
+
+// Unable to deal with Enter/Leave without a separate EventHandler (Motif 1.1.4)
+static void wxCanvasEnterLeave(Widget drawingArea,
+ XtPointer WXUNUSED(clientData),
+ XCrossingEvent * event)
+{
+ XmDrawingAreaCallbackStruct cbs;
+ XEvent ev;
+
+ ((XCrossingEvent &) ev) = *event;
+
+ cbs.reason = XmCR_INPUT;
+ cbs.event = &ev;
+
+ wxCanvasInputEvent(drawingArea, (XtPointer) NULL, &cbs);
+}
+
+// Fix to make it work under Motif 1.0 (!)
+static void wxCanvasMotionEvent (Widget WXUNUSED(drawingArea), XButtonEvent * WXUNUSED(event))
+{
+#if XmVersion <= 1000
+ XmDrawingAreaCallbackStruct cbs;
+ XEvent ev;
+
+ ev = *((XEvent *) event);
+ cbs.reason = XmCR_INPUT;
+ cbs.event = &ev;
+
+ wxCanvasInputEvent (drawingArea, (XtPointer) NULL, &cbs);
+#endif // XmVersion <= 1000
+}
+
+static void wxCanvasInputEvent(Widget drawingArea,
+ XtPointer WXUNUSED(data),
+ XmDrawingAreaCallbackStruct * cbs)
+{
+ wxWindow *canvas = wxGetWindowFromTable(drawingArea);
+ XEvent local_event;
+
+ if (canvas==NULL)
+ return;
+
+ if (cbs->reason != XmCR_INPUT)
+ return;
+
+ local_event = *(cbs->event); // We must keep a copy!
+
+ switch (local_event.xany.type)