Bug 22004 - no keyboard shortcuts for switching between pages of MultiPageEditorPart
Summary: no keyboard shortcuts for switching between pages of MultiPageEditorPart
Status: CLOSED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P1 normal (vote)
Target Milestone: 2.0.2   Edit
Assignee: Steve Northover CLA
QA Contact:
URL:
Whiteboard:
Keywords: accessibility
Depends on:
Blocks:
 
Reported: 2002-07-29 11:52 EDT by Kit Lo CLA
Modified: 2006-11-16 11:47 EST (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kit Lo CLA 2002-07-29 11:52:33 EDT
There are no keyboard shortcuts (or, maybe there are?, but not able to find 
them in the online help) for switching between pages of MultiPageEditorPart.

This is a accessibility violation.
Comment 1 Nick Edgar CLA 2002-07-29 14:27:09 EDT
Ctrl+Page Up and Ctrl+Page Down should switch between pages in a CTabFolder, 
which is used by MultiPageEditorPart.
If the focus widget is a StyledText, however, it processes the keypress before 
the CTabFolder.

An alternative is to use the tab key (or ctrl+tab) to give focus to the folder 
tab, then use the arrow keys to switch.

Comment 2 Nick Edgar CLA 2002-07-29 14:27:32 EDT
Moving to SWT to comment on StyledText / CTabFolder interaction.
Comment 3 Kit Lo CLA 2002-07-29 14:42:53 EDT
Ctrl+Page Up and Ctrl+Page Down used to work, but stopped working around F2. 
Please verify.

The suggested alternative works. However, after using the right arrow key to 
switch to the second page in the multi-page editor, I have to use Ctrl+Tab to 
tab through all the toolbar icons and perspective icons before the focus goes 
back to the folder tab. So, I need to press about another 10 keystrokes before 
I can switch to the third page.
Comment 4 Nick Edgar CLA 2002-07-29 15:33:40 EDT
Try going the other way: Ctrl+Shift+Tab.
Comment 5 Kit Lo CLA 2002-07-29 15:51:34 EDT
Ctrl+Shift+Tab works better. Thanks.

But I still prefer Ctrl+Page Up and Ctrl+Page Down. We have to find out why it 
stopped working.

Should we leave this bug report open to address the "Ctrl+Page Up and Ctrl+Page 
Down stopped working" problem? Or, should we just document to use the 
Ctrl+Shift+Tab way to switch between pages of multi-page editor?
Comment 6 Nick Edgar CLA 2002-07-29 15:54:09 EDT
Yes, SWT will investigate why Ctrl+Page Up and Ctrl+Page Down stopped working.
Comment 7 Steve Northover CLA 2002-07-29 16:00:16 EDT
I have verified that this is a problem in SWT in the following code:

public static void main (String [] args) {
	Display display = new Display ();
	Shell shell = new Shell (display);
	shell.setLayout (new FillLayout ());
	CTabFolder tabFolder = new CTabFolder (shell, SWT.BORDER);
	for (int i=0; i<6; i++) {
		CTabItem item = new CTabItem (tabFolder, SWT.NULL);
		item.setText ("TabItem " + i);
		StyledText text = new StyledText (tabFolder, SWT.BORDER | 
SWT.V_SCROLL | SWT.H_SCROLL);
		item.setControl (text);
	}
	shell.open ();
	tabFolder.getChildren () [0].setFocus ();
	while (!shell.isDisposed ()) {
		if (!display.readAndDispatch ()) display.sleep ();
	}
	display.dispose ();
}
Comment 8 Steve Northover CLA 2002-07-31 18:02:57 EDT
Fixed > 20020731
Comment 9 Kit Lo CLA 2002-08-02 14:21:14 EDT
Will the fix be available in Eclipse V2.0.1?
Comment 10 Steve Northover CLA 2002-08-07 11:27:43 EDT
So far, this PR is not on the list for 2.0.1.
Comment 11 Steve Northover CLA 2002-08-07 11:41:11 EDT
Nick, can you indicate in this PR that you want this fix for R2.0.1?
Comment 12 Amy Wu CLA 2002-08-26 16:00:08 EDT
was this ever added to v2.0.1?  doing a quick scan of bugs fixed for v2.0.1 it 
does not look like it was.
Comment 13 Steve Northover CLA 2002-09-20 12:06:46 EDT
This was not added to 2.0.1 and unfortunately, I can't remember off hand what 
the fix was.  Kevin, do you want to reopen this PR for 2.0.2?
Comment 14 Kevin Haaland CLA 2002-09-20 12:26:57 EDT
Yes. 

Minimum requirement is the widget has to be keyboard accessible. The particular 
key sequence is not as important. If Ctrl-Shift-Tab works then all that is left 
on this defect for 2.0.2 is to confirm that there isn't a lurking regression 
that will affect other scenarios. 
Comment 15 Veronika Irvine CLA 2002-09-20 13:08:14 EDT
Reopening to be patched to 2.0.2
Comment 16 Veronika Irvine CLA 2002-09-20 13:35:11 EDT
These I believe are the required changes:

Control on Windows:

boolean translateTraversal (MSG msg) {
	int key = msg.wParam;
	if (key == OS.VK_MENU) {
		Shell shell = getShell ();
		int hwndShell = shell.handle;
		OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, 
OS.UIS_INITIALIZE, 0);
		return false;
	}
	int hwnd = msg.hwnd;
	int detail = SWT.TRAVERSE_NONE;
	boolean doit = true, all = false;
	boolean lastVirtual = false;
	int lastKey = key, lastAscii = 0;
	switch (key) {
		case OS.VK_ESCAPE: {
			all = true;
			lastAscii = 27;
			int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 
0);
			if ((code & OS.DLGC_WANTALLKEYS) != 0) doit = false;
			detail = SWT.TRAVERSE_ESCAPE;
			break;
		}
		case OS.VK_RETURN: {
			all = true;
			lastAscii = '\r';
			int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 
0);
			if ((code & OS.DLGC_WANTALLKEYS) != 0) doit = false;
			detail = SWT.TRAVERSE_RETURN;
			break;
		}
		case OS.VK_TAB: {
			/*
			* NOTE: This code causes Shift+Tab and Ctrl+Tab to
			* always attempt traversal which is not correct.
			* The default should be the same as a plain Tab key.
			* This behavior is currently relied on by StyledText.
			*
			* The correct behavior is to give every key to a
			* control that answers DLGC_WANTALLKEYS.
			*/
			lastAscii = '\t';
			boolean next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
			int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 
0);
			if ((code & (OS.DLGC_WANTTAB | OS.DLGC_WANTALLKEYS)) != 
0) {
				if (next && OS.GetKeyState (OS.VK_CONTROL) >= 
0) doit = false;
			}
			detail = next ? SWT.TRAVERSE_TAB_NEXT : 
