Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

NVDA stops working when opening a document in Microsoft Word 2010 protected view #1686

Closed
nvaccessAuto opened this Issue Jul 22, 2011 · 27 comments

Comments

Projects
None yet
1 participant

Reported by surveyor on 2011-07-22 07:32
NVDA stops speaking just after a word file attachment opened in a message with outllook 2010. NVDA starts speaking after pressing esc, but this time MSWord displays a dialog box about document recovery. Everything is normal with NVDA closed and there's no problem if I open the same document after saving.
Blocked by #3526

Attachment NVDA_log.txt added by surveyor on 2011-07-22 07:33
Description:

Comment 1 by surveyor (in reply to comment description) on 2011-07-29 06:43
Replying to surveyor:

NVDA stops speaking just after a word file attachment opened in a message with outllook 2010. NVDA starts speaking after pressing esc, but this time MSWord displays a dialog box about document recovery. Everything is normal with NVDA closed and there's no problem if I open the same document after saving.

I've noticed the problem is related to MSWord 2010 and protected view rather than outlook 2010. That is, the problem occurs when a document opened in protected view with MSWord.

Comment 2 by jteh on 2011-08-01 00:08
Changes:
Changed title from "MSWord 2010 stops working, NVDA stops speking after opening an attachment in Outlook 2010" to "NVDA stops working when opening a document in Microsoft Word 2010 protected view"

Comment 3 by heikofolkerts on 2012-04-19 16:23
I encounter the same Problem under Windows XP and Office 2010. The deffect is quite high priority since it prevents reading Mails with Word attachments with NVDA. This makes it hard to use a system just with NVDA as screen reader when having many of those mails.

Comment 4 by manish on 2013-04-11 05:21
There are 2 problems here:

  1. nvda causes word to crash in protected view: This happens because of a call to the spelling errors.Count property when the report spelling errors configuration property is set. In protected view, word does not allow spell checking and accessing the spellingErrors.Count property causes the protected winword.exe process to crash.
  2. In protected mode, focus is set to the parent of the word document window (window class (_wwg). This parent window has 2 children, a toolbar containing a previous and next buttons and the actual word document window. To get to the actual document you have to first route the navigator object to the current focus, go to first child, move to next sybling and then move focus to the current navigator object.

Solutions:

  1. The attached patch solves the first problem. Before accessing the spelling errors property, the application.isSandbox property has been checked. The Same problem exists in the ExpandToLineHelper() method where a call is made to disable screen updates and re-enable them at the end of the method. These calls, however, fail silently and do not cause word to crash, which is why I haven't added the isSandbox check in these two calls.
  2. I am not sure of what is the right fix for the second problem - focus is set to parent instead of the document. Will appreciate any suggestion for fixing this.

Attachment fix-1686-crash-in-protected-documents.patch added by manish on 2013-04-11 05:27
Description:

Comment 5 by manish on 2013-04-26 17:09
The attached latest patch fixes both the crash and focus issues. After this patch, word documents in protected view work just fine for me.

Attachment fix-1686-word-document-protected-mode.patch added by manish on 2013-04-28 07:25
Description:
fixes focus problem correctly

Comment 6 by mdcurran (in reply to comment 5) on 2013-04-29 07:34
Replying to manish:
I tried the patch and I have no major issue with the code. However, the document.setFocus() seems to cause some issues on my system. Specifically, the document does get focus (it has the focused state) but the caret will not move, and pressing alt takes me to the system menu, not the ribbon. In order for it to work for me, i:

  • replaced the eventHandler.executeEvent and document.setFocus calls with a mouse click at the top left of the document.
  • Returned at the top of the event if there was pending focus events.

I'm interested if you ever saw the same simptoms I saw?
I would much prefer a call to setFocus, but if it does not work on some systems we'll have to go with the mouse click.
For an example of mouse clicks, see virtualBuffers/gecko_ia2.py and search for winUser.getCursorPos.

Comment 7 by jteh on 2013-04-29 08:28
A mouse click isn't safe, as it may cause a link or similar in the document to be clicked. Unfortunately, I don't have any better ideas. :)

Comment 8 by manish (in reply to comment 6) on 2013-04-29 12:50
Replying to mdcurran:

I can reproduce the same problem if I remove document.SetFocus() altogether.
My theory is that the "GainFocus" event is raised on a background thread and so, there may be a race condition where document.SetFocus() sometimes gets executed before the "GainFocus" event is processed, in which case, it becomes a no-op call.

One solution could be that we do a document.setFocus() in the event_gainFocus handler of the class that gets loaded for _wwg. We could derive a class from WordDocument that contains this handler and add it to the clsList only in case of protected documents (parent of _wwg obj is of class _wwb and role systemGenericClient).

