This App is No Longer Maintained. Visit the Replacement at StrokesPlus.net

StrokesPlus Forum
                       
StrokesPlus Forum
Home | Profile | Active Topics
Members | Search | FAQ
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 General Discussion
 You Know What Really Grinds My Gears?
 App specific gestures execute in wrong scope. meh.
 Forum Locked
 Printer Friendly
Author Previous Topic Topic Next Topic  

mousemagician

6 Posts

Posted - 06/20/2013 :  02:06:21  Show Profile
### Prelude:
Well, first hello, and thanks for developing such a great program, i stumbled in here by pure serendipity. Someone should really write a wiki article about mouse gesturing to make finding proper solutions easier. It's a shame to have these awesome tools hidden in the dark corners of the interwebz.

### Base Behavior:
-StrokesPlus evaluates which action to use for a gesture depending on where the gesture was started. This includes app specific actions.
-Stroke executes actions in the active window.

### The Problem:
Lets assume we have two apps A and B. A has an app specific action A1. B has no actions. There are no global actions defined. There are four possible cases.

Case 1: A is active, A1 is drawn above A.
Case 2: B is active, A1 is drawn above B.
Case 3: A is active, A1 is drawn above B.
Case 4: B is active, A1 is drawn above A.

1) Expected behavior, A1 is executed for A.
2) Expected behavior, A1 is not executed (not defined for B).
3) Unexpected behavior, A1 is not executed at all (not defined for B)!
4) Unexpected behavior, A1 is executed for B!

1 and 2 are ok, 3 is a minor nuisance because nothing happens at all. The real annoyance is 4. You suddenly get an action that is only defined for A executed in B, which can have all sorts of weird consequences.

### Possible Solutions:
### [This is just a list, not my opinion what should be done]

S1) Make the window which was drawn on active.
As mentioned several times on the forums, this seems to be the preferred solution for most ppl. You seem to dislike it and say ppl should just script it in themselves.
Pro:
+Gestures only execute for defined apps.
+Gestures can interact with windows that are inactive at drawing time.
Contra:
-The currently active window (or the user) might dislike loss of focus.

S2)Evaluate which action to use based on the active window instead of based on the window below the gesture starting point.
Pro:
+Gestures only execute for defined apps.
+No automatic shifting of focus.
Contra:
-Can not interact with inactive windows. Instead requiring manual activation by the user.

S3) Implement sending stuff to non-active windows autohotkey-style (aka ControlSend, etc).
Pro:
+Gestures only execute for defined apps.
+Can interact with inactive windows.
Contra:
-Complicates development as you have to always assume that the target windows is inactive.

S4) ??? Forgot what i wanted to write here :<. If you see any other approach I'd be interested.

S5) Delete this post, call me a heretic, destroy the earth, anything goes. Profit.

### My Opinion:
Well, S2 doesn't really seem to be an actual solution because it disabled interacting with inactive windows altogether, which is one of my favorite features :D. S1 Is my preferred solution because for me the forced activation doesn't cause any relevant problems (and I've already gotten used to it in StrokeIt times). So i guess S3 would be the only actual solution. I'm not sure how far AutoHotkey code is reusable so i can't even estimate how complicated it would be to implement that and there's probably other features and problems more urgent.

When i started writing this post i had a strong urge to simply posts this as a new bug, but thinking about it i realized that it's not all that easy to judge. So i use my own implementation of S1, which first pins the active window to the top, then activates the gestures target window to execute the action, and afterwards reverses the process. For ppl who just want to activate the active window - using mySafeActivateWindow() is probably the easiest solution.


function mySafeActivateWindow(target_window)
	-- try to activate the target window until it damn well works
	repeat
		acActivateWindow(target_window)
	until target_window == acGetForegroundWindow()
	acDelay(10) -- sometimes it takes a tad bit longer for the window to become responsive
end

function sp_before_action(gnm, gsx, gsy, gex, gey, gwd, gapp, gact)
	-- get window info
	user_active_window=acGetForegroundWindow()
	user_target_window=acGetParentWindowByPoint(gsx,gsy)
	-- fix the users active window so it stays on top even if it becomes inactive
	if not (user_active_window == user_target_window) then
		acToggleTopmost(user_active_window)
		mySafeActivateWindow(user_target_window)
	end
end

function sp_after_action(gnm, gsx, gsy, gex, gey, gwd, gapp, gact)
	-- unfix the users active window
	if not (user_active_window == user_target_window) then
		mySafeActivateWindow(user_active_window)
		acToggleTopmost(user_active_window)
	end
	-- discard window info
	user_active_window=nil
	user_target_window=nil
end

Rob

USA
2615 Posts

Posted - 06/20/2013 :  09:21:55  Show Profile  Visit Rob's Homepage
Thank you for your thorough post! Nothing worse than a vague complaint/nuisance/etc full of vagueness and frustration

I hear what you're saying; I haven't simply taken the stance that S+ should consider where the gesture began (as opposed to the active window) because that's what I think is best and everyone can just suck it. It boils down to flexibility. There are many instances for which I (and I would have to imagine at least a few others) don't want to have to first activate a window to have something accomplished for that window. It's important to consider that there are people who do some very crazy stuff with S+ which I never even considered to do! About 20% of my own gestures would no longer behave properly if S+ only worked in the active window.

However, there are plenty of people who also would prefer S+ only work with the active window. This situation is a prime example of the futility of trying to satisfy everyone's needs. In the end, they way S+ is currently structured is less limiting from an overall design perspective. I really set out to not impose my personal opinions of how it should work onto others, trying to make it as generic and flexible as possible. Although, there are always crossroads at which a tough call has to be made.

When it came to the target window evaluation, it seemed the better option to process actions based on where someone chose to begin drawing the gesture. Your example of case 4 above is likely the result of a call to acSendkeys, right? That's almost exclusively the only time this ever becomes an issue, simply because of how Windows handles input direction (to the active window). Yes, the truly brazen and dedicated can write write code which sends keystrokes to an inactive window, but it is a huge pain and not consistent at all, varying per application.

S1 is really the most flexible option. However, I'll admit that I could do a better job of packaging a very well written Global Lua script which handles this near flawlessly into the default installation and enabled by default. There are some apps which you just have to know that the main window is not the owner window (MediaMonkey is an example), there will always be applications that were built in an unconventional way which do not play well. But in the end, it would probably satisfy most new users, and the hardcore folks could see it's there and simply remove it...as opposed to someone like yourself having to figure it out.

That still leaves the actual evaluation of which action to use based on where the gesture began. It's certainly something I can look into and see if it can be an option (been a while since I've looked at the code).

