Recording multiple key presses in x11 - c

I want to record simultaneous key presses and test a function in x11 using C. For example, I was able to set something like,
if 'Q' is pressed,
let the window resize.
But I could not find a method for doing the same with a key combination such as Ctrl+Enter, etc, so that when 'Ctrl+Enter' is pressed, the window resizes.
Is there any event type or mask or function in x11 for recording these simultaneous key events ?
The code below is what I have written so far for recording single keys and performing specified action.
// USES KEYBOARD KEY TO RESIZE A WINDOW
// Compile : gcc -o go key_and_win.c -lX11
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
Display *d;
Window window;
XEvent event, ev;
int s;
/* open connection with the server */
d = XOpenDisplay(NULL);
if (d == NULL)
{
fprintf(stderr, "Cannot open d\n");
exit(1);
}
s = DefaultScreen(d);
/* create window */
window = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 200, 200, 1,
BlackPixel(d, s), BlackPixel(d, s));
/* select kind of events we are interested in */
XSelectInput(d, window, StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask );
/* map (show) the window */
XMapWindow(d, window);
/* event loop */
while (1)
{
XNextEvent(d, &event);
/* keyboard events */
if (event.type == KeyPress)
{
printf( "KeyPress: %x\n", event.xkey.keycode );
if(event.xkey.keycode == 0x18) // Resize on pressing Q as, key Q => 0x18
{
printf("Here in Q\n");
int r = XResizeWindow(d, window, 100, 200); // Resizing the window through Q keypress
if(r==BadValue || r==BadWindow)
printf("Error in resizing\n");
XNextEvent(d, &event); // To get ConfigureNotify event
if(event.type == ConfigureNotify)
printf("Resized!\n");
else
printf("Not resized\n");
//XMapWindow(d, window); // Map the resized window (not necessary)
}
/* exit on ESC key press */
if ( event.xkey.keycode == 0x09 )
break;
}
}
/* close connection to server */
XCloseDisplay(d);
return 0;
}

you have to look at event.xkey.state
from 10.5.2 Keyboard and Pointer Events :
The state member is set to indicate the logical state of the pointer buttons and modifier keys just prior to the event, which is the bitwise inclusive OR of one or more of the button or modifier key masks: Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask, ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask.

Related

Terminal in XLIB Window Manager not receiving key presses from "OnBoard" on screen keyboard

Consider the following minimal window manager found online. It compiles and runs fine.
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
Display *display;
Window window;
XEvent event;
int s;
/* open connection with the server */
display = XOpenDisplay(NULL);
if (display == NULL)
{
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(display);
/* create window */
window = XCreateSimpleWindow(display, RootWindow(display, s), 10, 10, 200, 200, 1,
BlackPixel(display, s), WhitePixel(display, s));
/* select kind of events we are interested in */
XSelectInput(display, window, KeyPressMask | KeyReleaseMask );
/* map (show) the window */
XMapWindow(display, window);
/* event loop */
while (1)
{
XNextEvent(display, &event);
/* keyboard events */
if (event.type == KeyPress)
{
printf( "KeyPress: %x\n", event.xkey.keycode );
/* exit on ESC key press */
if ( event.xkey.keycode == 0x09 )
break;
}
else if (event.type == KeyRelease)
{
printf( "KeyRelease: %x\n", event.xkey.keycode );
}
}
/* close connection to server */
XCloseDisplay(display);
return 0;
}
In this window manager, I can load a terminal (such as xterm) and the "onboard" on screen keyboard program with ubuntu (server addition, with xinit installed). The onboard on screen keyboard is not sending key input to other windows in this minimal window manager (onboard loads on the bottom region of the screen).
Note that DWM minimalist window manager works as expected (the onboard input gets sent to all other windows). Im unable to find in the DWM source where this kind of thing is considered.
My question is this: How to I make this minialist window manager allow the Onboard on screen keyboard to send input to other windows?
Found the solution. I should have been using XSetInputFocus on the terminal, then input goes there correctly.
//e.window is the program window for the program that should get the input.
XSetInputFocus(mDisplay, e.window, RevertToPointerRoot, CurrentTime);