I'll try this out and send an update.

-Manish

Replying to manish:

I tried the patch and I have no major issue with the code. However, the document.setFocus() seems to cause some issues on my system. Specifically, the document does get focus (it has the focused state) but the caret will not move, and pressing alt takes me to the system menu, not the ribbon. In order for it to work for me, i:

  • replaced the eventHandler.executeEvent and document.setFocus calls with a mouse click at the top left of the document.
  • Returned at the top of the event if there was pending focus events.

I'm interested if you ever saw the same simptoms I saw?

I would much prefer a call to setFocus, but if it does not work on some systems we'll have to go with the mouse click.

For an example of mouse clicks, see virtualBuffers/gecko_ia2.py and search for winUser.getCursorPos.

Comment 9 by manish (in reply to comment 8) on 2013-05-02 08:45
Replying to manish:
Instead of the mouse click, can we call the global script navigator_MoveFocus()?

My above theory on eventFocus doesn't work.
However, I am unable to reproduce the problem even once with the following code in NvdaObjects|IAccessible|Winword.py. Can you confirm if you Are having the focus problem with the exact code as below or do you have something else?:

    def event_gainFocus(self):
        """On gaining focus, simply set the focus on a child of type word document. 
        This is just a container window.
        """
        if eventHandler.isPendingEvents("gainFocus"):
            return
        document=next((x for x in self.children if isinstance(x,WordDocument)), None)  
        if document:
            eventHandler.executeEvent("gainFocus",document)
            document.setFocus()

Basically, I am trying to automate the following for a document opened in protected view:

  1. On changing focus to a word protected view window (through alt+tab or file|open|protectedView), move the navigator object to the first child of type _wwg.
  2. press NVDA+shift+backspace to move focus to the navigator object.

The above steps always work. So, instead of calling Document.SetFocus, can we call the global script navigator_movefocus somehow? is this also as bad as trying to do a left mouse click?

Replying to mdcurran:

I can reproduce the same problem if I remove document.SetFocus() altogether.

My theory is that the "GainFocus" event is raised on a background thread and so, there may be a race condition where document.SetFocus() sometimes gets executed before the "GainFocus" event is processed, in which case, it becomes a no-op call.

One solution could be that we do a document.setFocus() in the event_gainFocus handler of the class that gets loaded for _wwg. We could derive a class from WordDocument that contains this handler and add it to the clsList only in case of protected documents (parent of _wwg obj is of class _wwb and role systemGenericClient).

I'll try this out and send an update.

-Manish

Replying to manish:

I tried the patch and I have no major issue with the code. However, the document.setFocus() seems to cause some issues on my system. Specifically, the document does get focus (it has the focused state) but the caret will not move, and pressing alt takes me to the system menu, not the ribbon. In order for it to work for me, i:

  • replaced the eventHandler.executeEvent and document.setFocus calls with a mouse click at the top left of the document.
  • Returned at the top of the event if there was pending focus events.

I'm interested if you ever saw the same simptoms I saw?

I would much prefer a call to setFocus, but if it does not work on some systems we'll have to go with the mouse click.

For an example of mouse clicks, see virtualBuffers/gecko_ia2.py and search for winUser.getCursorPos.

Comment 10 by jteh on 2013-05-02 09:57
The move focus script just calls setFocus, so this won't make any difference.

gainFocus events are never handled in a different thread.

If you're calling setFocus, you shouldn't ever have to call the gainFocus event, as setFocus should set the focus and thus cause the application to fire a focus event. If you're having to call the gainFocus event yourself, setFocus isn't working properly.

It's possible there's a slight timing issue here. Perhaps Word doesn't like the focus being moved so quickly. We could try delaying the setFocus call (with wx.!CallLater).

Comment 11 by manish (in reply to comment 10) on 2013-05-03 11:37
Replying to jteh:
Mic, since I cannot reproduce the problem with Document.SetFocus(), I cannot tell if wx.CallLater will make a difference. Will it be possible for you to check this?

-Manish

The move focus script just calls setFocus, so this won't make any difference.

gainFocus events are never handled in a different thread.

If you're calling setFocus, you shouldn't ever have to call the gainFocus event, as setFocus should set the focus and thus cause the application to fire a focus event. If you're having to call the gainFocus event yourself, setFocus isn't working properly.

It's possible there's a slight timing issue here. Perhaps Word doesn't like the focus being moved so quickly. We could try delaying the setFocus call (with wx.!CallLater).

Comment 12 by manish (in reply to comment 10) on 2013-05-20 14:22
Replying to jteh:
I misunderstood your comments earlier. Have incorporated wx.CallLater and removed the explicit call to ExecuteEvent. This is working fine for me on 3 different machines. Mic, Can you test the patch attached after this comment now?

