CGEventPostToPSN - How to send keys with different keyboard locales? - objective-c

So I'm sending key presses to another application, like so:
- (void)keyPress:(int)hotkey withModifier:(unsigned int)modifier withKeyDown:(BOOL)keyDown{
// verify the process still exists
ProcessSerialNumber psn = [self myPSN];
CGEventRef keyEvent = NULL;
// create our source
CGEventSourceRef source = NULL; // this didn't used to be NULL, does this matter?
if ( source || 1 == 1 ){
keyEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)hotkey, keyDown);
// set flags for the event (does this even matter? No.)
CGEventSetFlags( keyEvent, modifier );
// hit any specified modifier keys
if ( modifier & NSAlternateKeyMask ){
PostKeyboardEvent( source, kVK_Option, keyDown );
}
if ( modifier & NSShiftKeyMask ){
PostKeyboardEvent( source, kVK_Shift, keyDown );
}
if ( modifier & NSControlKeyMask ){
PostKeyboardEvent( source, kVK_Control, keyDown );
}
if ( modifier & NSCommandKeyMask ){
PostKeyboardEvent( source, kVK_Command, keyDown );
}
// post the actual event
CGEventPostToPSN(&psn, keyEvent);
usleep(30000);
// post it again if we're doing key up, just in case!
if ( !keyDown ){
CGEventPostToPSN(&psn, keyEvent);
}
// release
if ( keyEvent ){
CFRelease(keyEvent);
}
}
}
Basically, I can send keys FINE if they are using a US Keyboard, such as sending: kVK_ANSI_A
The problem is with non-US keyboards, how can I adapt these keys to still send correctly if the keyboard layout is NOT set to US?
Here are the virtual key codes I'm having trouble with: http://pastebin.com/qXnXHb5M
Thanks in advance!

I think its the same question as How to convert ASCII character to CGKeyCode?

Related

Toggling LED through button (ESP32 FreeRTOS) + binary semaphore

I had already done several projects using simple freertos ideas: led, button. Implementing semaphores, queues or some interrupt. I can't run this simple code tough.
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#define BLINK_GPIO 21 //2
#define BUTTON_GPIO 0
void task_blink(void *pvParameters);
void task_botao(void *pvParameters);
//void wd_off_task(void *pvParameters);
SemaphoreHandle_t sem_sinc;
void app_main(void)
{
gpio_pad_select_gpio(BLINK_GPIO); // Configura o pino como IO
gpio_set_direction(BLINK_GPIO,GPIO_MODE_OUTPUT); // Configura o IO como saida
gpio_pad_select_gpio(BUTTON_GPIO); // Configura o pino como IO
gpio_set_direction(BUTTON_GPIO,GPIO_MODE_INPUT); // Configura o IO como entrada
vSemaphoreCreateBinary(sem_sinc); // Cria o Semaforo
xSemaphoreTake(sem_sinc,0); // Garante que inicializa com 0
xTaskCreate(task_blink,"Task Blink",1024,NULL,2,NULL);
printf("Task Blink Criada!!!\r\n");
xTaskCreate(task_botao,"Task Botao",1024,NULL,2,NULL);
printf("Task Botao Criada!!!\r\n");
//xTaskCreate(wd_off_task,"Task desliga WD",1024,NULL,1,NULL);
}
void task_botao(void *pvParameters)
{
while(1)
{
if(gpio_get_level(BUTTON_GPIO) == 0)
{
while(gpio_get_level(BUTTON_GPIO) == 0){}
printf("Botao Pressionado!!!\r\n");
xSemaphoreGive(sem_sinc);
vTaskDelay(1);
}
}
}
void task_blink(void *pvParameters)
{
while(1)
{
if(xSemaphoreTake(sem_sinc,portMAX_DELAY)==pdTRUE)
{
printf("Pisca Led!!!\r\n");
if((gpio_get_level(BUTTON_GPIO) == 0))
gpio_set_level(BLINK_GPIO, 1);
else
gpio_set_level(BLINK_GPIO, 0);
}
}
}
The issue:
The code is built nicely, and the same for the flashing to ESP. As I press the button, it shows in the terminal the designed messages. See, the only problem here lies on I can't set the LED's level, toggling it! Because of this, all I can get is the LED turning on and turning off afterwards quickly(every time the semaphore syncronizes the 2 tasks).
I suspect it's all about some kind of config, related to this GPIO. (Although I'm using the reset port to read the button, I still think this is not the matter, because the port was properly configured on the lines above)
Your switch polling needs to detect transitions, but avoid erroneously detecting switch bounce as a valid transition. For example:
#define BUTTON_DN = 0 ;
#define BUTTON_UP = 1 ;
#define POLL_DELAY = 50 ;
void task_botao(void *pvParameters)
{
int button_state = gpio_get_level( BUTTON_GPIO ) ;
for(;;)
{
int input_state = gpio_get_level( BUTTON_GPIO ) ;
// If button pressed...
if( input_state == BUTTON_DN &&
button_state != BUTTON_UP )
{
button_state = BUTTON_DN ;
// Signal button press event.
xSemaphoreGive(sem_sinc ) ;
}
// otherwise if button released...
else if( input_state == BUTTON_UP &&
button_state != BUTTON_DN )
{
button_state = BUTTON_UP ;
}
// Delay to yield processor and
// avoid switch bounce on transitions
vTaskDelay( POLL_DELAY );
}
}
The blinking task need not be reading the button input at all; not is it unnecessary, it is also a bad design:
void task_blink(void *pvParameters)
{
int led_state = 0 ;
gpio_set_level( BLINK_GPIO, led_state ) ;
for(;;)
{
if( xSemaphoreTake( sem_sinc, portMAX_DELAY ) == pdTRUE )
{
led_state = !led_state ;
gpio_set_level( BLINK_GPIO, led_state ) ;
}
}
}
There are some things to consider. Your thinking is logical, but there are some issues.
A button is a mechanical device and while you press it, you think it will be a straightforward 0 instead of 1 it’s not. If you have an oscilloscope, I recommend you to check the voltage level on the gpio input. Or google button bounce. And floating pins. Those two concepts should be clear. The processor is very straightforward in interpreting the values.
Example: https://hackaday.com/wp-content/uploads/2015/11/debounce_bouncing.png
Now your functions are in fact constantly checking the button status, somehow at the cost of processor time. For small projects not of an issue, but when they get bigger they are.
What you want to do is to setup an interrupt to the button status: at the moment the level changes it will fire some code. And it doesn’t have to double check the gpio status in two tasks, with the chance it will miss the status in the second (because of delays). It’s important to realize you are checking the same level twice now.
Not a problem now but maybe later: the stack size of the tasks is somehow small, make it a good use to always check if it’s enough by checking the current free size. Vague problems arise if it’s not.

Use UART events with Simplelink in Contiki-ng

I'm actually trying to receive serial line message using the UART0 of a CC1310 with Contiki-ng.
I have implemented a uart callback function with will group all the characters received into a single variable, and stop collecting when it receives a "\n" character.
int uart_handler(unsigned char c)
{
if (c == '\n')
{
end_of_string = 1;
index = 0;
}
else
{
received_message_from_uart[index] = c;
index++;
}
return 0;
}
The uart0 is initialised at the main and only process of the system and then it waits in a infinite while loop until the flag end_of_string
PROCESS_THREAD(udp_client_process, ev, data)
{
PROCESS_BEGIN();
uart0_init();
uart0_set_callback(uart_handler);
while (1)
{
//wait for uart message
if (end_of_string == 1 && received_message_from_uart[0] != 0)
{
LOG_INFO("Received mensaje\n");
index = 0;
end_of_string = 0;
// Delete received message from uart
memset(received_message_from_uart, 0, sizeof received_message_from_uart);
}
etimer_set(&timer, 0.1 * CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
}
PROCESS_END();
}
As you can see, the while loop stops at each iteration with a minimum time timer event. Although this method works, I think it is a bad way to do it, as I have read that there are uart events that can be used, but I have not been able to find anything for the CC1310.
Is it possible to use the CC1310 (or any other simplelink platform) UART with events and stop doing unnecessary iterations until a message has reached the device?

qmk: Make a layer respond to two modifier keys being pressed?

In a qmk_firmware configuration, I can map a single modifier key to a new keymap layer using MO(x).
How can I do this such that two modifier keys must be pressed simultaneously?
Example: I would like to map [Fn][Ctrl]-[d] to generate a Unicode delta, [Fn][Ctrl]-[e] to generate a Unicode epsilon, etc.
You have to put your specific code into the custom Quantum function process_record_user:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// enter your code for [Fn][Ctrl]-[α] here
return true;
}
You can try the Quantum tab in the Firmware Builder. Even if it is end-of-life, you'll see, what is meant.
You can also set UNICODEMAP_ENABLE = yes and use the Unicode Map.
Something like this should do (half) the trick:
In function layer_state_set_user, check for layer Fn (some bit arithmetic similar to update_tri_layer_state) and the Ctrl state (get_mods() & MOD_MASK_CTRL). When in Fn layer and Ctrl is down, deactivate Ctrl (del_mods(MOD_MASK_CTRL)) and return state | x; otherwise return state & ~x.
Unfortunately, this will probably require Ctrl to be pressed before Fn.
At least that's what happens in my similar shift + layer _L4 => layer _S_L4 implementation in my keymap. It requires shift to be pressed before LT(_L4,…).
For the other direction (_L4 + shift => _S_L4), I have MO(_S_L4) on the shift keys in layer _L4, but that is somehow disabled by my layer_state_set_user.
What should "Fn + E" and "Fn + D" do (when Ctrl is not held)? For sake of example, I'll assume you want them to do PgUp and PgDn.
Here is how I would go about implementing this:
Enable Unicode input: In rules.mk, add UNICODEMAP_ENABLE = yes. In config.h, add #define UNICODE_SELECTED_MODES UC_WINC if you are on Windows. See the Unicode documentation for other OSs and options.
Define an "Fn" layer in the keymap.
Define a couple custom keycodes, and place them in the Fn layer at the d and e positions.
Handle the custom keys in process_record_user(), using get_mods() to test whether Ctrl is held. See also macros that respond to mods. Then use send_unicode_string() to type the Unicode symbol itself.
Code sketch:
// Copyright 2022 Google LLC.
// SPDX-License-Identifier: Apache-2.0
enum layers { BASE, FN, /* Other layers... */ };
enum custom_keycodes {
UPDIR = SAFE_RANGE,
FN_E,
FN_D,
// Other custom keys...
};
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
[BASE] = LAYOUT(...),
[FN] = LAYOUT(..., FN_E, ..., FN_D, ...),
...
};
const uint32_t unicode_map[] PROGMEM = {};
static void symbol_key(uint16_t* registered_key,
keyrecord_t* record,
uint16_t default_keycode,
const char* symbol,
const char* uppercase_symbol) {
if (record->event.pressed) { // On key press.
const uint8_t mods = get_mods();
const bool ctrl_held = (mods & MOD_MASK_CTRL) != 0;
const bool shifted = (mods & MOD_MASK_SHIFT) != 0;
if (ctrl_held) { // Is the Ctrl mod held?
unregister_mods(MOD_MASK_CTRL); // Clear the Ctrl mod.
// Type Unicode symbol according to whether shift is active.
send_unicode_string(shifted ? uppercase_symbol : symbol);
*registered_key = KC_NO;
} else {
*registered_key = default_keycode;
register_code16(*registered_key);
}
} else { // On key release.
unregister_code16(*registered_key);
*registered_key = KC_NO;
}
}
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
const uint8_t mods = get_mods();
const bool ctrl_held = (mods & MOD_MASK_CTRL) != 0;
const bool shifted = (mods & MOD_MASK_SHIFT) != 0;
switch (keycode) {
case FN_E: {
static uint16_t registered_key = KC_NO;
symbol_key(&registered_key, record, KC_PGUP, "ε", "Ε");
} return false;
case FN_D: {
static uint16_t registered_key = KC_NO;
symbol_key(&registered_key, record, KC_PGDN, "δ", "Δ");
} return false;
}
return true;
}

Turning a C++ Application into VR [duplicate]

This question already has an answer here:
How to prepare my game for VR? [closed]
(1 answer)
Closed 3 years ago.
I have a working c++ application using openGL and Cuda, and want to convert it to a VR application. I searched the internet and it seems that the standard way to develop VR apps is to use a game engine (unity or unreal). Is there any other possible ways to avoid using one of these, and just convert my already existing application into VR?
The usual approach is, that at the start of render of a frame, you're polling the VR API for each eye's projection and "camera" translation matrix, then use that, to render into textures using an FBO, and at the end pass the IDs of those textures back to the API. With OpenVR:
Initialize the FBO
vr::EVRInitError err_hmd = vr::VRInitError_None;
m_hmd = vr::VR_Init(&err_hmd, vr::VRApplication_Scene);
if( err_hmd != vr::VRInitError_None ){
m_hmd = nullptr;
}
if( m_hmd ){
m_hmd->GetRecommendedRenderTargetSize(&m_hmd_width, &m_hmd_height);
mat44_from_hmd44(m_prj_l, m_hmd->GetProjectionMatrix(vr::Eye_Left, 0.01f, 10.f) );
mat44_from_hmd44(m_prj_r, m_hmd->GetProjectionMatrix(vr::Eye_Right, 0.01f, 10.f) );
mat44_from_hmd34(m_eye_l, m_hmd->GetEyeToHeadTransform(vr::Eye_Left) );
mat44_from_hmd34(m_eye_r, m_hmd->GetEyeToHeadTransform(vr::Eye_Right) );
if( !vr::VRCompositor() ){
vr::VR_Shutdown();
m_hmd = nullptr;
}
m_timer_vr = startTimer(1000/50);
} else {
}
if( m_hmd_width && m_hmd_height ){
qDebug() << "resize to" << m_hmd_width << m_hmd_height;
eye_target_textures.create(m_hmd_width, m_hmd_height);
}
Update the HMD pose:
vr::VREvent_t vrev;
while( m_hmd->PollNextEvent(&vrev, sizeof(vrev)) );
// Process SteamVR action state
// UpdateActionState is called each frame to update the state of the actions themselves. The application
// controls which action sets are active with the provided array of VRActiveActionSet_t structs.
vr::VRActiveActionSet_t actionSet = { 0 };
vr::VRInput()->UpdateActionState( &actionSet, sizeof(actionSet), 1 );
vr::TrackedDevicePose_t tdp[ vr::k_unMaxTrackedDeviceCount ];
vr::VRCompositor()->WaitGetPoses(tdp, vr::k_unMaxTrackedDeviceCount, NULL, 0);
mat4x4_translate(m_pose, 0, 0, -1);
for( int i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i ){
if( !tdp[i].bPoseIsValid ){ continue; }
switch( m_hmd->GetTrackedDeviceClass(i) ){
case vr::TrackedDeviceClass_HMD:
mat44_from_hmd34(m_pose, tdp[i].mDeviceToAbsoluteTracking );
break;
}
}
Then when rendering you use m_pose and the m_eye… matrices.

Pthreads not working in Embedded ARM

Hello i am using AM1808 ARM9 microprocessor.
I have an interfacing of GSM dongle.I want to make the GSM dongle connection as well all data transmission as well reception in the background using pthreads.
When i am trying to connect the dongle in background it is continuously blinking green light and i could not get connect to the server.
I can not find the problem.
Here is my code for the datacard initialisation as well as communication routine.
I am initialising the Thread in the Main thread.
int InitializeDataCard(void)
{
static int connect_ret = 0;
pthread_t processing_th;
pthread_create(&processing_th, NULL, Datacard_Connection_Thread, &db_mc_object);
pthread_detach(processing_th);
ShowMessageBox(msgbox_text[136], MB_TASKMODAL);
if(connect_ret)
{
ShowMessageBox(msgbox_text[163], MB_ICONERROR);
return -1;`enter code here`
}
else
{
return 0;
}
}
int ConnectToServer(void)
{
int connect_ret = 0;
Dprintf(__func__,"Trying to connect ....");
DPUUtilsLib_RetrieveParameter(PID_DATACARD_INFO,(UCHAR *)&datacard_info,sizeof(datacard_info));
connect_ret = DataCardConnect(datacard_info);
sleep(3);
//g_do_process = 0;
Dprintf(__func__,"DataCardConnect ret=%d",connect_ret);
return connect_ret;
}
void * Datacard_Connection_Thread(void *tempdata)
{
int ret=0,response = -1,enc_ret=0;
static int g_gsm_response = 0;
dpu_csv_file_param_t fileparam;
dpu_db_export_search_params_t tempparams;
dpu_db_milk_collection_t *livedata,*updatedata;
dpu_db_user_master_t CreatedBy,UpdatedBy;
dpu_db_society_master_t soc_info;
char filename[50]={0};
livedata = (dpu_db_milk_collection_t *)tempdata;
//Connect to the Network
create_connection :
ret = ConnectToServer();
//connected successfully
if(!ret)
{
//Get the SocietyCode from the Database
if(g_data_available)
{
g_data_available=0;
soc_info.SocietyId = g_society_list[g_selected_society].SocietyId;
DPUDBLib_search_society_master(&soc_info);
strncpy(livedata->SocietyCode,soc_info.SocietyCode,5);
Dprintf(__func__,"%04d\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %5.2f\n %7.2f\n %7.2f\n %03d\n %c\n %d\n %5.2d\n %s\n %d",
livedata->MemberCode,livedata->Fat,livedata->LRCLR,livedata->SNF,livedata->Solid,
livedata->FatKG,livedata->SNFKG,livedata->Rate,livedata->Amount,
livedata->CanNumber,livedata->EntryMode,livedata->MC_RateChartId,livedata->Water,livedata->SocietyCode,__LINE__);
sprintf(tempparams.FileName,"%s/%s",DATA_TEMP,MT_MILKLIVEFILE);
memcpy(fileparam.FilePath,tempparams.FileName,sizeof(tempparams.FileName));
fileparam.Type = DPU_CSV_EXPORT;
fileparam.FileType = DPU_CSV_MILK_LIVE_DATA_FILE;
//open a csv file
DPUCSVLib_open_csv_file(&fileparam);
memset(&CreatedBy,0,sizeof(dpu_db_user_master_t));
memset(&UpdatedBy,0,sizeof(dpu_db_user_master_t));
strncpy(CreatedBy.Username,TempUser,5);
//write the live data into the file
DPUCSVLib_write_csv_file(&fileparam,livedata,&CreatedBy,&UpdatedBy);
//encrypt the file
enc_ret = DPUEncryptFile(tempparams.FileName,filename);
if(!enc_ret)
{
//send file request to server for the accepting the data
response = SendFileRequest(g_gsm_response,filename,9);
if(!response)
{
//receive the response of the server
response = GetResponceFromServer(g_gsm_response,&response,9);
if(response || g_gsm_response) response = -1;
else
{
//If record is successfully sent to the server then update the FlagGSM flag of the record as well as
//Update the database
g_update_record = 1;
livedata->FlagGSM = 1;
updatedata->MilkCollectionId = livedata->MilkCollectionId;
DPUDBLib_search_milk_collection_entry_by_record(&updatedata);
DPUDBLib_edit_milk_collection_entry(&updatedata,&livedata);
g_update_record = 0;
}
}
//remove the temp file generated
remove(filename);
}
}
}
else
{
//if connection is not successfully done then try to reconnect the server
ShowMessageBox(msgbox_text[156], MB_ICONERROR);
goto create_connection;
}
}
I think there is basic mistake here. By declaring the static variable connect_ret in InitializeDataCard, it does not mean in any way that it is going to be the same variable declared in ConnectToServer. Therefore, the first function will always have the same behaviour...
I think you'll need a global variable (i.e. not defined in a function) and possibily some kind of synchronization, because when you create the thread, then probably it won't be executed immediately, so even if you have a global variable, you can't check against it until you know that it has been correctly set.