Gtk Grab pointer without "stealing" it from other software - gtk

Currently in my application I'm grabing the pointer to know when user clicks outside of some of my first window's widgets to hide my second window. Unfortunately if I grab the pointer then user needs to click outside of my application twice to set focus on another window.
When window gets focus I grab the pointer:
this.focus_in_event.connect(()=>{
var pointer = Gdk.Display.get_default ().get_device_manager ().get_client_pointer ();
pointer.grab (this.get_window (), Gdk.GrabOwnership.NONE, true,
Gdk.EventMask.BUTTON_PRESS_MASK, null, Gdk.CURRENT_TIME);
Gtk.device_grab_add (this, pointer, false);
return false;
});
When a click events occurs and some of window's widgets didn't 'lock' the pointer:
this.button_press_event.connect ( ()=>{
if (!lock_mouse_click) {
var pointer = Gdk.Display.get_default ().get_device_manager ().get_client_pointer ();
Gtk.device_grab_remove (this, pointer);
pointer.ungrab (Gdk.CURRENT_TIME);
feed_view.hide ();
}
lock_mouse_click = false;
return false;
});
What I would like to do is to "peek" at the pointer instead of stealing the mouse events outside of my application.
My code in vala but you may answer me in any language that uses gtk.

why dont you use "enter-notify-signal" ? when apointer enter your widget's window, create a on/off switch somewhere and use it in "button-press-signal". if its on when button is pressed do somethin, if its off do something else

Related

How to intercept system keypress in a GTK application

I am working on a Vala GTK application that starts minimized by default and I want to bind a specific keyword shortcut to bring the minimized window to the front.
I am able to handle Keyboard events using Accelerators when the app is focus ed, but I am unable to intercept any key press from the system when the app is minimized.
How can I make the app listen to system keyboard events so I can detect the key press accordingly?
Thank you.
I took a look at the source for Ideogram to see how it registers Super-e as a hot-key. It looks to be basically the following, including first checking that a custom hot-key has not already been registered for the application.
// These constants are set at class level.
public const string SHORTCUT = "<Super>e";
public const string ID = "com.github.cassidyjames.ideogram";
// Set shortcut within activate method.
CustomShortcutSettings.init ();
bool has_shortcut = false;
foreach (var shortcut in CustomShortcutSettings.list_custom_shortcuts ()) {
if (shortcut.command == ID) {
has_shortcut = true;
return;
}
}
if (!has_shortcut) {
var shortcut = CustomShortcutSettings.create_shortcut ();
if (shortcut != null) {
CustomShortcutSettings.edit_shortcut (shortcut, SHORTCUT);
CustomShortcutSettings.edit_command (shortcut, ID);
}
}
It uses a CustomShortcutSettings class included in its source to handle the reading and writing to the system settings. The class originated in another application called Clipped.

Gui.Window ContextClick

Is there a way to add an Event.ContextClick to a Gui.Window in a Unity Editor script?
The following is my context menu method that I've tried calling from both OnGUI() and my window's WindowFunction (call sites denoted below as "site: no luck"). I have not been able to get the "Success" message to show up unless I'm right clicking directly in the main editor window. If I right click in any of the Gui.Windows I have created, the ContextClick event doesn't show up.
void OnStateContextMenu(){
Event evt = Event.current;
// Ignore anything but contextclicks
if(evt.type != EventType.ContextClick)return;
Debug.Log("Success");
// Add generic menu at context point
GenericMenu menu = new GenericMenu();
menu.AddItem (new GUIContent ("AddState"),false,AddState,evt.mousePosition);
menu.ShowAsContext ();
evt.Use();
}
And the call site(s):
void doWindow(int id){
// OnStateContextMenu(); //site1: no luck
GUI.DragWindow();
}
void OnGUI(){
OnStateContextMenu(); //site2: no luck here either
BeginWindows();
wndRect = GUI.Window(0,wndRect,doWindow,"StateWnd");
EndWindows();
}
Update
For reference, green area responds to right-click, red area does not. But I want it to. The right-click menu I've created has specific actions I only want visible if the mouse cursor right clicks inside one of my windows, the 'Hello' in the image. Note: Ignore the button, right click doesn't work anywhere inside that window.
This might not directly answer your question but should be able to help
You are trying to achieve a rightclick function inside your red box( as shown in picute )
I had a sort alike question a while back but it was not for a rightclick but for a mouseover
so i figured this might be able to help you
string mouseover; // first of i created a new string
if (GUI.Button (new Rect (100,100,200,200),new GUIContent("Load game", "MouseOverOnButton0") ,menutexture ))
{
//added a mousoveronbutton command to my GUIcontent
executestuff();
}
buttoncheck();
}
void buttoncheck()
{
mouseover = GUI.tooltip;
if(mouseover == "MouseOverOnButton0")
{
GUI.Box(new Rect(380,45,235,25),"Not a implemented function as of yet ");
}
}
this code made a new gui box the moment the mouse hitted the box.
If you created the hello in a seperate box you could use this
if(mouseover == hello)
{
if(rightclick == true)
{
execute the stuff you want
}
}
or something like that. Hope this helps a bit atleast
UPDATE
To obtain the rightclick event you will have to use the
if(Event.current.button == 1 && Event.current.isMouse)
You have to place this in the OnGUI to work properly
this way you first trigger the in box part, then check for a right click and execute the stuff you want.

detecting right mouse double click with Bing maps

I don't see an event in the Bing map API v7 that will surface a double click event. Is there a way to do this? Assuming there isn't native support that I missed, I think I will have to write my own double click handler with a timer.
I had also a problem with the click-events. In facts, the normal click-event also fires during a double-click event. That is why I had to implement my own double-click handler. My approach can be translated to the rigth click, because I am only using the single-click event, which is also available for the right mouse button.
//Set up my Handler (of course every object can be the target)
Microsoft.Maps.Events.addHandler(map, 'click', Click);
//count variable, that counts the amount of clicks that belong together
myClick=0;
//A click fires this function
function click (e)
{
//If it is the first click of a "series", than start the timeout after which the clicks are handled
if (myClick == 0)
{
//Target have to be buffered
target= e;
//accumulate the clicks for 200ms and react afterwards
setTimeout("reaction(target)", 200);
}
//count the clicks
myClick = myClick+1;
}
//At the end of timeout check how often a click has been performed and react
function reaction(e)
{
if (myClick==1)
{
alert("Single Click!");
}
else (myClick==2)
{
alert("Double click!");
}
else (myClick==3)
{
alert("Tripple click");
}
//reset ClickCount to zero for the next clicks
myClick = 0;
}
Moreover it might be interesting to remove the standart double-click behaviour of Bing-Maps, to zoom in. This can be realized by the following code:
Microsoft.Maps.Events.addHandler(map, 'dblclick', function(e){
e.handled = true;
});
If you only use double click event
Microsoft.Maps.Events.addHandler(this.map, 'dblclick', functionHandler)
should solve the problem

Ignore multiple button taps after first one on iPhone webapp using jQuery Mobile?

Assume button A in an HTML5 webapp built with jQuery Mobile.
If someone taps button A, we call foo(). Foo() should get called once even if the user double taps button A.
We tried using event.preventDefault(), but that didn't stop the second tap from invoking foo(). event.stopImmediatePropagation() might work, but it also stops other methods further up the stack and may not lead to clean code maintenance.
Other suggestions? Maintaining a tracking variable seems like an awfully ugly solution and is undesirable.
You can set a flag and check if it's OK to run the foo() function or unbind the event for the time you don't want the user to be able to use it and then re-bind the event handler after a delay (just a couple options).
Here's what I would do. I would use a timeout to exclude the subsequent events:
$(document).delegate('#my-page-id', 'pageinit', function () {
//setup a flag to determine if it's OK to run the event handler
var okFlag = true;
//bind event handler to the element in question for the `click` event
$('#my-button-id').bind('click', function () {
//check to see if the flag is set to `true`, do nothing if it's not
if (okFlag) {
//set the flag to `false` so the event handler will be disabled until the timeout resolves
okFlag = false;
//set a timeout to set the flag back to `true` which enables the event handler once again
//you can change the delay for the timeout to whatever you may need, note that units are in milliseconds
setTimeout(function () {
okFlag = true;
}, 300);
//and now, finally, run your original event handler
foo();
}
});
});
I've created a sample here http://jsfiddle.net/kiliman/kH924/
If you're using <a data-role="button"> type buttons, there is no 'disabled' status, but you can add the appropriate class to give it the disabled look.
In your event handler, check to see if the button has the ui-disabled class, and if so, you can return right away. If it doesn't, add the ui-disabled class, then call foo()
If you want to re-enable the button, simply remove the class.
$(function() {
$('#page').bind('pageinit', function(e, data) {
// initialize page
$('#dofoo').click(function() {
var $btn = $(this),
isDisabled = $btn.hasClass('ui-disabled');
if (isDisabled) {
e.preventDefault();
return;
}
$btn.addClass('ui-disabled');
foo();
});
});
function foo() {
alert('I did foo');
}
});

can't unregister click event in openlayers

I am having issues with OpenLayers and unregistering the click events that are added to a layer. Basically, what I need to do is this:
When a user clicks on a marker, they get a bubble that has an "edit" link in it. The user clicks that and it creates a new layer on the map and then registers a click event to the map waiting for the user to click on the map. When they click somewhere on the map, it then moves the marker to where they clicked. This all works perfectly.
However, the issue is when the user clicks to edit the marker and then clicks on a button OUTSIDE OF THE MAP to cancel the action and NOT move the marker, the unregister of the click event doesn't work. They can still click on the map and it moves the marker.
Here is a sample of the code:
function move_marker(marker) {
lmLayer = new OpenLayers.Layer.Markers("Landmark Creation",{displayInLayerSwitcher: false});
map.addLayer(lmLayer);
map.events.register("click", lmLayer, function(evt){
var pixel = new OpenLayers.Pixel(evt.clientX,evt.clientY);
position = map.getLonLatFromPixel(pixel);
marker.lonlat = pixel;
marker.moveTo(pixel);
marker.draw();
lmLayer.redraw();
OpenLayers.Event.stop(evt);
});
}
function cancel_move() { // this function is triggered by a button outside of the map element
lmLayer = map.getLayersByName('Landmark Creation');
lmLayer[0].events.unregister("click");
map.events.unregister("click");
map.removeLayer(lmLayer[0]);
}
As you can see in the cancel function, I am getting the layer by the layer name, which according to the console.log it is finding at index 0. I added the unregister to the lmLayer in hopes that would help, but so far, no luck. Then on the map element I add the unregister call and then finally I remove that new layer because we don't want it interfering.
I'd appreciate some feedback on this. I'm losing my mind.
Thanks!
I think you need to tell OpenLayers which click event you want it to unregister:
var method = function() {
// Do stuff...
}
map.events.register('click', map, method);
map.events.unregister('click', map, method);
According to the OpenLayers.Events source it checks whether the scope and the method is present in the listener stack:
unregister: function (type, obj, func) {
if (obj == null) {
obj = this.object;
}
var listeners = this.listeners[type];
if (listeners != null) {
for (var i=0, len=listeners.length; i<len; i++) {
HERE --> if (listeners[i].obj == obj && listeners[i].func == func) { <-- HERE
listeners.splice(i, 1);
break;
}
}
}
},
I hope that works for you :)