I've implemented a horizontal splitter widget in Xlib. I'm trying to grab the mouse when the user clicks & drags on the splitter bar (so that the user can dynamically move the split & thus resize the windows on either side of the splitter bar).
I've used XGrabPointer() after receiving a left click, in hopes that all future mouse motion (dragging) will be diverted to the splitter window until the left button is released.
Unfortuntately, it doesn't seem to work like that. If the user drags too quickly and the mouse pointer enters one of the windows on either side of the split, the MotionEvent messages are diverted to that (child) window rather than the splitter window.
What have I done wrong? My XGrabPointer() call is as follows:
::XGrabPointer(mDisplay, window, True,
ButtonPressMask |
ButtonReleaseMask |
PointerMotionMask |
FocusChangeMask |
EnterWindowMask |
LeaveWindowMask,
GrabModeAsync,
GrabModeAsync,
RootWindow(mDisplay, DefaultScreen(mDisplay)),
None,
CurrentTime);
I'm almost embarrassed to admit this, but the answer turned out to be as simple as changing that third parameter (owner_events) from True to False.
From the Xlib tutorial/reference at tronche.com:
If owner_events is False, all generated pointer events are reported with respect to grab_window and are reported only if selected by event_mask. If owner_events is True and if a generated pointer event would normally be reported to this client, it is reported as usual. Otherwise, the event is reported with respect to the grab_window and is reported only if selected by event_mask.
I'm still not sure I completely understand the behavior of the True case, but my interpretation is that if True, other X programs (that is, windows created by other processes) are barred from receiving XEvents, but those that would hit any window created by your process are delivered as normal. In the false case, all events are reported with respect to the specific window you have selected. This was the behavior I was after.
Related
Trying to create very simple keyboard and mouse controller using the Raspberry Pi's GPIO pins. Would love to use the code in a educational setting, so trying to build super easy, readable code for children/students. But the code is acting somewhat strange, it keeps outputting the same keystrokes:
import gpiozero
from pynput.mouse import Button, Controller as MouseController
from pynput.keyboard import Key, Controller as KeyboardController
keyboard = KeyboardController()
mouse = MouseController()
Up = gpiozero.Button(26, bounce_time=0.02)
LeftMouse = gpiozero.Button(17, bounce_time=0.02)
while True:
if Up.is_pressed:
print("Up")
keyboard.press(Key.up)
Up.wait_for_release()
keyboard.release(Key.up)
elif LeftMouse.is_pressed:
print("Left Mouse button")
mouse.press(button.left)
LeftMouse.wait_for_release()
mouse.release(button.left)
Using Python 3.7.3. No matter which GPIO I trigger (26 or 17), the code always outputs 'Up' and press the keyboard 'up' button. It must be something stupid, but I can't seem to figure it out. Would love to keep using the if/elif, so I can expand the code later with more GPIO buttons. Any idea's anyone?
Although I am not very experienced in the GPIO of Raspberry, I think your code is almost alright. I suspected that the reason of always having 'Up' outcomes, which meant the 2nd mouse condition statement was bypass, was probably due to the word 'button' being not consistent with the module you called in the first line? Below is the one after using 'Button' throughout. Probably when you triggered pin 17, it did pass through the printing stage but it could not penetrate further. It will no choice but to select the first keyboard statement. So, it would end up with 'Up' all the way.
from pynput.mouse import Button, Controller as MouseController
elif LeftMouse.is_pressed:
print("Left Mouse button")
mouse.press(Button.left)
LeftMouse.wait_for_release()
mouse.release(Button.left)
I also found the below link quite useful in order to make sure the packages imported and defined properly.
pynput - Importing keyboard and mouse
Looking forward to hearing from your update.
What I have
I have two rooms: rm_home and rm_options. I have a sound: snd_Bgm. And, I have three objects: obj_bgm, obj_BtnOnClicked, and obj_BtnOffClicked.
What I want is very simple
Player can turn on/off the snd_Bgm.
What I have done
In obj_bgm, I have these events:
Create Event: set var global.sound to 1
Room Start: stop sound snd_Bgm; if global.sound == 1 then play sound snd_Bgm
In obj_BtnOnClicked, I have these events:
Left-Pressed Event: play sound snd_Bgm; set var global.sound to 1
In obj_BtnOffClicked, I have these events:
Left-Pressed Event: stop sound snd_Bgm; set var global.sound to 0
I put obj_BtnOnClicked, and obj_BtnOffClicked in rm_options, which can be accessed from rm_home. Then, I put obj_bgm in rm_home.
This is the problem
When game start, it will show rm_home and plays the snd_bgm. I go to rm_options, then click the obj_BtnOffClicked to turn off the sound, so the sound is off. But, when I go back to rm_home, the sound is on again.
What I think
I shouldn't put Create Event: set var global.sound to 1 in obj_bgm, because when rm_home start, it takes the value of var global.sound from Create Event. But, if I put Create Event in obj_BtnOnClicked or obj_BtnOffClicked, it shows a Get Error.
What should I do? Please explain your answer. Thanks.
Are your rooms and your variables persistent ?
If rm_home is not persistent, it will restart every time you leave it. So every object placed in that room will be reset, including obj_bgm, which sets your sound variable to 1. I think this is the reason the sound restarts when you come back to rm_home.
If you still want to reset the room but not this particular object, you can make it persistent. You can do it either by ticking the box in the object or through code.
If you put the create event in a button object, it will not be read until you go to the options room. So when the obj_bgm tries to set it to 1, it does not exist yet. I believe it causes the error.
I make these remarks on assumptions, but I would need to see your code or your error message to help you further.
I'm trying to implement a very customized implementation of awesome.
I have two monitors. I'd like to have my first client always open on the left monitor (a Chrome window in kiosk mode), then all clients after open up on the right monitor.
Are there any custom layouts that accomodate this?
I'd be willing to program it myself, but I'm not sure how to bind a script to some kind of "new client" event.
The new client event is the manage event. It is emitted whenever, well, a new client gets managed by awesome.
To send the first client that ever appears to screen 1 and all following ones to screen 2, you could do something like this:
local first = true
client.connect_signal("manage", function(c)
if first then
c.screen = 1
else
c.screen = 2
end
first = false
end)
I'm trying to send key stroke to an external application in java using jna.
It sends VK_DOWN key, also that application has a shortcut for ctrl+down which makes something very different. My application sends around ~15 down key with 1 sec in between, and if user happens to click CTRL during it while working on a different window, it breaks the application(treats it as ctrl+down).
I checked the keyboard messages via Spy++, compared mine with AutoIt, they are exactly same messages.
ControlSend("window_title", "", "", "{DOWN}")
This AutoIt code works perfect, even if I click ctrl when window is active or inactive, it does not interfere with down key.
My code on the other hand:
User32.INSTANCE.PostMessage(handle, WM_KEYDOWN, wparam, lparamDown);
User32.INSTANCE.PostMessage(handle, WM_KEYUP, wparam, lparamUp);
has exactly same messages, but it doesn't work.
I tried sending control up before sending down key but to no avail.
Spy++ output:
<14335> 00011456 P WM_KEYDOWN nVirtKey:VK_DOWN cRepeat:1 ScanCode:50 fExtended:1 fAltDown:0 fRepeat:0 fUp:0
<14336> 00011456 P WM_KEYUP nVirtKey:VK_DOWN cRepeat:1 ScanCode:50 fExtended:1 fAltDown:0 fRepeat:1 fUp:1
My ctrl clicks are not even on target application so why does it treat it as such? Should I use a hook?
On E63 or similar smart phones,there can be three softkeys(the left and right one always named "OK" or "Cancel" and the middle one always named "Select" or 'Query" alike actions' name) on the screen.QAction has this method:
void setSoftKeyRole ( SoftKeyRole softKeyRole )
,and SoftKeyRole goes these descriptions:
QAction::NoSoftKey 0 This action should not be used as a softkey
QAction::PositiveSoftKey 1 This action is used to describe a softkey with a positive or non-destructive role such as Ok, Select, or Options.
QAction::NegativeSoftKey 2 This action is used to describe a softkey with a negative or destructive role role such as Cancel, Discard, or Close.
QAction::SelectSoftKey 3 This action is used to describe a role that selects a particular item or widget in the application.
I have used PositiveSoftKeys and NegativeSoftKey to set the left and right softkey,but I can never do SelectSoftKey to the middle one?I found nothing related to this on qt bug repository.What I want to do is make full use of the three softkeys on most smartphones.Can anybody figure out what happened?Thanks always.
E63 does not have a touch screen,and it seems only smart phones with a touch screen(Nokia series) can set SelectSoftKey to the middle one.