wxGLCanvas strange focus behavior on MSW

59 views
Skip to first unread message

ardi

unread,
Jun 1, 2012, 1:38:50 PM6/1/12
to wx-users
As you can see in the OpenGL samples (for example take a look at the
penguin sample) on MSW the focus is lost when the mouse leaves the
glcanvas even if you're dragging the view... in other words, dragging-
type wxMouseEvents don't grab the focus.

This behavior is "strange" from a user point of view. The behavior on
the OSX-Cocoa port is what the user would expect (focus grabbed when
dragging). I suppose wxGTK will also grab the focus, although I didn't
test it.

The worst point of this isn't that you lose the focus, but that if
your app has several wglcanvas, the focus changes to the wglcanvas
behind the cursor _while_ you're dragging. This can be really
confusing. For example, I tried this with an app that uses several
canvases for different views, and when you're dragging a view near its
border, you easily begin dragging the neighbor wglcanvas.

Is there some way of grabbing the focus on MSW when a wglcanvas is
dragged?

TIA

ardi

Vadim Zeitlin

unread,
Jun 4, 2012, 8:17:02 PM6/4/12
to wx-u...@googlegroups.com
On Fri, 1 Jun 2012 10:38:50 -0700 (PDT) ardi wrote:

a> As you can see in the OpenGL samples (for example take a look at the
a> penguin sample) on MSW the focus is lost when the mouse leaves the
a> glcanvas even if you're dragging the view... in other words, dragging-
a> type wxMouseEvents don't grab the focus.

I think it's simply because TestGLCanvas::OnMouse() doesn't call
event.Skip() and also unnecessarily catches all mouse events instead of
just the movement ones. So the click never reach the native window and it
never gets focus.

a> Is there some way of grabbing the focus on MSW when a wglcanvas is
a> dragged?

I'm not sure if you mean focus, in the sense of SetFocus(), or mouse
capture, in the sense of CaptureMouse(). The sample is badly written and
doesn't do the latter while it definitely should. If you want to implement
something like this yourself, do call CaptureMouse() and react to mouse
capture lost events.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

ardi

unread,
Jun 10, 2012, 6:19:00 PM6/10/12
to wx-u...@googlegroups.com

On Tuesday, June 5, 2012 2:17:02 AM UTC+2, Vadim Zeitlin wrote:
On Fri, 1 Jun 2012 10:38:50 -0700 (PDT) ardi wrote:
[...]


a> Is there some way of grabbing the focus on MSW when a wglcanvas is
a> dragged?

 I'm not sure if you mean focus, in the sense of SetFocus(), or mouse
capture, in the sense of CaptureMouse(). The sample is badly written and
doesn't do the latter while it definitely should. If you want to implement
something like this yourself, do call CaptureMouse() and react to mouse
capture lost events.

Yes, I meant CaptureMouse() (didn't know this feature was available in wxWidgets).

Anyway, it's not a problem in the OpenGL samples, but in wxGLCanvas, because the MSW port doesn't capture mouse while dragging. The OSX port captures it, and I guess all other platforms will capture it as well, because that's the behavior the user expects to find.

What I'm doing now after your advice is to call CaptureMouse() when a mouse button is pressed, and call ReleaseMouse() when a mouse button is released (unless a MouseCaptureLost event is found, in which case no call to ReleaseMouse() is done... I don't know if I understood this correctly).

This fixes the problem, and with this the MSW port works the same as the rest.

These calls are enclosed between '#ifdefs' conditional blocks, because I use that only on MSW, as the other platforms work fine without this.

Thanks a lot for your advice, which allowed me to find a solution!

ardi
 

Vadim Zeitlin

unread,
Jun 11, 2012, 7:31:15 AM6/11/12
to wx-u...@googlegroups.com
On Sun, 10 Jun 2012 15:19:00 -0700 (PDT) ardi wrote:

a> Anyway, it's not a problem in the OpenGL samples, but in wxGLCanvas,
a> because the MSW port doesn't capture mouse while dragging. The OSX port
a> captures it, and I guess all other platforms will capture it as well,
a> because that's the behavior the user expects to find.

Does wxOSX do it for all windows or just wxGLCanvas? Because while this
could be the expected behaviour in your case, I think it would be pretty
unexpected if it did for plain wxWindow...

