Change Focus in Mail to Viewer (Generally)

Continuing the discussion from Change Focus In Mail?:

I have long wanted a sane way to change focus in Mail to the message list/conversations. Programming any kind of navigation in Mail is tricky because of its various view options Mail doesn’t seem to have a GUI structure — all I can find is a menubar.

Here’s my scenario:

  • Focus is in the message list/conversations viewer.
  • I am happily up and down arrowing to read messages in the message area.
  • I click in a message body; focus goes to the message.
  • I want to go back to the message list, but “I can’t find my way home”.

I might be able to write macro that saves the mouse position when I click in the currently selected message, but how would it know I had clicked?

The best I can think of now, and it is awful, is to click a viewer column head, which will reverse sorting, then click it again. But this would have to be the column by which the messages are currently being sorted.

In some, I want an “idempotent” way to get from the body of a message in the message viewer back to the corresponding entry in the list (which remains highlighted even with focus in the message body).

Hey Mitchell,

True. The script below is based on the Classic Layout.

Mail doesn’t seem to have a GUI structure

Yes, it does. (Although viewing anything in Full-screen view throws all kinds of things out the window.)

You’re using Sierra? Application-Tabs may have changed window options, and I can’t test at the moment.

Have you not bought a copy of UI Browser?

-Chris

--------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2015/07/20 02:48
# dMod: 2016/11/16 20:20
# Appl: Mail & System Events
# Task: Navigate into the Message List and Select the Next Available Message.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Mail, @System_Events, @Navigate, @Select, @Next, @Message
# Note: Updated for El Capitan - change in SEV syntax.
--------------------------------------------------------------------------------

try
   
   tell application "System Events"
      tell application process "Mail"
         set frontmost to true
         tell (first window whose attribute "AXRoleDescription"'s value is "standard window")
            
            tell scroll area 1 of group 1 of splitter group 1 of splitter group 1
               tell table 1
                  if focused is false then set focused to true
               end tell
            end tell
            
         end tell
      end tell
   end tell
   
on error e number n
   stdErr(e, n, true, true) of me
end try

--------------------------------------------------------------------------------
--» HANDLERS
--------------------------------------------------------------------------------
on stdErr(e, n, beepFlag, ddFlag)
   set e to e & return & return & "Num: " & n
   if beepFlag = true then
      beep
   end if
   if ddFlag = true then
      tell application (path to frontmost application as text) to set ddButton to button returned of ¬
         (display dialog e with title "ERROR!" buttons {"Copy Error Message", "Cancel", "OK"} ¬
            default button "OK" giving up after 30)
      if ddButton = "Copy Error Message" then set the clipboard to e
   else
      return e
   end if
end stdErr
--------------------------------------------------------------------------------

Sorry, left out a word — much of a GUI structure, and when I said that I was focusing on high-level concepts like "the message list" or "the message view".

My view has mailboxes listed on the left, messages listed on the top, and the text of the selected message on the bottom. The GUI programming challenge in going from the focused text message back up to the viewer is to find a place to click that (re)focuses the message list without changing the selection within it.

The following, derived from UI Browser, both cause errors:

tell application "System Events" to 
    tell application process "Mail"
        set frontmost to true
            get group 1 of splitter group 1 of ¬
                window "Unread Today (64 messages, 42 unread)"
    end tell
end tell

tell application "System Events"
    tell application process "Mail"
        select text field 2 of row 8 of table 1 of scroll area 1 of ¬
            group 1 of splitter group 1 of splitter group 1 of ¬
            window "Unread Today (64 messages, 42 unread)"
    end tell
end tell

as does the top-level tell in your code:

This is not a challenge. I do it many times per day.

The question is why are you having problems.

What do you get if you run this?

tell application "System Events"
   tell application process "Mail"
      tell front window
         properties
      end tell
   end tell
end tell

-Chris

That can’t be unless there are NO window open in Mail.

Quit and restart Mail.

Send me an image of what your set-up looks like to scriptmeister@thestoneforge.com

How many monitors are you using?

Is there anything unusual about your setup?

-Chris

“no windows” was the hint, and I should have realized the problem before: Mail’s message viewer and open messages are all in a different space than SD.

When I originally tried to find the message list in the message viewer using UI Browser I ran into problems. The main thing that tripped me up is that I left its access of the window as by name rather than index, and the number of messages in the mailbox changed in the time between when I got UI Browser’s access path and when I executed a script using the access path.

I also screwed up by completely forgetting about the focused property.

I let frustration get the better of my attempt to think.

Thanks/sorry.