Thanks,
Manish

The move focus script just calls setFocus, so this won't make any difference.

gainFocus events are never handled in a different thread.

If you're calling setFocus, you shouldn't ever have to call the gainFocus event, as setFocus should set the focus and thus cause the application to fire a focus event. If you're having to call the gainFocus event yourself, setFocus isn't working properly.

It's possible there's a slight timing issue here. Perhaps Word doesn't like the focus being moved so quickly. We could try delaying the setFocus call (with wx.!CallLater).

Attachment fix-1686-protected-document-focus-with-call-later.patch added by manish on 2013-05-20 14:23
Description:
wx.calllater works

Comment 13 by manish on 2013-06-27 13:00
Mic, did you get a chance to test the fix with Jamie's wx.callLater comment incorporated on your machine? I am able to successfully use this without problems on several machines.

Comment 14 by mdcurran on 2013-07-02 03:36
Oddly, I'm having lots of trouble trying to open a document in protected view. Out of interest, what exact version of Office 2010 are you using? I think I'm on sp1. If I open any document from downloading or as an outlook attachement, it is now just readonly and reads fine even without your patch. Yet in the past I have seen protected view.
I'd suggest checking Windows update for a later version of Office 2010 and installing it and seeing if protected view is fixed. If not, I will be unable to properly test your patch until I solve the issue on my system.
If you have a particular fie you use to test protected view, I'd appreciate if you could attach it to this ticket so I can see if that helps.

Comment 15 by manish (in reply to comment 14) on 2013-07-07 06:42
Hi Mic,
I am using ms word 2010 version 14.0.6129.5000 (SP1) as shown in the help about box.
Protected view is different from a read only view of a file. You probably have protected view disabled in file|options|protected view. Any word file can be opened in protected view with the following steps:

  1. file|open - open file dialog appears.
  2. select the file, go to the open button and press down arrow.
  3. A menu showing various options to open the file appears. The last option in this menu is protected view (notice, read only is a different option here).

When the file opens in protected view, the title bar of the word document says (protected view) in brackets.
An alternative way of opening a file in protected view is to open any file (not originating from your computer) sent to you in mail as an attachment.

Once you are able to open a file in protected view, there are two problems you will encounter:

  1. When you alt+tab to the protected word document window, the focus is not on the document control but on its parent (a Window object). You will need to use the navigator object to move down and right to get to the actual document object.
  2. If you have NVDA|preferences|document formatting|spelling errors selected, ms word will crash every time you try to read the document.

Protected view has not been fixed in the SP1 or in office 2013 for that matter.

Regards,
Manish
Replying to mdcurran:

Oddly, I'm having lots of trouble trying to open a document in protected view. Out of interest, what exact version of Office 2010 are you using? I think I'm on sp1. If I open any document from downloading or as an outlook attachement, it is now just readonly and reads fine even without your patch. Yet in the past I have seen protected view.

I'd suggest checking Windows update for a later version of Office 2010 and installing it and seeing if protected view is fixed. If not, I will be unable to properly test your patch until I solve the issue on my system.

If you have a particular fie you use to test protected view, I'd appreciate if you could attach it to this ticket so I can see if that helps.

Comment 16 by manish on 2013-08-02 07:24
The attached patch is out of date and cannot be applied on the latest code.
I have created a branch on bitbucket for this bug that can be merged. Any luck getting to open in protected view? Many users are asking for this.
url: https://manish_agrawal@bitbucket.org/manish_agrawal/nvda.git

branch: bug_1686

Regards,
Manish

Comment 17 by mdcurran on 2013-08-22 08:02
As I said in a previous comment, I still have problems on my system with that patch. However, I do have some code that partially solves things. To refresh the problem: sometimes with the patch, the focus according to NVDA would go correctly into the document from the _WwB pane, but I could not move the cursor, and pressing alt resulted in going to the system menu. Clearly although MSAA told NVDA focus had moved, it hadn't really according to MS word.

In NVDAObjects\IAccessible\winword.py in event_gainFocus, under the if document: check, replace the wx call with:

            import ctypes
            ctypes.windll.user32.AttachThreadInput(ctypes.windll.kernel32.GetCurrentThreadId(),document.windowThreadID,True)
            ctypes.windll.user32.SetFocus(document.windowHandle)
            ctypes.windll.user32.AttachThreadInput(ctypes.windll.kernel32.GetCurrentThreadId(),document.windowThreadID,False)
            if not document.WinwordWindowObject.active: document.WinwordWindowObject.activate()

This fixes the focus issues for me completely.

The AttachThreadInput allows us to temporarily control MS word's main thread, and then we call SetFocus to properly set focus to the document window. Note that AttachThreadInput is possibly a little hacky or dangerous, we may consider replacing all this with an rpc call, but for now this is good enough to test.
Finally, we also see if the document is active, and if not we activate it. This would have been the cause of not being able to move the cursor around.

