Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

expose your windows


  • Please log in to reply
13 replies to this topic
keyboardfreak
  • Members
  • 217 posts
  • Last active: Sep 27 2010 07:21 PM
  • Joined: 09 Oct 2004
Here's an AutoHotkey implementation of Apple's Expose. I haven't actually used Expose, just read some descriptions about it. The real thing is surely slicker than my feeble script.

I know there are native ports of Expose for windows, this script is only a toy, a demonstration of AutoHotkey's capabilities. Enjoy.

(Sometimes the tiling is not perfect if there are windows on the screen that do not allow resizing.)
;
; expose - a naive implementation of Apple's Expose feature
;
;
; When activated all the visible windows are tiled on the
; screen. A window can be selected with the cursor keys and
; enter. The window selection can be cancelled with escape.
;
; When a window is selected the size and positon of all
; windows is restored and the selected window is activated.
;
; TODO:
;
;     - handling minimized windows 
;       how do we know if a window is minimized?
;

; constants

square_numbers = 1,4,9,16,25,36,49,64,81,100
stringsplit, squares, square_numbers, `,

square_roots = 1,2,3,4,5,6,7,8,9,10
stringsplit, roots, square_roots, `,

; window data fields

field_id     = 1
field_x      = 2
field_y      = 3
field_width  = 4
field_height = 5

;----------------------------------------------------------------------
;
; I never use the right control key, that's why I chose it.
;
rcontrol::

; enumerate windows on the screen and store their information

numwindows = 0
active_window = 0

winget, ids, list, , , Program Manager
loop, %ids%
{
    stringtrimright, id, ids%a_index%, 0
    wingettitle, title, ahk_id %id%

    ; don't add windows with empty titles
    if title = 
        continue

    numwindows += 1

    wingetpos, x, y, width, height, ahk_id %id%
    windows%numwindows% = %id%#%x%#%y%#%width%#%height%

    ; store the index of the initially active window
    ifwinactive, ahk_id %id%
        active_window = %numwindows%
}


if numwindows = 0
{
    msgbox, There are no windows on the screen.
    return
}

if numwindows = 1
{
    msgbox, This is the only window
    return
}

if active_window = 0
{
    msg = no active window found
    gosub, fatalerror
}


; find the smallest rectangle which can hold all
; the windows

loop, %squares0%
{
    stringtrimleft, square, squares%a_index%, 0
    stringtrimleft, root, roots%a_index%, 0

    if numwindows <= %square%
        break
}

; compute the number of rows and columns

columns = %root%
rows = 1
winnum = %root%

loop, %root%
{
    if winnum >= %numwindows%
        break

    rows += 1
    winnum += %root%
}

; calculate the width of columns and the height of rows

wingetpos, , , column_width, row_height, Program Manager

column_width /= %columns%
row_height /= %rows%

; tile the windows on the screen

x = 0
y = 0

column = 1

loop, %numwindows%
{
    stringtrimleft, windata, windows%a_index%, 0
    stringsplit, windata, windata,#
    stringtrimleft, id, windata%field_id%, 0

    winmove, ahk_id %id%, , %x%, %y%, %column_width%, %row_height%

    if column = %columns%
    {
        column = 1
        x = 0
        y += %row_height%
    }
    else
    {
        column += 1
        x += %column_width%
    }
}

; let the user select a window

row = 0
column = 0

loop
{
    input, input, L1, {enter}{esc}{up}{down}{left}{right}

    if ErrorLevel = EndKey:enter
        break

    if ErrorLevel = EndKey:escape
        break

    if ErrorLevel = EndKey:up
        if row = 0
            continue
        else
            row -=1 

    if ErrorLevel = EndKey:down
    {
        row += 1
        gosub, calculatearrayindex

        if index = 0
        {
            row -= 1
            continue
        }
    }

    if ErrorLevel = EndKey:left
        if column = 0
            continue
        else
            column -=1 

    if ErrorLevel = EndKey:right
    {
        column += 1
        gosub, calculatearrayindex

        if index = 0
        {
            column -= 1
            continue
        }
    }

    ; activate selected window
    gosub, calculatearrayindex

    ; index cannot be 0 here
    if index = 0
    {
        msg = index is zero
        gosub, fatalerror
    }

    stringtrimleft, windata, windows%index%, 0
    stringsplit, windata, windata,#
    stringtrimleft, id,  windata%field_id%, 0

    winactivate, ahk_id %id%
}

; restore dimensions of selected window first and
; then the others in the background
;
; if the user pressed escape active_window already
; contains the index of initially active window

if ErrorLevel = EndKey:enter
{
    active_window = %index%
}

index = %active_window%
gosub, restorewindow
winactivate, ahk_id %id%

; restore size of the other windows

loop, %numwindows%
{
    ; it's already restored
    if a_index = %active_window%
        continue

    index = %a_index%
    gosub, restorewindow
}

return

;----------------------------------------------------------------------
;
; Calculate index of current position in the window array
;
; Parameters:
;     row        - the row index (0- based)
;     column     - the column index (0- based)
;     numwindows - the number of windows
;
; Returns:
;     index  - the calculated index or 0 if no valid index can be
;              calculated
;
calculatearrayindex:

if column = %columns%
{
    index = 0
    return
}

if row = %rows%
{
    index = 0
    return
}

index = %columns%
index *= %row%
index += %column%
index += 1   ; arrays are 1-based

if index > %numwindows%
{
    index = 0
    return
}

return

;----------------------------------------------------------------------
;
; Restore window size and position
;
; Parameters:
;     index  - the window index in the window array
;
restorewindow:

stringtrimleft, windata, windows%index%, 0
stringsplit, windata, windata,#

stringtrimleft, id,     windata%field_id%, 0
stringtrimleft, x,      windata%field_x%, 0
stringtrimleft, y,      windata%field_y%, 0
stringtrimleft, width,  windata%field_width%, 0
stringtrimleft, height, windata%field_height%, 0

winmove, ahk_id %id%, , %x%, %y%, %width%, %height%

return

;----------------------------------------------------------------------
;
; Displays an error message and terminates the script
;
; Parameters:
;     msg  - error message
;
fatalerror:
msgbox, Script error: %msg%
exit


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
I tried this script and it brought a smile. I like how you can move around all the miniaturized windows with the arrow keys, and then pick one to activate with the Enter key. I feared that all my windows would be permanently miniaturaized afterward, but it appears you've thought of everything: I think all of them were restored to their original sizes.

Thanks for sharing this.

keyboardfreak
  • Members
  • 217 posts
  • Last active: Sep 27 2010 07:21 PM
  • Joined: 09 Oct 2004

I feared that all my windows would be permanently miniaturaized afterward, but it appears you've thought of everything: I think all of them were restored to their original sizes.

I clarified the documentation to indicate that the size and position of all windows is restored after a window is selected.

BTW, how can I tell if a window is in minimized or maximized state?

Gre
  • Members
  • 74 posts
  • Last active: Nov 22 2004 06:23 AM
  • Joined: 12 Oct 2004
what a well structured(or structuralized??) script...
Thanks ,I(have?) learned some things reading it.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

how can I tell if a window is in minimized or maximized state

UseWinGetPos: When minimized, a window has an unusual/special size (this might vary depending on OS). Detecting maximized might be a little less certain, but perhaps by comparing the size of the desktop (via WinGetPos,,, desk_width, desk_height, Program Manager) to the size of the candidate window.

Soon there will be a new WinGet sub-command to make this easier.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
This was long overdue so I added it:

Added command "WinGet, OutputVar, MinMax, WinTitle", which retrieves -1 if the window is minimized, 1 if it is maximized, or 0 if it is neither.

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
i tried it and its a very nice script!

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


jonny
  • Members
  • 2951 posts
  • Last active: Feb 24 2008 04:22 AM
  • Joined: 13 Nov 2004
I'm finding this script to be a little buggy. Sometimes it'll act weird, or it won't undo the tile. Two recurring problems I'm having are keyboard malfunctions and the script window. With the keyboard, sometimes this script will partially disable it after activating. I say partially becuase it's entirely random, if you press some keys about 20% will go through. Not just letters, too. Also, the script's window itself causes some problems. Every once in a while, a blank window (just a titlebar and borders) will tile along with my windows. The title? Expose.ahk. :) Methinks this script could use some testing/debugging and some more features. But great idea, and a really good start on it!

keyboardfreak
  • Members
  • 217 posts
  • Last active: Sep 27 2010 07:21 PM
  • Joined: 09 Oct 2004

Methinks this script could use some testing/debugging and some more features. But great idea, and a really good start on it!

Well, this script is only a quick fun hack. I haven't spent too much time working on it.

If someone is interested in improving it it's up for grabs.

  • Guests
  • Last active:
  • Joined: --
Nice!

ahren37
  • Members
  • 1 posts
  • Last active: Aug 17 2005 06:58 PM
  • Joined: 17 Aug 2005
really good job with this script! :D

one question: is it possible, instead of changing the resizing the windows by changing their X, Y dimensions, to actually scale them to see a miniature of the window (essentially scaling without changing the X/Y ratio)? (this might not be very clear...) i could be smokin' crack or something, i just started messing around with scripts and programming stuff. maybe you tried already. if not maybe i'll give it a go.

drmurdoch
  • Members
  • 120 posts
  • Last active: Aug 05 2015 03:27 PM
  • Joined: 10 Nov 2006
I installed Expose and ran it.

A script version of apple's expose by Keyboardfreak can be found here

It makes all your active windows fit onto your screen when you press Ctrl. I think its possible to modify the script. Default hotkey is RControl


I used the RControl key.

This didn't work well on my dual screen (two monitor) setup.
As well, it seemed to disable the Windows + D and Windows + M usage.

FYI

polocanada
  • Members
  • 2 posts
  • Last active: Dec 28 2009 04:35 AM
  • Joined: 28 Dec 2009
Sorry, but how do I activate it. Is there a key combination or mouse gesture or something to activate expose? It's running in the tray but can't figure it out how to make it happen... :?

kli6891
  • Members
  • 46 posts
  • Last active: Nov 24 2012 08:12 PM
  • Joined: 01 Aug 2009
Seems that you press the right control key.