Open a dock type window with x11 and capture key press

I would like to open a "dock type" window without its title bar with x11 in C and I want to capture a key press (Ctrl-q) to close it. The actual code does not capture the key presses to the active window as they are all sent and printed in the terminal. Almost all the Ctrl key presses are somehow not detected. The only key presses that actually work on the opened window are Ctrl-c. I am aware of the _MOTIF_WM_HINTS property but it has the disadvantage to display a window icon in the panel to show a new opened window.
How can I have a "dock type" window while not losing the ability to detect key presses to the active window?
Here is the code basically copied from two other posts here and here
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
int main(int argc, char **argv)
{
Display *dpy = XOpenDisplay(0);
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, blackColor, blackColor);
//Tell X Server to send MapNotify events
XSelectInput(dpy, w, StructureNotifyMask | KeyPressMask);
Atom window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
XChangeProperty(dpy, w, window_type, 4, 32,
PropModeReplace,
(unsigned char *)&value, 1);
//Make window appear
XMapWindow(dpy, w);
//Graphics Context
GC gc = XCreateGC(dpy, w, 0, 0);
//Set white color for drawing
XSetForeground(dpy, gc, whiteColor);
//Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify) {
break;
}
}
//Draw the line
XDrawLine(dpy, w, gc, 10, 60, 180, 20);
//Send the "DrawLine" request to the server
XFlush(dpy);
char text[255];
XEvent e;
KeySym key;
int numKeys = 0;
for(;;) {
XNextEvent(dpy, &e);
if(e.type == KeyPress) {
if((numKeys = XLookupString(&e.xkey, text, 255, &key, 0))) {
if(e.xkey.state == ControlMask && key == XK_q) {
printf("CTRL-Q\n");
break;
}
}
}
}
if (dpy && gc) XFreeGC(dpy, gc);
if (dpy && w) XDestroyWindow(dpy, w);
if (dpy) XCloseDisplay(dpy);
return 0;
}
Compiled with:
gcc main.c -L/usr/X11R6/lib -lX11 -lm && ./a.out
I've also looked at the _NET_WM_STRUT_PARTIAL property but I haven't been succesful at implementing it.

Xopendisplay segmentation fault

I'm carrying out a simple X11 program in C. But I got segmentation fault(11) because of XOpenDisplay(NULL).
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
Display *display;
Window window;
XEvent event;
char *msg = "Hello, World!";
int s;
/* /2/ some basic X11 setup */
/* open connection with the server */
display = XOpenDisplay(NULL);
if (display == NULL)
{
fprintf(stderr, "Cannot open display\n");
exit(1);
}
s = DefaultScreen(display);
/* create window */
window = XCreateSimpleWindow(display, RootWindow(display, s), 10, 10, 200, 200, 1,
BlackPixel(display, s), WhitePixel(display, s));
/* select kind of events we are interested in */
XSelectInput(display, window, ExposureMask | KeyPressMask);
/* map (show) the window */
XMapWindow(display, window);
/* /3/ event loop */
for (;;)
{
XNextEvent(display, &event);
/* /4/ draw or redraw the window */
if (event.type == Expose)
{
XFillRectangle(display, window, DefaultGC(display, s), 20, 20, 10, 10);
XDrawString(display, window, DefaultGC(display, s), 50, 50, msg, strlen(msg));
}
/* /5/ exit on key press */
if (event.type == KeyPress)
break;
}
/* /6/ close connection to server */
XCloseDisplay(display);
return 0;
}
command line:
gcc -o out test.c -I/usr/X11R6/include/ -L/usr/X11R6/lib/ -lX11
I executed it failed in Mac terminal, but it worked in Xcode. I don't know the reasons.

Select a specific window X11

