Gtk - Intercept Mouse Button Events in Top Level Window - gtkmm

Keyboard events in Gtk propagates bottom up, starting from the top level window and then up the Z order. However mouse button events are first delivered to the widget at the top of the Z order and it is propagated down only if it is not handled there.
I am trying to implementing a UI lock feature where mouse button / touch events are to be ignored unless the user is clicking on the unlock button.
Is there any way in which I can intercept button presses at the top level window itself? I tried connecting to the signal_button_press_event with the after argument set to false. Even then the events are delivered to the child widget first.
Earlier I was using gdk event filters (Gdk::Window::add_filter) to do this however that works only on X11 backend and does not work for Wayland.
Updated after comment for adding minimal code
CTestWindow is a top level window derived from Gtk::Window. The button press signal is intercepted as below in the class constructor.
signal_button_press_event().connect(sigc::mem_fun(*this,
&CTestWindow::HandleButtonPress),
false);
This is how the handler is implemented
bool CTestWindow::HandleButtonPress(GdkEventButton *pEvent)
{
bool bRet = false;
/*
* If the button press coordinate is outside the allocated area of the unlock button,
* discard the event (by returning as processed).
*/
if (!CCommon::IsWithinBounds(m_oUnlockButton.get_allocation(),
(int)pEvent->x,
(int)pEvent->y))
{
bRet = true;
}
return bRet;
}

Related

how to see mouseReleased() event outside canvas using processing.js

I have an object I want to drag around the screen with the mouse in Processing. I set acquired to true on mouse down over the object, and to false on mouse up, thus:
void mousePressed() {
if (overThing()) {
acquired = true;
}
}
void mouseReleased() {
acquired = false;
}
I then query acquired in my update(), and drag the object if it is true.
void update() {
\\ other stuff...
if (acquired) {
\\ drag thing code ...
}
}
This all works fine in Processing. mouseReleased() gets called whether I release the mouse inside or outside the active window.
However, when I move the code to Chrome, using processing.js (v1.4.8), mouseReleased() is not called if I release the mouse outside the canvas (whether the mouse is still over the web page, or outside the browser window). So when I return the (now unclicked) mouse to the canvas, the object is still getting dragged around.
I tried including a test of mousePressed in update(), but that also returns true in these circumstances.
Any help on what I need to do to make mouse state changes outside the canvas visible with processing.js?
I don't know about Processing specifically, but releasing mouse buttons outside a widget is a common issue in GUI development.
I suspect that you have no way of knowing the precise time when the mouse is released outside the widget, but you do have two options:
Set acquired = false in mouseOut(), as #Kevin suggests.
I assume there is some type of mouseEntered() method in Processing, and also some way of knowing if the mouse button is currently pressed (either a global variable, or an event object passed to mouseEntered()). You can catch the mouse entered event, check if the mouse has been released, and set acquired = false then.
Like so:
void mouseEntered() {
if (mouse button is pressed) {
acquired = false;
}
}
Edit: From your comments, #Susan, it seems like there is a bug in processing.js, where mousePressed is not set to false if the mouse button is released outside the canvas. One thing pointing to this being a bug is that the mouse movement example on the processing website also shows this behaviour.
Depending upon how much control you have over the website this is going on, and how much effort you want to go to, you could fix the bug yourself by writing some javascript (separate from your processing code):
Define a mouseUp() event on the page <body>, to catch all mouse release events on the page.
In the mouseUp() event, check if the event comes from your Processing control. (There is probably an event object passed to the mouseUp() function, and you might have to give your Processing control an ID to identify it)
If the event doesn't come from your Processing control, then fire a mouseUp event yourself, on the Processing control. This should (hopefully!) trigger a mouse event inside your Processing code.
I'm not sure what Processing will make of the mouse (x,y) position being outside its control when it handles the event you send it. You might want to set a flag on the event object (assuming you can add extra data to the event object) to say "don't use the (x,y) position of this event - it's outside the control".
Edit2: It was easier than I thought! Here is the JavaScript code to detect the mouse being released outside of the Processing canvas and send the mouseReleased event to the canvas. I've tested it on the mouse movement example from the Processing website, and it fixes the bug.
It uses jQuery (although it could be re-written to not use jQuery), and it assumes your Processing canvas has the ID "processingCanvas":
$(':not(processingCanvas)').mouseup(function(){
Processing.getInstanceById('processingCanvas').mouseReleased();
});
To use this code, include it anywhere in your page (in a JavaScript file or in <script> tags) and make sure you have the jQuery library included before this code.
The Processing object allows JavaScript to call any functions defined in your Processing code. Here I've used it to call Processing's built in mouseReleased() function, but if you wanted to call a custom function to handle the mouse-released-outside state differently, then you could.
You should use the mouseOut() function to detect when the mouse leaves the sketch:
void mouseOut() {
acquired = false;
}
More info in the reference here.

wxWidgets Closing window from system menu

I am working on wxWidgets, In wxFrame I handled wxEVT_CLOSE event, inside the event handler I called Iconize(). When pressing the close button my window will be minimized it is work correctly. But while clicking quit from my system menu that time also my window is minimizing. But in my scenario I want to close my window from system menu and want to minimize while clicking close button.
This is my handler.
void Frame::OnClose(wxCloseEvent& event)
{
Iconize(true);
}
You can't distinguish between closing the window from the system menu and using the close button at wxWidgets API level. You can, however, do it using platform-specific code. For example, for MSW you can override MSWWindowProc() in your wxFrame-derived class and handle WM_SYSCOMMAND there and explicitly exit the application, instead of just iconizing it, when SC_CLOSE is received.
Just process menu command in other handler and call Destroy directly.
BEGIN_EVENT_TABLE(wxMyFrame,wxFrame)
EVT_MENU(wxMyFrame::idMenuQuit, wxMyFrame::OnMenuClose) // sample for using event table
END_EVENT_TABLE()
void wxMyFrame::OnMenuClose(wxCommandEvent& event)
{
Destroy();
}

How to prevent window from loosing focus when receiving a grabbed key from X11

My window calls hide() when a QEvent::FocusOut is received. Simultaniously I want its visibility to be toggled if a hotkey is pressed. Now I have the following problem: Pressing the hotkey, registered with XGrabKex(...) seems to steel the focus of my app. Resulting in an unwanted behaviour. If my app is visible the hotkeyevent steels focus, which results in a QEvent::FocusOut, which hides my app, and after that the hotkey is received which toggles visibility (shows) my app. I.e. my app does not hide when pressing the hotkey.
Is there a way to tell the x window system to not steel the focus when a grabbed key is pressed? Or are there other possible solutions to this problem?
A couple of different methods.
Use XQueryKeymap to see which keys are pressed. For instance, when you get a FocusOut event, call XQueryKeymap and see if your hotkey is pressed. If it is not, hide the window; if it is, don't hide it and wait for the hotkey event.
Delay hiding on FocusOut by 100 or so milliseconds. Cancel hiding if you either get the hot key or get your focus back during this time interval.
Look also here for useful info.
Finally got it to work in a "proper" way:
bool MainWidget::nativeEvent(const QByteArray &eventType, void *message, long *)
{
#ifdef Q_OS_LINUX
if (eventType == "xcb_generic_event_t")
{
xcb_generic_event_t* event = static_cast<xcb_generic_event_t *>(message);
switch (event->response_type & 127)
{
case XCB_FOCUS_OUT: {
xcb_focus_out_event_t *fe = (xcb_focus_out_event_t *)event;
if ((fe->mode==XCB_NOTIFY_MODE_GRAB && fe->detail==XCB_NOTIFY_DETAIL_NONLINEAR)
|| (fe->mode==XCB_NOTIFY_MODE_NORMAL && fe->detail==XCB_NOTIFY_DETAIL_NONLINEAR ))
hide();
break;
}
}
}
#endif
return false;
}

Cancel WinJS.UI.Animation.pointerDown if not clicked

I'm using WinJS.UI.Animation.pointerDown and WinJS.UI.Animation.pointerUp within a WinJS repeater's item template.
The problem is if a user holds their finger or the mouse button down on an item and moves off it, the pointerUp animation doesn't seem to fire or it fires but has no effect because the element that the up event is on is not the same as the one before. The best example of this is in the animation sample in example 6 (tap and click). Hold down the mouse button on a tile and move it off. It will stay in it's animated state and won't fire the pointerup event. Here's the code I'm using.
How can I cancel the pointerdown animation if the user moves off the element?
target1.addEventListener("pointerdown", function () {
WinJS.UI.Animation.pointerDown(this);
}, false);
target1.addEventListener("pointerup", function () {
WinJS.UI.Animation.pointerUp(this);
}, false);
target1.addEventListener("click", function () {
//do something spectacular
}, false);
I'm using the click event to commit the click action so that the right click remains clear for launching the navigation at the top of the app.
Have you tried adding an event listener for pointerout? That's the event that's dispatched when a pointing device (e.g. mouse cursor or finger) is moved out of the hit test boundaries of an element.
See the docs on pointer events here:
http://msdn.microsoft.com/en-us/library/ie/hh772103(v=vs.85).aspx

Custom context menu XAML for WP8

I try to implement a custom ContextMenu in a LongListSelector.
I'm not using the ContextMenu from Microsoft.Phone.Controls.Toolkit, it's basically the same as in the Rowi App:
(source: hiddenpineapple.com)
Approach 1
My list item toggles a VisualState on hold and an overlay is shown with controls in it.
The problem
I can't find a way to go back to the default state when the user clicks outside of the list item (as in the default ContextMenu).
Approach 2
I've implemented a custom template for the toolkit ContextMenu which looks exactly the same. I had to move its margin top to -itemHeight, as by default it is below the item.
The problem
The problem with this solution is, that it automatically closes itself when opening and I couldn't figure out how to avoid this.
Another problem was that it didn't work well with TiltEffect.IsTiltEnabled from the Toolkit (visual problems).
I need your help
Any suggestions on how to get this working?
Answer
Thanks to Cheese, now I know how to properly close the menu when the user clicks outside.
His suggestion was to get the coordinates of a Tap event on the current page, and check if it's inside the menu. When not, close the menu.
So I added a Tap listener to the page when the menu opens, and removed it when the menu closes. From the page listener I got the event coordinates and could check if it's inside the control which holds the menu (same size and position). I received the position of the control with Point leftUpperPoint = control.TransformToVisual(page).Transform(new Point(0, 0)) and the rightLowerPoint by adding the ActualWidth and ActualHeight.
But then I realized:
Why should I even calculate if the tap is inside the menu? I always want to close the menu when the user taps anywhere on the screen. If it's outside, yes. If it's on a menu button, yes.
Another modification I made was to listen for MouseLeftButtonDown instead of Tap as it also triggers when the user swipes.
So I removed this code and came up with the following:
private void ToggleMenu(object sender, System.Windows.Input.GestureEventArgs e)
{
PhoneApplicationFrame frame = ((PhoneApplicationFrame)Application.Current.RootVisual);
VisualState state = this.States.CurrentState;
if (state == null || state.Name == "DefaultState")
{
frame.MouseLeftButtonDown += MouseDownDelegate;
this.State = "MenuState";
}
else
{
frame.MouseLeftButtonDown -= MouseDownDelegate;
this.State = "DefaultState";
}
}
private void MouseDownDelegate(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
ToggleMenu(sender, null);
}
This works perfectly!
Thanks to Cheese for the hint.
Something like this by #denniscode http://dotnet.dzone.com/articles/rowi-show-tap-menu
Approach 1 problem
The best solution would be:
Get the menus coordinates, when user makes a tap - you check are tap coordinates on menu or not, if not - dissmiss - simple.
Approach 2 problem
I guess you had some button in a corner and when you tapped on it - nothing happened? And when you dissmissed the Tilt all worked. It seems that tilt works faster than a click, so, tilt changes the button coordinates, and device thiks you have missed/or dragged off
You can use what #ScottIsAFool suggested and maybe create another Dependency Property on your TapMenu control of type UIElement named CloseWhenTappedElement and automatically listen for Tap events inside your control once set. For example
<Grid x:Name="TapArea"/>
<TapMenu CloseWhenTappedElement="{Binding ElementName=TapArea"}/>