SWT.TRAVERSE_TAB_PREVIOUS;
			break;
		}
		case OS.VK_UP:
		case OS.VK_LEFT:
		case OS.VK_DOWN:
		case OS.VK_RIGHT: {
			lastVirtual = true;
			int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 
0);
			if ((code & (OS.DLGC_WANTARROWS /*| 
OS.DLGC_WANTALLKEYS*/)) != 0) doit = false;
			boolean next = key == OS.VK_DOWN || key == OS.VK_RIGHT;
			detail = next ? SWT.TRAVERSE_ARROW_NEXT : 
SWT.TRAVERSE_ARROW_PREVIOUS;
			break;
		}
		case OS.VK_PRIOR:
		case OS.VK_NEXT: {
			all = true;
			lastVirtual = true;
			if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
			/*
			* The fact that this code is commented causes Ctrl+PgUp
			* and Ctrl+PgDn to always attempt traversal which is not
			* correct.  This behavior is relied on by StyledText.
			* 
			* The correct behavior is to give every key to a control
			* that answers DLGC_WANTALLKEYS.
			*/
//			int code = OS.SendMessage (hwnd, OS., 0, 0);
//			if ((code & OS.DLGC_WANTALLKEYS) != 0) doit = false;
			detail = key == OS.VK_PRIOR ? 
SWT.TRAVERSE_PAGE_PREVIOUS : SWT.TRAVERSE_PAGE_NEXT;
			break;
		}
		default:
			return false;
	}
	Event event = new Event ();
	event.doit = doit;
	event.detail = detail;
	Display display = getDisplay ();
	display.lastKey = lastKey;
	display.lastAscii = lastAscii;
	display.lastVirtual = lastVirtual;
	display.lastNull = false;
	if (!setKeyState (event, SWT.Traverse)) {
		return false;
	}
	Shell shell = getShell ();
	Control control = this;
	do {
		if (control.traverse (event)) return true;
		if (!event.doit && control.hooks (SWT.Traverse)) {
			return false;
		}
		if (control == shell) return false;
		control = control.parent;
	} while (all && control != null);
	return false;
}