a> What I'm doing now after your advice is to call CaptureMouse() when a mouse
a> button is pressed, and call ReleaseMouse() when a mouse button is released
a> (unless a MouseCaptureLost event is found, in which case no call to
a> ReleaseMouse() is done... I don't know if I understood this correctly).

Yes, you did.

a> These calls are enclosed between '#ifdefs' conditional blocks, because I
a> use that only on MSW, as the other platforms work fine without this.

Presumably you don't get mouse capture lost however if you don't capture
the mouse. So capturing it explicitly could still be the right thing to do.

ardi

unread,
Jun 11, 2012, 9:39:19 AM6/11/12
to wx-users


On 11 jun, 13:31, Vadim Zeitlin <va...@wxwidgets.org> wrote:
> On Sun, 10 Jun 2012 15:19:00 -0700 (PDT) ardi wrote:
>
> a> Anyway, it's not a problem in the OpenGL samples, but in wxGLCanvas,
> a> because the MSW port doesn't capture mouse while dragging. The OSX port
> a> captures it, and I guess all other platforms will capture it as well,
> a> because that's the behavior the user expects to find.
>
>  Does wxOSX do it for all windows or just wxGLCanvas? Because while this
> could be the expected behaviour in your case, I think it would be pretty
> unexpected if it did for plain wxWindow...
>

No, Im talking about wxglcanvas only although other widgets, like
wxslider, also capture the mouse in all platforms, msw included. I
believe all users expect an opengl view to behave just like wxslider
mouse-wise

ardi

Vadim Zeitlin

unread,
Jun 11, 2012, 9:42:11 AM6/11/12
to wx-u...@googlegroups.com
On Mon, 11 Jun 2012 06:39:19 -0700 (PDT) ardi wrote:

a> No, Im talking about wxglcanvas only although other widgets, like
a> wxslider, also capture the mouse in all platforms, msw included. I
a> believe all users expect an opengl view to behave just like wxslider
a> mouse-wise

I'm really not sure. wxSlider is a specific control so of course it does
whatever it needs to do to allow dragging its position indicator. But
wxGLCanvas is a generic window, just like wxWindow, and it might not
support dragging at all and it could be unexpected if simply clicking on it
captured the mouse.

It would be interesting to check what does wxGTK do here but I don't think
it captures the mouse so I'd change wxOSX to not do this neither.

ardi

unread,
Jun 11, 2012, 12:40:15 PM6/11/12
to wx-u...@googlegroups.com


On Monday, June 11, 2012 3:42:11 PM UTC+2, Vadim Zeitlin wrote:
On Mon, 11 Jun 2012 06:39:19 -0700 (PDT) ardi wrote:

a> No, Im talking about wxglcanvas only although other widgets, like
a> wxslider, also capture the mouse in all platforms, msw included. I
a> believe all users expect an opengl view to behave just like wxslider
a> mouse-wise

 I'm really not sure. wxSlider is a specific control so of course it does
whatever it needs to do to allow dragging its position indicator. But
wxGLCanvas is a generic window, just like wxWindow, and it might not
support dragging at all and it could be unexpected if simply clicking on it
captured the mouse.  

 It would be interesting to check what does wxGTK do here but I don't think
it captures the mouse so I'd change wxOSX to not do this neither.
 
My guess is that wxGTK will capture the mouse, because that's always been the default OpenGL behavior everywhere. For example, standard Motif apps (non-wx, just plain Motif) capture the mouse by default. The same happens with all GLX demos I've seen on Linux, and OpenGL apps on OSX. And they do it automatically... nobody cares to "capture" the mouse, because it's done by the system by default.

Just consider the scenario I explained in the first post: Imagine an app with two gl canvases, side by side. Canvas one is a camera view of a 3D building, while canvas two is a plan view of the same 3D building. Imagine you drag the plan view, and the mouse cursor exits the plan canvas and enters the camera canvas. What would the user expect? Continue dragging the plan view, or begin dragging the camera view? Of course the user will expect to continue dragging the plan view unless the mouse button is released and the camera view is explicitly dragged.

Cheers,

ardi




Vadim Zeitlin

unread,
Jun 11, 2012, 2:01:50 PM6/11/12
to wx-u...@googlegroups.com
On Mon, 11 Jun 2012 09:40:15 -0700 (PDT) ardi wrote:

a> My guess is that wxGTK will capture the mouse, because that's always been
a> the default OpenGL behavior everywhere. For example, standard Motif apps
a> (non-wx, just plain Motif) capture the mouse by default.

I didn't know this.

a> Just consider the scenario I explained in the first post: Imagine an app
a> with two gl canvases, side by side. Canvas one is a camera view of a 3D
a> building, while canvas two is a plan view of the same 3D building. Imagine
a> you drag the plan view, and the mouse cursor exits the plan canvas and
a> enters the camera canvas. What would the user expect? Continue dragging the
a> plan view, or begin dragging the camera view?

The alternative in this question is incorrect anyhow. Of course you
wouldn't expect to start dragging a view which had never been clicked. The
fact that it happens in the sample is just a bug in the sample code, as I
wrote it just checks that the mouse is being dragged but not that we
actually started dragging it in this window. This is definitely wrong.

ardi

unread,
Jun 12, 2012, 4:17:37 AM6/12/12
to wx-u...@googlegroups.com


On Monday, June 11, 2012 8:01:50 PM UTC+2, Vadim Zeitlin wrote:

 The alternative in this question is incorrect anyhow. Of course you
wouldn't expect to start dragging a view which had never been clicked. The
fact that it happens in the sample is just a bug in the sample code, as I
wrote it just checks that the mouse is being dragged but not that we
actually started dragging it in this window. This is definitely wrong.


Hmm... this confuses me... do you mean that if a canvas gets a mouse motion event it must first check if such event belongs to it or to another canvas?... events received by a widget are supposed to belong to it, don't they?

For example, if I start dragging on a button and the cursor moves over another button, does the second receive a dragging event? If affirmative, is the second button expected to communicate the first one that a dragging event belongs to it? 

Anyway, it now works for me, by explicitly calling CaptureMouse() when compiling on MSW. I was talking about this just because OpenGL apps are what I've done most for the last 15 years (mostly UNIX, though) and I found this mouse behavior on MSW quite strange...

But maybe that's the standard in Microsoft's wgl widget... I don't know because I've never coded wgl apps directly, but if that's its default behavior, it's the only platform where it happens, AFAIK.

Cheers,

ardi
  

Vadim Zeitlin

unread,
Jun 12, 2012, 7:25:50 AM6/12/12
to wx-u...@googlegroups.com
On Tue, 12 Jun 2012 01:17:37 -0700 (PDT) ardi wrote:

a> On Monday, June 11, 2012 8:01:50 PM UTC+2, Vadim Zeitlin wrote:
a> > The alternative in this question is incorrect anyhow. Of course you
a> > wouldn't expect to start dragging a view which had never been clicked. The
a> > fact that it happens in the sample is just a bug in the sample code, as I
a> > wrote it just checks that the mouse is being dragged but not that we
a> > actually started dragging it in this window. This is definitely wrong.
a> >
a> Hmm... this confuses me... do you mean that if a canvas gets a mouse motion
a> event it must first check if such event belongs to it or to another
a> canvas?... events received by a widget are supposed to belong to it, don't
a> they?

Yes, they are but the sample doesn't check for motion events. It checks
for dragging events, i.e. motion events with a mouse button being pressed
down. And this is wrong because if you pressed the button outside of the
window and then moved the mouse into the window, it shouldn't count as
dragging event.

a> For example, if I start dragging on a button and the cursor moves over
a> another button, does the second receive a dragging event?

No because the first button captures the mouse and so gets all mouse
events until it releases the mouse.

a> Anyway, it now works for me, by explicitly calling CaptureMouse() when
a> compiling on MSW.

I can only repeat that IMO you should do this under all platforms. This
might work without CaptureMouse() under Mac and even GTK (although AFAIU
you didn't test this there) right now but it could change in the future.
With CaptureMouse() it should always work.

Richard

unread,
Jun 12, 2012, 11:47:23 AM6/12/12
to wxWidgets Users

In article <cd06934c-9f8d-4aba...@googlegroups.com>,
ardi <ardillas...@gmail.com> writes:

> Anyway, it now works for me, by explicitly calling CaptureMouse() when
> compiling on MSW. I was talking about this just because OpenGL apps are
> what I've done most for the last 15 years (mostly UNIX, though) and I found
> this mouse behavior on MSW quite strange...

Capturing the mouse is the right thing to do; I'm not sure what
frameworks you've used on unix in the past, but if you do low-level
Xlib/GLX programming, you'd have to capture the mouse yourself in order
to get the behavior you're after.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Reply all
Reply to author
Forward
0 new messages