Cocoa CGWindowListCopyWindowInfo & AXUIElementSetAttributeValue - macos

I'm using the following piece of code to get all windows:
CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
This gives me an array of dictionaries as found here: Front most window using CGWindowListCopyWindowInfo
Then I check their bounds to see if the mouse is in it, and the first I find is is the one my mouse is over.
Then I would like to be able to move it. I know how to use AXUIElementSetAttributeValue to move a window, though then I need a AXUIElementRef, which I can't figure out how to get out of the dictionary.
How can I solve this?

There is no way to go from a window number to an AXUIElementRef.
The closest you can get is to find the owner of the window, then ask it through Accessibility for its windows and look for one with the same title—but an app may have more than one window with the same title, so you need to figure out what you'll do in that case.
The only ways to move another application's windows are by AppleScript or by Accessibility. Using Accessibility is much more reliable than AppleScript (many, if not most, apps have incomplete and/or flaky scripting support). You can get the process ID and window title from the same window dictionary that gives the window number, but that's as specific as you can get. With AppleScript, you could only use the window's index within its application's window list, and hope that the list hasn't changed order in the split-second between you computing the index and trying to use it.

Related

How to get the hot item name and path from Explorer?

It was easy when the Windows' explorer was using a SysListView32 control for displaying its files list as opposed to the DirectUIHWND control in the subsequent versions of Windows after XP.
A simple task such as obtaining the 'hot item' which is that item (a filename) the mouse hovers above for some hundreds of milliseconds, where before I could use the macros
ListView_GetHotItem with ListView_GetItemText and be able to obtain the filename under the mouse cursor.
This simple task becomes almost impossible to do with the DirectUIHWND window unless I revert this control back to a
SysListView32 which I have seen being proposed as the only solution on the many sites I have searched, and even if used the change does not occur immediately but only after I navigate out of the folder first.
It has taken me almost 2 years trying to find a solution to this and until now I feel stumped.
Anyone any idea please ?
Basically I have subclassed the parent of the tooltip and intercepted the tooltip notifications and all I need is the filename and the full path of the item the mouse hoovers above it, the hot item.
https://learn.microsoft.com/en-us/archive/msdn-magazine/2000/march/windows-2000-ui-innovations-enhance-your-user-s-experience-with-new-infotip-and-icon-overlay-shell-extensions
IQueryInfo is required to provide the runtime text to the shell. IPersistFile is used by Explorer to let the extension know about the specific file currently under the mouse pointer.

Can AppleScript read mouse position / action in one application and replicate it in another application?

I've been searching for a mouse broadcaster for Mac for a while and it seems there are no solutions for doing this, so I must look for alternative solutions now. I'm wondering if AppleScript is capable of performing such a task. Basically, what I would like to do is read mouse position and action when performed in one application for as long as the script is active, and broadcast/replicate it in one or more other applications. Is AppleScript capable of this?
Just to clarify, I'd need to simulate mouse movement in the other applications... for example, if I opened up several instances of a drawing program, assuming that the program had the same resolution, anything I drew in the main program, would replicate on the other programs.
Really applescript cannot do what you need. It's not made for that. Applescript is made to run the commands in an application's applescript dictionary. I assume that the dictionary of the applications you want to control give you no way to read and control the mouse.
You do have an applescript alternative though. I have made a command line tool to read the mouse position and also to move the mouse. So theoretically you can do what you want with applescript and my tool. I do not believe you will get the results you expect though. Anyway you can try. Here's a link to the web page for my tool. I hope it helps.
Get it here.
Your basic approach could be 1) activate the application you want to read the mouse position, 2) run my tool in a repeat loop and record the mouse positions, 3) activate the second application that you want to duplicate the mouse movements, 4) use a repeat loop with my tool to make the mouse move according to how you recorded it.

Get Context Menu text of specific TaskBar button