I've definitely toned down the time I spend on S+, but there are times when I'll get the fever again and start making enhancements/fixes, so stay tuned

Thanks again for your feedback!
Go to Top of Page

mousemagician

6 Posts

Posted - 06/21/2013 :  09:44:22  Show Profile
Don't get me wrong. I did find the current behavior somewhat irritating, but i still consider being able to interact with inactive windows indispensable. Having to manually activate a window before being able to use gestures would be a total no-go. That's why i said S2 (see above post) can not be a solution but S1 can.

Though the misfiring is mostly acSendKeys that's probably because i haven't used much else yet. And i reckon that most ppl probably want to send keys 90% of the time, or click the mouse. Come to think of it afaics S+ also doesn't offer sending mouse clicks to background/inactive applications, thus for clicks you get the forced activate anyway. I guess I'm just used too much to autohotkey with its magic ControlClick and ControlSend commands. Haven't had a closer look at acSendMessage and acPostMessage, but on first look they didn't seem to be able to send nicely human readable commands like acSendKeys does.
quote:
However, I'll admit that I could do a better job of packaging a very well written Global Lua script which handles this near flawlessly into the default installation and enabled by default. There are some apps which you just have to know that the main window is not the owner window[...]

Actually i haven't had any failures with my above mySafeActivateWindow() code yet. It works around the issue of some windows no properly responding to a single acActivateWindow() by simply hammering the target until it "damn well works" (tho adding an upper limit to prevent eternal looping might be a good idea). The added 10ms delay has eliminated the problem of firefox activating but not being able to receive acSendStrokes yet (nothing happens). And with the additions to sp_after_action and sp_before action the previous window even gets it's focus back afterwards. Also i use the ParentWindow as target_window because the owner window is often something else, e.g. with file open/save dialogs the Parent is the dialog but the Owner would be the app itself, thus i don't want the Owner. Overall the target_window is only active for the split second that's needed to send the keys, and the only "drawback" is that the order of the other windows is changed because the target app is pushed to the front once and then back down again (and there doesn't seem to be any method to measure where exactly the target window or a method to push it back there). If you're going to write a built-in function feel free to use any of those ideas :P.

Go to Top of Page

Rob

USA
2615 Posts

Posted - 06/21/2013 :  15:32:56  Show Profile  Visit Rob's Homepage
acMouseClick should be able to send a click anywhere. You may want to call it like this to prevent physical mouse events from interfering:

acConsumePhysicalInput(1)
acDelay(20)
acMouseClick(100, 100, 0, 1, 1) --send a right-click @ 100,100 (x,y)
acConsumePhysicalInput(0)

Make CERTAIN you call acConsumePhysicalInput(0) or you will be pretty screwed =)

At work, so not a full response, just wanted to clarify the mouse click thing.
Go to Top of Page

mousemagician

6 Posts

Posted - 06/21/2013 :  16:15:03  Show Profile
You seem to have misunderstood me. I didn't mean: "You can not sent a mouse click to an inactive window." i meant: "By sending a mouse click to an inactive window you will activate that window." Aka, the mouse click itself will activate the window. Just tried and confirmed that and it's even worse, acMouseClick doesn't only sent a mouse click, it also _moves_ the mouse^^.

The magic ControlClick in Autohotkey can actually send a mouse click to a window, without causing that click to activate the window and without moving the mouse. I guess you haven't used AutoHotkey yourself much, you should try it once :D.

(I'm still in love with the gestures in S+ here, don't get me wrong. I'm just fantasizing about the ultimate customization tool.)
Go to Top of Page
  Previous Topic Topic Next Topic  
 Forum Locked
 Printer Friendly
Jump To:
StrokesPlus Forum © 2011-2018 Rob Yapchanyk Go To Top Of Page
Snitz Forums 2000