<AWT Dev> <Swing Dev> Public RequestFocusController/AWTAccessor API

Semyon Sadetsky semyon.sadetsky at oracle.com
Mon Apr 18 09:24:21 UTC 2016


YW.
You can track the new request here 
https://bugs.openjdk.java.net/browse/JDK-8154431

--Semyon

On 4/18/2016 11:26 AM, Reto Merz wrote:
> That sounds good.
>
> Thanks for you efforts.
>
> Best Regards
> Reto Merz
>
>
> On 4/14/2016 22:11, Semyon Sadetsky wrote:
>> On 4/14/2016 9:25 PM, Reto Merz wrote:
>>
>> This is a small part of our focus/validation framework.
>> I just try to explain it as simple as possible.
>>
>> javax.swing.InputVerifier gives only access to the source component.
>>
>> We need to know the target component.
>>
>> Would it be possible to overload verify(..) (or introduce another method) which has the "to"/target component as a argument too?
> Yes. That is what I will be able to do. Something like:
>
>     public boolean verifyTarget(JComponent input) {
>        return true;
>    }
>
>    public boolean shouldYieldFocus(JComponent from, JComponent to) {
>      return shouldYieldFocus(from) && verifyTarget(to);
>    }
>
> --Semyon
>
>> Thanks
>> Reto Merz
>
> On 14.04.2016 16:52, Semyon Sadetsky wrote:
>
> Thank for explanation.
> It seems to me such functionality belongs to the input validation domain
> and should not be mixed up with the Swing focus transfer internals.
> Swing has javax.swing.InputVerifier which you could extend and set to
> each component of your framework. I suppose it would be better design
> choice for you because it decouples your code from the focus transfer
> details which may be changed in future JDK releases. While the
> javax.swing.InputVerifier functionality will be preserved.
>
> --Semyon
>
> On 4/14/2016 4:58 PM, Reto Merz wrote:
>
> Exactly, the target can reject the focus transfer (and the source too).
> All our UI components support "FocusRequestEnterExit" listeners
> which has a requestEnter(EnterExitEvent) and requestExit(EnterExitEvent) method (among others focusGained/focusLost methods).
> The EnterExitEvent has a reject() and accept() method.
>
> requestEnter is invoked on the target component and requestExit on the source component listeners.
> The focus is only transferred after all source/target listeners have accept it.
> This can be used for simple user input validation.
>
> It is far more complex because our RIA is ULC based (https://ulc.canoo.com/developerzone/technicalconcept.html)
> which split UI components into client- and server-side half objects,
> but, basically this is how parts of our focus/validation framework works.
>
> Open Component#requestFocusInWindow(CausedFocusEvent.Cause) does not work
> because this allows only conditional invoking super.requestFocusInWindow.
> At this point it is not yet clear if the focus can be really transferred (see isRequestFocusAccepted).
> And after super.requestFocusInWindow it is to late because
> KeyboardFocusManager.setMostRecentFocusOwner is already invoked.
>
>   From my point of view the best (and easiest to maintain) solution is
> introducing a isRequestFocusAccepted() method which is invoked
> by isRequestFocusAccepted(boolean,boolean,CausedFocusEvent.Cause) at the end.
> So the new isRequestFocusAccepted makes the final decision to transfer focus or not.
> Furthermore that dont require to make CausedFocusEvent.Cause public (which looks a bit creepy).
>
> Best Regards
> Reto Merz
>
>
> On 14/04/16 14:49, Semyon Sadetsky wrote:
>
> Okay... You said the you need to intercept the focus request in the place
> where the target is set.
>    From my point of view opening
> Component#requestFocusInWindow(CausedFocusEvent.Cause cause)
> resolves that.
> But it looks like you need extra. What is the final purpose? Maybe you want
> to reject focus transfer depending on the target?
>
> --Semyon
>
> On 4/14/2016 3:19 PM, Reto Merz wrote:
>
> Thanks for your investigation Semyon.
>
> Make Component#requestFocusInWindow(CausedFocusEvent.Cause
> cause) public/protected will not help us.
>
> I can explain it more detailed if you want.
>
> What would help is to introduce a "protected boolean
> Component#isRequestFocusAccepted()"
>
> which is invoked by
> Component#isRequestFocusAccepted(boolean,boolean,CausedFocusEvent.
> Caus
>
> e) after the "Component.requestFocusController.acceptRequestFocus"
> statement (and only if acceptRequestFocus has returned true).
>
> This way you also don't have to make CausedFocusEvent.Cause public.
>
> Best Regards
> Reto Merz
>
> On 14/04/16 13:09, Semyon Sadetsky wrote:
>
> The FocusTraversalPolicy can be obtained using public API. It may give you
> the target. But I believe this is not what you would like to do...
>
> It seem sensible to make
> Component#requestFocusInWindow(CausedFocusEvent.Cause cause)
> public. Will it be enough for you?
>
> I could start to implement this right after the 8080395 push.
>
> --Semyon
>
> On 4/14/2016 12:30 PM, Reto Merz wrote:
> Hello Semyon,
>
> We need to know the target component: "which component will be
> focused".
>
> Target component means the component which should be "really"
> focused,
>
> so this can only be known after all the FocusCycle / FocusTraversalPolicy
> logic has processed.
>
> DefaultKeyboardFocusManager
> focusNextComponent/focusPreviousComponent
>
> provides only the source component. Not the target.
>
> The second argument of RequestFocusController#acceptRequestFocus is
> the "real" target component.
>
> We use only this argument in our custom RequestFocusController
> implementation.
>
> Thanks
> Reto Merz
>
> On 14/04/16 08:31, Semyon Sadetsky wrote:
> Hi Reto,
>
> It is unlikely that AWTAccessor API may be opened. It gives access to
> internal undocumented methods not to even mention that those methods
> have private and package accesses.
>
> As I understand you need the way to intercept focus transfer initiated by a
> traversal key. Why to subclass the DefaultKeyboardFocusManager to
> override its focusNextComponent/ focusPreviousComponent methods?
>
> --Semyon
>
> On 4/12/2016 2:37 PM, Reto Merz wrote:
> Hello Alexandr,
>
> Basically we need to detect and intercept focus changes.
>
> java.awt.Component allows to override this methods:
> requestFocus()
> requestFocus(boolean)
> requestFocusInWindow()
> requestFocusInWindow(boolean)
>
> requestFocus() is only invoked when the component is focused by a mouse
> click.
>
> But no requestFocus* method is invoked when a FocusTraversalPolicy is
> involed (f. e. the user press TAB to focus next component).
>
> sun.awt.RequestFocusController#acceptRequestFocus is invoked in both
> cases.
>
> Attached a demo to reproduce it:
> - if TextField is focused by a mouse click "requestFocus" and
> "acceptRequestFocus" is logged
> - if TextField is focused by TAB only "acceptRequestFocus" is logged
>
> Some more notes about the test program:
> ComponentAccessorDelegator delegates all calls to the original
> ComponentAccessor implementation.
>
> Only ComponentAccessor#setRequestFocusController is changed to keep
> our RequestFocusController implementation.
>
> I have just filled a RFE onhttp://bugreport.java.com/bugreport
>
> Thanks
> Reto Merz
>
>
> On 11/04/16 21:02, Alexander Scherbatiy wrote:
>     Hello Reto,
>
>     Could you provide use cases which illustrate tasks the requested API is
> intended to solve in your application?
>
>     Please, also create a request in the bug system
> http://bugreport.java.com/bugreport
>
>     Thanks,
> Alexandr.
>
> On 11/04/16 12:26, Alexander Scherbatiy wrote:
>
>     Resending the request to awt-dev alias.
>
>     Thanks,
>     Alexandr.
>
> On 4/4/2016 4:54 PM, Reto Merz wrote:
> Hello,
>
> Jigsaw will disallow access to internal packages.
> We have written a complex validation and focus management
> implementation for our closed-source RIA and maintain it since JRE
> 1.4.
>
> For this we use some internal API. We have a custom implementation of
> these interfaces:
>
> sun.awt.RequestFocusController
> sun.awt.AWTAccessor.ComponentAccessor
>
> And use this getter and setter:
>
> sun.awt.AWTAccessor#setComponentAccessor(AWTAccessor.ComponentAc
> cesso
>
> r)
> sun.awt.AWTAccessor#getComponentAccessor()
> sun.awt.AWTAccessor.ComponentAccessor#setRequestFocusController(Req
> ue
>
> stFocusController)
>
>
> Please make this API public.
>
> Furthermore we need to call
> java.awt.Component#revalidateSynchronously().
> We do this with reflection. It would be nice to have a public API for
> this.
> Maybe a new static method on AWTAccessor:
> AWTAccessor.revalidateSynchronously(Component)
>
> Best Regards
> Reto Merz
>
>
>
>
>
>
>
>
>
>



More information about the awt-dev mailing list