Control on GTK:

boolean translateTraversal (int gdkEvent) {
	int detail = SWT.TRAVERSE_NONE;
	GdkEventKey keyEvent = new GdkEventKey ();
	OS.memmove (keyEvent, gdkEvent, GdkEventKey.sizeof);
	int key = keyEvent.keyval;
	int code = traversalCode (key, gdkEvent);
	int [] state = new int [1];
	OS.gdk_event_get_state (gdkEvent, state);
	boolean all = false;
	switch (key) {
		case OS.GDK_Escape:
		case OS.GDK_Cancel: {
			all = true;
			detail = SWT.TRAVERSE_ESCAPE;
			break;
		}
		case OS.GDK_Return: {
			all = true;
			detail = SWT.TRAVERSE_RETURN;
			break;
		}
		case OS.GDK_ISO_Left_Tab: 
		case OS.GDK_Tab: {
			boolean next = (state [0] & OS.GDK_SHIFT_MASK) == 0;
			/*
			* NOTE: This code causes Shift+Tab and Ctrl+Tab to
			* always attempt traversal which is not correct.
			* The default should be the same as a plain Tab key.
			* This behavior is currently relied on by StyledText.
			* 
			* The correct behavior is to give every key to any
			* control that wants to see every key.  The default
			* behavior for a Canvas should be to see every key.
			*/
			switch (state [0]) {
				case OS.GDK_SHIFT_MASK:
				case OS.GDK_CONTROL_MASK:
					code |= SWT.TRAVERSE_TAB_PREVIOUS | 
SWT.TRAVERSE_TAB_NEXT;
			}
			detail = next ? SWT.TRAVERSE_TAB_NEXT : 
SWT.TRAVERSE_TAB_PREVIOUS;
			break;
		}
		case OS.GDK_Up:
		case OS.GDK_Left: 
		case OS.GDK_Down:
		case OS.GDK_Right: {
			boolean next = key == OS.GDK_Down || key == 
OS.GDK_Right;
			detail = next ? SWT.TRAVERSE_ARROW_NEXT : 
SWT.TRAVERSE_ARROW_PREVIOUS;
			break;
		}
		case OS.GDK_Page_Up:
		case OS.GDK_Page_Down: {
			all = true;
			if ((state [0] & OS.GDK_CONTROL_MASK) == 0) return 
false;
			/*
			* NOTE: This code causes Ctrl+PgUp and Ctrl+PgDn to 
always
			* attempt traversal which is not correct.  This 
behavior is
			* currently relied on by StyledText.
			* 
			* The correct behavior is to give every key to any
			* control that wants to see every key.  The default
			* behavior for a Canvas should be to see every key.
			*/
			code |= SWT.TRAVERSE_PAGE_NEXT | 
SWT.TRAVERSE_PAGE_PREVIOUS;
			detail = key == OS.GDK_Page_Down ? 
SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS;
			break;
		}
		default:
			return false;
	}
	Event event = new Event ();
	event.doit = (code & detail) != 0;
	event.detail = detail;
	event.time = keyEvent.time;
	setInputState (event, gdkEvent);
	Shell shell = getShell ();
	Control control = this;
	do {
		if (control.traverse (event)) return true;
		if (!event.doit && control.hooks (SWT.Traverse)) {
			return false;
		}
		if (control == shell) return false;
		control = control.parent;
	} while (all && control != null);
	return false;
}

