From 882b99e9a7e4725d560c06f84469664aec7fe933 Mon Sep 17 00:00:00 2001 From: Isaac Dunham Date: Sun, 9 Nov 2014 12:34:22 -0800 Subject: main/motif: move from testing --- main/motif/18-updated-fix-1565.patch | 431 +++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 main/motif/18-updated-fix-1565.patch (limited to 'main/motif/18-updated-fix-1565.patch') diff --git a/main/motif/18-updated-fix-1565.patch b/main/motif/18-updated-fix-1565.patch new file mode 100644 index 0000000000..850a6e2fbd --- /dev/null +++ b/main/motif/18-updated-fix-1565.patch @@ -0,0 +1,431 @@ +Description: Updated fix for upstream bug #1565 + This patch fixes the problem introduced by fix #1565, included in + Motif 2.3.4, which breaks keyboard navigation in menus. +Author: Olexiy Chernyavskyy +Origin: upstream, http://bugs.motifzone.net/show_bug.cgi?id=1565 +Bug: http://bugs.motifzone.net/show_bug.cgi?id=1630 +Bug-Debian: http://bugs.debian.org/730026 +Last-Update: 2013-11-29 +--- a/lib/Xm/ComboBox.c ++++ b/lib/Xm/ComboBox.c +@@ -3164,6 +3164,9 @@ + Arg args[4]; + ArgList merged_args; + Cardinal n; ++#ifdef FIX_1565 ++ XmGrabShellWidget grabsh; ++#endif + + n = 0; + XtSetArg(args[n], XmNlayoutDirection, LayoutM(parent)), n++; +@@ -3175,6 +3178,11 @@ + merged_args, n + *num_args); + XtFree((char*)merged_args); + ++#ifdef FIX_1565 ++ grabsh = (XmGrabShellWidget) shell; ++ grabsh->grab_shell.set_input_focus = False; ++#endif ++ + return shell; + } + +--- a/lib/Xm/DropDown.c ++++ b/lib/Xm/DropDown.c +@@ -2027,6 +2027,9 @@ + Arg *new_list, largs[10]; + Cardinal num_largs; + Widget sb; ++#ifdef FIX_1565 ++ XmGrabShellWidget grabsh; ++#endif + + num_largs = 0; + XtSetArg(largs[num_largs], XmNoverrideRedirect, True); num_largs++; +@@ -2040,6 +2043,10 @@ + xmGrabShellWidgetClass, w, + new_list, + num_largs + num_args); ++#ifdef FIX_1565 ++ grabsh = (XmGrabShellWidget) XmDropDown_popup_shell(cbw); ++ grabsh->grab_shell.set_input_focus = False; ++#endif + XtFree((char *) new_list); + + #ifdef FIX_1446 +--- a/lib/Xm/GrabShell.c ++++ b/lib/Xm/GrabShell.c +@@ -283,6 +283,10 @@ + + /* CR 9920: Popdown may be requested before MapNotify. */ + grabsh->grab_shell.mapped = False; ++ ++#ifdef FIX_1565 ++ grabsh->grab_shell.set_input_focus = True; ++#endif + } + + /* +@@ -395,8 +399,16 @@ + XGetInputFocus(XtDisplay(shell), &grabshell->grab_shell.old_focus, + &grabshell->grab_shell.old_revert_to); + old_handler = XSetErrorHandler(IgnoreXErrors); +- XSetInputFocus(XtDisplay(shell), XtWindow(shell), RevertToParent, time); +- XSync(XtDisplay(shell), False); ++#ifdef FIX_1565 ++ if (! grabshell->grab_shell.set_input_focus) { ++ XmForceGrabKeyboard(shell, time); ++ } else { ++#endif ++ XSetInputFocus(XtDisplay(shell), XtWindow(shell), RevertToParent, time); ++ XSync(XtDisplay(shell), False); ++#ifdef FIX_1565 ++ } ++#endif + XSetErrorHandler(old_handler); + } + +--- a/lib/Xm/GrabShellP.h ++++ b/lib/Xm/GrabShellP.h +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include "XmI.h" + + #ifdef __cplusplus + extern "C" { +@@ -55,6 +56,9 @@ + Boolean mapped; + Window old_focus; + int old_revert_to; ++#ifdef FIX_1565 ++ Boolean set_input_focus; ++#endif + } XmGrabShellPart; + + +--- a/lib/Xm/MenuShell.c ++++ b/lib/Xm/MenuShell.c +@@ -1514,9 +1514,7 @@ + + /** the real grab ***/ + _XmMenuGrabKeyboardAndPointer((Widget)rowcol, _time); +-#ifndef FIX_1565 + _XmMenuFocus(XtParent(rowcol), XmMENU_BEGIN, _time); +-#endif + + /* To support menu replay, keep the pointer in sync mode */ + XAllowEvents(XtDisplay(rowcol), SyncPointer, CurrentTime); +--- a/lib/Xm/MenuUtil.c ++++ b/lib/Xm/MenuUtil.c +@@ -1053,11 +1053,7 @@ + + register int status = + (_XmGrabKeyboard(widget, +-#ifdef FIX_1565 +- False, +-#else + True, +-#endif + GrabModeSync, + GrabModeAsync, + time) != GrabSuccess); +--- a/lib/Xm/RCMenu.c ++++ b/lib/Xm/RCMenu.c +@@ -85,6 +85,9 @@ + #include "TraversalI.h" + #include "UniqueEvnI.h" + #include "VendorSI.h" ++#ifdef FIX_1565 ++#include ++#endif + + #define FIX_1535 + +@@ -943,6 +946,13 @@ + XmMenuState mst = _XmGetMenuState((Widget)w); + Window tmpWindow; + int tmpRevert; ++#ifdef FIX_1565 ++ Widget shell; ++ ++ shell = w; ++ while (! XtIsSubclass(shell, shellWidgetClass)) ++ shell = XtParent(shell); ++#endif + + if (_time == CurrentTime) + _time = XtLastTimestampProcessed(XtDisplay(w)); +@@ -983,6 +993,11 @@ + shell.popped_up)) + **/ + { ++#ifdef FIX_1565 ++ if (XtIsSubclass(shell, xmGrabShellWidgetClass) || XtIsSubclass(shell, xmMenuShellWidgetClass)) ++ XmForceGrabKeyboard(w, _time); ++ else ++#endif + SetInputFocus(XtDisplay(w), mst->RC_menuFocus.oldFocus, + mst->RC_menuFocus.oldRevert, + mst->RC_menuFocus.oldTime); +@@ -996,6 +1011,11 @@ + */ + else + { ++#ifdef FIX_1565 ++ if (XtIsSubclass(shell, xmGrabShellWidgetClass) || XtIsSubclass(shell, xmMenuShellWidgetClass)) ++ XmForceGrabKeyboard(w, _time); ++ else ++#endif + SetInputFocus(XtDisplay(w), mst->RC_menuFocus.oldFocus, + mst->RC_menuFocus.oldRevert, + mst->RC_menuFocus.oldTime); +@@ -1014,6 +1034,11 @@ + RC_menuFocus.oldFocus); + mst->RC_menuFocus.oldTime = _time - 1; + ++#ifdef FIX_1565 ++ if (XtIsSubclass(shell, xmGrabShellWidgetClass) || XtIsSubclass(shell, xmMenuShellWidgetClass)) ++ XmForceGrabKeyboard(w, _time); ++ else ++#endif + SetInputFocus(XtDisplay(w), XtWindow(w), mst->RC_menuFocus.oldRevert, + mst->RC_menuFocus.oldTime); + +@@ -1027,6 +1052,11 @@ + XGetInputFocus(XtDisplay(w), &tmpWindow, &tmpRevert); + if (tmpWindow != XtWindow(w)) + { ++#ifdef FIX_1565 ++ if (XtIsSubclass(shell, xmGrabShellWidgetClass) || XtIsSubclass(shell, xmMenuShellWidgetClass)) ++ XmForceGrabKeyboard(w, _time); ++ else ++#endif + SetInputFocus(XtDisplay(w), XtWindow(w), tmpRevert, _time); + + mst->RC_menuFocus.oldRevert = tmpRevert; +@@ -1048,6 +1078,11 @@ + + break; + case XmMENU_MIDDLE: ++#ifdef FIX_1565 ++ if (XtIsSubclass(shell, xmGrabShellWidgetClass) || XtIsSubclass(shell, xmMenuShellWidgetClass)) ++ XmForceGrabKeyboard(w, _time); ++ else ++#endif + SetInputFocus(XtDisplay(w), XtWindow(w), + mst->RC_menuFocus.oldRevert, + mst->RC_menuFocus.oldTime); +@@ -1062,6 +1097,11 @@ + if ((tmpWindow != XtWindow(w)) && + (_time > mst->RC_menuFocus.oldTime)) + { ++#ifdef FIX_1565 ++ if (XtIsSubclass(shell, xmGrabShellWidgetClass) || XtIsSubclass(shell, xmMenuShellWidgetClass)) ++ XmForceGrabKeyboard(w, _time); ++ else ++#endif + SetInputFocus(XtDisplay(w), XtWindow(w), tmpRevert, _time); + + mst->RC_menuFocus.oldRevert = tmpRevert; +--- a/lib/Xm/Xm.c ++++ b/lib/Xm/Xm.c +@@ -40,6 +40,10 @@ + #ifdef FIX_345 + #include + #endif ++#ifdef FIX_1565 ++#include ++#include ++#endif + + + /************************************************************************** +@@ -530,3 +534,173 @@ + return p; + } + #endif ++ ++#ifdef FIX_1565 ++ ++typedef struct _GrabData GrabData; ++struct _GrabData { ++ Widget w; ++ GrabData *next; ++}; ++ ++static void _XmSendFocusEvent(Widget child, int type); ++static void _XmStartDispatcher(Display *display); ++static Boolean _XmEventDispatcher(XEvent *event); ++static void UnmapHandler(Widget w, XtPointer client_data, XEvent *event, Boolean *cont); ++static Boolean _UngrabKeyboard(Widget w); ++ ++static GrabData *grabw_top = NULL; ++static int xm_dispatcher_on = 0; ++static XtEventDispatchProc saved_dispatcher_proc = NULL; ++static XtEventDispatchProc xt_dispatcher_proc = NULL; ++ ++/* ++ XmForceGrabKeyboard function is defined to be a substitutor of XSetInputFocus calls ++ for popup and pulldown menus that should grab keyboard focus yet main window at the ++ same time should visually stay in focus for window manager. This resolves focus flip ++ issue when popup or pulldown menu is raised. ~ochern ++ */ ++void XmForceGrabKeyboard(Widget w, Time time) ++{ ++ GrabData *grabw; ++ ++ if (!w) ++ return; ++ ++ while (! XtIsSubclass(w, shellWidgetClass)) ++ w = XtParent(w); ++ ++ if (! (XtIsSubclass(w, xmGrabShellWidgetClass) || XtIsSubclass(w, xmMenuShellWidgetClass))) ++ return; ++ ++ _XmStartDispatcher(XtDisplay(w)); ++ ++ _UngrabKeyboard(w); ++ ++ grabw = (GrabData *) XtMalloc(sizeof(GrabData)); ++ grabw->w = w; ++ _XmProcessLock(); ++ grabw->next = grabw_top; ++ grabw_top = grabw; ++ _XmProcessUnlock(); ++ ++ XtInsertEventHandler(w, StructureNotifyMask, False, UnmapHandler, NULL, XtListHead); ++ ++ _XmSendFocusEvent(w, FocusIn); ++ ++ /* Following the XSetInputFocus behaviour we force sending FocusOut (see XGrabKeyboard(3)) ++ event to a previous keyboard holder */ ++ XtGrabKeyboard(w, True, GrabModeAsync, GrabModeAsync, time); ++} ++ ++static void _XmStartDispatcher(Display *display) ++{ ++ if (!display) ++ return; ++ ++ _XmProcessLock(); ++ ++ if (xm_dispatcher_on) { ++ _XmProcessUnlock(); ++ return; ++ } ++ ++ saved_dispatcher_proc = XtSetEventDispatcher(display, KeyPress, _XmEventDispatcher); ++ if (! xt_dispatcher_proc) ++ xt_dispatcher_proc = saved_dispatcher_proc; ++ XtSetEventDispatcher(display, KeyRelease, _XmEventDispatcher); ++ xm_dispatcher_on = 1; ++ ++ _XmProcessUnlock(); ++} ++ ++static Boolean _XmEventDispatcher(XEvent *event) ++{ ++ _XmProcessLock(); ++ if (grabw_top) { ++ if (event->type == KeyPress || event->type == KeyRelease) ++ event->xany.window = XtWindow(grabw_top->w); ++ } ++ _XmProcessUnlock(); ++ ++ if (saved_dispatcher_proc) { ++ return (*saved_dispatcher_proc)(event); ++ } else if (xt_dispatcher_proc) { ++ return (*xt_dispatcher_proc)(event); ++ } else { ++ if (grabw_top) ++ XtSetEventDispatcher(XtDisplay(grabw_top->w), event->type, NULL); ++ return XtDispatchEvent(event); ++ } ++} ++ ++static void UnmapHandler(Widget w, XtPointer client_data, XEvent *event, Boolean *cont) ++{ ++ if (event->type == UnmapNotify) ++ _UngrabKeyboard(w); ++ if (! grabw_top) { ++ XtSetEventDispatcher(XtDisplay(w), KeyPress, saved_dispatcher_proc); ++ XtSetEventDispatcher(XtDisplay(w), KeyRelease, saved_dispatcher_proc); ++ xm_dispatcher_on = 0; ++ } ++ ++ /* we do not call XtUngrabKeyboard since X server automatically performs an ++ UngrabKeyboard request if the event window for an active keyboard grab becomes ++ not viewable. ~ochern */ ++} ++ ++static Boolean _UngrabKeyboard(Widget w) ++{ ++ GrabData *grabw, *grabw_prev; ++ ++ _XmProcessLock(); ++ if (! grabw_top) { ++ _XmProcessUnlock(); ++ return False; ++ } ++ ++ grabw = grabw_top; ++ grabw_prev = NULL; ++ while(grabw && grabw->w != w) { ++ grabw_prev = grabw; ++ grabw = grabw->next; ++ } ++ if (grabw) { ++ if (grabw_prev) ++ grabw_prev->next = grabw->next; ++ else ++ grabw_top = grabw->next; ++ XtFree((char*) grabw); ++ ++ _XmProcessUnlock(); ++ return True; ++ } ++ ++ _XmProcessUnlock(); ++ return False; ++} ++ ++static void _XmSendFocusEvent(Widget child, int type) ++{ ++ child = XtIsWidget(child) ? child : _XtWindowedAncestor(child); ++ if (XtIsSensitive(child) && !child->core.being_destroyed ++ && XtIsRealized(child) && (XtBuildEventMask(child) & FocusChangeMask)) ++ { ++ XFocusChangeEvent event; ++ Display* dpy = XtDisplay (child); ++ ++ event.type = type; ++ event.serial = LastKnownRequestProcessed(dpy); ++ event.send_event = True; ++ event.display = dpy; ++ event.window = XtWindow(child); ++ event.mode = NotifyNormal; ++ event.detail = NotifyAncestor; ++ if (XFilterEvent((XEvent*)&event, XtWindow(child))) ++ return; ++ XtDispatchEventToWidget(child, (XEvent*)&event); ++ } ++} ++ ++#endif ++ +--- a/lib/Xm/XmI.h ++++ b/lib/Xm/XmI.h +@@ -242,7 +242,9 @@ + extern XChar2b* _XmUtf8ToUcs2(char *draw_text, + size_t seg_len, + size_t *ret_str_len); +- ++#ifdef FIX_1565 ++extern void XmForceGrabKeyboard(Widget w, Time time); ++#endif + + /******** End Private Function Declarations ********/ + -- cgit v1.2.3