I've got some code that grabs the TaskBar buttons and their text from the windows TaskBar using User32.SendMessage with the TB_GETBUTTON message to retrieve a TBBUTTON structure (Win32 API via C# P/Invokes). But I'm trying to figure out how to then, once I have the handle to the button, grab the associated context menu text. There is some status information on there for a specific application that I would like to retrieve. The button text gets me some of it, but I need to the context menu text to complete it.
Any ideas?
This is not completely clear... Context menus don't have text, as such - they have menu items, each one of which will have text. By "context menu text", do you mean the text of the menu items in the taskbar button's popup/context menu? For example, "Restore", "Minimize" etc in the screenshot below?
If so, I suspect you're going about this the wrong way:
This menu doesn't belong to the button, but is the system menu of the window represented by the taskbar button. If the button has a context menu, this is probably for a grouped collection of windows, not one specific window (or even windows for one process.)
Making judgements based on the context menu of a window sounds like a dodgy approach to me, especially based on text since that will change depending on where in the world your user is located. Applications can also change the contents of this menu so there's no guarantee it will contain something you expect to be there. It would be better to check the window style, if it's minimized, etc, to find out the information that also affects the contents of the menu.
I'm going to answer this based on what your needs seem to be from the question, not what you've directly asked, since (a) it's not possible as asked and (b) I think you're trying to do something else. (As a general guideline, in a question it's good to state why you're trying to do something - and even maybe ask about that, ie 'how do I achieve X' - in case there's a better method than the one you're using. Here, X is probably 'find out information about this window' not 'get the text of the context menu', because that's probably only one possible method to get to X.) Also I think extracting data from the internals of a third-party application like Explorer (the taskbar is an Explorer window) is fragile and prone to break in future versions of Windows.
The system menu or window information (whichever one) belongs to application windows. Unless taskbar buttons are grouped (and then it's the subitems) one taskbar button corresponds to one specific window in the system. So what you want to do is find these windows. You do this by:
Using the EnumWindows function
Then for each window that is passed to the callback, checking the extended window style using GetWindowLong with GWL_EXSTYLE to see if the WS_EX_APPWINDOW bit is set
In addition, sometimes other windows are shown: these heuristics should help.
Each one of these windows is a window that should appear on the taskbar, Alt-Tab dialog, etc.
You say you're getting the text of the taskbar button - this is probably the window caption of the window, and GetWindowText is the canonical (read: probably a lot more reliable) way to get the caption of a window belonging to another process.
If you really want the popup menu, then:
Use GetSystemMenu to retrieve the handle for the system menu for the window. Applications can customise this, so if your app is doing this (and that's why you want the popup menu) ensure you pass false to the bRevert parameter
You can then get the number of menu items using GetMenuItemCount and for each one call GetMenuItemInfo to get info about each menu item. Pass true to the fByPosition parameter to indicate you're accessing the menus by position (since you know the count, you're getting item 0, 1, 2... count-1).
This fills a MENUITEMINFO structure, which (I think, I haven't ever had to code this so I haven't tested) will tell you the text associated with an item via the dwTypeData field "if the MIIM_STRING flag is set in the fMask member".
If you really want information about the window status, you can get this information using methods like IsIconic to see if it's minimized, GetWindowLong again to get other information, etc. I'd suggest you ask another SO question about how to get whatever specific information about a window for details.
Hope that helps!

Is there anything like Winsplit Revolution for Mac OS X?

Is there anything like Winsplit Revolution for Mac OS X?
Try these:
Zooom/2 ($15) has been my favorite since I installed it. Fast, flexible, and minimizes the number of key combinations I need to remember
Divvy ($15) might soon replace Zoom/2 for me. It's closer to Winsplit. You can arrange windows on a grid, define your own grid arrangements, and define your own shortcuts. It also minimizes the number of keystroke combinations you need to remember. BONUS: There are Mac and Windows versions, which means if you use both platforms you can use the same window management method across all your machines.
Breeze ($8) makes it easy to make windows fullscreen, split left, or split right. It also lets you save screen states (generic) and for specific apps.
Moom ($5) is a more recent entry. It supports both keyboard shortcuts and mouse shortcuts. For the mouse shortcuts, moving the cursor over the greeen zoom button displays a popup list of different layout options: full screen, left/right half, top/bottom half, or any of the corners.
SizeUp ($10) mimics various aspects of WinSplit functionality, but it relies on many keystroke combinations that take time to learn. The advantage is quickly moving windows. The drawback is that it uses up a lot of global keyboard shortcuts, and there are so many I couldn't remember them all.
Cinch ($7) is a mouse-driven app by the makers of SizeUp. Drag your window to various hot zones on the screen edges and the window will "cinch" to that edge and resize to fill half the screen. Similar to the built-in resizing feature in Windows 7.
MercuryMover ($20) is quite powerful and offers fine-grained control. However, there are a lot of different key combinations and, overall, I didn't find it as easy to learn or as elegant as WinSplit. I uninstalled it almost immediately. It struck me as powerful, but inefficient and unwieldy.
The DIY approach (free) mentioned in another post is to combine some applescripts and bind them to quicksilver triggers. I haven't tried this. But it is a free solution.
I found the weak window management one of the hardest things to cope with when I started using a Mac.
Why go beyond spaces and expose?
Winsplit significantly adds to what spaces and expose can do. I didn't understand the appeal until I actually used it. Before that, I thought virtual desktops (ie, like spaces) was enough. Now I consider it must-have functionality, especially on large monitors and multi-mon setups.
On my Windows machine running 3 monitors, I would rank the importance of these different apps in the following order:
Winsplit-like window rearranging
Spaces-like virtual desktops
Expose-like application switching
On my MacBook, I've learned to approach it the other way.
Expose-like application switching
Winsplit-like window rearranging
Spaces-like virtual desktops
From the Winsplit website I understand more or less the functionality; in the past I actually used to have my window manager (Waimea) configured to do exactly that in linux.
You may try using Quicksilver to trigger one of a custom set of applescripts; each applescript would resize and move the currently focused window to a predefined location.
See this macosxhints post for inspiration...
ShiftIt is a free option. Assignable hotkeys to resize to different portions of the screen (Left, Right, Top, Bottom, Top Left, Top Right, Bottom Left, Bottom Right, Full Screen and Center with current size)
Link to ShiftIt on github
Just click on the big download button towards the right of the screen.
Spectacle is a good option, its free and open source. And easy to use with keyboard shortcut :
Windows can be moved to a number of predefined regions of the screen:
Move to the left half ⌥⌘←
Move to the right half ⌥⌘→
Move to the top half ⌥⌘↑
Move to the bottom half ⌥⌘↓
Move to the upper left ⌃⌘←
Move to the lower left ⌃⇧⌘←
Move to the upper right ⌃⌘→
Move to the lower right — ⌃⇧⌘→
Another question on StackOverflow adresses the same issue
https://stackoverflow.com/questions/276760/tiling-window-manager-for-os-x
One answer provided links to an app called TwoUP. It's free, and does the job on OSX!
Thanks to Dong Hoon's answer, I have developed a hybrid solution. Using the AppleScript Editor, you can create scripts to resize the current window, like this:
tell application "System Events"
set _everyProcess to every process
repeat with n from 1 to count of _everyProcess
set _frontMost to frontmost of item n of _everyProcess
if _frontMost is true then set _frontMostApp to process n
end repeat
set _windowOne to window 1 of _frontMostApp
set position of _windowOne to {5, 0}
set size of _windowOne to {1150, 735}
end tell
such a script will work on a 13" MacBook. Using subtle variations of this script saved to /Users/[YourUserNameHere]/Library/Scripts, you can have configure the AppleScript Editor to show itself in the menu bar, where it will allow you to select a script to run.
Using several different scripts, I'm able to resize and reposition any window with only two clicks.
Hope this helps.
It looks like TwoUp is dead, but here are some other options:
Cinch ($7) is like Aero Snap for Mac.
Breeze ($8) allows you to save window states and restore them like a template to another window.
Divvy ($14) shows a grid on the screen where you can select boxes to indicate how you want the window to fill your screen.
I haven't used Winsplit, so I don't know how it compares, but an app I developed, Optimal Layout, offers very flexible window tiling, as well as moving and resizing from the keyboard:
http://most-advantageous.com/optimal-layout/
You can also try Arrange application which features resize and reposition with keyboard shortcuts, on screen menu and by dragging window.
You should also try out secondbar. gives you an extra menubar at the second display + re-arrange options. See this link.
You can even try SplitScreenapp.com. It allows you to resize Mac Windows in many ways including full split, half split, drag and snap, etc.
I doubt it. Between Spaces and Expose, there's not much need for a third-party app to help manage multiple windows.

Getting a unique ID for a window of another application

I'm a newbie Cocoa developer and I'm developing my first application. I want to read a unique identifier from any window of any application - whether it's Cocoa or Carbon. Cocoa applications make their window IDs available to AppleScript (although I'm sure there's a much better way to do this through a proper Objective C route), but I'm trying to access window IDs from documents in the Adobe apps. This seems to be a lot trickier. All I can seem to find in the reference libraries is HIWindowGetCGWindowID:
"This function returns the window ID assigned by the window server when a window is created. The window ID is not generally useful with any other Carbon function, but may be used with other Mac OS X functions that require a window ID, such as functions in OpenGL."
Can this be used to get the ID from my program? Or is it just a function that can be used within one application?
If someone could point me in the right direction, I'd be eternally grateful.
The function HIWindowGetCGWindowID() can only return a CGWindowID for one of your app's windows, since a WindowRef from another program won't be valid in yours.
The function CGWindowListCopyWindowInfo() from CGWindow.h will return an array of dictionaries, one for each window that matches the criteria you set, including ones in other applications. It only lets you filter by windows above a given window, windows below a given window and "onscreen" windows, but the dictionary returned includes a process ID for the owning app which you can use to match up window to app. In each returned dictionary the kCGWindowNumber key will point to the window ID as a CFNumber. There is also a CGWindowListCreate() function that only returns an array of CGWindowIDs. There is basically no documentation for these functions beyond the CGWindow.h header and the Son of Grab sample code. Also, it's 10.5 only.

Resources