I am designing an app that having the ID of an X11 window to draw a rectangle.
The problem I have is that I can not draw nothing in the window.
Code
One obvious error is that you did not select ExposureMask in call to XSelectInput, so you will not receive Expose event you are waiting for.
Other possible problem is not setting foreground drawing color of the GC by XSetForegroundColor, default is black. And using default gc of screen may fail if the window has different color depth or different visual. Other important GC attributes issubwindow_mode (whether to draw over child windows).
Still, after I did those changes, the program only works for me (draws a rectangle) on root window and xev, but not for xterm, no expose events.
This is my fixed version:
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[]){
Window win;
Display *display;
XEvent e;
display = XOpenDisplay(NULL);
if(display==NULL){
fprintf(stderr,"Cannot open Display\n");
exit(1);
}
int s = DefaultScreen(display);
//unsigned long *id = (unsigned long*)(argv[1]);
sscanf(argv[1], "0x%x", &win);
if(!XSelectInput(display,win,StructureNotifyMask | ExposureMask)){
fprintf(stderr,"Cannot select Display\n");
return -1;
}
if(!XMapWindow(display,win)){
fprintf(stderr,"Cannot map Display\n");
return -1;
}
XGCValues gcv;
gcv.subwindow_mode = IncludeInferiors;
GC gc = XCreateGC(display, win, GCSubwindowMode,
&gcv);
XSetForeground(display, gc, 0xff00ff00);
XSetPlaneMask(display, gc, 0xffffffff);
while (1) {
puts("waiting for event\n");
XNextEvent(display, &e);
puts("got event\n");
if (e.type == Expose) {
printf("drawing\n");
XFillRectangle(display, win, gc, 20, 20, 100, 100);
}
if (e.type == KeyPress)
break;
}
return 0;
}

SDL C mouse/keyboard output

is there any ways to press keys mouse/keyboard with sdl in C?
if yes, how?
if no, do you know any ways to do that in C?
Create an SDL_event structure and fill in the fields as documented in http://wiki.libsdl.org/SDL_KeyboardEvent and http://wiki.libsdl.org/SDL_Keysym then use SDL_Pushevent() to put the event into the event queue:
http://wiki.libsdl.org/SDL_PushEvent
SDL_Event event;
event.type = SDL_KEYDOWN;
event.timestamp = lastEvent.timestamp + 1;
event.windowID - lastEvent.windowID;
event.state = SDL_PRESSED;
event.keysym.scancode = SDL_SCANCODE_ESCAPE; // from SDL_Keysym
event.keysym.sym = SDLK_ESCAPE;
event.keysym.mod = 0; // from SDL_Keymod
SDL_PushEvent(&Event) // Inject key press of the Escape Key
Do the same thing for any other event in the SDL_Event union including mouse events: http://wiki.libsdl.org/SDL_MouseButtonEvent
As of SDL 2.0.3, SDL doesn't support sending input events to other applications. On Windows you can use the SendInput function to send input events to other applications. With X11 you can use the xcb_send_event function. I'm not sure about OS X, iOS, or Android.
This program demonstrates how to read mouse and keyboard input in an SDL program. It will run for a few seconds, and display "up arrow" or "down arrow" when either of those keys are pressed, and display "mouse clicked" and coordinates when the mouse is clicked.
#include "SDL2/SDL.h"
#include <stdlib.h>
int main(){
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow( "Keyboard and mouse input",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
500, 500, SDL_WINDOW_SHOWN );
int i;
for (i = 0; i< 3000; i++){
SDL_UpdateWindowSurface(window);
SDL_Event event;
while (SDL_PollEvent(&event)){//this is where the important stuff happens:
if( event.type == SDL_KEYDOWN ) {
switch( event.key.keysym.sym ) {
case SDLK_UP:
puts("up arrow");
break;
case SDLK_DOWN://for full list of key names, http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlkey.html
puts("down arrow");
break;
}
}
else if (event.type == SDL_MOUSEBUTTONDOWN){
int x, y;
SDL_GetMouseState(&x,&y);
printf("%s button mouse clicked at: (%d,%d)\n",
(event.button.button == SDL_BUTTON_LEFT)? "left" : "right",
x,y);
}
}
SDL_Delay(1);
}
SDL_DestroyWindow(window);
SDL_Quit();
}
this is for SDL version 2
basically, you need to call SDL_PollEvent, and then check the resulting SDL_Event struct for information about whether it was a keyboard or mouse event, and if so where the mouse was or what button was pressed.

Resources