This question explains how to detect a ctrl+click in pygtk.
Does it also work on Lablgtk? Or is there a simpler way to do it?
In lablgtk, there is a more direct solution, although it is not immediately obvious.
From a mouse click event ev (of type GdkEvent.Button.t), you can detect events such as ctrl+click/shift+click with GdkEvent.Button.state and Gdk.Convert.modifier), as in the following example:
let state = GdkEvent.Button.state ev in
let modifiers = Gdk.Convert.modifier state in
let button = GdkEvent.Button.button ev in
if button = 1 && List.mem `CONTROL modifiers then
(* Ctrl+left click *) ...
else if button = 3 && List.mem `SHIFT` modifiers then
(* Shift+right click *) ...
The type of the modifier list is Gdk.Tags.modifier.
Related
Lately I have been using Autohotkey to help me get past my left hands injury and the pain I get when I "push it" by reaching out for keys, especially, when my other hand is on the mouse
I recently had this brilliant idea that will let me eliminate reaching out for keys, by using a keypad instead of a full sized keyboard.
My idea is to use a VIM style hotkey\editing (The Linux\text editing tool) design.
when I tap NumpadSub, then first tap of NumpadMult should perform a special action. After this first tap of NumpadMult future taps should perform the default windows function, as if no AHK scripts were running.
The thing is, to make up for the small number of keys available, I want to use EvilC's TapHoldManager library to achieve this. I have spent the past few days increasing my knowledge of this library.
Using THIS post and u\ExpiredDebitCard answer HERE I came up with this:
#include <TapHoldManger>
THMLeader:= new TapHoldManager(200,400,2)
THMLeader.Add("NumpadSub", Func("LeaderKey__NumpadSub"))
THMLeader.Add("NumPadMult", Func("LeaderKey__NumPadMult"))
LeaderKey__NumpadSub(isHold, taps, state)
{
if (taps == 1)
if (isHold == 0)
{
Tooltip, THMLeader Tap x1
TestFlag := 1
}
else
{
if (state)
{
Tooltip, THMLeader Hold x1
}
; else
; {
; }
}
}
LeaderKey__NumPadMult(isHold, taps, state)
{
if (taps == 1)
if (isHold == 0)
{
Tooltip, LeaderKey__NumPadMult Tap x1
}
else
{
if (state)
{
Tooltip, LeaderKey__NumPadMult Hold x1
}
; else
; {
; }
}
}
TestFlag := 1
Hotkey If,TestFlag == 1
;Hotkey If,(TestFlag == 1)
THMSubKey:=New TapHoldManager(200,400,2)
THMSubKey.Add("NumpadMult", Func("SubKey__NumPadMult"))
#If
SubKey__NumPadMult(isHold,taps,state)
{
if (taps == 1)
if (isHold == 0)
{
Tooltip, SubKey__NumPadMult Tap x1
TestFlag := 0
}
else
{
if (state)
{
Tooltip, SubKey__NumPadMult Hold x1
TestFlag := 0
}
; else
; {
; }
}
}
My intention with the above code is that, SubKey__NumPadMult code block should only ever be active if variable TestFlag is set to 1. Only single tap of NumpadSub can set TestFlag to 1. so
So in short,
A single tap of NumpadSub followed by NumpadMult will print SubKey__NumPadMult Tap x1.
A single tap of NumpadMult NOT preceded by a tap of NumpadSub will print LeaderKey__NumPadMult Tap x1
I am having issues with getting Hotkey If,TestFlag == 1 to work though. Running the above code gives me a runtime error:
Error: Parameter #2 must match an existing #If expression.
Changing it around like. Hotkey If,(TestFlag == 1) has not helped either.
What am I doing wrong here? I have tried many things, nothing seems to be giving in. Any help or ideas would be great.
Thanks for any help
So What I want to do is to press a button and inside the ButtonClicked Event I want to wait completing the event, until I press a specific button/one of the specified buttons.
I also know that there are some similar questions to this topic but I wasnt able to find a fix out of the answers
So basically this:
reactions += {
case event.ButtonClicked(`rollDice`) =>
some code ...
wait for one of the specified buttons to be pressed and then continue
some code ...
Is there an easy way to solve this problem without the use of threads?
There are certainly some abstractions you could set up around the event layer, but you asked for "easy", so my suggestion is to set a flag/state when the dice are rolled, and then check for that flag in the other buttons' event handler.
private var postDiceRollState: Option[InfoRelatedToRollDice] = None
reactions += {
case event.ButtonClicked(`rollDice`) =>
// capture whatever info you need to pass along to the later button handler
val relevantInfo = /* some code... */
// store that info in the "state"
postDiceRollState = Some(relevantInfo)
case event.ButtonClicked(other) if isPostDiceRollButton(other) =>
// when the other button gets clicked, pull the relevant info from your "state"
postDiceRollState match {
case Some(relevantInfo) =>
postDiceRollState = None // clear state
doInterestingStuff(relevantInfo) // "some code..."
case None =>
// nothing happens if you didn't roll the dice first
}
}
Note: I represented the "flag" as an Option, under the assumption that you might have some information you want to capture about the rollDice event. If you don't actually have anything to put in there, you could represent your state as private var didRollDice: Boolean = false and set/clear would be setting it to true/false respectively.
I am trying to intercept mouse move events using the CGEvent.tapCreate(tap:place:options:eventsOfInterest:callback:userInfo:) method as shown below:
let cfMachPort = CGEvent.tapCreate(tap: CGEventTapLocation.cghidEventTap,
place: CGEventTapPlacement.headInsertEventTap,
options: CGEventTapOptions.defaultTap,
eventsOfInterest:CGEventMask(CGEventType.mouseMoved.rawValue),
callback: {(eventTapProxy, eventType, event, mutablePointer) -> Unmanaged<CGEvent>? in event
print(event.type.rawValue) //Breakpoint
return nil
}, userInfo: nil)
let runloopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, cfMachPort!, 0)
let runLoop = RunLoop.current
let cfRunLoop = runLoop.getCFRunLoop()
CFRunLoopAddSource(cfRunLoop, runloopSource, CFRunLoopMode.defaultMode)
I pass as event type eventsOfInterest mouseMoved events with a raw value of 5 as seen in the documentation. But for some reason my print() is not executed unless I click with the mouse. Inspecting the send mouse event in the debugger gives me a raw value of 2, which according to the documentation is a leftMouseUp event.
In the documentation for CGEvent.tapCreate(tap:place:options:eventsOfInterest:callback:userInfo:) it says:
Event taps receive key up and key down events [...]
So it seems like the method ignores mouseMoved events in general?! But how am I supposed to listen to mouseMoved events? I am trying to prevent my cursor (custom cursor) from being replaced (for example when I hover over the application dock at the bottom of the screen).
You need to bitshift the CGEventType value used to create the CGEventMask parameter. In Objective-C, there is a macro to do this: CGEventMaskBit.
From the CGEventMask documentation:
to form the bit mask, use the CGEventMaskBit macro to convert each constant into an event mask and then OR the individual masks together
I don't know the equivalent mechanism in swift; but the macro itself looks like this:
*/ #define CGEventMaskBit(eventType) ((CGEventMask)1 << (eventType))
In your example, it's sufficient to just manually shift the argument; e.g.
eventsOfInterest:CGEventMask(1 << CGEventType.mouseMoved.rawValue),
I would point out that the code example given in the question is a little dangerous; as it creates a default event tap and then drops the events rather than allowing them to be processed. This messes up mouse click handling and it was tricky to actually terminate the application using the mouse. Anyone running the example could set the event tap type to CGEventTapOptions.listenOnly to prevent that.
Here is a way to listen for mouseMove global events (tested with Xcode 11.2+, macOS 10.15)
// ... say in AppDelegate
var globalObserver: Any!
var localObserver: Any!
func applicationDidFinishLaunching(_ aNotification: Notification) {
globalObserver = NSEvent.addGlobalMonitorForEvents(matching: .mouseMoved) { event in
let location = event.locationInWindow
print("in background: {\(location.x), \(location.y)}")
}
localObserver = NSEvent.addLocalMonitorForEvents(matching: .mouseMoved) { event in
let location = event.locationInWindow
print("active: {\(location.x), \(location.y)}")
return event
}
...
There's another thing incorrect in your code, although you might be lucky and it isn't normally causing a problem.
As documented for the mode parameter to CFRunLoopAddSource: "Use the constant kCFRunLoopCommonModes to add source to the set of objects monitored by all the common modes."
That third parameter should instead be CFRunLoopMode.commonModes.
What you have, CFRunLoopMode.defaultMode aka kCFRunLoopDefaultMode, is instead for use when calling CFRunLoopRun.
I found some example code when building a menu bar item in OS X. It makes use of the single | and I'm unsure what it actually means.
(What I'm trying to do is have a function called on left click of the menu item, but have it show the menu on right click)
Here's my code
//Get reference to main system status bar
let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)
statusItem.image = icon
statusItem.menu = menuBar
if let statusButton = statusItem.button
{
statusButton.target = self
statusButton.action = #selector(statusItemClicked)
statusButton.sendActionOn(Int(NSEventMask.RightMouseUpMask.rawValue | NSEventMask.LeftMouseUpMask.rawValue))
}
Original Answer with code Left vs Right Click Status Bar Item Mac Swift 2
Bitwise OR, just like it does in most C-like languages. In this context, it's being used to combine flags.
That must be really old code. Nowadays, in modern Swift, NSEventMask is an Option Set. You can just say [NSEventMask.rightMouseUp, NSEventMask.leftMouseUp], and you don't need the Int cast at all. (Or if you haven't updated to Swift 3 yet, the case names would start with capital letters.)
I am trying to programmatically change the "highlighted" item in my CellList, based on keyboard events in another control (a textbox). I can get the keyboard events just fine, but when I use CellList...
int row = getKeyboardSelectedRow() + 1;
setKeyboardSelected(row,selected,stealFocus)
It doesn't have any affect. If I put focus on my cellList indeed, I can move up and down and highlight a row. If I put true for "stealFocus" on the setKeyboardSelected() method, it "works", except I really want to keep focus on the textbox, rather than the cellList. How do I do this? I've attempted fireEvents, sending the keystrokes to the CellList, but that doesn't help either.
J
I have no immediate solution, but if I were you I'd step through the code of setKeyBoardSelected in com.google.gwt.user.cellview.client.AbstractCellTable in debug mode.
Maybe this is where it's going wrong?
if (KeyboardSelectionPolicy.DISABLED == getKeyboardSelectionPolicy()
|| !isRowWithinBounds(index) || columns.size() == 0) {
return;
}