xcb_keysym_t XcbIn::keysym(xcb_keycode_t code) const { xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(connection); // xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, kpe, kpe->state); xcb_keysym_t sym = xcb_key_symbols_get_keysym(symbols, code, 0); xcb_key_symbols_free(symbols); return sym; }
/* * Returns the mask for Mode_switch (to be used for looking up keysymbols by * keycode). * */ uint32_t get_mod_mask(xcb_connection_t *conn, uint32_t keycode) { xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(conn); xcb_get_modifier_mapping_reply_t *modmap_r; xcb_keycode_t *modmap, kc; xcb_keycode_t *modeswitchcodes = xcb_key_symbols_get_keycode(symbols, keycode); if (modeswitchcodes == NULL) return 0; modmap_r = xcb_get_modifier_mapping_reply(conn, xcb_get_modifier_mapping(conn), NULL); modmap = xcb_get_modifier_mapping_keycodes(modmap_r); for (int i = 0; i < 8; i++) for (int j = 0; j < modmap_r->keycodes_per_modifier; j++) { kc = modmap[i * modmap_r->keycodes_per_modifier + j]; for (xcb_keycode_t *ktest = modeswitchcodes; *ktest; ktest++) { if (*ktest != kc) continue; free(modeswitchcodes); free(modmap_r); return (1 << i); } } return 0; }
int16_t modfield_from_keysym(xcb_keysym_t keysym) { uint16_t modfield = 0; xcb_keycode_t *keycodes = NULL, *mod_keycodes = NULL; xcb_get_modifier_mapping_reply_t *reply = NULL; xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(dpy); if ((keycodes = xcb_key_symbols_get_keycode(symbols, keysym)) == NULL || (reply = xcb_get_modifier_mapping_reply(dpy, xcb_get_modifier_mapping(dpy), NULL)) == NULL || reply->keycodes_per_modifier < 1 || (mod_keycodes = xcb_get_modifier_mapping_keycodes(reply)) == NULL) { goto end; } unsigned int num_mod = xcb_get_modifier_mapping_keycodes_length(reply) / reply->keycodes_per_modifier; for (unsigned int i = 0; i < num_mod; i++) { for (unsigned int j = 0; j < reply->keycodes_per_modifier; j++) { xcb_keycode_t mk = mod_keycodes[i * reply->keycodes_per_modifier + j]; if (mk == XCB_NO_SYMBOL) { continue; } for (xcb_keycode_t *k = keycodes; *k != XCB_NO_SYMBOL; k++) { if (*k == mk) { modfield |= (1 << i); } } } } end: xcb_key_symbols_free(symbols); free(keycodes); free(reply); return modfield; }
void keyboard::update_mapping( void ) { auto cookie = xcb_get_modifier_mapping_unchecked( _connection ); if ( _keysyms ) xcb_key_symbols_free( _keysyms ); _keysyms = xcb_key_symbols_alloc( _connection ); auto numlockcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Num_Lock ) ); auto shiftlockcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Shift_Lock ) ); auto capslockcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Caps_Lock ) ); auto modeswitchcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Mode_switch ) ); auto modmap_r = core::wrap_cptr( xcb_get_modifier_mapping_reply( _connection, cookie, nullptr ) ); xcb_keycode_t *modmap = xcb_get_modifier_mapping_keycodes( modmap_r.get() ); _numlock = 0; _shiftlock = 0; _capslock = 0; _modeswitch = 0; for( int i = 0; i < 8; i++ ) { for( int j = 0; j < modmap_r->keycodes_per_modifier; j++ ) { xcb_keycode_t kc = modmap[i * modmap_r->keycodes_per_modifier + j]; look_for( _numlock, numlockcodes, kc, i ); look_for( _shiftlock, shiftlockcodes, kc, i ); look_for( _capslock, capslockcodes, kc, i ); look_for( _modeswitch, modeswitchcodes, kc, i ); } } }
/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; intf_sys_t *p_sys; p_intf->p_sys = p_sys = calloc( 1, sizeof(*p_sys) ); if( !p_sys ) return VLC_ENOMEM; char *psz_display = var_CreateGetNonEmptyString( p_intf, "x11-display" ); int i_screen_default; p_sys->p_connection = xcb_connect( psz_display, &i_screen_default ); free( psz_display ); if( !p_sys->p_connection ) goto error; /* Get the root windows of the default screen */ const xcb_setup_t* xcbsetup = xcb_get_setup( p_sys->p_connection ); if( !xcbsetup ) goto error; xcb_screen_iterator_t iter = xcb_setup_roots_iterator( xcbsetup ); for( int i = 0; i < i_screen_default; i++ ) { if( !iter.rem ) break; xcb_screen_next( &iter ); } if( !iter.rem ) goto error; p_sys->root = iter.data->root; /* */ p_sys->p_symbols = xcb_key_symbols_alloc( p_sys->p_connection ); // FIXME if( !p_sys->p_symbols ) goto error; Mapping( p_intf ); Register( p_intf ); if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { Unregister( p_intf ); free( p_sys->p_map ); goto error; } return VLC_SUCCESS; error: if( p_sys->p_symbols ) xcb_key_symbols_free( p_sys->p_symbols ); if( p_sys->p_connection ) xcb_disconnect( p_sys->p_connection ); free( p_sys ); return VLC_EGENERIC; }
/** * Create an X11 key event handler for a VLC window. * The caller shall arrange receiving applicable X11 events, and pass them to * ProcessKeyEvent() later. * * @param obj VLC object owning an X window * @param conn XCB connection to the X server (to fetch key mappings) * @return NULL on error, or a key handling context. */ key_handler_t *CreateKeyHandler (vlc_object_t *obj, xcb_connection_t *conn) { key_handler_t *ctx = malloc (sizeof (*ctx)); if (!ctx) return NULL; ctx->obj = obj; ctx->syms = xcb_key_symbols_alloc (conn); return ctx; }
XCBInput::XCBInput(xcb_connection_t *connection, XCBMediaLayer * mediaLayer) { this->connection = connection; syms = xcb_key_symbols_alloc(connection); pressedKeys = QList<xcb_keysym_t>(); // TODO(bmonkey): Hardcoded values => xml inputSpeed = .01; mouseSensitivity = .1; this->mediaLayer = mediaLayer; }
xcb_keycode_t* xcb_get_keycodes(xcb_keysym_t keysym) { // wrapper to get xcb keycodes from keysymbol xcb_key_symbols_t *keysyms; keysyms = xcb_key_symbols_alloc(SWM.xcb_conn); if (!keysyms) { return NULL; } xcb_keycode_t *keycode = xcb_key_symbols_get_keycode(keysyms, keysym); xcb_key_symbols_free(keysyms); return keycode; }
UGlobalHotkeys::UGlobalHotkeys(QWidget *parent) : QWidget(parent) { #if defined(Q_OS_LINUX) qApp->installNativeEventFilter(this); QWindow wndw; void* v = qApp->platformNativeInterface()->nativeResourceForWindow("connection", &wndw); X11Connection = (xcb_connection_t*)v; X11Wid = xcb_setup_roots_iterator(xcb_get_setup(X11Connection)).data->root; X11KeySymbs = xcb_key_symbols_alloc(X11Connection); #endif }
static xcb_keysym_t xcb_get_keysym (xcb_keysym_t keycode) { xcb_key_symbols_t *keysyms; xcb_keysym_t keysym; if (!(keysyms = xcb_key_symbols_alloc(conn))) return 0; keysym = xcb_key_symbols_get_keysym(keysyms, (unsigned char)keycode, 0); xcb_key_symbols_free(keysyms); return keysym; }
static xcb_keycode_t * xcb_get_keycode (xcb_keysym_t keysym) { xcb_key_symbols_t *keysyms; xcb_keycode_t *keycode; if (!(keysyms = xcb_key_symbols_alloc(conn))) return 0; keycode = xcb_key_symbols_get_keycode(keysyms, keysym); xcb_key_symbols_free(keysyms); return keycode; }
void ae3d::Window::Create( int width, int height, WindowCreateFlags flags ) { WindowGlobal::display = XOpenDisplay( nullptr ); if (!WindowGlobal::display) { std::cerr << "Can't open display" << std::endl; return; } int default_screen = DefaultScreen( WindowGlobal::display ); WindowGlobal::connection = XGetXCBConnection( WindowGlobal::display ); LoadAtoms(); if (!WindowGlobal::connection) { XCloseDisplay( WindowGlobal::display ); std::cerr << "Can't get xcb connection from display" << std::endl; return; } XSetEventQueueOwner( WindowGlobal::display, XCBOwnsEventQueue ); xcb_screen_t* screen = nullptr; xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator( xcb_get_setup( WindowGlobal::connection ) ); for (int screen_num = default_screen; screen_iter.rem && screen_num > 0; --screen_num, xcb_screen_next( &screen_iter )); screen = screen_iter.data; WindowGlobal::key_symbols = xcb_key_symbols_alloc( WindowGlobal::connection ); if (CreateWindowAndContext( WindowGlobal::display, WindowGlobal::connection, default_screen, screen, width, height, flags ) == -1) { return; } GfxDevice::Init( WindowGlobal::windowWidth, WindowGlobal::windowHeight ); const char *title = "Aether3D Game Engine"; xcb_change_property(WindowGlobal::connection, XCB_PROP_MODE_REPLACE, WindowGlobal::window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen (title), title ); WindowGlobal::isOpen = true; }
/* * Finds out which modifier mask is the one for numlock, as the user may change this. * */ void xcb_get_numlock_mask(xcb_connection_t *conn) { xcb_key_symbols_t *keysyms; xcb_get_modifier_mapping_cookie_t cookie; xcb_get_modifier_mapping_reply_t *reply; xcb_keycode_t *modmap; int mask, i; const int masks[8] = { XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL, XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4, XCB_MOD_MASK_5 }; /* Request the modifier map */ cookie = xcb_get_modifier_mapping_unchecked(conn); /* Get the keysymbols */ keysyms = xcb_key_symbols_alloc(conn); if ((reply = xcb_get_modifier_mapping_reply(conn, cookie, NULL)) == NULL) { xcb_key_symbols_free(keysyms); return; } modmap = xcb_get_modifier_mapping_keycodes(reply); /* Get the keycode for numlock */ #ifdef OLD_XCB_KEYSYMS_API xcb_keycode_t numlock = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK); #else /* For now, we only use the first keysymbol. */ xcb_keycode_t *numlock_syms = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK); if (numlock_syms == NULL) return; xcb_keycode_t numlock = *numlock_syms; free(numlock_syms); #endif /* Check all modifiers (Mod1-Mod5, Shift, Control, Lock) */ for (mask = 0; mask < 8; mask++) for (i = 0; i < reply->keycodes_per_modifier; i++) if (modmap[(mask * reply->keycodes_per_modifier) + i] == numlock) xcb_numlock_mask = masks[mask]; xcb_key_symbols_free(keysyms); free(reply); }
void setup(void) { dpy = xcb_connect(NULL, NULL); if (xcb_connection_has_error(dpy)) err("Can't open display.\n"); xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data; if (screen == NULL) err("Can't acquire screen.\n"); root = screen->root; if ((shell = getenv(SXHKD_SHELL_ENV)) == NULL && (shell = getenv(SHELL_ENV)) == NULL) err("The '%s' environment variable is not defined.\n", SHELL_ENV); symbols = xcb_key_symbols_alloc(dpy); hotkeys_head = hotkeys_tail = NULL; progress[0] = '\0'; }
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) { quint32 native = 0; KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); if (keysym == XCB_NO_SYMBOL) keysym = static_cast<ushort>(key); xcb_key_symbols_t *xcbKeySymbols = xcb_key_symbols_alloc(QX11Info::connection()); QScopedPointer<xcb_keycode_t, QScopedPointerPodDeleter> keycodes( xcb_key_symbols_get_keycode(xcbKeySymbols, keysym)); native = keycodes.data()[0]; // Use the first keycode xcb_key_symbols_free(xcbKeySymbols); return native; }
App::App(int argc, char** argv): QGuiApplication(argc, argv) ,m_eventFilter(new XcbEventFilter) ,m_init(false) ,m_bus(0) ,m_impanel(0) ,m_keyboardGrabbed(false) ,m_doGrab(false) ,m_syms(0) { m_syms = xcb_key_symbols_alloc(QX11Info::connection()); installNativeEventFilter(m_eventFilter.data()); ibus_init (); m_bus = ibus_bus_new (); g_signal_connect (m_bus, "connected", G_CALLBACK (ibus_connected_cb), this); g_signal_connect (m_bus, "disconnected", G_CALLBACK (ibus_disconnected_cb), this); if (ibus_bus_is_connected (m_bus)) { init(); } initIconMap(m_iconMap); }
static int _e_alert_handle_key_press(xcb_generic_event_t *event) { xcb_key_symbols_t *symbols; xcb_key_press_event_t *ev; xcb_keysym_t key; int r = 0; ev = (xcb_key_press_event_t *)event; symbols = xcb_key_symbols_alloc(conn); key = xcb_key_symbols_get_keysym(symbols, ev->detail, 0); if (key == XK_F1) r = 1; else if (key == XK_F12) r = 2; xcb_key_symbols_free(symbols); return r; }
static int init_key() { unsigned int i; const struct key_t *k; xcb_keycode_t key; nil_.key_syms = xcb_key_symbols_alloc(nil_.con); update_keys_mask(); xcb_ungrab_key(nil_.con, XCB_GRAB_ANY, nil_.scr->root, XCB_MOD_MASK_ANY); for (i = 0; i < cfg_.keys_len; ++i) { k = &cfg_.keys[i]; key = get_keycode(k->keysym); if (key == 0) { continue; } /* grap key in all combinations of NUMLOCK and CAPSLOCK*/ GRAB_ALL_MOD_(GRAB_KEY_, nil_.scr->root, key, k->mod); } return 0; }
void WindowSelector::handleKeyPress(xcb_keycode_t keycode, uint16_t state) { xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(connection()); xcb_keysym_t kc = xcb_key_symbols_get_keysym(symbols, keycode, 0); int mx = 0; int my = 0; const bool returnPressed = (kc == XK_Return) || (kc == XK_space); const bool escapePressed = (kc == XK_Escape); if (kc == XK_Left) { mx = -10; } if (kc == XK_Right) { mx = 10; } if (kc == XK_Up) { my = -10; } if (kc == XK_Down) { my = 10; } if (state & XCB_MOD_MASK_CONTROL) { mx /= 10; my /= 10; } Cursor::setPos(Cursor::pos() + QPoint(mx, my)); if (returnPressed) { selectWindowUnderPointer(); } if (returnPressed || escapePressed) { if (escapePressed) { m_callback(nullptr); } release(); } xcb_key_symbols_free(symbols); }
bool ZealNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { enabled = true; #ifdef WIN32 MSG* msg = static_cast<MSG*>(message); if(WM_HOTKEY == msg->message && msg->wParam == 10) { emit gotHotKey(); return true; } #elsif LINUX // WIN32 or LINUX xcb_generic_event_t* ev = static_cast<xcb_generic_event_t*>(message); if(((ev->response_type&127) == XCB_KEY_PRESS || (ev->response_type&127) == XCB_KEY_RELEASE) && !hotKey.isEmpty()) { // XCB_KEY_RELEASE must be ignored by Qt because otherwise it causes SIGSEGV in QXcbKeyboard::handleKeyReleaseEvent xcb_connection_t *c = static_cast<xcb_connection_t*>( ((QGuiApplication*)QGuiApplication::instance())-> platformNativeInterface()->nativeResourceForWindow("connection", 0)); xcb_key_press_event_t *event = (xcb_key_press_event_t *)ev; xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(c); xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(keysyms, GetX11Key(hotKey[0])); bool found = false; // found=true means either (a) complete hotkey was pressed, or (b) any of its separate // keys was released. We return true in both cases, because key releases while window // is not present cause SIGSEGV in QXcbKeyboard::handleKeyReleaseEvent if((ev->response_type&127) == XCB_KEY_RELEASE) { QList<QPair<int, Qt::Modifier> > modifiers; modifiers.append(qMakePair(XK_Alt_L, Qt::ALT)); modifiers.append(qMakePair(XK_Alt_R, Qt::ALT)); modifiers.append(qMakePair(XK_Control_L, Qt::CTRL)); modifiers.append(qMakePair(XK_Control_R, Qt::CTRL)); modifiers.append(qMakePair(XK_Meta_L, Qt::META)); modifiers.append(qMakePair(XK_Meta_R, Qt::META)); for(auto modifier : modifiers) { if(!(hotKey[0] & modifier.second)) { continue; } xcb_keycode_t *mod_keycodes = xcb_key_symbols_get_keycode(keysyms, modifier.first); if(mod_keycodes == nullptr) continue; int i = 0; while(mod_keycodes[i] != XCB_NO_SYMBOL) { if(event->detail == mod_keycodes[i]) { found = true; } i += 1; } free(mod_keycodes); } } int i = 0; while(keycodes[i] != XCB_NO_SYMBOL) { if(event->detail == keycodes[i]) { bool modifiers_present = true; if(hotKey[0] & Qt::ALT) { if(!(event->state & GetModifier(c, keysyms, XK_Alt_L) || event->state & GetModifier(c, keysyms, XK_Alt_R))) { modifiers_present = false; } } if(hotKey[0] & Qt::CTRL) { if(!(event->state & GetModifier(c, keysyms, XK_Control_L) || event->state & GetModifier(c, keysyms, XK_Control_R))) { modifiers_present = false; } } if(hotKey[0] & Qt::META) { if(!(event->state & GetModifier(c, keysyms, XK_Meta_L) || event->state & GetModifier(c, keysyms, XK_Meta_R))) { modifiers_present = false; } } if(hotKey[0] & Qt::SHIFT) { if(!(event->state & GetModifier(c, keysyms, XK_Shift_L) || event->state & GetModifier(c, keysyms, XK_Shift_R))) { modifiers_present = false; } } if(enabled && modifiers_present) { xcb_allow_events(c, XCB_ALLOW_ASYNC_KEYBOARD, event->time); if((ev->response_type&127) == XCB_KEY_PRESS) { emit gotHotKey(); } found = true; } else { if((ev->response_type&127) == XCB_KEY_RELEASE) { found = true; } xcb_allow_events(c, XCB_ALLOW_REPLAY_KEYBOARD, event->time); } break; } i += 1; } free(keysyms); free(keycodes); if(found) return true; } #endif // WIN32 or LINUX return false; }
void fill_keycodes() { struct xkb_keymap *keymap; struct xkb_context *context; const struct xkb_rule_names rules={ .rules=xkb_names[0], .model=xkb_names[1], .layout=xkb_names[2], .variant=xkb_names[3], .options=xkb_names[4] }; struct xkb_state *state; enum xkb_state_component current_state; int counter; int i,j,k; char mods[256]; char keysym_asc[256]; char file_path[256]; char command[15]; uint32_t max_keys; int w,h,retval; int jumpto; context=xkb_context_new(0); keymap=xkb_keymap_new_from_names(context,&rules,0); state=NULL; // Get all the modifier keys for(i=8;i<256;i++) { state=xkb_state_new(keymap); current_state=xkb_state_update_key(state, i,XKB_KEY_DOWN); if (current_state!=0) { mods[i]=1; } else { mods[i]=0; } xkb_state_unref(state); } mods[7]=1; // fake mod, used for "no mod" // Read the keyboard definition files sprintf(file_path,"%s/%s.keymap",BASE_CONFIG_DIR,lang_onscreen); FILE *keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Can't open keyboard definition file %s. Trying with US file\n",file_path); sprintf(file_path,"%s/us.keymap",BASE_CONFIG_DIR); keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Also failed to open the US keymap file. Aborting.\n"); exit(-1); } } retval=fscanf(keyboard_file,"%s %d",command,&keyboard_blocks); if (retval!=2) { printf("Can't read the number of blocks\n"); } else { max_keys=keyboard_blocks*4*KEYS_PER_ROW; keyboard_lowercase=(struct key_element *)malloc(max_keys*sizeof(struct key_element)); memset(keyboard_lowercase,0,max_keys*sizeof(struct key_element)); for(counter=0;(!feof(keyboard_file))&&(counter<max_keys);counter++) { retval=fscanf(keyboard_file,"%s %d %d",command,&w,&h); if(retval!=3) { break; } keyboard_lowercase[counter].size=KEYS_FONT_SIZE; keyboard_lowercase[counter].g_element[0]=0; keyboard_lowercase[counter].w=w; keyboard_lowercase[counter].h=h; keyboard_lowercase[counter].keycode=0; keyboard_lowercase[counter].modifier=0; if (!strcmp(command,"BLANK")) { keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } else if (!strcmp(command,"KEY")) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].keysym=init_utf8_to_keysym(keyboard_lowercase[counter].g_element); if (keyboard_lowercase[counter].keysym==0) { keyboard_lowercase[counter].type=KEY_BLANK; } } else if ((!strcmp(command,"KEYSYM"))||(!strcmp(command,"KEYSYMTEXT"))) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keysym_asc); keyboard_lowercase[counter].keysym=xkb_keysym_from_name(keysym_asc,0); if (keyboard_lowercase[counter].keysym==0) { printf("Unknown keysym %s\n",keysym_asc); keyboard_lowercase[counter].type=KEY_BLANK; } else { if (!strcmp(command,"KEYSYMTEXT")) { retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].size=KEYS_TEXT_FONT_SIZE; } else { retval=xkb_keysym_to_utf8(keyboard_lowercase[counter].keysym,keyboard_lowercase[counter].g_element,7); if (retval==-1) { retval++; } keyboard_lowercase[counter].g_element[retval]=0;// terminate string } } } else if (!strcmp(command,"TAB")) { keyboard_lowercase[counter].type=KEY_TAB; keyboard_lowercase[counter].keysym=XK_Tab; } else if (!strcmp(command,"SPACE")) { keyboard_lowercase[counter].type=KEY_SPACE; keyboard_lowercase[counter].keysym=XK_space; } else if (!strcmp(command,"RETURN")) { keyboard_lowercase[counter].type=KEY_RETURN; keyboard_lowercase[counter].keysym=XK_Return; } else if (!strcmp(command,"DELETE")) { keyboard_lowercase[counter].type=KEY_DELETE; keyboard_lowercase[counter].keysym=XK_BackSpace; } else if (!strcmp(command,"JUMPTO")) { retval=fscanf(keyboard_file,"%d %s",&jumpto,command); keyboard_lowercase[counter].type=KEY_JUMPTO; keyboard_lowercase[counter].keycode=jumpto; keyboard_lowercase[counter].keysym=0; if (!strcmp(command,"GEN")) { keyboard_lowercase[counter].modifier=0; } else if (!strcmp(command,"SHIFT")) { keyboard_lowercase[counter].modifier=1; } else if (!strcmp(command,"SYMBOLS")) { keyboard_lowercase[counter].modifier=2; } else if (!strcmp(command,"LETTERS")) { keyboard_lowercase[counter].modifier=3; } if (jumpto>=keyboard_blocks) { printf("Ilegal jump to block %d (max. is %d)\n",jumpto,keyboard_blocks); keyboard_lowercase[counter].type=KEY_BLANK; } } else if (!strcmp(command,"UP")) { keyboard_lowercase[counter].type=KEY_UP; keyboard_lowercase[counter].keysym=XK_Up; } else if (!strcmp(command,"DOWN")) { keyboard_lowercase[counter].type=KEY_DOWN; keyboard_lowercase[counter].keysym=XK_Down; } else if (!strcmp(command,"LEFT")) { keyboard_lowercase[counter].type=KEY_LEFT; keyboard_lowercase[counter].keysym=XK_Left; } else if (!strcmp(command,"RIGHT")) { keyboard_lowercase[counter].type=KEY_RIGHT; keyboard_lowercase[counter].keysym=XK_Right; } else { printf("Unknown command %s\n",command); keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } } xkb_keysym_t keysym; xkb_keycode_t keycode_mod; for(i=7;i<256;i++) { // do a loop on every modifier if (!mods[i]) { continue; // In this loop we test each modifier with each keycode } state=xkb_state_new(keymap); if (i!=7) { xkb_state_update_key(state, i,XKB_KEY_DOWN); // press the modifier key keycode_mod=i; } else { keycode_mod=0; } for(j=8;j<256;j++) { if (mods[j]) { continue; // Don't test modifiers; we want "normal" keys } keysym=xkb_state_key_get_one_sym(state, j); if (keysym==XKB_KEY_NoSymbol) { continue; } for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].keysym==keysym)) { keyboard_lowercase[k].keycode=j; keyboard_lowercase[k].modifier=keycode_mod; } } } xkb_state_unref(state); } /*for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained printf("Texto: %s, Keysym: %d, mod: %d\n",keyboard_lowercase[k].g_element,keyboard_lowercase[k].keycode,keyboard_lowercase[k].modifier); }*/ // Now assign new keysyms to keycodes not used, to allow other keysyms not available in US keyboards xcb_key_symbols_t *symbols; symbols=xcb_key_symbols_alloc(conn); xcb_flush(conn); xcb_keycode_t keycode=8; xcb_keycode_t keycode_found; xcb_keysym_t keysyms[4]; xcb_keycode_t keycode_shift; struct lower_upper_t {xcb_keysym_t upper_first; xcb_keysym_t upper_last; xcb_keysym_t lower_first; xcb_keysym_t lower_last; }; struct lower_upper_t lower_upper[] = { {XKB_KEY_Agrave,XKB_KEY_Odiaeresis,XKB_KEY_agrave,XKB_KEY_odiaeresis}, {XKB_KEY_Oslash,XKB_KEY_THORN,XKB_KEY_oslash,XKB_KEY_thorn}, {0,0,0,0} }; struct lower_upper_t *iter_lu; keycode_shift=*xcb_key_symbols_get_keycode(symbols,XKB_KEY_Shift_L); for(k=0;k<max_keys;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].type!=KEY_JUMPTO)) { // this key is not available in US keyboards; let's redefine a keycode for it keycode_found=0; while(keycode<256) { if ((0==xcb_key_symbols_get_keysym(symbols,keycode,0))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,1))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,2))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,3))) { keycode_found=keycode; break; } keycode++; } if (keycode_found==0) { printf("No more codes available\n"); break; // there are no more free keycodes available } keycode=keycode_found; keysyms[0]=keyboard_lowercase[k].keysym; keysyms[1]=0; keysyms[2]=keyboard_lowercase[k].keysym; keysyms[3]=0; for(iter_lu=lower_upper;iter_lu->upper_first;iter_lu++) { if ((keysyms[0]>=iter_lu->upper_first)&&(keysyms[0]<=iter_lu->upper_last)) { // it's an uppercase special character keysyms[0]|=0x20; // first character as lowercase break; } if ((keysyms[0]>=iter_lu->lower_first)&&(keysyms[0]<=iter_lu->lower_last)) { // it's a lowercase special character keysyms[2]&=0xDF; // second character as uppercase break; } } xcb_change_keyboard_mapping(conn,1,keycode,4,keysyms); // insert the new keysym for(j=k;j<max_keys;j++) { // set the keycode and the shift modifier, if needed, to all keys with that keysyms if (keyboard_lowercase[j].keysym==keysyms[0]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=0; continue; } if (keyboard_lowercase[j].keysym==keysyms[2]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=keycode_shift; continue; } } keycode++; } } xcb_key_symbols_free(symbols); } fclose(keyboard_file); keyboard_current_block=0; xkb_keymap_unref(keymap); xkb_context_unref(context); }
int main(int argc, char **argv) { memset(&globalconf, 0, sizeof(globalconf)); globalconf.connection = xcb_connect(NULL, &globalconf.screen_nbr); if(xcb_connection_has_error(globalconf.connection)) fatal("Cannot open display"); /* Get the root window */ globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.screen_nbr); /* Set up signal handlers and function called on normal exit */ struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_handler = exit_on_signal; sa.sa_flags = 0; sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); atexit(exit_cleanup); /** * First round-trip */ /* Send requests for EWMH atoms initialisation */ xcb_intern_atom_cookie_t *ewmh_cookies = atoms_init(); parse_command_line_parameters(argc, argv); /* Prefetch the extensions data */ xcb_prefetch_extension_data(globalconf.connection, &xcb_composite_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_damage_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_xfixes_id); /* Initialise errors handlers */ xcb_event_handlers_init(globalconf.connection, &globalconf.evenths); event_init_start_handlers(); /* Pre-initialisation of the rendering backend */ if(!rendering_load()) { free(ewmh_cookies); fatal("Can't initialise rendering backend"); } /* Get replies for EWMH atoms initialisation */ if(!atoms_init_finalise(ewmh_cookies)) /* No need to free ewmh_cookies in case of error as it's already handles by xcb-ewmh when getting the replies */ fatal("Cannot initialise atoms"); /* First check whether there is already a Compositing Manager (ICCCM) */ xcb_get_selection_owner_cookie_t wm_cm_owner_cookie = xcb_ewmh_get_wm_cm_owner(&globalconf.ewmh, globalconf.screen_nbr); /** * Second round-trip */ /* Initialise extensions based on the cache and perform initialisation of the rendering backend */ display_init_extensions(); if(!(*globalconf.rendering->init)()) return EXIT_FAILURE; /* Check ownership for WM_CM_Sn before actually claiming it (ICCCM) */ xcb_window_t wm_cm_owner_win; if(xcb_ewmh_get_wm_cm_owner_reply(&globalconf.ewmh, wm_cm_owner_cookie, &wm_cm_owner_win, NULL) && wm_cm_owner_win != XCB_NONE) fatal("A compositing manager is already active (window=%jx)", (uintmax_t) wm_cm_owner_win); /* Now send requests to register the CM */ display_register_cm(); /** * Third round-trip */ /* Check extensions version and finish initialisation of the rendering backend */ display_init_extensions_finalise(); if(!(*globalconf.rendering->init_finalise)()) return EXIT_FAILURE; /* All the plugins given in the configuration file */ plugin_load_all(); /* Validate errors and get PropertyNotify needed to acquire _NET_WM_CM_Sn ownership */ xcb_aux_sync(globalconf.connection); xcb_event_poll_for_event_loop(&globalconf.evenths); globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); xcb_get_modifier_mapping_cookie_t key_mapping_cookie = xcb_get_modifier_mapping_unchecked(globalconf.connection); /* Finish CM X registration */ if(!display_register_cm_finalise()) fatal("Could not acquire _NET_WM_CM_Sn ownership"); /** * Last initialisation round-trip */ /* Grab the server before performing redirection and get the tree of windows to ensure there won't be anything else at the same time */ xcb_grab_server(globalconf.connection); /* Now redirect windows and add existing windows */ display_init_redirect(); /* Validate errors handlers during redirect */ xcb_aux_sync(globalconf.connection); xcb_event_poll_for_event_loop(&globalconf.evenths); /* Manage existing windows */ display_init_redirect_finalise(); xcb_ungrab_server(globalconf.connection); /* Check the plugin requirements which will disable plugins which don't meet the requirements */ plugin_check_requirements(); /* Get the lock masks reply of the request previously sent */ key_lock_mask_get_reply(key_mapping_cookie); /* Initialise normal errors and events handlers */ event_init_handlers(); xcb_generic_event_t *event; /* Flush existing requests before the loop as DamageNotify events may have been received in the meantime */ xcb_flush(globalconf.connection); globalconf.do_repaint = true; /* Main event and error loop */ do { /* Block until an event is received */ event = xcb_wait_for_event(globalconf.connection); /* Check X connection to avoid SIGSEGV */ if(xcb_connection_has_error(globalconf.connection)) fatal("X connection invalid"); xcb_event_handle(&globalconf.evenths, event); free(event); /* Then process all remaining events in the queue because before painting, all the DamageNotify have to be received */ xcb_event_poll_for_event_loop(&globalconf.evenths); /* Now paint the windows */ if(globalconf.do_repaint) { window_t *windows = NULL; for(plugin_t *plugin = globalconf.plugins; plugin; plugin = plugin->next) if(plugin->enable && plugin->vtable->render_windows && (windows = (*plugin->vtable->render_windows)())) break; if(!windows) windows = globalconf.windows; window_paint_all(windows); xcb_aux_sync(globalconf.connection); } globalconf.do_repaint = false; } while(true); return EXIT_SUCCESS; }
static void ephyrProcessKeyRelease(xcb_generic_event_t *xev) { xcb_connection_t *conn = hostx_get_xcbconn(); xcb_key_release_event_t *key = (xcb_key_release_event_t *)xev; static xcb_key_symbols_t *keysyms; static int grabbed_screen = -1; int mod1_down = ephyrUpdateGrabModifierState(key->state); if (!keysyms) keysyms = xcb_key_symbols_alloc(conn); if (!EphyrWantNoHostGrab && (((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_L || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_R) && (key->state & XCB_MOD_MASK_CONTROL)) || ((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_L || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_R) && (key->state & XCB_MOD_MASK_SHIFT)))) { KdScreenInfo *screen = screen_from_window(key->event); EphyrScrPriv *scrpriv = screen->driver; if (grabbed_screen != -1) { xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME); xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); grabbed_screen = -1; hostx_set_win_title(screen, "(ctrl+shift grabs mouse and keyboard)"); } else if (!mod1_down) { /* Attempt grab */ xcb_grab_keyboard_cookie_t kbgrabc = xcb_grab_keyboard(conn, TRUE, scrpriv->win, XCB_TIME_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); xcb_grab_keyboard_reply_t *kbgrabr; xcb_grab_pointer_cookie_t pgrabc = xcb_grab_pointer(conn, TRUE, scrpriv->win, 0, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scrpriv->win, XCB_NONE, XCB_TIME_CURRENT_TIME); xcb_grab_pointer_reply_t *pgrabr; kbgrabr = xcb_grab_keyboard_reply(conn, kbgrabc, NULL); if (!kbgrabr || kbgrabr->status != XCB_GRAB_STATUS_SUCCESS) { xcb_discard_reply(conn, pgrabc.sequence); xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); } else { pgrabr = xcb_grab_pointer_reply(conn, pgrabc, NULL); if (!pgrabr || pgrabr->status != XCB_GRAB_STATUS_SUCCESS) { xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME); } else { grabbed_screen = scrpriv->mynum; hostx_set_win_title (screen, "(ctrl+shift releases mouse and keyboard)"); } } } } if (!ephyrKbd || !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) { return; } /* Still send the release event even if above has happened server * will get confused with just an up event. Maybe it would be * better to just block shift+ctrls getting to kdrive all * together. */ ephyrUpdateModifierState(key->state); KdEnqueueKeyboardEvent(ephyrKbd, key->detail, TRUE); }
int main(int argc, char **argv) { xcb_connection_t *connection = xcb_connect(NULL, &wm_conf.default_screen_num); if (xcb_connection_has_error(connection)) { fprintf(stderr, "failed to open display\n"); exit(1); } init_wm_conf(); init_conf_dir(); wm_conf.connection = connection; const xcb_setup_t *setup = xcb_get_setup(connection); int num_screens = xcb_setup_roots_length(setup); fprintf(stderr, "init: num_screens = %d\n", num_screens); fprintf(stderr, "init: default_screen_num = %d\n", wm_conf.default_screen_num); xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; wm_conf.screen = screen; xcb_window_t root_window = screen->root; xcb_grab_server(connection); xcb_flush(connection); xcb_event_handlers_t *event_handlers = &wm_conf.event_handlers; xcb_event_handlers_init(connection, event_handlers); set_exclusive_error_handler(event_handlers, handle_startup_error); /* Try to get substructure redirect events from root window. * This will cause an error if a window manager is already running. */ const uint32_t sub_redirect = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; xcb_change_window_attributes(connection, root_window, XCB_CW_EVENT_MASK, &sub_redirect); /* Need to xcb_flush to validate error handler */ xcb_aux_sync(connection); /* Process all errors in the queue if any */ xcb_event_poll_for_event_loop(event_handlers); scan_windows(); xinerama_test(); set_exclusive_error_handler(event_handlers, handle_error); set_event_handlers(event_handlers); /* Allocate the key symbols */ wm_conf.key_syms = xcb_key_symbols_alloc(connection); fprintf(stderr, "selecting events from root window\n"); const uint32_t root_win_event_mask = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_FOCUS_CHANGE; xcb_change_window_attributes(connection, root_window, XCB_CW_EVENT_MASK, &root_win_event_mask); xcb_ungrab_server(connection); xcb_flush(connection); wm_conf.repl_server = repl_server_init(); load_init_scheme(); fprintf(stderr, "entering event loop\n"); event_loop(); xcb_disconnect(connection); return 0; }
void UseConnection(xcb_connection_t *conn) { connection = conn; symbols = xcb_key_symbols_alloc(conn); }
void MainWindow::setHotKey(const QKeySequence& hotKey_) { // platform-specific code for global key grabbing #ifdef WIN32 UINT i_vk, i_mod = 0; if(!hotKey.isEmpty()) { // disable previous hotkey UnregisterHotKey(NULL, 10); } hotKey = hotKey_; nativeFilter.setHotKey(hotKey); settings.setValue("hotkey", hotKey); if(hotKey.isEmpty()) return; int key = hotKey[0]; if(key & Qt::ALT) i_mod |= MOD_ALT; if(key & Qt::CTRL) i_mod |= MOD_CONTROL; if(key & Qt::SHIFT) i_mod |= MOD_SHIFT; key = key & ~(Qt::ALT | Qt::CTRL | Qt::SHIFT | Qt::META); #ifndef VK_VOLUME_DOWN #define VK_VOLUME_DOWN 0xAE #define VK_VOLUME_UP 0xAF #endif #ifndef VK_MEDIA_NEXT_TRACK #define VK_MEDIA_NEXT_TRACK 0xB0 #define VK_MEDIA_PREV_TRACK 0xB1 #define VK_MEDIA_STOP 0xB2 #define VK_MEDIA_PLAY_PAUSE 0xB3 #endif #ifndef VK_PAGEUP #define VK_PAGEUP 0x21 #define VK_PAGEDOWN 0x22 #endif switch(key) { case Qt::Key_Left: i_vk = VK_LEFT; break; case Qt::Key_Right: i_vk = VK_RIGHT; break; case Qt::Key_Up: i_vk = VK_UP; break; case Qt::Key_Down: i_vk = VK_DOWN; break; case Qt::Key_Space: i_vk = VK_SPACE; break; case Qt::Key_Escape: i_vk = VK_ESCAPE; break; case Qt::Key_Enter: i_vk = VK_RETURN; break; case Qt::Key_Return: i_vk = VK_RETURN; break; case Qt::Key_F1: i_vk = VK_F1; break; case Qt::Key_F2: i_vk = VK_F2; break; case Qt::Key_F3: i_vk = VK_F3; break; case Qt::Key_F4: i_vk = VK_F4; break; case Qt::Key_F5: i_vk = VK_F5; break; case Qt::Key_F6: i_vk = VK_F6; break; case Qt::Key_F7: i_vk = VK_F7; break; case Qt::Key_F8: i_vk = VK_F8; break; case Qt::Key_F9: i_vk = VK_F9; break; case Qt::Key_F10: i_vk = VK_F10; break; case Qt::Key_F11: i_vk = VK_F11; break; case Qt::Key_F12: i_vk = VK_F12; break; case Qt::Key_PageUp: i_vk = VK_PAGEUP; break; case Qt::Key_PageDown: i_vk = VK_PAGEDOWN; break; case Qt::Key_Home: i_vk = VK_HOME; break; case Qt::Key_End: i_vk = VK_END; break; case Qt::Key_Insert: i_vk = VK_INSERT; break; case Qt::Key_Delete: i_vk = VK_DELETE; break; case Qt::Key_VolumeDown: i_vk = VK_VOLUME_DOWN; break; case Qt::Key_VolumeUp: i_vk = VK_VOLUME_UP; break; case Qt::Key_MediaTogglePlayPause: i_vk = VK_MEDIA_PLAY_PAUSE; break; case Qt::Key_MediaStop: i_vk = VK_MEDIA_STOP; break; case Qt::Key_MediaPrevious: i_vk = VK_MEDIA_PREV_TRACK; break; case Qt::Key_MediaNext: i_vk = VK_MEDIA_NEXT_TRACK; break; default: i_vk = toupper( key ); break; } if(!RegisterHotKey(NULL, 10, i_mod, i_vk)) { hotKey = QKeySequence(); nativeFilter.setHotKey(hotKey); settings.setValue("hotkey", hotKey); QMessageBox::warning(this, "Key binding failed", "Binding global hotkey failed."); } #elif LINUX auto platform = qApp->platformNativeInterface(); xcb_connection_t *c = static_cast<xcb_connection_t*>(platform->nativeResourceForWindow("connection", 0)); xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(c); if(!hotKey.isEmpty()) { // remove previous bindings from all screens xcb_screen_iterator_t iter; iter = xcb_setup_roots_iterator (xcb_get_setup (c)); for (; iter.rem; xcb_screen_next (&iter)) { xcb_ungrab_key(c, XCB_GRAB_ANY, iter.data->root, XCB_MOD_MASK_ANY); } } hotKey = hotKey_; nativeFilter.setHotKey(hotKey); settings.setValue("hotkey", hotKey); if(hotKey.isEmpty()) return; xcb_keysym_t keysym = GetX11Key(hotKey[0]); xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(keysyms, keysym), keycode; if(!keycodes) { hotKey = QKeySequence(); nativeFilter.setHotKey(hotKey); settings.setValue("hotkey", hotKey); QMessageBox::warning(this, "Key binding failed", "Binding global hotkey failed."); free(keysyms); return; } // add bindings for all screens xcb_screen_iterator_t iter; iter = xcb_setup_roots_iterator (xcb_get_setup (c)); bool any_failed = false; for (; iter.rem; xcb_screen_next (&iter)) { int i = 0; while(keycodes[i] != XCB_NO_SYMBOL) { keycode = keycodes[i]; for(auto modifier : GetX11Modifier(c, keysyms, hotKey[0])) { auto cookie = xcb_grab_key_checked(c, true, iter.data->root, modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_SYNC); if(xcb_request_check(c, cookie)) { any_failed = true; } } i += 1; } } if(any_failed) { QMessageBox::warning(this, "Key binding warning", "Warning: Global hotkey binding problem detected. Some other program might have a conflicting " "key binding. If the hotkey doesn't work, try closing some programs or using a different hotkey."); } free(keysyms); free(keycodes); #endif // WIN32 or LINUX }
/* @brief The main function. Initialization happens here. * * @return 0 on success and 1 on failure. */ int main(int argc, char **argv) { int32_t exit_code = 0; atexit(kill_zombie); int c; char *config_file = CONFIG_FILE; while ((c = getopt(argc, argv, "c:")) != -1) { switch (c) { case 'c': config_file = optarg; break; default: break; } } if (initialize_settings(config_file)) { return 1; } int i; enum { MAX_ARGS = 64 }; int nargs = 0; char *cmdargs[MAX_ARGS]; /* one extra for the NULL */ nargs = (argc - optind) + 2; if (nargs > 63) nargs = 63; for (i=optind; i < argc; i++) { if ((i - optind) + 1 > 62) break; cmdargs[(i - optind) + 1] = strdup(argv[i]); } cmdargs[nargs - 1] = NULL; /* Set up the remote process. */ int32_t to_child_fd, from_child_fd; char *exec_file = settings.cmd; if (spawn_piped_process(exec_file, &to_child_fd, &from_child_fd, (char **)cmdargs)) { fprintf(stderr, "Failed to spawn piped process.\n"); exit_code = 1; return exit_code; } /* Don't free #0, it is filled in by spawn_piped_process() and isn't memory that we own */ for (i=1; i < nargs - 1 ; i++) free(cmdargs[i]); /* The main way to communicate with our remote process. */ FILE *to_child = fdopen(to_child_fd, "w"); /* Connect to the X server. */ xcb_connection_t *connection = xcb_connect(NULL, NULL); /* Setup keyboard stuff. Thanks Apple! */ xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(connection); /* Get the first screen. */ const xcb_setup_t *setup = xcb_get_setup(connection); xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); xcb_screen_t *screen = iter.data; /* Create a window. */ xcb_window_t window = xcb_generate_id(connection); uint32_t values[2]; values[0] = screen->white_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS; xcb_void_cookie_t window_cookie = xcb_create_window_checked(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, settings.width, settings.height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values); if (check_xcb_cookie(window_cookie, connection, "Failed to initialize window.")) { exit_code = 1; goto cleanup; } /* Get the atoms to create a dock window type. */ xcb_atom_t window_type_atom, window_type_dock_atom; xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(connection, 0, strlen("_NET_WM_WINDOW_TYPE"), "_NET_WM_WINDOW_TYPE"); xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(connection, atom_cookie, NULL); if (!atom_reply) { fprintf(stderr, "Unable to set window type. You will need to manually set your window manager to run lighthouse as you'd like.\n"); } else { window_type_atom = atom_reply->atom; free(atom_reply); atom_cookie = xcb_intern_atom(connection, 0, strlen("_NET_WM_WINDOW_TYPE_DOCK"), "_NET_WM_WINDOW_TYPE_DOCK"); atom_reply = xcb_intern_atom_reply(connection, atom_cookie, NULL); if (atom_reply) { window_type_dock_atom = atom_reply->atom; free(atom_reply); xcb_change_property_checked(connection, XCB_PROP_MODE_REPLACE, window, window_type_atom, XCB_ATOM_ATOM, 32, 1, &window_type_dock_atom); } else { fprintf(stderr, "Unable to set window type. You will need to manually set your window manager to run lighthouse as you'd like.\n"); } } /* Now set which desktop to run on. */ xcb_atom_t desktop_atom; atom_cookie = xcb_intern_atom(connection, 0, strlen("_NET_WM_DESKTOP"), "_NET_WM_DESKTOP"); atom_reply = xcb_intern_atom_reply(connection, atom_cookie, NULL); if (!atom_reply) { fprintf(stderr, "Unable to set a specific desktop to launch on.\n"); } else { desktop_atom = atom_reply->atom; free(atom_reply); xcb_change_property_checked(connection, XCB_PROP_MODE_REPLACE, window, desktop_atom, XCB_ATOM_ATOM, 32, 1, (const uint32_t []){ settings.desktop }); }
/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t *)p_this; intf_sys_t *p_sys; int ret = VLC_EGENERIC; p_intf->p_sys = p_sys = calloc( 1, sizeof(*p_sys) ); if( !p_sys ) return VLC_ENOMEM; int i_screen_default; p_sys->p_connection = xcb_connect( NULL, &i_screen_default ); if( xcb_connection_has_error( p_sys->p_connection ) ) goto error; /* Get the root windows of the default screen */ const xcb_setup_t* xcbsetup = xcb_get_setup( p_sys->p_connection ); if( !xcbsetup ) goto error; xcb_screen_iterator_t iter = xcb_setup_roots_iterator( xcbsetup ); for( int i = 0; i < i_screen_default; i++ ) { if( !iter.rem ) break; xcb_screen_next( &iter ); } if( !iter.rem ) goto error; p_sys->root = iter.data->root; /* */ p_sys->p_symbols = xcb_key_symbols_alloc( p_sys->p_connection ); // FIXME if( !p_sys->p_symbols ) goto error; if( !Mapping( p_intf ) ) { ret = VLC_SUCCESS; p_intf->p_sys = NULL; /* for Close() */ goto error; } Register( p_intf ); if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) ) { if( p_sys->p_map ) { free( p_sys->p_map->p_keys ); free( p_sys->p_map ); } goto error; } return VLC_SUCCESS; error: if( p_sys->p_symbols ) xcb_key_symbols_free( p_sys->p_symbols ); xcb_disconnect( p_sys->p_connection ); free( p_sys ); return ret; }
/** Hello, this is main. * \param argc Who knows. * \param argv Who knows. * \return EXIT_SUCCESS I hope. */ int main(int argc, char **argv) { char *confpath = NULL; int xfd, i, screen_nbr, opt, colors_nbr; xcolor_init_request_t colors_reqs[2]; ssize_t cmdlen = 1; xdgHandle xdg; xcb_generic_event_t *event; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'v' }, { "config", 1, NULL, 'c' }, { "check", 0, NULL, 'k' }, { NULL, 0, NULL, 0 } }; /* event loop watchers */ ev_io xio = { .fd = -1 }; ev_check xcheck; ev_prepare a_refresh; ev_signal sigint; ev_signal sigterm; ev_signal sighup; /* clear the globalconf structure */ p_clear(&globalconf, 1); globalconf.keygrabber = LUA_REFNIL; globalconf.mousegrabber = LUA_REFNIL; buffer_init(&globalconf.startup_errors); /* save argv */ for(i = 0; i < argc; i++) cmdlen += a_strlen(argv[i]) + 1; globalconf.argv = p_new(char, cmdlen); a_strcpy(globalconf.argv, cmdlen, argv[0]); for(i = 1; i < argc; i++) { a_strcat(globalconf.argv, cmdlen, " "); a_strcat(globalconf.argv, cmdlen, argv[i]); } /* Text won't be printed correctly otherwise */ setlocale(LC_CTYPE, ""); /* Get XDG basedir data */ xdgInitHandle(&xdg); /* init lua */ luaA_init(&xdg); /* check args */ while((opt = getopt_long(argc, argv, "vhkc:", long_options, NULL)) != -1) switch(opt) { case 'v': eprint_version(); break; case 'h': exit_help(EXIT_SUCCESS); break; case 'k': if(!luaA_parserc(&xdg, confpath, false)) { fprintf(stderr, "✘ Configuration file syntax error.\n"); return EXIT_FAILURE; } else { fprintf(stderr, "✔ Configuration file syntax OK.\n"); return EXIT_SUCCESS; } case 'c': if(a_strlen(optarg)) confpath = a_strdup(optarg); else fatal("-c option requires a file name"); break; } globalconf.loop = ev_default_loop(0); ev_timer_init(&globalconf.timer, &luaA_on_timer, 0., 0.); /* register function for signals */ ev_signal_init(&sigint, exit_on_signal, SIGINT); ev_signal_init(&sigterm, exit_on_signal, SIGTERM); ev_signal_init(&sighup, restart_on_signal, SIGHUP); ev_signal_start(globalconf.loop, &sigint); ev_signal_start(globalconf.loop, &sigterm); ev_signal_start(globalconf.loop, &sighup); ev_unref(globalconf.loop); ev_unref(globalconf.loop); ev_unref(globalconf.loop); struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 }; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, 0); /* XLib sucks */ XkbIgnoreExtension(True); /* X stuff */ globalconf.display = XOpenDisplay(NULL); if (globalconf.display == NULL) fatal("cannot open display"); globalconf.default_screen = XDefaultScreen(globalconf.display); globalconf.connection = XGetXCBConnection(globalconf.display); /* Double checking then everything is OK. */ if(xcb_connection_has_error(globalconf.connection)) fatal("cannot open display"); /* Prefetch all the extensions we might need */ xcb_prefetch_extension_data(globalconf.connection, &xcb_big_requests_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_test_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_randr_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_shape_id); /* initialize dbus */ a_dbus_init(); /* Get the file descriptor corresponding to the X connection */ xfd = xcb_get_file_descriptor(globalconf.connection); ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ); ev_io_start(globalconf.loop, &xio); ev_check_init(&xcheck, &a_xcb_check_cb); ev_check_start(globalconf.loop, &xcheck); ev_unref(globalconf.loop); ev_prepare_init(&a_refresh, &a_refresh_cb); ev_prepare_start(globalconf.loop, &a_refresh); ev_unref(globalconf.loop); /* Grab server */ xcb_grab_server(globalconf.connection); /* Make sure there are no pending events. Since we didn't really do anything * at all yet, we will just discard all events which we received so far. * The above GrabServer should make sure no new events are generated. */ xcb_aux_sync(globalconf.connection); while ((event = xcb_poll_for_event(globalconf.connection)) != NULL) { /* Make sure errors are printed */ uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event); if(response_type == 0) event_handle(event); p_delete(&event); } for(screen_nbr = 0; screen_nbr < xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); screen_nbr++) { const uint32_t select_input_val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; /* This causes an error if some other window manager is running */ xcb_change_window_attributes(globalconf.connection, xutil_screen_get(globalconf.connection, screen_nbr)->root, XCB_CW_EVENT_MASK, &select_input_val); } /* Need to xcb_flush to validate error handler */ xcb_aux_sync(globalconf.connection); /* Process all errors in the queue if any. There can be no events yet, so if * this function returns something, it must be an error. */ if (xcb_poll_for_event(globalconf.connection) != NULL) fatal("another window manager is already running"); /* Prefetch the maximum request length */ xcb_prefetch_maximum_request_length(globalconf.connection); /* check for xtest extension */ const xcb_query_extension_reply_t *xtest_query; xtest_query = xcb_get_extension_data(globalconf.connection, &xcb_test_id); globalconf.have_xtest = xtest_query->present; /* Allocate the key symbols */ globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); xcb_get_modifier_mapping_cookie_t xmapping_cookie = xcb_get_modifier_mapping_unchecked(globalconf.connection); /* init atom cache */ atoms_init(globalconf.connection); /* init screens information */ screen_scan(); /* init default font and colors */ colors_reqs[0] = xcolor_init_unchecked(&globalconf.colors.fg, "black", sizeof("black") - 1); colors_reqs[1] = xcolor_init_unchecked(&globalconf.colors.bg, "white", sizeof("white") - 1); globalconf.font = draw_font_new("sans 8"); for(colors_nbr = 0; colors_nbr < 2; colors_nbr++) xcolor_init_reply(colors_reqs[colors_nbr]); xutil_lock_mask_get(globalconf.connection, xmapping_cookie, globalconf.keysyms, &globalconf.numlockmask, &globalconf.shiftlockmask, &globalconf.capslockmask, &globalconf.modeswitchmask); /* Get the window tree associated to this screen */ const int screen_max = xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); xcb_query_tree_cookie_t tree_c[screen_max]; /* do this only for real screen */ for(screen_nbr = 0; screen_nbr < screen_max; screen_nbr++) { /* select for events */ const uint32_t change_win_vals[] = { XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_FOCUS_CHANGE }; tree_c[screen_nbr] = xcb_query_tree_unchecked(globalconf.connection, xutil_screen_get(globalconf.connection, screen_nbr)->root); xcb_change_window_attributes(globalconf.connection, xutil_screen_get(globalconf.connection, screen_nbr)->root, XCB_CW_EVENT_MASK, change_win_vals); ewmh_init(screen_nbr); systray_init(screen_nbr); } /* init spawn (sn) */ spawn_init(); /* we will receive events, stop grabbing server */ xcb_ungrab_server(globalconf.connection); /* Parse and run configuration file */ if (!luaA_parserc(&xdg, confpath, true)) fatal("couldn't find any rc file"); scan(tree_c); xcb_flush(globalconf.connection); /* main event loop */ ev_loop(globalconf.loop, 0); /* cleanup event loop */ ev_ref(globalconf.loop); ev_check_stop(globalconf.loop, &xcheck); ev_ref(globalconf.loop); ev_prepare_stop(globalconf.loop, &a_refresh); ev_ref(globalconf.loop); ev_io_stop(globalconf.loop, &xio); awesome_atexit(false); return EXIT_SUCCESS; }
/* * Creates the config file and tells i3 to reload. * */ static void finish() { printf("creating \"%s\"...\n", config_path); if (!(dpy = XOpenDisplay(NULL))) errx(1, "Could not connect to X11"); FILE *kc_config = fopen(SYSCONFDIR "/i3/config.keycodes", "r"); if (kc_config == NULL) err(1, "Could not open input file \"%s\"", SYSCONFDIR "/i3/config.keycodes"); FILE *ks_config = fopen(config_path, "w"); if (ks_config == NULL) err(1, "Could not open output config file \"%s\"", config_path); free(config_path); char *line = NULL; size_t len = 0; #ifndef USE_FGETLN ssize_t read; #endif bool head_of_file = true; /* write a header about auto-generation to the output file */ fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config); fputs("# It will not be overwritten, so edit it as you like.\n", ks_config); fputs("#\n", ks_config); fputs("# Should you change your keyboard layout somewhen, delete\n", ks_config); fputs("# this file and re-run i3-config-wizard(1).\n", ks_config); fputs("#\n", ks_config); #ifdef USE_FGETLN char *buf = NULL; while ((buf = fgetln(kc_config, &len)) != NULL) { /* fgetln does not return null-terminated strings */ FREE(line); sasprintf(&line, "%.*s", len, buf); #else size_t linecap = 0; while ((read = getline(&line, &linecap, kc_config)) != -1) { len = strlen(line); #endif /* skip the warning block at the beginning of the input file */ if (head_of_file && strncmp("# WARNING", line, strlen("# WARNING")) == 0) continue; head_of_file = false; /* Skip leading whitespace */ char *walk = line; while (isspace(*walk) && walk < (line + len)) { /* Pre-output the skipped whitespaces to keep proper indentation */ fputc(*walk, ks_config); walk++; } /* Set the modifier the user chose */ if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) { if (modifier == MOD_Mod1) fputs("set $mod Mod1\n", ks_config); else fputs("set $mod Mod4\n", ks_config); continue; } /* Check for 'bindcode'. If it’s not a bindcode line, we * just copy it to the output file */ if (strncmp(walk, "bindcode", strlen("bindcode")) != 0) { fputs(walk, ks_config); continue; } char *result = rewrite_binding(walk); fputs(result, ks_config); free(result); } /* sync to do our best in order to have the file really stored on disk */ fflush(ks_config); fsync(fileno(ks_config)); #ifndef USE_FGETLN free(line); #endif fclose(kc_config); fclose(ks_config); /* tell i3 to reload the config file */ int sockfd = ipc_connect(socket_path); ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload"); close(sockfd); exit(0); } int main(int argc, char *argv[]) { config_path = resolve_tilde("~/.i3/config"); socket_path = getenv("I3SOCK"); char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"; char *patternbold = "-misc-fixed-bold-r-normal--13-120-75-75-C-70-iso10646-1"; int o, option_index = 0; static struct option long_options[] = { {"socket", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, {"limit", required_argument, 0, 'l'}, {"prompt", required_argument, 0, 'P'}, {"prefix", required_argument, 0, 'p'}, {"font", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; char *options_string = "s:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { case 's': FREE(socket_path); socket_path = strdup(optarg); break; case 'v': printf("i3-config-wizard " I3_VERSION "\n"); return 0; case 'h': printf("i3-config-wizard " I3_VERSION "\n"); printf("i3-config-wizard [-s <socket>] [-v]\n"); return 0; } } /* Check if the destination config file does not exist but the path is * writable. If not, exit now, this program is not useful in that case. */ struct stat stbuf; if (stat(config_path, &stbuf) == 0) { printf("The config file \"%s\" already exists. Exiting.\n", config_path); return 0; } /* Create ~/.i3 if it does not yet exist */ char *config_dir = resolve_tilde("~/.i3"); if (stat(config_dir, &stbuf) != 0) if (mkdir(config_dir, 0755) == -1) err(1, "mkdir(%s) failed", config_dir); free(config_dir); int fd; if ((fd = open(config_path, O_CREAT | O_RDWR, 0644)) == -1) { printf("Cannot open file \"%s\" for writing: %s. Exiting.\n", config_path, strerror(errno)); return 0; } close(fd); unlink(config_path); if (socket_path == NULL) socket_path = root_atom_contents("I3_SOCKET_PATH"); if (socket_path == NULL) socket_path = "/tmp/i3-ipc.sock"; int screens; if ((conn = xcb_connect(NULL, &screens)) == NULL || xcb_connection_has_error(conn)) errx(1, "Cannot open display\n"); xcb_get_modifier_mapping_cookie_t modmap_cookie; modmap_cookie = xcb_get_modifier_mapping(conn); symbols = xcb_key_symbols_alloc(conn); /* Place requests for the atoms we need as soon as possible */ #define xmacro(atom) \ xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom); #include "atoms.xmacro" #undef xmacro root_screen = xcb_aux_get_screen(conn, screens); root = root_screen->root; if (!(modmap_reply = xcb_get_modifier_mapping_reply(conn, modmap_cookie, NULL))) errx(EXIT_FAILURE, "Could not get modifier mapping\n"); xcb_numlock_mask = get_mod_mask_for(XCB_NUM_LOCK, symbols, modmap_reply); font = load_font(pattern, true); bold_font = load_font(patternbold, true); /* Open an input window */ win = xcb_generate_id(conn); xcb_create_window( conn, XCB_COPY_FROM_PARENT, win, /* the window id */ root, /* parent == root */ 490, 297, 300, 205, /* dimensions */ 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (uint32_t[]){ 0, /* back pixel: black */ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS }); /* Map the window (make it visible) */ xcb_map_window(conn, win); /* Setup NetWM atoms */ #define xmacro(name) \ do { \ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \ if (!reply) \ errx(EXIT_FAILURE, "Could not get atom " # name "\n"); \ \ A_ ## name = reply->atom; \ free(reply); \ } while (0); #include "atoms.xmacro" #undef xmacro /* Set dock mode */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_WINDOW_TYPE, A_ATOM, 32, 1, (unsigned char*) &A__NET_WM_WINDOW_TYPE_DIALOG); /* Set window title */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3: first configuration"), "i3: first configuration"); /* Create pixmap */ pixmap = xcb_generate_id(conn); pixmap_gc = xcb_generate_id(conn); xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, 500); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); /* Grab the keyboard to get all input */ xcb_flush(conn); /* Try (repeatedly, if necessary) to grab the keyboard. We might not * get the keyboard at the first attempt because of the keybinding * still being active when started via a wm’s keybinding. */ xcb_grab_keyboard_cookie_t cookie; xcb_grab_keyboard_reply_t *reply = NULL; int count = 0; while ((reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) && (count++ < 500)) { cookie = xcb_grab_keyboard(conn, false, win, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); reply = xcb_grab_keyboard_reply(conn, cookie, NULL); usleep(1000); } if (reply->status != XCB_GRAB_STATUS_SUCCESS) { fprintf(stderr, "Could not grab keyboard, status = %d\n", reply->status); exit(-1); } xcb_flush(conn); xcb_generic_event_t *event; while ((event = xcb_wait_for_event(conn)) != NULL) { if (event->response_type == 0) { fprintf(stderr, "X11 Error received! sequence %x\n", event->sequence); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press(NULL, conn, (xcb_key_press_event_t*)event); break; /* TODO: handle mappingnotify */ case XCB_BUTTON_PRESS: handle_button_press((xcb_button_press_event_t*)event); break; case XCB_EXPOSE: handle_expose(); break; } free(event); } return 0; }