Control on motif:

boolean translateTraversal (int key, XKeyEvent xEvent) {
	int detail = SWT.TRAVERSE_NONE;
	int code = traversalCode (key, xEvent);
	boolean all = false;
	switch (key) {
		case OS.XK_Escape:
		case OS.XK_Cancel: {
			all = true;
			detail = SWT.TRAVERSE_ESCAPE;
			break;
		}
		case OS.XK_Return: {
			all = true;
			detail = SWT.TRAVERSE_RETURN;
			break;
		}
		case OS.XK_Tab: {
			boolean next = (xEvent.state & OS.ShiftMask) == 0;
			/*
			* NOTE: This code causes Shift+Tab and Ctrl+Tab to
			* always attempt traversal which is not correct.
			* The default should be the same as a plain Tab key.
			* This behavior is currently relied on by StyledText.
			* 
			* The correct behavior is to give every key to any
			* control that wants to see every key.  The default
			* behavior for a Canvas should be to see every key.
			*/
			switch (xEvent.state) {
				case OS.ControlMask:
				case OS.ShiftMask:
					code |= SWT.TRAVERSE_TAB_PREVIOUS | 
SWT.TRAVERSE_TAB_NEXT;
			}
			detail = next ? SWT.TRAVERSE_TAB_NEXT : 
SWT.TRAVERSE_TAB_PREVIOUS;
			break;
		}
		case OS.XK_Up:
		case OS.XK_Left: 
		case OS.XK_Down:
		case OS.XK_Right: {
			boolean next = key == OS.XK_Down || key == OS.XK_Right;
			detail = next ? SWT.TRAVERSE_ARROW_NEXT : 
SWT.TRAVERSE_ARROW_PREVIOUS;
			break;
		}
		case OS.XK_Page_Up:
		case OS.XK_Page_Down: {
			all = true;
			if ((xEvent.state & OS.ControlMask) == 0) return false;
			/*
			* NOTE: This code causes Ctrl+PgUp and Ctrl+PgDn to 
always
			* attempt traversal which is not correct.  This 
behavior is
			* currently relied on by StyledText.
			* 
			* The correct behavior is to give every key to any
			* control that wants to see every key.  The default
			* behavior for a Canvas should be to see every key.
			*/
			code |= SWT.TRAVERSE_PAGE_NEXT | 
SWT.TRAVERSE_PAGE_PREVIOUS;
			detail = key == OS.XK_Page_Down ? 
SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS;
			break;
		}
		default:
			return false;
	}
	Event event = new Event ();
	event.doit = (code & detail) != 0;
	event.detail = detail;
	event.time = xEvent.time;
	setKeyState (event, xEvent);
	Shell shell = getShell ();
	Control control = this;
	do {
		if (control.traverse (event)) return true;
		if (!event.doit && control.hooks (SWT.Traverse)) {
			return false;
		}
		if (control == shell) return false;
		control = control.parent;
	} while (all && control != null);
	return false;
}
Comment 17 Steve Northover CLA 2002-09-23 08:47:30 EDT
Thanks.  The code looks like it contains other changes that we don't want in 
2.0.2.
Comment 18 Veronika Irvine CLA 2002-09-23 16:01:24 EDT
Fixed in 2.0.2.
Comment 19 Kit Lo CLA 2006-11-16 11:47:58 EST
closing old bug