There is still another issue, that I assume others see: When moving around the document, I don't get any formatting announced, and some of the lines are a little bit off. The cause of this is that all the rpc calls to fetch text and formatting are failing and we are falling back to range.text out-of-process. The reason the RPC calls are failing is because the appModule for this process has no binding handle... why this is I am still not sure. Oddly though speak typed characters works fine which means that parts of NVDAHelper are initialized.

Manish: please test with my proposed code change and let me know if things still work for you. If so then I will start on a proper feature branch and at least make a try build for others.

Comment 18 by mdcurran on 2013-08-23 03:12
The RPC issue is simply to do with UIAccess security. If I run a signed installed copy this particular issue is fixed.

Comment 19 by Michael Curran <mick@... on 2013-09-16 02:06
In [67071d5]:

MS word  2010 protected view support: When focus lands on the _WwB outer window, bounce focus to the document by instructing Windows to set focus to the document window using user32's SetFocus, and then also make  sure that the document has been activated if not already. Re #1686

Comment 20 by Michael Curran <mick@... on 2013-09-16 02:08
In [00d104a]:

Merge branch 't1686' into next. Incubates #1686

Changes:
Added labels: incubating

Comment 22 by manish (in reply to comment 17) on 2013-09-18 17:39
apologies for not responding on this earlier. *ps.

I tested this with word 2010 and it works fine for me so far. I'll do some more testing in the next few days.
In word 2013, there appears to be another problem. The word 2013 protected document doesn't seem to have a caret at all (even without nvda). and so, none of the arrow key reading commands seem to work. The only way to read the document in protected view in word 2013 is by using the "read by paragraph" ctrl+up and down arrows or with "read by sentence" (#3288 fix).
I am not sure what the correct solution for this should be. Will any of the new review modes help here? or should we use a virtual buffer? or provide "read by character", "read by word", and "read by line" in a way similar to the paragraph and sentence commands?
Anyway, we should probably open another ticket for this since this is working correctly in word 2010 at least.

PS: My track emails had started working and so, I assumed I'll get a mail if anyone updated this ticket. However, I did not get any mails for your updates on the ticket, which is why I didn't notice this.

Replying to mdcurran:

As I said in a previous comment, I still have problems on my system with that patch. However, I do have some code that partially solves things. To refresh the problem: sometimes with the patch, the focus according to NVDA would go correctly into the document from the _WwB pane, but I could not move the cursor, and pressing alt resulted in going to the system menu. Clearly although MSAA told NVDA focus had moved, it hadn't really according to MS word.

In NVDAObjects\IAccessible\winword.py in event_gainFocus, under the if document: check, replace the wx call with:

          import ctypes
          ctypes.windll.user32.AttachThreadInput(ctypes.windll.kernel32.GetCurrentThreadId(),document.windowThreadID,True)
          ctypes.windll.user32.SetFocus(document.windowHandle)
          ctypes.windll.user32.AttachThreadInput(ctypes.windll.kernel32.GetCurrentThreadId(),document.windowThreadID,False)
          if not document.WinwordWindowObject.active: document.WinwordWindowObject.activate()

This fixes the focus issues for me completely.

The AttachThreadInput allows us to temporarily control MS word's main thread, and then we call SetFocus to properly set focus to the document window. Note that AttachThreadInput is possibly a little hacky or dangerous, we may consider replacing all this with an rpc call, but for now this is good enough to test.

Finally, we also see if the document is active, and if not we activate it. This would have been the cause of not being able to move the cursor around.

There is still another issue, that I assume others see: When moving around the document, I don't get any formatting announced, and some of the lines are a little bit off. The cause of this is that all the rpc calls to fetch text and formatting are failing and we are falling back to range.text out-of-process. The reason the RPC calls are failing is because the appModule for this process has no binding handle... why this is I am still not sure. Oddly though speak typed characters works fine which means that parts of NVDAHelper are initialized.

Manish: please test with my proposed code change and let me know if things still work for you. If so then I will start on a proper feature branch and at least make a try build for others.

Comment 23 by Michael Curran <mick@... on 2013-10-02 01:24
In [1fd6eb2]:

Merge branch 't1686'. Fixes #1686

Changes:
Removed labels: incubating
State: closed

Comment 24 by mdcurran on 2013-10-02 01:26
A new ticket should be opened for MS word 2013 protected mode.
Changes:
Milestone changed from None to 2013.3

@nvaccessAuto nvaccessAuto added the bug label Nov 10, 2015

@nvaccessAuto nvaccessAuto added this to the 2013.3 milestone Nov 10, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment