XLIB and/or KDE: Determing and Changing Window Focus
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
XLIB and/or KDE: Determing and Changing Window Focus
Since Guttorn helped me to solve my previous issue, I now have a new problem to solve:
I am modifying a pre-existing C program that redirects USB events from a Contour Designs ShuttlePro V2 to keystrokes.
Issue #1
Is possible to find out what window is currently focused in X and/or KDE? If I can determine this then I can make the functions of some of the buttons change depending on which window of my video editing application (Cinelerra CV) is focused, making those 15 buttons go a lot further.
Issue #2
Is it possible to force focus to a specific window. For example, I could a key that would make the timeline focused and another to make the viewer focused, or better yet make one button toggle between the two if my first issue works.
Thanks,
Matt
BTW, here is the program thus far if anyone is interested:
Code:
/* -*- indent-tabs-mode:T; c-basic-offset:8; tab-width:8; -*- vi: set ts=8 noet:
* $Id: shuttlepro.c,v 1.1 2006/04/08 15:22:31 hudson Exp $
*
* Contour ShuttlePro v2 interface for Cinelerra.
* Based heavily on code by Arendt David <admin@prnet.org>
*
* (c) 2006 Trammell Hudson <hudson@osresearch.net>
*
* Build with:
* gcc -O3 -W -Wall ./shuttlepro.c -o shuttlepro -L /usr/X11R6/lib -lX11 -lXtst
*/
#define DELAY 10
#define KEY 1
#define KEY1 256
#define KEY2 257
#define KEY3 258
#define KEY4 259
#define KEY5 260
#define KEY6 261
#define KEY7 262
#define KEY8 263
#define KEY9 264
#define KEY10 265
#define KEY11 266
#define KEY12 267
#define KEY13 268
#define KEY14 269
#define KEY15 270
#define JOGSHUTTLE 2
#define JOG 7
#define SHUTTLE 8
#define X_LAST_KEYSYM
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <linux/input.h>
#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>
#include <X11/keysym.h>
typedef struct input_event EV;
unsigned short jogvalue = 0xffff;
int shuttlevalue = 0xffff;
struct timeval last_shuttle;
int need_synthetic_shuttle;
Display * display;
void initdisplay()
{
int event, error, major, minor;
display = XOpenDisplay(0);
if (!display)
{
fprintf(stderr, "unable to open X display\n");
exit(1);
}
if (!XTestQueryExtension(display, &event, &error, &major, &minor))
{
fprintf(stderr, "Xtest extensions not supported\n");
XCloseDisplay(display);
exit(1);
}
}
void
sendkey(
KeySym modifier,
KeySym key
)
{
KeyCode modifiercode;
KeyCode keycode;
if (modifier != 0)
{
modifiercode = XKeysymToKeycode(display, modifier);
XTestFakeKeyEvent(display, modifiercode, True, DELAY);
}
keycode = XKeysymToKeycode(display, key);
XTestFakeKeyEvent(display, keycode, True, DELAY);
XTestFakeKeyEvent(display, keycode, False, DELAY);
if (modifier != 0)
XTestFakeKeyEvent(display, modifiercode, False, DELAY);
XFlush(display);
}
/*
* The keys on the Contour Shuttle Pro v2 are arranged like this:
*
* 1 2 3 4
* 5 6 7 8 9
*
* 14 Jog 15
*
* 10 11
* 12 13
*
*/
static KeySym
button_mappings[][2] = {
// [ 1] = { XK_Delete }, // Extend Head
// [ 2] = { XK_Delete }, // Trim Head
// [ 3] = { XK_Delete }, // Extend Tail
// [ 4] = { XK_Delete }, // Trim Tail
// [ 5] = { 'v' }, // Nudge Back
// [ 6] = { 'b' }, // Nudge Forward
// [ 7] = { 'i' }, // Toggle Timeline/Viewer
[ 8] = { XK_Left, XK_Alt_L }, // Previous Edit/Media
[ 9] = { XK_Right, XK_Alt_L }, // Next Edit/Media
[10] = { '[', XK_Mode_switch }, // Mark In point
[11] = { 'v' }, // Splice
[12] = { ']', XK_Mode_switch }, // Mark Out point
[13] = { 'b' }, // Overwrite
[14] = { XK_KP_6 }, // Reverse
[15] = { XK_KP_3 }, // Play
};
void
key(
unsigned short code,
unsigned int value
)
{
if( value == 0 )
{
// Button release (ignored)
return;
}
code -= KEY1 - 1;
// Bound check!
if( code > 16 )
return;
KeySym * map = button_mappings[ code ];
if( map[0] == 0 && map[1] == 0 )
return; // Unmapped
sendkey( map[1], map[0] );
/*
{
case KEY5 : sendkey(0, 'z'); break; //undo
case KEY14 : sendkey(XK_Mode_switch, '['); break; //begin region
case KEY15 : sendkey(XK_Mode_switch, ']'); break; //end region
case KEY8 : sendkey(0, 'v'); break; //splice paste
case KEY9 : sendkey(0, 'x'); break; //cut
}
*/
}
void
shuttle(
int value
)
{
static int last_key = 100;
gettimeofday( &last_shuttle, 0 );
need_synthetic_shuttle = value != 0;
if( value == shuttlevalue )
return;
shuttlevalue = value;
switch( value )
{
case -7 : if (last_key != XK_KP_Add) sendkey(0, XK_KP_Add); last_key = XK_KP_Add; break; // Reverse Fast
case -6 : if (last_key != XK_KP_Add) sendkey(0, XK_KP_Add); last_key = XK_KP_Add; break; // Reverse Fast
case -5 : if (last_key != XK_KP_6) sendkey(0, XK_KP_6); last_key = XK_KP_6; break; // Reverse Plaay
case -4 : if (last_key != XK_KP_6) sendkey(0, XK_KP_6); last_key = XK_KP_6; break; // Reverse Play
case -3 : if (last_key != XK_KP_6) sendkey(0, XK_KP_6); last_key = XK_KP_6; break; // Reverse Play
case -2 : if (last_key != XK_KP_5) sendkey(0, XK_KP_5); last_key = XK_KP_5; break; // Reverse Slow
case -1 : if (last_key != XK_KP_5) sendkey(0, XK_KP_5); last_key = XK_KP_5; break; // Reverse Slow
case 0 : sendkey(0, XK_KP_0); break; // Stop!
case 1 : if (last_key != XK_KP_2) sendkey(0, XK_KP_2); last_key = XK_KP_2; break; // Forward Slow
case 2 : if (last_key != XK_KP_2) sendkey(0, XK_KP_2); last_key = XK_KP_2; break; // Forward Slow
case 3 : if (last_key != XK_KP_3) sendkey(0, XK_KP_3); last_key = XK_KP_3; break; // Forward Play
case 4 : if (last_key != XK_KP_3) sendkey(0, XK_KP_3); last_key = XK_KP_3; break; // Forward Play
case 5 : if (last_key != XK_KP_3) sendkey(0, XK_KP_3); last_key = XK_KP_3; break; // Forward Play
case 6 : if (last_key != XK_KP_Enter) sendkey(0, XK_KP_Enter); last_key = XK_KP_Enter; break; // Forward Fast
case 7 : if (last_key != XK_KP_Enter) sendkey(0, XK_KP_Enter); last_key = XK_KP_Enter; break; // Forward Fast
}
}
/*
* Due to a bug (?) in the way Linux HID handles the ShuttlePro, the
* center position is not reported for the shuttle wheel. Instead,
* a jog event is generated immediately when it returns. We check to
* see if the time since the last shuttle was more than a few ms ago
* and generate a shuttle of 0 if so.
*/
void
check_synthetic()
{
if( !need_synthetic_shuttle )
return;
struct timeval now, delta;
gettimeofday( &now, 0 );
timersub( &now, &last_shuttle, &delta );
if( delta.tv_sec < 1 && delta.tv_usec < 5000 )
return;
shuttle( 0 );
need_synthetic_shuttle = 0;
}
void
jog(
unsigned int value
)
{
// We should generate a synthetic event for the shuttle going
// to the home position if we have not seen one recently
check_synthetic();
if( jogvalue != 0xffff )
{
if (value < jogvalue)
sendkey( 0, XK_KP_4 );
else if (value > jogvalue)
sendkey( 0, XK_KP_1 );
}
jogvalue = value;
}
void
jogshuttle(
unsigned short code,
unsigned int value
)
{
switch (code)
{
case JOG : jog(value); break;
case SHUTTLE : shuttle(value); break;
}
}
void
handle_event(
EV ev
)
{
switch (ev.type)
{
case KEY : key(ev.code, ev.value); break;
case JOGSHUTTLE : jogshuttle(ev.code, ev.value); break;
}
}
int
main(
int argc,
char ** argv
)
{
char name[256] = "unknown";
EV ev;
if (argc < 2)
{
fprintf( stderr, "syntax: shuttlepro <device>\n" );
return EXIT_FAILURE;
}
//printf("shuttlepro 0.1beta written by Arendt David (admin@prnet.org)v 1.1 \n");
const char * dev_name = argv[1];
const int fd = open( dev_name, O_RDONLY );
if (fd < 0)
{
fprintf( stderr, "unable to open %s\n", dev_name );
return EXIT_FAILURE;
}
if( ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0 )
{
perror("evdev ioctl");
return EXIT_FAILURE;
}
printf( "%s: %s\n", dev_name, name );
/* Flag it as exclusive access */
if( ioctl( fd, EVIOCGRAB, 1 ) < 0 )
{
perror( "evgrab ioctl" );
return EXIT_FAILURE;
}
initdisplay();
while (1)
{
read(fd, &ev, sizeof(ev));
handle_event(ev);
}
close(fd);
return 0;
}
Thanks for posting your code, links and information! I'm trying to work with a ShuttlePro V2 under openSuSE 11.0 at the moment and am lost, never having had to deal with such complicated key bindings before...
Can you point me to any instructions on how to use your program, what it relies on and how to set up a build environment for it? Also, how is it used or invoked?
As you can probably guess, I've never undertaken anything with hardware inputs like this before, so am not sure where to start. I've done lots of reading based around using xbindkeys for extra buttons on devices, but from your posts it looks like this is the wrong approach.
Any help appreciated. Cheers,
Rishi.
My dmesg:
Code:
usb 1-1: new full speed USB device using ohci_hcd and address 2
usb 1-1: configuration #1 chosen from 1 choice
usb 1-1: New USB device found, idVendor=0b33, idProduct=0030
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1: Product: ShuttlePRO v2
usb 1-1: Manufacturer: Contour Design
usbcore: registered new interface driver hiddev
input: Contour Design ShuttlePRO v2 as /class/input/input5
input,hidraw0: USB HID v1.10 Device [Contour Design ShuttlePRO v2] on usb-0000:00:06.0-1
usbcore: registered new interface driver usbhid
drivers/hid/usbhid/hid-core.c: v2.6:USB HID core driver
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.