aboutsummaryrefslogtreecommitdiffstats
path: root/main/motif/18-updated-fix-1565.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/motif/18-updated-fix-1565.patch')
-rw-r--r--main/motif/18-updated-fix-1565.patch431
1 files changed, 431 insertions, 0 deletions
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 <ochern@ics.com>
+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 <Xm/GrabShell.h>
+ #include <Xm/XmP.h>
+ #include <X11/ShellP.h>
++#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 <Xm/GrabShell.h>
++#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 <X11/keysym.h>
+ #endif
++#ifdef FIX_1565
++#include <Xm/GrabShell.h>
++#include <Xm/MenuShell.h>
++#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 ********/
+